## Feat - 京东支付
This commit is contained in:
parent
a781afc437
commit
c037c4b535
|
@ -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;
|
||||
|
||||
/**
|
||||
* <p>
|
||||
* 支付请求主表
|
||||
* </p>
|
||||
*
|
||||
* @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<TOnlinePaymentSepAccD> sepAccDList;
|
||||
}
|
|
@ -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;
|
||||
|
||||
/**
|
||||
* <p>
|
||||
* 支付请求子表(分账)
|
||||
* </p>
|
||||
*
|
||||
* @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;
|
||||
}
|
|
@ -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<JdPaySeparateAccountConfig> separateAccounts;
|
||||
|
||||
}
|
|
@ -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;
|
||||
}
|
|
@ -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("退款异常,请刷新后重试");
|
||||
}
|
||||
}
|
||||
|
||||
}
|
|
@ -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<TOnlinePayment> 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) {
|
||||
|
|
|
@ -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<String, String> 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<String, String> getAllRequestParam(final HttpServletRequest request) {
|
||||
Map<String, String> 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;
|
||||
}
|
||||
|
||||
}
|
|
@ -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<String, String> 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;
|
||||
}
|
||||
|
||||
}
|
|
@ -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;
|
||||
|
||||
}
|
|
@ -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;
|
||||
|
||||
}
|
|
@ -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;
|
||||
|
||||
/**
|
||||
* <p>
|
||||
* 支付请求子表(分账) Mapper 接口
|
||||
* </p>
|
||||
*
|
||||
* @author bd
|
||||
* @since 2025-07-01
|
||||
*/
|
||||
public interface TOnlinePaymentSepAccDMapper extends BaseMapper<TOnlinePaymentSepAccD> {
|
||||
|
||||
}
|
|
@ -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;
|
||||
|
||||
/**
|
||||
* <p>
|
||||
* 支付请求主表 Mapper 接口
|
||||
* </p>
|
||||
*
|
||||
* @author bd
|
||||
* @since 2025-07-01
|
||||
*/
|
||||
public interface TOnlinePaymentSepAccMapper extends BaseMapper<TOnlinePaymentSepAcc> {
|
||||
|
||||
}
|
|
@ -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);
|
||||
|
||||
}
|
||||
|
|
|
@ -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;
|
||||
|
||||
/**
|
||||
* <p>
|
||||
* 支付请求子表(分账) 服务类
|
||||
* </p>
|
||||
*
|
||||
* @author bd
|
||||
* @since 2025-07-01
|
||||
*/
|
||||
public interface ITOnlinePaymentSepAccDService extends IService<TOnlinePaymentSepAccD> {
|
||||
|
||||
}
|
|
@ -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;
|
||||
|
||||
/**
|
||||
* <p>
|
||||
* 支付请求主表 服务类
|
||||
* </p>
|
||||
*
|
||||
* @author bd
|
||||
* @since 2025-07-01
|
||||
*/
|
||||
public interface ITOnlinePaymentSepAccService extends IService<TOnlinePaymentSepAcc> {
|
||||
void saveOrUpdateReq(TOnlinePaymentSepAcc tOnlinePaymentSepAcc);
|
||||
}
|
|
@ -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 {
|
|||
}
|
||||
}
|
||||
|
||||
|
||||
}
|
||||
|
|
|
@ -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<String, String> 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<String, Object> 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 "退款异常,请重试";
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -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;
|
||||
|
||||
/**
|
||||
* <p>
|
||||
* 支付请求子表(分账) 服务实现类
|
||||
* </p>
|
||||
*
|
||||
* @author bd
|
||||
* @since 2025-07-01
|
||||
*/
|
||||
@Service
|
||||
public class TOnlinePaymentSepAccDServiceImpl extends ServiceImpl<TOnlinePaymentSepAccDMapper, TOnlinePaymentSepAccD> implements ITOnlinePaymentSepAccDService {
|
||||
|
||||
}
|
|
@ -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;
|
||||
|
||||
/**
|
||||
* <p>
|
||||
* 支付请求主表 服务实现类
|
||||
* </p>
|
||||
*
|
||||
* @author bd
|
||||
* @since 2025-07-01
|
||||
*/
|
||||
@Service
|
||||
public class TOnlinePaymentSepAccServiceImpl extends ServiceImpl<TOnlinePaymentSepAccMapper, TOnlinePaymentSepAcc> implements ITOnlinePaymentSepAccService {
|
||||
|
||||
@Autowired
|
||||
private ITOnlinePaymentSepAccDService itOnlinePaymentSepAccDService;
|
||||
@Override
|
||||
public void saveOrUpdateReq(TOnlinePaymentSepAcc tOnlinePaymentSepAcc) {
|
||||
LambdaQueryWrapper<TOnlinePaymentSepAcc> 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<TOnlinePaymentSepAccD> 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());
|
||||
}
|
||||
|
||||
}
|
||||
}
|
|
@ -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:
|
||||
# #################### 基础支付相关(正式) ####################
|
||||
|
|
|
@ -0,0 +1,29 @@
|
|||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<!DOCTYPE mapper PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN" "http://mybatis.org/dtd/mybatis-3-mapper.dtd">
|
||||
<mapper namespace="com.hzs.com.hzs.common.domain.mapper.TOnlinePaymentSepAccDMapper">
|
||||
|
||||
<!-- 通用查询映射结果 -->
|
||||
<resultMap id="BaseResultMap" type="com.hzs.common.domain.third.pay.TOnlinePaymentSepAccD">
|
||||
<id column="PK_ID" property="pkId" />
|
||||
<result column="DEL_FLAG" property="delFlag" />
|
||||
<result column="CREATION_TIME" property="creationTime" />
|
||||
<result column="MODIFIED_TIME" property="modifiedTime" />
|
||||
<result column="PK_CREATOR" property="pkCreator" />
|
||||
<result column="PK_MODIFIED" property="pkModified" />
|
||||
<result column="PK_SEP_ACC" property="pkSepAcc" />
|
||||
<result column="ACCOUNT" property="account" />
|
||||
<result column="PROPORTION" property="proportion" />
|
||||
<result column="TRADE_AMOUNT" property="tradeAmount" />
|
||||
</resultMap>
|
||||
|
||||
<!-- 通用查询结果列 -->
|
||||
<sql id="Base_Column_List">
|
||||
DEL_FLAG,
|
||||
CREATION_TIME,
|
||||
MODIFIED_TIME,
|
||||
PK_CREATOR,
|
||||
PK_MODIFIED,
|
||||
PK_ID, PK_SEP_ACC, ACCOUNT, PROPORTION
|
||||
</sql>
|
||||
|
||||
</mapper>
|
|
@ -0,0 +1,31 @@
|
|||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<!DOCTYPE mapper PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN" "http://mybatis.org/dtd/mybatis-3-mapper.dtd">
|
||||
<mapper namespace="com.hzs.com.hzs.common.domain.mapper.TOnlinePaymentSepAccMapper">
|
||||
|
||||
<!-- 通用查询映射结果 -->
|
||||
<resultMap id="BaseResultMap" type="com.hzs.common.domain.third.pay.TOnlinePaymentSepAcc">
|
||||
<id column="PK_ID" property="pkId" />
|
||||
<result column="DEL_FLAG" property="delFlag" />
|
||||
<result column="CREATION_TIME" property="creationTime" />
|
||||
<result column="MODIFIED_TIME" property="modifiedTime" />
|
||||
<result column="PK_CREATOR" property="pkCreator" />
|
||||
<result column="PK_MODIFIED" property="pkModified" />
|
||||
<result column="PK_PAYMENT" property="pkPayment" />
|
||||
<result column="VERSION" property="version" />
|
||||
<result column="REQ_CONTENT" property="reqContent" />
|
||||
<result column="REQ_CONTENT_SEP_ACC" property="reqContentSepAcc" />
|
||||
<result column="RESP_CONTENT" property="respContent" />
|
||||
<result column="TRADE_AMOUNT" property="tradeAmount" />
|
||||
</resultMap>
|
||||
|
||||
<!-- 通用查询结果列 -->
|
||||
<sql id="Base_Column_List">
|
||||
DEL_FLAG,
|
||||
CREATION_TIME,
|
||||
MODIFIED_TIME,
|
||||
PK_CREATOR,
|
||||
PK_MODIFIED,
|
||||
PK_ID, PK_PAYMENT, VERSION, REQ_CONTENT, REQ_CONTENT_SEP_ACC, RESP_CONTENT
|
||||
</sql>
|
||||
|
||||
</mapper>
|
|
@ -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 '分账金额';
|
|
@ -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)
|
||||
|
||||
|
Loading…
Reference in New Issue