Commit cfe0f8bdc0d7f074113e3cf11cb61bc0c0b838fa

Authored by 陈威
1 parent 9346961f
Exists in dev

解决重复支付问题

backend/base/src/main/java/com/hotent/base/conf/WebSecurityConfig.java
... ... @@ -160,7 +160,8 @@ public class WebSecurityConfig extends WebSecurityConfigurerAdapter {
160 160 .antMatchers("/fileUpload").permitAll()
161 161 .antMatchers("/deleteFile").permitAll()
162 162 .antMatchers("/ueditor/**", "/apiManager/getToken").permitAll()
163   - .antMatchers("/user/wxPay/**").permitAll()
  163 + .antMatchers("/user/wxPay/handlePaySuccessCallback").permitAll()
  164 + .antMatchers("/user/wxPay/handleRefundSuccessCallback").permitAll()
164 165 .anyRequest().authenticated()
165 166 .accessDecisionManager(accessDecisionManager());
166 167  
... ...
backend/lpg-user/src/main/java/com/hotent/lpg/user/controller/DdConroller.java
... ... @@ -2,7 +2,11 @@ package com.hotent.lpg.user.controller;
2 2  
3 3 import cn.hutool.core.bean.BeanUtil;
4 4 import com.baomidou.mybatisplus.core.metadata.IPage;
  5 +import com.baomidou.mybatisplus.core.toolkit.Wrappers;
5 6 import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
  7 +import com.github.binarywang.wxpay.bean.order.WxPayMpOrderResult;
  8 +import com.github.binarywang.wxpay.bean.result.WxPayOrderQueryResult;
  9 +import com.github.binarywang.wxpay.bean.result.WxPayUnifiedOrderResult;
6 10 import com.hotent.base.model.CommonResult;
7 11 import com.hotent.lpg.common.enums.DdlyEnum;
8 12 import com.hotent.lpg.common.enums.DdztEnum;
... ... @@ -90,51 +94,6 @@ public class DdConroller {
90 94 return CommonResult.<String>ok();
91 95 }
92 96  
93   -// /**
94   -// * 创建订单
95   -// *
96   -// * @param request
97   -// * @return
98   -// * @throws Exception
99   -// * @throws
100   -// */
101   -// @PostMapping(value = "/save")
102   -// @ApiOperation(value = "创建订单", httpMethod = "POST", notes = "创建订单")
103   -// public CommonResult createOrder(@ApiParam(name = "CreateOrderRequest", value = "创建订单请求对象", required = true) @RequestBody DdDto request) throws Exception {
104   -// WHydz hydz = hydzDao.selectOneByHyIdAndDzId(ContextUtil.getCurrentUserId(), request.getHydzId());
105   -// if (BeanUtil.isEmpty(hydz)){
106   -// throw new RuntimeException("未查询到地址信息。");
107   -// }
108   -// WHyxx hyxx = wHyxxManager.getUseridByInfo(ContextUtil.getCurrentUserId());
109   -// if (BeanUtil.isEmpty(hyxx)){
110   -// throw new RuntimeException("未查询会员信息。");
111   -// }
112   -// request.setShlxr(hydz.getFLxr());
113   -// request.setShlxrdh(hydz.getFLxrdh());
114   -// request.setShsf(hydz.getFLxrsf());
115   -// request.setShs(hydz.getFLxrs());
116   -// request.setShq(hydz.getFLxrq());
117   -// request.setShjd(hydz.getFLxrjd());
118   -// request.setShxxdz(hydz.getFLxrxxdz());
119   -// request.setJd(hydz.getFJd());
120   -// request.setWd(hydz.getFWd());
121   -//
122   -// request.setSfhy("是");
123   -// request.setHydh(hyxx.getFSjh()); //账号就是电话
124   -// request.setHyid(hyxx.getFUserid());
125   -// request.setHymc(hyxx.getFXm());
126   -// request.setHylx(hyxx.getFHylx());
127   -// request.setSfzh(hyxx.getFSfzh());
128   -// request.setShtysbm(hyxx.getFShtysbm());
129   -//
130   -// request.setXdrlx(UserlxEnum.hy.getInfo());
131   -// request.setXdrid(ContextUtil.getCurrentUserId());
132   -// request.setXdrmc(ContextUtil.getCurrentUser().getFullname());
133   -// request.setDdly(DdlyEnum.xsxd.getInfo());
134   -// WDd order = wDdManager.createOrder(request);
135   -// return CommonResult.ok().value(order);
136   -// }
137   -
138 97 @PostMapping(value = "/add")
139 98 @ApiOperation(value = "创建订单", httpMethod = "POST", notes = "创建订单")
140 99 public CommonResult createOrder(@ApiParam(name = "CreateOrderRequest", value = "创建订单请求对象", required = true) @RequestBody DdDto ddDto) {
... ... @@ -172,9 +131,8 @@ public class DdConroller {
172 131 ddDto.setDdzt(DdztEnum.CREATED.getCode());
173 132 WDd order = wDdManager.addOrder(ddDto);
174 133 log.warn("创建订单2:{}", order);
175   - HashMap<String, Object> resultData = wxPayManager.generatePrepayOrder(order, ddDto.getOpenId());
176   - log.warn("创建订单3:{}", resultData);
177   - return CommonResult.ok().value(resultData);
  134 +// WxPayMpOrderResult prepayOrder = wxPayManager.generatePrepayOrder(order.getId(), ddDto.getOpenId(),order.getFZflx());
  135 + return CommonResult.ok().value(order);
178 136 }
179 137  
180 138  
... ...
backend/lpg-user/src/main/java/com/hotent/lpg/user/controller/WxPayController.java
1 1 package com.hotent.lpg.user.controller;
2 2  
3 3  
  4 +import com.github.binarywang.wxpay.bean.result.WxPayOrderQueryResult;
  5 +import com.github.binarywang.wxpay.exception.WxPayException;
  6 +import com.hotent.base.model.CommonResult;
  7 +import com.hotent.lpg.common.model.WDd;
  8 +import com.hotent.lpg.user.manager.DdManager;
4 9 import com.hotent.lpg.user.manager.WxPayManager;
  10 +import io.swagger.annotations.ApiOperation;
5 11 import lombok.AllArgsConstructor;
6 12 import lombok.extern.slf4j.Slf4j;
7 13 import org.springframework.validation.annotation.Validated;
8   -import org.springframework.web.bind.annotation.PostMapping;
9   -import org.springframework.web.bind.annotation.RequestBody;
10   -import org.springframework.web.bind.annotation.RequestMapping;
11   -import org.springframework.web.bind.annotation.RestController;
  14 +import org.springframework.web.bind.annotation.*;
  15 +
  16 +import java.util.HashMap;
12 17  
13 18 @RestController
14 19 @RequestMapping("/user/wxPay/")
... ... @@ -17,6 +22,31 @@ import org.springframework.web.bind.annotation.RestController;
17 22 @Slf4j
18 23 public class WxPayController {
19 24 private WxPayManager wxPayManager;
  25 + private DdManager ddManager;
  26 +
  27 + /**
  28 + * 调用统一下单接口
  29 + *
  30 + * @return
  31 + */
  32 + @PostMapping("/unifiedOrder")
  33 + public CommonResult unifiedOrder(@RequestBody HashMap<String, String> params) throws WxPayException {
  34 + String ddid = String.valueOf(params.get("ddid"));
  35 + String openId = params.get("openId");
  36 + String zflx = params.get("zflx");
  37 + return CommonResult.ok().value(wxPayManager.initiateJsApiPay(ddid, openId, zflx));
  38 + }
  39 +
  40 +
  41 + @GetMapping(value = "/getPrepayOrder")
  42 + @ApiOperation(value = "查询微信支付系统的预支付订单信息", httpMethod = "GET", notes = "查询微信支付系统的预支付订单信息")
  43 + public CommonResult getPrepayOrder(@RequestParam(required = true) String id) throws Exception {
  44 + WxPayOrderQueryResult weChatOrder = wxPayManager.getWxPayOrderQuery(id);
  45 + return CommonResult.ok().value(weChatOrder);
  46 + }
  47 +
  48 +
  49 +
20 50  
21 51 /**
22 52 * 处理支付成功回调
... ...
backend/lpg-user/src/main/java/com/hotent/lpg/user/manager/WxPayManager.java
1 1 package com.hotent.lpg.user.manager;
2 2  
  3 +import com.github.binarywang.wxpay.bean.order.WxPayMpOrderResult;
  4 +import com.github.binarywang.wxpay.bean.result.WxPayOrderCloseResult;
  5 +import com.github.binarywang.wxpay.bean.result.WxPayOrderQueryResult;
  6 +import com.github.binarywang.wxpay.bean.result.WxPayRefundResult;
  7 +import com.github.binarywang.wxpay.bean.result.WxPayUnifiedOrderResult;
  8 +import com.github.binarywang.wxpay.exception.WxPayException;
3 9 import com.hotent.lpg.common.model.WDd;
4 10  
5 11 import java.util.HashMap;
  12 +import java.util.Map;
6 13  
7 14 public interface WxPayManager {
8 15 /**
9 16 * 退款
  17 + *
10 18 * @param ddid
11 19 * @return
12 20 */
13   - String initiateRefundOrder(String ddid);
  21 + WxPayRefundResult initiateRefundOrder(String ddid);
14 22  
15 23 /**
16 24 * 处理退款成功回调
  25 + *
17 26 * @param xmlData
18 27 * @return
19 28 */
... ... @@ -22,6 +31,7 @@ public interface WxPayManager {
22 31  
23 32 /**
24 33 * 处理支付成功回调
  34 + *
25 35 * @param xmlData
26 36 * @return
27 37 */
... ... @@ -30,9 +40,33 @@ public interface WxPayManager {
30 40  
31 41 /**
32 42 * 生成预支付订单
33   - * @param order
  43 + *
  44 + * @param ddid
34 45 * @param openId
35 46 * @return
36 47 */
37   - HashMap<String, Object> generatePrepayOrder(WDd order, String openId);
  48 + WxPayMpOrderResult generatePrepayOrder(String ddid, String openId, String zflx);
  49 +
  50 + /**
  51 + * 如果订单状态为“待支付”,则获取原有的预支付订单信息
  52 + * SUCCESS: 交易支付成功
  53 + * REFUND: 交易已退款
  54 + * NOTPAY : 交易创建,但未支付
  55 + * CLOSED: 交易关闭
  56 + * REVOKED:交易已撤销(仅有服务商接口)
  57 + * USERPAYING: 用户支付中
  58 + * PAYERROR: 支付失败
  59 + * @return
  60 + */
  61 + WxPayOrderQueryResult getWxPayOrderQuery(String id);
  62 +
  63 +
  64 + WxPayMpOrderResult initiateJsApiPay(String ddid, String openId, String zflx) throws WxPayException;
  65 +
  66 +
  67 + /**
  68 + * 取消订单
  69 + * @param id
  70 + */
  71 + WxPayOrderCloseResult cancelOrder(String id);
38 72 }
... ...
backend/lpg-user/src/main/java/com/hotent/lpg/user/manager/impl/DdManagerImpl.java
... ... @@ -9,6 +9,8 @@ import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
9 9 import com.baomidou.mybatisplus.core.metadata.IPage;
10 10 import com.baomidou.mybatisplus.core.toolkit.Wrappers;
11 11 import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
  12 +import com.github.binarywang.wxpay.bean.result.WxPayOrderCloseResult;
  13 +import com.github.binarywang.wxpay.bean.result.WxPayRefundResult;
12 14 import com.hotent.base.id.IdGenerator;
13 15 import com.hotent.base.manager.impl.BaseManagerImpl;
14 16 import com.hotent.base.util.BeanUtils;
... ... @@ -86,19 +88,26 @@ public class DdManagerImpl extends BaseManagerImpl&lt;DdDao, WDd&gt; implements DdMana
86 88 || DdztEnum.SHIPPED.getCode().equals(dd.getFDdzt()))) {
87 89 throw new RuntimeException("订单状态不正确");
88 90 }
89   -
90   -
91 91 if (dd.getFDdly().equals(DdlyEnum.xsxd.getCode()) && dd.getFZffs().equals(DdZffsEnum.WX_PAY.getCode()) && dd.getFSfzf().equals(SysEnum.Y.getCode())) {
92 92 //线上下单+微信支付+已支付 才退款
93   - String shtkdh = wxPayManager.initiateRefundOrder(ddid);
94   - dd.setFDdzt(DdztEnum.REFUNDING.getCode());
95   - dd.setFShtkdh(shtkdh);
96   - dd.setFSftk(SysEnum.N.getCode());
97   - baseMapper.updateById(dd);
98   - }else {
  93 + WxPayRefundResult wxPayRefundResult = wxPayManager.initiateRefundOrder(ddid);
  94 + if ("SUCCESS".equals(wxPayRefundResult.getReturnCode()) && "SUCCESS".equals(wxPayRefundResult.getResultCode())) {
  95 + dd.setFDdzt(DdztEnum.REFUNDING.getCode());
  96 + dd.setFShtkdh(wxPayRefundResult.getOutRefundNo());
  97 + dd.setFSftk(SysEnum.N.getCode());
  98 + baseMapper.updateById(dd);
  99 + }
  100 + } else {
  101 +// WxPayOrderCloseResult wxPayOrderCloseResult = wxPayManager.cancelOrder(dd.getId());
  102 +// if ("SUCCESS".equals(wxPayOrderCloseResult.getReturnCode()) && "SUCCESS".equals(wxPayOrderCloseResult.getResultCode())) {
99 103 dd.setFDdzt(DdztEnum.REFUNDED.getCode());
100 104 dd.setFSftk(SysEnum.N.getCode());
101 105 baseMapper.updateById(dd);
  106 +// } else {
  107 +// String errCode = wxPayOrderCloseResult.getErrCode();
  108 +// String errCodeDes = wxPayOrderCloseResult.getErrCodeDes();
  109 +// throw new RuntimeException("取消订单失败,错误代码: " + errCode + ", 错误描述: " + errCodeDes);
  110 +// }
102 111 }
103 112 //添加服务日志
104 113 // wDdfwrzManager.insertDdfwrz(DdfwlxEnum.qxdd.getCode(), dd.getId());
... ...
backend/lpg-user/src/main/java/com/hotent/lpg/user/manager/impl/WxPayManagerImpl.java
... ... @@ -7,13 +7,22 @@ import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
7 7 import com.baomidou.mybatisplus.core.toolkit.Wrappers;
8 8 import com.github.binarywang.wxpay.bean.notify.WxPayOrderNotifyResult;
9 9 import com.github.binarywang.wxpay.bean.notify.WxPayRefundNotifyResult;
  10 +import com.github.binarywang.wxpay.bean.order.WxPayMpOrderResult;
  11 +import com.github.binarywang.wxpay.bean.request.WxPayOrderCloseRequest;
  12 +import com.github.binarywang.wxpay.bean.request.WxPayOrderQueryRequest;
10 13 import com.github.binarywang.wxpay.bean.request.WxPayRefundRequest;
11 14 import com.github.binarywang.wxpay.bean.request.WxPayUnifiedOrderRequest;
  15 +import com.github.binarywang.wxpay.bean.result.WxPayOrderCloseResult;
  16 +import com.github.binarywang.wxpay.bean.result.WxPayOrderQueryResult;
12 17 import com.github.binarywang.wxpay.bean.result.WxPayRefundResult;
  18 +import com.github.binarywang.wxpay.bean.result.WxPayUnifiedOrderResult;
  19 +import com.github.binarywang.wxpay.config.WxPayConfig;
13 20 import com.github.binarywang.wxpay.exception.WxPayException;
14 21 import com.github.binarywang.wxpay.service.WxPayService;
  22 +import com.github.binarywang.wxpay.util.SignUtils;
15 23 import com.hotent.base.exception.BaseException;
16 24 import com.hotent.base.util.BeanUtils;
  25 +import com.hotent.base.util.StringUtil;
17 26 import com.hotent.lpg.common.enums.DdZffsEnum;
18 27 import com.hotent.lpg.common.enums.DdlyEnum;
19 28 import com.hotent.lpg.common.enums.DdztEnum;
... ... @@ -50,7 +59,10 @@ import java.io.StringWriter;
50 59 import java.math.BigDecimal;
51 60 import java.rmi.ServerError;
52 61 import java.time.LocalDateTime;
  62 +import java.util.Collections;
53 63 import java.util.HashMap;
  64 +import java.util.Map;
  65 +import java.util.UUID;
54 66  
55 67 @Service
56 68 @Slf4j
... ... @@ -66,6 +78,7 @@ public class WxPayManagerImpl implements WxPayManager {
66 78 @Resource
67 79 private CzzfpzDao czzfpzDao;
68 80  
  81 +
69 82 /**
70 83 * 发起退款请求
71 84 *
... ... @@ -73,7 +86,7 @@ public class WxPayManagerImpl implements WxPayManager {
73 86 * @return
74 87 */
75 88 @Override
76   - public String initiateRefundOrder(String ddid) {
  89 + public WxPayRefundResult initiateRefundOrder(String ddid) {
77 90 // 1. 查询订单信息
78 91 WDd wDd = ddDao.selectById(ddid);
79 92 if (!DdztEnum.PAID.getCode().equals(wDd.getFDdzt())) {
... ... @@ -90,22 +103,43 @@ public class WxPayManagerImpl implements WxPayManager {
90 103 // 3. 初始化微信支付服务
91 104 WxPayService wxPayService = WxPayConfiguration.getPayService(wCzzfpz);
92 105 try {
93   - // 4. 调用微信退款接口
94   - // 这里需要构造退款请求对象,具体参数根据实际情况填写
95   - // 注意:这里需要根据实际的微信支付SDK版本和退款接口文档来调整
96   - // 示例代码可能需要根据实际情况修改
97   - String tkdh = RandomUtil.randomString(32);
98   - WxPayRefundRequest refundRequest = new WxPayRefundRequest();
99   - refundRequest.setTransactionId(wDd.getFZfdh());
100   - refundRequest.setOutTradeNo(wDd.getFDddh()); // 订单号
101   - refundRequest.setOutRefundNo(RandomUtil.randomString(32)); // 退款单号
102   - refundRequest.setTotalFee(wDd.getFDdje().multiply(new BigDecimal(100)).intValue()); // 订单总金额
103   - refundRequest.setRefundFee(wDd.getFDdje().multiply(new BigDecimal(100)).intValue()); // 退款金额
104   - refundRequest.setNotifyUrl(hostUrl + "/user/wxPay/handleRefundSuccessCallback");
105   - // 发起退款请求
106   - Object payment = wxPayService.refund(refundRequest);
107   - // 返回结果
108   - return tkdh;
  106 + // 4.查询微信支付系统的预支付订单信息
  107 + WxPayOrderQueryRequest request = new WxPayOrderQueryRequest();
  108 + request.setOutTradeNo(wDd.getFDddh());
  109 + WxPayOrderQueryResult wxPayOrderQueryResult = wxPayService.queryOrder(request);
  110 + if ("SUCCESS".equals(wxPayOrderQueryResult.getReturnCode()) && "SUCCESS".equals(wxPayOrderQueryResult.getResultCode())) {
  111 + String tradeState = wxPayOrderQueryResult.getTradeState();
  112 + switch (tradeState) {
  113 + case "SUCCESS":
  114 + // 4. 调用微信退款接口
  115 + WxPayRefundRequest refundRequest = new WxPayRefundRequest();
  116 + refundRequest.setTransactionId(wDd.getFZfdh());
  117 + refundRequest.setOutTradeNo(wDd.getFDddh()); // 订单号
  118 + refundRequest.setOutRefundNo(RandomUtil.randomString(32)); // 退款单号
  119 + refundRequest.setTotalFee(wDd.getFDdje().multiply(new BigDecimal(100)).intValue()); // 订单总金额
  120 + refundRequest.setRefundFee(wDd.getFDdje().multiply(new BigDecimal(100)).intValue()); // 退款金额
  121 + refundRequest.setNotifyUrl(hostUrl + "/user/wxPay/handleRefundSuccessCallback");
  122 + // 返回结果
  123 + return wxPayService.refund(refundRequest);
  124 + case "TRADE_CLOSED":
  125 + throw new RuntimeException("订单已关闭");
  126 + case "NOTPAY":
  127 + throw new RuntimeException("订单未支付");
  128 + case "REFUND":
  129 + throw new RuntimeException("订单已退款");
  130 + case "REFUNDCLOSED":
  131 + throw new RuntimeException("退款关闭");
  132 + case "REVERSAL":
  133 + throw new RuntimeException("交易撤销");
  134 + case "USERPAYING":
  135 + throw new RuntimeException("用户支付中");
  136 + case "PAYERROR":
  137 + throw new RuntimeException("支付失败");
  138 + default:
  139 + throw new RuntimeException("未知状态:" + tradeState);
  140 + }
  141 + }
  142 + throw new RuntimeException("订单状态异常");
109 143 } catch (WxPayException e) {
110 144 log.error("退款失败: {}", e.getErrCodeDes(), e);
111 145 throw new RuntimeException("退款失败: " + e.getErrCodeDes());
... ... @@ -132,10 +166,7 @@ public class WxPayManagerImpl implements WxPayManager {
132 166 String appid = rs.getAppid();
133 167 String mchId = rs.getMchId();
134 168 // 从数据库中查询对应的应用配置信息
135   - WCzzfpz wCzzfpz = czzfpzDao.selectOne(Wrappers.<WCzzfpz>lambdaQuery()
136   - .eq(WCzzfpz::getFAppid, appid)
137   - .eq(WCzzfpz::getFMchid, mchId)
138   - .last("LIMIT 1"));
  169 + WCzzfpz wCzzfpz = czzfpzDao.selectOne(Wrappers.<WCzzfpz>lambdaQuery().eq(WCzzfpz::getFAppid, appid).eq(WCzzfpz::getFMchid, mchId).last("LIMIT 1"));
139 170 // 如果没有找到对应的配置信息,则抛出异常
140 171 if (wCzzfpz == null) {
141 172 throw new BaseException("退款失败,请联系管理员。");
... ... @@ -153,15 +184,13 @@ public class WxPayManagerImpl implements WxPayManager {
153 184 String transactionId = reqInfo.getTransactionId();
154 185 String outTradeNo = reqInfo.getOutTradeNo();
155 186 // 从数据库中查询订单信息
156   - WDd wDd = ddDao.selectOne(Wrappers.<WDd>lambdaQuery()
157   - .eq(WDd::getFZfdh, transactionId)
158   - .eq(WDd::getFDddh, outTradeNo));
  187 + WDd wDd = ddDao.selectOne(Wrappers.<WDd>lambdaQuery().eq(WDd::getFZfdh, transactionId).eq(WDd::getFDddh, outTradeNo));
159 188 // 如果没有查询到订单,则生成失败响应并返回
160 189 if (wDd == null) {
161 190 return generateXmlResponse("FAIL", "未查询到订单", outTradeNo);
162 191 }
163 192 // 如果订单已经退款,则生成失败响应并返回
164   - if (wDd.getFSftk().equals(SysEnum.Y.getCode())) {
  193 + if (StringUtil.isEmpty(wDd.getFSftk()) || wDd.getFSftk().equals(SysEnum.Y.getCode())) {
165 194 return generateXmlResponse("FAIL", "订单已退款", outTradeNo);
166 195 }
167 196 // 更新订单状态为已退款,并记录相关信息
... ... @@ -201,6 +230,10 @@ public class WxPayManagerImpl implements WxPayManager {
201 230 String outTradeNo = extractValueFromXML(xmlData, "out_trade_no");
202 231 //先用订单号找到订单
203 232 WDd wDd = ddDao.selectOne(new LambdaQueryWrapper<WDd>().eq(WDd::getFDddh, outTradeNo));
  233 + if (wDd == null) {
  234 + log.warn("订单不存在: {}", wDd);
  235 + return generateXmlResponse("FAIL", "订单不存在", wDd.getFDddh());
  236 + }
204 237 //在用 场站信息 拿到场站对应得支付配置
205 238 WCzzfpz wCzzfpz = czzfpzDao.selectOne(Wrappers.<WCzzfpz>lambdaQuery().eq(WCzzfpz::getFCzid, wDd.getFCzid()).eq(WCzzfpz::getFZflx, wDd.getFZffs()));
206 239 WxPayService wxPayService = WxPayConfiguration.getPayService(wCzzfpz);
... ... @@ -247,19 +280,20 @@ public class WxPayManagerImpl implements WxPayManager {
247 280 /**
248 281 * 生成预支付订单
249 282 *
250   - * @param wDd
251   - * @param openId
252 283 * @return
253 284 */
254 285 @Override
255   - public HashMap<String, Object> generatePrepayOrder(WDd wDd, String openId) {
  286 + public WxPayMpOrderResult generatePrepayOrder(String ddid, String openId, String zflx) {
256 287 try {
  288 + WDd wDd = ddDao.selectById(ddid);
  289 + if (BeanUtils.isEmpty(wDd)) {
  290 + throw new RuntimeException("订单不存在");
  291 + }
257 292 WCzzfpz wCzzfpz = czzfpzDao.selectOne(Wrappers.<WCzzfpz>lambdaQuery().eq(WCzzfpz::getFCzid, wDd.getFCzid()).eq(WCzzfpz::getFZflx, wDd.getFZffs()));
258   - if (BeanUtils.isEmpty(wCzzfpz) || wCzzfpz == null) {
  293 + if (BeanUtils.isEmpty(wCzzfpz)) {
259 294 throw new RuntimeException("支付配置不存在");
260 295 }
261   - String tradeType = wDd.getFZflx();
262   - if (StrUtil.isBlank(tradeType)) {
  296 + if (StrUtil.isBlank(zflx)) {
263 297 throw new RuntimeException("支付方式错误");
264 298 }
265 299 WxPayUnifiedOrderRequest wxPayUnifiedOrderRequest = new WxPayUnifiedOrderRequest();
... ... @@ -268,7 +302,7 @@ public class WxPayManagerImpl implements WxPayManager {
268 302 wxPayUnifiedOrderRequest.setBody(wDd.getFDddh());
269 303 wxPayUnifiedOrderRequest.setOutTradeNo(wDd.getFDddh());
270 304 wxPayUnifiedOrderRequest.setTotalFee(wDd.getFDdje().multiply(new BigDecimal(100)).intValue());
271   - wxPayUnifiedOrderRequest.setTradeType(tradeType);
  305 + wxPayUnifiedOrderRequest.setTradeType(zflx);
272 306 JSONObject scene_info = new JSONObject();
273 307 scene_info.put("id", "LPG");
274 308 scene_info.put("name", "燃气");
... ... @@ -292,12 +326,7 @@ public class WxPayManagerImpl implements WxPayManager {
292 326 wxPayUnifiedOrderRequest.setSceneInfo(null);
293 327 }
294 328 WxPayService wxPayService = WxPayConfiguration.getPayService(wCzzfpz);
295   - Object payment = wxPayService.createOrder(wxPayUnifiedOrderRequest);
296   - HashMap<String, Object> resultData = new HashMap<String, Object>();
297   - resultData.put("payment", payment);
298   - resultData.put("ddid", wDd.getId());
299   - resultData.put("dddh", wDd.getFDddh());
300   - return resultData;
  329 + return wxPayService.createOrder(wxPayUnifiedOrderRequest);
301 330 } catch (WxPayException e) {
302 331 if ("INVALID_REQUEST".equals(e.getErrCode())) {
303 332 throw new RuntimeException("订单号重复,请重新下单");
... ... @@ -306,6 +335,148 @@ public class WxPayManagerImpl implements WxPayManager {
306 335 }
307 336 }
308 337  
  338 +
  339 + /**
  340 + * 获取订单状态
  341 + *
  342 + * @return
  343 + */
  344 + @Override
  345 + public WxPayOrderQueryResult getWxPayOrderQuery(String ddid) {
  346 + //先找到订单
  347 + WDd wDd = ddDao.selectById(ddid);
  348 + if (wDd == null) {
  349 + throw new RuntimeException("订单不存在");
  350 + }
  351 + WCzzfpz wCzzfpz = czzfpzDao.selectOne(Wrappers.<WCzzfpz>lambdaQuery().eq(WCzzfpz::getFCzid, wDd.getFCzid()).eq(WCzzfpz::getFZflx, wDd.getFZffs()));
  352 + if (BeanUtils.isEmpty(wCzzfpz)) {
  353 + throw new RuntimeException("支付配置不存在");
  354 + }
  355 + // 查询微信支付系统的预支付订单信息
  356 + WxPayOrderQueryRequest request = new WxPayOrderQueryRequest();
  357 + request.setOutTradeNo(wDd.getFDddh());
  358 + WxPayService wxPayService = WxPayConfiguration.getPayService(wCzzfpz);
  359 + try {
  360 + return wxPayService.queryOrder(request);
  361 + } catch (WxPayException e) {
  362 + throw new RuntimeException("查询预支付订单失败:" + e.getMessage());
  363 + }
  364 + }
  365 +
  366 + @Override
  367 + public WxPayMpOrderResult initiateJsApiPay(String ddid, String openId, String zflx) throws WxPayException {
  368 + // 1.获取订单
  369 + WDd wDd = ddDao.selectById(ddid);
  370 + if (BeanUtils.isEmpty(wDd)) {
  371 + throw new RuntimeException("订单不存在");
  372 + }
  373 + // 2. 获取支付配置
  374 + WCzzfpz wCzzfpz = czzfpzDao.selectOne(Wrappers.<WCzzfpz>lambdaQuery().eq(WCzzfpz::getFCzid, wDd.getFCzid()).eq(WCzzfpz::getFZflx, wDd.getFZffs()));
  375 + // 3. 初始化微信支付服务
  376 + WxPayUnifiedOrderRequest wxPayUnifiedOrderRequest = new WxPayUnifiedOrderRequest();
  377 + wxPayUnifiedOrderRequest.setAppid(wCzzfpz.getFAppid());
  378 + wxPayUnifiedOrderRequest.setOpenid(null);
  379 + wxPayUnifiedOrderRequest.setBody(wDd.getFDddh());
  380 + wxPayUnifiedOrderRequest.setOutTradeNo(wDd.getFDddh());
  381 + wxPayUnifiedOrderRequest.setTotalFee(wDd.getFDdje().multiply(new BigDecimal(100)).intValue());
  382 + wxPayUnifiedOrderRequest.setTradeType(zflx);
  383 + JSONObject scene_info = new JSONObject();
  384 + scene_info.put("id", "LPG");
  385 + scene_info.put("name", "燃气");
  386 + wxPayUnifiedOrderRequest.setSceneInfo(scene_info.toString());
  387 + wxPayUnifiedOrderRequest.setNotifyUrl(hostUrl + "/user/wxPay/handlePaySuccessCallback"); // 支付回调地址,开放不用登录
  388 + wxPayUnifiedOrderRequest.setSpbillCreateIp("127.0.0.1");
  389 + // trade_type=APP时 移动应用内的支付场景
  390 + if ("APP".equals(wxPayUnifiedOrderRequest.getTradeType())) {
  391 + wxPayUnifiedOrderRequest.setAppid(wCzzfpz.getFAppid());
  392 + }
  393 + // trade_type=NATIVE时 线下消费场景
  394 + if ("NATIVE".equals(wxPayUnifiedOrderRequest.getTradeType())) {
  395 + wxPayUnifiedOrderRequest.setProductId(wxPayUnifiedOrderRequest.getOutTradeNo());
  396 + }
  397 + // 公众号内或者微信内的网页支付
  398 + if ("JSAPI".equals(wxPayUnifiedOrderRequest.getTradeType())) {
  399 + wxPayUnifiedOrderRequest.setOpenid(openId);
  400 + }
  401 + // 手机浏览器中的支付场景
  402 + if ("MWEB".equals(wxPayUnifiedOrderRequest.getTradeType())) {
  403 + wxPayUnifiedOrderRequest.setSceneInfo(null);
  404 + }
  405 + WxPayService wxPayService = WxPayConfiguration.getPayService(wCzzfpz);
  406 + //创建并获取预支付订单
  407 + WxPayUnifiedOrderResult wxPayUnifiedOrderResult = wxPayService.unifiedOrder(wxPayUnifiedOrderRequest);
  408 + if ("SUCCESS".equals(wxPayUnifiedOrderResult.getReturnCode()) && "SUCCESS".equals(wxPayUnifiedOrderResult.getResultCode())) {
  409 + //生成唤起微信支付参数
  410 + WxPayConfig config = wxPayService.getConfig();
  411 + String prepayId = wxPayUnifiedOrderResult.getPrepayId();
  412 + String signType = "MD5";
  413 + // 查询订单状态
  414 + WxPayOrderQueryRequest queryRequest = new WxPayOrderQueryRequest();
  415 + queryRequest.setAppid(config.getAppId());
  416 + queryRequest.setMchId(config.getMchId());
  417 + queryRequest.setOutTradeNo(wDd.getFDddh()); // 假设 orderId 是订单号
  418 + WxPayOrderQueryResult queryResult = wxPayService.queryOrder(queryRequest);
  419 + if ("SUCCESS".equals(queryResult.getReturnCode()) && "SUCCESS".equals(queryResult.getResultCode())) {
  420 + String tradeState = queryResult.getTradeState();
  421 + if ("SUCCESS".equals(tradeState)) {
  422 + // 订单已支付
  423 + throw new RuntimeException("订单已支付。");
  424 + } else if ("NOTPAY".equals(tradeState)) {
  425 + // 订单未支付
  426 + WxPayMpOrderResult wxPayMpOrderResult = WxPayMpOrderResult.builder().
  427 + appId(wxPayUnifiedOrderResult.getAppid())
  428 + .timeStamp(String.valueOf(System.currentTimeMillis() / 1000L))
  429 + .nonceStr(UUID.randomUUID().toString().replace("-", ""))
  430 + .packageValue("prepay_id=" + prepayId)
  431 + .signType(signType).build();
  432 + wxPayMpOrderResult.setPaySign(SignUtils.createSign(wxPayMpOrderResult, signType, config.getMchKey(), (String[]) null));
  433 + return wxPayMpOrderResult;
  434 + } else {
  435 + // 其他状态
  436 + throw new RuntimeException("订单已取消或过期,请重新下单。");
  437 + }
  438 + } else {
  439 + // 查询失败
  440 + String errCode = queryResult.getErrCode();
  441 + String errCodeDes = queryResult.getErrCodeDes();
  442 + throw new RuntimeException("查询订单状态失败,错误代码: " + errCode + ", 错误描述: " + errCodeDes);
  443 + }
  444 +
  445 + } else {
  446 + throw new RuntimeException("预支付订单创建失败,请重新下单。");
  447 + }
  448 + }
  449 +
  450 +
  451 + /**
  452 + * 取消订单
  453 + *
  454 + * @param ddid
  455 + */
  456 + public WxPayOrderCloseResult cancelOrder(String ddid) {
  457 + try {
  458 + // 1.获取订单
  459 + WDd wDd = ddDao.selectById(ddid);
  460 + if (BeanUtils.isEmpty(wDd)) {
  461 + throw new RuntimeException("订单不存在");
  462 + }
  463 + // 2. 获取支付配置
  464 + WCzzfpz wCzzfpz = czzfpzDao.selectOne(Wrappers.<WCzzfpz>lambdaQuery().eq(WCzzfpz::getFCzid, wDd.getFCzid()).eq(WCzzfpz::getFZflx, wDd.getFZffs()));
  465 + WxPayService wxPayService = WxPayConfiguration.getPayService(wCzzfpz);
  466 + WxPayOrderCloseRequest closeRequest = new WxPayOrderCloseRequest();
  467 + WxPayConfig config = wxPayService.getConfig();
  468 + closeRequest.setAppid(config.getAppId());
  469 + closeRequest.setMchId(config.getMchId());
  470 + closeRequest.setOutTradeNo(wDd.getFDddh());
  471 + WxPayOrderCloseResult closeResult = wxPayService.closeOrder(closeRequest);
  472 + return closeResult;
  473 + } catch (Exception e) {
  474 + log.error("取消订单时发生错误: {}", e.getMessage(), e);
  475 + throw new RuntimeException("取消订单时发生错误");
  476 + }
  477 + }
  478 +
  479 +
309 480 /**
310 481 * 生成微信回调响应
311 482 *
... ... @@ -373,4 +544,5 @@ public class WxPayManagerImpl implements WxPayManager {
373 544 }
374 545 }
375 546  
  547 +
376 548 }
... ...