Commit d0a7f4187592c5da8d593473adb62a268fb66ee4
1 parent
68a4ef98
mall + pay:
1. 完善微信支付的 V3 支付回调、退款回调
Showing
4 changed files
with
121 additions
and
70 deletions
yudao-framework/yudao-spring-boot-starter-biz-pay/src/main/java/cn/iocoder/yudao/framework/pay/core/client/impl/AbstractPayClient.java
| @@ -70,6 +70,8 @@ public abstract class AbstractPayClient<Config extends PayClientConfig> implemen | @@ -70,6 +70,8 @@ public abstract class AbstractPayClient<Config extends PayClientConfig> implemen | ||
| 70 | return channelId; | 70 | return channelId; |
| 71 | } | 71 | } |
| 72 | 72 | ||
| 73 | + // ============ 支付相关 ========== | ||
| 74 | + | ||
| 73 | @Override | 75 | @Override |
| 74 | public final PayOrderUnifiedRespDTO unifiedOrder(PayOrderUnifiedReqDTO reqDTO) { | 76 | public final PayOrderUnifiedRespDTO unifiedOrder(PayOrderUnifiedReqDTO reqDTO) { |
| 75 | Validation.buildDefaultValidatorFactory().getValidator().validate(reqDTO); | 77 | Validation.buildDefaultValidatorFactory().getValidator().validate(reqDTO); |
| @@ -91,6 +93,8 @@ public abstract class AbstractPayClient<Config extends PayClientConfig> implemen | @@ -91,6 +93,8 @@ public abstract class AbstractPayClient<Config extends PayClientConfig> implemen | ||
| 91 | protected abstract PayOrderUnifiedRespDTO doUnifiedOrder(PayOrderUnifiedReqDTO reqDTO) | 93 | protected abstract PayOrderUnifiedRespDTO doUnifiedOrder(PayOrderUnifiedReqDTO reqDTO) |
| 92 | throws Throwable; | 94 | throws Throwable; |
| 93 | 95 | ||
| 96 | + // ============ 退款相关 ========== | ||
| 97 | + | ||
| 94 | @Override | 98 | @Override |
| 95 | public PayRefundRespDTO unifiedRefund(PayRefundUnifiedReqDTO reqDTO) { | 99 | public PayRefundRespDTO unifiedRefund(PayRefundUnifiedReqDTO reqDTO) { |
| 96 | Validation.buildDefaultValidatorFactory().getValidator().validate(reqDTO); | 100 | Validation.buildDefaultValidatorFactory().getValidator().validate(reqDTO); |
yudao-framework/yudao-spring-boot-starter-biz-pay/src/main/java/cn/iocoder/yudao/framework/pay/core/client/impl/weixin/AbstractWxPayClient.java
| @@ -4,7 +4,6 @@ import cn.hutool.core.bean.BeanUtil; | @@ -4,7 +4,6 @@ import cn.hutool.core.bean.BeanUtil; | ||
| 4 | import cn.hutool.core.codec.Base64; | 4 | import cn.hutool.core.codec.Base64; |
| 5 | import cn.hutool.core.date.LocalDateTimeUtil; | 5 | import cn.hutool.core.date.LocalDateTimeUtil; |
| 6 | import cn.hutool.core.date.TemporalAccessorUtil; | 6 | import cn.hutool.core.date.TemporalAccessorUtil; |
| 7 | -import cn.hutool.core.lang.Assert; | ||
| 8 | import cn.hutool.core.util.StrUtil; | 7 | import cn.hutool.core.util.StrUtil; |
| 9 | import cn.iocoder.yudao.framework.common.util.io.FileUtils; | 8 | import cn.iocoder.yudao.framework.common.util.io.FileUtils; |
| 10 | import cn.iocoder.yudao.framework.pay.core.client.dto.order.PayOrderRespDTO; | 9 | import cn.iocoder.yudao.framework.pay.core.client.dto.order.PayOrderRespDTO; |
| @@ -19,8 +18,11 @@ import cn.iocoder.yudao.framework.pay.core.enums.refund.PayRefundStatusRespEnum; | @@ -19,8 +18,11 @@ import cn.iocoder.yudao.framework.pay.core.enums.refund.PayRefundStatusRespEnum; | ||
| 19 | import com.github.binarywang.wxpay.bean.notify.WxPayOrderNotifyResult; | 18 | import com.github.binarywang.wxpay.bean.notify.WxPayOrderNotifyResult; |
| 20 | import com.github.binarywang.wxpay.bean.notify.WxPayOrderNotifyV3Result; | 19 | import com.github.binarywang.wxpay.bean.notify.WxPayOrderNotifyV3Result; |
| 21 | import com.github.binarywang.wxpay.bean.notify.WxPayRefundNotifyResult; | 20 | import com.github.binarywang.wxpay.bean.notify.WxPayRefundNotifyResult; |
| 21 | +import com.github.binarywang.wxpay.bean.notify.WxPayRefundNotifyV3Result; | ||
| 22 | import com.github.binarywang.wxpay.bean.request.WxPayRefundRequest; | 22 | import com.github.binarywang.wxpay.bean.request.WxPayRefundRequest; |
| 23 | +import com.github.binarywang.wxpay.bean.request.WxPayRefundV3Request; | ||
| 23 | import com.github.binarywang.wxpay.bean.result.WxPayRefundResult; | 24 | import com.github.binarywang.wxpay.bean.result.WxPayRefundResult; |
| 25 | +import com.github.binarywang.wxpay.bean.result.WxPayRefundV3Result; | ||
| 24 | import com.github.binarywang.wxpay.config.WxPayConfig; | 26 | import com.github.binarywang.wxpay.config.WxPayConfig; |
| 25 | import com.github.binarywang.wxpay.exception.WxPayException; | 27 | import com.github.binarywang.wxpay.exception.WxPayException; |
| 26 | import com.github.binarywang.wxpay.service.WxPayService; | 28 | import com.github.binarywang.wxpay.service.WxPayService; |
| @@ -78,6 +80,8 @@ public abstract class AbstractWxPayClient extends AbstractPayClient<WxPayClientC | @@ -78,6 +80,8 @@ public abstract class AbstractWxPayClient extends AbstractPayClient<WxPayClientC | ||
| 78 | client.setConfig(payConfig); | 80 | client.setConfig(payConfig); |
| 79 | } | 81 | } |
| 80 | 82 | ||
| 83 | + // ============ 支付相关 ========== | ||
| 84 | + | ||
| 81 | @Override | 85 | @Override |
| 82 | protected PayOrderUnifiedRespDTO doUnifiedOrder(PayOrderUnifiedReqDTO reqDTO) throws Exception { | 86 | protected PayOrderUnifiedRespDTO doUnifiedOrder(PayOrderUnifiedReqDTO reqDTO) throws Exception { |
| 83 | try { | 87 | try { |
| @@ -114,6 +118,58 @@ public abstract class AbstractWxPayClient extends AbstractPayClient<WxPayClientC | @@ -114,6 +118,58 @@ public abstract class AbstractWxPayClient extends AbstractPayClient<WxPayClientC | ||
| 114 | throws WxPayException; | 118 | throws WxPayException; |
| 115 | 119 | ||
| 116 | @Override | 120 | @Override |
| 121 | + public PayOrderRespDTO parseOrderNotify(Map<String, String> params, String body) { | ||
| 122 | + try { | ||
| 123 | + // 微信支付 v2 回调结果处理 | ||
| 124 | + switch (config.getApiVersion()) { | ||
| 125 | + case API_VERSION_V2: | ||
| 126 | + return parseOrderNotifyV2(body); | ||
| 127 | + case WxPayClientConfig.API_VERSION_V3: | ||
| 128 | + return parseOrderNotifyV3(body); | ||
| 129 | + default: | ||
| 130 | + throw new IllegalArgumentException(String.format("未知的 API 版本(%s)", config.getApiVersion())); | ||
| 131 | + } | ||
| 132 | + } catch (WxPayException e) { | ||
| 133 | + log.error("[parseNotify][params({}) body({}) 解析失败]", params, body, e); | ||
| 134 | +// throw buildPayException(e); | ||
| 135 | + throw new RuntimeException(e); | ||
| 136 | + // TODO 芋艿:缺一个异常翻译 | ||
| 137 | + } | ||
| 138 | + } | ||
| 139 | + | ||
| 140 | + private PayOrderRespDTO parseOrderNotifyV2(String body) throws WxPayException { | ||
| 141 | + // 1. 解析回调 | ||
| 142 | + WxPayOrderNotifyResult response = client.parseOrderNotifyResult(body); | ||
| 143 | + // 2. 构建结果 | ||
| 144 | + return PayOrderRespDTO.builder() | ||
| 145 | + .outTradeNo(response.getOutTradeNo()) | ||
| 146 | + .channelOrderNo(response.getTransactionId()) | ||
| 147 | + .channelUserId(response.getOpenid()) | ||
| 148 | + .status(Objects.equals(response.getResultCode(), "SUCCESS") ? | ||
| 149 | + PayOrderStatusRespEnum.SUCCESS.getStatus() : PayOrderStatusRespEnum.CLOSED.getStatus()) | ||
| 150 | + .successTime(parseDateV2(response.getTimeEnd())) | ||
| 151 | + .rawData(response) | ||
| 152 | + .build(); | ||
| 153 | + } | ||
| 154 | + | ||
| 155 | + private PayOrderRespDTO parseOrderNotifyV3(String body) throws WxPayException { | ||
| 156 | + // 1. 解析回调 | ||
| 157 | + WxPayOrderNotifyV3Result response = client.parseOrderNotifyV3Result(body, null); | ||
| 158 | + WxPayOrderNotifyV3Result.DecryptNotifyResult responseResult = response.getResult(); | ||
| 159 | + // 2. 构建结果 | ||
| 160 | + return PayOrderRespDTO.builder() | ||
| 161 | + .outTradeNo(responseResult.getOutTradeNo()) | ||
| 162 | + .channelOrderNo(responseResult.getTradeState()) | ||
| 163 | + .channelUserId(responseResult.getPayer() != null ? responseResult.getPayer().getOpenid() : null) | ||
| 164 | + .status(Objects.equals(responseResult.getTradeState(), "SUCCESS") ? | ||
| 165 | + PayOrderStatusRespEnum.SUCCESS.getStatus() : PayOrderStatusRespEnum.CLOSED.getStatus()) | ||
| 166 | + .successTime(parseDateV3(responseResult.getSuccessTime())) | ||
| 167 | + .build(); | ||
| 168 | + } | ||
| 169 | + | ||
| 170 | + // ============ 退款相关 ========== | ||
| 171 | + | ||
| 172 | + @Override | ||
| 117 | protected PayRefundRespDTO doUnifiedRefund(PayRefundUnifiedReqDTO reqDTO) throws Throwable { | 173 | protected PayRefundRespDTO doUnifiedRefund(PayRefundUnifiedReqDTO reqDTO) throws Throwable { |
| 118 | try { | 174 | try { |
| 119 | switch (config.getApiVersion()) { | 175 | switch (config.getApiVersion()) { |
| @@ -140,73 +196,48 @@ public abstract class AbstractWxPayClient extends AbstractPayClient<WxPayClientC | @@ -140,73 +196,48 @@ public abstract class AbstractWxPayClient extends AbstractPayClient<WxPayClientC | ||
| 140 | .setTotalFee(reqDTO.getPayPrice()) | 196 | .setTotalFee(reqDTO.getPayPrice()) |
| 141 | .setNotifyUrl(reqDTO.getNotifyUrl()); | 197 | .setNotifyUrl(reqDTO.getNotifyUrl()); |
| 142 | // 2.1 执行请求 | 198 | // 2.1 执行请求 |
| 143 | - WxPayRefundResult response = client.refundV2(request); // TODO 芋艿:可以分成 V2 和 V3 的退款接口 | 199 | + WxPayRefundResult response = client.refundV2(request); |
| 144 | // 2.2 创建返回结果 | 200 | // 2.2 创建返回结果 |
| 145 | PayRefundRespDTO refund = new PayRefundRespDTO() | 201 | PayRefundRespDTO refund = new PayRefundRespDTO() |
| 146 | .setOutRefundNo(reqDTO.getOutRefundNo()) | 202 | .setOutRefundNo(reqDTO.getOutRefundNo()) |
| 147 | .setRawData(response); | 203 | .setRawData(response); |
| 148 | if (Objects.equals("SUCCESS", response.getResultCode())) { | 204 | if (Objects.equals("SUCCESS", response.getResultCode())) { |
| 149 | - refund.setStatus(PayRefundStatusRespEnum.WAITING.getStatus()); | ||
| 150 | - refund.setChannelRefundNo(response.getRefundId()); | 205 | + refund.setStatus(PayRefundStatusRespEnum.WAITING.getStatus()) |
| 206 | + .setChannelRefundNo(response.getRefundId()); | ||
| 151 | } else { | 207 | } else { |
| 152 | refund.setStatus(PayRefundStatusRespEnum.FAILURE.getStatus()); | 208 | refund.setStatus(PayRefundStatusRespEnum.FAILURE.getStatus()); |
| 153 | - // TODO 芋艿;异常的处理; | ||
| 154 | } | 209 | } |
| 210 | + // TODO 芋艿;异常的处理; | ||
| 155 | return refund; | 211 | return refund; |
| 156 | } | 212 | } |
| 157 | 213 | ||
| 158 | private PayRefundRespDTO doUnifiedRefundV3(PayRefundUnifiedReqDTO reqDTO) throws Throwable { | 214 | private PayRefundRespDTO doUnifiedRefundV3(PayRefundUnifiedReqDTO reqDTO) throws Throwable { |
| 159 | - return null; | ||
| 160 | - } | ||
| 161 | - | ||
| 162 | - @Override | ||
| 163 | - public PayOrderRespDTO parseOrderNotify(Map<String, String> params, String body) { | ||
| 164 | - try { | ||
| 165 | - // 微信支付 v2 回调结果处理 | ||
| 166 | - switch (config.getApiVersion()) { | ||
| 167 | - case API_VERSION_V2: | ||
| 168 | - return parseOrderNotifyV2(body); | ||
| 169 | - case WxPayClientConfig.API_VERSION_V3: | ||
| 170 | - return parseOrderNotifyV3(body); | ||
| 171 | - default: | ||
| 172 | - throw new IllegalArgumentException(String.format("未知的 API 版本(%s)", config.getApiVersion())); | ||
| 173 | - } | ||
| 174 | - } catch (WxPayException e) { | ||
| 175 | - log.error("[parseNotify][params({}) body({}) 解析失败]", params, body, e); | ||
| 176 | -// throw buildPayException(e); | ||
| 177 | - throw new RuntimeException(e); | ||
| 178 | - // TODO 芋艿:缺一个异常翻译 | 215 | + // 1. 构建 WxPayRefundRequest 请求 |
| 216 | + WxPayRefundV3Request request = new WxPayRefundV3Request() | ||
| 217 | + .setOutTradeNo(reqDTO.getOutTradeNo()) | ||
| 218 | + .setOutRefundNo(reqDTO.getOutRefundNo()) | ||
| 219 | + .setAmount(new WxPayRefundV3Request.Amount().setRefund(reqDTO.getRefundPrice()) | ||
| 220 | + .setTotal(reqDTO.getPayPrice()).setCurrency("CNY")) | ||
| 221 | + .setReason(reqDTO.getReason()) | ||
| 222 | + .setNotifyUrl(reqDTO.getNotifyUrl()); | ||
| 223 | + // 2.1 执行请求 | ||
| 224 | + WxPayRefundV3Result response = client.refundV3(request); | ||
| 225 | + // 2.2 创建返回结果 | ||
| 226 | + PayRefundRespDTO refund = new PayRefundRespDTO() | ||
| 227 | + .setOutRefundNo(reqDTO.getOutRefundNo()) | ||
| 228 | + .setRawData(response); | ||
| 229 | + if (Objects.equals("SUCCESS", response.getStatus())) { | ||
| 230 | + refund.setStatus(PayRefundStatusRespEnum.SUCCESS.getStatus()) | ||
| 231 | + .setChannelRefundNo(response.getRefundId()) | ||
| 232 | + .setSuccessTime(parseDateV3(response.getSuccessTime())); | ||
| 233 | + } else if (Objects.equals("PROCESSING", response.getStatus())) { | ||
| 234 | + refund.setStatus(PayRefundStatusRespEnum.WAITING.getStatus()) | ||
| 235 | + .setChannelRefundNo(response.getRefundId()); | ||
| 236 | + } else { | ||
| 237 | + refund.setStatus(PayRefundStatusRespEnum.FAILURE.getStatus()); | ||
| 179 | } | 238 | } |
| 180 | - } | ||
| 181 | - | ||
| 182 | - private PayOrderRespDTO parseOrderNotifyV2(String body) throws WxPayException { | ||
| 183 | - // 1. 解析回调 | ||
| 184 | - WxPayOrderNotifyResult response = client.parseOrderNotifyResult(body); | ||
| 185 | - // 2. 构建结果 | ||
| 186 | - return PayOrderRespDTO.builder() | ||
| 187 | - .outTradeNo(response.getOutTradeNo()) | ||
| 188 | - .channelOrderNo(response.getTransactionId()) | ||
| 189 | - .channelUserId(response.getOpenid()) | ||
| 190 | - .status(Objects.equals(response.getResultCode(), "SUCCESS") ? | ||
| 191 | - PayOrderStatusRespEnum.SUCCESS.getStatus() : PayOrderStatusRespEnum.CLOSED.getStatus()) | ||
| 192 | - .successTime(parseDateV2(response.getTimeEnd())) | ||
| 193 | - .rawData(response) | ||
| 194 | - .build(); | ||
| 195 | - } | ||
| 196 | - | ||
| 197 | - private PayOrderRespDTO parseOrderNotifyV3(String body) throws WxPayException { | ||
| 198 | - WxPayOrderNotifyV3Result notifyResult = client.parseOrderNotifyV3Result(body, null); | ||
| 199 | - WxPayOrderNotifyV3Result.DecryptNotifyResult result = notifyResult.getResult(); | ||
| 200 | - // TODO 芋艿:翻译下 state | ||
| 201 | - // 转换结果 | ||
| 202 | - Assert.isTrue(Objects.equals(notifyResult.getResult().getTradeState(), "SUCCESS"), | ||
| 203 | - "支付结果非 SUCCESS"); | ||
| 204 | - return PayOrderRespDTO.builder() | ||
| 205 | - .outTradeNo(result.getOutTradeNo()) | ||
| 206 | - .channelOrderNo(result.getTradeState()) | ||
| 207 | - .channelUserId(result.getPayer() != null ? result.getPayer().getOpenid() : null) | ||
| 208 | - .successTime(parseDateV3(result.getSuccessTime())) | ||
| 209 | - .build(); | 239 | + // TODO 芋艿;异常的处理; |
| 240 | + return refund; | ||
| 210 | } | 241 | } |
| 211 | 242 | ||
| 212 | @Override | 243 | @Override |
| @@ -229,27 +260,42 @@ public abstract class AbstractWxPayClient extends AbstractPayClient<WxPayClientC | @@ -229,27 +260,42 @@ public abstract class AbstractWxPayClient extends AbstractPayClient<WxPayClientC | ||
| 229 | } | 260 | } |
| 230 | } | 261 | } |
| 231 | 262 | ||
| 263 | + @SuppressWarnings("DuplicatedCode") | ||
| 232 | private PayRefundRespDTO parseRefundNotifyV2(String body) throws WxPayException { | 264 | private PayRefundRespDTO parseRefundNotifyV2(String body) throws WxPayException { |
| 233 | // 1. 解析回调 | 265 | // 1. 解析回调 |
| 234 | WxPayRefundNotifyResult response = client.parseRefundNotifyResult(body); | 266 | WxPayRefundNotifyResult response = client.parseRefundNotifyResult(body); |
| 235 | - WxPayRefundNotifyResult.ReqInfo reqInfo = response.getReqInfo(); | 267 | + WxPayRefundNotifyResult.ReqInfo responseResult = response.getReqInfo(); |
| 236 | // 2. 构建结果 | 268 | // 2. 构建结果 |
| 237 | PayRefundRespDTO notify = new PayRefundRespDTO() | 269 | PayRefundRespDTO notify = new PayRefundRespDTO() |
| 238 | - .setChannelRefundNo(reqInfo.getRefundId()) | ||
| 239 | - .setOutRefundNo(reqInfo.getOutRefundNo()) | 270 | + .setChannelRefundNo(responseResult.getRefundId()) |
| 271 | + .setOutRefundNo(responseResult.getOutRefundNo()) | ||
| 240 | .setRawData(response); | 272 | .setRawData(response); |
| 241 | - if (Objects.equals("SUCCESS", reqInfo.getRefundStatus())) { | 273 | + if (Objects.equals("SUCCESS", responseResult.getRefundStatus())) { |
| 242 | notify.setStatus(PayRefundStatusRespEnum.SUCCESS.getStatus()) | 274 | notify.setStatus(PayRefundStatusRespEnum.SUCCESS.getStatus()) |
| 243 | - .setSuccessTime(parseDateV2B(reqInfo.getSuccessTime())); | 275 | + .setSuccessTime(parseDateV2B(responseResult.getSuccessTime())); |
| 244 | } else { | 276 | } else { |
| 245 | notify.setStatus(PayRefundStatusRespEnum.FAILURE.getStatus()); | 277 | notify.setStatus(PayRefundStatusRespEnum.FAILURE.getStatus()); |
| 246 | } | 278 | } |
| 247 | return notify; | 279 | return notify; |
| 248 | } | 280 | } |
| 249 | 281 | ||
| 282 | + @SuppressWarnings("DuplicatedCode") | ||
| 250 | private PayRefundRespDTO parseRefundNotifyV3(String body) throws WxPayException { | 283 | private PayRefundRespDTO parseRefundNotifyV3(String body) throws WxPayException { |
| 251 | - // TODO 芋艿:未实现 | ||
| 252 | - return null; | 284 | + // 1. 解析回调 |
| 285 | + WxPayRefundNotifyV3Result response = client.parseRefundNotifyV3Result(body, null); | ||
| 286 | + WxPayRefundNotifyV3Result.DecryptNotifyResult responseResult = response.getResult(); | ||
| 287 | + // 2. 构建结果 | ||
| 288 | + PayRefundRespDTO notify = new PayRefundRespDTO() | ||
| 289 | + .setChannelRefundNo(responseResult.getRefundId()) | ||
| 290 | + .setOutRefundNo(responseResult.getOutRefundNo()) | ||
| 291 | + .setRawData(response); | ||
| 292 | + if (Objects.equals("SUCCESS", responseResult.getRefundStatus())) { | ||
| 293 | + notify.setStatus(PayRefundStatusRespEnum.SUCCESS.getStatus()) | ||
| 294 | + .setSuccessTime(parseDateV3(responseResult.getSuccessTime())); | ||
| 295 | + } else { | ||
| 296 | + notify.setStatus(PayRefundStatusRespEnum.FAILURE.getStatus()); | ||
| 297 | + } | ||
| 298 | + return notify; | ||
| 253 | } | 299 | } |
| 254 | 300 | ||
| 255 | // ========== 各种工具方法 ========== | 301 | // ========== 各种工具方法 ========== |
yudao-framework/yudao-spring-boot-starter-biz-pay/src/main/java/cn/iocoder/yudao/framework/pay/core/client/impl/weixin/WxNativePayClient.java
| @@ -55,13 +55,13 @@ public class WxNativePayClient extends AbstractWxPayClient { | @@ -55,13 +55,13 @@ public class WxNativePayClient extends AbstractWxPayClient { | ||
| 55 | @Override | 55 | @Override |
| 56 | protected PayOrderUnifiedRespDTO doUnifiedOrderV3(PayOrderUnifiedReqDTO reqDTO) throws WxPayException { | 56 | protected PayOrderUnifiedRespDTO doUnifiedOrderV3(PayOrderUnifiedReqDTO reqDTO) throws WxPayException { |
| 57 | // 构建 WxPayUnifiedOrderRequest 对象 | 57 | // 构建 WxPayUnifiedOrderRequest 对象 |
| 58 | - WxPayUnifiedOrderV3Request request = new WxPayUnifiedOrderV3Request(); | ||
| 59 | - request.setOutTradeNo(reqDTO.getOutTradeNo()); | ||
| 60 | - request.setDescription(reqDTO.getBody()); | ||
| 61 | - request.setAmount(new WxPayUnifiedOrderV3Request.Amount().setTotal(reqDTO.getPrice())); // 单位分 | ||
| 62 | - request.setTimeExpire(formatDateV3(reqDTO.getExpireTime())); | ||
| 63 | - request.setSceneInfo(new WxPayUnifiedOrderV3Request.SceneInfo().setPayerClientIp(reqDTO.getUserIp())); | ||
| 64 | - request.setNotifyUrl(reqDTO.getNotifyUrl()); | 58 | + WxPayUnifiedOrderV3Request request = new WxPayUnifiedOrderV3Request() |
| 59 | + .setOutTradeNo(reqDTO.getOutTradeNo()) | ||
| 60 | + .setDescription(reqDTO.getSubject()) | ||
| 61 | + .setAmount(new WxPayUnifiedOrderV3Request.Amount().setTotal(reqDTO.getPrice())) // 单位分 | ||
| 62 | + .setTimeExpire(formatDateV3(reqDTO.getExpireTime())) | ||
| 63 | + .setSceneInfo(new WxPayUnifiedOrderV3Request.SceneInfo().setPayerClientIp(reqDTO.getUserIp())) | ||
| 64 | + .setNotifyUrl(reqDTO.getNotifyUrl()); | ||
| 65 | // 执行请求 | 65 | // 执行请求 |
| 66 | String response = client.createOrderV3(TradeTypeEnum.NATIVE, request); | 66 | String response = client.createOrderV3(TradeTypeEnum.NATIVE, request); |
| 67 | 67 |
yudao-ui-admin/src/views/pay/demo/index.vue
| @@ -41,7 +41,8 @@ | @@ -41,7 +41,8 @@ | ||
| 41 | </el-table-column> | 41 | </el-table-column> |
| 42 | <el-table-column label="退款时间" align="center" prop="refundTime" width="180"> | 42 | <el-table-column label="退款时间" align="center" prop="refundTime" width="180"> |
| 43 | <template v-slot="scope"> | 43 | <template v-slot="scope"> |
| 44 | - <span>{{ parseTime(scope.row.refundTime) }}</span> | 44 | + <span v-if="scope.row.refundTime">{{ parseTime(scope.row.refundTime) }}</span> |
| 45 | + <span v-else-if="scope.row.payRefundId">退款中,等待退款结果</span> | ||
| 45 | </template> | 46 | </template> |
| 46 | </el-table-column> | 47 | </el-table-column> |
| 47 | <el-table-column label="操作" align="center" class-name="small-padding fixed-width"> | 48 | <el-table-column label="操作" align="center" class-name="small-padding fixed-width"> |