退款调试
This commit is contained in:
parent
108ab7443f
commit
c4791fd6e9
@ -10,6 +10,7 @@ package com.suisung.mall.pay.service;
|
||||
|
||||
import cn.hutool.json.JSONObject;
|
||||
import com.suisung.mall.common.api.CommonResult;
|
||||
import org.springframework.data.util.Pair;
|
||||
|
||||
import javax.servlet.http.HttpServletRequest;
|
||||
import javax.servlet.http.HttpServletResponse;
|
||||
@ -62,6 +63,19 @@ public interface LakalaPayService {
|
||||
*/
|
||||
JSONObject refund(Integer storeId, String out_trade_no, String origin_trade_no, String refund_amount, String refund_reason, String requestIP);
|
||||
|
||||
/**
|
||||
* 执行内部拉卡拉交易退款
|
||||
* 参考地址:https://o.lakala.com/#/home/document/detail?id=113
|
||||
*
|
||||
* @param storeId 店铺ID
|
||||
* @param outTradeNo 外部交易订单号
|
||||
* @param originTradeNo 原拉卡拉交易流水号
|
||||
* @param refundAmount 退款金额(单位:分)
|
||||
* @param refundReason 退款原因
|
||||
* @return Pair<Boolean, String>,包含退款是否成功以及消息
|
||||
*/
|
||||
Pair<Boolean, String> innerLklRefund(Integer storeId, String outTradeNo, String originTradeNo, String refundAmount, String refundReason);
|
||||
|
||||
/**
|
||||
* 账户余额查询
|
||||
* 参考:https://o.lakala.com/#/home/document/detail?id=364
|
||||
|
||||
@ -37,7 +37,10 @@ import lombok.extern.slf4j.Slf4j;
|
||||
import org.springframework.beans.factory.annotation.Autowired;
|
||||
import org.springframework.beans.factory.annotation.Value;
|
||||
import org.springframework.context.annotation.Lazy;
|
||||
import org.springframework.data.util.Pair;
|
||||
import org.springframework.stereotype.Service;
|
||||
import org.springframework.web.context.request.RequestContextHolder;
|
||||
import org.springframework.web.context.request.ServletRequestAttributes;
|
||||
|
||||
import javax.servlet.http.HttpServletRequest;
|
||||
import javax.servlet.http.HttpServletResponse;
|
||||
@ -50,6 +53,8 @@ import java.util.List;
|
||||
@Service
|
||||
public class LakalaPayServiceImpl implements LakalaPayService {
|
||||
private static final boolean init = false;
|
||||
|
||||
|
||||
//### 可选的两个参数,不同的店铺商家,可以数据库里配置不同的商户号和终端号
|
||||
@Value("${lakala.merchant_no}")
|
||||
public String merchantNo; // 拉卡拉分配的商户号
|
||||
@ -331,6 +336,91 @@ public class LakalaPayServiceImpl implements LakalaPayService {
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* 执行内部拉卡拉交易退款
|
||||
* 参考地址:https://o.lakala.com/#/home/document/detail?id=113
|
||||
*
|
||||
* @param storeId 店铺ID
|
||||
* @param outTradeNo 退货订单号
|
||||
* @param originTradeNo 原拉卡拉交易流水号
|
||||
* @param refundAmount 退款金额(单位:分)
|
||||
* @param refundReason 退款原因
|
||||
* @return Pair<Boolean, String>,包含退款是否成功以及消息
|
||||
*/
|
||||
@Override
|
||||
public Pair<Boolean, String> innerLklRefund(Integer storeId, String outTradeNo, String originTradeNo, String refundAmount, String refundReason) {
|
||||
try {
|
||||
log.info("开始执行拉卡拉内部退款,参数: storeId={}, outTradeNo={}, originTradeNo={}, refundAmount={}, refundReason={}",
|
||||
storeId, outTradeNo, originTradeNo, refundAmount, refundReason);
|
||||
|
||||
// 1. 获取请求IP
|
||||
ServletRequestAttributes attributes = (ServletRequestAttributes) RequestContextHolder.getRequestAttributes();
|
||||
if (attributes == null) {
|
||||
log.error("无法获取HttpServletRequest,退款失败");
|
||||
return Pair.of(false, I18nUtil._("系统异常,无法获取请求信息!"));
|
||||
}
|
||||
HttpServletRequest request = attributes.getRequest();
|
||||
String requestIp = IpKit.getRealIp(request);
|
||||
// 2. 校验参数
|
||||
if (ObjectUtil.isEmpty(storeId) || org.apache.commons.lang3.StringUtils.isAnyBlank(outTradeNo, refundAmount, originTradeNo)) {
|
||||
log.warn("退款请求参数不完整: storeId={}, outTradeNo={}, originTradeNo={}, refundAmount={}, requestIp={}", storeId, outTradeNo, originTradeNo, refundAmount, requestIp);
|
||||
return Pair.of(false, I18nUtil._("缺少必要参数,退款失败!"));
|
||||
}
|
||||
if (!refundAmount.matches("\\d+") || Integer.parseInt(refundAmount) <= 0) {
|
||||
log.warn("退款金额不合法: refundAmount={}", refundAmount);
|
||||
return Pair.of(false, I18nUtil._("退款金额不合法!"));
|
||||
}
|
||||
// 3. 初始化拉卡拉SDK
|
||||
initLKLSDK();
|
||||
// 4. 获取店铺的拉卡拉商户号和终端号
|
||||
ShopStoreBase shopStoreBase = shopService.getLklMerchantNoAndTermNo(storeId);
|
||||
if (shopStoreBase == null || org.apache.commons.lang3.StringUtils.isAnyBlank(shopStoreBase.getLkl_merchant_no(), shopStoreBase.getLkl_term_no())) {
|
||||
log.error("无法获取店铺的拉卡拉商户号或终端号: storeId={}", storeId);
|
||||
return Pair.of(false, I18nUtil._("缺少商户号参数,退款失败!"));
|
||||
}
|
||||
// 5. 构造退款请求并发送
|
||||
V3LabsRelationRefundRequest refundRequest = new V3LabsRelationRefundRequest();
|
||||
refundRequest.setOutTradeNo(outTradeNo);
|
||||
refundRequest.setMerchantNo(shopStoreBase.getLkl_merchant_no());
|
||||
refundRequest.setTermNo(shopStoreBase.getLkl_term_no());
|
||||
refundRequest.setRefundAmount(refundAmount);
|
||||
refundRequest.setRefundReason(refundReason);
|
||||
refundRequest.setOriginTradeNo(originTradeNo);
|
||||
refundRequest.setLocationInfo(new V3LabsTradeLocationInfo(requestIp, null, ""));
|
||||
|
||||
log.info("拉卡拉退款请求参数: {}", JSONUtil.toJsonStr(refundRequest));
|
||||
|
||||
String responseString = LKLSDK.httpPost(refundRequest);
|
||||
// 6. 处理响应
|
||||
if (StrUtil.isBlank(responseString)) {
|
||||
log.error("拉卡拉退款接口无响应");
|
||||
return Pair.of(false, I18nUtil._("服务端无返回值,退款失败!"));
|
||||
}
|
||||
|
||||
log.info("拉卡拉退款接口响应: {}", responseString);
|
||||
|
||||
JSONObject lakalaResponseJson = JSONUtil.parseObj(responseString);
|
||||
if (lakalaResponseJson == null) {
|
||||
log.error("拉卡拉退款接口返回值解析失败: responseString={}", responseString);
|
||||
return Pair.of(false, I18nUtil._("返回值解析失败,退款失败!"));
|
||||
}
|
||||
if (!"BBS00000".equals(lakalaResponseJson.getStr("code"))) {
|
||||
String errorMessage = lakalaResponseJson.getStr("msg", "未知错误");
|
||||
log.error("拉卡拉退款失败, 错误信息: {}", errorMessage);
|
||||
return Pair.of(false, I18nUtil._(errorMessage));
|
||||
}
|
||||
log.info("拉卡拉退款成功: outTradeNo={}", outTradeNo);
|
||||
return Pair.of(true, I18nUtil._("退款成功!"));
|
||||
} catch (SDKException e) {
|
||||
log.error("拉卡拉退款SDK异常: ", e);
|
||||
return Pair.of(false, I18nUtil._("拉卡拉退款SDK异常,退款失败!") + e.getMessage());
|
||||
} catch (Exception e) {
|
||||
log.error("拉卡拉退款发生未知异常: ", e);
|
||||
return Pair.of(false, I18nUtil._("拉卡拉退款发生未知异常,退款失败!") + e.getMessage());
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* 账户余额查询
|
||||
* 参考:https://o.lakala.com/#/home/document/detail?id=364
|
||||
|
||||
@ -25,6 +25,8 @@ import com.suisung.mall.pay.mapper.PayConsumeTradeMapper;
|
||||
import com.suisung.mall.pay.service.*;
|
||||
import lombok.extern.slf4j.Slf4j;
|
||||
import org.springframework.beans.factory.annotation.Autowired;
|
||||
import org.springframework.context.annotation.Lazy;
|
||||
import org.springframework.data.util.Pair;
|
||||
import org.springframework.stereotype.Service;
|
||||
import org.springframework.transaction.annotation.Transactional;
|
||||
|
||||
@ -71,6 +73,10 @@ public class PayConsumeTradeServiceImpl extends BaseServiceImpl<PayConsumeTradeM
|
||||
@Autowired
|
||||
private PayConsumeTradeMapper payConsumeTradeMapper;
|
||||
|
||||
@Lazy
|
||||
@Autowired
|
||||
private LakalaPayService lakalaPayService;
|
||||
|
||||
@Override
|
||||
public List<Map> fixConsumeTrade(List<Map> rows, String field_key) {
|
||||
if (ObjectUtil.isNull(rows)) return new ArrayList<>();
|
||||
@ -1014,18 +1020,21 @@ public class PayConsumeTradeServiceImpl extends BaseServiceImpl<PayConsumeTradeM
|
||||
@Transactional
|
||||
@Override
|
||||
public boolean doRefund(List<ShopOrderReturn> returnRows) {
|
||||
log.info("执行退款操作开始");
|
||||
log.info("执行退款操作开始...");
|
||||
|
||||
if (CollUtil.isEmpty(returnRows)) {
|
||||
log.warn("退款订单列表为空,停止退款操作");
|
||||
return false;
|
||||
}
|
||||
|
||||
// log.info("退款订单列表大小: {}", returnRows.size());
|
||||
|
||||
// 存储已支付的退货单ID列表
|
||||
List<String> paidReturnIdList = new ArrayList<>();
|
||||
|
||||
// 获取是否原路退回配置,默认为 false
|
||||
boolean refundToOriginal = accountBaseConfigService.getConfig("order_refund_flag", false);
|
||||
log.info("是否原路退回:{}", refundToOriginal);
|
||||
|
||||
// 提取所有订单ID,并去重
|
||||
List<String> orderIdList = returnRows.stream().map(ShopOrderReturn::getOrder_id).distinct().collect(Collectors.toList());
|
||||
@ -1079,6 +1088,8 @@ public class PayConsumeTradeServiceImpl extends BaseServiceImpl<PayConsumeTradeM
|
||||
|
||||
// 循环处理每个退货单
|
||||
for (ShopOrderReturn returnRow : returnRows) {
|
||||
// log.info("处理退货单: {}", returnRow.getReturn_id());
|
||||
|
||||
try {
|
||||
// 获取买家用户ID
|
||||
Integer buyerUserId = returnRow.getBuyer_user_id();
|
||||
@ -1203,7 +1214,6 @@ public class PayConsumeTradeServiceImpl extends BaseServiceImpl<PayConsumeTradeM
|
||||
buyerConsumeRecordRow.setRecord_time(currentTime);
|
||||
// 设置买家消费记录的支付方式ID
|
||||
buyerConsumeRecordRow.setPayment_met_id(PaymentType.PAYMENT_MET_MONEY);
|
||||
|
||||
// 增加买家流水
|
||||
buyerConsumeRecordRow.setRecord_money(waitingRefundAmount); // 佣金问题?
|
||||
// 设置买家消费记录的交易类型ID
|
||||
@ -1322,7 +1332,6 @@ public class PayConsumeTradeServiceImpl extends BaseServiceImpl<PayConsumeTradeM
|
||||
orderDataRow.setOrder_refund_agree_points(NumberUtil.add(orderRefundAgreePoints, refundPoints));
|
||||
}
|
||||
|
||||
// TODO: 优化代码
|
||||
// 如果需要原路退回
|
||||
if (refundToOriginal) {
|
||||
// 读取在线支付信息,如果无在线支付信息,则余额支付 否则在线支付【联合支付】判断
|
||||
@ -1330,6 +1339,8 @@ public class PayConsumeTradeServiceImpl extends BaseServiceImpl<PayConsumeTradeM
|
||||
depositQueryWrapper.apply(orderId != null, "FIND_IN_SET ('" + orderId + "', order_id )");
|
||||
PayConsumeDeposit consumeRow = payConsumeDepositService.findOne(depositQueryWrapper);
|
||||
|
||||
// log.info("查询到的在线支付信息: {}", consumeRow);
|
||||
|
||||
// 如果存在在线支付信息
|
||||
if (consumeRow != null) {
|
||||
// 获取支付渠道ID
|
||||
@ -1338,17 +1349,33 @@ public class PayConsumeTradeServiceImpl extends BaseServiceImpl<PayConsumeTradeM
|
||||
PayPaymentChannel paymentChannelRow = payPaymentChannelService.get(paymentChannelId);
|
||||
// 获取支付渠道代码
|
||||
String paymentChannelCode = paymentChannelRow.getPayment_channel_code();
|
||||
// 获取支付总金额
|
||||
// 获取支付总金额(交易金额)
|
||||
BigDecimal depositTotalFee = consumeRow.getDeposit_total_fee();
|
||||
|
||||
log.debug("支付渠道代码: {}, 支付总金额: {}", paymentChannelCode, depositTotalFee);
|
||||
log.info("支付渠道代码: {}, 支付总金额: {}", paymentChannelCode, depositTotalFee);
|
||||
|
||||
// 如果支付渠道编号为支付宝或微信原生支付
|
||||
if (Arrays.asList("alipay", "wx_native").contains(paymentChannelCode)) {
|
||||
// 计算买家余额差额(退款的金额)
|
||||
BigDecimal moneyDifference = NumberUtil.round(NumberUtil.sub(buyerUserMoney, depositTotalFee), 2);
|
||||
if (Arrays.asList("alipay", "wx_native", "lakala").contains(paymentChannelCode)) {
|
||||
// 获取在线支付交易号
|
||||
String depositTradeNo = consumeRow.getDeposit_trade_no();
|
||||
// 计算买家余额差额
|
||||
// BigDecimal moneyDifference = NumberUtil.round(NumberUtil.sub(buyerUserMoney, depositTotalFee), 2);
|
||||
BigDecimal moneyDifference = buyerUserMoney;
|
||||
// log.info("买家余额差额: {}", moneyDifference);
|
||||
// 如果余额差额(退款的金额)大于 0
|
||||
if (moneyDifference.compareTo(BigDecimal.ZERO) > 0) {
|
||||
// log.info("买家余额差额大于 0,调用退款接口");
|
||||
// TODO 支付宝微信金额原路返回(调用 拉卡拉的退款接口)
|
||||
Pair<Boolean, String> refundResult = lakalaPayService.innerLklRefund(
|
||||
storeId,
|
||||
returnRow.getReturn_id(), // 退货单ID
|
||||
depositTradeNo,
|
||||
String.valueOf(moneyDifference.multiply(BigDecimal.valueOf(100)).intValue()), // 单位:分
|
||||
returnRow.getReturn_buyer_message()
|
||||
);
|
||||
if (!refundResult.getFirst()) {
|
||||
// 如果原路退款失败,直接退回余额
|
||||
|
||||
// 获取买家用户资源
|
||||
PayUserResource payUserResource = payUserResourceService.getById(buyerUserId);
|
||||
// 设置买家用户余额(原余额 + 余额差额)
|
||||
@ -1357,6 +1384,8 @@ public class PayConsumeTradeServiceImpl extends BaseServiceImpl<PayConsumeTradeM
|
||||
if (!payUserResourceService.edit(payUserResource)) {
|
||||
throw new ApiException(I18nUtil._("用户退款失败!"));
|
||||
}
|
||||
//throw new ApiException(I18nUtil._("退款原路返回失败!"));
|
||||
}
|
||||
}
|
||||
|
||||
// 如果买家用户积分大于 0
|
||||
@ -1367,9 +1396,6 @@ public class PayConsumeTradeServiceImpl extends BaseServiceImpl<PayConsumeTradeM
|
||||
}
|
||||
}
|
||||
|
||||
// 获取在线支付交易号
|
||||
String depositTradeNo = consumeRow.getDeposit_trade_no();
|
||||
|
||||
// 创建订单退货单对象
|
||||
ShopOrderReturn orderReturn = new ShopOrderReturn();
|
||||
// 设置退货单ID
|
||||
@ -1389,6 +1415,7 @@ public class PayConsumeTradeServiceImpl extends BaseServiceImpl<PayConsumeTradeM
|
||||
} else {
|
||||
// 非微信、支付宝支付的情况:
|
||||
// 如果买家用户余额大于 0
|
||||
log.info("买家用户余额: {}", buyerUserMoney);
|
||||
if (buyerUserMoney.compareTo(BigDecimal.ZERO) > 0) {
|
||||
// 获取买家用户资源
|
||||
PayUserResource payUserResource = payUserResourceService.getById(buyerUserId);
|
||||
|
||||
@ -105,6 +105,7 @@ logging:
|
||||
naming: error
|
||||
config: error
|
||||
netflix: error
|
||||
lkl: error
|
||||
org: error
|
||||
io: error
|
||||
reactor: error
|
||||
|
||||
@ -473,7 +473,7 @@ public class ShopMchEntryServiceImpl extends BaseServiceImpl<ShopMchEntryMapper,
|
||||
queryWrapper.orderByDesc("id");
|
||||
List<ShopMchEntry> recordList = list(queryWrapper);
|
||||
if (CollectionUtil.isEmpty(recordList)) {
|
||||
return CommonResult.success(null, "暂无申请记录!");
|
||||
return CommonResult.success(new JSONObject().set("approval_status", CommonConstant.MCH_APPR_STA_NONE), "请求成功!");
|
||||
}
|
||||
|
||||
ShopMchEntry record = recordList.get(0);
|
||||
|
||||
Loading…
Reference in New Issue
Block a user