From 947a34b5b5a9fe40121ab2f600481811f79956cc Mon Sep 17 00:00:00 2001 From: sangelxiu1 <15781802@163.com> Date: Tue, 1 Jul 2025 14:57:00 +0800 Subject: [PATCH] =?UTF-8?q?##=20Feat=20-=20=E4=BA=AC=E4=B8=9C=E6=94=AF?= =?UTF-8?q?=E4=BB=98?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../third/pay/TOnlinePaymentSepAcc.java | 72 ++++++ .../third/pay/TOnlinePaymentSepAccD.java | 56 +++++ .../hzs/third/pay/config/JdPayProperties.java | 17 ++ .../config/JdPaySeparateAccountConfig.java | 14 ++ .../controller/api/JdRefundController.java | 91 ++++++++ .../pay/controller/api/PayController.java | 14 +- .../notify/JdPayNotifyController.java | 210 ++++++++++++++++++ .../notify/JdRefundNotifyController.java | 148 ++++++++++++ .../jdpay/dto/JdPayRefundSuccessNotify.java | 66 ++++++ .../jdpay/dto/JdPayTradeSuccessNotify.java | 98 ++++++++ .../mapper/TOnlinePaymentSepAccDMapper.java | 16 ++ .../mapper/TOnlinePaymentSepAccMapper.java | 16 ++ .../hzs/third/pay/service/IRefundService.java | 19 ++ .../ITOnlinePaymentSepAccDService.java | 16 ++ .../service/ITOnlinePaymentSepAccService.java | 16 ++ .../pay/service/impl/JdPayServiceImpl.java | 37 ++- .../pay/service/impl/RefundServiceImpl.java | 146 ++++++++++++ .../TOnlinePaymentSepAccDServiceImpl.java | 20 ++ .../impl/TOnlinePaymentSepAccServiceImpl.java | 59 +++++ bd-third/src/main/resources/bootstrap.yml | 15 +- .../third/pay/TOnlinePaymentSepAccDMapper.xml | 29 +++ .../third/pay/TOnlinePaymentSepAccMapper.xml | 31 +++ sql/2025年7月1日_京东支付_分账.sql | 89 ++++++++ 文档/支付/支付回调/京东 | 5 + 24 files changed, 1286 insertions(+), 14 deletions(-) create mode 100644 bd-common/bd-common-domain/src/main/java/com/hzs/common/domain/third/pay/TOnlinePaymentSepAcc.java create mode 100644 bd-common/bd-common-domain/src/main/java/com/hzs/common/domain/third/pay/TOnlinePaymentSepAccD.java create mode 100644 bd-third/src/main/java/com/hzs/third/pay/config/JdPayProperties.java create mode 100644 bd-third/src/main/java/com/hzs/third/pay/config/JdPaySeparateAccountConfig.java create mode 100644 bd-third/src/main/java/com/hzs/third/pay/controller/api/JdRefundController.java create mode 100644 bd-third/src/main/java/com/hzs/third/pay/controller/notify/JdPayNotifyController.java create mode 100644 bd-third/src/main/java/com/hzs/third/pay/controller/notify/JdRefundNotifyController.java create mode 100644 bd-third/src/main/java/com/hzs/third/pay/jdpay/dto/JdPayRefundSuccessNotify.java create mode 100644 bd-third/src/main/java/com/hzs/third/pay/jdpay/dto/JdPayTradeSuccessNotify.java create mode 100644 bd-third/src/main/java/com/hzs/third/pay/mapper/TOnlinePaymentSepAccDMapper.java create mode 100644 bd-third/src/main/java/com/hzs/third/pay/mapper/TOnlinePaymentSepAccMapper.java create mode 100644 bd-third/src/main/java/com/hzs/third/pay/service/ITOnlinePaymentSepAccDService.java create mode 100644 bd-third/src/main/java/com/hzs/third/pay/service/ITOnlinePaymentSepAccService.java create mode 100644 bd-third/src/main/java/com/hzs/third/pay/service/impl/TOnlinePaymentSepAccDServiceImpl.java create mode 100644 bd-third/src/main/java/com/hzs/third/pay/service/impl/TOnlinePaymentSepAccServiceImpl.java create mode 100644 bd-third/src/main/resources/mapper/third/pay/TOnlinePaymentSepAccDMapper.xml create mode 100644 bd-third/src/main/resources/mapper/third/pay/TOnlinePaymentSepAccMapper.xml create mode 100644 sql/2025年7月1日_京东支付_分账.sql create mode 100644 文档/支付/支付回调/京东 diff --git a/bd-common/bd-common-domain/src/main/java/com/hzs/common/domain/third/pay/TOnlinePaymentSepAcc.java b/bd-common/bd-common-domain/src/main/java/com/hzs/common/domain/third/pay/TOnlinePaymentSepAcc.java new file mode 100644 index 00000000..3d8d0a1d --- /dev/null +++ b/bd-common/bd-common-domain/src/main/java/com/hzs/common/domain/third/pay/TOnlinePaymentSepAcc.java @@ -0,0 +1,72 @@ +package com.hzs.common.domain.third.pay; + +import com.baomidou.mybatisplus.annotation.KeySequence; +import com.baomidou.mybatisplus.annotation.TableName; +import com.baomidou.mybatisplus.annotation.TableId; +import com.baomidou.mybatisplus.annotation.TableField; +import com.hzs.common.core.web.domain.BaseEntity; +import lombok.*; +import lombok.experimental.Accessors; + +import java.math.BigDecimal; +import java.util.List; + +/** + *

+ * 支付请求主表 + *

+ * + * @author bd + * @since 2025-07-01 + */ +@Data +@EqualsAndHashCode(callSuper = true) +@Accessors(chain = true) +@TableName("T_ONLINE_PAYMENT_SEP_ACC") +@KeySequence("T_ONLINE_PAYMENT_SEP_ACC_SEQ") +@Builder +@NoArgsConstructor +@AllArgsConstructor +public class TOnlinePaymentSepAcc extends BaseEntity { + + private static final long serialVersionUID = 1L; + + @TableId("PK_ID") + private Long pkId; + + /** + * 在线支付信息ID + */ + @TableField("PK_PAYMENT") + private Long pkPayment; + + /** + * 版本号 + */ + @TableField("VERSION") + private String version; + + /** + * 支付请求信息 + */ + @TableField("REQ_CONTENT") + private String reqContent; + + /** + * 分账请求信息 + */ + @TableField("REQ_CONTENT_SEP_ACC") + private String reqContentSepAcc; + + /** + * 支付响应信息 + */ + @TableField("RESP_CONTENT") + private String respContent; + + @TableField("TRADE_AMOUNT") + private BigDecimal tradeAmount; + + @TableField(exist = false) + private List sepAccDList; +} diff --git a/bd-common/bd-common-domain/src/main/java/com/hzs/common/domain/third/pay/TOnlinePaymentSepAccD.java b/bd-common/bd-common-domain/src/main/java/com/hzs/common/domain/third/pay/TOnlinePaymentSepAccD.java new file mode 100644 index 00000000..8cdcb72e --- /dev/null +++ b/bd-common/bd-common-domain/src/main/java/com/hzs/common/domain/third/pay/TOnlinePaymentSepAccD.java @@ -0,0 +1,56 @@ +package com.hzs.common.domain.third.pay; + +import java.math.BigDecimal; + +import com.baomidou.mybatisplus.annotation.KeySequence; +import com.baomidou.mybatisplus.annotation.TableName; +import com.baomidou.mybatisplus.annotation.TableId; +import com.baomidou.mybatisplus.annotation.TableField; +import com.hzs.common.core.web.domain.BaseEntity; +import lombok.*; +import lombok.experimental.Accessors; + +/** + *

+ * 支付请求子表(分账) + *

+ * + * @author bd + * @since 2025-07-01 + */ +@Data +@EqualsAndHashCode(callSuper = true) +@Accessors(chain = true) +@TableName("T_ONLINE_PAYMENT_SEP_ACC_D") +@KeySequence("T_ONLINE_PAYMENT_SEP_ACC_D_SEQ") +@Builder +@NoArgsConstructor +@AllArgsConstructor +public class TOnlinePaymentSepAccD extends BaseEntity { + + private static final long serialVersionUID = 1L; + + @TableId("PK_ID") + private Long pkId; + + /** + * 支付请求主表ID + */ + @TableField("PK_SEP_ACC") + private Long pkSepAcc; + + /** + * 分账账号 + */ + @TableField("ACCOUNT") + private String account; + + /** + * 分账比例 + */ + @TableField("PROPORTION") + private BigDecimal proportion; + + @TableField("TRADE_AMOUNT") + private BigDecimal tradeAmount; +} diff --git a/bd-third/src/main/java/com/hzs/third/pay/config/JdPayProperties.java b/bd-third/src/main/java/com/hzs/third/pay/config/JdPayProperties.java new file mode 100644 index 00000000..0da66bcc --- /dev/null +++ b/bd-third/src/main/java/com/hzs/third/pay/config/JdPayProperties.java @@ -0,0 +1,17 @@ +package com.hzs.third.pay.config; + +import lombok.Getter; +import lombok.Setter; +import org.springframework.boot.context.properties.ConfigurationProperties; +import org.springframework.stereotype.Component; + +import java.util.List; + +@Setter +@Getter +@Component +@ConfigurationProperties(prefix = "jd.pay") // 绑定jd.pay前缀的配置 +public class JdPayProperties { + private List separateAccounts; + +} diff --git a/bd-third/src/main/java/com/hzs/third/pay/config/JdPaySeparateAccountConfig.java b/bd-third/src/main/java/com/hzs/third/pay/config/JdPaySeparateAccountConfig.java new file mode 100644 index 00000000..d4d05f2f --- /dev/null +++ b/bd-third/src/main/java/com/hzs/third/pay/config/JdPaySeparateAccountConfig.java @@ -0,0 +1,14 @@ +package com.hzs.third.pay.config; + +import com.fasterxml.jackson.annotation.JsonFormat; +import lombok.Data; + +import java.io.Serializable; +import java.math.BigDecimal; + +@Data +public class JdPaySeparateAccountConfig implements Serializable { + private String account; + @JsonFormat(shape = JsonFormat.Shape.STRING) + private BigDecimal proportion; +} diff --git a/bd-third/src/main/java/com/hzs/third/pay/controller/api/JdRefundController.java b/bd-third/src/main/java/com/hzs/third/pay/controller/api/JdRefundController.java new file mode 100644 index 00000000..7bb9788f --- /dev/null +++ b/bd-third/src/main/java/com/hzs/third/pay/controller/api/JdRefundController.java @@ -0,0 +1,91 @@ +package com.hzs.third.pay.controller.api; + +import com.hzs.common.core.enums.EPayChannel; +import com.hzs.common.core.enums.EPayStatus; +import com.hzs.common.core.utils.StringUtils; +import com.hzs.common.core.web.domain.AjaxResult; +import com.hzs.common.domain.third.pay.TOnlinePayment; +import com.hzs.common.security.utils.SecurityUtils; +import com.hzs.third.pay.controller.base.PayBaseController; +import com.hzs.third.pay.dto.RefundDTO; +import com.hzs.third.pay.param.PayParam; +import com.hzs.third.pay.service.IRefundService; +import com.hzs.third.pay.service.ITOnlinePaymentService; +import lombok.extern.slf4j.Slf4j; +import org.springframework.beans.factory.annotation.Autowired; +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; + +/** + * @Description: 京东退款控制器 + * @Author: jiang chao + * @Time: 2023/8/17 15:11 + * @Classname: JdRefundController + * @PackageName: com.hzs.third.pay.controller.api + */ +@Slf4j +@RestController +@RequestMapping("/jd-refund") +public class JdRefundController extends PayBaseController { + + @Autowired + private IRefundService iRefundService; + @Autowired + private ITOnlinePaymentService itOnlinePaymentService; + + /** + * 京东退款接口 + * + * @param param + * @return + */ + @PostMapping("/refund") + public AjaxResult refund(@RequestBody PayParam param) { + if (null == param.getBusinessType() || StringUtils.isEmpty(param.getBusinessCode())) { + // 缺少参数 + return AjaxResult.error("缺少参数"); + } + // 查询在线支付明细 + TOnlinePayment tOnlinePayment = itOnlinePaymentService.queryByBusiness(param.getBusinessType(), param.getBusinessCode(), SecurityUtils.getPkCountry()); + if (null == tOnlinePayment || EPayStatus.UNPAID.getValue() == tOnlinePayment.getPayStatus()) { + // 在线支付明细为空 或者 未支付成功,则不能进行退款 + return AjaxResult.error("订单不存在或未支付成功,不能进行退款"); + } + // 获取支付渠道 + EPayChannel ePayChannel = EPayChannel.getEnumByValue(tOnlinePayment.getPayChannel()); + if (null == ePayChannel) { + return AjaxResult.error("订单支付信息有误,不能进行退款"); + } + + try { + // 京东收银台退款处理 + String str = iRefundService.jdCashRefundHandle(RefundDTO.builder() + .businessType(param.getBusinessType()) + .businessCode(param.getBusinessCode()) + .refundAmount(tOnlinePayment.getPayMoney()) + .userId(SecurityUtils.getUserId()) + .pkCountry(SecurityUtils.getPkCountry()) + .build(), + tOnlinePayment); + // 京东银行卡退款处理 -- 旧 +// String str = iRefundService.jdRefundHandle(RefundDTO.builder() +// .businessType(param.getBusinessType()) +// .businessCode(param.getBusinessCode()) +// .refundAmount(tOnlinePayment.getPayMoney()) +// .userId(SecurityUtils.getUserId()) +// .pkCountry(SecurityUtils.getPkCountry()) +// .build(), +// tOnlinePayment); + if (null == str) { + return AjaxResult.success(); + } + return AjaxResult.error("退款失败:" + str); + } catch (Exception e) { + log.error("调用京东退款处理返回异常!", e); + return AjaxResult.error("退款异常,请刷新后重试"); + } + } + +} diff --git a/bd-third/src/main/java/com/hzs/third/pay/controller/api/PayController.java b/bd-third/src/main/java/com/hzs/third/pay/controller/api/PayController.java index 46471d4c..e45f8a8f 100644 --- a/bd-third/src/main/java/com/hzs/third/pay/controller/api/PayController.java +++ b/bd-third/src/main/java/com/hzs/third/pay/controller/api/PayController.java @@ -252,8 +252,8 @@ public class PayController { if (null != payResult) { if (payResult.isSuccess()) { // 实际支付金额在支付之前不需要入库,实际以取支付回调为准 - onlinePayment.setPayMoney(null); - itOnlinePaymentService.saveOrUpdate(onlinePayment); +// onlinePayment.setPayMoney(null); +// itOnlinePaymentService.saveOrUpdate(onlinePayment); return AjaxResult.success(payResult.getData()); } @@ -275,13 +275,13 @@ public class PayController { } // 业务类型(校验业务类型) - EPayBusinessType ePayBusinessType = EPayBusinessType.getEnumByValue(param.getBusinessType()); - if (null == ePayBusinessType) { - return AjaxResult.success("支付业务类型错误", 0); - } +// EPayBusinessType ePayBusinessType = EPayBusinessType.getEnumByValue(param.getBusinessType()); +// if (null == ePayBusinessType) { +// return AjaxResult.success("支付业务类型错误", 0); +// } QueryWrapper queryWrapper = new QueryWrapper<>(); - queryWrapper.eq("BUSINESS_TYPE", param.getBusinessType()); +// queryWrapper.eq("BUSINESS_TYPE", param.getBusinessType()); queryWrapper.eq("BUSINESS_CODE", param.getBusinessCode()); TOnlinePayment onlinePayment = itOnlinePaymentService.getOne(queryWrapper); if (null == onlinePayment) { diff --git a/bd-third/src/main/java/com/hzs/third/pay/controller/notify/JdPayNotifyController.java b/bd-third/src/main/java/com/hzs/third/pay/controller/notify/JdPayNotifyController.java new file mode 100644 index 00000000..c8222d48 --- /dev/null +++ b/bd-third/src/main/java/com/hzs/third/pay/controller/notify/JdPayNotifyController.java @@ -0,0 +1,210 @@ +package com.hzs.third.pay.controller.notify; + +import cn.hutool.json.JSONUtil; +import com.hzs.common.core.enums.EPayChannel; +import com.hzs.common.core.utils.DateUtils; +import com.hzs.third.pay.config.JdPayConfig; +import com.hzs.third.pay.constants.JdPayConstants; +import com.hzs.third.pay.controller.base.JdBaseController; +import com.hzs.third.pay.dto.jd.JdPayNotifyBody; +import com.hzs.third.pay.jdpay.dto.JdPayTradeSuccessNotify; +import com.hzs.third.pay.jdpay.sdk.JdPay; +import com.hzs.third.pay.jdpay.util.GsonUtil; +import com.hzs.third.pay.service.IPayService; +import lombok.extern.slf4j.Slf4j; +import org.springframework.beans.factory.annotation.Autowired; +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; + +import javax.annotation.Resource; +import javax.servlet.http.HttpServletRequest; +import java.math.BigDecimal; +import java.util.Date; +import java.util.Enumeration; +import java.util.HashMap; +import java.util.Map; + +/** + * 京东支付回调控制器 + */ +@Slf4j +@RestController +@RequestMapping("/jd") +public class JdPayNotifyController extends JdBaseController { + + @Autowired + private JdPayConfig jdPayConfig; + @Autowired + private IPayService iPayService; + + /** + * 京东支付回调 + * + * @param request + */ + @PostMapping("/notify") + public String notify(HttpServletRequest request) { + try { + String reqBody = this.getRequestBody(request); + log.info("京东支付回调! body: {}", reqBody); + + if (this.checkToken(request, reqBody, jdPayConfig.getSecretKey())) { + // 签名校验通过 + JdPayNotifyBody notifyBody = JSONUtil.toBean(reqBody, JdPayNotifyBody.class); + + // 支付流水号 + String payNumber = notifyBody.getOrderNum(); + // 支付时间 + Date payTime = DateUtils.parseDate(notifyBody.getCompleteTime(), DateUtils.YYYY_MM_DD_HH_MM_SS); + // 支付金额 + BigDecimal payMoney = new BigDecimal(notifyBody.getOrderAmount()); + + // 支付扩展类型 + String type = notifyBody.getExtraInfo(); + + // 回调订单编号 + String thirdOrderCode = notifyBody.getRequestNum(); + // 支付信息编号 + String orderCode = thirdOrderCode; + // 处理订单号以及扩展类型 + if (orderCode.indexOf("-") > 0) { + // 带有分隔,需要处理 + orderCode = orderCode.split("-")[0]; + } + + // 支付后续业务处理 + if (iPayService.notifyHandle(type, orderCode, thirdOrderCode, payNumber, payTime, payMoney, EPayChannel.JD, "")) { + return JdPayConstants.RETURN_SUCCESS; + } + } else { + log.error("京东支付回调签名校验失败!"); + } + } catch (Exception e) { + log.error("京东支付回调处理异常", e); + } + return JdPayConstants.RETURN_FAIL; + } + + + @Resource + private JdPay jdPay; + + /** + * 京东收银台处理成功返回 + */ + private static final String SUCCESS = "SUCCESS"; + /** + * 京东收银台处理失败返回 + */ + private static final String ERROR = "ERROR"; + + /** + * 京东收银台异步支付回调 + * + * @param reqText + * @return 成功返回"SUCCESS", 失败返回"ERROR",京东支付会再次发起通知,通知频次见接口文档。 + */ + @PostMapping("/trade-notify") + public String tradeNotify(@RequestBody String reqText) { + log.info("京东收银台支付异步回调! reqText: {}", reqText); + try { + // 验证签名与解密 + String interData = jdPay.verifyResponse(reqText); + JdPayTradeSuccessNotify successNotify = GsonUtil.fromJson(interData, JdPayTradeSuccessNotify.class); + if (null != successNotify) { + if ("FINI".equals(successNotify.getTradeStatus())) { + // 支付成功处理 + + // 商户订单号 + String payNumber = successNotify.getTradeNo(); + // 渠道流水号 + String channelNumber = ""; + // 支付完成时间 + Date payTime = DateUtils.parseDateOne(successNotify.getFinishDate(), DateUtils.YAMMERERS); + // 支付扩展类型 + String type = successNotify.getReturnParams(); + + // 回调订单编号 + String thirdOrderCode = successNotify.getOutTradeNo(); + // 订单编号 + String orderCode = thirdOrderCode; + + // 订单金额 + int tradeAmount = Integer.parseInt(successNotify.getTradeAmount()); + BigDecimal payMoney = new BigDecimal(tradeAmount).divide(new BigDecimal("100"), 2, BigDecimal.ROUND_HALF_UP); + + // 支付后续业务处理 + if (iPayService.notifyHandle(type, orderCode, thirdOrderCode, payNumber, payTime, payMoney, EPayChannel.JD, channelNumber)) { + return SUCCESS; + } + } else { + log.error("京东收银台支付异步回调失败,resultDesc: {}", successNotify.getResultDesc()); + } + } else { + log.error("京东收银台支付异步回调解密为空"); + } + } catch (Exception e) { + log.error("京东收银台支付异步回调异常", e); + } + return ERROR; + } + + + /** + * 京东收银台页面回调 + * + * @param request + * @return + */ + @PostMapping("/sync-notify") + public String syncNotify(HttpServletRequest request) { + // 签名验证逻辑,需要支持添加通知字段不影响结果 + Map respMap = getAllRequestParam(request); + log.info("京东收银台支付页面回调! request: {}", respMap); + + try { + if (jdPay.verifyPageCallBack(respMap)) { + if ("FINI".equals(respMap.get("status"))) { + // todo 支付成功 + + return SUCCESS; + } else if ("WPAR".equals(respMap.get("status"))) { + // todo 支付处理中 + log.error("京东支付页面回调,支付处理中"); + } else { + // todo 支付失败 + log.error("京东支付页面回调,支付失败"); + } + } else { + // 签名异常,报错 + log.error("京东收银台支付页面回调!签名异常!"); + } + } catch (Exception e) { + log.error("京东支付页面回调参数", e); + } + return ERROR; + } + + /** + * 获取客户端请求参数中所有的信息 + */ + private Map getAllRequestParam(final HttpServletRequest request) { + Map respMap = new HashMap<>(); + Enumeration temp = request.getParameterNames(); + if (null != temp) { + while (temp.hasMoreElements()) { + String en = (String) temp.nextElement(); + String value = request.getParameter(en); + respMap.put(en, value); + //如果字段的值为空,判断若值为空,则删除这个字段> + if (null == respMap.get(en) || "".equals(respMap.get(en))) { + respMap.remove(en); + } + } + } + return respMap; + } + +} diff --git a/bd-third/src/main/java/com/hzs/third/pay/controller/notify/JdRefundNotifyController.java b/bd-third/src/main/java/com/hzs/third/pay/controller/notify/JdRefundNotifyController.java new file mode 100644 index 00000000..f6ff3ea0 --- /dev/null +++ b/bd-third/src/main/java/com/hzs/third/pay/controller/notify/JdRefundNotifyController.java @@ -0,0 +1,148 @@ +package com.hzs.third.pay.controller.notify; + +import cn.hutool.json.JSONUtil; +import com.hzs.common.core.enums.EPayChannel; +import com.hzs.common.core.utils.DateUtils; +import com.hzs.third.pay.config.JdPayConfig; +import com.hzs.third.pay.constants.JdPayConstants; +import com.hzs.third.pay.controller.base.JdBaseController; +import com.hzs.third.pay.jdpay.dto.JdPayRefundSuccessNotify; +import com.hzs.third.pay.jdpay.sdk.JdPay; +import com.hzs.third.pay.jdpay.util.GsonUtil; +import com.hzs.third.pay.service.IRefundService; +import lombok.extern.slf4j.Slf4j; +import org.springframework.beans.factory.annotation.Autowired; +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; + +import javax.annotation.Resource; +import javax.servlet.http.HttpServletRequest; +import java.math.BigDecimal; +import java.util.Date; +import java.util.HashMap; +import java.util.Map; + +/** + * @Description: 京东退填回调控制器 + * @Author: jiang chao + * @Time: 2023/8/17 15:50 + * @Classname: JdRefundNotifyController + * @PackageName: com.hzs.third.pay.controller.notify + */ +@Slf4j +@RestController +@RequestMapping("/jd-refund") +public class JdRefundNotifyController extends JdBaseController { + + @Autowired + private JdPayConfig jdPayConfig; + @Autowired + private IRefundService iRefundService; + + /** + * 京东退款回调 + * + * @param request + * @return + * @throws Exception + */ + @PostMapping("/notify") + public String refundNotify(HttpServletRequest request) { + try { + String reqBody = this.getRequestBody(request); + log.info("京东退款回调! body: {}", reqBody); + + if (this.checkToken(request, reqBody, jdPayConfig.getSecretKey())) { + // 签名校验通过 + Map dataMap = JSONUtil.toBean(reqBody, HashMap.class); + + // 退款编号 + String refundCode = dataMap.get("refundRequestNum"); + // 京东交易流水号 + String refundNumber = dataMap.get("orderNum"); + // 退款完成时间 + Date finishTime = DateUtils.parseDate(dataMap.get("refundSuccessTime"), DateUtils.YYYY_MM_DD_HH_MM_SS); + // 退款金额 + BigDecimal finishMoney = new BigDecimal(dataMap.get("refundAmount")); + + if (JdPayConstants.ORDER_SUCCESS.equals(dataMap.get("refundStatus"))) { + // 退款成功 + // 退款后续业务处理 + if (iRefundService.notifyHandle(EPayChannel.JD, refundCode, refundNumber, finishTime, finishMoney)) { + return JdPayConstants.RETURN_SUCCESS; + } + } else { + // 退款失败 + log.error("京东退款失败: {}", dataMap.get("failReason")); + + if (iRefundService.notifyErrorHandle(EPayChannel.JD, refundCode, refundNumber, dataMap.get("failReason"))) { + return JdPayConstants.RETURN_SUCCESS; + } + } + } else { + log.error("京东支付回调签名校验失败!"); + } + } catch (Exception e) { + log.error("京东支付回调处理异常", e); + } + return JdPayConstants.RETURN_FAIL; + } + + + @Resource + private JdPay jdPay; + + /** + * 京东收银台处理成功返回 + */ + private static final String SUCCESS = "SUCCESS"; + /** + * 京东收银台处理失败返回 + */ + private static final String ERROR = "ERROR"; + + /** + * 京东收银台退款异步支付回调 + * + * @param reqText + * @return 成功返回"SUCCESS", 失败返回"ERROR",退款通知会再次发起通知,通知频次见接口文档。 + */ + @PostMapping("/trade-notify") + public String tradeNotify(@RequestBody String reqText) { + log.info("京东收银台退款异步回调! reqText: {}", reqText); + try { + // 验证签名与解密 + String interData = jdPay.verifyResponse(reqText); + JdPayRefundSuccessNotify successNotify = GsonUtil.fromJson(interData, JdPayRefundSuccessNotify.class); + if (null != successNotify) { + if ("FINI".equals(successNotify.getTradeStatus())) { + + // 退款编号 + String refundCode = successNotify.getOutTradeNo(); + // 京东交易流水号 + String refundNumber = successNotify.getTradeNo(); + // 退款完成时间 + Date finishTime = DateUtils.parseDate(successNotify.getFinishDate(), DateUtils.YAMMERERS); + // 退款金额 + int tradeAmount = Integer.parseInt(successNotify.getTradeAmount()); + BigDecimal finishMoney = new BigDecimal(tradeAmount).divide(new BigDecimal("100"), 2, BigDecimal.ROUND_HALF_UP); + + // 退款后续业务处理 + if (iRefundService.notifyHandle(EPayChannel.JD, refundCode, refundNumber, finishTime, finishMoney)) { + return SUCCESS; + } + } else { + log.error("京东收银台退款异步回调失败,resultDesc: {}", successNotify.getResultDesc()); + } + } else { + log.error("京东收银台退款异步回调解密为空"); + } + } catch (Exception e) { + log.error("京东收银台退款异步回调异常", e); + } + return ERROR; + } + +} diff --git a/bd-third/src/main/java/com/hzs/third/pay/jdpay/dto/JdPayRefundSuccessNotify.java b/bd-third/src/main/java/com/hzs/third/pay/jdpay/dto/JdPayRefundSuccessNotify.java new file mode 100644 index 00000000..e3b25444 --- /dev/null +++ b/bd-third/src/main/java/com/hzs/third/pay/jdpay/dto/JdPayRefundSuccessNotify.java @@ -0,0 +1,66 @@ +package com.hzs.third.pay.jdpay.dto; + +import lombok.AllArgsConstructor; +import lombok.Builder; +import lombok.Data; +import lombok.NoArgsConstructor; + +import java.io.Serializable; + +/** + * @Description: 退款成功通知 + * @Author: jiang chao + * @Time: 2025/3/21 10:24 + * @Classname: JdPayRefundSuccessNotify + * @PackageName: com.hzs.third.pay.jdpay.dto + */ +@Builder +@AllArgsConstructor +@NoArgsConstructor +@Data +public class JdPayRefundSuccessNotify implements Serializable { + + /** + * 业务结果 + */ + private String resultCode; + /** + * 响应描述 + */ + private String resultDesc; + + /** + * 京东退款订单号 + */ + private String tradeNo; + + /** + * 商户退款订单号 + */ + private String outTradeNo; + /** + * 商户原正单订单号 + */ + private String originalOutTradeNo; + /** + * 订单总金额 + */ + private String tradeAmount; + /** + * 退款完成时间 + */ + private String finishDate; + /** + * 交易状态 + */ + private String tradeStatus; + /** + * 回传字段 + */ + private String returnParams; + /** + * 币种 + */ + private String currency; + +} diff --git a/bd-third/src/main/java/com/hzs/third/pay/jdpay/dto/JdPayTradeSuccessNotify.java b/bd-third/src/main/java/com/hzs/third/pay/jdpay/dto/JdPayTradeSuccessNotify.java new file mode 100644 index 00000000..a42ba4fb --- /dev/null +++ b/bd-third/src/main/java/com/hzs/third/pay/jdpay/dto/JdPayTradeSuccessNotify.java @@ -0,0 +1,98 @@ +package com.hzs.third.pay.jdpay.dto; + +import lombok.AllArgsConstructor; +import lombok.Builder; +import lombok.Data; +import lombok.NoArgsConstructor; + +import java.io.Serializable; + +/** + * @Description: 交易成功通知 + * @Author: jiang chao + * @Time: 2025/3/21 10:24 + * @Classname: JdPayRefundSuccessNotify + * @PackageName: com.hzs.third.pay.jdpay.dto + */ +@Builder +@AllArgsConstructor +@NoArgsConstructor +@Data +public class JdPayTradeSuccessNotify implements Serializable { + + /** + * 业务结果 + */ + private String resultCode; + /** + * 响应描述 + */ + private String resultDesc; + + /** + * 京东交易订单号 + */ + private String tradeNo; + + /** + * 商户订单号 + */ + private String outTradeNo; + /** + * 订单总金额 + */ + private String tradeAmount; + /** + * 币种 + */ + private String currency; + /** + * 支付完成时间 + */ + private String finishDate; + /** + * 交易类型 + */ + private String tradeType; + /** + * 交易状态 + */ + private String tradeStatus; + /** + * 回传字段 + */ + private String returnParams; + /** + * 请求的端 + */ + private String clientType; + /** + * 商户用户标识 + */ + private String userId; + /** + * 优惠金额 + */ + private String discountAmount; + /** + * 支付工具 + */ + private String payTool; + /** + * 掩码卡号 + */ + private String maskCardNo; + /** + * 卡类型 + */ + private String cardType; + /** + * 银行编码 + */ + private String bankCode; + /** + * 白条分期数 + */ + private String installmentNum; + +} diff --git a/bd-third/src/main/java/com/hzs/third/pay/mapper/TOnlinePaymentSepAccDMapper.java b/bd-third/src/main/java/com/hzs/third/pay/mapper/TOnlinePaymentSepAccDMapper.java new file mode 100644 index 00000000..2d355e24 --- /dev/null +++ b/bd-third/src/main/java/com/hzs/third/pay/mapper/TOnlinePaymentSepAccDMapper.java @@ -0,0 +1,16 @@ +package com.hzs.third.pay.mapper; + +import com.baomidou.mybatisplus.core.mapper.BaseMapper; +import com.hzs.common.domain.third.pay.TOnlinePaymentSepAccD; + +/** + *

+ * 支付请求子表(分账) Mapper 接口 + *

+ * + * @author bd + * @since 2025-07-01 + */ +public interface TOnlinePaymentSepAccDMapper extends BaseMapper { + +} diff --git a/bd-third/src/main/java/com/hzs/third/pay/mapper/TOnlinePaymentSepAccMapper.java b/bd-third/src/main/java/com/hzs/third/pay/mapper/TOnlinePaymentSepAccMapper.java new file mode 100644 index 00000000..64655522 --- /dev/null +++ b/bd-third/src/main/java/com/hzs/third/pay/mapper/TOnlinePaymentSepAccMapper.java @@ -0,0 +1,16 @@ +package com.hzs.third.pay.mapper; + +import com.baomidou.mybatisplus.core.mapper.BaseMapper; +import com.hzs.common.domain.third.pay.TOnlinePaymentSepAcc; + +/** + *

+ * 支付请求主表 Mapper 接口 + *

+ * + * @author bd + * @since 2025-07-01 + */ +public interface TOnlinePaymentSepAccMapper extends BaseMapper { + +} diff --git a/bd-third/src/main/java/com/hzs/third/pay/service/IRefundService.java b/bd-third/src/main/java/com/hzs/third/pay/service/IRefundService.java index d1405669..68f5cafa 100644 --- a/bd-third/src/main/java/com/hzs/third/pay/service/IRefundService.java +++ b/bd-third/src/main/java/com/hzs/third/pay/service/IRefundService.java @@ -44,4 +44,23 @@ public interface IRefundService { */ boolean notifyErrorHandle(EPayChannel ePayChannel, String refundCode, String refundNumber, String errorMsg); + + /** + * 京东退款处理 + * + * @param refundDTO 业务类型 + * @param tOnlinePayment 退款对应支付信息 + * @return + */ + String jdRefundHandle(RefundDTO refundDTO, TOnlinePayment tOnlinePayment); + + /** + * 京东收银台退款处理 + * + * @param refundDTO 业务类型 + * @param tOnlinePayment 退款对应支付信息 + * @return + */ + String jdCashRefundHandle(RefundDTO refundDTO, TOnlinePayment tOnlinePayment); + } diff --git a/bd-third/src/main/java/com/hzs/third/pay/service/ITOnlinePaymentSepAccDService.java b/bd-third/src/main/java/com/hzs/third/pay/service/ITOnlinePaymentSepAccDService.java new file mode 100644 index 00000000..4cf631ee --- /dev/null +++ b/bd-third/src/main/java/com/hzs/third/pay/service/ITOnlinePaymentSepAccDService.java @@ -0,0 +1,16 @@ +package com.hzs.third.pay.service; + +import com.baomidou.mybatisplus.extension.service.IService; +import com.hzs.common.domain.third.pay.TOnlinePaymentSepAccD; + +/** + *

+ * 支付请求子表(分账) 服务类 + *

+ * + * @author bd + * @since 2025-07-01 + */ +public interface ITOnlinePaymentSepAccDService extends IService { + +} diff --git a/bd-third/src/main/java/com/hzs/third/pay/service/ITOnlinePaymentSepAccService.java b/bd-third/src/main/java/com/hzs/third/pay/service/ITOnlinePaymentSepAccService.java new file mode 100644 index 00000000..dd382d26 --- /dev/null +++ b/bd-third/src/main/java/com/hzs/third/pay/service/ITOnlinePaymentSepAccService.java @@ -0,0 +1,16 @@ +package com.hzs.third.pay.service; + +import com.baomidou.mybatisplus.extension.service.IService; +import com.hzs.common.domain.third.pay.TOnlinePaymentSepAcc; + +/** + *

+ * 支付请求主表 服务类 + *

+ * + * @author bd + * @since 2025-07-01 + */ +public interface ITOnlinePaymentSepAccService extends IService { + void saveOrUpdateReq(TOnlinePaymentSepAcc tOnlinePaymentSepAcc); +} diff --git a/bd-third/src/main/java/com/hzs/third/pay/service/impl/JdPayServiceImpl.java b/bd-third/src/main/java/com/hzs/third/pay/service/impl/JdPayServiceImpl.java index b6e58684..d3a17d31 100644 --- a/bd-third/src/main/java/com/hzs/third/pay/service/impl/JdPayServiceImpl.java +++ b/bd-third/src/main/java/com/hzs/third/pay/service/impl/JdPayServiceImpl.java @@ -1,5 +1,6 @@ package com.hzs.third.pay.service.impl; +import cn.hutool.core.util.ObjectUtil; import cn.hutool.json.JSONUtil; import com.hzs.common.core.config.BdConfig; import com.hzs.common.core.domain.R; @@ -9,7 +10,11 @@ import com.hzs.common.core.enums.EEnv; import com.hzs.common.core.utils.DateUtils; import com.hzs.common.domain.third.pay.TOnlineCard; import com.hzs.common.domain.third.pay.TOnlinePayment; +import com.hzs.common.domain.third.pay.TOnlinePaymentSepAcc; +import com.hzs.common.domain.third.pay.TOnlinePaymentSepAccD; import com.hzs.third.pay.config.JdPayConfig; +import com.hzs.third.pay.config.JdPayProperties; +import com.hzs.third.pay.config.JdPaySeparateAccountConfig; import com.hzs.third.pay.constants.JdPayConstants; import com.hzs.third.pay.constants.PayRedisConstants; import com.hzs.third.pay.dto.jd.JdFastDTO; @@ -20,9 +25,14 @@ import com.hzs.third.pay.enums.EJdAppType; import com.hzs.third.pay.enums.EJdTerminalType; import com.hzs.third.pay.jdpay.dto.JdPayAggregateCreateOrderRequest; import com.hzs.third.pay.jdpay.dto.JdPayAggregateCreateOrderResponse; +import com.hzs.third.pay.jdpay.dto.JdPayDivisionAccount; +import com.hzs.third.pay.jdpay.dto.JdPayDivisionAccountTradeInfo; import com.hzs.third.pay.jdpay.sdk.JdPay; +import com.hzs.third.pay.jdpay.util.GsonUtil; import com.hzs.third.pay.service.IJdPayService; import com.hzs.third.pay.service.ITOnlineCardService; +import com.hzs.third.pay.service.ITOnlinePaymentSepAccService; +import com.hzs.third.pay.service.ITOnlinePaymentService; import com.hzs.third.pay.util.JdPayUtil; import com.hzs.third.pay.util.PayUtil; import lombok.extern.slf4j.Slf4j; @@ -34,6 +44,8 @@ import org.springframework.stereotype.Service; import javax.annotation.Resource; import java.math.BigDecimal; import java.net.InetAddress; +import java.util.ArrayList; +import java.util.List; import java.util.concurrent.TimeUnit; /** @@ -49,9 +61,15 @@ public class JdPayServiceImpl implements IJdPayService { private ITOnlineCardService itOnlineCardService; @Resource private JdPay jdPay; - + @Autowired + private JdPayProperties jdPayProperties; @Autowired private RedisTemplate redisTemplate; + @Autowired + private ITOnlinePaymentSepAccService itOnlinePaymentSepAccService; + + @Autowired + private ITOnlinePaymentService itOnlinePaymentService; /** * 页面回调地址 @@ -241,12 +259,24 @@ public class JdPayServiceImpl implements IJdPayService { // 请求京东支付接口 JdPayAggregateCreateOrderResponse response = jdPay.aggregateCreateOrder(request); - + TOnlinePaymentSepAcc sepAcc = TOnlinePaymentSepAcc.builder() + .sepAccDList(sepAccDList) + .reqContent(request.getDivisionAccount()) + .reqContentSepAcc(JSONUtil.toJsonStr(divisionAccountTradeInfoList)) + .version(divisionAccount.getVersion()) + .respContent(JSONUtil.toJsonStr(response)) + .tradeAmount(onlinePayment.getPayMoney()) + .build(); if ("0000".equals(response.getResultCode())) { // 请求响应成功 // 京东唯一订单号 onlinePayment.setPayNumber(response.getTradeNo()); - + // 将controller内入库逻辑移至此为止 + onlinePayment.setPayMoney(null); + itOnlinePaymentService.saveOrUpdate(onlinePayment); + // 2025年7月1日 保存分账主表&子表 + sepAcc.setPkPayment(onlinePayment.getPkId()); + itOnlinePaymentSepAccService.saveOrUpdateReq(sepAcc); if ("AGGRE_QR".equals(tradeType)) { return R.ok(response.getQrCode()); } @@ -261,4 +291,5 @@ public class JdPayServiceImpl implements IJdPayService { } } + } diff --git a/bd-third/src/main/java/com/hzs/third/pay/service/impl/RefundServiceImpl.java b/bd-third/src/main/java/com/hzs/third/pay/service/impl/RefundServiceImpl.java index 9d747ee8..8d93de4c 100644 --- a/bd-third/src/main/java/com/hzs/third/pay/service/impl/RefundServiceImpl.java +++ b/bd-third/src/main/java/com/hzs/third/pay/service/impl/RefundServiceImpl.java @@ -1,5 +1,6 @@ package com.hzs.third.pay.service.impl; +import cn.hutool.json.JSONUtil; import com.hzs.common.core.domain.R; import com.hzs.common.core.enums.*; import com.hzs.common.core.utils.*; @@ -10,14 +11,20 @@ import com.hzs.sale.refund.ISaRefundServiceApi; import com.hzs.third.pay.config.*; import com.hzs.third.pay.constants.*; import com.hzs.third.pay.dto.RefundDTO; +import com.hzs.third.pay.jdpay.dto.JdPayRefundRequest; +import com.hzs.third.pay.jdpay.dto.JdPayRefundResponse; +import com.hzs.third.pay.jdpay.sdk.JdPay; import com.hzs.third.pay.service.IAllInPayService; import com.hzs.third.pay.service.IRefundService; import com.hzs.third.pay.service.ITOnlineRefundService; +import com.hzs.third.pay.util.JdPayUtil; import lombok.extern.slf4j.Slf4j; import org.apache.dubbo.config.annotation.DubboReference; import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.beans.factory.annotation.Value; import org.springframework.stereotype.Service; +import javax.annotation.Resource; import java.math.BigDecimal; import java.net.InetAddress; import java.util.*; @@ -35,9 +42,17 @@ public class RefundServiceImpl implements IRefundService { private IAllInPayService iAllInPayService; @Autowired private ITOnlineRefundService itOnlineRefundService; + @Autowired + private JdPayConfig jdPayConfig; @DubboReference ISaRefundServiceApi iSaRefundServiceApi; + @Value("${jd.pay.refundNotifyUrl}") + private String refundNotifyUrl; + + @Resource + private JdPay jdPay; + @Override public String allInRefundHandle(RefundDTO refundDTO, TOnlinePayment tOnlinePayment) { @@ -251,4 +266,135 @@ public class RefundServiceImpl implements IRefundService { return false; } + + @Override + public String jdRefundHandle(RefundDTO refundDTO, TOnlinePayment tOnlinePayment) { + try { + // 退款金额(默认按全款退) + BigDecimal amount = tOnlinePayment.getPayMoney(); + if (null != refundDTO.getRefundAmount()) { + // 如果传入实际退款金额,则按实际退款金额处理 + amount = refundDTO.getRefundAmount(); + } + + // 退款编号 + String refundCode = CommonUtil.createSerialNumber(EOrderPrefix.REFUND_CODE); + + Map requestMap = new HashMap<>(); + requestMap.put("version", JdPayConstants.PAY_VERSION); + // 商户编号 + requestMap.put("customerNum", jdPayConfig.getCustomerNum()); + // 店铺编号 + requestMap.put("shopNum", jdPayConfig.getShopNum()); + + // 商户订单号 + requestMap.put("requestNum", tOnlinePayment.getOriginalOrder()); + // 商户退款订单号 + requestMap.put("refundRequestNum", refundCode); + // 退款金额 + requestMap.put("refundPartAmount", amount.toString()); + // 退款回调地址 + requestMap.put("callbackUrl", jdPayConfig.getRefundCallbackUrl()); + + String body = JSONUtil.toJsonStr(requestMap); + + log.info("京东退款请求参数: {}", body); + + String postResult = JdPayUtil.requestOrder(JdPayConstants.REFUND_ORDER, body, jdPayConfig.getSecretKey(), jdPayConfig.getAccessKey()); + + log.info("京东退款返回数据: {}", postResult); + + Map resultMap = JSONUtil.toBean(postResult, HashMap.class); + + if (JdPayConstants.RESULT_SUCCESS.equals(resultMap.get("result").toString())) { + // 返回成功 + + // 返回业务数据 + cn.hutool.json.JSONObject jsonObject = JSONUtil.parseObj(resultMap.get("data")); + + // 申请退款成功,保存退款 + TOnlineRefund tOnlineRefund = new TOnlineRefund(); + tOnlineRefund.setRefundCode(refundCode); + tOnlineRefund.setPkOnlinePayment(tOnlinePayment.getPkId()); + tOnlineRefund.setBusinessCode(refundDTO.getRefundBusinessCode()); + tOnlineRefund.setRefundMoney(amount); + tOnlineRefund.setRefundChannel(tOnlinePayment.getPayChannel()); + tOnlineRefund.setRefundNumber(jsonObject.getStr("orderNum")); + tOnlineRefund.setPkCountry(refundDTO.getPkCountry()); + tOnlineRefund.setPkCreator(refundDTO.getUserId()); + if (itOnlineRefundService.save(tOnlineRefund)) { + return null; + } + log.error("调用京东退款入库失败, tOnlineRefund: {}", tOnlineRefund); + } else { + log.error("调用京东退款返回失败:{}", resultMap.get("errorMsg")); + } + return "退款失败,请重试"; + } catch (Exception e) { + log.error("调用京东退款处理返回异常!", e); + return "退款异常,请重试"; + } + } + + @Override + public String jdCashRefundHandle(RefundDTO refundDTO, TOnlinePayment tOnlinePayment) { + try { + // 退款金额(默认按全款退) + BigDecimal amount = tOnlinePayment.getPayMoney(); + if (null != refundDTO.getRefundAmount()) { + // 如果传入实际退款金额,则按实际退款金额处理 + amount = refundDTO.getRefundAmount(); + } + + // 退款编号 + String refundCode = CommonUtil.createSerialNumber(EOrderPrefix.REFUND_CODE); + // 当前时间 + Date nowDate = new Date(); + + JdPayRefundRequest request = JdPayRefundRequest.builder() + // 退款订单号 + .outTradeNo(refundCode) + // 原订单号(需要退款的订单号) + .originalOutTradeNo(tOnlinePayment.getBusinessCode()) + // 退款时间 + .tradeDate(DateUtils.parseDateToFormat(DateUtils.YAMMERERS, nowDate)) + // 退款金额 + .tradeAmount(amount.multiply(new BigDecimal("100")).intValue() + "") + // 货币种类 + .currency("CNY") + // 退款回调地址 + .notifyUrl(this.refundNotifyUrl) + // 回传信息 +// .returnParams("") + .build(); + + // 请求京东退款接口 + JdPayRefundResponse response = jdPay.refund(request); + + if ("0000".equals(response.getResultCode())) { + // 请求响应成功 + // 申请退款成功,保存退款 + TOnlineRefund tOnlineRefund = new TOnlineRefund(); + tOnlineRefund.setRefundCode(refundCode); + tOnlineRefund.setPkOnlinePayment(tOnlinePayment.getPkId()); + tOnlineRefund.setBusinessCode(refundDTO.getRefundBusinessCode()); + tOnlineRefund.setRefundMoney(amount); + tOnlineRefund.setRefundChannel(tOnlinePayment.getPayChannel()); + tOnlineRefund.setRefundNumber(response.getTradeNo()); + tOnlineRefund.setPkCountry(refundDTO.getPkCountry()); + tOnlineRefund.setPkCreator(refundDTO.getUserId()); + if (itOnlineRefundService.save(tOnlineRefund)) { + return null; + } else { + log.error("调用京东收银台退款入库处理失败,desc: {}", response.getResultDesc()); + return "退款失败,请联系系统管理员处理"; + } + } + log.error("调用京东收银台退款处理失败,desc: {}", response.getResultDesc()); + return "退款失败,请重试"; + } catch (Exception e) { + log.error("调用京东收银台退款处理返回异常!", e); + return "退款异常,请重试"; + } + } } diff --git a/bd-third/src/main/java/com/hzs/third/pay/service/impl/TOnlinePaymentSepAccDServiceImpl.java b/bd-third/src/main/java/com/hzs/third/pay/service/impl/TOnlinePaymentSepAccDServiceImpl.java new file mode 100644 index 00000000..58929229 --- /dev/null +++ b/bd-third/src/main/java/com/hzs/third/pay/service/impl/TOnlinePaymentSepAccDServiceImpl.java @@ -0,0 +1,20 @@ +package com.hzs.third.pay.service.impl; + +import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl; +import com.hzs.common.domain.third.pay.TOnlinePaymentSepAccD; +import com.hzs.third.pay.mapper.TOnlinePaymentSepAccDMapper; +import com.hzs.third.pay.service.ITOnlinePaymentSepAccDService; +import org.springframework.stereotype.Service; + +/** + *

+ * 支付请求子表(分账) 服务实现类 + *

+ * + * @author bd + * @since 2025-07-01 + */ +@Service +public class TOnlinePaymentSepAccDServiceImpl extends ServiceImpl implements ITOnlinePaymentSepAccDService { + +} diff --git a/bd-third/src/main/java/com/hzs/third/pay/service/impl/TOnlinePaymentSepAccServiceImpl.java b/bd-third/src/main/java/com/hzs/third/pay/service/impl/TOnlinePaymentSepAccServiceImpl.java new file mode 100644 index 00000000..aadf5ac3 --- /dev/null +++ b/bd-third/src/main/java/com/hzs/third/pay/service/impl/TOnlinePaymentSepAccServiceImpl.java @@ -0,0 +1,59 @@ +package com.hzs.third.pay.service.impl; + +import cn.hutool.core.collection.CollUtil; +import cn.hutool.core.util.ObjectUtil; +import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper; +import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl; +import com.hzs.common.core.utils.DateUtils; +import com.hzs.common.domain.third.pay.TOnlinePaymentSepAcc; +import com.hzs.common.domain.third.pay.TOnlinePaymentSepAccD; +import com.hzs.common.security.utils.SecurityUtils; +import com.hzs.third.pay.mapper.TOnlinePaymentSepAccMapper; +import com.hzs.third.pay.service.ITOnlinePaymentSepAccDService; +import com.hzs.third.pay.service.ITOnlinePaymentSepAccService; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.stereotype.Service; + +/** + *

+ * 支付请求主表 服务实现类 + *

+ * + * @author bd + * @since 2025-07-01 + */ +@Service +public class TOnlinePaymentSepAccServiceImpl extends ServiceImpl implements ITOnlinePaymentSepAccService { + + @Autowired + private ITOnlinePaymentSepAccDService itOnlinePaymentSepAccDService; + @Override + public void saveOrUpdateReq(TOnlinePaymentSepAcc tOnlinePaymentSepAcc) { + LambdaQueryWrapper wrapper = new LambdaQueryWrapper<>(); + wrapper.eq(TOnlinePaymentSepAcc::getPkPayment, tOnlinePaymentSepAcc.getPkPayment()); + TOnlinePaymentSepAcc source = this.getOne(wrapper, false); + if(ObjectUtil.isNotEmpty(source)){ + tOnlinePaymentSepAcc.setPkId(source.getPkId()); + }else{ + tOnlinePaymentSepAcc.setCreationTime(DateUtils.currentDateTime()); + tOnlinePaymentSepAcc.setPkCreator(SecurityUtils.getUserId()); + } + tOnlinePaymentSepAcc.setModifiedTime(DateUtils.currentDateTime()); + tOnlinePaymentSepAcc.setPkModified(SecurityUtils.getUserId()); + this.save(tOnlinePaymentSepAcc); + LambdaQueryWrapper wrapperD = new LambdaQueryWrapper<>(); + wrapperD.eq(TOnlinePaymentSepAccD::getPkSepAcc, tOnlinePaymentSepAcc.getPkId()); + itOnlinePaymentSepAccDService.remove(wrapperD); + if(CollUtil.isNotEmpty(tOnlinePaymentSepAcc.getSepAccDList())){ + for (TOnlinePaymentSepAccD tOnlinePaymentSepAccD : tOnlinePaymentSepAcc.getSepAccDList()) { + tOnlinePaymentSepAccD.setPkSepAcc(tOnlinePaymentSepAcc.getPkId()); + tOnlinePaymentSepAccD.setCreationTime(DateUtils.currentDateTime()); + tOnlinePaymentSepAccD.setPkCreator(SecurityUtils.getUserId()); + tOnlinePaymentSepAccD.setModifiedTime(DateUtils.currentDateTime()); + tOnlinePaymentSepAccD.setPkModified(SecurityUtils.getUserId()); + } + itOnlinePaymentSepAccDService.saveBatch(tOnlinePaymentSepAcc.getSepAccDList()); + } + + } +} diff --git a/bd-third/src/main/resources/bootstrap.yml b/bd-third/src/main/resources/bootstrap.yml index cb1ee881..ad31f194 100644 --- a/bd-third/src/main/resources/bootstrap.yml +++ b/bd-third/src/main/resources/bootstrap.yml @@ -101,12 +101,19 @@ jd: ## 生产环境api接口域名 apiDomain: http://wapi.jd.com ## 页面回调地址 - pageBackUrl: https://t-app.beida666.com/prod-api/pay/jd/sync-notify +# pageBackUrl: https://t-app.beida666.com/prod-api/pay/jd/sync-notify + pageBackUrl: https://t-app.beida666.com/#/pages/pay/index ## 支付回调地址 - notifyUrl: https://t-app.beida666.com/prod-api/pay/jd/trade-notify +# notifyUrl: https://t-app.beida666.com/prod-api/pay/jd/trade-notify + notifyUrl: https://b747-218-57-66-5.ngrok-free.app/pay/jd/trade-notify ## 退款回调地下 - refundNotifyUrl: https://t-app.beida666.com/prod-api/pay/jd-refund/trade-notify - +# refundNotifyUrl: https://t-app.beida666.com/prod-api/pay/jd-refund/trade-notify + refundNotifyUrl: https://b747-218-57-66-5.ngrok-free.app/pay/jd-refund/trade-notify + separateAccounts: + - account: 153428607007 + proportion: 0.5 + - account: 153428607005 + proportion: 0.5 ## 通联支付配置 allinpay: # #################### 基础支付相关(正式) #################### diff --git a/bd-third/src/main/resources/mapper/third/pay/TOnlinePaymentSepAccDMapper.xml b/bd-third/src/main/resources/mapper/third/pay/TOnlinePaymentSepAccDMapper.xml new file mode 100644 index 00000000..0eaa9269 --- /dev/null +++ b/bd-third/src/main/resources/mapper/third/pay/TOnlinePaymentSepAccDMapper.xml @@ -0,0 +1,29 @@ + + + + + + + + + + + + + + + + + + + + + DEL_FLAG, + CREATION_TIME, + MODIFIED_TIME, + PK_CREATOR, + PK_MODIFIED, + PK_ID, PK_SEP_ACC, ACCOUNT, PROPORTION + + + diff --git a/bd-third/src/main/resources/mapper/third/pay/TOnlinePaymentSepAccMapper.xml b/bd-third/src/main/resources/mapper/third/pay/TOnlinePaymentSepAccMapper.xml new file mode 100644 index 00000000..a7a28bfe --- /dev/null +++ b/bd-third/src/main/resources/mapper/third/pay/TOnlinePaymentSepAccMapper.xml @@ -0,0 +1,31 @@ + + + + + + + + + + + + + + + + + + + + + + + DEL_FLAG, + CREATION_TIME, + MODIFIED_TIME, + PK_CREATOR, + PK_MODIFIED, + PK_ID, PK_PAYMENT, VERSION, REQ_CONTENT, REQ_CONTENT_SEP_ACC, RESP_CONTENT + + + diff --git a/sql/2025年7月1日_京东支付_分账.sql b/sql/2025年7月1日_京东支付_分账.sql new file mode 100644 index 00000000..9e5e94d5 --- /dev/null +++ b/sql/2025年7月1日_京东支付_分账.sql @@ -0,0 +1,89 @@ +CREATE TABLE "CLOUD_2"."T_ONLINE_PAYMENT_SEP_ACC" ( + "PK_ID" NUMBER(20,0), + "PK_PAYMENT" NUMBER(20,0), + "VERSION" VARCHAR2(255), + "REQ_CONTENT" VARCHAR2(1024), + "REQ_CONTENT_SEP_ACC" VARCHAR2(1024), + "RESP_CONTENT" VARCHAR2(2048), + "DEL_FLAG" NUMBER(1), + "PK_COUNTRY" NUMBER(4,0) DEFAULT 1 NOT NULL ENABLE, + "CREATION_TIME" DATE, + "MODIFIED_TIME" DATE, + "PK_CREATOR" NUMBER(20,0), + "PK_MODIFIED" NUMBER(20,0), + PRIMARY KEY ("PK_ID") +) +; + +COMMENT ON COLUMN "CLOUD_2"."T_ONLINE_PAYMENT_SEP_ACC"."PK_PAYMENT" IS '在线支付信息ID'; + +COMMENT ON COLUMN "CLOUD_2"."T_ONLINE_PAYMENT_SEP_ACC"."VERSION" IS '版本号'; + +COMMENT ON COLUMN "CLOUD_2"."T_ONLINE_PAYMENT_SEP_ACC"."REQ_CONTENT" IS '支付请求信息'; + +COMMENT ON COLUMN "CLOUD_2"."T_ONLINE_PAYMENT_SEP_ACC"."REQ_CONTENT_SEP_ACC" IS '分账请求信息'; + +COMMENT ON COLUMN "CLOUD_2"."T_ONLINE_PAYMENT_SEP_ACC"."RESP_CONTENT" IS '支付响应信息'; + +COMMENT ON COLUMN "CLOUD_2"."T_ONLINE_PAYMENT_SEP_ACC"."DEL_FLAG" IS '逻辑删除 (0=未删除,1已删除)'; + +COMMENT ON COLUMN "CLOUD_2"."T_ONLINE_PAYMENT_SEP_ACC"."CREATION_TIME" IS '创建时间'; + +COMMENT ON COLUMN "CLOUD_2"."T_ONLINE_PAYMENT_SEP_ACC"."MODIFIED_TIME" IS '修改时间'; + +COMMENT ON COLUMN "CLOUD_2"."T_ONLINE_PAYMENT_SEP_ACC"."PK_CREATOR" IS '创建者'; + +COMMENT ON COLUMN "CLOUD_2"."T_ONLINE_PAYMENT_SEP_ACC"."PK_MODIFIED" IS '更新者'; + +COMMENT ON TABLE "CLOUD_2"."T_ONLINE_PAYMENT_SEP_ACC" IS '支付请求主表'; + +CREATE SEQUENCE T_ONLINE_PAYMENT_SEP_ACC_SEQ + START WITH 1 + INCREMENT BY 1; + +CREATE TABLE "CLOUD_2"."T_ONLINE_PAYMENT_SEP_ACC_D" ( + "PK_ID" NUMBER(20,0), + "PK_SEP_ACC" NUMBER(20,0), + "ACCOUNT" VARCHAR2(255), + "PROPORTION" NUMBER(10, 2), + "DEL_FLAG" NUMBER(1), + "PK_COUNTRY" NUMBER(4,0) DEFAULT 1 NOT NULL ENABLE, + "CREATION_TIME" DATE, + "MODIFIED_TIME" DATE, + "PK_CREATOR" NUMBER(20,0), + "PK_MODIFIED" NUMBER(20,0), + PRIMARY KEY ("PK_ID") +) +; + +COMMENT ON COLUMN "CLOUD_2"."T_ONLINE_PAYMENT_SEP_ACC_D"."PK_SEP_ACC" IS '支付请求主表ID'; + +COMMENT ON COLUMN "CLOUD_2"."T_ONLINE_PAYMENT_SEP_ACC_D"."ACCOUNT" IS '分账账号'; + +COMMENT ON COLUMN "CLOUD_2"."T_ONLINE_PAYMENT_SEP_ACC_D"."PROPORTION" IS '分账比例'; + +COMMENT ON COLUMN "CLOUD_2"."T_ONLINE_PAYMENT_SEP_ACC_D"."DEL_FLAG" IS '逻辑删除 (0=未删除,1已删除)'; + +COMMENT ON COLUMN "CLOUD_2"."T_ONLINE_PAYMENT_SEP_ACC_D"."CREATION_TIME" IS '创建时间'; + +COMMENT ON COLUMN "CLOUD_2"."T_ONLINE_PAYMENT_SEP_ACC_D"."MODIFIED_TIME" IS '修改时间'; + +COMMENT ON COLUMN "CLOUD_2"."T_ONLINE_PAYMENT_SEP_ACC_D"."PK_CREATOR" IS '创建者'; + +COMMENT ON COLUMN "CLOUD_2"."T_ONLINE_PAYMENT_SEP_ACC_D"."PK_MODIFIED" IS '更新者'; + +COMMENT ON TABLE "CLOUD_2"."T_ONLINE_PAYMENT_SEP_ACC_D" IS '支付请求子表(分账)'; + +CREATE SEQUENCE T_ONLINE_PAYMENT_SEP_ACC_D_SEQ + START WITH 1 + INCREMENT BY 1; + + +ALTER TABLE "CLOUD_2"."T_ONLINE_PAYMENT_SEP_ACC" + ADD ("TRADE_AMOUNT" NUMBER(16,2)); +COMMENT ON COLUMN "CLOUD_2"."T_ONLINE_PAYMENT_SEP_ACC"."TRADE_AMOUNT" IS '总金额'; + + +ALTER TABLE "CLOUD_2"."T_ONLINE_PAYMENT_SEP_ACC_D" + ADD ("TRADE_AMOUNT" NUMBER(16,2)); +COMMENT ON COLUMN "CLOUD_2"."T_ONLINE_PAYMENT_SEP_ACC_D"."TRADE_AMOUNT" IS '分账金额'; diff --git a/文档/支付/支付回调/京东 b/文档/支付/支付回调/京东 new file mode 100644 index 00000000..8598f156 --- /dev/null +++ b/文档/支付/支付回调/京东 @@ -0,0 +1,5 @@ +正常支付回调: + {"signData":"CFC402DAEBC319048859760C3C1076E252A0AA8E06480D33ABE8E9E4F6F64942","charset":"UTF-8","encType":"AP7","code":"00000","signType":"SHA-256","respData":"eyJiYW5rQ29kZSI6IkNDQiIsInRyYWRlTm8iOiIyMDI1MDcwMTE0MDI0MzIwMTE4MzAyNzYyOTk0MTkiLCJyZXN1bHRDb2RlIjoiMDAwMCIsImNhcmRUeXBlIjoiREUiLCJtYXNrQ2FyZE5vIjoiMDMwNSIsInJlc3VsdERlc2MiOiLmiJDlip8iLCJiYW5rU3VibWl0Tm8iOiIwNzAxNjU5MDI3NDk2MTUzIiwidXNlcklkIjoiVF8xMDkiLCJleHRJbmZvIjoie30iLCJwYXlUb29sIjoiRVhQUiIsInRyYWRlQW1vdW50IjoiMiIsInJldHVyblBhcmFtcyI6IjEiLCJvdXRUcmFkZU5vIjoiQkRTTzE3NTEzNDk3NTE0MDk2MDgiLCJ0cmFkZVN0YXR1cyI6IkZJTkkiLCJmaW5pc2hEYXRlIjoiMjAyNTA3MDExNDAzMTciLCJjdXJyZW5jeSI6IkNOWSIsInRyYWRlVHlwZSI6IkFHR1JFIn0=","formatType":"JSON","desc":"成功","merchantNo":"153428607005"} +退款回调: 入口(my-order/self-revoke-order) + +