From 4e2d5446bb03a0c69ac1189982b7bb4f4448e16e Mon Sep 17 00:00:00 2001 From: chenwei Date: Fri, 6 Sep 2024 10:20:41 +0800 Subject: [PATCH] 微信h5退款 --- backend/base/src/main/java/com/hotent/base/conf/WebSecurityConfig.java | 2 +- backend/lpg-common/src/main/java/com/hotent/lpg/common/enums/DdztEnum.java | 4 ++++ backend/lpg-common/src/main/java/com/hotent/lpg/common/model/WCzzfpz.java | 73 +++++++++++++++++++++++++++++++++++++++++++++++++++++++++---------------- backend/lpg-common/src/main/java/com/hotent/lpg/common/model/WDd.java | 25 +++++++++++++++++++++++++ backend/lpg-user/src/main/java/com/hotent/lpg/user/controller/DdConroller.java | 124 +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++------------------------------------- backend/lpg-user/src/main/java/com/hotent/lpg/user/controller/PaymentController.java | 110 -------------------------------------------------------------------------------------------------------------- backend/lpg-user/src/main/java/com/hotent/lpg/user/controller/WxPayController.java | 47 +++++++++++++++++++++++++++++++++++++++++++++++ backend/lpg-user/src/main/java/com/hotent/lpg/user/manager/PaymentManage.java | 16 ---------------- backend/lpg-user/src/main/java/com/hotent/lpg/user/manager/WxPayManager.java | 38 ++++++++++++++++++++++++++++++++++++++ backend/lpg-user/src/main/java/com/hotent/lpg/user/manager/impl/DdManagerImpl.java | 32 ++++++++++++++++++++++---------- backend/lpg-user/src/main/java/com/hotent/lpg/user/manager/impl/PaymentManageImpl.java | 213 --------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- backend/lpg-user/src/main/java/com/hotent/lpg/user/manager/impl/WxPayManagerImpl.java | 336 ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ backend/lpg-user/src/main/java/com/hotent/lpg/user/util/WxPayConfiguration.java | 6 ++++++ 13 files changed, 623 insertions(+), 403 deletions(-) delete mode 100644 backend/lpg-user/src/main/java/com/hotent/lpg/user/controller/PaymentController.java create mode 100644 backend/lpg-user/src/main/java/com/hotent/lpg/user/controller/WxPayController.java delete mode 100644 backend/lpg-user/src/main/java/com/hotent/lpg/user/manager/PaymentManage.java create mode 100644 backend/lpg-user/src/main/java/com/hotent/lpg/user/manager/WxPayManager.java delete mode 100644 backend/lpg-user/src/main/java/com/hotent/lpg/user/manager/impl/PaymentManageImpl.java create mode 100644 backend/lpg-user/src/main/java/com/hotent/lpg/user/manager/impl/WxPayManagerImpl.java diff --git a/backend/base/src/main/java/com/hotent/base/conf/WebSecurityConfig.java b/backend/base/src/main/java/com/hotent/base/conf/WebSecurityConfig.java index 312f62d..6625e40 100644 --- a/backend/base/src/main/java/com/hotent/base/conf/WebSecurityConfig.java +++ b/backend/base/src/main/java/com/hotent/base/conf/WebSecurityConfig.java @@ -160,7 +160,7 @@ public class WebSecurityConfig extends WebSecurityConfigurerAdapter { .antMatchers("/fileUpload").permitAll() .antMatchers("/deleteFile").permitAll() .antMatchers("/ueditor/**", "/apiManager/getToken").permitAll() - .antMatchers("/user/order/payment/notifyOrder").permitAll() + .antMatchers("/user/wxPay/**").permitAll() .anyRequest().authenticated() .accessDecisionManager(accessDecisionManager()); diff --git a/backend/lpg-common/src/main/java/com/hotent/lpg/common/enums/DdztEnum.java b/backend/lpg-common/src/main/java/com/hotent/lpg/common/enums/DdztEnum.java index 6a8fc20..215cd13 100644 --- a/backend/lpg-common/src/main/java/com/hotent/lpg/common/enums/DdztEnum.java +++ b/backend/lpg-common/src/main/java/com/hotent/lpg/common/enums/DdztEnum.java @@ -17,6 +17,10 @@ public enum DdztEnum { dzf("dzf", "待支付"), /** + * 退款中 + */ + tkz("tkz", "退款中"), + /** * 待配送 */ dps("dps", "待配送"), diff --git a/backend/lpg-common/src/main/java/com/hotent/lpg/common/model/WCzzfpz.java b/backend/lpg-common/src/main/java/com/hotent/lpg/common/model/WCzzfpz.java index 9cd33bd..473abd7 100644 --- a/backend/lpg-common/src/main/java/com/hotent/lpg/common/model/WCzzfpz.java +++ b/backend/lpg-common/src/main/java/com/hotent/lpg/common/model/WCzzfpz.java @@ -2,6 +2,7 @@ package com.hotent.lpg.common.model; import com.baomidou.mybatisplus.annotation.IdType; import com.hotent.base.entity.BaseModel; +import com.baomidou.mybatisplus.extension.activerecord.Model; import com.baomidou.mybatisplus.annotation.TableId; import com.baomidou.mybatisplus.annotation.TableField; import java.io.Serializable; @@ -11,8 +12,9 @@ import com.fasterxml.jackson.annotation.JsonProperty; /** * 厂站支付配置 * - * @author cw - * @since 2024-09-04 + * @company + * @author 超级管理员 + * @since 2024-09-06 */ @ApiModel(value="WCzzfpz对象", description="厂站支付配置") public class WCzzfpz extends BaseModel { @@ -83,6 +85,21 @@ public class WCzzfpz extends BaseModel { @JsonProperty("fFormDataRev") private Long fFormDataRev; + @ApiModelProperty(value = " .p12 格式的密钥文件路径,私钥和证书") + @TableField("F_keyPath") + @JsonProperty("fKeypath") + private String fKeypath; + + @ApiModelProperty(value = "私钥文件路径") + @TableField("F_privateKeyPath") + @JsonProperty("fPrivatekeypath") + private String fPrivatekeypath; + + @ApiModelProperty(value = "私有证书文件路径") + @TableField("F_privateCertPath") + @JsonProperty("fPrivatecertpath") + private String fPrivatecertpath; + public String getId() { return id; @@ -175,6 +192,27 @@ public class WCzzfpz extends BaseModel { public void setFFormDataRev(Long fFormDataRev) { this.fFormDataRev = fFormDataRev; } + public String getFKeypath() { + return fKeypath; + } + + public void setFKeypath(String fKeypath) { + this.fKeypath = fKeypath; + } + public String getFPrivatekeypath() { + return fPrivatekeypath; + } + + public void setFPrivatekeypath(String fPrivatekeypath) { + this.fPrivatekeypath = fPrivatekeypath; + } + public String getFPrivatecertpath() { + return fPrivatecertpath; + } + + public void setFPrivatecertpath(String fPrivatecertpath) { + this.fPrivatecertpath = fPrivatecertpath; + } @Override @@ -185,19 +223,22 @@ public class WCzzfpz extends BaseModel { @Override public String toString() { return "WCzzfpz{" + - "id=" + id + - ", refId=" + refId + - ", fQyid=" + fQyid + - ", fCzid=" + fCzid + - ", fQymc=" + fQymc + - ", fCzmc=" + fCzmc + - ", fZflx=" + fZflx + - ", fAppid=" + fAppid + - ", fMchid=" + fMchid + - ", fMchkey=" + fMchkey + - ", fCertserialno=" + fCertserialno + - ", fApiv3key=" + fApiv3key + - ", fFormDataRev=" + fFormDataRev + - "}"; + "id=" + id + + ", refId=" + refId + + ", fQyid=" + fQyid + + ", fCzid=" + fCzid + + ", fQymc=" + fQymc + + ", fCzmc=" + fCzmc + + ", fZflx=" + fZflx + + ", fAppid=" + fAppid + + ", fMchid=" + fMchid + + ", fMchkey=" + fMchkey + + ", fCertserialno=" + fCertserialno + + ", fApiv3key=" + fApiv3key + + ", fFormDataRev=" + fFormDataRev + + ", fKeypath=" + fKeypath + + ", fPrivatekeypath=" + fPrivatekeypath + + ", fPrivatecertpath=" + fPrivatecertpath + + "}"; } } diff --git a/backend/lpg-common/src/main/java/com/hotent/lpg/common/model/WDd.java b/backend/lpg-common/src/main/java/com/hotent/lpg/common/model/WDd.java index b984570..9b4be0e 100644 --- a/backend/lpg-common/src/main/java/com/hotent/lpg/common/model/WDd.java +++ b/backend/lpg-common/src/main/java/com/hotent/lpg/common/model/WDd.java @@ -269,6 +269,31 @@ public class WDd extends BaseModel { private String fZfdh; + @ApiModelProperty(value = "是否退款(是,否)") + @TableField("F_sftk") + @JsonProperty("fSftk") + private String fSftk; + + + @ApiModelProperty(value = "退款单号") + @TableField("F_tkdh") + @JsonProperty("fTkdh") + private String fTkdh; + + @ApiModelProperty(value = "商户退款单号") + @TableField("F_shtkdh") + @JsonProperty("fShtkdh") + private String fShtkdh; + + + @ApiModelProperty(value = "退款时间") + @TableField("F_tksj") + @JsonProperty("fTksj") + private LocalDateTime fTksj; + + + + /** * 订单详情 */ diff --git a/backend/lpg-user/src/main/java/com/hotent/lpg/user/controller/DdConroller.java b/backend/lpg-user/src/main/java/com/hotent/lpg/user/controller/DdConroller.java index a3e646f..a219385 100644 --- a/backend/lpg-user/src/main/java/com/hotent/lpg/user/controller/DdConroller.java +++ b/backend/lpg-user/src/main/java/com/hotent/lpg/user/controller/DdConroller.java @@ -5,6 +5,7 @@ import com.baomidou.mybatisplus.core.metadata.IPage; import com.baomidou.mybatisplus.extension.plugins.pagination.Page; import com.hotent.base.model.CommonResult; import com.hotent.lpg.common.enums.DdlyEnum; +import com.hotent.lpg.common.enums.DdztEnum; import com.hotent.lpg.common.enums.UserlxEnum; import com.hotent.lpg.common.model.WDd; import com.hotent.lpg.common.model.WHydz; @@ -13,16 +14,20 @@ import com.hotent.lpg.user.dao.HydzDao; import com.hotent.lpg.user.dto.DdDto; import com.hotent.lpg.user.manager.DdManager; import com.hotent.lpg.user.manager.HyxxManager; +import com.hotent.lpg.user.manager.WxPayManager; import com.hotent.uc.util.ContextUtil; import io.swagger.annotations.ApiOperation; import io.swagger.annotations.ApiParam; +import lombok.extern.slf4j.Slf4j; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.validation.annotation.Validated; import org.springframework.web.bind.annotation.*; import javax.annotation.Resource; +import java.util.HashMap; import java.util.List; +@Slf4j @RestController //@RequestMapping("/customer/dd/") @RequestMapping("/user/order/") @@ -36,6 +41,8 @@ public class DdConroller { private HydzDao hydzDao; @Resource private HyxxManager wHyxxManager; + @Resource + private WxPayManager wxPayManager; /** @@ -82,49 +89,92 @@ public class DdConroller { return CommonResult.ok(); } - /** - * 创建订单 - * - * @param request - * @return - * @throws Exception - * @throws - */ - @PostMapping(value = "/save") +// /** +// * 创建订单 +// * +// * @param request +// * @return +// * @throws Exception +// * @throws +// */ +// @PostMapping(value = "/save") +// @ApiOperation(value = "创建订单", httpMethod = "POST", notes = "创建订单") +// public CommonResult createOrder(@ApiParam(name = "CreateOrderRequest", value = "创建订单请求对象", required = true) @RequestBody DdDto request) throws Exception { +// WHydz hydz = hydzDao.selectOneByHyIdAndDzId(ContextUtil.getCurrentUserId(), request.getHydzId()); +// if (BeanUtil.isEmpty(hydz)){ +// throw new RuntimeException("未查询到地址信息。"); +// } +// WHyxx hyxx = wHyxxManager.getUseridByInfo(ContextUtil.getCurrentUserId()); +// if (BeanUtil.isEmpty(hyxx)){ +// throw new RuntimeException("未查询会员信息。"); +// } +// request.setShlxr(hydz.getFLxr()); +// request.setShlxrdh(hydz.getFLxrdh()); +// request.setShsf(hydz.getFLxrsf()); +// request.setShs(hydz.getFLxrs()); +// request.setShq(hydz.getFLxrq()); +// request.setShjd(hydz.getFLxrjd()); +// request.setShxxdz(hydz.getFLxrxxdz()); +// request.setJd(hydz.getFJd()); +// request.setWd(hydz.getFWd()); +// +// request.setSfhy("是"); +// request.setHydh(hyxx.getFSjh()); //账号就是电话 +// request.setHyid(hyxx.getFUserid()); +// request.setHymc(hyxx.getFXm()); +// request.setHylx(hyxx.getFHylx()); +// request.setSfzh(hyxx.getFSfzh()); +// request.setShtysbm(hyxx.getFShtysbm()); +// +// request.setXdrlx(UserlxEnum.hy.getInfo()); +// request.setXdrid(ContextUtil.getCurrentUserId()); +// request.setXdrmc(ContextUtil.getCurrentUser().getFullname()); +// request.setDdly(DdlyEnum.xsxd.getInfo()); +// WDd order = wDdManager.createOrder(request); +// return CommonResult.ok().value(order); +// } + + @PostMapping(value = "/add") @ApiOperation(value = "创建订单", httpMethod = "POST", notes = "创建订单") - public CommonResult createOrder(@ApiParam(name = "CreateOrderRequest", value = "创建订单请求对象", required = true) @RequestBody DdDto request) throws Exception { - WHydz hydz = hydzDao.selectOneByHyIdAndDzId(ContextUtil.getCurrentUserId(), request.getHydzId()); - if (BeanUtil.isEmpty(hydz)){ + public CommonResult createOrder(@ApiParam(name = "CreateOrderRequest", value = "创建订单请求对象", required = true) @RequestBody DdDto ddDto) { + log.warn("创建订单1:{}", ddDto); + WHydz hydz = hydzDao.selectOneByHyIdAndDzId(ContextUtil.getCurrentUserId(), ddDto.getHydzId()); + if (BeanUtil.isEmpty(hydz)) { throw new RuntimeException("未查询到地址信息。"); } WHyxx hyxx = wHyxxManager.getUseridByInfo(ContextUtil.getCurrentUserId()); - if (BeanUtil.isEmpty(hyxx)){ + if (BeanUtil.isEmpty(hyxx)) { throw new RuntimeException("未查询会员信息。"); } - request.setShlxr(hydz.getFLxr()); - request.setShlxrdh(hydz.getFLxrdh()); - request.setShsf(hydz.getFLxrsf()); - request.setShs(hydz.getFLxrs()); - request.setShq(hydz.getFLxrq()); - request.setShjd(hydz.getFLxrjd()); - request.setShxxdz(hydz.getFLxrxxdz()); - request.setJd(hydz.getFJd()); - request.setWd(hydz.getFWd()); - - request.setSfhy("是"); - request.setHydh(hyxx.getFSjh()); //账号就是电话 - request.setHyid(hyxx.getFUserid()); - request.setHymc(hyxx.getFXm()); - request.setHylx(hyxx.getFHylx()); - request.setSfzh(hyxx.getFSfzh()); - request.setShtysbm(hyxx.getFShtysbm()); - - request.setXdrlx(UserlxEnum.hy.getInfo()); - request.setXdrid(ContextUtil.getCurrentUserId()); - request.setXdrmc(ContextUtil.getCurrentUser().getFullname()); - request.setDdly(DdlyEnum.xsxd.getInfo()); - WDd order = wDdManager.createOrder(request); - return CommonResult.ok().value(order); + ddDto.setShlxr(hydz.getFLxr()); + ddDto.setShlxrdh(hydz.getFLxrdh()); + ddDto.setShsf(hydz.getFLxrsf()); + ddDto.setShs(hydz.getFLxrs()); + ddDto.setShq(hydz.getFLxrq()); + ddDto.setShjd(hydz.getFLxrjd()); + ddDto.setShxxdz(hydz.getFLxrxxdz()); + ddDto.setJd(hydz.getFJd()); + ddDto.setWd(hydz.getFWd()); + + ddDto.setSfhy("是"); + ddDto.setHydh(hyxx.getFSjh()); //账号就是电话 + ddDto.setHyid(hyxx.getFUserid()); + ddDto.setHymc(hyxx.getFXm()); + ddDto.setHylx(hyxx.getFHylx()); + ddDto.setSfzh(hyxx.getFSfzh()); + ddDto.setShtysbm(hyxx.getFShtysbm()); + + ddDto.setXdrlx(UserlxEnum.hy.getInfo()); + ddDto.setXdrid(ContextUtil.getCurrentUserId()); + ddDto.setXdrmc(ContextUtil.getCurrentUser().getFullname()); + ddDto.setDdly(DdlyEnum.xsxd.getInfo()); + ddDto.setDdzt(DdztEnum.dzf.getInfo()); + WDd order = wDdManager.addOrder(ddDto); + log.warn("创建订单2:{}", order); + HashMap resultData = wxPayManager.generatePrepayOrder(order, ddDto.getOpenId()); + log.warn("创建订单3:{}", resultData); + return CommonResult.ok().value(resultData); } + } diff --git a/backend/lpg-user/src/main/java/com/hotent/lpg/user/controller/PaymentController.java b/backend/lpg-user/src/main/java/com/hotent/lpg/user/controller/PaymentController.java deleted file mode 100644 index b07aa50..0000000 --- a/backend/lpg-user/src/main/java/com/hotent/lpg/user/controller/PaymentController.java +++ /dev/null @@ -1,110 +0,0 @@ -package com.hotent.lpg.user.controller; - -import cn.hutool.core.bean.BeanUtil; -import com.hotent.base.model.CommonResult; -import com.hotent.lpg.common.enums.DdlyEnum; -import com.hotent.lpg.common.enums.DdztEnum; -import com.hotent.lpg.common.enums.UserlxEnum; -import com.hotent.lpg.common.model.WDd; -import com.hotent.lpg.common.model.WHydz; -import com.hotent.lpg.common.model.WHyxx; -import com.hotent.lpg.user.dao.HydzDao; -import com.hotent.lpg.user.dto.DdDto; -import com.hotent.lpg.user.enums.PayTypeEnum; -import com.hotent.lpg.user.manager.DdManager; -import com.hotent.lpg.user.manager.HyxxManager; -import com.hotent.lpg.user.manager.PaymentManage; -import com.hotent.lpg.user.vo.ResultData; -import com.hotent.uc.util.ContextUtil; -import io.swagger.annotations.ApiOperation; -import io.swagger.annotations.ApiParam; -import lombok.AllArgsConstructor; -import lombok.extern.slf4j.Slf4j; -import org.springframework.beans.factory.annotation.Autowired; -import org.springframework.validation.annotation.Validated; -import org.springframework.web.bind.annotation.*; - -import javax.annotation.Resource; -import java.util.HashMap; - -@RestController -@RequestMapping("/user/order/payment/") -@AllArgsConstructor -@Validated -@Slf4j -public class PaymentController { - private final PaymentManage paymentManage; - - private final DdManager wDdManager; - private final HydzDao hydzDao; - private final HyxxManager wHyxxManager; -// /** -// * 预支付 -// * @param ddid -// * @return -// */ -// @PostMapping("/{ddid}") -// public ResultData pay(@PathVariable("ddid") String ddid) { -// String payType = PayTypeEnum.WX.getName(); // 默认微信 -// return paymentManage.pay(ddid, payType); -// } - - - @PostMapping(value = "/add") - @ApiOperation(value = "创建订单", httpMethod = "POST", notes = "创建订单") - public CommonResult createOrder(@ApiParam(name = "CreateOrderRequest", value = "创建订单请求对象", required = true) @RequestBody DdDto ddDto) throws Exception { - log.warn("创建订单1:{}", ddDto); - WHydz hydz = hydzDao.selectOneByHyIdAndDzId(ContextUtil.getCurrentUserId(), ddDto.getHydzId()); - if (BeanUtil.isEmpty(hydz)){ - throw new RuntimeException("未查询到地址信息。"); - } - WHyxx hyxx = wHyxxManager.getUseridByInfo(ContextUtil.getCurrentUserId()); - if (BeanUtil.isEmpty(hyxx)){ - throw new RuntimeException("未查询会员信息。"); - } - ddDto.setShlxr(hydz.getFLxr()); - ddDto.setShlxrdh(hydz.getFLxrdh()); - ddDto.setShsf(hydz.getFLxrsf()); - ddDto.setShs(hydz.getFLxrs()); - ddDto.setShq(hydz.getFLxrq()); - ddDto.setShjd(hydz.getFLxrjd()); - ddDto.setShxxdz(hydz.getFLxrxxdz()); - ddDto.setJd(hydz.getFJd()); - ddDto.setWd(hydz.getFWd()); - - ddDto.setSfhy("是"); - ddDto.setHydh(hyxx.getFSjh()); //账号就是电话 - ddDto.setHyid(hyxx.getFUserid()); - ddDto.setHymc(hyxx.getFXm()); - ddDto.setHylx(hyxx.getFHylx()); - ddDto.setSfzh(hyxx.getFSfzh()); - ddDto.setShtysbm(hyxx.getFShtysbm()); - - ddDto.setXdrlx(UserlxEnum.hy.getInfo()); - ddDto.setXdrid(ContextUtil.getCurrentUserId()); - ddDto.setXdrmc(ContextUtil.getCurrentUser().getFullname()); - ddDto.setDdly(DdlyEnum.xsxd.getInfo()); - ddDto.setDdzt(DdztEnum.dzf.getInfo()); - WDd order = wDdManager.addOrder(ddDto); - log.warn("创建订单2:{}", order); - HashMap resultData = paymentManage.wxPay(order,ddDto.getOpenId()); - log.warn("创建订单3:{}", resultData); - return CommonResult.ok().value(resultData); - } - - - - - - /** - * 支付回调 - * @return - */ - @PostMapping("/notifyOrder") - public String notifyOrder(@RequestBody String xmlData) { - log.warn("支付回调:{}", xmlData); - String res = paymentManage.notifyOrder(xmlData); - log.warn("处理状态:{}", xmlData); - return xmlData; - } -} diff --git a/backend/lpg-user/src/main/java/com/hotent/lpg/user/controller/WxPayController.java b/backend/lpg-user/src/main/java/com/hotent/lpg/user/controller/WxPayController.java new file mode 100644 index 0000000..f6b1588 --- /dev/null +++ b/backend/lpg-user/src/main/java/com/hotent/lpg/user/controller/WxPayController.java @@ -0,0 +1,47 @@ +package com.hotent.lpg.user.controller; + + +import com.hotent.lpg.user.manager.WxPayManager; +import lombok.AllArgsConstructor; +import lombok.extern.slf4j.Slf4j; +import org.springframework.validation.annotation.Validated; +import org.springframework.web.bind.annotation.PostMapping; +import org.springframework.web.bind.annotation.RequestBody; +import org.springframework.web.bind.annotation.RequestMapping; +import org.springframework.web.bind.annotation.RestController; + +@RestController +@RequestMapping("/user/wxPay/") +@AllArgsConstructor +@Validated +@Slf4j +public class WxPayController { + private WxPayManager wxPayManager; + /** + * 处理支付成功回调 + * @param xmlData + * @return + */ + @PostMapping("/handlePaySuccessCallback") + public String handlePaySuccessCallback(@RequestBody String xmlData) { + log.warn("支付回调:{}", xmlData); + String res = wxPayManager.handlePaySuccessCallback(xmlData); + log.warn("处理状态:{}", xmlData); + return xmlData; + } + + + /** + * 处理退款成功回调 + * @param xmlData + * @return + */ + @PostMapping("/handleRefundSuccessCallback") + public String handleRefundSuccessCallback(@RequestBody String xmlData) { + log.warn("退款回调:{}", xmlData); + String res = wxPayManager.handleRefundSuccessCallback(xmlData); + log.warn("退款状态:{}", xmlData); + return res; + } + +} diff --git a/backend/lpg-user/src/main/java/com/hotent/lpg/user/manager/PaymentManage.java b/backend/lpg-user/src/main/java/com/hotent/lpg/user/manager/PaymentManage.java deleted file mode 100644 index fc53ac9..0000000 --- a/backend/lpg-user/src/main/java/com/hotent/lpg/user/manager/PaymentManage.java +++ /dev/null @@ -1,16 +0,0 @@ -package com.hotent.lpg.user.manager; - - -import com.hotent.lpg.common.model.WDd; -import com.hotent.lpg.user.vo.ResultData; - -import java.util.HashMap; - -public interface PaymentManage { -// ResultData pay(String ddid, String payType); - - String notifyOrder(String xmlData); - - HashMap wxPay(WDd order,String openId); - -} diff --git a/backend/lpg-user/src/main/java/com/hotent/lpg/user/manager/WxPayManager.java b/backend/lpg-user/src/main/java/com/hotent/lpg/user/manager/WxPayManager.java new file mode 100644 index 0000000..d8283ac --- /dev/null +++ b/backend/lpg-user/src/main/java/com/hotent/lpg/user/manager/WxPayManager.java @@ -0,0 +1,38 @@ +package com.hotent.lpg.user.manager; + +import com.hotent.lpg.common.model.WDd; + +import java.util.HashMap; + +public interface WxPayManager { + /** + * 退款 + * @param ddid + * @return + */ + String initiateRefundOrder(String ddid); + + /** + * 处理退款成功回调 + * @param xmlData + * @return + */ + String handleRefundSuccessCallback(String xmlData); + + + /** + * 处理支付成功回调 + * @param xmlData + * @return + */ + String handlePaySuccessCallback(String xmlData); + + + /** + * 生成预支付订单 + * @param order + * @param openId + * @return + */ + HashMap generatePrepayOrder(WDd order, String openId); +} diff --git a/backend/lpg-user/src/main/java/com/hotent/lpg/user/manager/impl/DdManagerImpl.java b/backend/lpg-user/src/main/java/com/hotent/lpg/user/manager/impl/DdManagerImpl.java index f78910f..6f3df0d 100644 --- a/backend/lpg-user/src/main/java/com/hotent/lpg/user/manager/impl/DdManagerImpl.java +++ b/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; import com.hotent.lpg.common.model.WDdxq; import com.hotent.lpg.common.model.WHyyqjl; import com.hotent.lpg.common.model.WQplx; +import com.hotent.lpg.user.dao.CzzfpzDao; import com.hotent.lpg.user.dao.DdDao; import com.hotent.lpg.user.dao.DdxqDao; import com.hotent.lpg.user.dao.QplxDao; import com.hotent.lpg.user.dto.DdDto; -import com.hotent.lpg.user.manager.DdManager; -import com.hotent.lpg.user.manager.DdfwrzManager; -import com.hotent.lpg.user.manager.HyxxManager; -import com.hotent.lpg.user.manager.HyyqjlManager; +import com.hotent.lpg.user.manager.*; import com.hotent.lpg.user.vo.DdxxVo; import com.hotent.uc.util.ContextUtil; import lombok.extern.slf4j.Slf4j; @@ -63,6 +61,11 @@ public class DdManagerImpl extends BaseManagerImpl implements DdMana private HyxxManager wHyxxManager; @Resource private HyyqjlManager wHyyqjlManager; + @Resource + private CzzfpzDao czzfpzDao; + @Resource + private WxPayManager wxPayManager; + @Override public WDd getDetail(String id) { WDd wDd = this.get(id); @@ -72,20 +75,29 @@ public class DdManagerImpl extends BaseManagerImpl implements DdMana wDd.setDdxqList(ddxqDao.selectList(new LambdaQueryWrapper().eq(WDdxq::getfDdid, wDd.getId()))); return wDd; } + @Override public void cancel(String ddid) { WDd dd = baseMapper.selectById(ddid); if (ObjectUtil.isNull(dd)) { throw new RuntimeException("参数错误:订单不存在"); } - if (DdztEnum.dps.getInfo().equals(dd.getFDdzt()) || DdztEnum.psz.getInfo().equals(dd.getFDdzt())) { - dd.setFDdzt(DdztEnum.yqx.getInfo()); - baseMapper.updateById(dd); - } else { + if (!(DdztEnum.dps.getInfo().equals(dd.getFDdzt()) || DdztEnum.psz.getInfo().equals(dd.getFDdzt()) || DdztEnum.dzf.getInfo().equals(dd.getFDdzt()))) { throw new RuntimeException("订单状态不正确"); } +// dd.setFDdzt(DdztEnum.yqx.getInfo()); +// baseMapper.updateById(dd); + + if (dd.getFDdly().equals("线上下单") && dd.getFZffs().equals("微信") && dd.getFSfzf().equals("是")) { + //线上下单+微信支付+已支付 才退款 + String shtkdh = wxPayManager.initiateRefundOrder(ddid); + dd.setFDdzt(DdztEnum.tkz.getInfo()); + dd.setFShtkdh(shtkdh); + dd.setFSftk("否"); + baseMapper.updateById(dd); + } //添加服务日志 - wDdfwrzManager.insertDdfwrz(DdfwlxEnum.qxdd.getCode(), dd.getId()); +// wDdfwrzManager.insertDdfwrz(DdfwlxEnum.qxdd.getCode(), dd.getId()); } @Override @@ -216,7 +228,7 @@ public class DdManagerImpl extends BaseManagerImpl implements DdMana dd.setFZflx(ddDto.getZflx()); dd.setFSfzf("否"); dd.setFPsfs(ddDto.getPsfs()); - dd.setFDdzt(StringUtil.isEmail(ddDto.getDdzt())?DdztEnum.dps.getInfo():ddDto.getDdzt()); + dd.setFDdzt(StringUtil.isEmail(ddDto.getDdzt()) ? DdztEnum.dps.getInfo() : ddDto.getDdzt()); dd.setFMjly(ddDto.getMjly()); dd.setFBz(ddDto.getBz()); dd.setFCzid(qplx.getfSsczid()); diff --git a/backend/lpg-user/src/main/java/com/hotent/lpg/user/manager/impl/PaymentManageImpl.java b/backend/lpg-user/src/main/java/com/hotent/lpg/user/manager/impl/PaymentManageImpl.java deleted file mode 100644 index 35c1017..0000000 --- a/backend/lpg-user/src/main/java/com/hotent/lpg/user/manager/impl/PaymentManageImpl.java +++ /dev/null @@ -1,213 +0,0 @@ -package com.hotent.lpg.user.manager.impl; - -import cn.hutool.core.util.RandomUtil; -import cn.hutool.core.util.StrUtil; -import com.alibaba.fastjson.JSONObject; -import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper; -import com.baomidou.mybatisplus.core.toolkit.Wrappers; -import com.github.binarywang.wxpay.bean.notify.WxPayNotifyResponse; -import com.github.binarywang.wxpay.bean.notify.WxPayOrderNotifyResult; -import com.github.binarywang.wxpay.bean.request.WxPayUnifiedOrderRequest; -import com.github.binarywang.wxpay.bean.result.WxPayUnifiedOrderResult; -import com.github.binarywang.wxpay.exception.WxPayException; -import com.github.binarywang.wxpay.service.WxPayService; - -import com.hotent.base.util.BeanUtils; -import com.hotent.lpg.common.model.WCzzfpz; -import com.hotent.lpg.common.model.WDd; -import com.hotent.lpg.common.model.WQpxx; -import com.hotent.lpg.user.dao.CzzfpzDao; -import com.hotent.lpg.user.dao.DdDao; -import com.hotent.lpg.user.enums.PayTypeEnum; -import com.hotent.lpg.user.manager.PaymentManage; -import com.hotent.lpg.user.util.LocalDateTimeUtils; -import com.hotent.lpg.user.util.WxPayConfiguration; -import com.hotent.lpg.user.vo.ResultData; -import lombok.AllArgsConstructor; -import lombok.extern.slf4j.Slf4j; -import org.springframework.stereotype.Service; -import org.springframework.transaction.annotation.Transactional; -import org.w3c.dom.Document; -import org.w3c.dom.Element; -import org.w3c.dom.Node; -import org.xml.sax.InputSource; - -import javax.xml.parsers.DocumentBuilder; -import javax.xml.parsers.DocumentBuilderFactory; -import javax.xml.transform.Transformer; -import javax.xml.transform.TransformerFactory; -import javax.xml.transform.dom.DOMSource; -import javax.xml.transform.stream.StreamResult; -import java.io.StringReader; -import java.io.StringWriter; -import java.math.BigDecimal; -import java.sql.Wrapper; -import java.time.LocalDateTime; -import java.util.HashMap; - -@Service -@Transactional -@AllArgsConstructor -@Slf4j -public class PaymentManageImpl implements PaymentManage { - private final DdDao ddDao; - private final CzzfpzDao czzfpzDao; - @Override - public String notifyOrder(String xmlData) { - // 从 XML 数据中提取支付单号 - String outTradeNo = extractValueFromXML(xmlData, "out_trade_no"); - //先用订单号找到订单 - WDd wDd = ddDao.selectOne(new LambdaQueryWrapper().eq(WDd::getFDddh, outTradeNo)); - //在用 场站信息 拿到场站对应得支付配置 - WCzzfpz wCzzfpz = czzfpzDao.selectOne(Wrappers.lambdaQuery().eq(WCzzfpz::getFCzid, wDd.getFCzid()).eq(WCzzfpz::getFZflx, wDd.getFZffs())); - WxPayService wxPayService = WxPayConfiguration.getPayService(wCzzfpz); - //下面依旧是走微信sdk,查询订单和验证订单,为了保证数据得安全性,还是重复验证一次 - String dddh = null; - try { - WxPayOrderNotifyResult notifyResult = wxPayService.parseOrderNotifyResult(xmlData); - // 获取订单编号 - dddh = notifyResult.getOutTradeNo(); - // 获取微信支付单号 - String transactionId = notifyResult.getTransactionId(); - wDd = ddDao.selectOne(new LambdaQueryWrapper().eq(WDd::getFDddh, dddh)); - if (wDd == null) { - log.warn("订单不存在: {}", dddh); - return generateXmlResponse("FAIL", "订单不存在", dddh); - } - // 检查订单状态是否已支付 - if ("已支付".equals(wDd.getFDdzt())) { - log.warn("订单 {} 已经处理过,忽略本次通知", dddh); - return generateXmlResponse("SUCCESS", "已处理过", dddh); - } - BigDecimal payPrice = wDd.getFDdje(); - if (payPrice.multiply(new BigDecimal(100)).intValue() != notifyResult.getTotalFee()) { - log.warn("付款金额与订单金额不等: {}", dddh); - return generateXmlResponse("FAIL", "付款金额与订单金额不等", dddh); - } - - String timeEnd = notifyResult.getTimeEnd(); - LocalDateTime paymentTime = LocalDateTimeUtils.parse(timeEnd); - wDd.setFFksj(paymentTime); - wDd.setFSfzf("是"); - wDd.setFDdzt("待配送"); - wDd.setFZfdh(transactionId); - ddDao.updateById(wDd); - - log.info("订单支付成功: {}", dddh); - return generateXmlResponse("SUCCESS", "成功", dddh); - } catch (WxPayException e) { - log.error("支付回调处理失败: {}", e.getErrCodeDes(), e); - return generateXmlResponse("FAIL", e.getErrCodeDes(), dddh); - } - } - - - private String extractValueFromXML(String xmlData, String paramName) { - // 解析 XML 数据以提取指定参数的值 - try { - DocumentBuilderFactory dbFactory = DocumentBuilderFactory.newInstance(); - DocumentBuilder dBuilder = dbFactory.newDocumentBuilder(); - InputSource is = new InputSource(new StringReader(xmlData)); - Document doc = dBuilder.parse(is); - - Element element = doc.getDocumentElement(); - Node paramNode = element.getElementsByTagName(paramName).item(0).getFirstChild(); - return paramNode != null ? paramNode.getNodeValue() : null; - } catch (Exception e) { - log.error("解析 XML 数据失败: {}", e.getMessage(), e); - return null; - } - } - - - private String generateXmlResponse(String returnCode, String returnMsg, String outTradeNo) { - DocumentBuilderFactory dbFactory = DocumentBuilderFactory.newInstance(); - DocumentBuilder dBuilder; - try { - dBuilder = dbFactory.newDocumentBuilder(); - Document doc = dBuilder.newDocument(); - - Element rootElement = doc.createElement("xml"); - doc.appendChild(rootElement); - - Element returnCodeElement = doc.createElement("return_code"); - returnCodeElement.appendChild(doc.createTextNode(returnCode)); - rootElement.appendChild(returnCodeElement); - - Element returnMsgElement = doc.createElement("return_msg"); - returnMsgElement.appendChild(doc.createTextNode(returnMsg)); - rootElement.appendChild(returnMsgElement); - - Element outTradeNoElement = doc.createElement("out_trade_no"); - outTradeNoElement.appendChild(doc.createTextNode(outTradeNo)); - rootElement.appendChild(outTradeNoElement); - - TransformerFactory transformerFactory = TransformerFactory.newInstance(); - Transformer transformer = transformerFactory.newTransformer(); - DOMSource source = new DOMSource(doc); - StringWriter writer = new StringWriter(); - StreamResult result = new StreamResult(writer); - transformer.transform(source, result); - return writer.toString(); - } catch (Exception e) { - log.error("构建 XML 响应失败", e); - return "FAIL处理失败"; - } - } - - @Override - public HashMap wxPay(WDd wDd,String openId) { - try { - WCzzfpz wCzzfpz = czzfpzDao.selectOne(Wrappers.lambdaQuery().eq(WCzzfpz::getFCzid, wDd.getFCzid()).eq(WCzzfpz::getFZflx, wDd.getFZffs())); - if (BeanUtils.isEmpty(wCzzfpz) || wCzzfpz == null) { - throw new RuntimeException("支付配置不存在"); - } - String tradeType = wDd.getFZflx(); - if (StrUtil.isBlank(tradeType)) { - throw new RuntimeException("支付方式错误"); - } - WxPayUnifiedOrderRequest wxPayUnifiedOrderRequest = new WxPayUnifiedOrderRequest(); - wxPayUnifiedOrderRequest.setAppid(wCzzfpz.getFAppid()); - wxPayUnifiedOrderRequest.setOpenid(null); - wxPayUnifiedOrderRequest.setBody(wDd.getFDddh()); - wxPayUnifiedOrderRequest.setOutTradeNo(wDd.getFDddh()); - wxPayUnifiedOrderRequest.setTotalFee(wDd.getFDdje().multiply(new BigDecimal(100)).intValue()); - wxPayUnifiedOrderRequest.setTradeType(tradeType); - log.warn("创建订单5:{}", wxPayUnifiedOrderRequest); - JSONObject scene_info = new JSONObject(); - scene_info.put("id", "LPG"); - scene_info.put("name", "燃气"); - wxPayUnifiedOrderRequest.setSceneInfo(scene_info.toString()); - wxPayUnifiedOrderRequest.setNotifyUrl("http://pmrsig.natappfree.cc/api/user/order/payment/notifyOrder"); // 支付回调地址,开放不用登录 - wxPayUnifiedOrderRequest.setSpbillCreateIp("127.0.0.1"); - // trade_type=APP时 移动应用内的支付场景 - if ("APP".equals(wxPayUnifiedOrderRequest.getTradeType())) { - wxPayUnifiedOrderRequest.setAppid(wCzzfpz.getFAppid()); - } - // trade_type=NATIVE时 线下消费场景 - if ("NATIVE".equals(wxPayUnifiedOrderRequest.getTradeType())) { - wxPayUnifiedOrderRequest.setProductId(wxPayUnifiedOrderRequest.getOutTradeNo()); - } - // 公众号内或者微信内的网页支付 - if ("JSAPI".equals(wxPayUnifiedOrderRequest.getTradeType())) { - wxPayUnifiedOrderRequest.setOpenid(openId); - } - // 手机浏览器中的支付场景 - if ("MWEB".equals(wxPayUnifiedOrderRequest.getTradeType())) { - wxPayUnifiedOrderRequest.setSceneInfo(null); - } - WxPayService wxPayService = WxPayConfiguration.getPayService(wCzzfpz); - Object payment = wxPayService.createOrder(wxPayUnifiedOrderRequest); - HashMap resultData = new HashMap(); - resultData.put("payment", payment); - resultData.put("ddid", wDd.getId()); - resultData.put("dddh", wDd.getFDddh()); - return resultData; - } catch (WxPayException e) { - if ("INVALID_REQUEST".equals(e.getErrCode())) { - throw new RuntimeException("订单号重复,请重新下单"); - } - throw new RuntimeException(e.getMessage()); - } - } -} diff --git a/backend/lpg-user/src/main/java/com/hotent/lpg/user/manager/impl/WxPayManagerImpl.java b/backend/lpg-user/src/main/java/com/hotent/lpg/user/manager/impl/WxPayManagerImpl.java new file mode 100644 index 0000000..0a39997 --- /dev/null +++ b/backend/lpg-user/src/main/java/com/hotent/lpg/user/manager/impl/WxPayManagerImpl.java @@ -0,0 +1,336 @@ +package com.hotent.lpg.user.manager.impl; + +import cn.hutool.core.util.RandomUtil; +import cn.hutool.core.util.StrUtil; +import com.alibaba.fastjson.JSONObject; +import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper; +import com.baomidou.mybatisplus.core.toolkit.Wrappers; +import com.github.binarywang.wxpay.bean.notify.WxPayOrderNotifyResult; +import com.github.binarywang.wxpay.bean.notify.WxPayRefundNotifyResult; +import com.github.binarywang.wxpay.bean.request.WxPayRefundRequest; +import com.github.binarywang.wxpay.bean.request.WxPayUnifiedOrderRequest; +import com.github.binarywang.wxpay.bean.result.WxPayRefundResult; +import com.github.binarywang.wxpay.exception.WxPayException; +import com.github.binarywang.wxpay.service.WxPayService; +import com.hotent.base.util.BeanUtils; +import com.hotent.lpg.common.enums.DdztEnum; +import com.hotent.lpg.common.model.WCzzfpz; +import com.hotent.lpg.common.model.WDd; +import com.hotent.lpg.user.dao.CzzfpzDao; +import com.hotent.lpg.user.dao.DdDao; +import com.hotent.lpg.user.manager.WxPayManager; +import com.hotent.lpg.user.util.LocalDateTimeUtils; +import com.hotent.lpg.user.util.WxPayConfiguration; +import lombok.AllArgsConstructor; +import lombok.extern.slf4j.Slf4j; +import org.springframework.stereotype.Service; +import org.w3c.dom.Document; +import org.w3c.dom.Element; +import org.w3c.dom.Node; +import org.xml.sax.InputSource; + +import javax.xml.bind.JAXBContext; +import javax.xml.parsers.DocumentBuilder; +import javax.xml.parsers.DocumentBuilderFactory; +import javax.xml.transform.Transformer; +import javax.xml.transform.TransformerFactory; +import javax.xml.transform.dom.DOMSource; +import javax.xml.transform.stream.StreamResult; +import javax.xml.xpath.XPath; +import javax.xml.xpath.XPathConstants; +import javax.xml.xpath.XPathFactory; +import java.io.StringReader; +import java.io.StringWriter; +import java.math.BigDecimal; +import java.time.LocalDateTime; +import java.util.HashMap; + +@Service +@AllArgsConstructor +@Slf4j +public class WxPayManagerImpl implements WxPayManager { + + private final DdDao ddDao; + private final CzzfpzDao czzfpzDao; + + /** + * 发起退款请求 + * + * @param ddid + * @return + */ + @Override + public String initiateRefundOrder(String ddid) { + // 1. 查询订单信息 + WDd wDd = ddDao.selectById(ddid); + if (!DdztEnum.dps.getInfo().equals(wDd.getFDdzt())) { + throw new RuntimeException("订单状态不正确"); + } + if (!(wDd.getFDdly().equals("线上下单") && wDd.getFZffs().equals("微信") && wDd.getFSfzf().equals("是"))) { + throw new RuntimeException("订单状态不正确"); + } + // 2. 获取支付配置 + WCzzfpz wCzzfpz = czzfpzDao.selectOne(Wrappers.lambdaQuery().eq(WCzzfpz::getFCzid, wDd.getFCzid()).eq(WCzzfpz::getFZflx, wDd.getFZffs())); + if (wCzzfpz == null) { + throw new RuntimeException("支付配置不存在"); + } + // 3. 初始化微信支付服务 + WxPayService wxPayService = WxPayConfiguration.getPayService(wCzzfpz); + try { + // 4. 调用微信退款接口 + // 这里需要构造退款请求对象,具体参数根据实际情况填写 + // 注意:这里需要根据实际的微信支付SDK版本和退款接口文档来调整 + // 示例代码可能需要根据实际情况修改 + String tkdh = RandomUtil.randomString(32); + WxPayRefundRequest refundRequest = new WxPayRefundRequest(); + refundRequest.setTransactionId(wDd.getFZfdh()); + refundRequest.setOutTradeNo(wDd.getFDddh()); // 订单号 + refundRequest.setOutRefundNo(RandomUtil.randomString(32)); // 退款单号 + refundRequest.setTotalFee(wDd.getFDdje().multiply(new BigDecimal(100)).intValue()); // 订单总金额 + refundRequest.setRefundFee(wDd.getFDdje().multiply(new BigDecimal(100)).intValue()); // 退款金额 + refundRequest.setNotifyUrl(WxPayConfiguration.hostUrl + "/user/wxPay/handleRefundSuccessCallback"); + // 发起退款请求 + Object payment = wxPayService.refund(refundRequest); + // 返回结果 + return tkdh; + } catch (WxPayException e) { + log.error("退款失败: {}", e.getErrCodeDes(), e); + throw new RuntimeException("退款失败: " + e.getErrCodeDes()); + } + } + + /** + * 处理退款成功回调 + * + * @param xmlData + * @return + */ + @Override + public String handleRefundSuccessCallback(String xmlData) { + WxPayOrderNotifyResult rs = WxPayOrderNotifyResult.fromXML(xmlData); + String returnCode = rs.getReturnCode(); + if (!returnCode.equals("SUCCESS")) { + return generateXmlResponse("FAIL", "退款失败", returnCode); + } + String appid = rs.getAppid(); + String mchId = rs.getMchId(); + //在用 场站信息 拿到场站对应得支付配置 + WCzzfpz wCzzfpz = czzfpzDao.selectOne(Wrappers.lambdaQuery().eq(WCzzfpz::getFAppid, appid).eq(WCzzfpz::getFMchid, mchId)); + WxPayService wxPayService = WxPayConfiguration.getPayService(wCzzfpz); + //下面依旧是走微信sdk,查询订单和验证订单,为了保证数据得安全性,还是重复验证一次 + String dddh = null; + try { + WxPayRefundNotifyResult notifyResult = wxPayService.parseRefundNotifyResult(xmlData); + WxPayRefundNotifyResult.ReqInfo reqInfo = notifyResult.getReqInfo(); + String refundId = reqInfo.getRefundId(); + String successTime = reqInfo.getSuccessTime(); + String transactionId = reqInfo.getTransactionId(); + String outTradeNo = reqInfo.getOutTradeNo(); + WDd wDd = ddDao.selectOne(Wrappers.lambdaQuery().eq(WDd::getFZfdh, transactionId).eq(WDd::getFDddh, outTradeNo)); + if (wDd == null) { + return generateXmlResponse("FAIL", "未查询到订单", outTradeNo); + } + if (wDd.getFSftk().equals("是")){ + return generateXmlResponse("FAIL", "订单已退款", outTradeNo); + } + // 5. 更新订单状态 + wDd.setFDdzt(DdztEnum.yqx.getInfo()); + wDd.setFSftk("是"); + wDd.setFTkdh(refundId); + wDd.setFTksj(LocalDateTimeUtils.parse(successTime)); + ddDao.updateById(wDd); + log.info("微信退款成功: {}", dddh); + return generateXmlResponse("SUCCESS", "成功", dddh); + } catch (WxPayException e) { + log.error("微信退款回调处理失败: {}", e.getErrCodeDes(), e); + return generateXmlResponse("FAIL", e.getErrCodeDes(), dddh); + } + } + + + + + /** + * 处理支付成功回调 + * + * @param xmlData + * @return + */ + @Override + public String handlePaySuccessCallback(String xmlData) { + // 从 XML 数据中提取支付单号 + String outTradeNo = extractValueFromXML(xmlData, "out_trade_no"); + //先用订单号找到订单 + WDd wDd = ddDao.selectOne(new LambdaQueryWrapper().eq(WDd::getFDddh, outTradeNo)); + //在用 场站信息 拿到场站对应得支付配置 + WCzzfpz wCzzfpz = czzfpzDao.selectOne(Wrappers.lambdaQuery().eq(WCzzfpz::getFCzid, wDd.getFCzid()).eq(WCzzfpz::getFZflx, wDd.getFZffs())); + WxPayService wxPayService = WxPayConfiguration.getPayService(wCzzfpz); + //下面依旧是走微信sdk,查询订单和验证订单,为了保证数据得安全性,还是重复验证一次 + String dddh = null; + try { + WxPayOrderNotifyResult notifyResult = wxPayService.parseOrderNotifyResult(xmlData); + // 获取订单编号 + dddh = notifyResult.getOutTradeNo(); + // 获取微信支付单号 + String transactionId = notifyResult.getTransactionId(); + wDd = ddDao.selectOne(new LambdaQueryWrapper().eq(WDd::getFDddh, dddh)); + if (wDd == null) { + log.warn("订单不存在: {}", dddh); + return generateXmlResponse("FAIL", "订单不存在", dddh); + } + // 检查订单状态是否已支付 + if ("已支付".equals(wDd.getFDdzt())) { + log.warn("订单 {} 已经处理过,忽略本次通知", dddh); + return generateXmlResponse("SUCCESS", "已处理过", dddh); + } + BigDecimal payPrice = wDd.getFDdje(); + if (payPrice.multiply(new BigDecimal(100)).intValue() != notifyResult.getTotalFee()) { + log.warn("付款金额与订单金额不等: {}", dddh); + return generateXmlResponse("FAIL", "付款金额与订单金额不等", dddh); + } + + String timeEnd = notifyResult.getTimeEnd(); + LocalDateTime paymentTime = LocalDateTimeUtils.parse(timeEnd); + wDd.setFFksj(paymentTime); + wDd.setFSfzf("是"); + wDd.setFDdzt("待配送"); + wDd.setFZfdh(transactionId); + ddDao.updateById(wDd); + + log.info("订单支付成功: {}", dddh); + return generateXmlResponse("SUCCESS", "成功", dddh); + } catch (WxPayException e) { + log.error("支付回调处理失败: {}", e.getErrCodeDes(), e); + return generateXmlResponse("FAIL", e.getErrCodeDes(), dddh); + } + } + + /** + * 生成预支付订单 + * @param wDd + * @param openId + * @return + */ + @Override + public HashMap generatePrepayOrder(WDd wDd, String openId) { + try { + WCzzfpz wCzzfpz = czzfpzDao.selectOne(Wrappers.lambdaQuery().eq(WCzzfpz::getFCzid, wDd.getFCzid()).eq(WCzzfpz::getFZflx, wDd.getFZffs())); + if (BeanUtils.isEmpty(wCzzfpz) || wCzzfpz == null) { + throw new RuntimeException("支付配置不存在"); + } + String tradeType = wDd.getFZflx(); + if (StrUtil.isBlank(tradeType)) { + throw new RuntimeException("支付方式错误"); + } + WxPayUnifiedOrderRequest wxPayUnifiedOrderRequest = new WxPayUnifiedOrderRequest(); + wxPayUnifiedOrderRequest.setAppid(wCzzfpz.getFAppid()); + wxPayUnifiedOrderRequest.setOpenid(null); + wxPayUnifiedOrderRequest.setBody(wDd.getFDddh()); + wxPayUnifiedOrderRequest.setOutTradeNo(wDd.getFDddh()); + wxPayUnifiedOrderRequest.setTotalFee(wDd.getFDdje().multiply(new BigDecimal(100)).intValue()); + wxPayUnifiedOrderRequest.setTradeType(tradeType); + JSONObject scene_info = new JSONObject(); + scene_info.put("id", "LPG"); + scene_info.put("name", "燃气"); + wxPayUnifiedOrderRequest.setSceneInfo(scene_info.toString()); + wxPayUnifiedOrderRequest.setNotifyUrl(WxPayConfiguration.hostUrl + "/user/wxPay/handlePaySuccessCallback"); // 支付回调地址,开放不用登录 + wxPayUnifiedOrderRequest.setSpbillCreateIp("127.0.0.1"); + // trade_type=APP时 移动应用内的支付场景 + if ("APP".equals(wxPayUnifiedOrderRequest.getTradeType())) { + wxPayUnifiedOrderRequest.setAppid(wCzzfpz.getFAppid()); + } + // trade_type=NATIVE时 线下消费场景 + if ("NATIVE".equals(wxPayUnifiedOrderRequest.getTradeType())) { + wxPayUnifiedOrderRequest.setProductId(wxPayUnifiedOrderRequest.getOutTradeNo()); + } + // 公众号内或者微信内的网页支付 + if ("JSAPI".equals(wxPayUnifiedOrderRequest.getTradeType())) { + wxPayUnifiedOrderRequest.setOpenid(openId); + } + // 手机浏览器中的支付场景 + if ("MWEB".equals(wxPayUnifiedOrderRequest.getTradeType())) { + wxPayUnifiedOrderRequest.setSceneInfo(null); + } + WxPayService wxPayService = WxPayConfiguration.getPayService(wCzzfpz); + Object payment = wxPayService.createOrder(wxPayUnifiedOrderRequest); + HashMap resultData = new HashMap(); + resultData.put("payment", payment); + resultData.put("ddid", wDd.getId()); + resultData.put("dddh", wDd.getFDddh()); + return resultData; + } catch (WxPayException e) { + if ("INVALID_REQUEST".equals(e.getErrCode())) { + throw new RuntimeException("订单号重复,请重新下单"); + } + throw new RuntimeException(e.getMessage()); + } + } + + /** + * 生成微信回调响应 + * + * @param returnCode + * @param returnMsg + * @param outTradeNo + * @return + */ + private String generateXmlResponse(String returnCode, String returnMsg, String outTradeNo) { + DocumentBuilderFactory dbFactory = DocumentBuilderFactory.newInstance(); + DocumentBuilder dBuilder; + try { + dBuilder = dbFactory.newDocumentBuilder(); + Document doc = dBuilder.newDocument(); + + Element rootElement = doc.createElement("xml"); + doc.appendChild(rootElement); + + Element returnCodeElement = doc.createElement("return_code"); + returnCodeElement.appendChild(doc.createTextNode(returnCode)); + rootElement.appendChild(returnCodeElement); + + Element returnMsgElement = doc.createElement("return_msg"); + returnMsgElement.appendChild(doc.createTextNode(returnMsg)); + rootElement.appendChild(returnMsgElement); + + Element outTradeNoElement = doc.createElement("out_trade_no"); + outTradeNoElement.appendChild(doc.createTextNode(outTradeNo)); + rootElement.appendChild(outTradeNoElement); + + TransformerFactory transformerFactory = TransformerFactory.newInstance(); + Transformer transformer = transformerFactory.newTransformer(); + DOMSource source = new DOMSource(doc); + StringWriter writer = new StringWriter(); + StreamResult result = new StreamResult(writer); + transformer.transform(source, result); + return writer.toString(); + } catch (Exception e) { + log.error("构建 XML 响应失败", e); + return "FAIL处理失败"; + } + } + + /** + * 从 XML 数据中提取指定参数的值 + * + * @param xmlData + * @param paramName + * @return + */ + private String extractValueFromXML(String xmlData, String paramName) { + // 解析 XML 数据以提取指定参数的值 + try { + DocumentBuilderFactory dbFactory = DocumentBuilderFactory.newInstance(); + DocumentBuilder dBuilder = dbFactory.newDocumentBuilder(); + InputSource is = new InputSource(new StringReader(xmlData)); + Document doc = dBuilder.parse(is); + + Element element = doc.getDocumentElement(); + Node paramNode = element.getElementsByTagName(paramName).item(0).getFirstChild(); + return paramNode != null ? paramNode.getNodeValue() : null; + } catch (Exception e) { + log.error("解析 XML 数据失败: {}", e.getMessage(), e); + return null; + } + } + +} diff --git a/backend/lpg-user/src/main/java/com/hotent/lpg/user/util/WxPayConfiguration.java b/backend/lpg-user/src/main/java/com/hotent/lpg/user/util/WxPayConfiguration.java index 27799d8..59b9d3a 100644 --- a/backend/lpg-user/src/main/java/com/hotent/lpg/user/util/WxPayConfiguration.java +++ b/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; import com.hotent.lpg.common.model.WCzzfpz; public class WxPayConfiguration { + + + public static final String hostUrl = "http://qyhtiz.natappfree.cc/api"; public static WxPayService getPayService(WCzzfpz wCzzfpz) { WxPayConfig wxPayConfig = new WxPayConfig(); wxPayConfig.setAppId(wCzzfpz.getFAppid()); // appId(应用id)(微信支付商户平台获取) @@ -18,6 +21,9 @@ public class WxPayConfiguration { wxPayConfig.setUseSandboxEnv(false); WxPayService wxPayService = new WxPayServiceImpl(); wxPayService.setConfig(wxPayConfig); + wxPayConfig.setKeyPath(wCzzfpz.getFKeypath()); + wxPayConfig.setPrivateKeyPath(wCzzfpz.getFPrivatekeypath()); + wxPayConfig.setPrivateCertPath(wCzzfpz.getFPrivatecertpath()); return wxPayService; } } -- libgit2 0.21.2