diff --git a/yudao-framework/yudao-spring-boot-starter-biz-pay/src/main/java/cn/iocoder/yudao/framework/pay/core/client/impl/weixin/AbstractWxPayClient.java b/yudao-framework/yudao-spring-boot-starter-biz-pay/src/main/java/cn/iocoder/yudao/framework/pay/core/client/impl/weixin/AbstractWxPayClient.java index 95589865d..fa5a793d5 100644 --- a/yudao-framework/yudao-spring-boot-starter-biz-pay/src/main/java/cn/iocoder/yudao/framework/pay/core/client/impl/weixin/AbstractWxPayClient.java +++ b/yudao-framework/yudao-spring-boot-starter-biz-pay/src/main/java/cn/iocoder/yudao/framework/pay/core/client/impl/weixin/AbstractWxPayClient.java @@ -169,7 +169,7 @@ public abstract class AbstractWxPayClient extends AbstractPayClient付款码支付 + * + * @author 芋道源码 + */ +@Slf4j public class WxBarPayClient extends AbstractWxPayClient { + /** + * 微信付款码的过期时间 + */ + private static final Duration AUTH_CODE_EXPIRE = Duration.ofMinutes(3); + public WxBarPayClient(Long channelId, WxPayClientConfig config) { super(channelId, PayChannelEnum.WX_BAR.getCode(), config); } @@ -29,23 +50,44 @@ public class WxBarPayClient extends AbstractWxPayClient { @Override protected PayOrderUnifiedRespDTO doUnifiedOrderV2(PayOrderUnifiedReqDTO reqDTO) throws WxPayException { + // 由于付款码需要不断轮询,所以需要在较短的时间完成支付 + LocalDateTime expireTime = LocalDateTimeUtils.addTime(AUTH_CODE_EXPIRE); + if (expireTime.isAfter(reqDTO.getExpireTime())) { + expireTime = reqDTO.getExpireTime(); + } // 构建 WxPayMicropayRequest 对象 WxPayMicropayRequest request = WxPayMicropayRequest.newBuilder() .outTradeNo(reqDTO.getMerchantOrderId()) .body(reqDTO.getSubject()) .detail(reqDTO.getBody()) .totalFee(reqDTO.getAmount()) // 单位分 - .timeExpire(formatDateV2(reqDTO.getExpireTime())) + .timeExpire(formatDateV2(expireTime)) .spbillCreateIp(reqDTO.getUserIp()) .authCode(getAuthCode(reqDTO)) .build(); - // 执行请求 - WxPayMicropayResult response = client.micropay(request); - - // 转换结果 - // TODO 芋艿:这里后面要看看 - return new PayOrderUnifiedRespDTO(PayOrderDisplayModeEnum.CUSTOM.getMode(), - JsonUtils.toJsonString(response)); + // 执行请求,重试直到失败(过期),或者成功 + for (int i = 1; i < Byte.MAX_VALUE; i++) { + try { + WxPayMicropayResult response = client.micropay(request); + // 支付成功(例如说,用户输入了密码) + return new PayOrderUnifiedRespDTO(PayOrderDisplayModeEnum.BAR_CODE.getMode(), + JsonUtils.toJsonString(response), + PayOrderStatusRespEnum.SUCCESS.getStatus()); + } catch (WxPayException ex) { + // 如果不满足这 3 种任一的,则直接抛出 WxPayException 异常,不仅需处理 + // 1. SYSTEMERROR:接口返回错误:请立即调用被扫订单结果查询API,查询当前订单状态,并根据订单的状态决定下一步的操作。 + // 2. USERPAYING:用户支付中,需要输入密码:等待 5 秒,然后调用被扫订单结果查询 API,查询当前订单的不同状态,决定下一步的操作。 + // 3. BANKERROR:银行系统异常:请立即调用被扫订单结果查询 API,查询当前订单的不同状态,决定下一步的操作。 + if (!StrUtil.equalsAny(ex.getErrCode(), "SYSTEMERROR", "USERPAYING", "BANKERROR")) { + throw ex; + } + // 等待 5 秒,继续下一轮重新发起支付 + log.info("[doUnifiedOrderV2][发起微信 Bar 支付第({})失败,等待下一轮重试,请求({}),响应({})]", i, + JsonUtils.toJsonString(request), ex.getMessage()); + ThreadUtil.sleep(5, TimeUnit.SECONDS); + } + } + throw new IllegalStateException("微信 Bar 支付,重试多次失败"); } @Override diff --git a/yudao-framework/yudao-spring-boot-starter-biz-pay/src/main/java/cn/iocoder/yudao/framework/pay/core/client/impl/weixin/WxLitePayClient.java b/yudao-framework/yudao-spring-boot-starter-biz-pay/src/main/java/cn/iocoder/yudao/framework/pay/core/client/impl/weixin/WxLitePayClient.java index 55ad62be5..9929955ae 100644 --- a/yudao-framework/yudao-spring-boot-starter-biz-pay/src/main/java/cn/iocoder/yudao/framework/pay/core/client/impl/weixin/WxLitePayClient.java +++ b/yudao-framework/yudao-spring-boot-starter-biz-pay/src/main/java/cn/iocoder/yudao/framework/pay/core/client/impl/weixin/WxLitePayClient.java @@ -4,10 +4,12 @@ import cn.iocoder.yudao.framework.pay.core.enums.channel.PayChannelEnum; import lombok.extern.slf4j.Slf4j; /** - * 微信支付(小程序)的 PayClient 实现类 + * 微信支付【小程序】的 PayClient 实现类 * * 由于公众号和小程序的微信支付逻辑一致,所以直接进行继承 * + * 文档:JSAPI 下单 + * * @author zwy */ @Slf4j diff --git a/yudao-framework/yudao-spring-boot-starter-biz-pay/src/main/java/cn/iocoder/yudao/framework/pay/core/client/impl/weixin/WxPayClientConfig.java b/yudao-framework/yudao-spring-boot-starter-biz-pay/src/main/java/cn/iocoder/yudao/framework/pay/core/client/impl/weixin/WxPayClientConfig.java index 48228f379..e109a6cf7 100644 --- a/yudao-framework/yudao-spring-boot-starter-biz-pay/src/main/java/cn/iocoder/yudao/framework/pay/core/client/impl/weixin/WxPayClientConfig.java +++ b/yudao-framework/yudao-spring-boot-starter-biz-pay/src/main/java/cn/iocoder/yudao/framework/pay/core/client/impl/weixin/WxPayClientConfig.java @@ -23,20 +23,21 @@ public class WxPayClientConfig implements PayClientConfig { /** * API 版本 - V2 * - * https://pay.weixin.qq.com/wiki/doc/api/jsapi.php?chapter=4_1 + * V2 协议说明 */ public static final String API_VERSION_V2 = "v2"; /** * API 版本 - V3 * - * https://pay.weixin.qq.com/wiki/doc/apiv3/wechatpay/wechatpay-1.shtml + * V3 协议说明 */ public static final String API_VERSION_V3 = "v3"; /** * 公众号或者小程序的 appid + * + * 只有公众号或小程序需要该字段 */ - @NotBlank(message = "APPID 不能为空", groups = {V2.class, V3.class}) private String appId; /** * 商户号 diff --git a/yudao-framework/yudao-spring-boot-starter-biz-pay/src/main/java/cn/iocoder/yudao/framework/pay/core/client/impl/weixin/WxPubPayClient.java b/yudao-framework/yudao-spring-boot-starter-biz-pay/src/main/java/cn/iocoder/yudao/framework/pay/core/client/impl/weixin/WxPubPayClient.java index cc4b5b848..f23942bc7 100644 --- a/yudao-framework/yudao-spring-boot-starter-biz-pay/src/main/java/cn/iocoder/yudao/framework/pay/core/client/impl/weixin/WxPubPayClient.java +++ b/yudao-framework/yudao-spring-boot-starter-biz-pay/src/main/java/cn/iocoder/yudao/framework/pay/core/client/impl/weixin/WxPubPayClient.java @@ -23,6 +23,8 @@ import static cn.iocoder.yudao.framework.common.exception.util.ServiceExceptionU /** * 微信支付(公众号)的 PayClient 实现类 * + * 文档:JSAPI 下单 + * * @author 芋道源码 */ @Slf4j diff --git a/yudao-module-pay/yudao-module-pay-biz/src/main/java/cn/iocoder/yudao/module/pay/controller/app/order/AppPayOrderController.http b/yudao-module-pay/yudao-module-pay-biz/src/main/java/cn/iocoder/yudao/module/pay/controller/app/order/AppPayOrderController.http index cd19b4af6..70b85d80e 100644 --- a/yudao-module-pay/yudao-module-pay-biz/src/main/java/cn/iocoder/yudao/module/pay/controller/app/order/AppPayOrderController.http +++ b/yudao-module-pay/yudao-module-pay-biz/src/main/java/cn/iocoder/yudao/module/pay/controller/app/order/AppPayOrderController.http @@ -19,7 +19,7 @@ tenant-id: {{appTenentId}} "id": 202, "channelCode": "wx_bar", "channelExtras": { - "authCode": "132527737910208222" + "authCode": "132990241553789274" } }