|
@@ -1,19 +1,35 @@
|
|
|
package com.ruoyi.wx.web.controller;
|
|
|
|
|
|
|
|
|
+import com.github.binarywang.wxpay.bean.notify.OriginNotifyResponse;
|
|
|
+import com.github.binarywang.wxpay.bean.notify.SignatureHeader;
|
|
|
+import com.github.binarywang.wxpay.bean.notify.WxPayNotifyV3Result;
|
|
|
import com.github.binarywang.wxpay.bean.request.WxPayOrderCloseRequest;
|
|
|
import com.github.binarywang.wxpay.bean.request.WxPayOrderQueryRequest;
|
|
|
import com.github.binarywang.wxpay.bean.request.WxPayUnifiedOrderRequest;
|
|
|
+import com.github.binarywang.wxpay.bean.request.WxPayUnifiedOrderV3Request;
|
|
|
import com.github.binarywang.wxpay.bean.result.WxPayOrderCloseResult;
|
|
|
import com.github.binarywang.wxpay.bean.result.WxPayOrderQueryResult;
|
|
|
import com.github.binarywang.wxpay.bean.result.WxPayUnifiedOrderResult;
|
|
|
+import com.github.binarywang.wxpay.bean.result.WxPayUnifiedOrderV3Result;
|
|
|
+import com.github.binarywang.wxpay.bean.result.enums.TradeTypeEnum;
|
|
|
import com.github.binarywang.wxpay.exception.WxPayException;
|
|
|
import com.github.binarywang.wxpay.service.WxPayService;
|
|
|
+import com.google.gson.GsonBuilder;
|
|
|
+import com.ruoyi.common.core.domain.AjaxResult;
|
|
|
+import com.ruoyi.common.utils.StringUtils;
|
|
|
+import com.ruoyi.wx.web.domain.dto.WxPayDto;
|
|
|
+import com.ruoyi.wx.web.unit.WeixinNotifyUtils;
|
|
|
import io.swagger.annotations.ApiOperation;
|
|
|
+import jakarta.servlet.http.HttpServletRequest;
|
|
|
+import jakarta.servlet.http.HttpServletResponse;
|
|
|
import lombok.extern.slf4j.Slf4j;
|
|
|
import org.springframework.beans.factory.annotation.Autowired;
|
|
|
import org.springframework.web.bind.annotation.*;
|
|
|
|
|
|
+import java.math.BigDecimal;
|
|
|
+import java.util.concurrent.locks.ReentrantLock;
|
|
|
+
|
|
|
/**
|
|
|
*
|
|
|
* 支付接口
|
|
@@ -25,7 +41,7 @@ public class WxPayController {
|
|
|
@Autowired
|
|
|
private WxPayService wxPayService;
|
|
|
|
|
|
-
|
|
|
+ private final ReentrantLock orderLock = new ReentrantLock();
|
|
|
/**
|
|
|
* <pre>
|
|
|
* 查询订单(详见https://pay.weixin.qq.com/wiki/doc/api/jsapi.php?chapter=9_2)
|
|
@@ -86,14 +102,36 @@ public class WxPayController {
|
|
|
/**
|
|
|
* 调用统一下单接口,并组装生成支付所需参数对象.
|
|
|
*
|
|
|
- * @param request 统一下单请求参数
|
|
|
- * @param <T> 请使用{@link com.github.binarywang.wxpay.bean.order}包下的类
|
|
|
+ * @param dto 统一下单请求参数
|
|
|
* @return 返回 {@link com.github.binarywang.wxpay.bean.order}包下的类对象
|
|
|
*/
|
|
|
@ApiOperation(value = "统一下单,并组装所需支付参数")
|
|
|
@PostMapping("/createOrder")
|
|
|
- public <T> T createOrder(@RequestBody WxPayUnifiedOrderRequest request) throws WxPayException {
|
|
|
- return this.wxPayService.createOrder(request);
|
|
|
+ public AjaxResult createOrder(@RequestBody WxPayDto dto) throws WxPayException {
|
|
|
+ WxPayUnifiedOrderV3Request request = new WxPayUnifiedOrderV3Request();
|
|
|
+ request.setDescription("购买会员");
|
|
|
+ // 商品订单号
|
|
|
+ String orderNo = "ORDER_" + System.currentTimeMillis();
|
|
|
+ request.setOutTradeNo(orderNo);
|
|
|
+ // 订单金额
|
|
|
+ WxPayUnifiedOrderV3Request.Amount amount = new WxPayUnifiedOrderV3Request.Amount();
|
|
|
+ amount.setCurrency("CNY");
|
|
|
+ BigDecimal total = new BigDecimal("0");
|
|
|
+ if (StringUtils.isNotEmpty(dto.getMoney())) {
|
|
|
+ total = total.subtract(new BigDecimal(dto.getMoney()));
|
|
|
+ } else if (StringUtils.isNotEmpty(dto.getDiscount())) {
|
|
|
+ total = total.multiply(new BigDecimal(dto.getDiscount()).divide(new BigDecimal(10)));
|
|
|
+ }
|
|
|
+ amount.setTotal(total.intValue() * 100);
|
|
|
+ WxPayUnifiedOrderV3Result.JsapiResult orderV3 = this.wxPayService.createOrderV3(TradeTypeEnum.JSAPI, request);
|
|
|
+ AjaxResult result = new AjaxResult();
|
|
|
+ result.put("appId", orderV3.getAppId());
|
|
|
+ result.put("timeStamp", orderV3.getTimeStamp());
|
|
|
+ result.put("nonceStr", orderV3.getNonceStr());
|
|
|
+ result.put("packageValue", orderV3.getPackageValue());
|
|
|
+ result.put("signType", orderV3.getSignType());
|
|
|
+ result.put("outTradeNo", orderNo);
|
|
|
+ return result;
|
|
|
}
|
|
|
|
|
|
/**
|
|
@@ -108,4 +146,44 @@ public class WxPayController {
|
|
|
public WxPayUnifiedOrderResult unifiedOrder(@RequestBody WxPayUnifiedOrderRequest request) throws WxPayException {
|
|
|
return this.wxPayService.unifiedOrder(request);
|
|
|
}
|
|
|
+
|
|
|
+ /**
|
|
|
+ * 回调接口
|
|
|
+ */
|
|
|
+ @ApiOperation(value = "回调接口")
|
|
|
+ @PostMapping("/notify")
|
|
|
+ public AjaxResult notify(HttpServletRequest request, HttpServletResponse response, @RequestBody String notifyData) throws WxPayException {
|
|
|
+ log.debug("======= 接收到通知 =========");
|
|
|
+ // 获取请求头信息
|
|
|
+ SignatureHeader signatureHeader = WeixinNotifyUtils.getSignatureHeader(request);
|
|
|
+ // 将请求体json字符串转换为实体
|
|
|
+ OriginNotifyResponse notifyResponse = new GsonBuilder().create().fromJson(notifyData, OriginNotifyResponse.class);
|
|
|
+ // 支付成功通知
|
|
|
+ if ("TRANSACTION.SUCCESS".equals(notifyResponse.getEventType())) {
|
|
|
+ // 获取锁
|
|
|
+ if (orderLock.tryLock()) {
|
|
|
+ try {
|
|
|
+ // 解析支付结果通知
|
|
|
+ WxPayNotifyV3Result result = wxPayService.parseOrderNotifyV3Result(notifyData, signatureHeader);
|
|
|
+ // TODO 此处根据返回结果处理订单信息
|
|
|
+ log.debug("支付成功 ---> orderNo:" + result.getResult().getOutTradeNo());
|
|
|
+ // 返回成功(无需数据,系统状态码为200即可)
|
|
|
+ return AjaxResult.success();
|
|
|
+ } catch (Exception e) {
|
|
|
+ // 支付结果解析异常/订单处理异常
|
|
|
+ log.error("支付通知处理异常:", e);
|
|
|
+ response.setStatus(500);// 支付成功通知处理失败时需要将状态码修改为5xx/4xx,微信才会重新发送回调
|
|
|
+ return AjaxResult.error();
|
|
|
+ } finally {
|
|
|
+ // 释放锁
|
|
|
+ orderLock.unlock();
|
|
|
+ }
|
|
|
+ } else {
|
|
|
+ // 锁获取失败,返回异常,等待下次消息
|
|
|
+ response.setStatus(503);// 支付成功通知处理失败时需要将状态码修改为5xx/4xx,微信才会重新发送回调
|
|
|
+ return AjaxResult.error();
|
|
|
+ }
|
|
|
+ }
|
|
|
+ return AjaxResult.success();
|
|
|
+ }
|
|
|
}
|