Commit 4e2d5446bb03a0c69ac1189982b7bb4f4448e16e
1 parent
29574b70
Exists in
dev
微信h5退款
Showing
13 changed files
with
623 additions
and
403 deletions
Show diff stats
backend/base/src/main/java/com/hotent/base/conf/WebSecurityConfig.java
... | ... | @@ -160,7 +160,7 @@ 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/order/payment/notifyOrder").permitAll() | |
163 | + .antMatchers("/user/wxPay/**").permitAll() | |
164 | 164 | .anyRequest().authenticated() |
165 | 165 | .accessDecisionManager(accessDecisionManager()); |
166 | 166 | ... | ... |
backend/lpg-common/src/main/java/com/hotent/lpg/common/enums/DdztEnum.java
backend/lpg-common/src/main/java/com/hotent/lpg/common/model/WCzzfpz.java
... | ... | @@ -2,6 +2,7 @@ package com.hotent.lpg.common.model; |
2 | 2 | |
3 | 3 | import com.baomidou.mybatisplus.annotation.IdType; |
4 | 4 | import com.hotent.base.entity.BaseModel; |
5 | +import com.baomidou.mybatisplus.extension.activerecord.Model; | |
5 | 6 | import com.baomidou.mybatisplus.annotation.TableId; |
6 | 7 | import com.baomidou.mybatisplus.annotation.TableField; |
7 | 8 | import java.io.Serializable; |
... | ... | @@ -11,8 +12,9 @@ import com.fasterxml.jackson.annotation.JsonProperty; |
11 | 12 | /** |
12 | 13 | * 厂站支付配置 |
13 | 14 | * |
14 | - * @author cw | |
15 | - * @since 2024-09-04 | |
15 | + * @company | |
16 | + * @author 超级管理员 | |
17 | + * @since 2024-09-06 | |
16 | 18 | */ |
17 | 19 | @ApiModel(value="WCzzfpz对象", description="厂站支付配置") |
18 | 20 | public class WCzzfpz extends BaseModel<WCzzfpz> { |
... | ... | @@ -83,6 +85,21 @@ public class WCzzfpz extends BaseModel<WCzzfpz> { |
83 | 85 | @JsonProperty("fFormDataRev") |
84 | 86 | private Long fFormDataRev; |
85 | 87 | |
88 | + @ApiModelProperty(value = " .p12 格式的密钥文件路径,私钥和证书") | |
89 | + @TableField("F_keyPath") | |
90 | + @JsonProperty("fKeypath") | |
91 | + private String fKeypath; | |
92 | + | |
93 | + @ApiModelProperty(value = "私钥文件路径") | |
94 | + @TableField("F_privateKeyPath") | |
95 | + @JsonProperty("fPrivatekeypath") | |
96 | + private String fPrivatekeypath; | |
97 | + | |
98 | + @ApiModelProperty(value = "私有证书文件路径") | |
99 | + @TableField("F_privateCertPath") | |
100 | + @JsonProperty("fPrivatecertpath") | |
101 | + private String fPrivatecertpath; | |
102 | + | |
86 | 103 | |
87 | 104 | public String getId() { |
88 | 105 | return id; |
... | ... | @@ -175,6 +192,27 @@ public class WCzzfpz extends BaseModel<WCzzfpz> { |
175 | 192 | public void setFFormDataRev(Long fFormDataRev) { |
176 | 193 | this.fFormDataRev = fFormDataRev; |
177 | 194 | } |
195 | + public String getFKeypath() { | |
196 | + return fKeypath; | |
197 | + } | |
198 | + | |
199 | + public void setFKeypath(String fKeypath) { | |
200 | + this.fKeypath = fKeypath; | |
201 | + } | |
202 | + public String getFPrivatekeypath() { | |
203 | + return fPrivatekeypath; | |
204 | + } | |
205 | + | |
206 | + public void setFPrivatekeypath(String fPrivatekeypath) { | |
207 | + this.fPrivatekeypath = fPrivatekeypath; | |
208 | + } | |
209 | + public String getFPrivatecertpath() { | |
210 | + return fPrivatecertpath; | |
211 | + } | |
212 | + | |
213 | + public void setFPrivatecertpath(String fPrivatecertpath) { | |
214 | + this.fPrivatecertpath = fPrivatecertpath; | |
215 | + } | |
178 | 216 | |
179 | 217 | |
180 | 218 | @Override |
... | ... | @@ -185,19 +223,22 @@ public class WCzzfpz extends BaseModel<WCzzfpz> { |
185 | 223 | @Override |
186 | 224 | public String toString() { |
187 | 225 | return "WCzzfpz{" + |
188 | - "id=" + id + | |
189 | - ", refId=" + refId + | |
190 | - ", fQyid=" + fQyid + | |
191 | - ", fCzid=" + fCzid + | |
192 | - ", fQymc=" + fQymc + | |
193 | - ", fCzmc=" + fCzmc + | |
194 | - ", fZflx=" + fZflx + | |
195 | - ", fAppid=" + fAppid + | |
196 | - ", fMchid=" + fMchid + | |
197 | - ", fMchkey=" + fMchkey + | |
198 | - ", fCertserialno=" + fCertserialno + | |
199 | - ", fApiv3key=" + fApiv3key + | |
200 | - ", fFormDataRev=" + fFormDataRev + | |
201 | - "}"; | |
226 | + "id=" + id + | |
227 | + ", refId=" + refId + | |
228 | + ", fQyid=" + fQyid + | |
229 | + ", fCzid=" + fCzid + | |
230 | + ", fQymc=" + fQymc + | |
231 | + ", fCzmc=" + fCzmc + | |
232 | + ", fZflx=" + fZflx + | |
233 | + ", fAppid=" + fAppid + | |
234 | + ", fMchid=" + fMchid + | |
235 | + ", fMchkey=" + fMchkey + | |
236 | + ", fCertserialno=" + fCertserialno + | |
237 | + ", fApiv3key=" + fApiv3key + | |
238 | + ", fFormDataRev=" + fFormDataRev + | |
239 | + ", fKeypath=" + fKeypath + | |
240 | + ", fPrivatekeypath=" + fPrivatekeypath + | |
241 | + ", fPrivatecertpath=" + fPrivatecertpath + | |
242 | + "}"; | |
202 | 243 | } |
203 | 244 | } | ... | ... |
backend/lpg-common/src/main/java/com/hotent/lpg/common/model/WDd.java
... | ... | @@ -269,6 +269,31 @@ public class WDd extends BaseModel<WDd> { |
269 | 269 | private String fZfdh; |
270 | 270 | |
271 | 271 | |
272 | + @ApiModelProperty(value = "是否退款(是,否)") | |
273 | + @TableField("F_sftk") | |
274 | + @JsonProperty("fSftk") | |
275 | + private String fSftk; | |
276 | + | |
277 | + | |
278 | + @ApiModelProperty(value = "退款单号") | |
279 | + @TableField("F_tkdh") | |
280 | + @JsonProperty("fTkdh") | |
281 | + private String fTkdh; | |
282 | + | |
283 | + @ApiModelProperty(value = "商户退款单号") | |
284 | + @TableField("F_shtkdh") | |
285 | + @JsonProperty("fShtkdh") | |
286 | + private String fShtkdh; | |
287 | + | |
288 | + | |
289 | + @ApiModelProperty(value = "退款时间") | |
290 | + @TableField("F_tksj") | |
291 | + @JsonProperty("fTksj") | |
292 | + private LocalDateTime fTksj; | |
293 | + | |
294 | + | |
295 | + | |
296 | + | |
272 | 297 | /** |
273 | 298 | * 订单详情 |
274 | 299 | */ | ... | ... |
backend/lpg-user/src/main/java/com/hotent/lpg/user/controller/DdConroller.java
... | ... | @@ -5,6 +5,7 @@ import com.baomidou.mybatisplus.core.metadata.IPage; |
5 | 5 | import com.baomidou.mybatisplus.extension.plugins.pagination.Page; |
6 | 6 | import com.hotent.base.model.CommonResult; |
7 | 7 | import com.hotent.lpg.common.enums.DdlyEnum; |
8 | +import com.hotent.lpg.common.enums.DdztEnum; | |
8 | 9 | import com.hotent.lpg.common.enums.UserlxEnum; |
9 | 10 | import com.hotent.lpg.common.model.WDd; |
10 | 11 | import com.hotent.lpg.common.model.WHydz; |
... | ... | @@ -13,16 +14,20 @@ import com.hotent.lpg.user.dao.HydzDao; |
13 | 14 | import com.hotent.lpg.user.dto.DdDto; |
14 | 15 | import com.hotent.lpg.user.manager.DdManager; |
15 | 16 | import com.hotent.lpg.user.manager.HyxxManager; |
17 | +import com.hotent.lpg.user.manager.WxPayManager; | |
16 | 18 | import com.hotent.uc.util.ContextUtil; |
17 | 19 | import io.swagger.annotations.ApiOperation; |
18 | 20 | import io.swagger.annotations.ApiParam; |
21 | +import lombok.extern.slf4j.Slf4j; | |
19 | 22 | import org.springframework.beans.factory.annotation.Autowired; |
20 | 23 | import org.springframework.validation.annotation.Validated; |
21 | 24 | import org.springframework.web.bind.annotation.*; |
22 | 25 | |
23 | 26 | import javax.annotation.Resource; |
27 | +import java.util.HashMap; | |
24 | 28 | import java.util.List; |
25 | 29 | |
30 | +@Slf4j | |
26 | 31 | @RestController |
27 | 32 | //@RequestMapping("/customer/dd/") |
28 | 33 | @RequestMapping("/user/order/") |
... | ... | @@ -36,6 +41,8 @@ public class DdConroller { |
36 | 41 | private HydzDao hydzDao; |
37 | 42 | @Resource |
38 | 43 | private HyxxManager wHyxxManager; |
44 | + @Resource | |
45 | + private WxPayManager wxPayManager; | |
39 | 46 | |
40 | 47 | |
41 | 48 | /** |
... | ... | @@ -82,49 +89,92 @@ public class DdConroller { |
82 | 89 | return CommonResult.<String>ok(); |
83 | 90 | } |
84 | 91 | |
85 | - /** | |
86 | - * 创建订单 | |
87 | - * | |
88 | - * @param request | |
89 | - * @return | |
90 | - * @throws Exception | |
91 | - * @throws | |
92 | - */ | |
93 | - @PostMapping(value = "/save") | |
92 | +// /** | |
93 | +// * 创建订单 | |
94 | +// * | |
95 | +// * @param request | |
96 | +// * @return | |
97 | +// * @throws Exception | |
98 | +// * @throws | |
99 | +// */ | |
100 | +// @PostMapping(value = "/save") | |
101 | +// @ApiOperation(value = "创建订单", httpMethod = "POST", notes = "创建订单") | |
102 | +// public CommonResult createOrder(@ApiParam(name = "CreateOrderRequest", value = "创建订单请求对象", required = true) @RequestBody DdDto request) throws Exception { | |
103 | +// WHydz hydz = hydzDao.selectOneByHyIdAndDzId(ContextUtil.getCurrentUserId(), request.getHydzId()); | |
104 | +// if (BeanUtil.isEmpty(hydz)){ | |
105 | +// throw new RuntimeException("未查询到地址信息。"); | |
106 | +// } | |
107 | +// WHyxx hyxx = wHyxxManager.getUseridByInfo(ContextUtil.getCurrentUserId()); | |
108 | +// if (BeanUtil.isEmpty(hyxx)){ | |
109 | +// throw new RuntimeException("未查询会员信息。"); | |
110 | +// } | |
111 | +// request.setShlxr(hydz.getFLxr()); | |
112 | +// request.setShlxrdh(hydz.getFLxrdh()); | |
113 | +// request.setShsf(hydz.getFLxrsf()); | |
114 | +// request.setShs(hydz.getFLxrs()); | |
115 | +// request.setShq(hydz.getFLxrq()); | |
116 | +// request.setShjd(hydz.getFLxrjd()); | |
117 | +// request.setShxxdz(hydz.getFLxrxxdz()); | |
118 | +// request.setJd(hydz.getFJd()); | |
119 | +// request.setWd(hydz.getFWd()); | |
120 | +// | |
121 | +// request.setSfhy("是"); | |
122 | +// request.setHydh(hyxx.getFSjh()); //账号就是电话 | |
123 | +// request.setHyid(hyxx.getFUserid()); | |
124 | +// request.setHymc(hyxx.getFXm()); | |
125 | +// request.setHylx(hyxx.getFHylx()); | |
126 | +// request.setSfzh(hyxx.getFSfzh()); | |
127 | +// request.setShtysbm(hyxx.getFShtysbm()); | |
128 | +// | |
129 | +// request.setXdrlx(UserlxEnum.hy.getInfo()); | |
130 | +// request.setXdrid(ContextUtil.getCurrentUserId()); | |
131 | +// request.setXdrmc(ContextUtil.getCurrentUser().getFullname()); | |
132 | +// request.setDdly(DdlyEnum.xsxd.getInfo()); | |
133 | +// WDd order = wDdManager.createOrder(request); | |
134 | +// return CommonResult.ok().value(order); | |
135 | +// } | |
136 | + | |
137 | + @PostMapping(value = "/add") | |
94 | 138 | @ApiOperation(value = "创建订单", httpMethod = "POST", notes = "创建订单") |
95 | - public CommonResult createOrder(@ApiParam(name = "CreateOrderRequest", value = "创建订单请求对象", required = true) @RequestBody DdDto request) throws Exception { | |
96 | - WHydz hydz = hydzDao.selectOneByHyIdAndDzId(ContextUtil.getCurrentUserId(), request.getHydzId()); | |
97 | - if (BeanUtil.isEmpty(hydz)){ | |
139 | + public CommonResult createOrder(@ApiParam(name = "CreateOrderRequest", value = "创建订单请求对象", required = true) @RequestBody DdDto ddDto) { | |
140 | + log.warn("创建订单1:{}", ddDto); | |
141 | + WHydz hydz = hydzDao.selectOneByHyIdAndDzId(ContextUtil.getCurrentUserId(), ddDto.getHydzId()); | |
142 | + if (BeanUtil.isEmpty(hydz)) { | |
98 | 143 | throw new RuntimeException("未查询到地址信息。"); |
99 | 144 | } |
100 | 145 | WHyxx hyxx = wHyxxManager.getUseridByInfo(ContextUtil.getCurrentUserId()); |
101 | - if (BeanUtil.isEmpty(hyxx)){ | |
146 | + if (BeanUtil.isEmpty(hyxx)) { | |
102 | 147 | throw new RuntimeException("未查询会员信息。"); |
103 | 148 | } |
104 | - request.setShlxr(hydz.getFLxr()); | |
105 | - request.setShlxrdh(hydz.getFLxrdh()); | |
106 | - request.setShsf(hydz.getFLxrsf()); | |
107 | - request.setShs(hydz.getFLxrs()); | |
108 | - request.setShq(hydz.getFLxrq()); | |
109 | - request.setShjd(hydz.getFLxrjd()); | |
110 | - request.setShxxdz(hydz.getFLxrxxdz()); | |
111 | - request.setJd(hydz.getFJd()); | |
112 | - request.setWd(hydz.getFWd()); | |
113 | - | |
114 | - request.setSfhy("是"); | |
115 | - request.setHydh(hyxx.getFSjh()); //账号就是电话 | |
116 | - request.setHyid(hyxx.getFUserid()); | |
117 | - request.setHymc(hyxx.getFXm()); | |
118 | - request.setHylx(hyxx.getFHylx()); | |
119 | - request.setSfzh(hyxx.getFSfzh()); | |
120 | - request.setShtysbm(hyxx.getFShtysbm()); | |
121 | - | |
122 | - request.setXdrlx(UserlxEnum.hy.getInfo()); | |
123 | - request.setXdrid(ContextUtil.getCurrentUserId()); | |
124 | - request.setXdrmc(ContextUtil.getCurrentUser().getFullname()); | |
125 | - request.setDdly(DdlyEnum.xsxd.getInfo()); | |
126 | - WDd order = wDdManager.createOrder(request); | |
127 | - return CommonResult.ok().value(order); | |
149 | + ddDto.setShlxr(hydz.getFLxr()); | |
150 | + ddDto.setShlxrdh(hydz.getFLxrdh()); | |
151 | + ddDto.setShsf(hydz.getFLxrsf()); | |
152 | + ddDto.setShs(hydz.getFLxrs()); | |
153 | + ddDto.setShq(hydz.getFLxrq()); | |
154 | + ddDto.setShjd(hydz.getFLxrjd()); | |
155 | + ddDto.setShxxdz(hydz.getFLxrxxdz()); | |
156 | + ddDto.setJd(hydz.getFJd()); | |
157 | + ddDto.setWd(hydz.getFWd()); | |
158 | + | |
159 | + ddDto.setSfhy("是"); | |
160 | + ddDto.setHydh(hyxx.getFSjh()); //账号就是电话 | |
161 | + ddDto.setHyid(hyxx.getFUserid()); | |
162 | + ddDto.setHymc(hyxx.getFXm()); | |
163 | + ddDto.setHylx(hyxx.getFHylx()); | |
164 | + ddDto.setSfzh(hyxx.getFSfzh()); | |
165 | + ddDto.setShtysbm(hyxx.getFShtysbm()); | |
166 | + | |
167 | + ddDto.setXdrlx(UserlxEnum.hy.getInfo()); | |
168 | + ddDto.setXdrid(ContextUtil.getCurrentUserId()); | |
169 | + ddDto.setXdrmc(ContextUtil.getCurrentUser().getFullname()); | |
170 | + ddDto.setDdly(DdlyEnum.xsxd.getInfo()); | |
171 | + ddDto.setDdzt(DdztEnum.dzf.getInfo()); | |
172 | + WDd order = wDdManager.addOrder(ddDto); | |
173 | + log.warn("创建订单2:{}", order); | |
174 | + HashMap<String, Object> resultData = wxPayManager.generatePrepayOrder(order, ddDto.getOpenId()); | |
175 | + log.warn("创建订单3:{}", resultData); | |
176 | + return CommonResult.ok().value(resultData); | |
128 | 177 | } |
129 | 178 | |
179 | + | |
130 | 180 | } | ... | ... |
backend/lpg-user/src/main/java/com/hotent/lpg/user/controller/PaymentController.java
... | ... | @@ -1,110 +0,0 @@ |
1 | -package com.hotent.lpg.user.controller; | |
2 | - | |
3 | -import cn.hutool.core.bean.BeanUtil; | |
4 | -import com.hotent.base.model.CommonResult; | |
5 | -import com.hotent.lpg.common.enums.DdlyEnum; | |
6 | -import com.hotent.lpg.common.enums.DdztEnum; | |
7 | -import com.hotent.lpg.common.enums.UserlxEnum; | |
8 | -import com.hotent.lpg.common.model.WDd; | |
9 | -import com.hotent.lpg.common.model.WHydz; | |
10 | -import com.hotent.lpg.common.model.WHyxx; | |
11 | -import com.hotent.lpg.user.dao.HydzDao; | |
12 | -import com.hotent.lpg.user.dto.DdDto; | |
13 | -import com.hotent.lpg.user.enums.PayTypeEnum; | |
14 | -import com.hotent.lpg.user.manager.DdManager; | |
15 | -import com.hotent.lpg.user.manager.HyxxManager; | |
16 | -import com.hotent.lpg.user.manager.PaymentManage; | |
17 | -import com.hotent.lpg.user.vo.ResultData; | |
18 | -import com.hotent.uc.util.ContextUtil; | |
19 | -import io.swagger.annotations.ApiOperation; | |
20 | -import io.swagger.annotations.ApiParam; | |
21 | -import lombok.AllArgsConstructor; | |
22 | -import lombok.extern.slf4j.Slf4j; | |
23 | -import org.springframework.beans.factory.annotation.Autowired; | |
24 | -import org.springframework.validation.annotation.Validated; | |
25 | -import org.springframework.web.bind.annotation.*; | |
26 | - | |
27 | -import javax.annotation.Resource; | |
28 | -import java.util.HashMap; | |
29 | - | |
30 | -@RestController | |
31 | -@RequestMapping("/user/order/payment/") | |
32 | -@AllArgsConstructor | |
33 | -@Validated | |
34 | -@Slf4j | |
35 | -public class PaymentController { | |
36 | - private final PaymentManage paymentManage; | |
37 | - | |
38 | - private final DdManager wDdManager; | |
39 | - private final HydzDao hydzDao; | |
40 | - private final HyxxManager wHyxxManager; | |
41 | -// /** | |
42 | -// * 预支付 | |
43 | -// * @param ddid | |
44 | -// * @return | |
45 | -// */ | |
46 | -// @PostMapping("/{ddid}") | |
47 | -// public ResultData pay(@PathVariable("ddid") String ddid) { | |
48 | -// String payType = PayTypeEnum.WX.getName(); // 默认微信 | |
49 | -// return paymentManage.pay(ddid, payType); | |
50 | -// } | |
51 | - | |
52 | - | |
53 | - @PostMapping(value = "/add") | |
54 | - @ApiOperation(value = "创建订单", httpMethod = "POST", notes = "创建订单") | |
55 | - public CommonResult createOrder(@ApiParam(name = "CreateOrderRequest", value = "创建订单请求对象", required = true) @RequestBody DdDto ddDto) throws Exception { | |
56 | - log.warn("创建订单1:{}", ddDto); | |
57 | - WHydz hydz = hydzDao.selectOneByHyIdAndDzId(ContextUtil.getCurrentUserId(), ddDto.getHydzId()); | |
58 | - if (BeanUtil.isEmpty(hydz)){ | |
59 | - throw new RuntimeException("未查询到地址信息。"); | |
60 | - } | |
61 | - WHyxx hyxx = wHyxxManager.getUseridByInfo(ContextUtil.getCurrentUserId()); | |
62 | - if (BeanUtil.isEmpty(hyxx)){ | |
63 | - throw new RuntimeException("未查询会员信息。"); | |
64 | - } | |
65 | - ddDto.setShlxr(hydz.getFLxr()); | |
66 | - ddDto.setShlxrdh(hydz.getFLxrdh()); | |
67 | - ddDto.setShsf(hydz.getFLxrsf()); | |
68 | - ddDto.setShs(hydz.getFLxrs()); | |
69 | - ddDto.setShq(hydz.getFLxrq()); | |
70 | - ddDto.setShjd(hydz.getFLxrjd()); | |
71 | - ddDto.setShxxdz(hydz.getFLxrxxdz()); | |
72 | - ddDto.setJd(hydz.getFJd()); | |
73 | - ddDto.setWd(hydz.getFWd()); | |
74 | - | |
75 | - ddDto.setSfhy("是"); | |
76 | - ddDto.setHydh(hyxx.getFSjh()); //账号就是电话 | |
77 | - ddDto.setHyid(hyxx.getFUserid()); | |
78 | - ddDto.setHymc(hyxx.getFXm()); | |
79 | - ddDto.setHylx(hyxx.getFHylx()); | |
80 | - ddDto.setSfzh(hyxx.getFSfzh()); | |
81 | - ddDto.setShtysbm(hyxx.getFShtysbm()); | |
82 | - | |
83 | - ddDto.setXdrlx(UserlxEnum.hy.getInfo()); | |
84 | - ddDto.setXdrid(ContextUtil.getCurrentUserId()); | |
85 | - ddDto.setXdrmc(ContextUtil.getCurrentUser().getFullname()); | |
86 | - ddDto.setDdly(DdlyEnum.xsxd.getInfo()); | |
87 | - ddDto.setDdzt(DdztEnum.dzf.getInfo()); | |
88 | - WDd order = wDdManager.addOrder(ddDto); | |
89 | - log.warn("创建订单2:{}", order); | |
90 | - HashMap<String,Object> resultData = paymentManage.wxPay(order,ddDto.getOpenId()); | |
91 | - log.warn("创建订单3:{}", resultData); | |
92 | - return CommonResult.ok().value(resultData); | |
93 | - } | |
94 | - | |
95 | - | |
96 | - | |
97 | - | |
98 | - | |
99 | - /** | |
100 | - * 支付回调 | |
101 | - * @return | |
102 | - */ | |
103 | - @PostMapping("/notifyOrder") | |
104 | - public String notifyOrder(@RequestBody String xmlData) { | |
105 | - log.warn("支付回调:{}", xmlData); | |
106 | - String res = paymentManage.notifyOrder(xmlData); | |
107 | - log.warn("处理状态:{}", xmlData); | |
108 | - return xmlData; | |
109 | - } | |
110 | -} |
backend/lpg-user/src/main/java/com/hotent/lpg/user/controller/WxPayController.java
0 → 100644
... | ... | @@ -0,0 +1,47 @@ |
1 | +package com.hotent.lpg.user.controller; | |
2 | + | |
3 | + | |
4 | +import com.hotent.lpg.user.manager.WxPayManager; | |
5 | +import lombok.AllArgsConstructor; | |
6 | +import lombok.extern.slf4j.Slf4j; | |
7 | +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; | |
12 | + | |
13 | +@RestController | |
14 | +@RequestMapping("/user/wxPay/") | |
15 | +@AllArgsConstructor | |
16 | +@Validated | |
17 | +@Slf4j | |
18 | +public class WxPayController { | |
19 | + private WxPayManager wxPayManager; | |
20 | + /** | |
21 | + * 处理支付成功回调 | |
22 | + * @param xmlData | |
23 | + * @return | |
24 | + */ | |
25 | + @PostMapping("/handlePaySuccessCallback") | |
26 | + public String handlePaySuccessCallback(@RequestBody String xmlData) { | |
27 | + log.warn("支付回调:{}", xmlData); | |
28 | + String res = wxPayManager.handlePaySuccessCallback(xmlData); | |
29 | + log.warn("处理状态:{}", xmlData); | |
30 | + return xmlData; | |
31 | + } | |
32 | + | |
33 | + | |
34 | + /** | |
35 | + * 处理退款成功回调 | |
36 | + * @param xmlData | |
37 | + * @return | |
38 | + */ | |
39 | + @PostMapping("/handleRefundSuccessCallback") | |
40 | + public String handleRefundSuccessCallback(@RequestBody String xmlData) { | |
41 | + log.warn("退款回调:{}", xmlData); | |
42 | + String res = wxPayManager.handleRefundSuccessCallback(xmlData); | |
43 | + log.warn("退款状态:{}", xmlData); | |
44 | + return res; | |
45 | + } | |
46 | + | |
47 | +} | ... | ... |
backend/lpg-user/src/main/java/com/hotent/lpg/user/manager/PaymentManage.java
... | ... | @@ -1,16 +0,0 @@ |
1 | -package com.hotent.lpg.user.manager; | |
2 | - | |
3 | - | |
4 | -import com.hotent.lpg.common.model.WDd; | |
5 | -import com.hotent.lpg.user.vo.ResultData; | |
6 | - | |
7 | -import java.util.HashMap; | |
8 | - | |
9 | -public interface PaymentManage { | |
10 | -// ResultData pay(String ddid, String payType); | |
11 | - | |
12 | - String notifyOrder(String xmlData); | |
13 | - | |
14 | - HashMap<String,Object> wxPay(WDd order,String openId); | |
15 | - | |
16 | -} |
backend/lpg-user/src/main/java/com/hotent/lpg/user/manager/WxPayManager.java
0 → 100644
... | ... | @@ -0,0 +1,38 @@ |
1 | +package com.hotent.lpg.user.manager; | |
2 | + | |
3 | +import com.hotent.lpg.common.model.WDd; | |
4 | + | |
5 | +import java.util.HashMap; | |
6 | + | |
7 | +public interface WxPayManager { | |
8 | + /** | |
9 | + * 退款 | |
10 | + * @param ddid | |
11 | + * @return | |
12 | + */ | |
13 | + String initiateRefundOrder(String ddid); | |
14 | + | |
15 | + /** | |
16 | + * 处理退款成功回调 | |
17 | + * @param xmlData | |
18 | + * @return | |
19 | + */ | |
20 | + String handleRefundSuccessCallback(String xmlData); | |
21 | + | |
22 | + | |
23 | + /** | |
24 | + * 处理支付成功回调 | |
25 | + * @param xmlData | |
26 | + * @return | |
27 | + */ | |
28 | + String handlePaySuccessCallback(String xmlData); | |
29 | + | |
30 | + | |
31 | + /** | |
32 | + * 生成预支付订单 | |
33 | + * @param order | |
34 | + * @param openId | |
35 | + * @return | |
36 | + */ | |
37 | + HashMap<String, Object> generatePrepayOrder(WDd order, String openId); | |
38 | +} | ... | ... |
backend/lpg-user/src/main/java/com/hotent/lpg/user/manager/impl/DdManagerImpl.java
... | ... | @@ -19,14 +19,12 @@ import com.hotent.lpg.common.model.WDd; |
19 | 19 | import com.hotent.lpg.common.model.WDdxq; |
20 | 20 | import com.hotent.lpg.common.model.WHyyqjl; |
21 | 21 | import com.hotent.lpg.common.model.WQplx; |
22 | +import com.hotent.lpg.user.dao.CzzfpzDao; | |
22 | 23 | import com.hotent.lpg.user.dao.DdDao; |
23 | 24 | import com.hotent.lpg.user.dao.DdxqDao; |
24 | 25 | import com.hotent.lpg.user.dao.QplxDao; |
25 | 26 | import com.hotent.lpg.user.dto.DdDto; |
26 | -import com.hotent.lpg.user.manager.DdManager; | |
27 | -import com.hotent.lpg.user.manager.DdfwrzManager; | |
28 | -import com.hotent.lpg.user.manager.HyxxManager; | |
29 | -import com.hotent.lpg.user.manager.HyyqjlManager; | |
27 | +import com.hotent.lpg.user.manager.*; | |
30 | 28 | import com.hotent.lpg.user.vo.DdxxVo; |
31 | 29 | import com.hotent.uc.util.ContextUtil; |
32 | 30 | import lombok.extern.slf4j.Slf4j; |
... | ... | @@ -63,6 +61,11 @@ public class DdManagerImpl extends BaseManagerImpl<DdDao, WDd> implements DdMana |
63 | 61 | private HyxxManager wHyxxManager; |
64 | 62 | @Resource |
65 | 63 | private HyyqjlManager wHyyqjlManager; |
64 | + @Resource | |
65 | + private CzzfpzDao czzfpzDao; | |
66 | + @Resource | |
67 | + private WxPayManager wxPayManager; | |
68 | + | |
66 | 69 | @Override |
67 | 70 | public WDd getDetail(String id) { |
68 | 71 | WDd wDd = this.get(id); |
... | ... | @@ -72,20 +75,29 @@ public class DdManagerImpl extends BaseManagerImpl<DdDao, WDd> implements DdMana |
72 | 75 | wDd.setDdxqList(ddxqDao.selectList(new LambdaQueryWrapper<WDdxq>().eq(WDdxq::getfDdid, wDd.getId()))); |
73 | 76 | return wDd; |
74 | 77 | } |
78 | + | |
75 | 79 | @Override |
76 | 80 | public void cancel(String ddid) { |
77 | 81 | WDd dd = baseMapper.selectById(ddid); |
78 | 82 | if (ObjectUtil.isNull(dd)) { |
79 | 83 | throw new RuntimeException("参数错误:订单不存在"); |
80 | 84 | } |
81 | - if (DdztEnum.dps.getInfo().equals(dd.getFDdzt()) || DdztEnum.psz.getInfo().equals(dd.getFDdzt())) { | |
82 | - dd.setFDdzt(DdztEnum.yqx.getInfo()); | |
83 | - baseMapper.updateById(dd); | |
84 | - } else { | |
85 | + if (!(DdztEnum.dps.getInfo().equals(dd.getFDdzt()) || DdztEnum.psz.getInfo().equals(dd.getFDdzt()) || DdztEnum.dzf.getInfo().equals(dd.getFDdzt()))) { | |
85 | 86 | throw new RuntimeException("订单状态不正确"); |
86 | 87 | } |
88 | +// dd.setFDdzt(DdztEnum.yqx.getInfo()); | |
89 | +// baseMapper.updateById(dd); | |
90 | + | |
91 | + if (dd.getFDdly().equals("线上下单") && dd.getFZffs().equals("微信") && dd.getFSfzf().equals("是")) { | |
92 | + //线上下单+微信支付+已支付 才退款 | |
93 | + String shtkdh = wxPayManager.initiateRefundOrder(ddid); | |
94 | + dd.setFDdzt(DdztEnum.tkz.getInfo()); | |
95 | + dd.setFShtkdh(shtkdh); | |
96 | + dd.setFSftk("否"); | |
97 | + baseMapper.updateById(dd); | |
98 | + } | |
87 | 99 | //添加服务日志 |
88 | - wDdfwrzManager.insertDdfwrz(DdfwlxEnum.qxdd.getCode(), dd.getId()); | |
100 | +// wDdfwrzManager.insertDdfwrz(DdfwlxEnum.qxdd.getCode(), dd.getId()); | |
89 | 101 | } |
90 | 102 | |
91 | 103 | @Override |
... | ... | @@ -216,7 +228,7 @@ public class DdManagerImpl extends BaseManagerImpl<DdDao, WDd> implements DdMana |
216 | 228 | dd.setFZflx(ddDto.getZflx()); |
217 | 229 | dd.setFSfzf("否"); |
218 | 230 | dd.setFPsfs(ddDto.getPsfs()); |
219 | - dd.setFDdzt(StringUtil.isEmail(ddDto.getDdzt())?DdztEnum.dps.getInfo():ddDto.getDdzt()); | |
231 | + dd.setFDdzt(StringUtil.isEmail(ddDto.getDdzt()) ? DdztEnum.dps.getInfo() : ddDto.getDdzt()); | |
220 | 232 | dd.setFMjly(ddDto.getMjly()); |
221 | 233 | dd.setFBz(ddDto.getBz()); |
222 | 234 | dd.setFCzid(qplx.getfSsczid()); | ... | ... |
backend/lpg-user/src/main/java/com/hotent/lpg/user/manager/impl/PaymentManageImpl.java
... | ... | @@ -1,213 +0,0 @@ |
1 | -package com.hotent.lpg.user.manager.impl; | |
2 | - | |
3 | -import cn.hutool.core.util.RandomUtil; | |
4 | -import cn.hutool.core.util.StrUtil; | |
5 | -import com.alibaba.fastjson.JSONObject; | |
6 | -import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper; | |
7 | -import com.baomidou.mybatisplus.core.toolkit.Wrappers; | |
8 | -import com.github.binarywang.wxpay.bean.notify.WxPayNotifyResponse; | |
9 | -import com.github.binarywang.wxpay.bean.notify.WxPayOrderNotifyResult; | |
10 | -import com.github.binarywang.wxpay.bean.request.WxPayUnifiedOrderRequest; | |
11 | -import com.github.binarywang.wxpay.bean.result.WxPayUnifiedOrderResult; | |
12 | -import com.github.binarywang.wxpay.exception.WxPayException; | |
13 | -import com.github.binarywang.wxpay.service.WxPayService; | |
14 | - | |
15 | -import com.hotent.base.util.BeanUtils; | |
16 | -import com.hotent.lpg.common.model.WCzzfpz; | |
17 | -import com.hotent.lpg.common.model.WDd; | |
18 | -import com.hotent.lpg.common.model.WQpxx; | |
19 | -import com.hotent.lpg.user.dao.CzzfpzDao; | |
20 | -import com.hotent.lpg.user.dao.DdDao; | |
21 | -import com.hotent.lpg.user.enums.PayTypeEnum; | |
22 | -import com.hotent.lpg.user.manager.PaymentManage; | |
23 | -import com.hotent.lpg.user.util.LocalDateTimeUtils; | |
24 | -import com.hotent.lpg.user.util.WxPayConfiguration; | |
25 | -import com.hotent.lpg.user.vo.ResultData; | |
26 | -import lombok.AllArgsConstructor; | |
27 | -import lombok.extern.slf4j.Slf4j; | |
28 | -import org.springframework.stereotype.Service; | |
29 | -import org.springframework.transaction.annotation.Transactional; | |
30 | -import org.w3c.dom.Document; | |
31 | -import org.w3c.dom.Element; | |
32 | -import org.w3c.dom.Node; | |
33 | -import org.xml.sax.InputSource; | |
34 | - | |
35 | -import javax.xml.parsers.DocumentBuilder; | |
36 | -import javax.xml.parsers.DocumentBuilderFactory; | |
37 | -import javax.xml.transform.Transformer; | |
38 | -import javax.xml.transform.TransformerFactory; | |
39 | -import javax.xml.transform.dom.DOMSource; | |
40 | -import javax.xml.transform.stream.StreamResult; | |
41 | -import java.io.StringReader; | |
42 | -import java.io.StringWriter; | |
43 | -import java.math.BigDecimal; | |
44 | -import java.sql.Wrapper; | |
45 | -import java.time.LocalDateTime; | |
46 | -import java.util.HashMap; | |
47 | - | |
48 | -@Service | |
49 | -@Transactional | |
50 | -@AllArgsConstructor | |
51 | -@Slf4j | |
52 | -public class PaymentManageImpl implements PaymentManage { | |
53 | - private final DdDao ddDao; | |
54 | - private final CzzfpzDao czzfpzDao; | |
55 | - @Override | |
56 | - public String notifyOrder(String xmlData) { | |
57 | - // 从 XML 数据中提取支付单号 | |
58 | - String outTradeNo = extractValueFromXML(xmlData, "out_trade_no"); | |
59 | - //先用订单号找到订单 | |
60 | - WDd wDd = ddDao.selectOne(new LambdaQueryWrapper<WDd>().eq(WDd::getFDddh, outTradeNo)); | |
61 | - //在用 场站信息 拿到场站对应得支付配置 | |
62 | - WCzzfpz wCzzfpz = czzfpzDao.selectOne(Wrappers.<WCzzfpz>lambdaQuery().eq(WCzzfpz::getFCzid, wDd.getFCzid()).eq(WCzzfpz::getFZflx, wDd.getFZffs())); | |
63 | - WxPayService wxPayService = WxPayConfiguration.getPayService(wCzzfpz); | |
64 | - //下面依旧是走微信sdk,查询订单和验证订单,为了保证数据得安全性,还是重复验证一次 | |
65 | - String dddh = null; | |
66 | - try { | |
67 | - WxPayOrderNotifyResult notifyResult = wxPayService.parseOrderNotifyResult(xmlData); | |
68 | - // 获取订单编号 | |
69 | - dddh = notifyResult.getOutTradeNo(); | |
70 | - // 获取微信支付单号 | |
71 | - String transactionId = notifyResult.getTransactionId(); | |
72 | - wDd = ddDao.selectOne(new LambdaQueryWrapper<WDd>().eq(WDd::getFDddh, dddh)); | |
73 | - if (wDd == null) { | |
74 | - log.warn("订单不存在: {}", dddh); | |
75 | - return generateXmlResponse("FAIL", "订单不存在", dddh); | |
76 | - } | |
77 | - // 检查订单状态是否已支付 | |
78 | - if ("已支付".equals(wDd.getFDdzt())) { | |
79 | - log.warn("订单 {} 已经处理过,忽略本次通知", dddh); | |
80 | - return generateXmlResponse("SUCCESS", "已处理过", dddh); | |
81 | - } | |
82 | - BigDecimal payPrice = wDd.getFDdje(); | |
83 | - if (payPrice.multiply(new BigDecimal(100)).intValue() != notifyResult.getTotalFee()) { | |
84 | - log.warn("付款金额与订单金额不等: {}", dddh); | |
85 | - return generateXmlResponse("FAIL", "付款金额与订单金额不等", dddh); | |
86 | - } | |
87 | - | |
88 | - String timeEnd = notifyResult.getTimeEnd(); | |
89 | - LocalDateTime paymentTime = LocalDateTimeUtils.parse(timeEnd); | |
90 | - wDd.setFFksj(paymentTime); | |
91 | - wDd.setFSfzf("是"); | |
92 | - wDd.setFDdzt("待配送"); | |
93 | - wDd.setFZfdh(transactionId); | |
94 | - ddDao.updateById(wDd); | |
95 | - | |
96 | - log.info("订单支付成功: {}", dddh); | |
97 | - return generateXmlResponse("SUCCESS", "成功", dddh); | |
98 | - } catch (WxPayException e) { | |
99 | - log.error("支付回调处理失败: {}", e.getErrCodeDes(), e); | |
100 | - return generateXmlResponse("FAIL", e.getErrCodeDes(), dddh); | |
101 | - } | |
102 | - } | |
103 | - | |
104 | - | |
105 | - private String extractValueFromXML(String xmlData, String paramName) { | |
106 | - // 解析 XML 数据以提取指定参数的值 | |
107 | - try { | |
108 | - DocumentBuilderFactory dbFactory = DocumentBuilderFactory.newInstance(); | |
109 | - DocumentBuilder dBuilder = dbFactory.newDocumentBuilder(); | |
110 | - InputSource is = new InputSource(new StringReader(xmlData)); | |
111 | - Document doc = dBuilder.parse(is); | |
112 | - | |
113 | - Element element = doc.getDocumentElement(); | |
114 | - Node paramNode = element.getElementsByTagName(paramName).item(0).getFirstChild(); | |
115 | - return paramNode != null ? paramNode.getNodeValue() : null; | |
116 | - } catch (Exception e) { | |
117 | - log.error("解析 XML 数据失败: {}", e.getMessage(), e); | |
118 | - return null; | |
119 | - } | |
120 | - } | |
121 | - | |
122 | - | |
123 | - private String generateXmlResponse(String returnCode, String returnMsg, String outTradeNo) { | |
124 | - DocumentBuilderFactory dbFactory = DocumentBuilderFactory.newInstance(); | |
125 | - DocumentBuilder dBuilder; | |
126 | - try { | |
127 | - dBuilder = dbFactory.newDocumentBuilder(); | |
128 | - Document doc = dBuilder.newDocument(); | |
129 | - | |
130 | - Element rootElement = doc.createElement("xml"); | |
131 | - doc.appendChild(rootElement); | |
132 | - | |
133 | - Element returnCodeElement = doc.createElement("return_code"); | |
134 | - returnCodeElement.appendChild(doc.createTextNode(returnCode)); | |
135 | - rootElement.appendChild(returnCodeElement); | |
136 | - | |
137 | - Element returnMsgElement = doc.createElement("return_msg"); | |
138 | - returnMsgElement.appendChild(doc.createTextNode(returnMsg)); | |
139 | - rootElement.appendChild(returnMsgElement); | |
140 | - | |
141 | - Element outTradeNoElement = doc.createElement("out_trade_no"); | |
142 | - outTradeNoElement.appendChild(doc.createTextNode(outTradeNo)); | |
143 | - rootElement.appendChild(outTradeNoElement); | |
144 | - | |
145 | - TransformerFactory transformerFactory = TransformerFactory.newInstance(); | |
146 | - Transformer transformer = transformerFactory.newTransformer(); | |
147 | - DOMSource source = new DOMSource(doc); | |
148 | - StringWriter writer = new StringWriter(); | |
149 | - StreamResult result = new StreamResult(writer); | |
150 | - transformer.transform(source, result); | |
151 | - return writer.toString(); | |
152 | - } catch (Exception e) { | |
153 | - log.error("构建 XML 响应失败", e); | |
154 | - return "<xml><return_code>FAIL</return_code><return_msg>处理失败</return_msg></xml>"; | |
155 | - } | |
156 | - } | |
157 | - | |
158 | - @Override | |
159 | - public HashMap<String, Object> wxPay(WDd wDd,String openId) { | |
160 | - try { | |
161 | - WCzzfpz wCzzfpz = czzfpzDao.selectOne(Wrappers.<WCzzfpz>lambdaQuery().eq(WCzzfpz::getFCzid, wDd.getFCzid()).eq(WCzzfpz::getFZflx, wDd.getFZffs())); | |
162 | - if (BeanUtils.isEmpty(wCzzfpz) || wCzzfpz == null) { | |
163 | - throw new RuntimeException("支付配置不存在"); | |
164 | - } | |
165 | - String tradeType = wDd.getFZflx(); | |
166 | - if (StrUtil.isBlank(tradeType)) { | |
167 | - throw new RuntimeException("支付方式错误"); | |
168 | - } | |
169 | - WxPayUnifiedOrderRequest wxPayUnifiedOrderRequest = new WxPayUnifiedOrderRequest(); | |
170 | - wxPayUnifiedOrderRequest.setAppid(wCzzfpz.getFAppid()); | |
171 | - wxPayUnifiedOrderRequest.setOpenid(null); | |
172 | - wxPayUnifiedOrderRequest.setBody(wDd.getFDddh()); | |
173 | - wxPayUnifiedOrderRequest.setOutTradeNo(wDd.getFDddh()); | |
174 | - wxPayUnifiedOrderRequest.setTotalFee(wDd.getFDdje().multiply(new BigDecimal(100)).intValue()); | |
175 | - wxPayUnifiedOrderRequest.setTradeType(tradeType); | |
176 | - log.warn("创建订单5:{}", wxPayUnifiedOrderRequest); | |
177 | - JSONObject scene_info = new JSONObject(); | |
178 | - scene_info.put("id", "LPG"); | |
179 | - scene_info.put("name", "燃气"); | |
180 | - wxPayUnifiedOrderRequest.setSceneInfo(scene_info.toString()); | |
181 | - wxPayUnifiedOrderRequest.setNotifyUrl("http://pmrsig.natappfree.cc/api/user/order/payment/notifyOrder"); // 支付回调地址,开放不用登录 | |
182 | - wxPayUnifiedOrderRequest.setSpbillCreateIp("127.0.0.1"); | |
183 | - // trade_type=APP时 移动应用内的支付场景 | |
184 | - if ("APP".equals(wxPayUnifiedOrderRequest.getTradeType())) { | |
185 | - wxPayUnifiedOrderRequest.setAppid(wCzzfpz.getFAppid()); | |
186 | - } | |
187 | - // trade_type=NATIVE时 线下消费场景 | |
188 | - if ("NATIVE".equals(wxPayUnifiedOrderRequest.getTradeType())) { | |
189 | - wxPayUnifiedOrderRequest.setProductId(wxPayUnifiedOrderRequest.getOutTradeNo()); | |
190 | - } | |
191 | - // 公众号内或者微信内的网页支付 | |
192 | - if ("JSAPI".equals(wxPayUnifiedOrderRequest.getTradeType())) { | |
193 | - wxPayUnifiedOrderRequest.setOpenid(openId); | |
194 | - } | |
195 | - // 手机浏览器中的支付场景 | |
196 | - if ("MWEB".equals(wxPayUnifiedOrderRequest.getTradeType())) { | |
197 | - wxPayUnifiedOrderRequest.setSceneInfo(null); | |
198 | - } | |
199 | - WxPayService wxPayService = WxPayConfiguration.getPayService(wCzzfpz); | |
200 | - Object payment = wxPayService.createOrder(wxPayUnifiedOrderRequest); | |
201 | - HashMap<String, Object> resultData = new HashMap<String, Object>(); | |
202 | - resultData.put("payment", payment); | |
203 | - resultData.put("ddid", wDd.getId()); | |
204 | - resultData.put("dddh", wDd.getFDddh()); | |
205 | - return resultData; | |
206 | - } catch (WxPayException e) { | |
207 | - if ("INVALID_REQUEST".equals(e.getErrCode())) { | |
208 | - throw new RuntimeException("订单号重复,请重新下单"); | |
209 | - } | |
210 | - throw new RuntimeException(e.getMessage()); | |
211 | - } | |
212 | - } | |
213 | -} |
backend/lpg-user/src/main/java/com/hotent/lpg/user/manager/impl/WxPayManagerImpl.java
0 → 100644
... | ... | @@ -0,0 +1,336 @@ |
1 | +package com.hotent.lpg.user.manager.impl; | |
2 | + | |
3 | +import cn.hutool.core.util.RandomUtil; | |
4 | +import cn.hutool.core.util.StrUtil; | |
5 | +import com.alibaba.fastjson.JSONObject; | |
6 | +import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper; | |
7 | +import com.baomidou.mybatisplus.core.toolkit.Wrappers; | |
8 | +import com.github.binarywang.wxpay.bean.notify.WxPayOrderNotifyResult; | |
9 | +import com.github.binarywang.wxpay.bean.notify.WxPayRefundNotifyResult; | |
10 | +import com.github.binarywang.wxpay.bean.request.WxPayRefundRequest; | |
11 | +import com.github.binarywang.wxpay.bean.request.WxPayUnifiedOrderRequest; | |
12 | +import com.github.binarywang.wxpay.bean.result.WxPayRefundResult; | |
13 | +import com.github.binarywang.wxpay.exception.WxPayException; | |
14 | +import com.github.binarywang.wxpay.service.WxPayService; | |
15 | +import com.hotent.base.util.BeanUtils; | |
16 | +import com.hotent.lpg.common.enums.DdztEnum; | |
17 | +import com.hotent.lpg.common.model.WCzzfpz; | |
18 | +import com.hotent.lpg.common.model.WDd; | |
19 | +import com.hotent.lpg.user.dao.CzzfpzDao; | |
20 | +import com.hotent.lpg.user.dao.DdDao; | |
21 | +import com.hotent.lpg.user.manager.WxPayManager; | |
22 | +import com.hotent.lpg.user.util.LocalDateTimeUtils; | |
23 | +import com.hotent.lpg.user.util.WxPayConfiguration; | |
24 | +import lombok.AllArgsConstructor; | |
25 | +import lombok.extern.slf4j.Slf4j; | |
26 | +import org.springframework.stereotype.Service; | |
27 | +import org.w3c.dom.Document; | |
28 | +import org.w3c.dom.Element; | |
29 | +import org.w3c.dom.Node; | |
30 | +import org.xml.sax.InputSource; | |
31 | + | |
32 | +import javax.xml.bind.JAXBContext; | |
33 | +import javax.xml.parsers.DocumentBuilder; | |
34 | +import javax.xml.parsers.DocumentBuilderFactory; | |
35 | +import javax.xml.transform.Transformer; | |
36 | +import javax.xml.transform.TransformerFactory; | |
37 | +import javax.xml.transform.dom.DOMSource; | |
38 | +import javax.xml.transform.stream.StreamResult; | |
39 | +import javax.xml.xpath.XPath; | |
40 | +import javax.xml.xpath.XPathConstants; | |
41 | +import javax.xml.xpath.XPathFactory; | |
42 | +import java.io.StringReader; | |
43 | +import java.io.StringWriter; | |
44 | +import java.math.BigDecimal; | |
45 | +import java.time.LocalDateTime; | |
46 | +import java.util.HashMap; | |
47 | + | |
48 | +@Service | |
49 | +@AllArgsConstructor | |
50 | +@Slf4j | |
51 | +public class WxPayManagerImpl implements WxPayManager { | |
52 | + | |
53 | + private final DdDao ddDao; | |
54 | + private final CzzfpzDao czzfpzDao; | |
55 | + | |
56 | + /** | |
57 | + * 发起退款请求 | |
58 | + * | |
59 | + * @param ddid | |
60 | + * @return | |
61 | + */ | |
62 | + @Override | |
63 | + public String initiateRefundOrder(String ddid) { | |
64 | + // 1. 查询订单信息 | |
65 | + WDd wDd = ddDao.selectById(ddid); | |
66 | + if (!DdztEnum.dps.getInfo().equals(wDd.getFDdzt())) { | |
67 | + throw new RuntimeException("订单状态不正确"); | |
68 | + } | |
69 | + if (!(wDd.getFDdly().equals("线上下单") && wDd.getFZffs().equals("微信") && wDd.getFSfzf().equals("是"))) { | |
70 | + throw new RuntimeException("订单状态不正确"); | |
71 | + } | |
72 | + // 2. 获取支付配置 | |
73 | + WCzzfpz wCzzfpz = czzfpzDao.selectOne(Wrappers.<WCzzfpz>lambdaQuery().eq(WCzzfpz::getFCzid, wDd.getFCzid()).eq(WCzzfpz::getFZflx, wDd.getFZffs())); | |
74 | + if (wCzzfpz == null) { | |
75 | + throw new RuntimeException("支付配置不存在"); | |
76 | + } | |
77 | + // 3. 初始化微信支付服务 | |
78 | + WxPayService wxPayService = WxPayConfiguration.getPayService(wCzzfpz); | |
79 | + try { | |
80 | + // 4. 调用微信退款接口 | |
81 | + // 这里需要构造退款请求对象,具体参数根据实际情况填写 | |
82 | + // 注意:这里需要根据实际的微信支付SDK版本和退款接口文档来调整 | |
83 | + // 示例代码可能需要根据实际情况修改 | |
84 | + String tkdh = RandomUtil.randomString(32); | |
85 | + WxPayRefundRequest refundRequest = new WxPayRefundRequest(); | |
86 | + refundRequest.setTransactionId(wDd.getFZfdh()); | |
87 | + refundRequest.setOutTradeNo(wDd.getFDddh()); // 订单号 | |
88 | + refundRequest.setOutRefundNo(RandomUtil.randomString(32)); // 退款单号 | |
89 | + refundRequest.setTotalFee(wDd.getFDdje().multiply(new BigDecimal(100)).intValue()); // 订单总金额 | |
90 | + refundRequest.setRefundFee(wDd.getFDdje().multiply(new BigDecimal(100)).intValue()); // 退款金额 | |
91 | + refundRequest.setNotifyUrl(WxPayConfiguration.hostUrl + "/user/wxPay/handleRefundSuccessCallback"); | |
92 | + // 发起退款请求 | |
93 | + Object payment = wxPayService.refund(refundRequest); | |
94 | + // 返回结果 | |
95 | + return tkdh; | |
96 | + } catch (WxPayException e) { | |
97 | + log.error("退款失败: {}", e.getErrCodeDes(), e); | |
98 | + throw new RuntimeException("退款失败: " + e.getErrCodeDes()); | |
99 | + } | |
100 | + } | |
101 | + | |
102 | + /** | |
103 | + * 处理退款成功回调 | |
104 | + * | |
105 | + * @param xmlData | |
106 | + * @return | |
107 | + */ | |
108 | + @Override | |
109 | + public String handleRefundSuccessCallback(String xmlData) { | |
110 | + WxPayOrderNotifyResult rs = WxPayOrderNotifyResult.fromXML(xmlData); | |
111 | + String returnCode = rs.getReturnCode(); | |
112 | + if (!returnCode.equals("SUCCESS")) { | |
113 | + return generateXmlResponse("FAIL", "退款失败", returnCode); | |
114 | + } | |
115 | + String appid = rs.getAppid(); | |
116 | + String mchId = rs.getMchId(); | |
117 | + //在用 场站信息 拿到场站对应得支付配置 | |
118 | + WCzzfpz wCzzfpz = czzfpzDao.selectOne(Wrappers.<WCzzfpz>lambdaQuery().eq(WCzzfpz::getFAppid, appid).eq(WCzzfpz::getFMchid, mchId)); | |
119 | + WxPayService wxPayService = WxPayConfiguration.getPayService(wCzzfpz); | |
120 | + //下面依旧是走微信sdk,查询订单和验证订单,为了保证数据得安全性,还是重复验证一次 | |
121 | + String dddh = null; | |
122 | + try { | |
123 | + WxPayRefundNotifyResult notifyResult = wxPayService.parseRefundNotifyResult(xmlData); | |
124 | + WxPayRefundNotifyResult.ReqInfo reqInfo = notifyResult.getReqInfo(); | |
125 | + String refundId = reqInfo.getRefundId(); | |
126 | + String successTime = reqInfo.getSuccessTime(); | |
127 | + String transactionId = reqInfo.getTransactionId(); | |
128 | + String outTradeNo = reqInfo.getOutTradeNo(); | |
129 | + WDd wDd = ddDao.selectOne(Wrappers.<WDd>lambdaQuery().eq(WDd::getFZfdh, transactionId).eq(WDd::getFDddh, outTradeNo)); | |
130 | + if (wDd == null) { | |
131 | + return generateXmlResponse("FAIL", "未查询到订单", outTradeNo); | |
132 | + } | |
133 | + if (wDd.getFSftk().equals("是")){ | |
134 | + return generateXmlResponse("FAIL", "订单已退款", outTradeNo); | |
135 | + } | |
136 | + // 5. 更新订单状态 | |
137 | + wDd.setFDdzt(DdztEnum.yqx.getInfo()); | |
138 | + wDd.setFSftk("是"); | |
139 | + wDd.setFTkdh(refundId); | |
140 | + wDd.setFTksj(LocalDateTimeUtils.parse(successTime)); | |
141 | + ddDao.updateById(wDd); | |
142 | + log.info("微信退款成功: {}", dddh); | |
143 | + return generateXmlResponse("SUCCESS", "成功", dddh); | |
144 | + } catch (WxPayException e) { | |
145 | + log.error("微信退款回调处理失败: {}", e.getErrCodeDes(), e); | |
146 | + return generateXmlResponse("FAIL", e.getErrCodeDes(), dddh); | |
147 | + } | |
148 | + } | |
149 | + | |
150 | + | |
151 | + | |
152 | + | |
153 | + /** | |
154 | + * 处理支付成功回调 | |
155 | + * | |
156 | + * @param xmlData | |
157 | + * @return | |
158 | + */ | |
159 | + @Override | |
160 | + public String handlePaySuccessCallback(String xmlData) { | |
161 | + // 从 XML 数据中提取支付单号 | |
162 | + String outTradeNo = extractValueFromXML(xmlData, "out_trade_no"); | |
163 | + //先用订单号找到订单 | |
164 | + WDd wDd = ddDao.selectOne(new LambdaQueryWrapper<WDd>().eq(WDd::getFDddh, outTradeNo)); | |
165 | + //在用 场站信息 拿到场站对应得支付配置 | |
166 | + WCzzfpz wCzzfpz = czzfpzDao.selectOne(Wrappers.<WCzzfpz>lambdaQuery().eq(WCzzfpz::getFCzid, wDd.getFCzid()).eq(WCzzfpz::getFZflx, wDd.getFZffs())); | |
167 | + WxPayService wxPayService = WxPayConfiguration.getPayService(wCzzfpz); | |
168 | + //下面依旧是走微信sdk,查询订单和验证订单,为了保证数据得安全性,还是重复验证一次 | |
169 | + String dddh = null; | |
170 | + try { | |
171 | + WxPayOrderNotifyResult notifyResult = wxPayService.parseOrderNotifyResult(xmlData); | |
172 | + // 获取订单编号 | |
173 | + dddh = notifyResult.getOutTradeNo(); | |
174 | + // 获取微信支付单号 | |
175 | + String transactionId = notifyResult.getTransactionId(); | |
176 | + wDd = ddDao.selectOne(new LambdaQueryWrapper<WDd>().eq(WDd::getFDddh, dddh)); | |
177 | + if (wDd == null) { | |
178 | + log.warn("订单不存在: {}", dddh); | |
179 | + return generateXmlResponse("FAIL", "订单不存在", dddh); | |
180 | + } | |
181 | + // 检查订单状态是否已支付 | |
182 | + if ("已支付".equals(wDd.getFDdzt())) { | |
183 | + log.warn("订单 {} 已经处理过,忽略本次通知", dddh); | |
184 | + return generateXmlResponse("SUCCESS", "已处理过", dddh); | |
185 | + } | |
186 | + BigDecimal payPrice = wDd.getFDdje(); | |
187 | + if (payPrice.multiply(new BigDecimal(100)).intValue() != notifyResult.getTotalFee()) { | |
188 | + log.warn("付款金额与订单金额不等: {}", dddh); | |
189 | + return generateXmlResponse("FAIL", "付款金额与订单金额不等", dddh); | |
190 | + } | |
191 | + | |
192 | + String timeEnd = notifyResult.getTimeEnd(); | |
193 | + LocalDateTime paymentTime = LocalDateTimeUtils.parse(timeEnd); | |
194 | + wDd.setFFksj(paymentTime); | |
195 | + wDd.setFSfzf("是"); | |
196 | + wDd.setFDdzt("待配送"); | |
197 | + wDd.setFZfdh(transactionId); | |
198 | + ddDao.updateById(wDd); | |
199 | + | |
200 | + log.info("订单支付成功: {}", dddh); | |
201 | + return generateXmlResponse("SUCCESS", "成功", dddh); | |
202 | + } catch (WxPayException e) { | |
203 | + log.error("支付回调处理失败: {}", e.getErrCodeDes(), e); | |
204 | + return generateXmlResponse("FAIL", e.getErrCodeDes(), dddh); | |
205 | + } | |
206 | + } | |
207 | + | |
208 | + /** | |
209 | + * 生成预支付订单 | |
210 | + * @param wDd | |
211 | + * @param openId | |
212 | + * @return | |
213 | + */ | |
214 | + @Override | |
215 | + public HashMap<String, Object> generatePrepayOrder(WDd wDd, String openId) { | |
216 | + try { | |
217 | + WCzzfpz wCzzfpz = czzfpzDao.selectOne(Wrappers.<WCzzfpz>lambdaQuery().eq(WCzzfpz::getFCzid, wDd.getFCzid()).eq(WCzzfpz::getFZflx, wDd.getFZffs())); | |
218 | + if (BeanUtils.isEmpty(wCzzfpz) || wCzzfpz == null) { | |
219 | + throw new RuntimeException("支付配置不存在"); | |
220 | + } | |
221 | + String tradeType = wDd.getFZflx(); | |
222 | + if (StrUtil.isBlank(tradeType)) { | |
223 | + throw new RuntimeException("支付方式错误"); | |
224 | + } | |
225 | + WxPayUnifiedOrderRequest wxPayUnifiedOrderRequest = new WxPayUnifiedOrderRequest(); | |
226 | + wxPayUnifiedOrderRequest.setAppid(wCzzfpz.getFAppid()); | |
227 | + wxPayUnifiedOrderRequest.setOpenid(null); | |
228 | + wxPayUnifiedOrderRequest.setBody(wDd.getFDddh()); | |
229 | + wxPayUnifiedOrderRequest.setOutTradeNo(wDd.getFDddh()); | |
230 | + wxPayUnifiedOrderRequest.setTotalFee(wDd.getFDdje().multiply(new BigDecimal(100)).intValue()); | |
231 | + wxPayUnifiedOrderRequest.setTradeType(tradeType); | |
232 | + JSONObject scene_info = new JSONObject(); | |
233 | + scene_info.put("id", "LPG"); | |
234 | + scene_info.put("name", "燃气"); | |
235 | + wxPayUnifiedOrderRequest.setSceneInfo(scene_info.toString()); | |
236 | + wxPayUnifiedOrderRequest.setNotifyUrl(WxPayConfiguration.hostUrl + "/user/wxPay/handlePaySuccessCallback"); // 支付回调地址,开放不用登录 | |
237 | + wxPayUnifiedOrderRequest.setSpbillCreateIp("127.0.0.1"); | |
238 | + // trade_type=APP时 移动应用内的支付场景 | |
239 | + if ("APP".equals(wxPayUnifiedOrderRequest.getTradeType())) { | |
240 | + wxPayUnifiedOrderRequest.setAppid(wCzzfpz.getFAppid()); | |
241 | + } | |
242 | + // trade_type=NATIVE时 线下消费场景 | |
243 | + if ("NATIVE".equals(wxPayUnifiedOrderRequest.getTradeType())) { | |
244 | + wxPayUnifiedOrderRequest.setProductId(wxPayUnifiedOrderRequest.getOutTradeNo()); | |
245 | + } | |
246 | + // 公众号内或者微信内的网页支付 | |
247 | + if ("JSAPI".equals(wxPayUnifiedOrderRequest.getTradeType())) { | |
248 | + wxPayUnifiedOrderRequest.setOpenid(openId); | |
249 | + } | |
250 | + // 手机浏览器中的支付场景 | |
251 | + if ("MWEB".equals(wxPayUnifiedOrderRequest.getTradeType())) { | |
252 | + wxPayUnifiedOrderRequest.setSceneInfo(null); | |
253 | + } | |
254 | + WxPayService wxPayService = WxPayConfiguration.getPayService(wCzzfpz); | |
255 | + Object payment = wxPayService.createOrder(wxPayUnifiedOrderRequest); | |
256 | + HashMap<String, Object> resultData = new HashMap<String, Object>(); | |
257 | + resultData.put("payment", payment); | |
258 | + resultData.put("ddid", wDd.getId()); | |
259 | + resultData.put("dddh", wDd.getFDddh()); | |
260 | + return resultData; | |
261 | + } catch (WxPayException e) { | |
262 | + if ("INVALID_REQUEST".equals(e.getErrCode())) { | |
263 | + throw new RuntimeException("订单号重复,请重新下单"); | |
264 | + } | |
265 | + throw new RuntimeException(e.getMessage()); | |
266 | + } | |
267 | + } | |
268 | + | |
269 | + /** | |
270 | + * 生成微信回调响应 | |
271 | + * | |
272 | + * @param returnCode | |
273 | + * @param returnMsg | |
274 | + * @param outTradeNo | |
275 | + * @return | |
276 | + */ | |
277 | + private String generateXmlResponse(String returnCode, String returnMsg, String outTradeNo) { | |
278 | + DocumentBuilderFactory dbFactory = DocumentBuilderFactory.newInstance(); | |
279 | + DocumentBuilder dBuilder; | |
280 | + try { | |
281 | + dBuilder = dbFactory.newDocumentBuilder(); | |
282 | + Document doc = dBuilder.newDocument(); | |
283 | + | |
284 | + Element rootElement = doc.createElement("xml"); | |
285 | + doc.appendChild(rootElement); | |
286 | + | |
287 | + Element returnCodeElement = doc.createElement("return_code"); | |
288 | + returnCodeElement.appendChild(doc.createTextNode(returnCode)); | |
289 | + rootElement.appendChild(returnCodeElement); | |
290 | + | |
291 | + Element returnMsgElement = doc.createElement("return_msg"); | |
292 | + returnMsgElement.appendChild(doc.createTextNode(returnMsg)); | |
293 | + rootElement.appendChild(returnMsgElement); | |
294 | + | |
295 | + Element outTradeNoElement = doc.createElement("out_trade_no"); | |
296 | + outTradeNoElement.appendChild(doc.createTextNode(outTradeNo)); | |
297 | + rootElement.appendChild(outTradeNoElement); | |
298 | + | |
299 | + TransformerFactory transformerFactory = TransformerFactory.newInstance(); | |
300 | + Transformer transformer = transformerFactory.newTransformer(); | |
301 | + DOMSource source = new DOMSource(doc); | |
302 | + StringWriter writer = new StringWriter(); | |
303 | + StreamResult result = new StreamResult(writer); | |
304 | + transformer.transform(source, result); | |
305 | + return writer.toString(); | |
306 | + } catch (Exception e) { | |
307 | + log.error("构建 XML 响应失败", e); | |
308 | + return "<xml><return_code>FAIL</return_code><return_msg>处理失败</return_msg></xml>"; | |
309 | + } | |
310 | + } | |
311 | + | |
312 | + /** | |
313 | + * 从 XML 数据中提取指定参数的值 | |
314 | + * | |
315 | + * @param xmlData | |
316 | + * @param paramName | |
317 | + * @return | |
318 | + */ | |
319 | + private String extractValueFromXML(String xmlData, String paramName) { | |
320 | + // 解析 XML 数据以提取指定参数的值 | |
321 | + try { | |
322 | + DocumentBuilderFactory dbFactory = DocumentBuilderFactory.newInstance(); | |
323 | + DocumentBuilder dBuilder = dbFactory.newDocumentBuilder(); | |
324 | + InputSource is = new InputSource(new StringReader(xmlData)); | |
325 | + Document doc = dBuilder.parse(is); | |
326 | + | |
327 | + Element element = doc.getDocumentElement(); | |
328 | + Node paramNode = element.getElementsByTagName(paramName).item(0).getFirstChild(); | |
329 | + return paramNode != null ? paramNode.getNodeValue() : null; | |
330 | + } catch (Exception e) { | |
331 | + log.error("解析 XML 数据失败: {}", e.getMessage(), e); | |
332 | + return null; | |
333 | + } | |
334 | + } | |
335 | + | |
336 | +} | ... | ... |
backend/lpg-user/src/main/java/com/hotent/lpg/user/util/WxPayConfiguration.java
... | ... | @@ -6,6 +6,9 @@ import com.github.binarywang.wxpay.service.impl.WxPayServiceImpl; |
6 | 6 | import com.hotent.lpg.common.model.WCzzfpz; |
7 | 7 | |
8 | 8 | public class WxPayConfiguration { |
9 | + | |
10 | + | |
11 | + public static final String hostUrl = "http://qyhtiz.natappfree.cc/api"; | |
9 | 12 | public static WxPayService getPayService(WCzzfpz wCzzfpz) { |
10 | 13 | WxPayConfig wxPayConfig = new WxPayConfig(); |
11 | 14 | wxPayConfig.setAppId(wCzzfpz.getFAppid()); // appId(应用id)(微信支付商户平台获取) |
... | ... | @@ -18,6 +21,9 @@ public class WxPayConfiguration { |
18 | 21 | wxPayConfig.setUseSandboxEnv(false); |
19 | 22 | WxPayService wxPayService = new WxPayServiceImpl(); |
20 | 23 | wxPayService.setConfig(wxPayConfig); |
24 | + wxPayConfig.setKeyPath(wCzzfpz.getFKeypath()); | |
25 | + wxPayConfig.setPrivateKeyPath(wCzzfpz.getFPrivatekeypath()); | |
26 | + wxPayConfig.setPrivateCertPath(wCzzfpz.getFPrivatecertpath()); | |
21 | 27 | return wxPayService; |
22 | 28 | } |
23 | 29 | } | ... | ... |