分账业务申请和异步通知方法 修复

This commit is contained in:
Jack 2025-05-20 17:04:47 +08:00
parent a01c9adb25
commit 9d287da156
13 changed files with 629 additions and 286 deletions

View File

@ -45,12 +45,13 @@ public class CommonConstant {
public static final Integer PRODUCT_DATA_SOURCE_USER = 1;
public static final Integer PRODUCT_DATA_SOURCE_SX = 2;
// 入驻商家的审批状态1-已通过2-未通过3-待审核4-未申请过5-已提交拉卡拉审核
// 入驻审批状态1-已通过2-未通过3-待审核4-未申请过5-已提交拉卡拉审核21-拉卡拉审核未通过
public static final Integer MCH_APPR_STA_PASS = 1;
public static final Integer MCH_APPR_STA_NOPASS = 2;
public static final Integer MCH_APPR_STA_PADDING = 3;
public static final Integer MCH_APPR_STA_NONE = 4;
public static final Integer MCH_APPR_STA_LKL_PADDING = 5;
public static final Integer MCH_APPR_STA_LKL_NOPASS = 21;
// 入驻商家主体类型企业或个人1-企业2-个人
public static final Integer MCH_ENTITY_TYPE_QY = 1;

View File

@ -39,6 +39,7 @@ public class LklLedgerEc implements Serializable {
private String ec_no;
private String ec_name;
private String ec_file;
private String lkl_file_path;
private String ec_status;
private Long ec_apply_id;
private String result_url;

View File

@ -231,6 +231,9 @@ public class ShopMchEntry implements Serializable {
@ApiModelProperty(value = "拉卡拉入网电子合同名称")
private String lkl_ec_name;
@ApiModelProperty(value = "入网电子合同拉卡拉相对路径")
private String lkl_ec_file_path;
@ApiModelProperty(value = "拉卡拉入网电子合同签署H5地址进件必须使用")
private String lkl_ec_result_url;
@ -240,6 +243,18 @@ public class ShopMchEntry implements Serializable {
@ApiModelProperty(value = "店铺创建状态1-已启用入驻已审批合同已生成2-未启用")
private Integer store_status;
@ApiModelProperty(value = "是否签署电子合同1-是2-否;")
private Integer has_ec_signed;
@ApiModelProperty(value = "是否申请分账业务1-是2-否;")
private Integer has_apply_split;
@ApiModelProperty(value = "是否新增分账接收方1-是2-否;")
private Integer has_apply_receiver;
@ApiModelProperty(value = "是否绑定分账接收方1-是2-否;")
private Integer has_bind_receiver;
@ApiModelProperty(value = "该商家入驻记录是否有效0:无效1:有效")
private Integer status;

View File

@ -310,6 +310,21 @@ public class UploadUtil {
return null;
}
public static String fileToBase64(File file) {
if (file == null) {
return null;
}
try {
byte[] bytes = Files.readAllBytes(file.toPath());
return Base64Utils.encodeToString(bytes);
} catch (IOException e) {
// 可以在这里添加日志记录方便调试这里简单打印异常信息
log.error("处理file时出现 IOException: ", e.getMessage());
}
return null;
}
/**
* 将MultipartFile 图片转换为Base64字符串
*

View File

@ -316,7 +316,7 @@ public class EsignContractServiceImpl extends BaseServiceImpl<EsignContractMappe
}
// 更新商家的hasEsigned状态=1
lklLedgerMemberService.updateMulStatus("", esignContract.getMch_mobile(), 1, 0, 0, 0);
shopMchEntryService.updateMulStatus(esignContract.getMch_mobile(), "", 1, 0, 0, 0);
return new ResponseEntity<>(new JSONObject().put("code", 200).put("msg", "success").toString(), HttpStatus.OK);
}

View File

@ -14,6 +14,8 @@ import com.suisung.mall.common.service.impl.BaseControllerImpl;
import com.suisung.mall.shop.lakala.service.LakalaApiService;
import io.swagger.annotations.Api;
import io.swagger.annotations.ApiOperation;
import org.springframework.http.HttpStatus;
import org.springframework.http.ResponseEntity;
import org.springframework.util.Base64Utils;
import org.springframework.web.bind.annotation.*;
import org.springframework.web.multipart.MultipartFile;
@ -52,8 +54,13 @@ public class LakalaController extends BaseControllerImpl {
@ApiOperation(value = "商户入网电子合同申请回调通知", notes = "商户入网电子合同申请回调通知")
@RequestMapping(value = "/ec/applyNotify", method = RequestMethod.POST)
public JSONObject ecApplyNotify(HttpServletRequest request) {
return lakalaPayService.applyLedgerMerEcNotify(request);
public ResponseEntity<JSONObject> ecApplyNotify(HttpServletRequest request) {
JSONObject resp = lakalaPayService.applyLedgerMerEcNotify(request);
if (resp != null && "SUCCESS".equals(resp.get("code"))) {
return new ResponseEntity<>(resp, HttpStatus.OK);
}
return new ResponseEntity<>(resp, HttpStatus.INTERNAL_SERVER_ERROR);
}
@ApiOperation(value = "商户分账业务开通申请", notes = "商户分账业务开通申请")
@ -64,8 +71,13 @@ public class LakalaController extends BaseControllerImpl {
@ApiOperation(value = "商户分账业务开通申请异步回调通知", notes = "商户分账业务开通申请异步回调通知")
@RequestMapping(value = "/ledger/applyLedgerMerNotify", method = RequestMethod.POST)
public JSONObject ledgerApplyLedgerMerNotify(HttpServletRequest request) {
return lakalaPayService.applyLedgerMerNotify(request);
public ResponseEntity<JSONObject> ledgerApplyLedgerMerNotify(HttpServletRequest request) {
JSONObject resp = lakalaPayService.applyLedgerMerNotify(request);
if (resp != null && "SUCCESS".equals(resp.get("code"))) {
return new ResponseEntity<>(resp, HttpStatus.OK);
}
return new ResponseEntity<>(resp, HttpStatus.INTERNAL_SERVER_ERROR);
}
@ApiOperation(value = "分账接收方创建申请", notes = "分账接收方创建申请")
@ -83,7 +95,12 @@ public class LakalaController extends BaseControllerImpl {
// https://mall.gpxscs.cn/api/mobile/shop/lakala/ledger/applyLedgerMerReceiverBindNotify
@ApiOperation(value = "分账关系绑定申请异步回调通知", notes = "分账关系绑定申请异步回调通知")
@RequestMapping(value = "/ledger/applyLedgerMerReceiverBindNotify", method = RequestMethod.POST)
public JSONObject applyBindNotify(HttpServletRequest request) {
return lakalaPayService.applyLedgerMerReceiverBindNotify(request);
public ResponseEntity<JSONObject> applyBindNotify(HttpServletRequest request) {
JSONObject resp = lakalaPayService.applyLedgerMerReceiverBindNotify(request);
if (resp != null && "SUCCESS".equals(resp.get("code"))) {
return new ResponseEntity<>(resp, HttpStatus.OK);
}
return new ResponseEntity<>(resp, HttpStatus.INTERNAL_SERVER_ERROR);
}
}

View File

@ -133,7 +133,7 @@ public interface LakalaApiService {
* @param ecApplyId
* @return
*/
String LedgerMerEcDownload(Long ecApplyId);
Pair<String, String> ledgerMerEcDownload(Long ecApplyId);
/**
* 商户分账业务开通申请回调

View File

@ -689,8 +689,8 @@ public class LakalaApiServiceImpl implements LakalaApiService {
req.setVersion("2.0");
req.setOrderNo(StringUtils.genLklOrderNo(8));// 14位年月日时24小时制分秒+8位的随机数
req.setOrgCode(orgCode);
req.setMerInnerNo(shopMchEntry.getLkl_mer_inner_no());// 从进件申请返回的内部商户号
req.setMerCupNo(shopMchEntry.getLkl_mer_cup_no()); // 从进件申请返回的商户号
// req.setMerInnerNo(shopMchEntry.getLkl_mer_inner_no());// 从进件申请返回的内部商户号
req.setMerCupNo(shopMchEntry.getLkl_mer_cup_no()); // 从进件申请返回的商户号不要传入内部商户号传银联商户号才有效
req.setContactMobile(shopMchEntry.getLogin_mobile()); // 商户入驻注册的手机号
// 分账比例为了考虑低价订单的运费占比高分账比例暂时定70%分账给商户30%分账给平台
req.setSplitLowestRatio(new BigDecimal(splitLowestRatio));
@ -699,15 +699,15 @@ public class LakalaApiServiceImpl implements LakalaApiService {
req.setSplitEntrustFileName(fileName);
// TODO 分账结算委托书文件上传到拉卡拉服务器
JSONObject fileUploadResp = uploadFile(req.getOrderNo(), "SPLIT_ENTRUST_FILE", StringUtils.getFileExt(fileName), UploadUtil.fileUrlToBase64(shopMchEntry.getContract_download_url()));
if (fileUploadResp == null || StrUtil.isBlank(fileUploadResp.getStr("attFileId"))) {
log.error("商家分账授权委托书{}上传失败!", shopMchEntry.getContract_download_url());
// return Pair.of(false, I18nUtil._("商家分账授权委托书上传失败!"));
// throw new ApiException(I18nUtil._("商家分账授权委托书上传失败!"));
}
// JSONObject fileUploadResp = uploadFile(req.getOrderNo(), "SPLIT_ENTRUST_FILE", StringUtils.getFileExt(fileName), UploadUtil.fileUrlToBase64(shopMchEntry.getContract_download_url()));
// if (fileUploadResp == null || StrUtil.isBlank(fileUploadResp.getStr("attFileId"))) {
// log.error("商家分账授权委托书{}上传失败!", shopMchEntry.getContract_download_url());
// // return Pair.of(false, I18nUtil._("商家分账授权委托书上传失败!"));
//// throw new ApiException(I18nUtil._("商家分账授权委托书上传失败!"));
// }
String splitEntrustFilePath = fileUploadResp.getStr("attFileId");
req.setSplitEntrustFilePath(splitEntrustFilePath); //比如G1/M00/06/64/CrFdEmBQc-aAGc_XAAAiIbS3WIE960.pdf;
String splitEntrustFilePath = shopMchEntry.getLkl_ec_file_path(); //fileUploadResp.getStr("attFileId");
req.setSplitEntrustFilePath(splitEntrustFilePath); //比如MMS/20250519/165150-39c8bbca513b4cccab1e942999021fd6.pdf;
String domain = projectDomain;
if (isProdProject()) {
@ -719,7 +719,6 @@ public class LakalaApiServiceImpl implements LakalaApiService {
log.debug("商户分账业务申请请求参数:{}", JSONUtil.toJsonStr(req));
try {
//3. 发送请求
String responseStr = LKLSDK.httpPost(req);
@ -727,14 +726,16 @@ public class LakalaApiServiceImpl implements LakalaApiService {
return Pair.of(false, I18nUtil._("无返回值,申请开通分账失败!"));
}
log.debug("商户分账业务申请响应数据:{}", responseStr);
// 成功返回示例{'retCode':'000000','retMsg':'申请已受理请等待审核结果','respData':{'version':'1.0','orderNo':'KFPT20230223181025407788734','orgCode':'1','applyId':681201215598657536}}
JSONObject lakalaRespJSON = JSONUtil.parseObj(responseStr);
if (lakalaRespJSON == null) {
return Pair.of(false, I18nUtil._("无返回值,申请开通分账失败!"));
}
String applyId = lakalaRespJSON.getStr("applyId");
if (!lakalaRespJSON.getStr("retCode").equals(lklSuccessCode) || StrUtil.isBlank(applyId)) {
Object applyId = lakalaRespJSON.getByPath("respData.applyId");
if (!lakalaRespJSON.getStr("retCode").equals(lklSuccessCode) || applyId == null) {
return Pair.of(false, lakalaRespJSON.getStr("retMsg"));
}
@ -743,7 +744,7 @@ public class LakalaApiServiceImpl implements LakalaApiService {
paramsJSON.put("org_code", orgCode);
paramsJSON.put("version", "2.0");
paramsJSON.put("ret_url", retUrl);
paramsJSON.put("mer_inner_no", req.getMerInnerNo());
paramsJSON.put("mer_inner_no", shopMchEntry.getLkl_mer_inner_no());
paramsJSON.put("mer_cup_no", shopMchEntry.getLkl_mer_cup_no());
paramsJSON.put("contact_mobile", shopMchEntry.getLogin_mobile());
paramsJSON.put("split_lowest_ratio", req.getSplitLowestRatio());
@ -790,8 +791,8 @@ public class LakalaApiServiceImpl implements LakalaApiService {
// 验签
String authorization = request.getHeader("Authorization");
String requestBody = LakalaUtil.getBody(request);
log.debug("商户入网电子合同申请回调返回request body参数{}", requestBody);
log.debug("商户入网电子合同申请回调返回authorization参数{}", authorization);
log.debug("商户入网电子合同申请回调返回requestbody 参数:{}\n authorization参数:{}\n", requestBody, authorization);
String errMsg = "商户入网电子合同申请回调:";
boolean checkSuccess = LakalaUtil.verify(authorization, requestBody, lklNotifyCerPath);
@ -812,7 +813,7 @@ public class LakalaApiServiceImpl implements LakalaApiService {
String ecStatus = paramsJSON.getStr("ecStatus"); // COMPLETED
if (ecStatus == null || !ecStatus.equals("COMPLETED")) {
log.debug("商户入网电子合同申请状态尚未签署完成!");
respData.put("message", "入网电子合同尚未签署,请稍候!");
respData.put("message", "商户入网电子合同尚未签署,请稍候!");
return respData;
}
@ -838,20 +839,27 @@ public class LakalaApiServiceImpl implements LakalaApiService {
}
// base64 合同文件上传到 cos 服务器返回 url 地址
String ecFileUrl = LedgerMerEcDownload(ecApplyId);
Pair<String, String> ecFilePair = ledgerMerEcDownload(ecApplyId);
String ecCosFileUrl = "";
String eclklFilePath = "";
if (ecFilePair != null) {
ecCosFileUrl = ecFilePair.getFirst();
eclklFilePath = ecFilePair.getSecond();
}
// 更改本地记录状态数据
LklLedgerEc updRecord = new LklLedgerEc();
updRecord.setEc_apply_id(ecApplyId);
updRecord.setEc_no(ecNo);
updRecord.setEc_name(paramsJSON.getStr("ecName"));
updRecord.setEc_file(ecFileUrl); // 合同本地文件COS URL链接
updRecord.setEc_file(ecCosFileUrl); // 合同本地文件COS URL链接
updRecord.setLkl_file_path(eclklFilePath);
updRecord.setEc_status(paramsJSON.getStr("ecStatus"));
// 更新本地数据状态和合同编号合同名字
Boolean success = lklLedgerEcService.updateByApplyId(updRecord);
if (success) {
// 更新商家入驻表的合同编号和签署地址更改状态
shopMchEntryService.updateMerchEntryLklEcNo(lklLedgerEc.getMch_id(), ecNo, paramsJSON.getStr("ecName"), lklLedgerEc.getResult_url(), ecFileUrl);
shopMchEntryService.updateMerchEntryLklEcNo(lklLedgerEc.getMch_id(), ecNo, paramsJSON.getStr("ecName"), lklLedgerEc.getResult_url(), ecCosFileUrl, eclklFilePath);
// TODO 商家电子合同签署完毕后收到异步通知触发拉卡拉商家进件重要环节
// 下一步等待拉卡拉系统审核和人工审核收到异步通知之后触发1e签宝的电子合同签署2新增分账接收方
@ -878,16 +886,16 @@ public class LakalaApiServiceImpl implements LakalaApiService {
}
/**
* 商户入网盖章电子合同下载
* 商户入网盖章电子合同下载, 并上传到 cos 服务器
*
* @param ecApplyId
* @return
* @return cosUrl, lklFilePath
*/
@Override
public String LedgerMerEcDownload(Long ecApplyId) {
public Pair<String, String> ledgerMerEcDownload(Long ecApplyId) {
log.debug("商家开始申请入网电子合同");
if (ObjectUtil.isEmpty(ecApplyId)) {
return "";
return null;
}
JSONObject reqData = new JSONObject();
@ -914,32 +922,32 @@ public class LakalaApiServiceImpl implements LakalaApiService {
ResponseEntity<JSONObject> response = RestTemplateHttpUtil.sendPostBodyBackEntity(reqUrl, header, reqBody, JSONObject.class);
if (ObjectUtil.isEmpty(response) || response.getStatusCode() != HttpStatus.OK) {
log.error("下载电子合同失败:返回状态有误!");
return "";
return null;
}
JSONObject respBody = response.getBody();
if (ObjectUtil.isNotEmpty(respBody) && !lklSuccessCode.equals(respBody.getStr("code"))) {
String errMsg = StrUtil.isBlank(respBody.getStr("msg")) ? "返回状态有误" : respBody.getStr("msg");
log.error("下载电子合同失败:{}", errMsg);
return "";
return null;
}
JSONObject respData = respBody.getJSONObject("resp_data");
if (respBody.getJSONObject("resp_data") == null) {
log.error("下载电子合同失败:返回数据有误!");
return "";
return null;
}
String ecFile = respData.getStr("ec_file");
if (StrUtil.isBlank(ecFile)) {
log.error("下载电子合同失败:返回数据有误!");
return "";
return null;
}
LklLedgerEc lklLedgerEc = lklLedgerEcService.getByApplyId(ecApplyId, "", CommonConstant.Enable);
if (lklLedgerEc == null) {
log.error("下载电子合同失败:未找到对应的入网电子合同记录");
return "";
return null;
}
String fileBase64 = respData.getStr("ec_file");
@ -956,10 +964,22 @@ public class LakalaApiServiceImpl implements LakalaApiService {
// 上传到cos服务器
String cosFileUrl = ossService.uploadObject4OSS(file, cosFileName);
// 文件上传到拉卡拉服务器
JSONObject fileUploadResp = uploadFile(StringUtils.genLklOrderNo(8),
"SPLIT_COOPERATION_FILE",
"pdf",
UploadUtil.fileToBase64(file));
if (fileUploadResp == null || StrUtil.isBlank(fileUploadResp.getStr("attFileId"))) {
log.error("下载电子合同失败:未找到对应的入网电子合同记录");
}
String lklFilePath = fileUploadResp.getStr("attFileId");
// 删除临时文件
file.delete();
return cosFileUrl;
return Pair.of(cosFileUrl, lklFilePath);
}
/**
@ -1065,8 +1085,8 @@ public class LakalaApiServiceImpl implements LakalaApiService {
* @return
*/
@Transactional
@Override
public JSONObject applyLedgerMerNotify(HttpServletRequest request) {
// @Override
public JSONObject applyLedgerMerNotifyTemp(HttpServletRequest request) {
log.debug("商户分账申请业务异步回调通知开始");
// 验签
@ -1141,8 +1161,8 @@ public class LakalaApiServiceImpl implements LakalaApiService {
// return respData;
}
// 更新商家的hasApplySplit状态=1;has_esigned=1
lklLedgerMemberService.updateMulStatus(merCupNo, "", 1, 1, 0, 0);
// 更新商家的hasApplySplit状态=1;
shopMchEntryService.updateMulStatus("", merCupNo, 0, 1, 0, 0);
respData.put("code", "SUCCESS");
respData.put("message", "操作成功!");
@ -1154,6 +1174,102 @@ public class LakalaApiServiceImpl implements LakalaApiService {
throw new ApiException("商户分账申请业务回调:操作失败!");
}
/**
* 商户分账业务开通申请回调
* 参考https://o.lakala.com/#/home/document/detail?id=379
*
* @param request HTTP请求
* @return 处理结果JSON
*/
@Transactional
@Override
public JSONObject applyLedgerMerNotify(HttpServletRequest request) {
log.debug("商户分账申请业务异步回调通知开始");
// 验签
String authorization = request.getHeader("Authorization");
String requestBody = LakalaUtil.getBody(request);
log.debug("商户分账申请业务异步回调返回requestbody 参数:{}\n authorization参数{}\n", requestBody, authorization);
if (!LakalaUtil.verify(authorization, requestBody, lklNotifyCerPath)) {
log.error("商户分账申请业务回调:验签失败");
return JSONUtil.createObj().put("code", "FAIL").put("message", "验签失败!");
}
JSONObject paramsJSON = JSONUtil.parseObj(requestBody);
if (paramsJSON == null) {
log.error("商户分账申请业务回调:请求参数为空");
return JSONUtil.createObj().put("code", "FAIL").put("message", "请求参数为空");
}
String applyId = paramsJSON.getStr("applyId");
String auditStatus = paramsJSON.getStr("auditStatus");
String merCupNo = paramsJSON.getStr("merCupNo");
if (StrUtil.isBlank(applyId) || StrUtil.isBlank(auditStatus) || StrUtil.isBlank(merCupNo)) {
String errMsg = "商户分账申请业务回调缺少必要参数applyId/auditStatus/merCupNo";
log.error(errMsg + "applyId={}, auditStatus={}, merCupNo={}", applyId, auditStatus, merCupNo);
return JSONUtil.createObj().put("code", "FAIL").put("message", errMsg);
}
if (!auditStatus.equals("1")) {
log.warn("商户分账申请业务回调:审核未通过,状态={}", auditStatus);
return JSONUtil.createObj().put("code", "FAIL").put("message", "商户分账申请被驳回!");
}
LklLedgerMember lklLedgerMember = lklLedgerMemberService.getByApplyId(applyId, CommonConstant.Enable);
if (lklLedgerMember != null) {
log.debug("商户分账申请业务回调已处理成功applyId={}", applyId);
return JSONUtil.createObj().put("code", "SUCCESS").put("message", "商户分账申请已处理成功!");
}
String merInnerNo = paramsJSON.getStr("merInnerNo");
String entrustFileName = paramsJSON.getStr("entrustFileName");
String entrustFilePath = paramsJSON.getStr("entrustFilePath");
String auditStatusText = paramsJSON.getStr("auditStatusText");
String remark = paramsJSON.getStr("remark");
Boolean updateSuccess = lklLedgerMemberService.updateAuditResult(
applyId, merInnerNo, merCupNo, entrustFileName, entrustFilePath,
auditStatus, auditStatusText, remark
);
if (!updateSuccess) {
log.error("商户分账申请业务回调更新审核结果失败applyId={}", applyId);
return JSONUtil.createObj().put("code", "FAIL").put("message", "更新审核结果失败");
}
try {
JSONObject bindParamsJSON = new JSONObject()
.put("merInnerNo", merInnerNo)
.put("merCupNo", merCupNo);
Pair<Boolean, String> bindResult = innerApplyLedgerMerReceiverBind(bindParamsJSON);
if (!bindResult.getFirst()) {
String errMsg = "商户分账申请业务回调:预绑定接收方失败 - " + bindResult.getSecond();
log.error("商户{}预绑定接收方出错:{}", merCupNo, errMsg);
// 更新商户审批状态
if (lklLedgerMember != null) { // 防御性判断理论上此时应为null但保留安全检查
shopMchEntryService.updateMerchEntryApprovalByMchId(
lklLedgerMember.getMch_id(), "", CommonConstant.MCH_APPR_STA_NOPASS, errMsg
);
}
return JSONUtil.createObj().put("code", "FAIL").put("message", errMsg);
}
} catch (Exception e) {
log.error("商户分账申请业务回调:绑定接收方异常", e);
return JSONUtil.createObj().put("code", "FAIL").put("message", "绑定接收方失败");
}
// 更新商家分账申请状态为已申请hasApplySplit=1
shopMchEntryService.updateMulStatus("", merCupNo, 0, 1, 0, 0);
log.debug("商户分账申请业务回调处理成功applyId={}", applyId);
return JSONUtil.createObj().put("code", "SUCCESS").put("message", "操作成功!");
}
/**
* 分账接收方创建申请
* 参考https://o.lakala.com/#/home/document/detail?id=380
@ -1258,6 +1374,9 @@ public class LakalaApiServiceImpl implements LakalaApiService {
return CommonResult.failed(I18nUtil._("接收方创建成功,但更新本地数据失败!"));
}
// 更新商户分账多个状态 has_apply_receiver=1
shopMchEntryService.updateMulStatus(mchMobile, "", 0, 0, 1, 0);
return CommonResult.success(lklLedgerReceiver, "创建接收方成功!");
} catch (Exception e) {
log.error("接收方创建失败:{}", e);
@ -1269,131 +1388,63 @@ public class LakalaApiServiceImpl implements LakalaApiService {
* 商家与平台代理商分账关系绑定申请
* 参考https://o.lakala.com/#/home/document/detail?id=386
*
* @param paramsJSON
* @param paramsJSON {merCupNo}
* @return
*/
@Override
public CommonResult applyLedgerMerReceiverBind(JSONObject paramsJSON) {
// 检查分账方和接收方记录是否存在
if (lklLedgerMemberService.getByMerCupNo(paramsJSON.getStr("merCupNo")) == null
|| lklLedgerReceiverService.getByReceiverNo(paramsJSON.getStr("receiverNo")) == null) {
return CommonResult.failed(I18nUtil._("绑定方不存在!"));
Pair<Boolean, String> retPair = innerApplyLedgerMerReceiverBind(paramsJSON);
if (!retPair.getFirst()) {
return CommonResult.failed(retPair.getSecond());
}
LklLedgerMerReceiverBind lklLedgerMerReceiverBindOld = lklLedgerMerReceiverBindService.getByCondition(paramsJSON.getStr("merCupNo"), paramsJSON.getStr("receiverNo"));
if (lklLedgerMerReceiverBindOld != null) {
return CommonResult.success(lklLedgerMerReceiverBindOld, "分账绑定关系已存在!");
}
// 1. 配置初始化
initLKLSDK();
//2. 装配数据
V2MmsOpenApiLedgerApplyBindRequest req = new V2MmsOpenApiLedgerApplyBindRequest();
String orderNo = StringUtils.genLklOrderNo(8); // 8位随机数
req.setOrderNo(orderNo);
req.setOrgCode(orgCode);
req.setVersion("2.0");
req.setMerInnerNo(paramsJSON.getStr("merInnerNo"));
req.setMerCupNo(paramsJSON.getStr("merCupNo"));
req.setReceiverNo(paramsJSON.getStr("receiverNo"));
String fileName = paramsJSON.getStr("entrustFileName");
String splitEntrustFileBase64 = UploadUtil.fileUrlToBase64(paramsJSON.getStr("entrustFile")); // 这个是 url 地址不是 base64 字节码
req.setEntrustFileName(fileName);
// 正式上线的时候调整 api 地址
String domain = projectDomain;
if (isProdProject()) {
domain += "/api";
}
// 给拉卡拉通知的回调地址
String retUrl = domain + "/mobile/shop/lakala/ledger/applyLedgerMerReceiverBindNotify";
req.setRetUrl(retUrl);
// 文件上传到拉卡拉服务器
JSONObject fileUploadResp = uploadFile(orderNo,
"SPLIT_COOPERATION_FILE",
StringUtils.getFileExt(fileName),
splitEntrustFileBase64);
if (fileUploadResp == null || StrUtil.isBlank(fileUploadResp.getStr("attFileId"))) {
throw new ApiException(I18nUtil._("合作协议上传失败!"));
}
String entrustFilePath = fileUploadResp.getStr("attFileId");
req.setEntrustFilePath(entrustFilePath);
paramsJSON.set("orderNo", orderNo);
paramsJSON.set("version", "2.0");
paramsJSON.set("ret_url", retUrl);
paramsJSON.set("org_code", orgCode);
paramsJSON.set("entrust_file_name", fileName);
paramsJSON.set("entrust_file_path", entrustFilePath);
try {
//3. 发送请求
String responseStr = LKLSDK.httpPost(req);
JSONObject lakalaRespJSON = JSONUtil.parseObj(responseStr);
if (lakalaRespJSON == null) {
throw new ApiException(I18nUtil._(lakalaRespJSON.getStr("retMsg")));
}
if (!lakalaRespJSON.getStr("retCode").equals(lklSuccessCode)) {
throw new ApiException(I18nUtil._(lakalaRespJSON.getStr("retMsg")));
}
paramsJSON.set("apply_id", lakalaRespJSON.getByPath("respData.applyId"));
paramsJSON.set("remark", lakalaRespJSON.getStr("retMsg"));
// 新增数据
// JSON 对象的键名转换为下划线命名
LklLedgerMerReceiverBind lklLedgerMerReceiverBind = JSONUtil.toBean(StringUtils.convertCamelToSnake(paramsJSON.toString()), LklLedgerMerReceiverBind.class);
lklLedgerMerReceiverBindService.saveOrUpdateByMerCupNoReceiverNo(lklLedgerMerReceiverBind);
return CommonResult.success(lklLedgerMerReceiverBind, "提交成功,待审核中!");
} catch (SDKException e) {
log.error("分账绑定关系申请失败:", e);
throw new ApiException(I18nUtil._("分账绑定关系申请失败!"), e);
}
return CommonResult.success(null, "接收方绑定成功!");
}
/**
* 内部调用分账关系绑定申请
* 内部调用分账关系绑定申请废弃
* 参考https://o.lakala.com/#/home/document/detail?id=386
*
* @param paramsJSON
* @return
*/
public Pair<Boolean, String> innerApplyLedgerMerReceiverBind(JSONObject paramsJSON) {
// 检查分账方和接收方记录是否存在
if (lklLedgerMemberService.getByMerCupNo(paramsJSON.getStr("merCupNo")) == null) {
return Pair.of(false, I18nUtil._("绑定方不存在!"));
public Pair<Boolean, String> innerApplyLedgerMerReceiverBindTemp(JSONObject paramsJSON) {
if (paramsJSON == null) {
return Pair.of(false, I18nUtil._("绑定参数有误!"));
}
String merCupNo = paramsJSON.getStr("merCupNo");
if (StrUtil.isBlank(merCupNo)) {
return Pair.of(false, I18nUtil._("商户参数不能为空!"));
}
// 获取商家入驻记录
ShopMchEntry shopMchEntry = shopMchEntryService.getShopMerchEntryByMerCupNo(paramsJSON.getStr("merCupNo"));
ShopMchEntry shopMchEntry = shopMchEntryService.getShopMerchEntryByMerCupNo(merCupNo);
if (shopMchEntry == null) {
return Pair.of(false, I18nUtil._("商户入驻记录不存在!"));
}
// 检查分账方和接收方记录是否存在
LklLedgerMember lklLedgerMember = lklLedgerMemberService.getByMerCupNo(merCupNo);
if (lklLedgerMember == null) {
return Pair.of(false, I18nUtil._("商家尚未做分账业务申请!"));
}
// 代理商Id平台默认为0
Long platformId = shopMchEntry.getDistributor_id();
// Long platformId = shopMchEntry.getDistributor_id();
String entrustFileName = "小发同城合作协议书.pdf";
String entrustFileUrl = shopMchEntry.getContract_download_url();
// String entrustFileUrl = shopMchEntry.getContract_download_url();
int successCnt = 0;
// 获取平台接收方记录可能多个记录平台+代理商
List<LklLedgerReceiver> lklLedgerReceiverList = lklLedgerReceiverService.getByCondition("", shopMchEntry.getLogin_mobile());
if (CollectionUtils.isEmpty(lklLedgerReceiverList)) {
return Pair.of(false, I18nUtil._("分账接收方不存在"));
return Pair.of(false, I18nUtil._("先新增接收方信息!"));
}
for (LklLedgerReceiver lklLedgerReceiver : lklLedgerReceiverList) {
LklLedgerMerReceiverBind lklLedgerMerReceiverBindOld = lklLedgerMerReceiverBindService.getByCondition(paramsJSON.getStr("merCupNo"), paramsJSON.getStr("receiverNo"));
LklLedgerMerReceiverBind lklLedgerMerReceiverBindOld = lklLedgerMerReceiverBindService.getByCondition(merCupNo, lklLedgerReceiver.getReceiver_no());
if (lklLedgerMerReceiverBindOld != null) {
// return Pair.of(false, "分账绑定关系已存在!");
continue;
@ -1410,12 +1461,12 @@ public class LakalaApiServiceImpl implements LakalaApiService {
req.setOrgCode(orgCode);
req.setVersion("2.0");
req.setMerInnerNo(paramsJSON.getStr("merInnerNo"));
req.setMerCupNo(paramsJSON.getStr("merCupNo"));
req.setMerInnerNo(lklLedgerMember.getMer_inner_no());
req.setMerCupNo(merCupNo);
req.setReceiverNo(lklLedgerReceiver.getReceiver_no());
// String fileName = paramsJSON.getStr("entrustFileName");
String splitEntrustFileBase64 = UploadUtil.fileUrlToBase64(entrustFileUrl); // 这个是 url 地址不是 base64 字节码
//String splitEntrustFileBase64 = UploadUtil.fileUrlToBase64(entrustFileUrl); // 这个是 url 地址不是 base64 字节码
req.setEntrustFileName(entrustFileName);
String domain = projectDomain;
@ -1427,27 +1478,30 @@ public class LakalaApiServiceImpl implements LakalaApiService {
req.setRetUrl(retUrl);
// 文件上传到拉卡拉服务器
JSONObject fileUploadResp = uploadFile(orderNo,
"SPLIT_COOPERATION_FILE",
StringUtils.getFileExt(entrustFileName),
splitEntrustFileBase64);
if (fileUploadResp == null || StrUtil.isBlank(fileUploadResp.getStr("attFileId"))) {
// throw new ApiException(I18nUtil._("合作协议上传失败!"));
log.error(I18nUtil._("合作协议上传失败!"));
continue;
}
// JSONObject fileUploadResp = uploadFile(orderNo,
// "SPLIT_COOPERATION_FILE",
// StringUtils.getFileExt(entrustFileName),
// splitEntrustFileBase64);
// if (fileUploadResp == null || StrUtil.isBlank(fileUploadResp.getStr("attFileId"))) {
// // throw new ApiException(I18nUtil._("合作协议上传失败!"));
// log.error(I18nUtil._("合作协议上传失败!"));
// continue;
// }
String entrustFilePath = fileUploadResp.getStr("attFileId");
String entrustFilePath = shopMchEntry.getLkl_ec_file_path();//fileUploadResp.getStr("attFileId");
req.setEntrustFilePath(entrustFilePath);
paramsJSON.set("orderNo", orderNo);
paramsJSON.set("version", "2.0");
paramsJSON.set("ret_url", retUrl);
paramsJSON.set("org_code", orgCode);
paramsJSON.set("merInnerNo", lklLedgerMember.getMer_inner_no());
paramsJSON.set("entrust_file_name", entrustFileName);
paramsJSON.set("entrust_file_path", entrustFilePath);
try {
log.debug("绑定接收方参数:{}", JSONUtil.toJsonStr(req));
//3. 发送请求
String responseStr = LKLSDK.httpPost(req);
@ -1483,93 +1537,191 @@ public class LakalaApiServiceImpl implements LakalaApiService {
return Pair.of(true, "提交成功,待审核中!");
}
/**
* 内部调用分账关系绑定申请优化版
* 参考https://o.lakala.com/#/home/document/detail?id=386
*
* @param paramsJSON 包含绑定参数的JSON对象 {merCupNo}
* @return 操作结果及提示信息
*/
public Pair<Boolean, String> innerApplyLedgerMerReceiverBind(JSONObject paramsJSON) {
// 1. 参数校验提前失败
if (paramsJSON == null) {
return Pair.of(false, I18nUtil._("绑定参数为空"));
}
String merCupNo = paramsJSON.getStr("merCupNo");
if (StrUtil.isBlank(merCupNo)) {
return Pair.of(false, I18nUtil._("商户号merCupNo为空"));
}
// 2. 基础数据查询提前失败
ShopMchEntry shopMchEntry = shopMchEntryService.getShopMerchEntryByMerCupNo(merCupNo);
if (shopMchEntry == null) {
return Pair.of(false, I18nUtil._("商户入驻记录不存在"));
}
LklLedgerMember lklLedgerMember = lklLedgerMemberService.getByMerCupNo(merCupNo);
if (lklLedgerMember == null) {
return Pair.of(false, I18nUtil._("商家尚未做分账业务申请"));
}
List<LklLedgerReceiver> receiverList = lklLedgerReceiverService.getByCondition("", shopMchEntry.getLogin_mobile());
if (CollectionUtils.isEmpty(receiverList)) {
return Pair.of(false, I18nUtil._("接收方信息为空"));
}
// 3. 公共参数准备避免循环内重复计算
String domain = projectDomain;
if (isProdProject()) {
domain += "/api";
}
String retUrl = domain + "/mobile/shop/lakala/ledger/applyLedgerMerReceiverBindNotify";
String entrustFileName = "小发同城合作协议书.pdf";
String entrustFilePath = shopMchEntry.getLkl_ec_file_path();
int successCount = 0;
int totalCount = receiverList.size();
// 5. 初始化SDK建议移至类初始化或统一配置
initLKLSDK();
// 4. 循环处理接收方绑定
for (LklLedgerReceiver receiver : receiverList) {
try {
// 跳过已存在的绑定关系
if (lklLedgerMerReceiverBindService.getByCondition(merCupNo, receiver.getReceiver_no()) != null) {
log.warn("分账绑定关系已存在merCupNo={}, receiverNo={}", merCupNo, receiver.getReceiver_no());
continue;
}
// 6. 构建请求参数
String orderNo = StringUtils.genLklOrderNo(8);
V2MmsOpenApiLedgerApplyBindRequest request = new V2MmsOpenApiLedgerApplyBindRequest();
request.setOrderNo(orderNo);
request.setOrgCode(orgCode);
request.setVersion("2.0");
request.setMerInnerNo(lklLedgerMember.getMer_inner_no());
request.setMerCupNo(merCupNo);
request.setReceiverNo(receiver.getReceiver_no());
request.setEntrustFileName(entrustFileName);
request.setEntrustFilePath(entrustFilePath);
request.setRetUrl(retUrl);
// 7. 记录请求参数
log.debug("绑定接收方参数:{}", JSONUtil.toJsonStr(request));
// 8. 发送请求并处理响应
String responseStr = LKLSDK.httpPost(request);
JSONObject respJson = JSONUtil.parseObj(responseStr);
if (respJson == null || !lklSuccessCode.equals(respJson.getStr("retCode"))) {
log.error("拉卡拉响应失败:{}", respJson != null ? respJson.getStr("retMsg") : "无响应数据");
continue; // 单个失败不影响其他接收方处理
}
// 9. 更新参数并保存记录
paramsJSON.set("orderNo", orderNo);
paramsJSON.set("apply_id", respJson.getByPath("respData.applyId"));
paramsJSON.set("receiver_no", receiver.getReceiver_no());
paramsJSON.set("remark", respJson.getStr("retMsg"));
// 转换JSON键名格式并保存
String snakeJson = StringUtils.convertCamelToSnake(paramsJSON.toString());
LklLedgerMerReceiverBind bindRecord = JSONUtil.toBean(snakeJson, LklLedgerMerReceiverBind.class);
if (lklLedgerMerReceiverBindService.saveOrUpdateByMerCupNoReceiverNo(bindRecord)) {
successCount++;
} else {
log.warn("绑定记录保存失败merCupNo={}, receiverNo={}", merCupNo, receiver.getReceiver_no());
}
} catch (Exception e) {
log.error("处理分账绑定失败merCupNo={}, receiverNo={}", merCupNo, receiver.getReceiver_no(), e);
// 单个接收方处理失败继续处理其他接收方
}
}
// 10. 返回结果
if (successCount == 0) {
return Pair.of(false, "所有分账绑定均失败");
} else if (successCount < totalCount) {
return Pair.of(true, "部分提交成功(" + successCount + "/" + totalCount + "),待审核中");
} else {
return Pair.of(true, "全部提交成功,待审核中");
}
}
/**
* 分账关系绑定申请回调
* 参考https://o.lakala.com/#/home/document/detail?id=379
*
* @param request
* @return
* @param request HTTP请求对象
* @return 处理结果JSON
*/
@Transactional
@Override
public JSONObject applyLedgerMerReceiverBindNotify(HttpServletRequest request) {
log.debug("分账商家绑定接收方异步回调通知开始");
// 验签
// 1. 验签处理提前失败返回
String authorization = request.getHeader("Authorization");
String requestBody = LakalaUtil.getBody(request);
log.debug("分账商家绑定接收方异步回调返回request body参数{}", requestBody);
log.debug("分账商家绑定接收方异步回调返回authorization参数{}", authorization);
log.debug("回调参数requestBody={}\nauthorization={}", requestBody, authorization);
boolean checkSuccess = LakalaUtil.verify(authorization, requestBody, lklNotifyCerPath);
if (!checkSuccess) {
return JSONUtil.createObj().put("code", "FAIL").put("message", "验签失败!");
if (!LakalaUtil.verify(authorization, requestBody, lklNotifyCerPath)) {
log.error("验签失败,拒绝处理回调");
return JSONUtil.createObj().put("code", "FAIL").put("message", "验签失败");
}
// 2. 参数解析与校验
JSONObject paramsJSON = JSONUtil.parseObj(requestBody);
JSONObject respData = new JSONObject();
respData.put("code", "FAIL");
respData.put("message", "处理失败!");
if (paramsJSON != null) {
String merCupNo = paramsJSON.getStr("merCupNo");
String applyId = paramsJSON.getStr("applyId");
String auditStatus = paramsJSON.getStr("auditStatus");
if (StrUtil.isBlank(merCupNo) || StrUtil.isBlank(applyId) || StrUtil.isBlank(auditStatus)) {
String errMsg = "缺少返回必要参数";
log.error(errMsg + "applyId={}, applyId={}, auditStatus={}", merCupNo, applyId, auditStatus);
respData.put("message", errMsg);
return respData;
}
//auditStatus:1:通过2拒绝
if (!auditStatus.equals("1")) {
respData.put("message", "绑定接收方被驳回!");
return respData;
}
Boolean success = lklLedgerMerReceiverBindService.updateAuditResult(applyId,
paramsJSON.getStr("merInnerNo"),
merCupNo,
paramsJSON.getStr("receiverNo"),
paramsJSON.getStr("entrustFileName"),
paramsJSON.getStr("entrustFilePath"),
paramsJSON.getStr("auditStatus"),
paramsJSON.getStr("auditStatusText"),
paramsJSON.getStr("remark"));
if (success) {
// 更改商家的状态 has_bind_receiver 状态=1
lklLedgerMemberService.updateMulStatus(merCupNo, "", 0, 0, 0, 1);
// TODO 新建一个正式的已审核通过的店铺 新建之前判断是否已经新建过了
// 新建一个正式的已审核通过的店铺
ShopMchEntry shopEntry = shopMchEntryService.getShopMerchEntryByMerCupNo(merCupNo);
if (shopEntry != null && !CommonConstant.Enable.equals(shopEntry.getStore_status())) {
String mchMobile = shopEntry.getLogin_mobile();
Pair<Integer, String> retPair = shopStoreBaseService.merchEntryInfo2StoreInfo(mchMobile);
if (retPair.getFirst() > 0) {
// 2025-05-17暂停e签宝电子合同生成流程
// 更改合同记录表的店铺id
// esignContractService.updateContractStoreId(mchMobile, retPair.getFirst());
// 填充合同模版表的店铺Id
// esignContractFillingFileService.updateContractFillingStoreId(mchMobile, retPair.getFirst());
// 店铺创建状态已完成
shopMchEntryService.updateMerchEntryStoreStatus(mchMobile, CommonConstant.Enable);
} else {
throw new ApiException("商家绑定接收方:创建初始化店铺失败!");
}
}
respData.put("code", "SUCCESS");
respData.put("message", "操作成功!");
return respData;
}
if (paramsJSON == null || !paramsJSON.containsKey("respData")) {
log.error("回调参数缺失respData字段");
return JSONUtil.createObj().put("code", "FAIL").put("message", "参数格式错误");
}
throw new ApiException("商家绑定接收方:操作失败!");
JSONObject respData = paramsJSON.getJSONObject("respData");
String merCupNo = respData.getStr("merCupNo");
String applyId = respData.getStr("applyId");
String auditStatus = respData.getStr("auditStatus");
// throw new ServiceException("分账绑定关系申请回调失败!");
// return respData;
// 3. 核心参数校验
if (org.apache.commons.lang3.StringUtils.isAnyBlank(merCupNo, applyId, auditStatus)) {
String errorMsg = "关键参数缺失merCupNo={}, applyId={}, auditStatus={}";
log.error(errorMsg, merCupNo, applyId, auditStatus);
return JSONUtil.createObj().put("code", "FAIL").put("message", "接收方绑定参数有误");
}
// 4. 审核状态判断
if (!"1".equals(auditStatus)) {
log.warn("绑定审核未通过,状态:{}", auditStatus);
return JSONUtil.createObj().put("code", "FAIL").put("message", "绑定接收方被驳回");
}
// 5. 更新绑定记录状态
Boolean updateSuccess = lklLedgerMerReceiverBindService.updateAuditResult(
applyId,
respData.getStr("merInnerNo"),
merCupNo,
respData.getStr("receiverNo"),
respData.getStr("entrustFileName"),
respData.getStr("entrustFilePath"),
auditStatus,
respData.getStr("auditStatusText"),
respData.getStr("remark")
);
if (!updateSuccess) {
log.error("更新绑定记录失败applyId{}", applyId);
return JSONUtil.createObj().put("code", "FAIL").put("message", "更新绑定状态失败");
}
// 6. 更新商家绑定状态
shopMchEntryService.updateMulStatus("", merCupNo, 0, 0, 0, 1);
log.debug("分账商家绑定接收方回调处理完成merCupNo{}", merCupNo);
return JSONUtil.createObj().put("code", "SUCCESS").put("message", "操作成功");
}
/**

View File

@ -87,15 +87,31 @@ public class LklLedgerMerReceiverBindServiceImpl extends BaseServiceImpl<LklLedg
UpdateWrapper<LklLedgerMerReceiverBind> updateWrapper = new UpdateWrapper<>();
updateWrapper.eq("apply_id", applyId);
updateWrapper.set("receiver_no", receiverNo);
updateWrapper.set("mer_inner_no", merInnerNo);
updateWrapper.set("mer_cup_no", merCupNo);
updateWrapper.set("entrust_file_name", entrustFileName);
updateWrapper.set("entrust_file_path", entrustFilePath);
updateWrapper.set("audit_status", auditStatus);
updateWrapper.set("audit_status_text", auditStatusText);
updateWrapper.set("remark", remark);
if (StrUtil.isNotBlank(merInnerNo)) {
updateWrapper.set("mer_inner_no", merInnerNo);
}
if (StrUtil.isNotBlank(merCupNo)) {
updateWrapper.set("mer_cup_no", merCupNo);
}
if (StrUtil.isNotBlank(receiverNo)) {
updateWrapper.set("receiver_no", receiverNo);
}
if (StrUtil.isNotBlank(entrustFileName)) {
updateWrapper.set("entrust_file_name", entrustFileName);
}
if (StrUtil.isNotBlank(entrustFilePath)) {
updateWrapper.set("entrust_file_path", entrustFilePath);
}
if (StrUtil.isNotBlank(auditStatus)) {
updateWrapper.set("audit_status", auditStatus);
}
if (StrUtil.isNotBlank(auditStatusText)) {
updateWrapper.set("audit_status_text", auditStatusText);
}
if (StrUtil.isNotBlank(remark)) {
updateWrapper.set("remark", remark);
}
return update(updateWrapper);
}
}

View File

@ -15,6 +15,7 @@ import cn.hutool.json.JSONArray;
import cn.hutool.json.JSONObject;
import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import com.suisung.mall.common.api.CommonResult;
import com.suisung.mall.common.api.ResultCode;
import com.suisung.mall.common.constant.CommonConstant;
import com.suisung.mall.common.modules.esign.EsignPlatformInfo;
import com.suisung.mall.common.modules.lakala.LklLedgerReceiver;
@ -209,6 +210,7 @@ public class LklLedgerReceiverServiceImpl extends BaseServiceImpl<LklLedgerRecei
*/
@Override
public Boolean innerApplyLedgerReceiver(String merCupNo, Long platformId) {
// 接收方至少有一个平台方
JSONArray buildApplyLedgerReceiverReqParams = buildApplyLedgerReceiverReqParams(platformId);
if (buildApplyLedgerReceiverReqParams == null || buildApplyLedgerReceiverReqParams.isEmpty()) {
log.error("获取不到平台或代理商信息");
@ -219,7 +221,7 @@ public class LklLedgerReceiverServiceImpl extends BaseServiceImpl<LklLedgerRecei
for (JSONObject reqParam : buildApplyLedgerReceiverReqParams.jsonIter()) {
log.debug("申请分账接收方参数:{}", reqParam.toString());
CommonResult result = lakalaApiService.applyLedgerReceiver(reqParam);
if (result == null || result.getCode() != 200) {
if (result == null || result.getStatus() != ResultCode.SUCCESS.getStatus()) {
log.error("申请分账接收方失败:{}", result.getMsg());
continue;
}

View File

@ -28,6 +28,7 @@ import com.suisung.mall.shop.lakala.service.LklLedgerReceiverService;
import com.suisung.mall.shop.lakala.utils.LakalaUtil;
import com.suisung.mall.shop.page.service.impl.OssServiceImpl;
import com.suisung.mall.shop.store.service.ShopMchEntryService;
import com.suisung.mall.shop.store.service.ShopStoreBaseService;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;
@ -89,6 +90,10 @@ public class LklTkServiceImpl {
// @Resource
// private EsignContractFillingFileService esignContractFillingFileService;
@Lazy
@Resource
private ShopStoreBaseService shopStoreBaseService;
@Lazy
@Resource
private LakalaApiServiceImpl lakalaApiService;
@ -511,9 +516,9 @@ public class LklTkServiceImpl {
}
// 更改入驻记录的拉卡拉内部商户号和进件请求参数
String lklMerCupNo = respBody.getStr("merchantNo"); //拉卡拉内部商户号
String lklMerInnerNo = respBody.getStr("merchantNo"); //拉卡拉内部商户号
// 表中的内部外部商户号暂时都传同一个内部商户号以便异步通知更改记录
Boolean success = shopMchEntryService.updateMerchEntryLklMerCupNo(mchMobile, CommonConstant.Disable2, lklMerCupNo, lklMerCupNo, formData.toString(), respBody.toString());
Boolean success = shopMchEntryService.updateMerchEntryLklMerCupNo(mchMobile, CommonConstant.Disable2, lklMerInnerNo, lklMerInnerNo, formData.toString(), respBody.toString());
if (!success) {
return Pair.of(false, "提交进件成功,但更新商户号失败!");
}
@ -540,24 +545,24 @@ public class LklTkServiceImpl {
String requestBody = LakalaUtil.getBody(request);
logger.debug("拉卡拉进件异步通知返回参数:{}", requestBody);
if (StrUtil.isBlank(requestBody)) {
return new JSONObject().set("code", "FAIL").set("message", "返回参数为空");
return new JSONObject().set("code", "400").set("message", "返回参数为空");
}
JSONObject reqBodyJSON = JSONUtil.parseObj(requestBody);
if (reqBodyJSON.isEmpty() || reqBodyJSON.get("data") == null) {
return new JSONObject().set("code", "FAIL").set("message", "参数格式有误,无法解析");
return new JSONObject().set("code", "400").set("message", "参数格式有误,无法解析");
}
String srcData = reqBodyJSON.getStr("data");
if (StrUtil.isBlank(srcData)) {
return new JSONObject().set("code", "FAIL").set("message", "关键参数为空值");
return new JSONObject().set("code", "400").set("message", "关键参数为空值");
}
// 公钥解密出来的数据
String notifyPubKey = LakalaUtil.getResourceFile(notifyPubKeyPath, false, false);
String data = LakalaUtil.decryptNotifyData(notifyPubKey, srcData);
if (StrUtil.isBlank(data)) {
return new JSONObject().set("code", "FAIL").set("message", "密文解密出错!");
return new JSONObject().set("code", "400").set("message", "密文解密出错!");
}
logger.debug("拉卡拉进件异步通知data解密成功开始处理逻辑");
@ -580,18 +585,18 @@ public class LklTkServiceImpl {
String merInnerNo = dataJSON.getStr("customerNo"); //拉卡拉内部商户号
String termNos = dataJSON.getStr("termNos"); //拉卡拉分配的业务终端号
if (StrUtil.isBlank(merInnerNo) || StrUtil.isBlank(merCupNo)) {
return new JSONObject().set("code", "FAIL").set("message", "返回数据有误");
return new JSONObject().set("code", "500").set("message", "返回数据有误");
}
ShopMchEntry shopMchEntry = shopMchEntryService.getShopMerchEntryByMerInnerNo(merInnerNo);
if (ObjectUtil.isEmpty(shopMchEntry)) {
logger.error("拉卡拉进件异步通知:返回的内部商户号:{} 入驻信息不存在!", merInnerNo);
return new JSONObject().put("code", "FAIL").put("message", "内部商户号:" + merInnerNo + " 入驻信息不存在");
return new JSONObject().put("code", "500").put("message", "内部商户号:" + merInnerNo + " 入驻信息不存在");
}
Boolean success = shopMchEntryService.updateMerchEntryLklAuditStatusByLklMerCupNo(merInnerNo, merCupNo, termNos, CommonConstant.Enable, null, data);
if (!success) {
return new JSONObject().set("code", "FAIL").set("message", "更新商户号失败");
return new JSONObject().set("code", "500").set("message", "更新商户号失败");
// throw new ApiException("更新商户号失败");
}
@ -612,6 +617,25 @@ public class LklTkServiceImpl {
// 给商家申请分账功能使用务必检查是否申请过申请过忽略
if (success && StrUtil.isNotBlank(shopMchEntry.getContract_download_url())) {
// TODO 新建一个正式的已审核通过的店铺 新建之前判断是否已经新建过了
// 新建一个正式的已审核通过的店铺
// ShopMchEntry shopEntry = shopMchEntryService.getShopMerchEntryByMerCupNo(merCupNo);
// if (shopEntry != null && !CommonConstant.Enable.equals(shopEntry.getStore_status())) {
// String mchMobile = shopEntry.getLogin_mobile();
// Pair<Integer, String> retPair = shopStoreBaseService.merchEntryInfo2StoreInfo(mchMobile);
// if (retPair.getFirst() > 0) {
// // 2025-05-17暂停e签宝电子合同生成流程
// // 更改合同记录表的店铺id
// // esignContractService.updateContractStoreId(mchMobile, retPair.getFirst());
// // 填充合同模版表的店铺Id
// // esignContractFillingFileService.updateContractFillingStoreId(mchMobile, retPair.getFirst());
// // 店铺创建状态已完成
// shopMchEntryService.updateMerchEntryStoreStatus(mchMobile, CommonConstant.Enable);
// } else {
// throw new ApiException("商家进件:初始化店铺失败!");
// }
// }
// 1电子合同给商家申请分账功能使用务必检查是否申请过申请过忽略
// 下一步等待拉卡拉审核通过再绑定接收方和商家的关系
Pair<Boolean, String> retPair = lakalaApiService.innerApplyLedgerMer(merCupNo);
@ -620,22 +644,22 @@ public class LklTkServiceImpl {
Boolean genSuccess = lklLedgerReceiverService.innerApplyLedgerReceiver(merCupNo, shopMchEntry.getDistributor_id());
if (retPair.getFirst() && genSuccess) {
return new JSONObject().put("code", "SUCCESS").put("message", "处理成功");
return new JSONObject().put("code", "200").put("message", "处理成功");
}
if (!retPair.getFirst()) {
String message = "商家申请分账功能失败:" + retPair.getSecond();
logger.error(message);
return new JSONObject().set("code", "FAIL").set("message", message);
return new JSONObject().set("code", "500").set("message", message);
}
if (!genSuccess) {
logger.error("申请分账接收方失败");
return new JSONObject().set("code", "FAIL").set("message", "申请分账接收方失败");
return new JSONObject().set("code", "500").set("message", "申请分账接收方失败");
}
}
return new JSONObject().set("code", "FAIL").set("message", "进件回调处理失败");
return new JSONObject().set("code", "500").set("message", "进件回调处理失败");
}
/**

View File

@ -168,7 +168,7 @@ public interface ShopMchEntryService {
* @param lklTkRegNotifyReq lklTkRegResp 异步请求参数
* @return
*/
Boolean updateMerchEntryLklAuditStatusByLklMerCupNo(String lklMerCupNo, String lklInnerMerNo, String termNos, Integer lklAuditStatus, Integer approvalStatus, String lklTkRegNotifyReq);
Boolean updateMerchEntryLklAuditStatusByLklMerCupNo(String lklInnerMerNo, String lklMerCupNo, String termNos, Integer lklAuditStatus, Integer approvalStatus, String lklTkRegNotifyReq);
/**
@ -181,16 +181,17 @@ public interface ShopMchEntryService {
Boolean updateMerchEntryStoreId(Long id, Integer storeId);
/**
* 更新拉卡拉入网电子合同合同名称签署地址
* 更新拉卡拉入网电子合同合同名称签署COS地址, LKL文件相对路径
*
* @param id
* @param lklEcNo
* @param lklEcName
* @param lklEcResultUrl
* @param ecDownloadUrl
* @param ecLklFilePath
* @return
*/
Boolean updateMerchEntryLklEcNo(Long id, String lklEcNo, String lklEcName, String lklEcResultUrl, String ecDownloadUrl);
Boolean updateMerchEntryLklEcNo(Long id, String lklEcNo, String lklEcName, String lklEcResultUrl, String ecDownloadUrl, String ecLklFilePath);
/**
* 更新商家入驻申请的审批状态和审批备注
@ -203,4 +204,17 @@ public interface ShopMchEntryService {
*/
Boolean updateMerchEntryApprovalByMchId(Long mchId, String mchMobile, Integer approvalStatus, String approvalRemark);
/**
* 根据商户号或商家手机号修改商户分账多个状态
*
* @param mchMobile
* @param merCupNo
* @param hasEcSigned
* @param hasApplySplit
* @param hasApplyReceiver
* @param hasBindReceiver
* @return
*/
Boolean updateMulStatus(String mchMobile, String merCupNo, Integer hasEcSigned, Integer hasApplySplit, Integer hasApplyReceiver, Integer hasBindReceiver);
}

View File

@ -113,7 +113,7 @@ public class ShopMchEntryServiceImpl extends BaseServiceImpl<ShopMchEntryMapper,
}
/**
* 商家重新申请入驻商城平台
* 商家申请入驻商城平台
*
* @param shopMerchEntryJSON
* @return
@ -159,22 +159,10 @@ public class ShopMchEntryServiceImpl extends BaseServiceImpl<ShopMchEntryMapper,
}
// 校验身份证手机号格式
if (StrUtil.isNotBlank(record.getLegal_person_id_number()) && !StringUtils.validateIDCard(record.getLegal_person_id_number())) {
return CommonResult.failed("法人身份证号码有误!");
}
if (StrUtil.isNotBlank(record.getIndividual_id_number()) && !StringUtils.validateIDCard(record.getIndividual_id_number())) {
return CommonResult.failed("个人身份证号码有误!");
}
if (StrUtil.isNotBlank(record.getLogin_mobile()) && !PhoneNumberUtils.checkPhoneNumber(record.getLogin_mobile())) {
return CommonResult.failed("申请人手机号码有误!");
}
if (StrUtil.isNotBlank(record.getLegal_person_mobile()) && !PhoneNumberUtils.checkPhoneNumber(record.getLegal_person_mobile())) {
return CommonResult.failed("法人手机号码有误!");
}
// 检查企业法人或个人的营业执照或身份证
if (ObjectUtil.isNotEmpty(record.getEntity_type()) && record.getEntity_type().equals(2)) {
@ -183,6 +171,10 @@ public class ShopMchEntryServiceImpl extends BaseServiceImpl<ShopMchEntryMapper,
return CommonResult.failed("缺少个人身份证信息!");
}
if (StrUtil.isNotBlank(record.getIndividual_id_number()) && !StringUtils.validateIDCard(record.getIndividual_id_number())) {
return CommonResult.failed("个人身份证号码有误!");
}
} else {
// 企业
if (StrUtil.isBlank(record.getBiz_license_number()) || StrUtil.isBlank(record.getBiz_license_image())) {
@ -194,7 +186,15 @@ public class ShopMchEntryServiceImpl extends BaseServiceImpl<ShopMchEntryMapper,
}
if (StrUtil.isBlank(record.getLegal_person_id_images()) || StrUtil.isBlank(record.getLegal_person_id_images2())) {
return CommonResult.failed("缺少企业法人身份证信息!");
return CommonResult.failed("法人身份证信息!");
}
if (StrUtil.isNotBlank(record.getLegal_person_id_number()) && !StringUtils.validateIDCard(record.getLegal_person_id_number())) {
return CommonResult.failed("法人身份证号码有误!");
}
if (StrUtil.isNotBlank(record.getLegal_person_mobile()) && !PhoneNumberUtils.checkPhoneNumber(record.getLegal_person_mobile())) {
return CommonResult.failed("法人手机号码有误!");
}
}
@ -207,8 +207,11 @@ public class ShopMchEntryServiceImpl extends BaseServiceImpl<ShopMchEntryMapper,
return CommonResult.failed("银行卡号格式有误!");
}
if (StrUtil.isBlank(record.getOpenning_bank_code()) || StrUtil.isBlank(record.getClearing_bank_code())) {
return CommonResult.failed("请填写银行开户行号或结算行号!");
if (StrUtil.isBlank(record.getOpenning_bank_code())) {
return CommonResult.failed("请填写结算账户清算⾏号!");
} else {
// 对公对私结算账户清算号和结算账户开户号一定一致
record.setClearing_bank_code(record.getOpenning_bank_code());
}
if (StrUtil.isNotBlank(record.getStore_name()) && shopStoreBaseService.isExistsByStoreName(record.getStore_name())) {
@ -226,6 +229,9 @@ public class ShopMchEntryServiceImpl extends BaseServiceImpl<ShopMchEntryMapper,
record.setSales_info(record.getBiz_license_content());
}
// 重要备注自动计算商家分成比例
record.setSplit_ratio(shopBaseStoreCategoryService.getStoreCategoryRatio(record.getBiz_category()));
record.setCreated_by(userId);
record.setApproval_status(CommonConstant.MCH_APPR_STA_PADDING);
record.setApproval_remark("您的申请入驻平台材料已提交,待审中,请耐心等待!");
@ -287,30 +293,54 @@ public class ShopMchEntryServiceImpl extends BaseServiceImpl<ShopMchEntryMapper,
return CommonResult.failed("参数转换失败,请联系管理员!");
}
// 验证企业营业执照号码
if (StrUtil.isNotBlank(record.getBiz_license_number()) && !StringUtils.verifyBusinessLicense(record.getBiz_license_number())) {
return CommonResult.failed("营业执照号码有误!");
// 检查企业法人或个人的营业执照或身份证
if (ObjectUtil.isNotEmpty(record.getEntity_type()) && record.getEntity_type().equals(2)) {
// 个人
if (StrUtil.isBlank(record.getIndividual_id_number()) || StrUtil.isBlank(record.getIndividual_id_images()) || StrUtil.isBlank(record.getIndividual_id_images2())) {
return CommonResult.failed("缺少个人身份证信息!");
}
if (StrUtil.isNotBlank(record.getIndividual_id_number()) && !StringUtils.validateIDCard(record.getIndividual_id_number())) {
return CommonResult.failed("个人身份证号码有误!");
}
} else {
// 企业
if (StrUtil.isBlank(record.getBiz_license_number()) || StrUtil.isBlank(record.getBiz_license_image())) {
return CommonResult.failed("缺少企业营业执照信息!");
}
if (!StringUtils.verifyBusinessLicense(record.getBiz_license_number())) {
return CommonResult.failed("营业执照号码有误!");
}
if (StrUtil.isBlank(record.getLegal_person_id_images()) || StrUtil.isBlank(record.getLegal_person_id_images2())) {
return CommonResult.failed("法人身份证信息!");
}
if (StrUtil.isNotBlank(record.getLegal_person_id_number()) && !StringUtils.validateIDCard(record.getLegal_person_id_number())) {
return CommonResult.failed("法人身份证号码有误!");
}
if (StrUtil.isNotBlank(record.getLegal_person_mobile()) && !PhoneNumberUtils.checkPhoneNumber(record.getLegal_person_mobile())) {
return CommonResult.failed("法人手机号码有误!");
}
}
// 校验身份证手机号格式
if (StrUtil.isNotBlank(record.getLegal_person_id_number()) && !StringUtils.validateIDCard(record.getLegal_person_id_number())) {
return CommonResult.failed("法人身份证号码有误!");
}
if (StrUtil.isNotBlank(record.getIndividual_id_number()) && !StringUtils.validateIDCard(record.getIndividual_id_number())) {
return CommonResult.failed("个人身份证号码有误!");
}
if (StrUtil.isNotBlank(record.getLogin_mobile()) && !PhoneNumberUtils.checkPhoneNumber(record.getLogin_mobile())) {
return CommonResult.failed("申请人手机号码有误!");
}
if (StrUtil.isNotBlank(record.getLegal_person_mobile()) && !PhoneNumberUtils.checkPhoneNumber(record.getLegal_person_mobile())) {
return CommonResult.failed("法人手机号码有误!");
// 检查银行账号
if (StrUtil.isBlank(record.getBank_name()) || StrUtil.isBlank(record.getAccount_number()) || StrUtil.isBlank(record.getAccount_holder_name())) {
return CommonResult.failed("缺少银行账号信息!");
}
if (StrUtil.isNotBlank(record.getAccount_number()) && !BankUtil.isValidZHBankAccount(record.getAccount_number())) {
return CommonResult.failed("收款账号(银行卡号)格式有误!");
return CommonResult.failed("银行卡号格式有误!");
}
if (StrUtil.isBlank(record.getOpenning_bank_code())) {
return CommonResult.failed("请填写结算账户开户⾏号!");
} else {
// 对公对私结算账户清算号和结算账户开户号一定一致
record.setClearing_bank_code(record.getOpenning_bank_code());
}
if (StrUtil.isNotBlank(record.getStore_name()) && shopStoreBaseService.isExistsByStoreName(record.getStore_name())) {
@ -486,7 +516,7 @@ public class ShopMchEntryServiceImpl extends BaseServiceImpl<ShopMchEntryMapper,
ShopMchEntry record = getById(id);
if (record == null) {
return CommonResult.failed("未找到入驻记录");
return CommonResult.failed("商家入驻记录不存在");
}
// TODO 已经审核通过的不能再审核了
@ -809,8 +839,8 @@ public class ShopMchEntryServiceImpl extends BaseServiceImpl<ShopMchEntryMapper,
* @return
*/
@Override
public Boolean updateMerchEntryLklAuditStatusByLklMerCupNo(String lklMerCupNo, String lklInnerMerNo, String termNos, Integer lklAuditStatus, Integer approvalStatus, String lklTkRegNotifyReq) {
if (StrUtil.isBlank(lklMerCupNo)) {
public Boolean updateMerchEntryLklAuditStatusByLklMerCupNo(String lklInnerMerNo, String lklMerCupNo, String termNos, Integer lklAuditStatus, Integer approvalStatus, String lklTkRegNotifyReq) {
if (StrUtil.isBlank(lklInnerMerNo)) {
return false;
}
@ -836,7 +866,7 @@ public class ShopMchEntryServiceImpl extends BaseServiceImpl<ShopMchEntryMapper,
if (StrUtil.isNotBlank(lklTkRegNotifyReq)) {
updateWrapper.set("lkl_tk_reg_notify_req", lklTkRegNotifyReq);
}
return update(updateWrapper);
}
@ -865,10 +895,11 @@ public class ShopMchEntryServiceImpl extends BaseServiceImpl<ShopMchEntryMapper,
* @param lklEcNo
* @param lklEcResultUrl
* @param ecDownloadUrl
* @param ecLklFilePath
* @return
*/
@Override
public Boolean updateMerchEntryLklEcNo(Long id, String lklEcNo, String lklEcName, String lklEcResultUrl, String ecDownloadUrl) {
public Boolean updateMerchEntryLklEcNo(Long id, String lklEcNo, String lklEcName, String lklEcResultUrl, String ecDownloadUrl, String ecLklFilePath) {
if (ObjectUtil.isEmpty(id) && StrUtil.isBlank(lklEcNo)) {
return false;
}
@ -888,7 +919,12 @@ public class ShopMchEntryServiceImpl extends BaseServiceImpl<ShopMchEntryMapper,
if (StrUtil.isNotBlank(ecDownloadUrl)) {
updateWrapper.set("contract_download_url", ecDownloadUrl);
updateWrapper.set("signed_status", CommonConstant.CONTRACT_SIGN_STA_FINISH);
// updateWrapper.set("signed_status", CommonConstant.CONTRACT_SIGN_STA_FINISH);
updateWrapper.set("has_ec_signed", CommonConstant.Enable);
}
if (StrUtil.isNotBlank(ecLklFilePath)) {
updateWrapper.set("lkl_ec_file_path", ecLklFilePath);
}
return update(updateWrapper);
@ -906,7 +942,7 @@ public class ShopMchEntryServiceImpl extends BaseServiceImpl<ShopMchEntryMapper,
@Override
public Boolean updateMerchEntryApprovalByMchId(Long mchId, String mchMobile, Integer approvalStatus, String approvalRemark) {
if (ObjectUtil.isEmpty(mchId) && StrUtil.isBlank(mchMobile)) {
log.error("更新商家入驻申请审批状态和备注失败,缺少必要参数");
log.error("更新入驻审批状态和备注失败,缺少必要参数");
return false;
}
@ -928,4 +964,54 @@ public class ShopMchEntryServiceImpl extends BaseServiceImpl<ShopMchEntryMapper,
return update(updateWrapper);
}
/**
* 根据商户号或商家手机号修改商户分账多个状态
*
* @param mchMobile
* @param merCupNo
* @param hasEcSigned
* @param hasApplySplit
* @param hasApplyReceiver
* @param hasBindReceiver
* @return
*/
@Override
public Boolean updateMulStatus(String mchMobile, String merCupNo, Integer hasEcSigned,
Integer hasApplySplit, Integer hasApplyReceiver, Integer hasBindReceiver) {
// 参数校验
if (StrUtil.isAllBlank(merCupNo, mchMobile)) {
log.error("缺少merCupNo或mchMobile参数");
return false;
}
UpdateWrapper<ShopMchEntry> updateWrapper = new UpdateWrapper<>();
// 设置查询条件
Optional.ofNullable(mchMobile)
.filter(StrUtil::isNotBlank)
.ifPresent(mobile -> updateWrapper.eq("login_mobile", mobile));
Optional.ofNullable(merCupNo)
.filter(StrUtil::isNotBlank)
.ifPresent(cupNo -> updateWrapper.eq("lkl_mer_cup_no", cupNo));
// 流式构建更新字段
Map<String, Integer> fieldMap = new LinkedHashMap<>();
fieldMap.put("has_ec_signed", hasEcSigned);
fieldMap.put("has_apply_split", hasApplySplit);
fieldMap.put("has_apply_receiver", hasApplyReceiver);
fieldMap.put("has_bind_receiver", hasBindReceiver);
// 过滤有效字段并设置
fieldMap.entrySet().stream()
.filter(entry -> entry.getValue() != null && entry.getValue() > 0)
.forEach(entry -> updateWrapper.set(entry.getKey(), entry.getValue()));
try {
return update(updateWrapper);
} catch (Exception e) {
log.error("更新商家分账业务多个状态失败", e);
return false;
}
}
}