分账前期的工作

This commit is contained in:
Jack 2025-05-30 01:35:23 +08:00
parent 03b34a858f
commit 4c5408d57d
21 changed files with 527 additions and 115 deletions

View File

@ -1,5 +1,6 @@
package com.suisung.mall.common.feignService; package com.suisung.mall.common.feignService;
import cn.hutool.json.JSONObject;
import com.suisung.mall.common.api.CommonResult; import com.suisung.mall.common.api.CommonResult;
import com.suisung.mall.common.domain.OssDto; import com.suisung.mall.common.domain.OssDto;
import com.suisung.mall.common.modules.base.ShopBaseDistrict; import com.suisung.mall.common.modules.base.ShopBaseDistrict;
@ -280,5 +281,24 @@ public interface ShopService {
@PostMapping(value = "/mobile/shop/merch/approval/status") @PostMapping(value = "/mobile/shop/merch/approval/status")
Long shopMerchEntryApprovalStatus(@RequestBody Map<String, Object> params); Long shopMerchEntryApprovalStatus(@RequestBody Map<String, Object> params);
/**
* 当拉卡拉支付时新增一个拉卡拉订单信息
*
* @param lklPayReqAndRespJson 参数参考实现方法
* @return
*/
@PostMapping(value = "/mobile/shop/orderlkl/pay/add/order")
Boolean lklPayAddShopOrderLkl(@RequestBody JSONObject lklPayReqAndRespJson);
/**
* 当拉卡拉支付成功后更改一个拉卡拉订单信息
*
* @param lklPayNotifyDataJson 参数参考实现方法
* @return
*/
@PostMapping(value = "/mobile/shop/orderlkl/pay/notify/update/order")
Boolean lklPayNotifyUpdateShopOrderLkl(@RequestBody JSONObject lklPayNotifyDataJson);
} }

View File

@ -76,6 +76,9 @@ public class LklOrderSeparate {
@ApiModelProperty(value = "最终分账明细JSON 格式") @ApiModelProperty(value = "最终分账明细JSON 格式")
private String detail_datas; private String detail_datas;
@ApiModelProperty(value = "总计分账金额")
private Integer total_separate_value;
@ApiModelProperty(value = "拉卡拉机构编号") @ApiModelProperty(value = "拉卡拉机构编号")
private String lkl_org_no; private String lkl_org_no;

View File

@ -92,6 +92,9 @@ public class ShopOrderData implements Serializable {
@ApiModelProperty(value = "实际运费金额-卖家可修改") @ApiModelProperty(value = "实际运费金额-卖家可修改")
private BigDecimal order_shipping_fee; private BigDecimal order_shipping_fee;
@ApiModelProperty(value = "总计分账金额(从拉卡拉上分账,分给平台和代理商费用),单位:元")
private BigDecimal total_separate_value;
@ApiModelProperty(value = "平台费(分给平台或代理商的费用),根据不同的店铺分类,从商品原价中扣除相应的费用。") @ApiModelProperty(value = "平台费(分给平台或代理商的费用),根据不同的店铺分类,从商品原价中扣除相应的费用。")
private BigDecimal platform_fee; private BigDecimal platform_fee;

View File

@ -38,12 +38,6 @@ public class ShopOrderLkl implements Serializable {
private String order_id; private String order_id;
private String log_no;
private String log_date;
private String merchant_no;
private Integer total_amt; private Integer total_amt;
private Integer shopping_fee; private Integer shopping_fee;
@ -56,12 +50,26 @@ public class ShopOrderLkl implements Serializable {
private String trans_type; private String trans_type;
private String trade_status;
private String lkl_log_no;
private String lkl_log_date;
private String lkl_trade_no; private String lkl_trade_no;
private String lkl_merchant_no;
private String lkl_term_no; private String lkl_term_no;
private String notify_url;
private String lkl_req;
private String lkl_resp; private String lkl_resp;
private String lkl_notify_resp;
private Integer status; private Integer status;
private Date created_at; private Date created_at;

View File

@ -63,8 +63,8 @@ public class IndexController extends BaseControllerImpl {
@ApiOperation(value = "测试接口", notes = "测试接口") @ApiOperation(value = "测试接口", notes = "测试接口")
@RequestMapping(value = "/test/case", method = RequestMethod.POST) @RequestMapping(value = "/test/case", method = RequestMethod.POST)
public JSONObject testCase(HttpServletRequest request, HttpServletResponse response, public JSONObject testCase(HttpServletRequest request, HttpServletResponse response,
@RequestBody JSONObject objectJSON){ @RequestBody JSONObject objectJSON) {
return lakalaPayService.transPreOrder(request,response, (String) objectJSON.get("orderId")); return lakalaPayService.transPreOrder(request, response, (String) objectJSON.get("orderId"));
} }
@ApiOperation(value = "获取支付密码", notes = "获取支付密码") @ApiOperation(value = "获取支付密码", notes = "获取支付密码")
@ -243,7 +243,7 @@ public class IndexController extends BaseControllerImpl {
return payUserPayService.notifyUrl(request, response, "wx_native"); return payUserPayService.notifyUrl(request, response, "wx_native");
} }
@ApiOperation(value = "拉卡拉在微信回调通知", notes = "拉卡拉在微信回调通知") @ApiOperation(value = "第三方拉卡拉在微信回调通知", notes = "第三方拉卡拉在微信回调通知")
@RequestMapping(value = "/lkl_wxPay_notify_url", method = RequestMethod.POST) @RequestMapping(value = "/lkl_wxPay_notify_url", method = RequestMethod.POST)
public String lklWxNotifyUrl(HttpServletRequest request) { public String lklWxNotifyUrl(HttpServletRequest request) {
return payUserPayService.lklNotifyUrl(request); return payUserPayService.lklNotifyUrl(request);

View File

@ -28,6 +28,7 @@ public interface LakalaPayService {
* @param termNo 终端号 * @param termNo 终端号
* @param xcxAppId 小程序appid * @param xcxAppId 小程序appid
* @param openId openid * @param openId openid
* @param storeId 店铺号
* @param orderId 订单号 * @param orderId 订单号
* @param subject 订单标题 * @param subject 订单标题
* @param totalAmount 订单金额 * @param totalAmount 订单金额
@ -36,7 +37,7 @@ public interface LakalaPayService {
* @param remark 备注 * @param remark 备注
* @return * @return
*/ */
JSONObject transPreOrder(String merchantNo, String termNo, String xcxAppId, String openId, String orderId, String subject, String totalAmount, String notifyURL, String requestIP, String remark); JSONObject transPreOrder(String merchantNo, String termNo, String xcxAppId, String openId, String storeId, String orderId, String subject, String totalAmount, String notifyURL, String requestIP, String remark);
/** /**
* 聚合扫码-交易查询 * 聚合扫码-交易查询

View File

@ -157,6 +157,7 @@ public class LakalaPayServiceImpl implements LakalaPayService {
* @param termNo 终端号 * @param termNo 终端号
* @param xcxAppId 小程序appid * @param xcxAppId 小程序appid
* @param openId openid * @param openId openid
* @param storeId 订单号
* @param orderId 订单号 * @param orderId 订单号
* @param subject 订单标题 * @param subject 订单标题
* @param totalAmount 订单金额 * @param totalAmount 订单金额
@ -166,7 +167,7 @@ public class LakalaPayServiceImpl implements LakalaPayService {
* @return * @return
*/ */
@Override @Override
public JSONObject transPreOrder(String merchantNo, String termNo, String xcxAppId, String openId, String orderId, String subject, String totalAmount, String notifyURL, String requestIP, String remark) { public JSONObject transPreOrder(String merchantNo, String termNo, String xcxAppId, String openId, String storeId, String orderId, String subject, String totalAmount, String notifyURL, String requestIP, String remark) {
// 1. 配置初始化 // 1. 配置初始化
initLKLSDK(); initLKLSDK();
@ -188,7 +189,7 @@ public class LakalaPayServiceImpl implements LakalaPayService {
v3LabsTransPreorderWechatReq.setAccountType("WECHAT"); v3LabsTransPreorderWechatReq.setAccountType("WECHAT");
// 41:NATIVEALIPAY云闪付支持京东白条分期51:JSAPI微信公众号支付支付宝服务窗支付银联JS支付翼支付JS支付拉卡拉钱包支付71:微信小程序支付 61:APP支付微信APP支付 // 41:NATIVEALIPAY云闪付支持京东白条分期51:JSAPI微信公众号支付支付宝服务窗支付银联JS支付翼支付JS支付拉卡拉钱包支付71:微信小程序支付 61:APP支付微信APP支付
v3LabsTransPreorderWechatReq.setTransType("51"); v3LabsTransPreorderWechatReq.setTransType("51");
v3LabsTransPreorderWechatReq.setTotalAmount(totalAmount); v3LabsTransPreorderWechatReq.setTotalAmount(totalAmount); // 应支付金额单位
v3LabsTransPreorderWechatReq.setSettleType("1"); //0或者空常规结算方式如需接拉卡拉分账通需传1商户未开通分账之前切记不用上送此参数 v3LabsTransPreorderWechatReq.setSettleType("1"); //0或者空常规结算方式如需接拉卡拉分账通需传1商户未开通分账之前切记不用上送此参数
v3LabsTransPreorderWechatReq.setNotifyUrl(notifyURL); v3LabsTransPreorderWechatReq.setNotifyUrl(notifyURL);
v3LabsTransPreorderWechatReq.setRemark(remark); v3LabsTransPreorderWechatReq.setRemark(remark);
@ -202,6 +203,7 @@ public class LakalaPayServiceImpl implements LakalaPayService {
wechatBus.setSubAppid(xcxAppId); // 小程序appId wechatBus.setSubAppid(xcxAppId); // 小程序appId
wechatBus.setUserId(openId); // 微信 openId wechatBus.setUserId(openId); // 微信 openId
wechatBus.setDeviceInfo("WEB"); // 终端设备号(门店号或收银设备ID)注意PC网页或JSAPI支付请传WEB wechatBus.setDeviceInfo("WEB"); // 终端设备号(门店号或收银设备ID)注意PC网页或JSAPI支付请传WEB
wechatBus.setAttach(storeId); // 附加数据商户自定义数据在查询交易结果时原样返回
v3LabsTransPreorderWechatReq.setAccBusiFields(wechatBus); v3LabsTransPreorderWechatReq.setAccBusiFields(wechatBus);
try { try {
@ -216,8 +218,13 @@ public class LakalaPayServiceImpl implements LakalaPayService {
JSONObject lakalaRespJSON = JSONUtil.parseObj(responseStr); JSONObject lakalaRespJSON = JSONUtil.parseObj(responseStr);
// || !lakalaRespJSON.getStr("code").equals("BBS00000") if (lakalaRespJSON != null && lakalaRespJSON.getStr("code").equals("BBS00000")) {
// 新增一个拉卡拉订单记录 shop_order_lkl
JSONObject lklPayReqAndRespJson = new JSONObject();
lklPayReqAndRespJson.put("req", JSONUtil.parseObj(v3LabsTransPreorderWechatReq));
lklPayReqAndRespJson.put("resp", lakalaRespJSON);
shopService.lklPayAddShopOrderLkl(lklPayReqAndRespJson);
}
//4. 响应 //4. 响应
return lakalaRespJSON; return lakalaRespJSON;
} catch (SDKException e) { } catch (SDKException e) {

View File

@ -573,7 +573,7 @@ public class PayConsumeDepositServiceImpl extends BaseServiceImpl<PayConsumeDepo
throw new ApiException(ResultCode.FAILED); throw new ApiException(ResultCode.FAILED);
}*/ }*/
if (CollUtil.isNotEmpty(paid_order_id_row)) { if (CollUtil.isNotEmpty(paid_order_id_row)) {
// 发送消息给Mq // 发送消息给 RabbitMQ
CommonResult res = shopService.sendMqMsg(MqConstant.SHOP_EXCHANGE, MqConstant.SHOP_PAIDYES_ROUTING_KEY, paid_order_id_row.toString()); CommonResult res = shopService.sendMqMsg(MqConstant.SHOP_EXCHANGE, MqConstant.SHOP_PAIDYES_ROUTING_KEY, paid_order_id_row.toString());
res.checkFenResult(); res.checkFenResult();
} }

View File

@ -572,7 +572,7 @@ public class PayUserPayServiceImpl extends BaseServiceImpl<PayUserPayMapper, Pay
} }
/** /**
* 拉卡拉第三方 JSAPI 下单返回调起微信支付的收银台参数 * 第三方拉卡拉 JSAPI 下单返回调起微信支付的收银台参数
* *
* @param request * @param request
* @param response * @param response
@ -586,7 +586,7 @@ public class PayUserPayServiceImpl extends BaseServiceImpl<PayUserPayMapper, Pay
String subject = payConsumeTrade.getTrade_title(); String subject = payConsumeTrade.getTrade_title();
String trade_remark = ObjectUtil.defaultIfNull(payConsumeTrade.getTrade_remark(), ""); String trade_remark = ObjectUtil.defaultIfNull(payConsumeTrade.getTrade_remark(), "");
// 实际付款金额 // 实际付款金额
String total_fee = StrUtil.toString(NumberUtil.mul(NumberUtil.round(payConsumeTrade.getTrade_payment_amount(), 2), 100).intValue()); String total_amt = StrUtil.toString(NumberUtil.mul(NumberUtil.round(payConsumeTrade.getTrade_payment_amount(), 2), 100).intValue());
// 微信支付配置值 // 微信支付配置值
WxPayApiConfig wxPayApiConfig = WxPayApiConfigKit.getWxPayApiConfig(); WxPayApiConfig wxPayApiConfig = WxPayApiConfigKit.getWxPayApiConfig();
logger.debug("微信支付配置值:{}", JSONUtil.toJsonStr(wxPayApiConfig)); logger.debug("微信支付配置值:{}", JSONUtil.toJsonStr(wxPayApiConfig));
@ -598,7 +598,7 @@ public class PayUserPayServiceImpl extends BaseServiceImpl<PayUserPayMapper, Pay
// 这里获取店铺的拉卡拉的商户号和终端号码 // 这里获取店铺的拉卡拉的商户号和终端号码
ShopStoreBase shopStoreBase = shopService.getLklMerchantNoAndTermNo(payConsumeTrade.getStore_id()); ShopStoreBase shopStoreBase = shopService.getLklMerchantNoAndTermNo(payConsumeTrade.getStore_id());
if (shopStoreBase == null) { if (shopStoreBase == null) {
data.put("message", "获取店铺信息失败!"); data.put("message", "获取店铺商户号失败!");
setResponseBody(response, data); setResponseBody(response, data);
return; return;
} }
@ -607,10 +607,11 @@ public class PayUserPayServiceImpl extends BaseServiceImpl<PayUserPayMapper, Pay
String domain = wxPayApiConfig.getDomain(); String domain = wxPayApiConfig.getDomain();
String requestIP = IpKit.getRealIp(request); String requestIP = IpKit.getRealIp(request);
String notifyUrl = domain + "/lkl_wxPay_notify_url"; String notifyUrl = domain + "/lkl_wxPay_notify_url";
String storeId = Convert.toStr(payConsumeTrade.getStore_id());// 店铺Id
// 拉卡拉预支付返回参数 // 拉卡拉预支付返回参数
cn.hutool.json.JSONObject lakalaRespJSON = lakalaPayService.transPreOrder(shopStoreBase.getLkl_merchant_no(), shopStoreBase.getLkl_term_no(), cn.hutool.json.JSONObject lakalaRespJSON = lakalaPayService.transPreOrder(shopStoreBase.getLkl_merchant_no(), shopStoreBase.getLkl_term_no(),
appId, openId, out_trade_no, subject, total_fee, appId, openId, storeId, out_trade_no, subject, total_amt,
notifyUrl, notifyUrl,
requestIP, trade_remark); requestIP, trade_remark);
@ -635,7 +636,6 @@ public class PayUserPayServiceImpl extends BaseServiceImpl<PayUserPayMapper, Pay
Map result = new HashMap(); Map result = new HashMap();
result.put("data", params); result.put("data", params);
result.put("statusCode", 200); result.put("statusCode", 200);
data.put("status", 200); data.put("status", 200);
data.put("data", result); data.put("data", result);
data.put("message", "OK"); data.put("message", "OK");
@ -1237,11 +1237,13 @@ public class PayUserPayServiceImpl extends BaseServiceImpl<PayUserPayMapper, Pay
try { try {
if (tradeCombine != null) { if (tradeCombine != null) {
notify_row.setOrder_id(tradeCombine.getOrder_ids()); notify_row.setOrder_id(tradeCombine.getOrder_ids());
// 重要支付完成接口调用
if (!payConsumeDepositService.processDeposit(notify_row, zero, zero, zero, zero, zero)) { if (!payConsumeDepositService.processDeposit(notify_row, zero, zero, zero, zero, zero)) {
log.error("支付失败!"); log.error("支付失败!");
return notifyMsg(false, payment_channel_code, "支付失败!"); return notifyMsg(false, payment_channel_code, "支付失败!");
} }
} else { } else {
// 重要支付完成接口调用
if (!payConsumeDepositService.processDeposit(notify_row, zero, zero, zero, zero, zero)) { if (!payConsumeDepositService.processDeposit(notify_row, zero, zero, zero, zero, zero)) {
log.error("支付失败!"); log.error("支付失败!");
return notifyMsg(false, payment_channel_code, "支付失败!"); return notifyMsg(false, payment_channel_code, "支付失败!");
@ -1258,7 +1260,6 @@ public class PayUserPayServiceImpl extends BaseServiceImpl<PayUserPayMapper, Pay
log.error("验签失败!"); log.error("验签失败!");
return notifyMsg(false, payment_channel_code, "验签失败!"); return notifyMsg(false, payment_channel_code, "验签失败!");
} }
} }
@ -1278,14 +1279,15 @@ public class PayUserPayServiceImpl extends BaseServiceImpl<PayUserPayMapper, Pay
// 敏感头信息脱敏打印 // 敏感头信息脱敏打印
logger.debug("拉卡拉支付异步通知回调 body:{} \n authorization: {}", body, authorization); logger.debug("拉卡拉支付异步通知回调 body:{} \n authorization: {}", body, authorization);
// 异步通知返回的json数据{"out_trade_no":"202203151637334864280014","trade_no":"2022031566210203291925","log_no":"66210203291925", // 异步通知返回的body json数据{"out_trade_no":"202203151637334864280014","trade_no":"2022031566210203291925","log_no":"66210203291925",
// "acc_trade_no":"2022031522001483661454130929 ","trade_status":"SUCCESS","trade_state":"SUCCESS","total_amount":"1", // "acc_trade_no":"2022031522001483661454130929 ","trade_status":"SUCCESS","trade_state":"SUCCESS","total_amount":"1",
// "payer_amount":"1","acc_settle_amount":"1","trade_time":"20220315163808","user_id1":"app***@163.com", // "payer_amount":"1","acc_settle_amount":"1","trade_time":"20220315163808","user_id1":"app***@163.com",
// "user_id2":"2088432881453660","notify_url":"https://www.baidu.com","account_type":"ALIPAY","card_type":"99"} // "user_id2":"2088432881453660","notify_url":"https://www.baidu.com","account_type":"ALIPAY","card_type":"99"}
// 解析JSON格式响应 // 解析JSON格式响应
params = Convert.toMap(String.class, String.class, JSONUtil.parseObj(body)); cn.hutool.json.JSONObject lklNotifyRespJSON = JSONUtil.parseObj(body);
String order_id = params.getOrDefault("out_trade_no", ""); params = Convert.toMap(String.class, String.class, lklNotifyRespJSON);
String orderId = params.getOrDefault("out_trade_no", "");
// 提取授权签名信息 // 提取授权签名信息
Map<String, String> authMap = LakalaUtil.getLakalaAuthorizationMap(authorization); Map<String, String> authMap = LakalaUtil.getLakalaAuthorizationMap(authorization);
@ -1296,9 +1298,14 @@ public class PayUserPayServiceImpl extends BaseServiceImpl<PayUserPayMapper, Pay
return lklNotifyMsg(false, "缺少签名信息"); return lklNotifyMsg(false, "缺少签名信息");
} }
if (StrUtil.isBlank(orderId)) {
logger.error("缺少out_trade_no字段");
return lklNotifyMsg(false, "缺少out_trade_no字段");
}
// 查询交易信息 // 查询交易信息
QueryWrapper<PayConsumeTrade> tradeQueryWrapper = new QueryWrapper<>(); QueryWrapper<PayConsumeTrade> tradeQueryWrapper = new QueryWrapper<>();
tradeQueryWrapper.eq("order_id", order_id); tradeQueryWrapper.eq("order_id", orderId);
PayConsumeTrade trade_row_tmp = payConsumeTradeService.findOne(tradeQueryWrapper); PayConsumeTrade trade_row_tmp = payConsumeTradeService.findOne(tradeQueryWrapper);
Integer payment_store_id = trade_row_tmp != null ? trade_row_tmp.getStore_id() : 0; Integer payment_store_id = trade_row_tmp != null ? trade_row_tmp.getStore_id() : 0;
@ -1318,7 +1325,7 @@ public class PayUserPayServiceImpl extends BaseServiceImpl<PayUserPayMapper, Pay
// 插入充值记录 // 插入充值记录
PayConsumeDeposit payConsumeDeposit = createNotify(params, payPaymentChannel); PayConsumeDeposit payConsumeDeposit = createNotify(params, payPaymentChannel);
payConsumeDeposit.setOrder_id(order_id); payConsumeDeposit.setOrder_id(orderId);
payConsumeDeposit.setStore_id(payment_store_id); // 所属店铺 payConsumeDeposit.setStore_id(payment_store_id); // 所属店铺
payConsumeDeposit.setChain_id(0); // 所属门店默认为0 payConsumeDeposit.setChain_id(0); // 所属门店默认为0
payConsumeDeposit.setPayment_channel_id(payment_channel_id); payConsumeDeposit.setPayment_channel_id(payment_channel_id);
@ -1327,13 +1334,18 @@ public class PayUserPayServiceImpl extends BaseServiceImpl<PayUserPayMapper, Pay
payConsumeDeposit.setUser_id(userId); payConsumeDeposit.setUser_id(userId);
// 判断是否联合支付 // 判断是否联合支付
PayConsumeTradeCombine tradeCombine = payConsumeTradeCombineService.get(order_id); PayConsumeTradeCombine tradeCombine = payConsumeTradeCombineService.get(orderId);
TransactionStatus transactionStatus = transactionManager.getTransaction(transactionDefinition); TransactionStatus transactionStatus = transactionManager.getTransaction(transactionDefinition);
try { try {
// 修改 拉卡拉的订单记录 shop_order_lkl
shopService.lklPayNotifyUpdateShopOrderLkl(lklNotifyRespJSON);
if (tradeCombine != null && StrUtil.isNotBlank(tradeCombine.getOrder_ids())) { if (tradeCombine != null && StrUtil.isNotBlank(tradeCombine.getOrder_ids())) {
payConsumeDeposit.setOrder_id(tradeCombine.getOrder_ids()); payConsumeDeposit.setOrder_id(tradeCombine.getOrder_ids());
} }
// 重要支付完成接口调用
if (!payConsumeDepositService.processDeposit(payConsumeDeposit, BigDecimal.ZERO, BigDecimal.ZERO, if (!payConsumeDepositService.processDeposit(payConsumeDeposit, BigDecimal.ZERO, BigDecimal.ZERO,
BigDecimal.ZERO, BigDecimal.ZERO, BigDecimal.ZERO)) { BigDecimal.ZERO, BigDecimal.ZERO, BigDecimal.ZERO)) {
log.error("支付失败!"); log.error("支付失败!");
@ -1347,7 +1359,8 @@ public class PayUserPayServiceImpl extends BaseServiceImpl<PayUserPayMapper, Pay
throw new ApiException(e.getMessage()); throw new ApiException(e.getMessage());
} }
// TODO 分账指令 写入 MQ 定时执行
// TODO 分账指令执行
return lklNotifyMsg(true, "执行成功"); return lklNotifyMsg(true, "执行成功");
} catch (Exception e) { } catch (Exception e) {

View File

@ -205,10 +205,11 @@ public interface LakalaApiService {
* 说明分账指令是异步处理模式响应报文成功时指令状态是status: PROCESSING需要等待分账结果通知或者主动发起查询建议主动发起查询与分账指令动作之间间隔15秒以上 * 说明分账指令是异步处理模式响应报文成功时指令状态是status: PROCESSING需要等待分账结果通知或者主动发起查询建议主动发起查询与分账指令动作之间间隔15秒以上
* 参考https://o.lakala.com/#/home/document/detail?id=389 * 参考https://o.lakala.com/#/home/document/detail?id=389
* *
* @param orderId 平台订单号 * @param orderId 平台订单号,必填参数
* @param storeId 商户门店编号,非必填参数
* @return * @return
*/ */
Pair<Boolean, String> innerDoOrderSeparate(String orderId); Pair<Boolean, String> innerDoOrderSeparate(String orderId, String storeId);
/** /**
* 分账结果通知 * 分账结果通知

View File

@ -1625,29 +1625,31 @@ public class LakalaApiServiceImpl implements LakalaApiService {
* @return * @return
*/ */
@Override @Override
public Pair<Boolean, String> innerDoOrderSeparate(String orderId) { public Pair<Boolean, String> innerDoOrderSeparate(String orderId, String storeId) {
// 输入参数校验 // 输入参数校验
if (StrUtil.isBlank(orderId)) { if (StrUtil.isBlank(orderId)) {
return Pair.of(false, "订单号不能为空"); return Pair.of(false, "订单号不能为空");
} }
try { try {
// TODO 检查可分账余额是否足够
// 初始化拉卡拉SDK // 初始化拉卡拉SDK
initLKLSDK(); initLKLSDK();
// 查询订单信息 // 查询订单信息
List<ShopOrderLkl> shopOrders = shopOrderLklService.selectByOrderId(orderId, ""); List<ShopOrderLkl> shopOrderLklList = shopOrderLklService.selectByOrderId(orderId, "", storeId);
if (CollectionUtil.isEmpty(shopOrders)) { if (CollectionUtil.isEmpty(shopOrderLklList)) {
return Pair.of(false, "订单不存在"); return Pair.of(false, "订单不存在");
} }
int totalCount = shopOrders.size(); int totalCount = shopOrderLklList.size();
int successCount = 0; int successCount = 0;
StringBuilder errorMessages = new StringBuilder(); StringBuilder errorMessages = new StringBuilder();
// 遍历处理每个店铺订单的分账 // 遍历处理每个店铺订单的分账
for (ShopOrderLkl order : shopOrders) { for (ShopOrderLkl order : shopOrderLklList) {
String merchantNo = order.getMerchant_no(); String merchantNo = order.getLkl_merchant_no();
Integer paymentAmount = order.getTotal_amt(); Integer paymentAmount = order.getTotal_amt();
Integer shoppingFee = order.getShopping_fee(); Integer shoppingFee = order.getShopping_fee();
BigDecimal splitRatioMch = order.getSplit_ratio(); BigDecimal splitRatioMch = order.getSplit_ratio();
@ -1680,8 +1682,8 @@ public class LakalaApiServiceImpl implements LakalaApiService {
// 构建分账请求对象 // 构建分账请求对象
V3SacsSeparateRequest request = new V3SacsSeparateRequest(); V3SacsSeparateRequest request = new V3SacsSeparateRequest();
request.setMerchantNo(merchantNo); request.setMerchantNo(merchantNo);
request.setLogNo(order.getLog_no()); request.setLogNo(order.getLkl_log_no());
request.setLogDate(order.getLog_date()); request.setLogDate(order.getLkl_log_date());
request.setOutSeparateNo(orderId); request.setOutSeparateNo(orderId);
request.setTotalAmt(paymentAmount.toString()); request.setTotalAmt(paymentAmount.toString());
request.setLklOrgNo(orgCode); request.setLklOrgNo(orgCode);
@ -1699,8 +1701,10 @@ public class LakalaApiServiceImpl implements LakalaApiService {
recvDatas.add(receiver); recvDatas.add(receiver);
} }
Integer totalSeparateValue = 0;// 平台方和代理商总计分账金额
// 2. 再处理剩余金额的分账如果可以分账 // 2. 再处理剩余金额的分账如果可以分账
if (canSplit) { if (canSplit) {
// 计算实际可分账金额扣除运费后 // 计算实际可分账金额扣除运费后
Integer splitAmount = paymentAmount - shoppingFee; Integer splitAmount = paymentAmount - shoppingFee;
// 计算平台+代理商的总比例 // 计算平台+代理商的总比例
@ -1715,6 +1719,8 @@ public class LakalaApiServiceImpl implements LakalaApiService {
receiver.setRecvNo(platform.getReceiver_no()); receiver.setRecvNo(platform.getReceiver_no());
receiver.setSeparateValue(platformValue.toString()); receiver.setSeparateValue(platformValue.toString());
recvDatas.add(receiver); recvDatas.add(receiver);
totalSeparateValue += platformValue.intValue();
} }
// 代理商分账扣除平台1%后的剩余比例 // 代理商分账扣除平台1%后的剩余比例
@ -1725,6 +1731,8 @@ public class LakalaApiServiceImpl implements LakalaApiService {
receiver.setRecvNo(distributors.get(0).getReceiver_no()); receiver.setRecvNo(distributors.get(0).getReceiver_no());
receiver.setSeparateValue(distributorValue.toString()); receiver.setSeparateValue(distributorValue.toString());
recvDatas.add(receiver); recvDatas.add(receiver);
totalSeparateValue += distributorValue.intValue();
} }
} else { } else {
// 仅平台分账模式 // 仅平台分账模式
@ -1735,6 +1743,8 @@ public class LakalaApiServiceImpl implements LakalaApiService {
receiver.setRecvNo(platform.getReceiver_no()); receiver.setRecvNo(platform.getReceiver_no());
receiver.setSeparateValue(platformValue.toString()); receiver.setSeparateValue(platformValue.toString());
recvDatas.add(receiver); recvDatas.add(receiver);
totalSeparateValue += platformValue.intValue();
} }
} }
} }
@ -1762,21 +1772,22 @@ public class LakalaApiServiceImpl implements LakalaApiService {
// 保存分账记录 // 保存分账记录
JSONObject respData = respJson.getJSONObject("resp_data"); JSONObject respData = respJson.getJSONObject("resp_data");
LklOrderSeparate record = new LklOrderSeparate(); LklOrderSeparate lklOrderSeparate = new LklOrderSeparate();
record.setSeparate_no(respData.getStr("separate_no")); lklOrderSeparate.setSeparate_no(respData.getStr("separate_no"));
record.setOut_separate_no(request.getOutSeparateNo()); lklOrderSeparate.setOut_separate_no(request.getOutSeparateNo());
record.setMerchant_no(merchantNo); lklOrderSeparate.setMerchant_no(merchantNo);
record.setLog_no(request.getLogNo()); lklOrderSeparate.setLog_no(request.getLogNo());
record.setLog_date(request.getLogDate()); lklOrderSeparate.setLog_date(request.getLogDate());
record.setOrder_id(order.getOrder_id()); lklOrderSeparate.setOrder_id(order.getOrder_id());
record.setTotal_amt(request.getTotalAmt()); lklOrderSeparate.setTotal_amt(request.getTotalAmt());
record.setNotify_url(request.getNotifyUrl()); lklOrderSeparate.setNotify_url(request.getNotifyUrl());
record.setLkl_org_no(request.getLklOrgNo()); lklOrderSeparate.setLkl_org_no(request.getLklOrgNo());
record.setRecv_datas(JSONUtil.toJsonStr(request.getRecvDatas())); lklOrderSeparate.setRecv_datas(JSONUtil.toJsonStr(request.getRecvDatas()));
record.setStatus(respData.getStr("status")); lklOrderSeparate.setStatus(respData.getStr("status"));
lklOrderSeparate.setTotal_separate_value(totalSeparateValue);
try { try {
lklOrderSeparateService.addOrUpdateByReceiverNo(record); lklOrderSeparateService.addOrUpdateByReceiverNo(lklOrderSeparate);
successCount++; successCount++;
} catch (Exception e) { } catch (Exception e) {
log.error("保存分账记录失败: {}", e.getMessage(), e); log.error("保存分账记录失败: {}", e.getMessage(), e);
@ -1848,23 +1859,23 @@ public class LakalaApiServiceImpl implements LakalaApiService {
} }
// 4. 构建分账记录对象 // 4. 构建分账记录对象
LklOrderSeparate record = new LklOrderSeparate(); LklOrderSeparate lklOrderSeparate = new LklOrderSeparate();
record.setLog_no(logNo); lklOrderSeparate.setLog_no(logNo);
record.setSeparate_no(separateNo); lklOrderSeparate.setSeparate_no(separateNo);
record.setOut_separate_no(outSeparateNo); lklOrderSeparate.setOut_separate_no(outSeparateNo);
record.setStatus(status); lklOrderSeparate.setStatus(status);
record.setFinal_status(finalStatus); lklOrderSeparate.setFinal_status(finalStatus);
record.setCal_type(paramsJson.getStr("cal_type")); lklOrderSeparate.setCal_type(paramsJson.getStr("cal_type"));
record.setSeparate_type(paramsJson.getStr("separate_type")); lklOrderSeparate.setSeparate_type(paramsJson.getStr("separate_type"));
record.setSeparate_date(paramsJson.getStr("separate_date")); lklOrderSeparate.setSeparate_date(paramsJson.getStr("separate_date"));
// 处理detail_datas避免空指针 // 处理detail_datas避免空指针
JSONArray detailDatas = paramsJson.getJSONArray("detail_datas"); JSONArray detailDatas = paramsJson.getJSONArray("detail_datas");
record.setDetail_datas(detailDatas != null ? detailDatas.toString() : "[]"); lklOrderSeparate.setDetail_datas(detailDatas != null ? detailDatas.toString() : "[]");
// 5. 持久化处理 // 5. 持久化处理
try { try {
boolean updateSuccess = lklOrderSeparateService.addOrUpdateByReceiverNo(record); boolean updateSuccess = lklOrderSeparateService.addOrUpdateByReceiverNo(lklOrderSeparate);
if (!updateSuccess) { if (!updateSuccess) {
log.error("分账记录更新失败, separateNo={}", separateNo); log.error("分账记录更新失败, separateNo={}", separateNo);
return JSONUtil.createObj() return JSONUtil.createObj()

View File

@ -0,0 +1,39 @@
package com.suisung.mall.shop.order.controller.mobile;
import cn.hutool.json.JSONObject;
import com.suisung.mall.common.service.impl.BaseControllerImpl;
import com.suisung.mall.shop.order.service.ShopOrderLklService;
import io.swagger.annotations.Api;
import io.swagger.annotations.ApiOperation;
import org.springframework.web.bind.annotation.RequestBody;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RequestMethod;
import org.springframework.web.bind.annotation.RestController;
import javax.annotation.Resource;
/**
* 拉卡拉订单控制器
*/
@Api(tags = "拉卡拉订单控制器,拉卡拉支付时和成功之后,写入拉卡拉的订单信息。")
@RestController()
@RequestMapping("/mobile/shop/orderlkl")
public class ShopOrderLklController extends BaseControllerImpl {
@Resource
private ShopOrderLklService shopOrderLklService;
@ApiOperation(value = "当拉卡拉支付时,新增一个拉卡拉订单信息", notes = "当拉卡拉支付时,新增一个拉卡拉订单信息")
@RequestMapping(value = "/pay/add/order", method = RequestMethod.POST)
public Boolean lklPayAddShopOrderLkl(@RequestBody JSONObject lklPayReqAndRespJson) {
return shopOrderLklService.addOrUpdateByLklPayDataJson(lklPayReqAndRespJson);
}
@ApiOperation(value = "当拉卡拉支付成功后,更改一个拉卡拉订单信息", notes = "当拉卡拉支付成功后,更改一个拉卡拉订单信息")
@RequestMapping(value = "/pay/notify/update/order", method = RequestMethod.POST)
public Boolean lklPayNotifyUpdateShopOrderLkl(@RequestBody JSONObject lklPayNotifyDataJson) {
return shopOrderLklService.addOrUpdateByLklPayNotifyDataJson(lklPayNotifyDataJson);
}
}

View File

@ -25,6 +25,8 @@ import java.util.List;
/** /**
* 支付成功后微信和支付宝发出异步通知消息到 RabbitMQ * 支付成功后微信和支付宝发出异步通知消息到 RabbitMQ
* 这里 MQ 监听到消息后执行更改订单状态为已支付 * 这里 MQ 监听到消息后执行更改订单状态为已支付
* <p>
* payConsumeDepositService.processDeposit 这个方法里发出 mq 消息
*/ */
@Service @Service
@Slf4j @Slf4j

View File

@ -3,6 +3,8 @@ package com.suisung.mall.shop.order.service;
import com.suisung.mall.common.modules.order.ShopOrderData; import com.suisung.mall.common.modules.order.ShopOrderData;
import com.suisung.mall.core.web.service.IBaseService; import com.suisung.mall.core.web.service.IBaseService;
import java.math.BigDecimal;
/** /**
* <p> * <p>
* 订单详细信息 服务类 * 订单详细信息 服务类
@ -13,4 +15,11 @@ import com.suisung.mall.core.web.service.IBaseService;
*/ */
public interface ShopOrderDataService extends IBaseService<ShopOrderData> { public interface ShopOrderDataService extends IBaseService<ShopOrderData> {
/**
* 获取订单运费
*
* @param orderId
* @return
*/
BigDecimal getOrderShippingFee(String orderId);
} }

View File

@ -8,6 +8,7 @@
package com.suisung.mall.shop.order.service; package com.suisung.mall.shop.order.service;
import cn.hutool.json.JSONObject;
import com.suisung.mall.common.modules.order.ShopOrderLkl; import com.suisung.mall.common.modules.order.ShopOrderLkl;
import com.suisung.mall.core.web.service.IBaseService; import com.suisung.mall.core.web.service.IBaseService;
@ -23,12 +24,33 @@ public interface ShopOrderLklService extends IBaseService<ShopOrderLkl> {
*/ */
Boolean addOrUpdateByStoreOrder(ShopOrderLkl record); Boolean addOrUpdateByStoreOrder(ShopOrderLkl record);
/**
* 根据拉卡拉的支付请求和响应数据新增或更新拉卡拉的订单信息
*
* @param lklPayReqAndRespJson 拉卡拉支付请求和响应JSON参数
* @return
*/
Boolean addOrUpdateByLklPayDataJson(JSONObject lklPayReqAndRespJson);
/**
* 根据拉卡拉的回调数据更新拉卡拉的订单信息
*
* @param lklPayNotifyDataJson 异步通知返回的body json数据
* // {"out_trade_no":"202203151637334864280014","trade_no":"2022031566210203291925","log_no":"66210203291925",
* // "acc_trade_no":"2022031522001483661454130929 ","trade_status":"SUCCESS","trade_state":"SUCCESS","total_amount":"1",
* // "payer_amount":"1","acc_settle_amount":"1","trade_time":"20220315163808","user_id1":"app***@163.com",
* // "user_id2":"2088432881453660","notify_url":"https://www.baidu.com","account_type":"ALIPAY","card_type":"99"}
* @return
*/
Boolean addOrUpdateByLklPayNotifyDataJson(JSONObject lklPayNotifyDataJson);
/** /**
* 根据订单编号查询多条记录因为一个订单里可能有多个店铺的商品 * 根据订单编号查询多条记录因为一个订单里可能有多个店铺的商品
* *
* @param orderId * @param orderId
* @param lklLogNo 拉卡拉支付流水号可选参数
* @param storeId * @param storeId
* @return * @return
*/ */
List<ShopOrderLkl> selectByOrderId(String orderId, String storeId); List<ShopOrderLkl> selectByOrderId(String orderId, String lklLogNo, String storeId);
} }

View File

@ -6211,6 +6211,7 @@ public class ShopOrderBaseServiceImpl extends BaseServiceImpl<ShopOrderBaseMappe
BigDecimal order_money_select_items = Convert.toBigDecimal(store_item.get("order_money_select_items")); BigDecimal order_money_select_items = Convert.toBigDecimal(store_item.get("order_money_select_items"));
BigDecimal freight = Convert.toBigDecimal(store_item.get("freight")); BigDecimal freight = Convert.toBigDecimal(store_item.get("freight"));
BigDecimal voucher_price = Convert.toBigDecimal(order_voucher_row.get("voucher_price")); BigDecimal voucher_price = Convert.toBigDecimal(order_voucher_row.get("voucher_price"));
// 应付款金额计算
BigDecimal order_payment_amount = NumberUtil.sub(NumberUtil.add(order_money_select_items, freight), voucher_price); BigDecimal order_payment_amount = NumberUtil.sub(NumberUtil.add(order_money_select_items, freight), voucher_price);
order_payment_amount = NumberUtil.sub(order_payment_amount, dedu_price); order_payment_amount = NumberUtil.sub(order_payment_amount, dedu_price);
order_payment_amount = NumberUtil.max(order_payment_amount, BigDecimal.valueOf(0)); order_payment_amount = NumberUtil.max(order_payment_amount, BigDecimal.valueOf(0));
@ -7388,6 +7389,9 @@ public class ShopOrderBaseServiceImpl extends BaseServiceImpl<ShopOrderBaseMappe
data_row.setOrder_shipping_fee_amount(_freight); // 运费价格/运费金额 data_row.setOrder_shipping_fee_amount(_freight); // 运费价格/运费金额
data_row.setOrder_shipping_fee(_freight); // 实际运费金额-卖家可修改 data_row.setOrder_shipping_fee(_freight); // 实际运费金额-卖家可修改
// base_row 中获取应付款 order_payment_amount计算平台和代理商的总计分账金额
data_row.setTotal_separate_value(calculatePlatformAndAgentShareAmount(Convert.toInt(base_row.get("store_id")), order_payment_amount)); // 从拉卡拉分账给平台和代理商的总计分账金额
Integer voucher_id = (Integer) order_voucher_row.get("voucher_id"); Integer voucher_id = (Integer) order_voucher_row.get("voucher_id");
String voucher_code = (String) order_voucher_row.get("voucher_code"); String voucher_code = (String) order_voucher_row.get("voucher_code");
BigDecimal _voucher_price = Convert.toBigDecimal(order_voucher_row.get("voucher_price")); BigDecimal _voucher_price = Convert.toBigDecimal(order_voucher_row.get("voucher_price"));
@ -8654,4 +8658,33 @@ public class ShopOrderBaseServiceImpl extends BaseServiceImpl<ShopOrderBaseMappe
return String.format("%07d", pickNum); return String.format("%07d", pickNum);
} }
/**
* 计算平台与代理商的总分账金额即支付金额 × (100% - 平台分账比例)
*
* @param storeId 包含订单基础信息的 Map必须包含 store_id
* @param orderPaymentAmount 订单实际支付金额单位
* @return 分账给平台和代理商的总金额单位
*/
public BigDecimal calculatePlatformAndAgentShareAmount(Integer storeId, BigDecimal orderPaymentAmount) {
if (storeId == null || storeId <= 0 || orderPaymentAmount == null) {
return BigDecimal.ZERO;
}
// 获取平台分账比例例如 95 表示 95%
BigDecimal store_platform_ratio = shopStoreBaseService.getStorePlatformRatio(storeId, false);
if (store_platform_ratio == null) {
return BigDecimal.ZERO;
}
// 确保比例在合理范围 [0, 100]
store_platform_ratio = store_platform_ratio.max(BigDecimal.ZERO).min(new BigDecimal(100));
// 分账比例 = 100% - 平台分账比例
BigDecimal separateRatio = new BigDecimal(100).subtract(store_platform_ratio);
// 分账金额 = 支付金额 × 分账比例 ÷ 100 将百分比转换为小数
return orderPaymentAmount.multiply(separateRatio)
.divide(new BigDecimal(100), 2, RoundingMode.HALF_UP); // 保留两位小数四舍五入
}
} }

View File

@ -6,6 +6,8 @@ import com.suisung.mall.shop.order.mapper.ShopOrderDataMapper;
import com.suisung.mall.shop.order.service.ShopOrderDataService; import com.suisung.mall.shop.order.service.ShopOrderDataService;
import org.springframework.stereotype.Service; import org.springframework.stereotype.Service;
import java.math.BigDecimal;
/** /**
* <p> * <p>
@ -17,4 +19,32 @@ import org.springframework.stereotype.Service;
*/ */
@Service @Service
public class ShopOrderDataServiceImpl extends BaseServiceImpl<ShopOrderDataMapper, ShopOrderData> implements ShopOrderDataService { public class ShopOrderDataServiceImpl extends BaseServiceImpl<ShopOrderDataMapper, ShopOrderData> implements ShopOrderDataService {
/**
* 获取订单运费
*
* @param orderId
* @return
*/
@Override
public BigDecimal getOrderShippingFee(String orderId) {
if (orderId == null) {
return BigDecimal.ZERO;
}
ShopOrderData shopOrderData = getById(orderId);
if (shopOrderData == null) {
return BigDecimal.ZERO;
}
BigDecimal result = shopOrderData.getOrder_shipping_fee();
if (result == null || result.compareTo(BigDecimal.ZERO) == -1) {
result = shopOrderData.getOrder_shipping_fee_amount();
}
if (result == null || result.compareTo(BigDecimal.ZERO) == -1) {
return BigDecimal.ZERO;
}
return result;
}
} }

View File

@ -9,30 +9,48 @@
package com.suisung.mall.shop.order.service.impl; package com.suisung.mall.shop.order.service.impl;
import cn.hutool.core.collection.CollectionUtil; import cn.hutool.core.collection.CollectionUtil;
import cn.hutool.core.convert.Convert;
import cn.hutool.core.util.StrUtil; import cn.hutool.core.util.StrUtil;
import cn.hutool.json.JSONObject;
import cn.hutool.json.JSONUtil;
import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper; import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import com.suisung.mall.common.modules.order.ShopOrderLkl; import com.suisung.mall.common.modules.order.ShopOrderLkl;
import com.suisung.mall.common.utils.DateTimeUtils;
import com.suisung.mall.core.web.service.impl.BaseServiceImpl; import com.suisung.mall.core.web.service.impl.BaseServiceImpl;
import com.suisung.mall.shop.order.mapper.ShopOrderLklMapper; import com.suisung.mall.shop.order.mapper.ShopOrderLklMapper;
import com.suisung.mall.shop.order.service.ShopOrderDataService;
import com.suisung.mall.shop.order.service.ShopOrderLklService; import com.suisung.mall.shop.order.service.ShopOrderLklService;
import com.suisung.mall.shop.store.service.ShopStoreBaseService;
import lombok.extern.slf4j.Slf4j; import lombok.extern.slf4j.Slf4j;
import org.apache.commons.lang3.StringUtils; import org.apache.commons.lang3.StringUtils;
import org.springframework.context.annotation.Lazy;
import org.springframework.stereotype.Service; import org.springframework.stereotype.Service;
import javax.annotation.Resource;
import java.math.BigDecimal;
import java.time.LocalDateTime;
import java.util.List; import java.util.List;
@Slf4j @Slf4j
@Service @Service
public class ShopOrderLklServiceImpl extends BaseServiceImpl<ShopOrderLklMapper, ShopOrderLkl> implements ShopOrderLklService { public class ShopOrderLklServiceImpl extends BaseServiceImpl<ShopOrderLklMapper, ShopOrderLkl> implements ShopOrderLklService {
@Lazy
@Resource
private ShopStoreBaseService shopStoreBaseService;
@Lazy
@Resource
private ShopOrderDataService shopOrderDataService;
@Override @Override
public Boolean addOrUpdateByStoreOrder(ShopOrderLkl record) { public Boolean addOrUpdateByStoreOrder(ShopOrderLkl record) {
if (record == null if (record == null
|| StringUtils.isAnyBlank(record.getOrder_id(), record.getStore_id(), record.getLog_no())) { || StringUtils.isAnyBlank(record.getOrder_id(), record.getLkl_log_no())) {
return false; return false;
} }
List<ShopOrderLkl> existsRecordList = selectByOrderId(record.getOrder_id(), record.getStore_id()); List<ShopOrderLkl> existsRecordList = selectByOrderId(record.getOrder_id(), record.getLkl_log_no(), record.getStore_id());
if (CollectionUtil.isNotEmpty(existsRecordList) if (CollectionUtil.isNotEmpty(existsRecordList)
&& existsRecordList.get(0) != null && existsRecordList.get(0) != null
&& existsRecordList.get(0).getId() > 0) { && existsRecordList.get(0).getId() > 0) {
@ -45,19 +63,181 @@ public class ShopOrderLklServiceImpl extends BaseServiceImpl<ShopOrderLklMapper,
} }
/** /**
* 根据订单编号查询多条记录因为一个订单里可能有多个店铺的商品 * 根据拉卡拉的回调数据更新拉卡拉的订单信息
* *
* @param orderId * @param lklPayReqAndRespJson 拉卡拉支付请求和响应JSON参数
* {"req":{
* "req_time": "20240621153714",
* "version": "3.0",
* "req_data": {
* "merchant_no": "822290059430BCY",
* "term_no": "D9285650",
* "out_trade_no": "720982165373671834096",
* "account_type": "ALIPAY",
* "trans_type": "41",
* "total_amount": 1,
* "notify_url": "http://47.105.146.241:9510/channelbacknotice/open/platform/transfer/V3",
* "location_info": {
* "request_ip": "192.168.23.165",
* "location": "+23.137208/+113.381982"
* },
* "subject": "测试"
* }
* },
* "resp": {
* "code": "BBS00000",
* "msg": "成功",
* "resp_time": "20240626155843",
* "resp_data": {
* "merchant_no": "822290059430BCY",
* "out_trade_no": "720982165373671834096",
* "trade_no": "2024062666210315450047",
* "log_no": "66210315450047",
* "settle_merchant_no": "",
* "settle_term_no": "",
* "acc_resp_fields": {
* "code": "https://qr.alipay.com/bax01162hikpdvl7nk9t005f",
* "code_image": "",
* "prepay_id": "",
* "app_id": "",
* "pay_sign": "",
* "time_stamp": "",
* "nonce_str": "",
* "package": "",
* "sign_type": "",
* "form_data": "",
* "redirect_url": "",
* "best_pay_info": ""
* }
* }
* }
* }
* @return * @return
*/ */
@Override @Override
public List<ShopOrderLkl> selectByOrderId(String orderId, String storeId) { public Boolean addOrUpdateByLklPayDataJson(JSONObject lklPayReqAndRespJson) {
if (lklPayReqAndRespJson == null) {
log.warn("参数为空,无法保存拉卡拉订单记录");
return false;
}
// 获取请求体和响应体
JSONObject reqDataJson = JSONUtil.parseObj(lklPayReqAndRespJson.getByPath("req.req_data"));
JSONObject respDataJson = JSONUtil.parseObj(lklPayReqAndRespJson.getByPath("resp.resp_data"));
if (reqDataJson == null || respDataJson == null) {
log.warn("请求或响应数据中的 req_data / resp_data 为空");
return false;
}
// 提取订单号并校验
String orderId = reqDataJson.getStr("out_trade_no");
if (StringUtils.isBlank(orderId)) {
log.warn("订单ID为空无法保存拉卡拉支付记录");
return false;
}
ShopOrderLkl record = new ShopOrderLkl();
record.setOrder_id(orderId);
// 设置请求内容
record.setLkl_merchant_no(reqDataJson.getStr("merchant_no"));
record.setLkl_term_no(reqDataJson.getStr("term_no"));
// 订单金额安全处理
Integer amount = reqDataJson.getInt("total_amount");
if (amount == null) {
log.error("订单{}金额无效: {}", orderId, amount);
return false;
}
record.setTotal_amt(amount);
record.setAccount_type(reqDataJson.getStr("account_type"));
record.setTrans_type(reqDataJson.getStr("trans_type"));
record.setNotify_url(reqDataJson.getStr("notify_url"));
record.setLkl_req(JSONUtil.toJsonStr(reqDataJson));
// 设置响应内容
record.setLkl_log_no(respDataJson.getStr("log_no"));
record.setLkl_trade_no(respDataJson.getStr("trade_no"));
record.setLkl_resp(JSONUtil.toJsonStr(respDataJson));
// 关键数据获取店铺ID分账比例用到
Integer storeId = 0;
Object attachObj = reqDataJson.getByPath("acc_busi_fields.attach");
if (attachObj != null) {
storeId = Convert.toInt(attachObj);
record.setStore_id(storeId.toString());
}
// 运费和商家分账比例
BigDecimal shipperFee = shopOrderDataService.getOrderShippingFee(orderId);
record.setShopping_fee(shipperFee.multiply(BigDecimal.valueOf(100)).intValue()); // 运费单位
record.setSplit_ratio(shopStoreBaseService.getStorePlatformRatio(storeId, false)); // 商家分账比例
return addOrUpdateByStoreOrder(record);
}
@Override
public Boolean addOrUpdateByLklPayNotifyDataJson(JSONObject lklPayNotifyDataJson) {
if (lklPayNotifyDataJson == null) {
log.warn("参数为空,无法保存拉卡拉支付通知记录");
return false;
}
String orderId = lklPayNotifyDataJson.getStr("out_trade_no");
if (StringUtils.isBlank(orderId)) {
log.warn("订单ID为空无法保存拉卡拉支付通知记录");
return false;
}
ShopOrderLkl record = new ShopOrderLkl();
record.setOrder_id(orderId);
// 设置必填字段并校验
String logNo = lklPayNotifyDataJson.getStr("log_no");
if (StringUtils.isBlank(logNo)) {
log.warn("log_no 为空,无法保存拉卡拉支付通知记录");
return false;
}
record.setLkl_log_no(logNo);
// 设置日期字段
record.setLkl_log_date(DateTimeUtils.formatDateTime(LocalDateTime.now(), "yyyy-MM-dd"));
// 设置可选字段
record.setLkl_trade_no(lklPayNotifyDataJson.getStr("trade_no"));
record.setTrade_status(lklPayNotifyDataJson.getStr("trade_status"));
// 安全地设置响应内容
record.setLkl_resp(JSONUtil.toJsonStr(lklPayNotifyDataJson));
return addOrUpdateByStoreOrder(record);
}
/**
* 根据订单编号查询多条记录因为一个订单里可能有多个店铺的商品
*
* @param orderId 订单Id必填参数
* @param lklLogNo 拉卡拉支付流水号可选参数
* @param storeId 店铺Id可选参数
* @return
*/
@Override
public List<ShopOrderLkl> selectByOrderId(String orderId, String lklLogNo, String storeId) {
if (StringUtils.isBlank(orderId)) { if (StringUtils.isBlank(orderId)) {
return null; return null;
} }
QueryWrapper<ShopOrderLkl> queryWrapper = new QueryWrapper<>(); QueryWrapper<ShopOrderLkl> queryWrapper = new QueryWrapper<>();
queryWrapper.eq("order_id", orderId).orderByAsc("id"); queryWrapper.eq("order_id", orderId).orderByAsc("id");
if (StrUtil.isNotBlank(lklLogNo)) {
queryWrapper.eq("lkl_log_no", lklLogNo);
}
if (StrUtil.isNotBlank(storeId)) { if (StrUtil.isNotBlank(storeId)) {
queryWrapper.eq("store_id", storeId); queryWrapper.eq("store_id", storeId);
} }

View File

@ -172,4 +172,5 @@ public interface ShopStoreBaseService extends IBaseService<ShopStoreBase> {
* @return 平台分账比例的数值 * @return 平台分账比例的数值
*/ */
BigDecimal getStorePlatformRatio(Integer storeId, boolean reCalculate); BigDecimal getStorePlatformRatio(Integer storeId, boolean reCalculate);
} }

View File

@ -43,6 +43,7 @@ import org.springframework.data.util.Pair;
import org.springframework.stereotype.Service; import org.springframework.stereotype.Service;
import javax.annotation.Resource; import javax.annotation.Resource;
import java.math.BigDecimal;
import java.util.*; import java.util.*;
/** /**
@ -497,58 +498,73 @@ public class ShopMchEntryServiceImpl extends BaseServiceImpl<ShopMchEntryMapper,
*/ */
@Override @Override
public CommonResult shopMerchEntryApproval(Long id, Integer approvalStatus, String approvalRemark, String approvalInvalidCol) { public CommonResult shopMerchEntryApproval(Long id, Integer approvalStatus, String approvalRemark, String approvalInvalidCol) {
// 检查登录用户是否有管理权限 // 固定用户ID模拟管理员
String userId = "0"; String userId = "0";
// UserDto user = getCurrentUser(); // UserDto user = getCurrentUser();
// if (!user.isAdmin()) { // if (!user.isAdmin()) {
// return CommonResult.failed("权限不足!"); // return CommonResult.failed("权限不足!");
// } // }
// userId = user.getId().toString(); // userId = user.getId().toString();
// 参数校验流程
if (ObjectUtil.isEmpty(id) || ObjectUtil.isEmpty(approvalStatus)) { if (ObjectUtil.isEmpty(id) || ObjectUtil.isEmpty(approvalStatus)) {
return CommonResult.failed("缺少必要参数!"); return CommonResult.failed("缺少必要参数!");
} }
// 审核状态有效性校验
if (!approvalStatus.equals(CommonConstant.MCH_APPR_STA_LKL_PADDING) && !approvalStatus.equals(CommonConstant.MCH_APPR_STA_NOPASS)) { if (!approvalStatus.equals(CommonConstant.MCH_APPR_STA_LKL_PADDING) && !approvalStatus.equals(CommonConstant.MCH_APPR_STA_NOPASS)) {
return CommonResult.failed("审批状态有误!"); return CommonResult.failed("审批状态有误!");
} }
// 查询入驻记录
ShopMchEntry record = getById(id); ShopMchEntry record = getById(id);
if (record == null) { if (record == null) {
return CommonResult.failed("商家入驻记录不存在!"); return CommonResult.failed("商家入驻记录不存在!");
} }
// TODO 已经审核通过的不能再审核了 // 初始化更新包装器
UpdateWrapper<ShopMchEntry> updateWrapper = new UpdateWrapper<>(); UpdateWrapper<ShopMchEntry> updateWrapper = new UpdateWrapper<>();
if (approvalStatus.equals(CommonConstant.MCH_APPR_STA_LKL_PADDING) && StrUtil.isBlank(approvalRemark)) { updateWrapper.eq("id", id);
// 审核通过
approvalRemark = "初步审核通过,等待进一步审核。";//"审核通过,后续将向您发起签署电子合同流程。";
updateWrapper.set("signed_status", CommonConstant.CONTRACT_SIGN_STA_ING);
updateWrapper.set("approval_status", CommonConstant.MCH_APPR_STA_LKL_PADDING); // 进入拉卡拉审核中
log.info("准备提交给拉卡拉进件审核。"); // 设置默认审批备注
} else if (approvalStatus.equals(CommonConstant.MCH_APPR_STA_NOPASS) && StrUtil.isBlank(approvalRemark)) { if (StrUtil.isBlank(approvalRemark)) {
approvalRemark = "审核未通过,请继续完善入驻资料信息。"; approvalRemark = "审核未通过,请继续完善入驻资料信息。";
} }
// 重要备注自动计算商家分成比例 if (approvalStatus.equals(CommonConstant.MCH_APPR_STA_LKL_PADDING)) {
record.setSplit_ratio(shopBaseStoreCategoryService.getStoreCategoryRatio(record.getBiz_category())); approvalRemark = "初审通过,等待进一步审核。";
// updateWrapper.set("signed_status", CommonConstant.CONTRACT_SIGN_STA_ING); // 合同签署中
updateWrapper.eq("id", id) approvalInvalidCol = "[]";
.set("approval_status", approvalStatus)
.set("approval_remark", approvalRemark)
.set("updated_by", userId);
// 指定哪些字段无效字段的审批细节
if (StrUtil.isNotBlank(approvalInvalidCol)) {
updateWrapper.set("approval_invalid_col", approvalInvalidCol);
} }
// 设置无效字段
if (StrUtil.isBlank(approvalInvalidCol)) {
approvalInvalidCol = "[]";
}
// 自动计算商家分成比例
BigDecimal splitRatio = shopBaseStoreCategoryService.getStoreCategoryRatio(record.getBiz_category());
if (splitRatio == null || splitRatio.compareTo(BigDecimal.ZERO) <= 0) {
splitRatio = new BigDecimal("100");
}
// 构建更新参数
updateWrapper
.set("approval_status", approvalStatus)
.set("approval_remark", approvalRemark)
.set("split_ratio", splitRatio)
.set("approval_invalid_col", approvalInvalidCol)
.set("updated_by", userId);
// 执行更新操作
if (!update(updateWrapper)) { if (!update(updateWrapper)) {
log.error("系统处理审批出错请联系管理员当前记录ID: {}", id);
return CommonResult.failed("系统处理审批出错,请联系管理员!"); return CommonResult.failed("系统处理审批出错,请联系管理员!");
} }
// 如果是驳回状态直接返回成功消息
if (approvalStatus.equals(CommonConstant.MCH_APPR_STA_NOPASS)) { if (approvalStatus.equals(CommonConstant.MCH_APPR_STA_NOPASS)) {
return CommonResult.success(null, "驳回成功!"); return CommonResult.success(null, "驳回成功!");
} }
@ -557,11 +573,15 @@ public class ShopMchEntryServiceImpl extends BaseServiceImpl<ShopMchEntryMapper,
// 平台人工审核通过后触发去拉卡拉商家入网电子合同签署 // 平台人工审核通过后触发去拉卡拉商家入网电子合同签署
// 下一步商家入网电子合同签署完毕后收到异步通知触发拉卡拉商家进件重要环节 // 下一步商家入网电子合同签署完毕后收到异步通知触发拉卡拉商家进件重要环节
Pair<Boolean, String> resultPair = lakalaApiService.applyLedgerMerEc(record.getLogin_mobile()); try {
if (!resultPair.getFirst()) { Pair<Boolean, String> resultPair = lakalaApiService.applyLedgerMerEc(record.getLogin_mobile());
return CommonResult.failed(resultPair.getSecond()); if (!resultPair.getFirst()) {
} log.warn("拉卡拉电子合同签署申请失败: {}", resultPair.getSecond());
return CommonResult.failed(resultPair.getSecond());
}
// E签宝暂时停止使用
// if (approvalStatus.equals(CommonConstant.Enable)) { // if (approvalStatus.equals(CommonConstant.Enable)) {
// // 多线程执行电子合同生成和填充 // // 多线程执行电子合同生成和填充
// taskService.executeTask(() -> { // taskService.executeTask(() -> {
@ -576,6 +596,11 @@ public class ShopMchEntryServiceImpl extends BaseServiceImpl<ShopMchEntryMapper,
// }); // });
// } // }
} catch (Exception e) {
log.error("调用拉卡拉电子合同接口异常", e);
return CommonResult.failed("调用拉卡拉服务失败,请稍后重试");
}
return CommonResult.success(); return CommonResult.success();
} }

View File

@ -3487,37 +3487,41 @@ public class ShopStoreBaseServiceImpl extends BaseServiceImpl<ShopStoreBaseMappe
*/ */
@Override @Override
public BigDecimal getStorePlatformRatio(Integer storeId, boolean reCalculate) { public BigDecimal getStorePlatformRatio(Integer storeId, boolean reCalculate) {
if (ObjectUtil.isEmpty(storeId)) { if (storeId == null || storeId <= 0) {
return null; return null;
} }
// 获取店铺基础信息
ShopStoreBase shopStoreBase = get(storeId); ShopStoreBase shopStoreBase = get(storeId);
if (ObjectUtil.isEmpty(shopStoreBase)) { if (shopStoreBase == null) {
return null; return null;
} }
// 获取店铺已配置的分账比例
BigDecimal splitRatio = shopStoreBase.getSplit_ratio(); BigDecimal splitRatio = shopStoreBase.getSplit_ratio();
if (splitRatio == null) {
splitRatio = new BigDecimal(100); // 如果没有配置或需要重新计算则基于店铺分类获取比例
if (reCalculate || splitRatio == null) {
Integer storeCategoryId = shopStoreBase.getStore_category_id();
if (storeCategoryId == null) {
return new BigDecimal(100); // 默认 100%
}
// 获取店铺分类信息
ShopBaseStoreCategory category = shopBaseStoreCategoryService.get(storeCategoryId);
if (category != null && category.getSplit_ratio() != null) {
splitRatio = category.getSplit_ratio();
} else {
splitRatio = new BigDecimal(100); // 默认值
}
// 确保比例不超过 100%
if (splitRatio.compareTo(new BigDecimal(100)) > 0) {
splitRatio = new BigDecimal(100);
}
} }
if (!reCalculate) { return splitRatio;
return splitRatio;
}
Integer storeCategoryId = shopStoreBase.getStore_category_id();
if (ObjectUtil.isEmpty(storeCategoryId)) {
return splitRatio;
}
// 重新计算分账比例()
ShopBaseStoreCategory shopBaseStoreCategory = shopBaseStoreCategoryService.get(storeCategoryId);
if (ObjectUtil.isEmpty(shopBaseStoreCategory)) {
return splitRatio;
}
splitRatio = shopBaseStoreCategory.getSplit_ratio();
return ObjectUtil.isEmpty(splitRatio) ? new BigDecimal(100) : splitRatio;
} }
/** /**