Commit de3de82d authored by dingzhiwei's avatar dingzhiwei
Browse files

初始化Jeepay项目

parent 40dcaf4a
/*
* Copyright (c) 2021-2031, 河北计全科技有限公司 (https://www.jeequan.com & jeequan@126.com).
* <p>
* Licensed under the GNU LESSER GENERAL PUBLIC LICENSE 3.0;
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
* <p>
* http://www.gnu.org/licenses/lgpl.html
* <p>
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package com.jeequan.jeepay.pay.channel.wxpay;
import com.alibaba.fastjson.JSONObject;
import com.github.binarywang.wxpay.bean.request.WxPayOrderQueryRequest;
import com.github.binarywang.wxpay.bean.result.WxPayOrderQueryResult;
import com.github.binarywang.wxpay.exception.WxPayException;
import com.github.binarywang.wxpay.service.WxPayService;
import com.jeequan.jeepay.core.constants.CS;
import com.jeequan.jeepay.core.entity.PayOrder;
import com.jeequan.jeepay.pay.channel.IPayOrderQueryService;
import com.jeequan.jeepay.pay.channel.wxpay.kits.WxpayKit;
import com.jeequan.jeepay.pay.channel.wxpay.kits.WxpayV3Util;
import com.jeequan.jeepay.pay.model.MchConfigContext;
import com.jeequan.jeepay.pay.rqrs.msg.ChannelRetMsg;
import org.springframework.stereotype.Service;
/*
* 微信查单接口
*
* @author zhuxiao
* @site https://www.jeepay.vip
* @date 2021/6/8 18:10
*/
@Service
public class WxpayPayOrderQueryService implements IPayOrderQueryService {
@Override
public String getIfCode() {
return CS.IF_CODE.WXPAY;
}
@Override
public ChannelRetMsg query(PayOrder payOrder, MchConfigContext mchConfigContext) {
try {
if (CS.PAY_IF_VERSION.WX_V2.equals(mchConfigContext.getWxServiceWrapper().getApiVersion())) { //V2
WxPayOrderQueryRequest req = new WxPayOrderQueryRequest();
//放置isv信息
WxpayKit.putApiIsvInfo(mchConfigContext, req);
req.setOutTradeNo(payOrder.getPayOrderId());
WxPayService wxPayService = mchConfigContext.getWxServiceWrapper().getWxPayService();
WxPayOrderQueryResult result = wxPayService.queryOrder(req);
if("SUCCESS".equals(result.getTradeState())){ //支付成功
return ChannelRetMsg.confirmSuccess(result.getTransactionId());
}else if("USERPAYING".equals(result.getTradeState())){ //支付中,等待用户输入密码
return ChannelRetMsg.waiting(); //支付中
}else if("CLOSED".equals(result.getTradeState())
|| "REVOKED".equals(result.getTradeState())
|| "PAYERROR".equals(result.getTradeState())){ //CLOSED—已关闭, REVOKED—已撤销(刷卡支付), PAYERROR--支付失败(其他原因,如银行返回失败)
return ChannelRetMsg.confirmFail(); //支付失败
}else{
return ChannelRetMsg.unknown();
}
}else if (CS.PAY_IF_VERSION.WX_V3.equals(mchConfigContext.getWxServiceWrapper().getApiVersion())) { //V3
JSONObject resultJSON = WxpayV3Util.queryOrderV3(payOrder.getPayOrderId(), mchConfigContext.getWxServiceWrapper().getWxPayService().getConfig());
String channelState = resultJSON.getString("trade_state");
if ("SUCCESS".equals(channelState)) {
return ChannelRetMsg.confirmSuccess(resultJSON.getString("transaction_id"));
}else if("USERPAYING".equals(channelState)){ //支付中,等待用户输入密码
return ChannelRetMsg.waiting(); //支付中
}else if("CLOSED".equals(channelState)
|| "REVOKED".equals(channelState)
|| "PAYERROR".equals(channelState)){ //CLOSED—已关闭, REVOKED—已撤销(刷卡支付), PAYERROR--支付失败(其他原因,如银行返回失败)
return ChannelRetMsg.confirmFail(); //支付失败
}else{
return ChannelRetMsg.unknown();
}
}else {
return ChannelRetMsg.unknown();
}
} catch (WxPayException e) {
return ChannelRetMsg.sysError(e.getReturnMsg());
} catch (Exception e) {
return ChannelRetMsg.sysError(e.getMessage());
}
}
}
/*
* Copyright (c) 2021-2031, 河北计全科技有限公司 (https://www.jeequan.com & jeequan@126.com).
* <p>
* Licensed under the GNU LESSER GENERAL PUBLIC LICENSE 3.0;
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
* <p>
* http://www.gnu.org/licenses/lgpl.html
* <p>
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package com.jeequan.jeepay.pay.channel.wxpay;
import com.alibaba.fastjson.JSONObject;
import com.github.binarywang.wxpay.bean.request.WxPayUnifiedOrderRequest;
import com.github.binarywang.wxpay.service.WxPayService;
import com.jeequan.jeepay.core.constants.CS;
import com.jeequan.jeepay.core.entity.PayOrder;
import com.jeequan.jeepay.core.exception.BizException;
import com.jeequan.jeepay.core.model.params.wxpay.WxpayIsvsubMchParams;
import com.jeequan.jeepay.pay.channel.AbstractPaymentService;
import com.jeequan.jeepay.pay.rqrs.AbstractRS;
import com.jeequan.jeepay.pay.rqrs.payorder.UnifiedOrderRQ;
import com.jeequan.jeepay.pay.util.PaywayUtil;
import com.jeequan.jeepay.pay.model.MchConfigContext;
import org.springframework.stereotype.Service;
/*
* 支付接口: 微信官方
* 支付方式: 自适应
*
* @author zhuxiao
* @site https://www.jeepay.vip
* @date 2021/6/8 18:10
*/
@Service
public class WxpayPaymentService extends AbstractPaymentService {
@Override
public String getIfCode() {
return CS.IF_CODE.WXPAY;
}
@Override
public boolean isSupport(String wayCode) {
return true;
}
@Override
public String preCheck(UnifiedOrderRQ rq, PayOrder payOrder) {
return PaywayUtil.getRealPaywayService(this, payOrder.getWayCode()).preCheck(rq, payOrder);
}
@Override
public AbstractRS pay(UnifiedOrderRQ rq, PayOrder payOrder, MchConfigContext mchConfigContext) throws Exception {
// 微信API版本
String apiVersion = mchConfigContext.getWxServiceWrapper().getApiVersion();
if (CS.PAY_IF_VERSION.WX_V2.equals(apiVersion)) {
return PaywayUtil.getRealPaywayService(this, payOrder.getWayCode()).pay(rq, payOrder, mchConfigContext);
} else if (CS.PAY_IF_VERSION.WX_V3.equals(apiVersion)) {
return PaywayUtil.getRealPaywayV3Service(this, payOrder.getWayCode()).pay(rq, payOrder, mchConfigContext);
} else {
throw new BizException("不支持的微信支付API版本");
}
}
/**
* 构建微信统一下单请求数据
* @param payOrder
* @return
*/
public WxPayUnifiedOrderRequest buildUnifiedOrderRequest(PayOrder payOrder, MchConfigContext mchConfigContext) {
String payOrderId = payOrder.getPayOrderId();
// 微信统一下单请求对象
WxPayUnifiedOrderRequest request = new WxPayUnifiedOrderRequest();
request.setOutTradeNo(payOrderId);
request.setBody(payOrder.getSubject());
request.setDetail(payOrder.getBody());
request.setFeeType("CNY");
request.setTotalFee(payOrder.getAmount().intValue());
request.setSpbillCreateIp(payOrder.getClientIp());
request.setNotifyUrl(getNotifyUrl());
request.setProductId(System.currentTimeMillis()+"");
// 特约商户
if(mchConfigContext.isIsvsubMch()){
WxpayIsvsubMchParams isvsubMchParams = mchConfigContext.getIsvsubMchParamsByIfCode(getIfCode(), WxpayIsvsubMchParams.class);
request.setSubMchId(isvsubMchParams.getSubMchId());
request.setSubAppId(isvsubMchParams.getSubMchAppId());
}
return request;
}
/**
* 构建微信APIV3接口 统一下单请求数据
* @param payOrder
* @return
*/
public JSONObject buildV3OrderRequest(PayOrder payOrder, MchConfigContext mchConfigContext) {
String payOrderId = payOrder.getPayOrderId();
// 微信统一下单请求对象
JSONObject reqJSON = new JSONObject();
reqJSON.put("out_trade_no", payOrderId);
reqJSON.put("description", payOrder.getSubject());
reqJSON.put("notify_url", getNotifyUrl(payOrderId));
JSONObject amount = new JSONObject();
amount.put("total", payOrder.getAmount().intValue());
amount.put("currency", "CNY");
reqJSON.put("amount", amount);
JSONObject sceneInfo = new JSONObject();
sceneInfo.put("payer_client_ip", payOrder.getClientIp());
reqJSON.put("scene_info", sceneInfo);
WxPayService wxPayService = mchConfigContext.getWxServiceWrapper().getWxPayService();
if(mchConfigContext.isIsvsubMch()){ // 特约商户
WxpayIsvsubMchParams isvsubMchParams = mchConfigContext.getIsvsubMchParamsByIfCode(getIfCode(), WxpayIsvsubMchParams.class);
reqJSON.put("sp_appid", wxPayService.getConfig().getAppId());
reqJSON.put("sp_mchid", wxPayService.getConfig().getMchId());
reqJSON.put("sub_mchid", isvsubMchParams.getSubMchId());
reqJSON.put("sub_appid", isvsubMchParams.getSubMchAppId());
}else { // 普通商户
reqJSON.put("appid", wxPayService.getConfig().getAppId());
reqJSON.put("mchid", wxPayService.getConfig().getMchId());
}
return reqJSON;
}
}
/*
* Copyright (c) 2021-2031, 河北计全科技有限公司 (https://www.jeequan.com & jeequan@126.com).
* <p>
* Licensed under the GNU LESSER GENERAL PUBLIC LICENSE 3.0;
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
* <p>
* http://www.gnu.org/licenses/lgpl.html
* <p>
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package com.jeequan.jeepay.pay.channel.wxpay.kits;
import com.github.binarywang.wxpay.bean.request.BaseWxPayRequest;
import com.github.binarywang.wxpay.exception.WxPayException;
import com.jeequan.jeepay.core.constants.CS;
import com.jeequan.jeepay.core.model.params.wxpay.WxpayIsvsubMchParams;
import com.jeequan.jeepay.pay.rqrs.msg.ChannelRetMsg;
import com.jeequan.jeepay.pay.model.MchConfigContext;
import org.apache.commons.lang3.StringUtils;
/*
* 【微信支付】支付通道工具包
*
* @author terrfly
* @site https://www.jeepay.vip
* @date 2021/6/8 17:21
*/
public class WxpayKit {
/** 放置 isv特殊信息 **/
public static void putApiIsvInfo(MchConfigContext mchConfigContext, BaseWxPayRequest req){
//不是特约商户, 无需放置此值
if(!mchConfigContext.isIsvsubMch()){
return ;
}
WxpayIsvsubMchParams isvsubMchParams = mchConfigContext.getIsvsubMchParamsByIfCode(CS.IF_CODE.WXPAY, WxpayIsvsubMchParams.class);
req.setSubMchId(isvsubMchParams.getSubMchId());
req.setSubAppId(isvsubMchParams.getSubMchAppId());
}
public static String appendErrCode(String code, String subCode){
return StringUtils.defaultIfEmpty(subCode, code); //优先: subCode
}
public static String appendErrMsg(String msg, String subMsg){
if(StringUtils.isNotEmpty(msg) && StringUtils.isNotEmpty(subMsg) ){
return msg + "【" + subMsg + "】";
}
return StringUtils.defaultIfEmpty(subMsg, msg);
}
public static void commonSetErrInfo(ChannelRetMsg channelRetMsg, WxPayException wxPayException){
channelRetMsg.setChannelErrCode(appendErrCode( wxPayException.getReturnCode(), wxPayException.getErrCode() ));
channelRetMsg.setChannelErrMsg(appendErrMsg( "OK".equalsIgnoreCase(wxPayException.getReturnMsg()) ? null : wxPayException.getReturnMsg(), wxPayException.getErrCodeDes() ));
}
}
/*
* Copyright (c) 2021-2031, 河北计全科技有限公司 (https://www.jeequan.com & jeequan@126.com).
* <p>
* Licensed under the GNU LESSER GENERAL PUBLIC LICENSE 3.0;
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
* <p>
* http://www.gnu.org/licenses/lgpl.html
* <p>
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package com.jeequan.jeepay.pay.channel.wxpay.kits;
import com.alibaba.fastjson.JSON;
import com.alibaba.fastjson.JSONObject;
import com.github.binarywang.wxpay.config.WxPayConfig;
import com.github.binarywang.wxpay.constant.WxPayConstants;
import com.github.binarywang.wxpay.exception.WxPayException;
import com.github.binarywang.wxpay.v3.WxPayV3HttpClientBuilder;
import com.github.binarywang.wxpay.v3.auth.AutoUpdateCertificatesVerifier;
import com.github.binarywang.wxpay.v3.auth.PrivateKeySigner;
import com.github.binarywang.wxpay.v3.auth.WxPayCredentials;
import com.github.binarywang.wxpay.v3.auth.WxPayValidator;
import com.github.binarywang.wxpay.v3.util.PemUtils;
import lombok.extern.slf4j.Slf4j;
import org.apache.http.HttpStatus;
import org.apache.http.client.config.RequestConfig;
import org.apache.http.client.methods.CloseableHttpResponse;
import org.apache.http.client.methods.HttpGet;
import org.apache.http.client.methods.HttpPost;
import org.apache.http.entity.ContentType;
import org.apache.http.entity.StringEntity;
import org.apache.http.impl.client.CloseableHttpClient;
import org.apache.http.util.EntityUtils;
import java.io.FileInputStream;
import java.io.FileNotFoundException;
import java.io.UnsupportedEncodingException;
import java.nio.charset.StandardCharsets;
import java.security.PrivateKey;
import java.util.HashMap;
import java.util.Map;
/**
* @Author: ZhuXiao
* @Description:
* @Date: 15:22 2021/5/26
*/
@Slf4j
public class WxpayV3Util {
private static final String PAY_BASE_URL = "https://api.mch.weixin.qq.com";
public static final Map<String, String> NORMALMCH_URL_MAP = new HashMap<>();
static {
NORMALMCH_URL_MAP.put(WxPayConstants.TradeType.APP, "/v3/pay/transactions/app");
NORMALMCH_URL_MAP.put(WxPayConstants.TradeType.JSAPI, "/v3/pay/transactions/jsapi");
NORMALMCH_URL_MAP.put(WxPayConstants.TradeType.NATIVE, "/v3/pay/transactions/native");
NORMALMCH_URL_MAP.put(WxPayConstants.TradeType.MWEB, "/v3/pay/transactions/h5");
}
public static final Map<String, String> ISV_URL_MAP = new HashMap<>();
static {
ISV_URL_MAP.put(WxPayConstants.TradeType.APP, "/v3/pay/partner/transactions/app");
ISV_URL_MAP.put(WxPayConstants.TradeType.JSAPI, "/v3/pay/partner/transactions/jsapi");
ISV_URL_MAP.put(WxPayConstants.TradeType.NATIVE, "/v3/pay/partner/transactions/native");
ISV_URL_MAP.put(WxPayConstants.TradeType.MWEB, "/v3/pay/partner/transactions/h5");
}
public static JSONObject unifiedOrderV3(String url, JSONObject reqJSON, WxPayConfig wxPayConfig) throws WxPayException {
String response = postV3(PAY_BASE_URL + url, reqJSON.toJSONString(), wxPayConfig);
return JSON.parseObject(response);
}
public static JSONObject queryOrderV3(String payOrderId, WxPayConfig wxPayConfig) throws WxPayException {
String url = String.format("%s/v3/pay/transactions/out-trade-no/%s", PAY_BASE_URL, payOrderId);
String response = getV3(url, wxPayConfig);
return JSON.parseObject(response);
}
public static String postV3(String url, String requestStr, WxPayConfig wxPayConfig) throws WxPayException {
CloseableHttpClient httpClient = createApiV3HttpClient(wxPayConfig);
HttpPost httpPost = createHttpPost(url, requestStr);
httpPost.addHeader("Accept", "application/json");
httpPost.addHeader("Content-Type", "application/json");
try (CloseableHttpResponse response = httpClient.execute(httpPost)) {
//v3已经改为通过状态码判断200 204 成功
int statusCode = response.getStatusLine().getStatusCode();
//post方法有可能会没有返回值的情况
String responseString;
if (response.getEntity() == null) {
responseString = null;
} else {
responseString = EntityUtils.toString(response.getEntity(), StandardCharsets.UTF_8);
}
log.info("\n【请求地址】:{}\n【请求数据】:{}\n【响应数据】:{}", url, requestStr, responseString);
if (HttpStatus.SC_OK == statusCode || HttpStatus.SC_NO_CONTENT == statusCode) {
return responseString;
} else {
//有错误提示信息返回
JSONObject jsonObject = JSON.parseObject(responseString);
WxPayException wxPayException = new WxPayException(jsonObject.getString("message"));
wxPayException.setErrCode(jsonObject.getString("code"));
wxPayException.setErrCodeDes(jsonObject.getString("message"));
throw wxPayException;
}
} catch (Exception e) {
log.error("\n【异常信息】:{}", e.getMessage());
throw (e instanceof WxPayException) ? (WxPayException) e : new WxPayException(e.getMessage(), e);
} finally {
httpPost.releaseConnection();
}
}
public static String getV3(String url, WxPayConfig wxPayConfig) throws WxPayException {
HttpGet httpGet = new HttpGet(url);
httpGet.addHeader("Accept", "application/json");
httpGet.addHeader("Content-Type", "application/json");
httpGet.setConfig(RequestConfig.custom()
.setConnectionRequestTimeout(5000)
.setConnectTimeout(5000)
.setSocketTimeout(10000)
.build());
CloseableHttpClient httpClient = createApiV3HttpClient(wxPayConfig);
try (CloseableHttpResponse response = httpClient.execute(httpGet)) {
//v3已经改为通过状态码判断200 204 成功
int statusCode = response.getStatusLine().getStatusCode();
//post方法有可能会没有返回值的情况
String responseString;
if (response.getEntity() == null) {
responseString = null;
} else {
responseString = EntityUtils.toString(response.getEntity(), StandardCharsets.UTF_8);
}
if (HttpStatus.SC_OK == statusCode || HttpStatus.SC_NO_CONTENT == statusCode) {
log.info("\n【请求地址】:{}\n【响应数据】:{}", url, responseString);
return responseString;
} else {
//有错误提示信息返回
JSONObject jsonObject = JSON.parseObject(responseString);
WxPayException wxPayException = new WxPayException(jsonObject.getString("message"));
wxPayException.setErrCode(jsonObject.getString("code"));
wxPayException.setErrCodeDes(jsonObject.getString("message"));
throw wxPayException;
}
} catch (Exception e) {
log.error("\n【异常信息】:{}", url, e.getMessage());
throw (e instanceof WxPayException) ? (WxPayException) e : new WxPayException(e.getMessage(), e);
} finally {
httpGet.releaseConnection();
}
}
private static CloseableHttpClient createApiV3HttpClient(WxPayConfig wxPayConfig) throws WxPayException {
try {
// 自动获取微信平台证书
PrivateKey privateKey = PemUtils.loadPrivateKey(new FileInputStream(wxPayConfig.getPrivateKeyPath()));
AutoUpdateCertificatesVerifier verifier = new AutoUpdateCertificatesVerifier(
new WxPayCredentials(wxPayConfig.getMchId(), new PrivateKeySigner(wxPayConfig.getCertSerialNo(), privateKey)),
wxPayConfig.getApiV3Key().getBytes("utf-8"));
WxPayV3HttpClientBuilder builder = WxPayV3HttpClientBuilder.create()
.withMerchant(wxPayConfig.getMchId(), wxPayConfig.getCertSerialNo(), privateKey)
.withValidator(new WxPayValidator(verifier));
CloseableHttpClient apiV3HttpClient = builder.build();
return apiV3HttpClient;
} catch (FileNotFoundException | UnsupportedEncodingException e) {
log.error("", e);
}
CloseableHttpClient apiV3HttpClient = wxPayConfig.getApiV3HttpClient();
if (null == apiV3HttpClient) {
return wxPayConfig.initApiV3HttpClient();
}
return null;
}
private static HttpPost createHttpPost(String url, String requestStr) {
HttpPost httpPost = new HttpPost(url);
httpPost.setEntity(new StringEntity(requestStr, ContentType.create("application/json", "utf-8")));
httpPost.setConfig(RequestConfig.custom()
.setConnectionRequestTimeout(5000)
.setConnectTimeout(5000)
.setSocketTimeout(10000)
.build());
return httpPost;
}
}
/*
* Copyright (c) 2021-2031, 河北计全科技有限公司 (https://www.jeequan.com & jeequan@126.com).
* <p>
* Licensed under the GNU LESSER GENERAL PUBLIC LICENSE 3.0;
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
* <p>
* http://www.gnu.org/licenses/lgpl.html
* <p>
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package com.jeequan.jeepay.pay.channel.wxpay.payway;
import com.alibaba.fastjson.JSON;
import com.alibaba.fastjson.JSONObject;
import com.github.binarywang.wxpay.bean.order.WxPayAppOrderResult;
import com.github.binarywang.wxpay.bean.request.WxPayUnifiedOrderRequest;
import com.github.binarywang.wxpay.constant.WxPayConstants;
import com.github.binarywang.wxpay.exception.WxPayException;
import com.github.binarywang.wxpay.service.WxPayService;
import com.jeequan.jeepay.core.entity.PayOrder;
import com.jeequan.jeepay.pay.channel.wxpay.WxpayPaymentService;
import com.jeequan.jeepay.pay.channel.wxpay.kits.WxpayKit;
import com.jeequan.jeepay.pay.rqrs.AbstractRS;
import com.jeequan.jeepay.pay.rqrs.payorder.UnifiedOrderRQ;
import com.jeequan.jeepay.pay.rqrs.payorder.payway.WxAppOrderRS;
import com.jeequan.jeepay.pay.rqrs.msg.ChannelRetMsg;
import com.jeequan.jeepay.pay.util.ApiResBuilder;
import com.jeequan.jeepay.pay.model.MchConfigContext;
import org.springframework.stereotype.Service;
/*
* 微信 app支付
*
* @author zhuxiao
* @site https://www.jeepay.vip
* @date 2021/6/8 18:08
*/
@Service("wxpayPaymentByAppService") //Service Name需保持全局唯一性
public class WxApp extends WxpayPaymentService {
@Override
public String preCheck(UnifiedOrderRQ rq, PayOrder payOrder) {
return null;
}
@Override
public AbstractRS pay(UnifiedOrderRQ rq, PayOrder payOrder, MchConfigContext mchConfigContext) throws Exception{
WxPayUnifiedOrderRequest req = buildUnifiedOrderRequest(payOrder, mchConfigContext);
req.setTradeType(WxPayConstants.TradeType.APP);
// 构造函数响应数据
WxAppOrderRS res = ApiResBuilder.buildSuccess(WxAppOrderRS.class);
ChannelRetMsg channelRetMsg = new ChannelRetMsg();
res.setChannelRetMsg(channelRetMsg);
// 调起上游接口:
// 1. 如果抛异常,则订单状态为: 生成状态,此时没有查单处理操作。 订单将超时关闭
// 2. 接口调用成功, 后续异常需进行捕捉, 如果 逻辑代码出现异常则需要走完正常流程,此时订单状态为: 支付中, 需要查单处理。
WxPayService wxPayService = mchConfigContext.getWxServiceWrapper().getWxPayService();
try {
WxPayAppOrderResult payResult = wxPayService.createOrder(req);
JSONObject resJSON = (JSONObject) JSON.toJSON(payResult);
resJSON.put("package", payResult.getPackageValue());
res.setPayInfo(resJSON.toJSONString());
// 支付中
channelRetMsg.setChannelState(ChannelRetMsg.ChannelState.WAITING);
} catch (WxPayException e) {
channelRetMsg.setChannelState(ChannelRetMsg.ChannelState.CONFIRM_FAIL);
WxpayKit.commonSetErrInfo(channelRetMsg, e);
}
return res;
}
}
/*
* Copyright (c) 2021-2031, 河北计全科技有限公司 (https://www.jeequan.com & jeequan@126.com).
* <p>
* Licensed under the GNU LESSER GENERAL PUBLIC LICENSE 3.0;
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
* <p>
* http://www.gnu.org/licenses/lgpl.html
* <p>
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package com.jeequan.jeepay.pay.channel.wxpay.payway;
import com.github.binarywang.wxpay.bean.request.WxPayMicropayRequest;
import com.github.binarywang.wxpay.bean.result.WxPayMicropayResult;
import com.github.binarywang.wxpay.exception.WxPayException;
import com.github.binarywang.wxpay.service.WxPayService;
import com.jeequan.jeepay.core.entity.PayOrder;
import com.jeequan.jeepay.core.exception.BizException;
import com.jeequan.jeepay.pay.channel.wxpay.WxpayPaymentService;
import com.jeequan.jeepay.pay.channel.wxpay.kits.WxpayKit;
import com.jeequan.jeepay.pay.rqrs.AbstractRS;
import com.jeequan.jeepay.pay.rqrs.payorder.UnifiedOrderRQ;
import com.jeequan.jeepay.pay.rqrs.payorder.payway.WxBarOrderRQ;
import com.jeequan.jeepay.pay.rqrs.payorder.payway.WxBarOrderRS;
import com.jeequan.jeepay.pay.rqrs.msg.ChannelRetMsg;
import com.jeequan.jeepay.pay.util.ApiResBuilder;
import com.jeequan.jeepay.pay.model.MchConfigContext;
import org.apache.commons.lang3.StringUtils;
import org.springframework.stereotype.Service;
/*
* 微信 bar
*
* @author zhuxiao
* @site https://www.jeepay.vip
* @date 2021/6/8 18:08
*/
@Service("wxpayPaymentByBarService") //Service Name需保持全局唯一性
public class WxBar extends WxpayPaymentService {
@Override
public String preCheck(UnifiedOrderRQ rq, PayOrder payOrder) {
WxBarOrderRQ bizRQ = (WxBarOrderRQ) rq;
if(StringUtils.isEmpty(bizRQ.getAuthCode())){
throw new BizException("用户支付条码[authCode]不可为空");
}
return null;
}
@Override
public AbstractRS pay(UnifiedOrderRQ rq, PayOrder payOrder, MchConfigContext mchConfigContext) throws Exception{
WxBarOrderRQ bizRQ = (WxBarOrderRQ) rq;
// 微信统一下单请求对象
WxPayMicropayRequest request = new WxPayMicropayRequest();
request.setOutTradeNo(payOrder.getPayOrderId());
request.setBody(payOrder.getSubject());
request.setDetail(payOrder.getBody());
request.setFeeType("CNY");
request.setTotalFee(payOrder.getAmount().intValue());
request.setSpbillCreateIp(payOrder.getClientIp());
request.setAuthCode(bizRQ.getAuthCode());
//放置isv信息
WxpayKit.putApiIsvInfo(mchConfigContext, request);
// 构造函数响应数据
WxBarOrderRS res = ApiResBuilder.buildSuccess(WxBarOrderRS.class);
ChannelRetMsg channelRetMsg = new ChannelRetMsg();
res.setChannelRetMsg(channelRetMsg);
// 调起上游接口:
// 1. 如果抛异常,则订单状态为: 生成状态,此时没有查单处理操作。 订单将超时关闭
// 2. 接口调用成功, 后续异常需进行捕捉, 如果 逻辑代码出现异常则需要走完正常流程,此时订单状态为: 支付中, 需要查单处理。
WxPayService wxPayService = mchConfigContext.getWxServiceWrapper().getWxPayService();
try {
WxPayMicropayResult wxPayMicropayResult = wxPayService.micropay(request);
channelRetMsg.setChannelOrderId(wxPayMicropayResult.getTransactionId());
channelRetMsg.setChannelState(ChannelRetMsg.ChannelState.CONFIRM_SUCCESS);
} catch (WxPayException e) {
//微信返回支付状态为【支付结果未知】, 需进行查单操作
if("SYSTEMERROR".equals(e.getErrCode()) || "USERPAYING".equals(e.getErrCode()) || "BANKERROR".equals(e.getErrCode())){
//轮询查询订单
channelRetMsg.setChannelState(ChannelRetMsg.ChannelState.WAITING);
channelRetMsg.setNeedQuery(true);
}else {
channelRetMsg.setChannelState(ChannelRetMsg.ChannelState.CONFIRM_FAIL);
WxpayKit.commonSetErrInfo(channelRetMsg, e);
}
}
return res;
}
}
/*
* Copyright (c) 2021-2031, 河北计全科技有限公司 (https://www.jeequan.com & jeequan@126.com).
* <p>
* Licensed under the GNU LESSER GENERAL PUBLIC LICENSE 3.0;
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
* <p>
* http://www.gnu.org/licenses/lgpl.html
* <p>
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package com.jeequan.jeepay.pay.channel.wxpay.payway;
import com.github.binarywang.wxpay.bean.order.WxPayMwebOrderResult;
import com.github.binarywang.wxpay.bean.request.WxPayUnifiedOrderRequest;
import com.github.binarywang.wxpay.constant.WxPayConstants;
import com.github.binarywang.wxpay.exception.WxPayException;
import com.github.binarywang.wxpay.service.WxPayService;
import com.jeequan.jeepay.core.constants.CS;
import com.jeequan.jeepay.core.entity.PayOrder;
import com.jeequan.jeepay.pay.channel.wxpay.WxpayPaymentService;
import com.jeequan.jeepay.pay.channel.wxpay.kits.WxpayKit;
import com.jeequan.jeepay.pay.rqrs.AbstractRS;
import com.jeequan.jeepay.pay.rqrs.payorder.UnifiedOrderRQ;
import com.jeequan.jeepay.pay.rqrs.payorder.payway.WxH5OrderRQ;
import com.jeequan.jeepay.pay.rqrs.payorder.payway.WxH5OrderRS;
import com.jeequan.jeepay.pay.rqrs.msg.ChannelRetMsg;
import com.jeequan.jeepay.pay.util.ApiResBuilder;
import com.jeequan.jeepay.pay.model.MchConfigContext;
import org.springframework.stereotype.Service;
/*
* 微信 H5 支付
*
* @author zhuxiao
* @site https://www.jeepay.vip
* @date 2021/6/8 18:08
*/
@Service("wxpayPaymentByH5Service") //Service Name需保持全局唯一性
public class WxH5 extends WxpayPaymentService {
@Override
public String preCheck(UnifiedOrderRQ rq, PayOrder payOrder) {
return null;
}
@Override
public AbstractRS pay(UnifiedOrderRQ rq, PayOrder payOrder, MchConfigContext mchConfigContext) {
WxH5OrderRQ bizRQ = (WxH5OrderRQ) rq;
WxPayUnifiedOrderRequest req = buildUnifiedOrderRequest(payOrder, mchConfigContext);
req.setTradeType(WxPayConstants.TradeType.MWEB);
// 构造函数响应数据
WxH5OrderRS res = ApiResBuilder.buildSuccess(WxH5OrderRS.class);
ChannelRetMsg channelRetMsg = new ChannelRetMsg();
res.setChannelRetMsg(channelRetMsg);
// 调起上游接口:
// 1. 如果抛异常,则订单状态为: 生成状态,此时没有查单处理操作。 订单将超时关闭
// 2. 接口调用成功, 后续异常需进行捕捉, 如果 逻辑代码出现异常则需要走完正常流程,此时订单状态为: 支付中, 需要查单处理。
WxPayService wxPayService = mchConfigContext.getWxServiceWrapper().getWxPayService();
try {
WxPayMwebOrderResult wxPayMwebOrderResult = wxPayService.createOrder(req);
String payUrl = wxPayMwebOrderResult.getMwebUrl();
if(CS.PAY_DATA_TYPE.FORM.equals(bizRQ.getPayDataType())){ //表单方式
res.setFormContent(payUrl);
}else if (CS.PAY_DATA_TYPE.CODE_IMG_URL.equals(bizRQ.getPayDataType())){ //二维码图片地址
res.setCodeImgUrl(sysConfigService.getDBApplicationConfig().genScanImgUrl(payUrl));
}else{ // 默认都为 payUrl方式
res.setPayUrl(payUrl);
}
// 支付中
channelRetMsg.setChannelState(ChannelRetMsg.ChannelState.WAITING);
} catch (WxPayException e) {
channelRetMsg.setChannelState(ChannelRetMsg.ChannelState.CONFIRM_FAIL);
WxpayKit.commonSetErrInfo(channelRetMsg, e);
}
return res;
}
}
/*
* Copyright (c) 2021-2031, 河北计全科技有限公司 (https://www.jeequan.com & jeequan@126.com).
* <p>
* Licensed under the GNU LESSER GENERAL PUBLIC LICENSE 3.0;
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
* <p>
* http://www.gnu.org/licenses/lgpl.html
* <p>
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package com.jeequan.jeepay.pay.channel.wxpay.payway;
import com.alibaba.fastjson.JSON;
import com.alibaba.fastjson.JSONObject;
import com.github.binarywang.wxpay.bean.order.WxPayMpOrderResult;
import com.github.binarywang.wxpay.bean.request.WxPayUnifiedOrderRequest;
import com.github.binarywang.wxpay.constant.WxPayConstants;
import com.github.binarywang.wxpay.exception.WxPayException;
import com.github.binarywang.wxpay.service.WxPayService;
import com.jeequan.jeepay.core.entity.PayOrder;
import com.jeequan.jeepay.core.exception.BizException;
import com.jeequan.jeepay.pay.channel.wxpay.WxpayPaymentService;
import com.jeequan.jeepay.pay.channel.wxpay.kits.WxpayKit;
import com.jeequan.jeepay.pay.rqrs.AbstractRS;
import com.jeequan.jeepay.pay.rqrs.payorder.UnifiedOrderRQ;
import com.jeequan.jeepay.pay.rqrs.payorder.payway.WxJsapiOrderRQ;
import com.jeequan.jeepay.pay.rqrs.payorder.payway.WxJsapiOrderRS;
import com.jeequan.jeepay.pay.rqrs.msg.ChannelRetMsg;
import com.jeequan.jeepay.pay.util.ApiResBuilder;
import com.jeequan.jeepay.pay.model.MchConfigContext;
import lombok.extern.slf4j.Slf4j;
import org.apache.commons.lang3.StringUtils;
import org.springframework.stereotype.Service;
/*
* 微信 jsapi支付
*
* @author zhuxiao
* @site https://www.jeepay.vip
* @date 2021/6/8 18:08
*/
@Service("wxpayPaymentByJsapiService") //Service Name需保持全局唯一性
@Slf4j
public class WxJsapi extends WxpayPaymentService {
@Override
public String preCheck(UnifiedOrderRQ rq, PayOrder payOrder) {
WxJsapiOrderRQ bizRQ = (WxJsapiOrderRQ) rq;
if(StringUtils.isEmpty(bizRQ.getOpenid())){
throw new BizException("[openid]不可为空");
}
return null;
}
@Override
public AbstractRS pay(UnifiedOrderRQ rq, PayOrder payOrder, MchConfigContext mchConfigContext) throws Exception{
WxJsapiOrderRQ bizRQ = (WxJsapiOrderRQ) rq;
WxPayUnifiedOrderRequest req = buildUnifiedOrderRequest(payOrder, mchConfigContext);
req.setTradeType(WxPayConstants.TradeType.JSAPI);
req.setOpenid(bizRQ.getOpenid());
// 构造函数响应数据
WxJsapiOrderRS res = ApiResBuilder.buildSuccess(WxJsapiOrderRS.class);
ChannelRetMsg channelRetMsg = new ChannelRetMsg();
res.setChannelRetMsg(channelRetMsg);
// 调起上游接口:
// 1. 如果抛异常,则订单状态为: 生成状态,此时没有查单处理操作。 订单将超时关闭
// 2. 接口调用成功, 后续异常需进行捕捉, 如果 逻辑代码出现异常则需要走完正常流程,此时订单状态为: 支付中, 需要查单处理。
WxPayService wxPayService = mchConfigContext.getWxServiceWrapper().getWxPayService();
try {
WxPayMpOrderResult payResult = wxPayService.createOrder(req);
JSONObject resJSON = (JSONObject) JSON.toJSON(payResult);
resJSON.put("package", payResult.getPackageValue());
res.setPayInfo(resJSON.toJSONString());
// 支付中
channelRetMsg.setChannelState(ChannelRetMsg.ChannelState.WAITING);
} catch (WxPayException e) {
log.error("WxPayException:", e);
//明确失败
channelRetMsg.setChannelState(ChannelRetMsg.ChannelState.CONFIRM_FAIL);
WxpayKit.commonSetErrInfo(channelRetMsg, e);
}
return res;
}
}
/*
* Copyright (c) 2021-2031, 河北计全科技有限公司 (https://www.jeequan.com & jeequan@126.com).
* <p>
* Licensed under the GNU LESSER GENERAL PUBLIC LICENSE 3.0;
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
* <p>
* http://www.gnu.org/licenses/lgpl.html
* <p>
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package com.jeequan.jeepay.pay.channel.wxpay.payway;
import com.alibaba.fastjson.JSON;
import com.alibaba.fastjson.JSONObject;
import com.github.binarywang.wxpay.bean.order.WxPayMpOrderResult;
import com.github.binarywang.wxpay.bean.request.WxPayUnifiedOrderRequest;
import com.github.binarywang.wxpay.constant.WxPayConstants;
import com.github.binarywang.wxpay.exception.WxPayException;
import com.github.binarywang.wxpay.service.WxPayService;
import com.jeequan.jeepay.core.entity.PayOrder;
import com.jeequan.jeepay.core.exception.BizException;
import com.jeequan.jeepay.pay.channel.wxpay.WxpayPaymentService;
import com.jeequan.jeepay.pay.channel.wxpay.kits.WxpayKit;
import com.jeequan.jeepay.pay.rqrs.AbstractRS;
import com.jeequan.jeepay.pay.rqrs.payorder.UnifiedOrderRQ;
import com.jeequan.jeepay.pay.rqrs.payorder.payway.WxJsapiOrderRQ;
import com.jeequan.jeepay.pay.rqrs.payorder.payway.WxJsapiOrderRS;
import com.jeequan.jeepay.pay.rqrs.msg.ChannelRetMsg;
import com.jeequan.jeepay.pay.util.ApiResBuilder;
import com.jeequan.jeepay.pay.model.MchConfigContext;
import org.apache.commons.lang3.StringUtils;
import org.springframework.stereotype.Service;
/*
* 微信 小程序支付
*
* @author zhuxiao
* @site https://www.jeepay.vip
* @date 2021/6/8 18:08
*/
@Service("wxpayPaymentByLiteService") //Service Name需保持全局唯一性
public class WxLite extends WxpayPaymentService {
@Override
public String preCheck(UnifiedOrderRQ rq, PayOrder payOrder) {
WxJsapiOrderRQ bizRQ = (WxJsapiOrderRQ) rq;
if(StringUtils.isEmpty(bizRQ.getOpenid())){
throw new BizException("[openid]不可为空");
}
return null;
}
@Override
public AbstractRS pay(UnifiedOrderRQ rq, PayOrder payOrder, MchConfigContext mchConfigContext) throws Exception{
WxJsapiOrderRQ bizRQ = (WxJsapiOrderRQ) rq;
WxPayUnifiedOrderRequest req = buildUnifiedOrderRequest(payOrder, mchConfigContext);
req.setTradeType(WxPayConstants.TradeType.JSAPI);
req.setOpenid(bizRQ.getOpenid());
// 构造函数响应数据
WxJsapiOrderRS res = ApiResBuilder.buildSuccess(WxJsapiOrderRS.class);
ChannelRetMsg channelRetMsg = new ChannelRetMsg();
res.setChannelRetMsg(channelRetMsg);
// 调起上游接口:
// 1. 如果抛异常,则订单状态为: 生成状态,此时没有查单处理操作。 订单将超时关闭
// 2. 接口调用成功, 后续异常需进行捕捉, 如果 逻辑代码出现异常则需要走完正常流程,此时订单状态为: 支付中, 需要查单处理。
WxPayService wxPayService = mchConfigContext.getWxServiceWrapper().getWxPayService();
try {
WxPayMpOrderResult payResult = wxPayService.createOrder(req);
JSONObject resJSON = (JSONObject) JSON.toJSON(payResult);
resJSON.put("package", payResult.getPackageValue());
res.setPayInfo(resJSON.toJSONString());
// 支付中
channelRetMsg.setChannelState(ChannelRetMsg.ChannelState.WAITING);
} catch (WxPayException e) {
channelRetMsg.setChannelState(ChannelRetMsg.ChannelState.CONFIRM_FAIL);
WxpayKit.commonSetErrInfo(channelRetMsg, e);
}
return res;
}
}
/*
* Copyright (c) 2021-2031, 河北计全科技有限公司 (https://www.jeequan.com & jeequan@126.com).
* <p>
* Licensed under the GNU LESSER GENERAL PUBLIC LICENSE 3.0;
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
* <p>
* http://www.gnu.org/licenses/lgpl.html
* <p>
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package com.jeequan.jeepay.pay.channel.wxpay.payway;
import com.github.binarywang.wxpay.bean.order.WxPayNativeOrderResult;
import com.github.binarywang.wxpay.bean.request.WxPayUnifiedOrderRequest;
import com.github.binarywang.wxpay.constant.WxPayConstants;
import com.github.binarywang.wxpay.exception.WxPayException;
import com.github.binarywang.wxpay.service.WxPayService;
import com.jeequan.jeepay.core.constants.CS;
import com.jeequan.jeepay.core.entity.PayOrder;
import com.jeequan.jeepay.pay.channel.wxpay.WxpayPaymentService;
import com.jeequan.jeepay.pay.channel.wxpay.kits.WxpayKit;
import com.jeequan.jeepay.pay.rqrs.AbstractRS;
import com.jeequan.jeepay.pay.rqrs.payorder.UnifiedOrderRQ;
import com.jeequan.jeepay.pay.rqrs.payorder.payway.WxNativeOrderRQ;
import com.jeequan.jeepay.pay.rqrs.payorder.payway.WxNativeOrderRS;
import com.jeequan.jeepay.pay.rqrs.msg.ChannelRetMsg;
import com.jeequan.jeepay.pay.util.ApiResBuilder;
import com.jeequan.jeepay.pay.model.MchConfigContext;
import org.springframework.stereotype.Service;
/*
* 微信 native支付
*
* @author zhuxiao
* @site https://www.jeepay.vip
* @date 2021/6/8 18:08
*/
@Service("wxpayPaymentByNativeService") //Service Name需保持全局唯一性
public class WxNative extends WxpayPaymentService {
@Override
public String preCheck(UnifiedOrderRQ rq, PayOrder payOrder) {
return null;
}
@Override
public AbstractRS pay(UnifiedOrderRQ rq, PayOrder payOrder, MchConfigContext mchConfigContext) throws Exception{
WxNativeOrderRQ bizRQ = (WxNativeOrderRQ) rq;
WxPayUnifiedOrderRequest req = buildUnifiedOrderRequest(payOrder, mchConfigContext);
req.setTradeType(WxPayConstants.TradeType.NATIVE);
// 构造函数响应数据
WxNativeOrderRS res = ApiResBuilder.buildSuccess(WxNativeOrderRS.class);
ChannelRetMsg channelRetMsg = new ChannelRetMsg();
res.setChannelRetMsg(channelRetMsg);
// 调起上游接口:
// 1. 如果抛异常,则订单状态为: 生成状态,此时没有查单处理操作。 订单将超时关闭
// 2. 接口调用成功, 后续异常需进行捕捉, 如果 逻辑代码出现异常则需要走完正常流程,此时订单状态为: 支付中, 需要查单处理。
WxPayService wxPayService = mchConfigContext.getWxServiceWrapper().getWxPayService();
try {
WxPayNativeOrderResult wxPayNativeOrderResult = wxPayService.createOrder(req);
String codeUrl = wxPayNativeOrderResult.getCodeUrl();
if (CS.PAY_DATA_TYPE.CODE_IMG_URL.equals(bizRQ.getPayDataType())){ //二维码图片地址
res.setCodeImgUrl(sysConfigService.getDBApplicationConfig().genScanImgUrl(codeUrl));
}else{
res.setCodeUrl(codeUrl);
}
// 支付中
channelRetMsg.setChannelState(ChannelRetMsg.ChannelState.WAITING);
} catch (WxPayException e) {
channelRetMsg.setChannelState(ChannelRetMsg.ChannelState.CONFIRM_FAIL);
WxpayKit.commonSetErrInfo(channelRetMsg, e);
}
return res;
}
}
/*
* Copyright (c) 2021-2031, 河北计全科技有限公司 (https://www.jeequan.com & jeequan@126.com).
* <p>
* Licensed under the GNU LESSER GENERAL PUBLIC LICENSE 3.0;
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
* <p>
* http://www.gnu.org/licenses/lgpl.html
* <p>
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package com.jeequan.jeepay.pay.channel.wxpay.paywayV3;
import com.alibaba.fastjson.JSONObject;
import com.github.binarywang.wxpay.constant.WxPayConstants;
import com.github.binarywang.wxpay.exception.WxPayException;
import com.github.binarywang.wxpay.service.WxPayService;
import com.jeequan.jeepay.core.entity.PayOrder;
import com.jeequan.jeepay.pay.channel.wxpay.WxpayPaymentService;
import com.jeequan.jeepay.pay.channel.wxpay.kits.WxpayKit;
import com.jeequan.jeepay.pay.channel.wxpay.kits.WxpayV3Util;
import com.jeequan.jeepay.pay.rqrs.AbstractRS;
import com.jeequan.jeepay.pay.rqrs.payorder.UnifiedOrderRQ;
import com.jeequan.jeepay.pay.rqrs.payorder.payway.WxAppOrderRS;
import com.jeequan.jeepay.pay.rqrs.msg.ChannelRetMsg;
import com.jeequan.jeepay.pay.util.ApiResBuilder;
import com.jeequan.jeepay.pay.model.MchConfigContext;
import org.springframework.stereotype.Service;
/*
* 微信 app支付
*
* @author zhuxiao
* @site https://www.jeepay.vip
* @date 2021/6/8 18:08
*/
@Service("wxpayPaymentByAppV3Service") //Service Name需保持全局唯一性
public class WxApp extends WxpayPaymentService {
@Override
public String preCheck(UnifiedOrderRQ rq, PayOrder payOrder) {
return null;
}
@Override
public AbstractRS pay(UnifiedOrderRQ rq, PayOrder payOrder, MchConfigContext mchConfigContext) {
WxPayService wxPayService = mchConfigContext.getWxServiceWrapper().getWxPayService();
// 构造请求数据
JSONObject reqJSON = buildV3OrderRequest(payOrder, mchConfigContext);
String reqUrl; // 请求地址
if(mchConfigContext.isIsvsubMch()){ // 特约商户
reqUrl = WxpayV3Util.ISV_URL_MAP.get(WxPayConstants.TradeType.APP);
}else {
reqUrl = WxpayV3Util.NORMALMCH_URL_MAP.get(WxPayConstants.TradeType.APP);
}
// 构造函数响应数据
WxAppOrderRS res = ApiResBuilder.buildSuccess(WxAppOrderRS.class);
ChannelRetMsg channelRetMsg = new ChannelRetMsg();
res.setChannelRetMsg(channelRetMsg);
// 调起上游接口:
// 1. 如果抛异常,则订单状态为: 生成状态,此时没有查单处理操作。 订单将超时关闭
// 2. 接口调用成功, 后续异常需进行捕捉, 如果 逻辑代码出现异常则需要走完正常流程,此时订单状态为: 支付中, 需要查单处理。
try {
JSONObject resJSON = WxpayV3Util.unifiedOrderV3(reqUrl, reqJSON, wxPayService.getConfig());
res.setPayInfo(resJSON.toJSONString());
// 支付中
channelRetMsg.setChannelState(ChannelRetMsg.ChannelState.WAITING);
} catch (WxPayException e) {
//明确失败
channelRetMsg.setChannelState(ChannelRetMsg.ChannelState.CONFIRM_FAIL);
WxpayKit.commonSetErrInfo(channelRetMsg, e);
}
return res;
}
}
/*
* Copyright (c) 2021-2031, 河北计全科技有限公司 (https://www.jeequan.com & jeequan@126.com).
* <p>
* Licensed under the GNU LESSER GENERAL PUBLIC LICENSE 3.0;
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
* <p>
* http://www.gnu.org/licenses/lgpl.html
* <p>
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package com.jeequan.jeepay.pay.channel.wxpay.paywayV3;
import com.jeequan.jeepay.core.entity.PayOrder;
import com.jeequan.jeepay.pay.channel.wxpay.WxpayPaymentService;
import com.jeequan.jeepay.pay.model.MchConfigContext;
import com.jeequan.jeepay.pay.rqrs.AbstractRS;
import com.jeequan.jeepay.pay.rqrs.payorder.UnifiedOrderRQ;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
/*
* 微信 条码支付
*
* @author zhuxiao
* @site https://www.jeepay.vip
* @date 2021/6/8 18:08
*/
@Service("wxpayPaymentByBarV3Service") //Service Name需保持全局唯一性
public class WxBar extends WxpayPaymentService {
@Autowired
private com.jeequan.jeepay.pay.channel.wxpay.payway.WxBar wxBar;
@Override
public String preCheck(UnifiedOrderRQ rq, PayOrder payOrder) {
return wxBar.preCheck(rq, payOrder);
}
@Override
public AbstractRS pay(UnifiedOrderRQ rq, PayOrder payOrder, MchConfigContext mchConfigContext) throws Exception {
return wxBar.pay(rq, payOrder, mchConfigContext);
}
}
/*
* Copyright (c) 2021-2031, 河北计全科技有限公司 (https://www.jeequan.com & jeequan@126.com).
* <p>
* Licensed under the GNU LESSER GENERAL PUBLIC LICENSE 3.0;
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
* <p>
* http://www.gnu.org/licenses/lgpl.html
* <p>
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package com.jeequan.jeepay.pay.channel.wxpay.paywayV3;
import com.alibaba.fastjson.JSONObject;
import com.github.binarywang.wxpay.constant.WxPayConstants;
import com.github.binarywang.wxpay.exception.WxPayException;
import com.github.binarywang.wxpay.service.WxPayService;
import com.jeequan.jeepay.core.constants.CS;
import com.jeequan.jeepay.core.entity.PayOrder;
import com.jeequan.jeepay.pay.channel.wxpay.WxpayPaymentService;
import com.jeequan.jeepay.pay.channel.wxpay.kits.WxpayKit;
import com.jeequan.jeepay.pay.channel.wxpay.kits.WxpayV3Util;
import com.jeequan.jeepay.pay.rqrs.AbstractRS;
import com.jeequan.jeepay.pay.rqrs.payorder.UnifiedOrderRQ;
import com.jeequan.jeepay.pay.rqrs.payorder.payway.WxH5OrderRQ;
import com.jeequan.jeepay.pay.rqrs.payorder.payway.WxH5OrderRS;
import com.jeequan.jeepay.pay.rqrs.msg.ChannelRetMsg;
import com.jeequan.jeepay.pay.util.ApiResBuilder;
import com.jeequan.jeepay.pay.model.MchConfigContext;
import org.springframework.stereotype.Service;
/*
* 微信 H5支付
*
* @author zhuxiao
* @site https://www.jeepay.vip
* @date 2021/6/8 18:08
*/
@Service("wxpayPaymentByH5V3Service") //Service Name需保持全局唯一性
public class WxH5 extends WxpayPaymentService {
@Override
public String preCheck(UnifiedOrderRQ rq, PayOrder payOrder) {
return null;
}
@Override
public AbstractRS pay(UnifiedOrderRQ rq, PayOrder payOrder, MchConfigContext mchConfigContext) {
WxH5OrderRQ bizRQ = (WxH5OrderRQ) rq;
WxPayService wxPayService = mchConfigContext.getWxServiceWrapper().getWxPayService();
// 构造请求数据
JSONObject reqJSON = buildV3OrderRequest(payOrder, mchConfigContext);
JSONObject sceneInfo = reqJSON.getJSONObject("scene_info");
JSONObject h5Info = new JSONObject();
h5Info.put("type", "iOS, Android, Wap");
sceneInfo.put("h5_info", h5Info);
reqJSON.put("scene_info", sceneInfo);
String reqUrl; // 请求地址
if(mchConfigContext.isIsvsubMch()){ // 特约商户
reqUrl = WxpayV3Util.ISV_URL_MAP.get(WxPayConstants.TradeType.MWEB);
}else {
reqUrl = WxpayV3Util.NORMALMCH_URL_MAP.get(WxPayConstants.TradeType.MWEB);
}
// 构造函数响应数据
WxH5OrderRS res = ApiResBuilder.buildSuccess(WxH5OrderRS.class);
ChannelRetMsg channelRetMsg = new ChannelRetMsg();
res.setChannelRetMsg(channelRetMsg);
// 调起上游接口:
// 1. 如果抛异常,则订单状态为: 生成状态,此时没有查单处理操作。 订单将超时关闭
// 2. 接口调用成功, 后续异常需进行捕捉, 如果 逻辑代码出现异常则需要走完正常流程,此时订单状态为: 支付中, 需要查单处理。
try {
JSONObject resJSON = WxpayV3Util.unifiedOrderV3(reqUrl, reqJSON, wxPayService.getConfig());
String payUrl = resJSON.getString("h5_url");
if (CS.PAY_DATA_TYPE.CODE_IMG_URL.equals(bizRQ.getPayDataType())){ //二维码图片地址
res.setCodeImgUrl(sysConfigService.getDBApplicationConfig().genScanImgUrl(payUrl));
}else{ // 默认都为 payUrl方式
res.setPayUrl(payUrl);
}
// 支付中
channelRetMsg.setChannelState(ChannelRetMsg.ChannelState.WAITING);
} catch (WxPayException e) {
//明确失败
channelRetMsg.setChannelState(ChannelRetMsg.ChannelState.CONFIRM_FAIL);
WxpayKit.commonSetErrInfo(channelRetMsg, e);
}
return res;
}
}
/*
* Copyright (c) 2021-2031, 河北计全科技有限公司 (https://www.jeequan.com & jeequan@126.com).
* <p>
* Licensed under the GNU LESSER GENERAL PUBLIC LICENSE 3.0;
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
* <p>
* http://www.gnu.org/licenses/lgpl.html
* <p>
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package com.jeequan.jeepay.pay.channel.wxpay.paywayV3;
import com.alibaba.fastjson.JSONObject;
import com.github.binarywang.wxpay.constant.WxPayConstants;
import com.github.binarywang.wxpay.exception.WxPayException;
import com.github.binarywang.wxpay.service.WxPayService;
import com.jeequan.jeepay.core.entity.PayOrder;
import com.jeequan.jeepay.pay.channel.wxpay.WxpayPaymentService;
import com.jeequan.jeepay.pay.channel.wxpay.kits.WxpayKit;
import com.jeequan.jeepay.pay.channel.wxpay.kits.WxpayV3Util;
import com.jeequan.jeepay.pay.rqrs.AbstractRS;
import com.jeequan.jeepay.pay.rqrs.payorder.UnifiedOrderRQ;
import com.jeequan.jeepay.pay.rqrs.payorder.payway.WxJsapiOrderRQ;
import com.jeequan.jeepay.pay.rqrs.payorder.payway.WxJsapiOrderRS;
import com.jeequan.jeepay.pay.rqrs.msg.ChannelRetMsg;
import com.jeequan.jeepay.pay.util.ApiResBuilder;
import com.jeequan.jeepay.pay.model.MchConfigContext;
import org.springframework.stereotype.Service;
/*
* 微信 jsapi支付
*
* @author zhuxiao
* @site https://www.jeepay.vip
* @date 2021/6/8 18:08
*/
@Service("wxpayPaymentByJsapiV3Service") //Service Name需保持全局唯一性
public class WxJsapi extends WxpayPaymentService {
@Override
public String preCheck(UnifiedOrderRQ rq, PayOrder payOrder) {
// 使用的是V2接口的预先校验
return null;
}
@Override
public AbstractRS pay(UnifiedOrderRQ rq, PayOrder payOrder, MchConfigContext mchConfigContext) throws Exception{
WxJsapiOrderRQ bizRQ = (WxJsapiOrderRQ) rq;
WxPayService wxPayService = mchConfigContext.getWxServiceWrapper().getWxPayService();
// 构造请求数据
JSONObject reqJSON = buildV3OrderRequest(payOrder, mchConfigContext);
String reqUrl; // 请求地址
if(mchConfigContext.isIsvsubMch()){ // 特约商户
reqUrl = WxpayV3Util.ISV_URL_MAP.get(WxPayConstants.TradeType.JSAPI);
JSONObject payer = new JSONObject();
payer.put("sp_openid", bizRQ.getOpenid());
reqJSON.put("payer", payer);
}else {
reqUrl = WxpayV3Util.NORMALMCH_URL_MAP.get(WxPayConstants.TradeType.JSAPI);
JSONObject payer = new JSONObject();
payer.put("openid", bizRQ.getOpenid());
reqJSON.put("payer", payer);
}
// 构造函数响应数据
WxJsapiOrderRS res = ApiResBuilder.buildSuccess(WxJsapiOrderRS.class);
ChannelRetMsg channelRetMsg = new ChannelRetMsg();
res.setChannelRetMsg(channelRetMsg);
// 调起上游接口:
// 1. 如果抛异常,则订单状态为: 生成状态,此时没有查单处理操作。 订单将超时关闭
// 2. 接口调用成功, 后续异常需进行捕捉, 如果 逻辑代码出现异常则需要走完正常流程,此时订单状态为: 支付中, 需要查单处理。
try {
JSONObject resJSON = WxpayV3Util.unifiedOrderV3(reqUrl, reqJSON, wxPayService.getConfig());
res.setPayInfo(resJSON.toJSONString());
// 支付中
channelRetMsg.setChannelState(ChannelRetMsg.ChannelState.WAITING);
} catch (WxPayException e) {
//明确失败
channelRetMsg.setChannelState(ChannelRetMsg.ChannelState.CONFIRM_FAIL);
WxpayKit.commonSetErrInfo(channelRetMsg, e);
}
return res;
}
}
/*
* Copyright (c) 2021-2031, 河北计全科技有限公司 (https://www.jeequan.com & jeequan@126.com).
* <p>
* Licensed under the GNU LESSER GENERAL PUBLIC LICENSE 3.0;
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
* <p>
* http://www.gnu.org/licenses/lgpl.html
* <p>
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package com.jeequan.jeepay.pay.channel.wxpay.paywayV3;
import com.alibaba.fastjson.JSONObject;
import com.github.binarywang.wxpay.constant.WxPayConstants;
import com.github.binarywang.wxpay.exception.WxPayException;
import com.github.binarywang.wxpay.service.WxPayService;
import com.jeequan.jeepay.core.entity.PayOrder;
import com.jeequan.jeepay.pay.channel.wxpay.WxpayPaymentService;
import com.jeequan.jeepay.pay.channel.wxpay.kits.WxpayKit;
import com.jeequan.jeepay.pay.channel.wxpay.kits.WxpayV3Util;
import com.jeequan.jeepay.pay.rqrs.AbstractRS;
import com.jeequan.jeepay.pay.rqrs.payorder.UnifiedOrderRQ;
import com.jeequan.jeepay.pay.rqrs.payorder.payway.WxJsapiOrderRQ;
import com.jeequan.jeepay.pay.rqrs.payorder.payway.WxJsapiOrderRS;
import com.jeequan.jeepay.pay.rqrs.msg.ChannelRetMsg;
import com.jeequan.jeepay.pay.util.ApiResBuilder;
import com.jeequan.jeepay.pay.model.MchConfigContext;
import org.springframework.stereotype.Service;
/*
* 微信 小程序
*
* @author zhuxiao
* @site https://www.jeepay.vip
* @date 2021/6/8 18:08
*/
@Service("wxpayPaymentByLiteV3Service") //Service Name需保持全局唯一性
public class WxLite extends WxpayPaymentService {
@Override
public String preCheck(UnifiedOrderRQ rq, PayOrder payOrder) {
// 使用的是V2接口的预先校验
return null;
}
@Override
public AbstractRS pay(UnifiedOrderRQ rq, PayOrder payOrder, MchConfigContext mchConfigContext) throws Exception{
WxJsapiOrderRQ bizRQ = (WxJsapiOrderRQ) rq;
WxPayService wxPayService = mchConfigContext.getWxServiceWrapper().getWxPayService();
// 构造请求数据
JSONObject reqJSON = buildV3OrderRequest(payOrder, mchConfigContext);
String reqUrl; // 请求地址
if(mchConfigContext.isIsvsubMch()){ // 特约商户
reqUrl = WxpayV3Util.ISV_URL_MAP.get(WxPayConstants.TradeType.JSAPI);
JSONObject payer = new JSONObject();
payer.put("sp_openid", bizRQ.getOpenid());
reqJSON.put("payer", payer);
}else {
reqUrl = WxpayV3Util.NORMALMCH_URL_MAP.get(WxPayConstants.TradeType.JSAPI);
JSONObject payer = new JSONObject();
payer.put("openid", bizRQ.getOpenid());
reqJSON.put("payer", payer);
}
// 构造函数响应数据
WxJsapiOrderRS res = ApiResBuilder.buildSuccess(WxJsapiOrderRS.class);
ChannelRetMsg channelRetMsg = new ChannelRetMsg();
res.setChannelRetMsg(channelRetMsg);
// 调起上游接口:
// 1. 如果抛异常,则订单状态为: 生成状态,此时没有查单处理操作。 订单将超时关闭
// 2. 接口调用成功, 后续异常需进行捕捉, 如果 逻辑代码出现异常则需要走完正常流程,此时订单状态为: 支付中, 需要查单处理。
try {
JSONObject resJSON = WxpayV3Util.unifiedOrderV3(reqUrl, reqJSON, wxPayService.getConfig());
res.setPayInfo(resJSON.toJSONString());
// 支付中
channelRetMsg.setChannelState(ChannelRetMsg.ChannelState.WAITING);
} catch (WxPayException e) {
//明确失败
channelRetMsg.setChannelState(ChannelRetMsg.ChannelState.CONFIRM_FAIL);
WxpayKit.commonSetErrInfo(channelRetMsg, e);
}
return res;
}
}
/*
* Copyright (c) 2021-2031, 河北计全科技有限公司 (https://www.jeequan.com & jeequan@126.com).
* <p>
* Licensed under the GNU LESSER GENERAL PUBLIC LICENSE 3.0;
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
* <p>
* http://www.gnu.org/licenses/lgpl.html
* <p>
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package com.jeequan.jeepay.pay.channel.wxpay.paywayV3;
import com.alibaba.fastjson.JSONObject;
import com.github.binarywang.wxpay.constant.WxPayConstants;
import com.github.binarywang.wxpay.exception.WxPayException;
import com.github.binarywang.wxpay.service.WxPayService;
import com.jeequan.jeepay.core.constants.CS;
import com.jeequan.jeepay.core.entity.PayOrder;
import com.jeequan.jeepay.pay.channel.wxpay.WxpayPaymentService;
import com.jeequan.jeepay.pay.channel.wxpay.kits.WxpayKit;
import com.jeequan.jeepay.pay.channel.wxpay.kits.WxpayV3Util;
import com.jeequan.jeepay.pay.model.MchConfigContext;
import com.jeequan.jeepay.pay.rqrs.AbstractRS;
import com.jeequan.jeepay.pay.rqrs.msg.ChannelRetMsg;
import com.jeequan.jeepay.pay.rqrs.payorder.UnifiedOrderRQ;
import com.jeequan.jeepay.pay.rqrs.payorder.payway.WxNativeOrderRQ;
import com.jeequan.jeepay.pay.rqrs.payorder.payway.WxNativeOrderRS;
import com.jeequan.jeepay.pay.util.ApiResBuilder;
import org.springframework.stereotype.Service;
/*
* 微信 native支付
*
* @author zhuxiao
* @site https://www.jeepay.vip
* @date 2021/6/8 18:08
*/
@Service("wxpayPaymentByNativeV3Service") //Service Name需保持全局唯一性
public class WxNative extends WxpayPaymentService {
@Override
public String preCheck(UnifiedOrderRQ rq, PayOrder payOrder) {
return null;
}
@Override
public AbstractRS pay(UnifiedOrderRQ rq, PayOrder payOrder, MchConfigContext mchConfigContext) {
WxNativeOrderRQ bizRQ = (WxNativeOrderRQ) rq;
WxPayService wxPayService = mchConfigContext.getWxServiceWrapper().getWxPayService();
// 构造请求数据
JSONObject reqJSON = buildV3OrderRequest(payOrder, mchConfigContext);
String reqUrl; // 请求地址
if(mchConfigContext.isIsvsubMch()){ // 特约商户
reqUrl = WxpayV3Util.ISV_URL_MAP.get(WxPayConstants.TradeType.NATIVE);
}else {
reqUrl = WxpayV3Util.NORMALMCH_URL_MAP.get(WxPayConstants.TradeType.NATIVE);
}
// 构造函数响应数据
WxNativeOrderRS res = ApiResBuilder.buildSuccess(WxNativeOrderRS.class);
ChannelRetMsg channelRetMsg = new ChannelRetMsg();
res.setChannelRetMsg(channelRetMsg);
// 调起上游接口:
// 1. 如果抛异常,则订单状态为: 生成状态,此时没有查单处理操作。 订单将超时关闭
// 2. 接口调用成功, 后续异常需进行捕捉, 如果 逻辑代码出现异常则需要走完正常流程,此时订单状态为: 支付中, 需要查单处理。
try {
JSONObject resJSON = WxpayV3Util.unifiedOrderV3(reqUrl, reqJSON, wxPayService.getConfig());
String codeUrl = resJSON.getString("code_url");
if (CS.PAY_DATA_TYPE.CODE_IMG_URL.equals(bizRQ.getPayDataType())){ //二维码图片地址
res.setCodeImgUrl(sysConfigService.getDBApplicationConfig().genScanImgUrl(codeUrl));
}else{
res.setCodeUrl(codeUrl);
}
// 支付中
channelRetMsg.setChannelState(ChannelRetMsg.ChannelState.WAITING);
} catch (WxPayException e) {
//明确失败
channelRetMsg.setChannelState(ChannelRetMsg.ChannelState.CONFIRM_FAIL);
WxpayKit.commonSetErrInfo(channelRetMsg, e);
}
return res;
}
}
/*
* Copyright (c) 2021-2031, 河北计全科技有限公司 (https://www.jeequan.com & jeequan@126.com).
* <p>
* Licensed under the GNU LESSER GENERAL PUBLIC LICENSE 3.0;
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
* <p>
* http://www.gnu.org/licenses/lgpl.html
* <p>
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package com.jeequan.jeepay.pay.channel.ysfpay;
import com.alibaba.fastjson.JSONObject;
import com.jeequan.jeepay.core.constants.CS;
import com.jeequan.jeepay.core.entity.PayOrder;
import com.jeequan.jeepay.core.exception.ResponseException;
import com.jeequan.jeepay.core.model.params.ysf.YsfpayIsvParams;
import com.jeequan.jeepay.pay.channel.AbstractChannelNoticeService;
import com.jeequan.jeepay.pay.channel.ysfpay.utils.YsfSignUtils;
import com.jeequan.jeepay.pay.rqrs.msg.ChannelRetMsg;
import com.jeequan.jeepay.pay.model.IsvConfigContext;
import com.jeequan.jeepay.pay.model.MchConfigContext;
import lombok.extern.slf4j.Slf4j;
import org.apache.commons.lang3.StringUtils;
import org.apache.commons.lang3.tuple.MutablePair;
import org.springframework.http.ResponseEntity;
import org.springframework.stereotype.Service;
import javax.servlet.http.HttpServletRequest;
/**
* 云闪付回调
*
* @author pangxiaoyu
* @site https://www.jeepay.vip
* @date 2021-06-07 07:15
*/
@Service
@Slf4j
public class YsfpayChannelNoticeService extends AbstractChannelNoticeService {
@Override
public String getIfCode() {
return CS.IF_CODE.YSFPAY;
}
@Override
public MutablePair<String, Object> parseParams(HttpServletRequest request, String urlOrderId, NoticeTypeEnum noticeTypeEnum) {
try {
JSONObject params = getReqParamJSON();
String payOrderId = params.getString("orderNo");
return MutablePair.of(payOrderId, params);
} catch (Exception e) {
log.error("error", e);
throw ResponseException.buildText("ERROR");
}
}
@Override
public ChannelRetMsg doNotice(HttpServletRequest request, Object params, PayOrder payOrder, MchConfigContext mchConfigContext, NoticeTypeEnum noticeTypeEnum) {
try {
ChannelRetMsg result = ChannelRetMsg.confirmSuccess(null);
String logPrefix = "【处理云闪付支付回调】";
// 获取请求参数
JSONObject jsonParams = (JSONObject) params;
log.info("{} 回调参数, jsonParams:{}", logPrefix, jsonParams);
// 校验支付回调
boolean verifyResult = verifyParams(jsonParams, payOrder, mchConfigContext.getIsvConfigContext());
// 验证参数失败
if(!verifyResult){
throw ResponseException.buildText("ERROR");
}
log.info("{}验证支付通知数据及签名通过", logPrefix);
//验签成功后判断上游订单状态
ResponseEntity okResponse = textResp("success");
result.setResponseEntity(okResponse);
result.setChannelOrderId(jsonParams.getString("transIndex"));
return result;
} catch (Exception e) {
log.error("error", e);
throw ResponseException.buildText("ERROR");
}
}
/**
* 验证云闪付支付通知参数
* @return
*/
public boolean verifyParams(JSONObject jsonParams, PayOrder payOrder, IsvConfigContext isvConfigContext) {
String orderNo = jsonParams.getString("orderNo"); // 商户订单号
String txnAmt = jsonParams.getString("txnAmt"); // 支付金额
if (StringUtils.isEmpty(orderNo)) {
log.info("订单ID为空 [orderNo]={}", orderNo);
return false;
}
if (StringUtils.isEmpty(txnAmt)) {
log.info("金额参数为空 [txnAmt] :{}", txnAmt);
return false;
}
YsfpayIsvParams isvParams = isvConfigContext.getIsvParamsByIfCode(getIfCode(), YsfpayIsvParams.class);
//验签
String ysfpayPublicKey = isvParams.getYsfpayPublicKey();
//验签失败
if(!YsfSignUtils.validate((JSONObject) JSONObject.toJSON(jsonParams), ysfpayPublicKey)) {
log.info("【云闪付回调】 验签失败! 回调参数:parameter = {}, ysfpayPublicKey={} ", jsonParams, ysfpayPublicKey);
return false;
}
// 核对金额
long dbPayAmt = payOrder.getAmount().longValue();
if (dbPayAmt != Long.parseLong(txnAmt)) {
log.info("订单金额与参数金额不符。 dbPayAmt={}, txnAmt={}, payOrderId={}", dbPayAmt, txnAmt, orderNo);
return false;
}
return true;
}
}
/*
* Copyright (c) 2021-2031, 河北计全科技有限公司 (https://www.jeequan.com & jeequan@126.com).
* <p>
* Licensed under the GNU LESSER GENERAL PUBLIC LICENSE 3.0;
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
* <p>
* http://www.gnu.org/licenses/lgpl.html
* <p>
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package com.jeequan.jeepay.pay.channel.ysfpay;
import com.alibaba.fastjson.JSONObject;
import com.jeequan.jeepay.core.constants.CS;
import com.jeequan.jeepay.core.entity.PayOrder;
import com.jeequan.jeepay.pay.channel.IPayOrderQueryService;
import com.jeequan.jeepay.pay.channel.ysfpay.utils.YsfHttpUtil;
import com.jeequan.jeepay.pay.rqrs.msg.ChannelRetMsg;
import com.jeequan.jeepay.pay.model.MchConfigContext;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
/**
* 云闪付查单
*
* @author pangxiaoyu
* @site https://www.jeepay.vip
* @date 2021-06-07 07:15
*/
@Service
@Slf4j
public class YsfpayPayOrderQueryService implements IPayOrderQueryService {
@Override
public String getIfCode() {
return CS.IF_CODE.YSFPAY;
}
@Autowired
private YsfpayPaymentService ysfpayPaymentService;
@Override
public ChannelRetMsg query(PayOrder payOrder, MchConfigContext mchConfigContext) throws Exception {
JSONObject reqParams = new JSONObject();
String orderType = YsfHttpUtil.getOrderTypeByCommon(payOrder.getWayCode());
String logPrefix = "【云闪付("+orderType+")查单】";
try {
reqParams.put("orderNo", payOrder.getPayOrderId()); //订单号
reqParams.put("orderType", orderType); //订单类型
//封装公共参数 & 签名 & 调起http请求 & 返回响应数据并包装为json格式。
JSONObject resJSON = ysfpayPaymentService.packageParamAndReq("/gateway/api/pay/queryOrder", reqParams, logPrefix, mchConfigContext.getIsvConfigContext(), mchConfigContext);
log.info("查询订单 payorderId:{}, 返回结果:{}", payOrder.getPayOrderId(), resJSON);
if(resJSON == null){
return ChannelRetMsg.waiting(); //支付中
}
//请求 & 响应成功, 判断业务逻辑
String respCode = resJSON.getString("respCode"); //应答码
String origRespCode = resJSON.getString("origRespCode"); //原交易应答码
String respMsg = resJSON.getString("respMsg"); //应答信息
if(("00").equals(respCode)){//如果查询交易成功
//00- 支付成功 01- 转入退款 02- 未支付 03- 已关闭 04- 已撤销(付款码支付) 05- 用户支付中 06- 支付失败
if(("00").equals(origRespCode)){
//交易成功,更新商户订单状态
return ChannelRetMsg.confirmSuccess(resJSON.getString("transIndex")); //支付成功
}else if( "02".equals(origRespCode) || "05".equals(origRespCode) ) {
return ChannelRetMsg.waiting(); //支付中
}
}
return ChannelRetMsg.waiting(); //支付中
}catch (Exception e) {
return ChannelRetMsg.waiting(); //支付中
}
}
}
/*
* Copyright (c) 2021-2031, 河北计全科技有限公司 (https://www.jeequan.com & jeequan@126.com).
* <p>
* Licensed under the GNU LESSER GENERAL PUBLIC LICENSE 3.0;
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
* <p>
* http://www.gnu.org/licenses/lgpl.html
* <p>
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package com.jeequan.jeepay.pay.channel.ysfpay;
import cn.hutool.core.date.DatePattern;
import cn.hutool.core.date.DateUtil;
import com.alibaba.fastjson.JSONObject;
import com.jeequan.jeepay.core.constants.CS;
import com.jeequan.jeepay.core.entity.PayOrder;
import com.jeequan.jeepay.core.exception.BizException;
import com.jeequan.jeepay.core.model.params.ysf.YsfpayConfig;
import com.jeequan.jeepay.core.model.params.ysf.YsfpayIsvParams;
import com.jeequan.jeepay.core.model.params.ysf.YsfpayIsvsubMchParams;
import com.jeequan.jeepay.pay.channel.AbstractPaymentService;
import com.jeequan.jeepay.pay.channel.ysfpay.utils.YsfHttpUtil;
import com.jeequan.jeepay.pay.channel.ysfpay.utils.YsfSignUtils;
import com.jeequan.jeepay.pay.config.SystemYmlConfig;
import com.jeequan.jeepay.pay.model.IsvConfigContext;
import com.jeequan.jeepay.pay.model.MchConfigContext;
import com.jeequan.jeepay.pay.rqrs.AbstractRS;
import com.jeequan.jeepay.pay.rqrs.payorder.UnifiedOrderRQ;
import com.jeequan.jeepay.pay.util.PaywayUtil;
import lombok.extern.slf4j.Slf4j;
import org.apache.commons.lang3.StringUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import java.io.File;
import java.util.Date;
/**
* 云闪付下单
*
* @author pangxiaoyu
* @site https://www.jeepay.vip
* @date 2021-06-07 07:15
*/
@Service
@Slf4j
public class YsfpayPaymentService extends AbstractPaymentService {
@Autowired private SystemYmlConfig mainConfig;
@Override
public String getIfCode() {
return CS.IF_CODE.YSFPAY;
}
@Override
public boolean isSupport(String wayCode) {
return true;
}
@Override
public String preCheck(UnifiedOrderRQ rq, PayOrder payOrder) {
return PaywayUtil.getRealPaywayService(this, payOrder.getWayCode()).preCheck(rq, payOrder);
}
@Override
public AbstractRS pay(UnifiedOrderRQ rq, PayOrder payOrder, MchConfigContext mchConfigContext) throws Exception {
return PaywayUtil.getRealPaywayService(this, payOrder.getWayCode()).pay(rq, payOrder, mchConfigContext);
}
/** 封装参数 & 统一请求 **/
public JSONObject packageParamAndReq(String apiUri, JSONObject reqParams, String logPrefix, IsvConfigContext isvConfigContext, MchConfigContext mchConfigContext) throws Exception {
YsfpayIsvParams isvParams = isvConfigContext.getIsvParamsByIfCode(getIfCode(), YsfpayIsvParams.class);
if (isvParams.getSerProvId() == null) {
log.error("服务商配置为空:isvParams:{}", isvParams);
throw new BizException("服务商配置为空。");
}
reqParams.put("serProvId", isvParams.getSerProvId()); //云闪付服务商标识
YsfpayIsvsubMchParams isvsubMchParams = mchConfigContext.getIsvsubMchParamsByIfCode(getIfCode(), YsfpayIsvsubMchParams.class);
reqParams.put("merId", isvsubMchParams.getMerId()); // 商户号
//签名
String isvPrivateCertFile = channelCertConfigKitBean.getCertFilePath(isvParams.getIsvPrivateCertFile());
String isvPrivateCertPwd = isvParams.getIsvPrivateCertPwd();
reqParams.put("signature", YsfSignUtils.signBy256(reqParams, isvPrivateCertFile, isvPrivateCertPwd)); //RSA 签名串
// 调起上游接口
log.info("{} reqJSON={}", logPrefix, reqParams);
String resText = YsfHttpUtil.doPostJson(getYsfpayHost4env(isvParams) + apiUri, null, reqParams);
log.info("{} resJSON={}", logPrefix, resText);
if(StringUtils.isEmpty(resText)){
return null;
}
return JSONObject.parseObject(resText);
}
/** 获取云闪付正式环境/沙箱HOST地址 **/
public static String getYsfpayHost4env(YsfpayIsvParams isvParams){
return CS.YES == isvParams.getSandbox() ? YsfpayConfig.SANDBOX_SERVER_URL : YsfpayConfig.PROD_SERVER_URL;
}
/** 云闪付 jsapi下单请求统一发送参数 **/
public static void jsapiParamsSet(JSONObject reqParams, PayOrder payOrder, String notifyUrl, String returnUrl) {
String orderType = YsfHttpUtil.getOrderTypeByJSapi(payOrder.getWayCode());
reqParams.put("orderType", orderType); //订单类型: alipayJs-支付宝, wechatJs-微信支付, upJs-银联二维码
ysfPublicParams(reqParams, payOrder);
reqParams.put("backUrl", notifyUrl); //交易通知地址
reqParams.put("frontUrl", returnUrl); //前台通知地址
}
/** 云闪付 bar下单请求统一发送参数 **/
public static void barParamsSet(JSONObject reqParams, PayOrder payOrder) {
String orderType = YsfHttpUtil.getOrderTypeByBar(payOrder.getWayCode());
reqParams.put("orderType", orderType); //订单类型: alipay-支付宝, wechat-微信支付, -unionpay银联二维码
ysfPublicParams(reqParams, payOrder);
// TODO 终端编号暂时写死
reqParams.put("termId", "01727367"); // 终端编号
}
/** 云闪付公共参数赋值 **/
public static void ysfPublicParams(JSONObject reqParams, PayOrder payOrder) {
//获取订单类型
reqParams.put("orderNo", payOrder.getPayOrderId()); //订单号
reqParams.put("orderTime", DateUtil.format(new Date(), DatePattern.PURE_DATETIME_PATTERN)); //订单时间 如:20180702142900
reqParams.put("txnAmt", payOrder.getAmount()); //交易金额 单位:分,不带小数点
reqParams.put("currencyCode", "156"); //交易币种 不出现则默认为人民币-156
reqParams.put("orderInfo", payOrder.getSubject()); //订单信息 订单描述信息,如:京东生鲜食品
}
}
/*
* Copyright (c) 2021-2031, 河北计全科技有限公司 (https://www.jeequan.com & jeequan@126.com).
* <p>
* Licensed under the GNU LESSER GENERAL PUBLIC LICENSE 3.0;
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
* <p>
* http://www.gnu.org/licenses/lgpl.html
* <p>
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package com.jeequan.jeepay.pay.channel.ysfpay.payway;
import com.alibaba.fastjson.JSONObject;
import com.jeequan.jeepay.core.entity.PayOrder;
import com.jeequan.jeepay.core.exception.BizException;
import com.jeequan.jeepay.pay.channel.ysfpay.YsfpayPaymentService;
import com.jeequan.jeepay.pay.rqrs.AbstractRS;
import com.jeequan.jeepay.pay.rqrs.payorder.payway.AliBarOrderRQ;
import com.jeequan.jeepay.pay.rqrs.payorder.payway.AliBarOrderRS;
import com.jeequan.jeepay.pay.rqrs.payorder.UnifiedOrderRQ;
import com.jeequan.jeepay.pay.rqrs.msg.ChannelRetMsg;
import com.jeequan.jeepay.pay.util.ApiResBuilder;
import com.jeequan.jeepay.pay.model.MchConfigContext;
import org.apache.commons.lang3.StringUtils;
import org.springframework.stereotype.Service;
/*
* 云闪付 支付宝 条码支付
*
* @author pangxiaoyu
* @site https://www.jeepay.vip
* @date 2021/6/8 18:11
*/
@Service("ysfPaymentByAliBarService") //Service Name需保持全局唯一性
public class AliBar extends YsfpayPaymentService {
@Override
public String preCheck(UnifiedOrderRQ rq, PayOrder payOrder) {
AliBarOrderRQ bizRQ = (AliBarOrderRQ) rq;
if(StringUtils.isEmpty(bizRQ.getAuthCode())){
throw new BizException("用户支付条码[authCode]不可为空");
}
return null;
}
@Override
public AbstractRS pay(UnifiedOrderRQ rq, PayOrder payOrder, MchConfigContext mchConfigContext) throws Exception {
String logPrefix = "【云闪付条码(alipay)支付】";
AliBarOrderRQ bizRQ = (AliBarOrderRQ) rq;
AliBarOrderRS res = ApiResBuilder.buildSuccess(AliBarOrderRS.class);
ChannelRetMsg channelRetMsg = new ChannelRetMsg();
res.setChannelRetMsg(channelRetMsg);
JSONObject reqParams = new JSONObject();
reqParams.put("authCode", bizRQ.getAuthCode()); //付款码: 用户 APP 展示的付款条码或二维码
// 云闪付 bar 统一参数赋值
barParamsSet(reqParams, payOrder);
//客户端IP
reqParams.put("termInfo", "{\"ip\": \""+StringUtils.defaultIfEmpty(payOrder.getClientIp(), "127.0.0.1")+"\"}"); //终端信息
// 发送请求
JSONObject resJSON = packageParamAndReq("/gateway/api/pay/micropay", reqParams, logPrefix, mchConfigContext.getIsvConfigContext(), mchConfigContext);
//请求 & 响应成功, 判断业务逻辑
String respCode = resJSON.getString("respCode"); //应答码
String respMsg = resJSON.getString("respMsg"); //应答信息
try {
//00-交易成功, 02-用户支付中 , 12-交易重复, 需要发起查询处理 其他认为失败
if("00".equals(respCode)){
channelRetMsg.setChannelState(ChannelRetMsg.ChannelState.CONFIRM_SUCCESS);
res.setPayData(resJSON.getString("payData"));
}else if("02".equals(respCode) ||"12".equals(respCode) || "99".equals(respCode)){
channelRetMsg.setChannelState(ChannelRetMsg.ChannelState.WAITING);
channelRetMsg.setNeedQuery(true); // 开启轮询查单
}else{
channelRetMsg.setChannelState(ChannelRetMsg.ChannelState.CONFIRM_FAIL);
channelRetMsg.setChannelErrCode(respCode);
channelRetMsg.setChannelErrMsg(respMsg);
}
}catch (Exception e) {
channelRetMsg.setChannelErrCode(respCode);
channelRetMsg.setChannelErrMsg(respMsg);
}
return res;
}
}
Supports Markdown
0% or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment