赞
踩
设计模式:单例+策略模式+抽象
在开发中经常对接微信支付和支付宝支付,相对来说,阿里的文档比微信的接口文档清晰一点,这里用的第三方库(com.github.binarywang)整合两个支付
开箱即用。
微信支付分开放平台和公众号,具体的请自行参考文裆自行配置. https://pay.weixin.qq.com/wiki/doc/api/jsapi.php?chapter=23_9&index=1
支付宝文档地址 https://opendocs.alipay.com/apis/api_1/alipay.trade.pay
微信支付大致可以分为 :
- 原生扫码支付(NATIVE) 扫码
- App支付(APP)
- 公众号支付/小程序支付.(JSAPI) 注意下单是需要带openid (所申请的公众号绑定的openid)
- H5支付(MWEB) l
- (刷卡支付)MICROPAY
支付宝:
- pc
- app
- h5
阿里
<aliyun-java-sdk.version>4.5.20</aliyun-java-sdk.version>
<weixin-java-pay.version>4.0.0</weixin-java-pay.version>
<ali-java-pay.version>4.13.0.ALL</ali-java-pay.version>
<dependency>
<groupId>com.aliyun</groupId>
<artifactId>aliyun-java-sdk-core</artifactId>
<version>${aliyun-java-sdk.version}</version>
</dependency>
<dependency>
<groupId>com.alipay.sdk</groupId>
<artifactId>alipay-sdk-java</artifactId>
<version>${ali-java-pay.version}</version>
</dependency>
微信
<dependency>
<groupId>com.github.binarywang</groupId>
<artifactId>weixin-java-pay</artifactId>
<version>${weixin-java-pay.version}</version>
</dependency>
支付抽象类
package com.ac.flaget.pay.abstracts; import com.ac.flaget.common.bean.ReturnValue; import com.ac.flaget.pay.request.PayRequest; import com.ac.flaget.pay.request.RefundRequest; import com.ac.flaget.pay.response.PayResponse; import com.ac.flaget.pay.response.RefundResponse; import com.github.binarywang.wxpay.exception.WxPayException; /** * @author: crayWen * @date: 2021-05-17 16:02 * @desc: 支付抽象类 */ public interface AbstractPay<PayReq extends PayRequest,RefundReq extends RefundRequest> { /** * 预支付(包含验签) * @param request 请求参数 * @return PayResponse 返回的信息 */ ReturnValue<PayResponse> pay(PayReq request) throws WxPayException; /** * 支付结果主动查询 */ ReturnValue<PayResponse> payQuery(PayReq request); /** * 支付取消 */ ReturnValue<PayResponse> payCancel(PayReq request); /** * 退款 */ ReturnValue<RefundResponse> refund(RefundReq request); /** * 退款结果主动查询 */ ReturnValue<RefundResponse> refundQuery(RefundReq request); /** * 验证签名 */ Boolean verifySign(String jsonObject, Integer verifyType); }
支付配置,单例
package com.ac.flaget.pay.config; import com.ac.flaget.pay.sdk.FlagPayClient; import com.ac.flaget.pay.sdk.alipay.api.AliPayApi; import com.ac.flaget.pay.sdk.alipay.config.impl.AliPayAppConfig; import com.ac.flaget.pay.sdk.alipay.config.impl.AliPayH5Config; import com.ac.flaget.pay.sdk.fgpay.api.WalletApi; import com.ac.flaget.pay.sdk.wxpay.api.WxPayApi; import com.ac.flaget.pay.sdk.wxpay.config.impl.WxPayAppConfig; import com.ac.flaget.pay.sdk.wxpay.config.impl.WxPayH5Config; import com.ac.flaget.user.web.handler.WalletHandler; import lombok.AllArgsConstructor; import org.springframework.boot.autoconfigure.condition.ConditionalOnClass; import org.springframework.boot.autoconfigure.condition.ConditionalOnMissingBean; import org.springframework.context.annotation.Bean; import org.springframework.context.annotation.Configuration; /** * @author: cray wen * @date: 2021-06-18 11:09 * @desc: 支付配置类 */ @Configuration @AllArgsConstructor @ConditionalOnClass({WxPayH5Config.class,WxPayAppConfig.class,AliPayH5Config.class,AliPayAppConfig.class}) public class PayConfiguration { /** * 等同于注解 @Resource 前提加 @AllArgsConstructor */ private final WxPayH5Config wxPayH5Config; private final WxPayAppConfig wxPayAppConfig; private final AliPayH5Config aliPayH5Config; private final AliPayAppConfig aliPayAppConfig; private final WalletHandler walletHandler; @Bean public WxPayApi wxPayAppApi() { return new WxPayApi(wxPayAppConfig); } @Bean public WxPayApi wxPayH5Api() { return new WxPayApi(wxPayH5Config); } @Bean public AliPayApi aliPayAppApi() { return new AliPayApi(aliPayAppConfig); } @Bean public AliPayApi aliPayH5Api() { return new AliPayApi(aliPayH5Config); } @Bean(name = "apiWalletHandler") public WalletApi walletApi(){ return new WalletApi(walletHandler); } /** * 只存在一个实例,并在启动时就初始化了 */ @Bean @ConditionalOnMissingBean public FlagPayClient flagPayClient(){ return new FlagPayClient(wxPayAppApi(),wxPayH5Api(),aliPayAppApi(),aliPayH5Api(),walletApi()); } }
支付策略切换类
支付配置 分为APP 和 H5配置,具体参考文档
package com.ac.flaget.pay.sdk; import com.ac.flaget.pay.abstracts.AbstractPay; import com.ac.flaget.pay.enums.PayChannelEnum; import com.ac.flaget.pay.request.PayRequest; import com.ac.flaget.pay.request.RefundRequest; import com.ac.flaget.pay.sdk.alipay.api.AliPayApi; import com.ac.flaget.pay.sdk.fgpay.api.WalletApi; import com.ac.flaget.pay.sdk.wxpay.api.WxPayApi; import lombok.extern.slf4j.Slf4j; import java.util.Objects; /** * @author: cray wen * @date: 2021-05-27 11:14 * @desc: 支付切换类 */ @Slf4j public class FlagPayClient { /** *切换api */ private final WxPayApi wxAppPayApi; private final WxPayApi wxH5PayApi; private final AliPayApi aliAppPayApi; private final AliPayApi aliH5PayApi; private final WalletApi walletApi; public FlagPayClient( WxPayApi wxAppPayApi, WxPayApi wxH5PayApi , AliPayApi aliAppPayApi, AliPayApi aliPayH5Api, WalletApi walletApi){ this.wxAppPayApi = wxAppPayApi; this. wxH5PayApi = wxH5PayApi; this.aliAppPayApi = aliAppPayApi; this.aliH5PayApi = aliPayH5Api; this.walletApi =walletApi; } /** * * @param payStyle 支付类型 * @param configType APP(公众开放平台) */ public AbstractPay<PayRequest, RefundRequest> getPayApi(Integer payStyle,Integer configType){ if(Objects.isNull(payStyle)){ log.info("支付类型为空:{}",payStyle); return null; } if(PayChannelEnum.PayTypeEnum.ALIPAY.getCode().intValue() == payStyle && PayChannelEnum.PayConfigTypeEnum.APP.getCode().intValue() == configType) { return aliAppPayApi; } if(PayChannelEnum.PayTypeEnum.ALIPAY.getCode().intValue() == payStyle && PayChannelEnum.PayConfigTypeEnum.H5.getCode().intValue() == configType) { return aliH5PayApi; } if(PayChannelEnum.PayTypeEnum.WEIPAY.getCode().intValue() == payStyle && PayChannelEnum.PayConfigTypeEnum.APP.getCode().intValue() == configType) { return wxAppPayApi; } if(PayChannelEnum.PayTypeEnum.WEIPAY.getCode().intValue() == payStyle && PayChannelEnum.PayConfigTypeEnum.H5.getCode().intValue() == configType) { return wxH5PayApi; } if(PayChannelEnum.PayTypeEnum.WALLET.getCode().intValue()==payStyle){ return walletApi; } return null; } }
支付宝配置接口类
package com.ac.flaget.pay.sdk.alipay.config; /** * @author: cray wen * @date: 2021-05-27 11:26 * @desc: 支付宝 配置 */ public interface AliCustomConfig { /** * 支付宝支付根地址 */ public String getAliPayUrl(); /** * 支付宝加密算法私钥 */ public String getAliPayPrivateKey(); /** * 支付宝加密算法公钥 */ public String getAliPayPublicKey(); /** * 支付宝APPID */ public String getAliPayAppid(); /** * 支付宝支付回调通知URL */ public String getAliPayPayNotifyUrl(); /** * 支付宝支付前端页面回跳页面url */ public String getAliPayReturnPageUrl(); public Boolean getAliUseSandboxEnv(); public String getSignType(); public String getCharset(); }
配置实现就不贴了, AliPayH5Config ; AliPayAppConfig ;
有app 和h5 自行实现spring bean 注入或者是 xxl job实现等
微信配置接口类
package com.ac.flaget.pay.sdk.wxpay.config; /** * @author: cray wen * @date: 2021-05-27 11:39 * @desc: */ public interface WxCustomConfig { /** * 设置微信公众号或者小程序等的appid */ public String getWexinAppId(); /** * 微信支付商户号 */ public String getWexinMchId(); /** * 微信支付商户密钥 */ public String getWexinMchKey(); /** * 服务商模式下的子商户公众账号ID,普通模式请不要配置,请在配置文件中将对应项删除 */ public String getWexinSubAppId(); /** * 服务商模式下的子商户号,普通模式请不要配置,最好是请在配置文件中将对应项删除 */ public String getWexinSubMchId(); /** * apiclient_cert.p12文件的绝对路径,或者如果放在项目中,请以classpath:开头指定 */ public String getWexinKeyPath(); /** * 异步通知url */ public String getWexinNotifyUrl(); /** * 退款通知url */ public String getWexinRefundNotifyUrl(); /** * 是否使用沙箱环境 */ public Boolean getWexinUseSandboxEnv(); public String getSignType(); public String getCharset(); }
与支付宝类似,有app 和h5支付的实现类
WxPayH5Config WxPayAppConfig;
配置实现类其中一个
package com.ac.flaget.pay.sdk.wxpay.config.impl; import com.ac.flaget.pay.sdk.wxpay.config.WxCustomConfig; import org.springframework.beans.factory.annotation.Value; import org.springframework.stereotype.Service; /** * @author: craywen * @date: 2021-06-08 11:36 * @desc: */ @Service public class WxPayAppConfig implements WxCustomConfig { @Value("${pay.config.wx.app.appId}") private String wexinAppId; @Value("${pay.config.wx.app.mchId}") private String wxinMchId; @Value("${pay.config.wx.app.mchKey}") private String wexinMchKey; @Value("${pay.config.wx.app.keyPath}") private String wexinKeyPath; @Value("${pay.config.wx.app.notifyUrl}") private String wexinNotifyUrl; @Value("${pay.config.wx.app.useSandboxEnv}") private Boolean wexinUseSandboxEnv; @Override public String getSignType() { return "MD5"; } @Override public String getCharset() { return "UTF-8"; }
@Slf4j
public class AliPayApi implements AbstractPay<PayRequest, RefundRequest> {
private AliCustomConfig aliCustomConfig;
private AlipayClient alipayClient;
public AliPayApi(AliCustomConfig aliCustomConfig) {
this.aliCustomConfig = aliCustomConfig;
alipayClient = new DefaultAlipayClient(aliCustomConfig.getAliPayUrl(), aliCustomConfig.getAliPayAppid(), aliCustomConfig.getAliPayPrivateKey(), AlipayConstants.FORMAT_JSON, AlipayConstants.CHARSET_UTF8, aliCustomConfig.getAliPayPublicKey(), AlipayConstants.SIGN_TYPE_RSA2);
}
pay 方法(预支付下单)
@Override public ReturnValue<PayResponse> pay(PayRequest payRequest) { long timeMillis = System.currentTimeMillis(); try { if (PayTradeTypeEnum.H5_PAY_TRADE_TYPE.getCode().intValue() != payRequest.getTradeType() && PayTradeTypeEnum.PC_PAY_TRADE_TYPE.getCode().intValue() != payRequest.getTradeType() && PayTradeTypeEnum.APP_PAY_TRADE_TYPE.getCode().intValue() != payRequest.getTradeType()) { return ReturnValue.ofFailed(PayErrorCodeEnum.PAY_ERROR_CODE_2310006.getCode(), PayErrorCodeEnum.PAY_ERROR_CODE_2310006.getDesc()); } AlipayRequest<?> alipayRequest = null; AlipayResponse alipayResponse = null; //网页返回网页 if (PayTradeTypeEnum.H5_PAY_TRADE_TYPE.getCode().intValue() == payRequest.getTradeType()) { alipayRequest = new AlipayTradeWapPayRequest(); ((AlipayTradeWapPayRequest) alipayRequest).setBizContent("" + "{\"out_trade_no\":\"" + payRequest.getRequestOrderSn() + "\"," + "\"total_amount\":\"" + payRequest.getPayAmount() + "\"," + "\"subject\":\"" + payRequest.getBody() + "\"," + "\"body\":\"" + payRequest.getBody() + "\"," + "\"product_code\":\"QUICK_WAP_WAY\"}"); } //pc if (PayTradeTypeEnum.PC_PAY_TRADE_TYPE.getCode().intValue() == payRequest.getTradeType()) { alipayRequest = new AlipayTradePagePayRequest(); ((AlipayTradePagePayRequest) alipayRequest).setBizContent("{" + "\"out_trade_no\":\"" + payRequest.getRequestOrderSn() + "\"," + "\"total_amount\":\"" + payRequest.getPayAmount() + "\"," + "\"subject\":\"" + payRequest.getBody() + "\"," + "\"body\":\"" + payRequest.getBody() + "\"," + "\"passback_params\":\"" + payRequest.getTradeType() + "\"," + "\"product_code\":\"FAST_INSTANT_TRADE_PAY\"}"); } //唤起App(aa) if (PayTradeTypeEnum.APP_PAY_TRADE_TYPE.getCode().intValue() == payRequest.getTradeType()) { alipayRequest = new AlipayTradeAppPayRequest(); ((AlipayTradeAppPayRequest) alipayRequest).setBizContent("{" + "\"out_trade_no\":\"" + payRequest.getRequestOrderSn() + "\"," + "\"total_amount\":\"" + payRequest.getPayAmount() + "\"," + "\"subject\":\"" + payRequest.getBody() + "\"," + "\"body\":\"" + payRequest.getBody() + "\"," + "\"product_code\":\"QUICK_MSECURITY_PAY\"}"); } // alipayRequest.setReturnUrl(aliCustomConfig.getAliPayReturnPageUrl()); alipayRequest.setReturnUrl(payRequest.getReturnUrl()); alipayRequest.setNotifyUrl(aliCustomConfig.getAliPayPayNotifyUrl()); if (alipayRequest instanceof AlipayTradeAppPayRequest) { alipayResponse = alipayClient.sdkExecute(alipayRequest); } else if (alipayRequest instanceof AlipayTradePayRequest) { alipayResponse = alipayClient.execute(alipayRequest); } else { // page 必传get 方式 ,默认post 会使验签方式错误, // if ("GET".equalsIgnoreCase(httpMethod)) { // rsp.setBody(this.getRedirectUrl(requestHolder)); // } else { // String baseUrl = this.getRequestUrl(requestHolder); // rsp.setBody(WebUtils.buildForm(baseUrl, requestHolder.getApplicationParams())); // } alipayResponse = alipayClient.pageExecute(alipayRequest,RequestMethod.GET.name() ); } log.info("LOG-IN-ALIPAY,支付SDK结果详情 pay request:{} \n,response:{}", JSONUtils.toString(alipayRequest), JSONUtils.toString(alipayResponse)); if (Objects.nonNull(alipayResponse) && alipayResponse.isSuccess()) { PayResponse response = new PayResponse(); response.setCaskDeskUrl(alipayResponse.getBody()); response.setCreatePayTime(timeMillis); response.setTimeoutPayTime(DateUtils.nextMinute(response.getCreatePayTime(), 15)); response.setRequestOrderSn(payRequest.getRequestOrderSn()); response.setThirdRemark(""); response.setThirdTradeNo(""); //, URLEncoder.encode(dynStr, StandardCharsets.UTF_8.toString())).build(true) response.setSign(alipayResponse.getBody()); response.setPayStatus(PayStatusEnum.PayOrderStatusEnum.PAYING_STATUS_PAY.getCode()); return ReturnValue.ofSuccessful(response); } String errMessageStr = Objects.isNull(alipayResponse) ? "" : alipayResponse.getMsg() + "_" + alipayResponse.getSubMsg(); return ReturnValue.ofFailed(PayErrorCodeEnum.PAY_ERROR_CODE_2310001.getCode(), PayErrorCodeEnum.PAY_ERROR_CODE_2310001.getDesc() + "[" + errMessageStr + "]"); } catch (Exception e) { log.error("ERROR-IN-AliPayApi-pay", e); } return ReturnValue.ofFailed(PayErrorCodeEnum.PAY_ERROR_CODE_2310001.getCode(), PayErrorCodeEnum.PAY_ERROR_CODE_2310001.getDesc()); }
支付主动查询结果(异步回调请见文章二)
@Override public ReturnValue<PayResponse> payQuery(PayRequest payRequest) { try { AlipayTradeQueryRequest request = new AlipayTradeQueryRequest(); request.setBizContent("{\"out_trade_no\":\"" + payRequest.getRequestOrderSn() + "\"" + "}"); AlipayTradeQueryResponse alipayTradeQueryResponse = alipayClient.execute(request); log.info("LOG-IN-ALIPAY,支付SDK查询支付结果详情 pay request:{},response:{}", JSONUtils.toString(alipayTradeQueryResponse), JSONUtils.toString(alipayTradeQueryResponse)); if (Objects.nonNull(alipayTradeQueryResponse) && alipayTradeQueryResponse.isSuccess()) { PayResponse response = new PayResponse(); response.setPayStatus(ConvertStatusUtil.getConvertAliPayStatus(alipayTradeQueryResponse.getTradeStatus())); response.setPaySuccessTime(System.currentTimeMillis()); response.setThirdTradeNo(alipayTradeQueryResponse.getTradeNo()); response.setTotalAmount(new BigDecimal(alipayTradeQueryResponse.getTotalAmount())); return ReturnValue.ofSuccessful(response); } String errMessageStr = Objects.isNull(alipayTradeQueryResponse) ? "" : alipayTradeQueryResponse.getMsg() + "_" + alipayTradeQueryResponse.getSubMsg(); return ReturnValue.ofFailed(PayErrorCodeEnum.PAY_ERROR_CODE_2310003.getCode(), PayErrorCodeEnum.PAY_ERROR_CODE_2310003.getDesc() + "[" + errMessageStr + "]"); } catch (Exception e) { log.error("ERROR-IN-AliPayApi-payQuery", e); } return ReturnValue.ofFailed(PayErrorCodeEnum.PAY_ERROR_CODE_2310003.getCode(), PayErrorCodeEnum.PAY_ERROR_CODE_2310003.getDesc()); }
微信支付
继承 WxPayServiceApacheHttpImpl,的方法和属性
@Slf4j public class WxPayApi extends WxPayServiceApacheHttpImpl implements AbstractPay<PayRequest, RefundRequest> { private Logger logger = LoggerFactory.getLogger(WxPayApi.class); //配置信息 private WxCustomConfig wxCustomConfig; public WxPayApi(WxCustomConfig wxCustomConfig) { this.wxCustomConfig = wxCustomConfig; WxPayConfig payConfig = new WxPayConfig(); payConfig.setAppId(StringUtils.trimToNull(wxCustomConfig.getWexinAppId())); payConfig.setMchId(StringUtils.trimToNull(wxCustomConfig.getWexinMchId())); payConfig.setMchKey(StringUtils.trimToNull(wxCustomConfig.getWexinMchKey())); payConfig.setSubAppId(StringUtils.trimToNull(wxCustomConfig.getWexinSubAppId())); payConfig.setSubMchId(StringUtils.trimToNull(wxCustomConfig.getWexinSubMchId())); payConfig.setKeyPath(StringUtils.trimToNull(wxCustomConfig.getWexinKeyPath())); // 可以指定是否使用沙箱环境 payConfig.setUseSandboxEnv(wxCustomConfig.getWexinUseSandboxEnv()); this.setConfig(payConfig); }
预支付
@Override public ReturnValue<PayResponse> pay(PayRequest request) throws WxPayException { long currentTimeMillis = System.currentTimeMillis(); if (PayTradeTypeEnum.H5_PAY_TRADE_TYPE.getCode().intValue() != request.getTradeType() && PayTradeTypeEnum.PC_PAY_TRADE_TYPE.getCode().intValue() != request.getTradeType() && PayTradeTypeEnum.APP_PAY_TRADE_TYPE.getCode().intValue() != request.getTradeType() && PayTradeTypeEnum.WXGZH_PAY_TRADE_TYPE.getCode().intValue() != request.getTradeType() && PayTradeTypeEnum.WXMINIPROGRAM_PAY_TRADE_TYPE.getCode().intValue() != request.getTradeType()) { throw new BusinessException(PayErrorCodeEnum.PAY_ERROR_CODE_2310001.getCode(), PayErrorCodeEnum.PAY_ERROR_CODE_2310001.getDesc()); } String tradeTypeStr = ""; // //PC 扫码 if (PayTradeTypeEnum.PC_PAY_TRADE_TYPE.getCode().intValue() == request.getTradeType()) { tradeTypeStr = WxPayConstants.TradeType.NATIVE; //APP } else if (PayTradeTypeEnum.APP_PAY_TRADE_TYPE.getCode().intValue() == request.getTradeType()) { tradeTypeStr = WxPayConstants.TradeType.APP; //JSAPI 需要带公众号绑定的openid much_id } else if (PayTradeTypeEnum.WXGZH_PAY_TRADE_TYPE.getCode().intValue() == request.getTradeType() || PayTradeTypeEnum.WXMINIPROGRAM_PAY_TRADE_TYPE.getCode().intValue() == request.getTradeType()) { tradeTypeStr = WxPayConstants.TradeType.JSAPI; // H5 } else { tradeTypeStr = WxPayConstants.TradeType.MWEB; } Object result = null; WxPayUnifiedOrderRequest orderRequest = null; try { orderRequest = WxPayUnifiedOrderRequest.newBuilder().body(request.getBody()) .totalFee(request.getPayAmount().multiply(new BigDecimal(PayConstant.multiple)).intValue()) .spbillCreateIp(request.getSpbillCreateIp()) .notifyUrl(wxCustomConfig.getWexinNotifyUrl()) .tradeType(tradeTypeStr) .outTradeNo(request.getRequestOrderSn()) .productId(request.getSkuId()) .deviceInfo((PayTradeTypeEnum.PC_PAY_TRADE_TYPE.getCode().intValue() == request.getTradeType()) ? "WEB" : "") .build(); ///JSAPI 需要带公众号绑定的openid much_id if (PayTradeTypeEnum.WXGZH_PAY_TRADE_TYPE.getCode().intValue() == request.getTradeType() || PayTradeTypeEnum.WXMINIPROGRAM_PAY_TRADE_TYPE.getCode().intValue() == request.getTradeType()) { orderRequest.setOpenid(request.getOpenId()); orderRequest.setMchId(wxCustomConfig.getWexinMchId()); } result = this.createOrder(orderRequest); } catch (WxPayException e) { log.error("微信支付失败:请求参数:request:{}, ", JSONUtils.toString(orderRequest), e); } log.info("LOG-IN-pay result,{},request:{}", JSONUtils.toString(result), JSONUtils.toString(request)); PayResponse response = new PayResponse(); response.setCreatePayTime(currentTimeMillis); response.setTimeoutPayTime(DateUtils.nextMinute(response.getCreatePayTime(), 5)); response.setThirdRemark(""); response.setThirdTradeNo(""); response.setPayStatus(PayStatusEnum.PayOrderStatusEnum.PAYING_STATUS_PAY.getCode()); response.setRequestOrderSn(request.getRequestOrderSn()); if (result instanceof WxPayMwebOrderResult) { //微信统一H5 支付 WxPayMwebOrderResult wxPayMwebOrderResult = (WxPayMwebOrderResult) result; response.setCaskDeskUrl(wxPayMwebOrderResult.getMwebUrl()+"&redirect_url="+request.getReturnUrl()); } else if (result instanceof WxPayNativeOrderResult) { // 微信扫码支付统一下单后发起支付拼接所需参数实现类 response.setCaskDeskUrl(((WxPayNativeOrderResult) result).getCodeUrl()); } else if (result instanceof WxPayMpOrderResult) { //微信JsAPi支付 微信公众号支付进行统一下单后组装所需参数的类(WxPayMpOrderResult) WxPayMpOrderResult wxPayMpOrderResult = (WxPayMpOrderResult) result; response.setSign(wxPayMpOrderResult.getPaySign()); } else if (result instanceof WxPayAppOrderResult) { //APP支付调用统一下单接口后的组装所需参数的实现类(WxPayAppOrderResult) WxPayAppOrderResult wxPayAppOrderResult = (WxPayAppOrderResult) result; response.setSign(wxPayAppOrderResult.getSign()); } //基础返回的签名数据拷贝 BeanUtils.copyProperties(result, response); return ReturnValue.ofSuccessful(response); }
支付主动查询支付结果(异步回调请见文章二)
@Override public ReturnValue<PayResponse> payQuery(PayRequest request) { try { WxPayOrderQueryResult result = this.queryOrder(WxPayOrderQueryRequest.newBuilder().outTradeNo(request.getRequestOrderSn()).build()); if (!PayStatusEnum.SUCCESS.equals(result.getReturnCode())) { log.error("查询支付信息失败,{}", result.getReturnMsg()); return ReturnValue.ofFailed(PayErrorCodeEnum.PAY_ERROR_CODE_2310002.getCode(), PayErrorCodeEnum.PAY_ERROR_CODE_2310002.getDesc()); } PayOrderNotifyResponse payOrderNotifyResponse = new PayOrderNotifyResponse(); BeanUtils.copyProperties(result, payOrderNotifyResponse); PayResponse response = new PayResponse(); response.setPayStatus(ConvertStatusUtil.getConvertWeixinPayStatus(payOrderNotifyResponse.getTradeState())); response.setTotalAmount(new BigDecimal(payOrderNotifyResponse.getTotalFee())); response.setThirdTradeNo(payOrderNotifyResponse.getTransactionId()); response.setPaySuccessTime(DateUtils.toDate(payOrderNotifyResponse.getTimeEnd(), "yyyyMMddHHmmss")); return ReturnValue.ofSuccessful(response); } catch (Exception e) { log.error("ERROR-IN-payQuery,request:{}", JSONUtils.toString(request)); } return ReturnValue.ofFailed(PayErrorCodeEnum.PAY_ERROR_CODE_2310003.getCode(), PayErrorCodeEnum.PAY_ERROR_CODE_2310003.getDesc()); }
喜欢的话可以点赞,评论后面的功能会再后续文章更新
(注意:微信支付有串单的问题,这边使用的是每次预支付会生成不同的第三方订单号,所以每个订单再有效的时间内,可以跨支付方式唤起支付)
签名等是第三方框架验证,看下源代码就很容易理解,还是封装的比较好的
Copyright © 2003-2013 www.wpsshop.cn 版权所有,并保留所有权利。