退款调试

This commit is contained in:
Jack 2025-06-17 11:38:00 +08:00
parent 108ab7443f
commit c4791fd6e9
5 changed files with 153 additions and 21 deletions

View File

@ -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

View File

@ -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

File diff suppressed because one or more lines are too long

View File

@ -105,6 +105,7 @@ logging:
naming: error
config: error
netflix: error
lkl: error
org: error
io: error
reactor: error

View File

@ -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);
@ -1041,7 +1041,7 @@ public class ShopMchEntryServiceImpl extends BaseServiceImpl<ShopMchEntryMapper,
return false;
}
}
/**
* 根据商户号或商家手机号修改商户分账多个状态