shop 项目增加拉卡拉的业务逻辑

This commit is contained in:
Jack 2025-04-24 17:38:12 +08:00
parent 39e52b54fd
commit c1896f3c39
29 changed files with 1768 additions and 18 deletions

View File

@ -9,6 +9,7 @@
package com.suisung.mall.admin.controller.mobile;
import cn.hutool.core.util.ObjectUtil;
import cn.hutool.json.JSONObject;
import com.suisung.mall.admin.service.AdminAppMarketUpdateService;
import com.suisung.mall.common.api.CommonResult;
@ -35,4 +36,14 @@ public class AppMarketUpdateController {
return adminAppMarketUpdateService.checkLatestVersion(paramsJSON.getInt("marketId"), paramsJSON.getStr("packageName"), paramsJSON.getInt("currVersionKey"));
}
@ApiOperation(value = "最新通用商家版App下载地址", notes = "最新通用商家版App下载地址")
@RequestMapping(value = "/last/apk", method = RequestMethod.POST)
public CommonResult lastCommonApp(@RequestBody(required = false) JSONObject paramsJSON) {
Integer marketId = 100;
if (paramsJSON != null && ObjectUtil.isNotEmpty(paramsJSON.getInt("marketId"))) {
marketId = paramsJSON.getInt("marketId");
}
return adminAppMarketUpdateService.lastAdminAppMarketUpdate(marketId);
}
}

View File

@ -24,6 +24,14 @@ public interface AdminAppMarketUpdateService {
*/
CommonResult checkLatestVersion(Integer marketId, String packageName, Integer currVersionKey);
/**
* 获取最新的(默认通用)商家版 App 下载地址
*
* @param marketId
* @return
*/
CommonResult lastAdminAppMarketUpdate(Integer marketId);
/**
* 后台管理员搜索列表

View File

@ -17,6 +17,7 @@ import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import com.suisung.mall.admin.mapper.AdminAppMarketUpdateMapper;
import com.suisung.mall.admin.service.AdminAppMarketUpdateService;
import com.suisung.mall.common.api.CommonResult;
import com.suisung.mall.common.constant.CommonConstant;
import com.suisung.mall.common.domain.UserDto;
import com.suisung.mall.common.modules.admin.AdminAppMarketUpdate;
import com.suisung.mall.common.pojo.dto.FileInfoDTO;
@ -77,6 +78,30 @@ public class AdminAppMarketUpdateServiceImpl extends BaseServiceImpl<AdminAppMar
return CommonResult.success(adminAppMarketUpdate);
}
/**
* 获取最新的(默认通用)商家版 App 下载地址
*
* @param marketId
* @return
*/
@Override
public CommonResult lastAdminAppMarketUpdate(Integer marketId) {
Integer defMarketId = 100;
if (ObjectUtil.isEmpty(marketId)) {
marketId = defMarketId;
}
QueryWrapper<AdminAppMarketUpdate> queryWrapper = new QueryWrapper<>();
queryWrapper.eq("market_id", marketId).eq("status", CommonConstant.Enable).orderByDesc("version_key");
AdminAppMarketUpdate adminAppMarketUpdate = findOne(queryWrapper);
if (adminAppMarketUpdate == null) {
return CommonResult.success(null, "没有找到最新版本");
}
return CommonResult.success(adminAppMarketUpdate);
}
/**
* 后台管理员搜索列表
*
@ -257,7 +282,7 @@ public class AdminAppMarketUpdateServiceImpl extends BaseServiceImpl<AdminAppMar
}
QueryWrapper<AdminAppMarketUpdate> queryWrapper = new QueryWrapper<>();
queryWrapper.eq("market_id", marketId)
queryWrapper.eq("market_id", marketId).eq("status", CommonConstant.Enable)
.eq("package_name", packageName).orderByDesc("version_key");
return findOne(queryWrapper);

View File

@ -69,29 +69,29 @@ secure:
- "/admin/account/account-user-base/register"
- "/admin/account/account-user-base/login"
- "/static/image/**"
- "/mobile/pay/index/notify_url"
#- "/mobile/pay/index/lkl_wxPay_notify_url" #拉卡拉微信支付回调
- "/mobile/pay/index/return_url"
- "/shop/static/**"
- "/mobile/shop/qrcode/getQrcode"
- "/admin/shop/shop-base-config/image"
- "/admin/account/open/**"
- "/admin/account/account-user-base/doLogin"
#- "/mobile/pay/index/lkl_wxPay_notify_url" #拉卡拉微信支付回调
- "/mobile/pay/index/notify_url"
- "/mobile/pay/index/return_url"
- "/admin/pay/pay-user-resource/userInfoImport"
- "/admin/pay/pay-card-history/payCardHistoryImport"
- "/admin/pay/payController/wxRefundNotify"
- "/mobile/shop/qrcode/getQrcode"
- "/admin/shop/shop-purchase-invoice/impPurchaseInvoiceTemp"
- "/admin/shop/shop-product-base/impProductTemp"
- "/admin/pay/payController/wxRefundNotify"
- "/admin/shop/shop-base-config/image"
- "/mobile/shop/sf-express/order/status/listening/**"
- "/admin/shop/open/**"
- "/admin/shop/esign/async/notify" #E签宝电子签章异步回调
- "/shop/sf-express/cancel-order/notify"
- "/shop/sf-express/rider-order-status/notify"
- "/shop/sf-express/order-complete/notify"
- "/shop/sync/third/**"
- "/mobile/shop/sf-express/order/status/listening/**"
- "/admin/shop/open/**"
- "/admin/account/open/**"
- "/esProduct/**"
- "/admin/oss/upload/**"
- "/mobile/**/**/test/case"
- "/admin/shop/esign/async/notify" #E签宝电子签章异步回调
universal:
urls:
- "/admin/account/account-user-base/info"

View File

@ -103,6 +103,10 @@ public class LakalaPayServiceImpl implements LakalaPayService {
return true;
}
protected boolean isProd() {
return "prod".equalsIgnoreCase(profile);
}
@Override
public cn.hutool.json.JSONObject transPreOrder(HttpServletRequest request, HttpServletResponse response, String orderId) {
// 1. 配置初始化
@ -419,19 +423,19 @@ public class LakalaPayServiceImpl implements LakalaPayService {
String fileName = paramsJSON.getStr("splitEntrustFileName");
req.setSplitEntrustFileName(fileName);
// 文件上传到拉卡拉服务器
// 分账结算委托书文件上传到拉卡拉服务器
JSONObject fileUploadResp = uploadFile(orderNo, "SPLIT_ENTRUST_FILE", StringUtils.getFileExt(fileName), paramsJSON.getStr("splitEntrustFile"));
if (fileUploadResp == null || StrUtil.isBlank(fileUploadResp.getStr("attFileId"))) {
throw new ApiException(I18nUtil._("分账结算委托书上传失败!"));
}
String splitEntrustFilePath = fileUploadResp.getStr("attFileId");
req.setSplitEntrustFilePath(splitEntrustFilePath);
// req.setSplitEntrustFilePath("G1/M00/06/64/CrFdEmBQc-aAGc_XAAAiIbS3WIE960.pdf");
req.setSplitEntrustFilePath(splitEntrustFilePath); //比如G1/M00/06/64/CrFdEmBQc-aAGc_XAAAiIbS3WIE960.pdf;
if (profile.equals("prod")) {
if (isProd()) {
projectDomain = projectDomain + "/api";
}
// 给拉卡拉通知的回调地址
String retUrl = projectDomain + "/mobile/pay/lakala/ledger/applyLedgerMerNotify";
req.setRetUrl(retUrl);
@ -503,6 +507,7 @@ public class LakalaPayServiceImpl implements LakalaPayService {
reqData.getStr("auditStatus"),
reqData.getStr("auditStatusText"),
reqData.getStr("remark"));
if (success) {
respData.put("retCode", "000000");
respData.put("retMsg", "操作成功!");

View File

@ -115,7 +115,7 @@ project:
domain: @project.domain@
#拉卡拉支付和分账
lakala:
# 服务地址
#服务地址
server_url: https://s2.lakala.com
#应用Id
app_id: OP10000439
@ -127,7 +127,7 @@ lakala:
api_pri_key_path: payKey/lakala/prod/api_private_key.pem
#拉卡拉平台证书
lkl_platform_cer_path: payKey/lakala/prod/lkl_platform.cer
# 机构代码
#机构代码
org_code: 980688
#商户号
merchant_no: 8226330599900LN

View File

@ -278,6 +278,22 @@
<version>9.4.1.jre8</version> <!-- 或者使用合适的版本 -->
</dependency>
<!--拉卡拉支付与分账 开始-->
<dependency>
<groupId>com.lkl.laop.sdk</groupId>
<artifactId>lkl-laop-java-sdk</artifactId>
<version>1.0.7</version>
<systemPath>${project.basedir}/src/main/resources/lib/lkl-java-sdk-1.0.7.jar</systemPath>
<scope>system</scope>
</dependency>
<dependency>
<groupId>com.github.javen205</groupId>
<artifactId>IJPay-Core</artifactId>
<version>2.8.0</version>
<scope>compile</scope>
</dependency>
<!--拉卡拉支付与分账 结束-->
</dependencies>
<profiles>

View File

@ -0,0 +1,69 @@
/*
* Copyright (c) 2025. Lorem ipsum dolor sit amet, consectetur adipiscing elit.
* Morbi non lorem porttitor neque feugiat blandit. Ut vitae ipsum eget quam lacinia accumsan.
* Etiam sed turpis ac ipsum condimentum fringilla. Maecenas magna.
* Proin dapibus sapien vel ante. Aliquam erat volutpat. Pellentesque sagittis ligula eget metus.
* Vestibulum commodo. Ut rhoncus gravida arcu.
*/
package com.suisung.mall.shop.lakala.controller;
import cn.hutool.json.JSONObject;
import com.suisung.mall.common.api.CommonResult;
import com.suisung.mall.common.service.impl.BaseControllerImpl;
import com.suisung.mall.shop.lakala.service.LakalaPayService;
import io.swagger.annotations.Api;
import io.swagger.annotations.ApiOperation;
import org.springframework.util.Base64Utils;
import org.springframework.web.bind.annotation.*;
import org.springframework.web.multipart.MultipartFile;
import javax.annotation.Resource;
import javax.servlet.http.HttpServletRequest;
import java.io.IOException;
@Api(tags = "拉卡拉相关接口 - 前端控制器")
@RestController
@RequestMapping("/mobile/shop/lakala")
public class LakalaController extends BaseControllerImpl {
@Resource
private LakalaPayService lakalaPayService;
@ApiOperation(value = "本地文件转base64", notes = "本地文件转base64")
@RequestMapping(value = "/file2base64", method = RequestMethod.POST)
public String file2Base64(@RequestParam("file") MultipartFile file) throws IOException {
String str = Base64Utils.encodeToString(file.getBytes());
return str;
}
@ApiOperation(value = "商户分账业务开通申请", notes = "商户分账业务开通申请")
@RequestMapping(value = "/ledger/applyLedgerMer", method = RequestMethod.POST)
public CommonResult ledgerApplyLedgerMer(@RequestBody JSONObject paramsJSON) {
return lakalaPayService.applyLedgerMer(paramsJSON);
}
@ApiOperation(value = "商户分账业务开通申请异步回调回调", notes = "商户分账业务开通申请异步回调回调")
@RequestMapping(value = "/ledger/applyLedgerMerNotify", method = RequestMethod.POST)
public JSONObject ledgerApplyLedgerMerNotify(HttpServletRequest request) {
return lakalaPayService.applyLedgerMerNotify(request);
}
@ApiOperation(value = "分账接收方创建申请", notes = "分账接收方创建申请")
@RequestMapping(value = "/ledger/applyLedgerReceiver", method = RequestMethod.POST)
public CommonResult applyLedgerReceiver(@RequestBody JSONObject paramsJSON) {
return lakalaPayService.applyLedgerReceiver(paramsJSON);
}
@ApiOperation(value = "分账关系绑定申请", notes = "分账关系绑定申请")
@RequestMapping(value = "/ledger/applyBind", method = RequestMethod.POST)
public CommonResult applyBind(@RequestBody JSONObject paramsJSON) {
return lakalaPayService.applyLedgerMerReceiverBind(paramsJSON);
}
@ApiOperation(value = "分账关系绑定申请异步回调通知", notes = "分账关系绑定申请异步回调通知")
@RequestMapping(value = "/ledger/applyBindNotify", method = RequestMethod.POST)
public JSONObject applyBindNotify(HttpServletRequest request) {
return lakalaPayService.applyLedgerMerReceiverBindNotify(request);
}
}

View File

@ -0,0 +1,18 @@
/*
* Copyright (c) 2025. Lorem ipsum dolor sit amet, consectetur adipiscing elit.
* Morbi non lorem porttitor neque feugiat blandit. Ut vitae ipsum eget quam lacinia accumsan.
* Etiam sed turpis ac ipsum condimentum fringilla. Maecenas magna.
* Proin dapibus sapien vel ante. Aliquam erat volutpat. Pellentesque sagittis ligula eget metus.
* Vestibulum commodo. Ut rhoncus gravida arcu.
*/
package com.suisung.mall.shop.lakala.mapper;
import com.baomidou.mybatisplus.core.mapper.BaseMapper;
import com.suisung.mall.common.modules.lakala.LklLedgerMember;
import org.springframework.stereotype.Repository;
@Repository
public interface LklLedgerMemberMapper extends BaseMapper<LklLedgerMember> {
}

View File

@ -0,0 +1,18 @@
/*
* Copyright (c) 2025. Lorem ipsum dolor sit amet, consectetur adipiscing elit.
* Morbi non lorem porttitor neque feugiat blandit. Ut vitae ipsum eget quam lacinia accumsan.
* Etiam sed turpis ac ipsum condimentum fringilla. Maecenas magna.
* Proin dapibus sapien vel ante. Aliquam erat volutpat. Pellentesque sagittis ligula eget metus.
* Vestibulum commodo. Ut rhoncus gravida arcu.
*/
package com.suisung.mall.shop.lakala.mapper;
import com.baomidou.mybatisplus.core.mapper.BaseMapper;
import com.suisung.mall.common.modules.lakala.LklLedgerMerReceiverBind;
import org.springframework.stereotype.Repository;
@Repository
public interface LklLedgerMerReceiverBindMapper extends BaseMapper<LklLedgerMerReceiverBind> {
}

View File

@ -0,0 +1,18 @@
/*
* Copyright (c) 2025. Lorem ipsum dolor sit amet, consectetur adipiscing elit.
* Morbi non lorem porttitor neque feugiat blandit. Ut vitae ipsum eget quam lacinia accumsan.
* Etiam sed turpis ac ipsum condimentum fringilla. Maecenas magna.
* Proin dapibus sapien vel ante. Aliquam erat volutpat. Pellentesque sagittis ligula eget metus.
* Vestibulum commodo. Ut rhoncus gravida arcu.
*/
package com.suisung.mall.shop.lakala.mapper;
import com.baomidou.mybatisplus.core.mapper.BaseMapper;
import com.suisung.mall.common.modules.lakala.LklLedgerReceiver;
import org.springframework.stereotype.Repository;
@Repository
public interface LklLedgerReceiverMapper extends BaseMapper<LklLedgerReceiver> {
}

View File

@ -0,0 +1,138 @@
/*
* Copyright (c) 2025. Lorem ipsum dolor sit amet, consectetur adipiscing elit.
* Morbi non lorem porttitor neque feugiat blandit. Ut vitae ipsum eget quam lacinia accumsan.
* Etiam sed turpis ac ipsum condimentum fringilla. Maecenas magna.
* Proin dapibus sapien vel ante. Aliquam erat volutpat. Pellentesque sagittis ligula eget metus.
* Vestibulum commodo. Ut rhoncus gravida arcu.
*/
package com.suisung.mall.shop.lakala.service;
import cn.hutool.json.JSONObject;
import com.suisung.mall.common.api.CommonResult;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
public interface LakalaPayService {
Boolean initLKLSDK();
JSONObject transPreOrder(HttpServletRequest request, HttpServletResponse response, String orderId);
/**
* 拉卡拉预下单
* 参考https://o.lakala.com/#/home/document/detail?id=110
*
* @param merchantNo 商户号
* @param termNo 终端号
* @param xcxAppId 小程序appid
* @param openId openid
* @param orderId 订单号
* @param subject 订单标题
* @param totalAmount 订单金额
* @param notifyURL 回调地址
* @param requestIP 请求ip
* @param remark 备注
* @return
*/
JSONObject transPreOrder(String merchantNo, String termNo, String xcxAppId, String openId, String orderId, String subject, String totalAmount, String notifyURL, String requestIP, String remark);
/**
* 聚合扫码-交易查询
*
* @param storeId
* @param orderId
* @return
*/
JSONObject tradeQuery(Integer storeId, String orderId);
/**
* 聚合扫码-退款交易
* 主被扫交易发生后因商家或消费者原因需要退款时商家调用此接口退还消费者支付款项
* 注意 1调用退款接口时请保证商户/账户余额大于等于本次退款金额
*
* @param storeId
* @param out_trade_no
* @param origin_trade_no // 原拉卡拉交易流水号
* @param refund_amount 单位分整数数字型字符
* @param refund_reason
* @param requestIP
* @return
*/
JSONObject refund(Integer storeId, String out_trade_no, String origin_trade_no, String refund_amount, String refund_reason, String requestIP);
/**
* 账户余额查询
* 参考https://o.lakala.com/#/home/document/detail?id=364
*
* @param orgNo bmcp机构号
* @param merchantNo 商户号 receiveNo 商户用户编号
* @param payNo 账号若该参数上送则payType将无效
* @param payType 账号类型01收款账户02付款账户03分账商户账户04分账接收方账户05充值代付账户06结算代付账户- 未上送则默认为01
* @return
*/
JSONObject ewalletBalanceQuery(String orgNo, String merchantNo, String payNo, String payType);
/**
* 文件上传
* 参考https://o.lakala.com/#/home/document/detail?id=90
*
* @param orderNo
* @param attType
* @param attExtName
* @param attContext
* @return
*/
JSONObject uploadFile(String orderNo, String attType, String attExtName, String attContext);
/**
* 商户分账业务开通申请
* 参考https://o.lakala.com/#/home/document/detail?id=379
*
* @param paramsJSON
* @return
*/
CommonResult applyLedgerMer(JSONObject paramsJSON);
/**
* 商户分账业务开通申请回调
* 参考https://o.lakala.com/#/home/document/detail?id=379
*
* @param request
* @return
*/
JSONObject applyLedgerMerNotify(HttpServletRequest request);
/**
* 分账接收方创建申请
* 参考https://o.lakala.com/#/home/document/detail?id=380
*
* @param paramsJSON
* @return
*/
CommonResult applyLedgerReceiver(JSONObject paramsJSON);
/**
* 分账关系绑定申请
* 参考https://o.lakala.com/#/home/document/detail?id=386
*
* @param paramsJSON
* @return
*/
CommonResult applyLedgerMerReceiverBind(JSONObject paramsJSON);
/**
* 分账关系绑定申请回调
* 参考https://o.lakala.com/#/home/document/detail?id=379
*
* @param request
* @return
*/
JSONObject applyLedgerMerReceiverBindNotify(HttpServletRequest request);
}

View File

@ -0,0 +1,39 @@
/*
* Copyright (c) 2025. Lorem ipsum dolor sit amet, consectetur adipiscing elit.
* Morbi non lorem porttitor neque feugiat blandit. Ut vitae ipsum eget quam lacinia accumsan.
* Etiam sed turpis ac ipsum condimentum fringilla. Maecenas magna.
* Proin dapibus sapien vel ante. Aliquam erat volutpat. Pellentesque sagittis ligula eget metus.
* Vestibulum commodo. Ut rhoncus gravida arcu.
*/
package com.suisung.mall.shop.lakala.service;
import com.suisung.mall.common.modules.lakala.LklLedgerMember;
import com.suisung.mall.core.web.service.IBaseService;
public interface LklLedgerMemberService extends IBaseService<LklLedgerMember> {
/**
* 根据银联商户号新增或修改记录
*
* @param record
* @return
*/
Boolean saveOrUpdateByMerCupNo(LklLedgerMember record);
/**
* 更新审核结果
*
* @param applyId
* @param merInnerNo
* @param merCupNo
* @param entrustFileName
* @param entrustFilePath
* @param auditStatus
* @param auditStatusText
* @param remark
* @return
*/
Boolean updateAuditResult(String applyId, String merInnerNo, String merCupNo, String entrustFileName, String entrustFilePath, String auditStatus, String auditStatusText, String remark);
}

View File

@ -0,0 +1,39 @@
/*
* Copyright (c) 2025. Lorem ipsum dolor sit amet, consectetur adipiscing elit.
* Morbi non lorem porttitor neque feugiat blandit. Ut vitae ipsum eget quam lacinia accumsan.
* Etiam sed turpis ac ipsum condimentum fringilla. Maecenas magna.
* Proin dapibus sapien vel ante. Aliquam erat volutpat. Pellentesque sagittis ligula eget metus.
* Vestibulum commodo. Ut rhoncus gravida arcu.
*/
package com.suisung.mall.shop.lakala.service;
import com.suisung.mall.common.modules.lakala.LklLedgerMerReceiverBind;
import com.suisung.mall.core.web.service.IBaseService;
public interface LklLedgerMerReceiverBindService extends IBaseService<LklLedgerMerReceiverBind> {
/**
* 根据接收方编号新增或更新记录
*
* @param record
* @return
*/
Boolean saveOrUpdateByMerCupNoReceiverNo(LklLedgerMerReceiverBind record);
/**
* 更新审核结果
*
* @param applyId
* @param merInnerNo
* @param merCupNo
* @param receiverNo
* @param entrustFileName
* @param entrustFilePath
* @param auditStatus
* @param auditStatusText
* @param remark
* @return
*/
Boolean updateAuditResult(String applyId, String merInnerNo, String merCupNo, String receiverNo, String entrustFileName, String entrustFilePath, String auditStatus, String auditStatusText, String remark);
}

View File

@ -0,0 +1,23 @@
/*
* Copyright (c) 2025. Lorem ipsum dolor sit amet, consectetur adipiscing elit.
* Morbi non lorem porttitor neque feugiat blandit. Ut vitae ipsum eget quam lacinia accumsan.
* Etiam sed turpis ac ipsum condimentum fringilla. Maecenas magna.
* Proin dapibus sapien vel ante. Aliquam erat volutpat. Pellentesque sagittis ligula eget metus.
* Vestibulum commodo. Ut rhoncus gravida arcu.
*/
package com.suisung.mall.shop.lakala.service;
import com.suisung.mall.common.modules.lakala.LklLedgerReceiver;
import com.suisung.mall.core.web.service.IBaseService;
public interface LklLedgerReceiverService extends IBaseService<LklLedgerReceiver> {
/**
* 根据接收方编号新增或更新记录
*
* @param record
* @return
*/
Boolean saveOrUpdateByReceiverNo(LklLedgerReceiver record);
}

View File

@ -0,0 +1,741 @@
/*
* Copyright (c) 2025. Lorem ipsum dolor sit amet, consectetur adipiscing elit.
* Morbi non lorem porttitor neque feugiat blandit. Ut vitae ipsum eget quam lacinia accumsan.
* Etiam sed turpis ac ipsum condimentum fringilla. Maecenas magna.
* Proin dapibus sapien vel ante. Aliquam erat volutpat. Pellentesque sagittis ligula eget metus.
* Vestibulum commodo. Ut rhoncus gravida arcu.
*/
package com.suisung.mall.shop.lakala.service.impl;
import cn.hutool.core.util.ObjectUtil;
import cn.hutool.core.util.StrUtil;
import cn.hutool.json.JSONObject;
import cn.hutool.json.JSONUtil;
import com.ijpay.core.kit.IpKit;
import com.lkl.laop.sdk.LKLSDK;
import com.lkl.laop.sdk.exception.SDKException;
import com.lkl.laop.sdk.request.*;
import com.lkl.laop.sdk.request.model.V3LabsTradeLocationInfo;
import com.lkl.laop.sdk.request.model.V3LabsTradePreorderWechatBus;
import com.suisung.mall.common.api.CommonResult;
import com.suisung.mall.common.exception.ApiException;
import com.suisung.mall.common.feignService.ShopService;
import com.suisung.mall.common.modules.lakala.LklLedgerMember;
import com.suisung.mall.common.modules.lakala.LklLedgerMerReceiverBind;
import com.suisung.mall.common.modules.lakala.LklLedgerReceiver;
import com.suisung.mall.common.modules.store.ShopStoreBase;
import com.suisung.mall.common.utils.I18nUtil;
import com.suisung.mall.common.utils.StringUtils;
import com.suisung.mall.shop.lakala.service.LakalaPayService;
import com.suisung.mall.shop.lakala.service.LklLedgerMemberService;
import com.suisung.mall.shop.lakala.service.LklLedgerMerReceiverBindService;
import com.suisung.mall.shop.lakala.service.LklLedgerReceiverService;
import com.suisung.mall.shop.lakala.utils.LakalaUtil;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.context.annotation.Lazy;
import org.springframework.stereotype.Service;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.math.BigDecimal;
import java.util.ArrayList;
import java.util.List;
@Slf4j
@Service
public class LakalaPayServiceImpl implements LakalaPayService {
private static final boolean init = false;
private static final String lklSuccessCode = "000000";
//### 可选的两个参数不同的店铺商家可以数据库里配置不同的商户号和终端号
@Value("${lakala.merchant_no}")
public String merchantNo; // 拉卡拉分配的商户号
@Value("${lakala.term_no}")
public String termNo; // 拉卡拉分配的终端号码
@Value("${lakala.server_url}")
private String serverUrl; //服务地址
@Value("${lakala.app_id}")
private String appId; // 拉卡拉appId
@Value("${lakala.serial_no}")
private String serialNo; // 你的证书序列号
@Value("${lakala.api_pri_key_path}")
private String priKeyPath; //商户私钥信息地址
@Value("${lakala.lkl_platform_cer_path}")
private String lklCerPath; //拉卡拉支付平台证书地址
@Value("${lakala.api_cert_path}")
private String apiCertPath;
@Value("${lakala.lkl_platform_cer_path}")
private String lklNotifyCerPath; //拉卡拉支付平台证书地址2(用于拉卡拉通知验签)
@Value("${lakala.org_code}")
private String orgCode;
@Value("${project.domain}")
private String projectDomain;
@Value("${spring.profiles.active}")
private String profile;
@Lazy
@Autowired
private ShopService shopService;
@Autowired
private LklLedgerMemberService lklLedgerMemberService;
@Autowired
private LklLedgerReceiverService lklLedgerReceiverService;
@Autowired
private LklLedgerMerReceiverBindService lklLedgerMerReceiverBindService;
/**
* 初始化 拉卡拉SDK
*
* @return
*/
@Override
public Boolean initLKLSDK() {
if (!init) {
return LakalaUtil.initLKLSDK(appId, serialNo, priKeyPath, lklCerPath, lklNotifyCerPath, serverUrl);
}
return true;
}
protected boolean isProd() {
return "prod".equalsIgnoreCase(profile);
}
@Override
public JSONObject transPreOrder(HttpServletRequest request, HttpServletResponse response, String orderId) {
// 1. 配置初始化
initLKLSDK();
//2. 装配数据
/*** 微信主扫场景示例 */
V3LabsTransPreorderRequest v3LabsTransPreorderWechatReq = new V3LabsTransPreorderRequest();
v3LabsTransPreorderWechatReq.setMerchantNo(merchantNo);
v3LabsTransPreorderWechatReq.setTermNo(termNo);
v3LabsTransPreorderWechatReq.setOutTradeNo(orderId);
v3LabsTransPreorderWechatReq.setSubject("油麦菜5斤装特惠");
v3LabsTransPreorderWechatReq.setAccountType("WECHAT");
v3LabsTransPreorderWechatReq.setTransType("51");
v3LabsTransPreorderWechatReq.setTotalAmount("1");
v3LabsTransPreorderWechatReq.setNotifyUrl("http://mall.gpxscs.cn/notify");
v3LabsTransPreorderWechatReq.setRemark("测试预下单备注");
//地址位置信息
V3LabsTradeLocationInfo v3LabsTradePreorderLocationInfo1 = new V3LabsTradeLocationInfo(IpKit.getRealIp(request));
v3LabsTransPreorderWechatReq.setLocationInfo(v3LabsTradePreorderLocationInfo1);
//微信主扫场景下acc_busi_fields域内容
V3LabsTradePreorderWechatBus wechatBus = new V3LabsTradePreorderWechatBus();
wechatBus.setSubAppid("wx5a73f844dac0da5c"); // 小程序appId
wechatBus.setUserId("oDVKR7T0qxg6O8tqIL9SgY6LXqqQ"); // 微信 openId
wechatBus.setDeviceInfo("WEB"); // 终端设备号(门店号或收银设备ID)注意PC网页或JSAPI支付请传WEB
v3LabsTransPreorderWechatReq.setAccBusiFields(wechatBus);
try {
//3. 发送请求
String responseStr = LKLSDK.httpPost(v3LabsTransPreorderWechatReq);
//4. 响应
return JSONUtil.parseObj(responseStr);
} catch (SDKException e) {
LakalaPayServiceImpl.log.error("transPreOrder error", e);
throw new ApiException(I18nUtil._("获取公众号绑定信息失败!"), e);
}
}
/**
* 拉卡拉预下单
* 参考https://o.lakala.com/#/home/document/detail?id=110
*
* @param merchantNo 商户号
* @param termNo 终端号
* @param xcxAppId 小程序appid
* @param openId openid
* @param orderId 订单号
* @param subject 订单标题
* @param totalAmount 订单金额
* @param notifyURL 回调地址
* @param requestIP 请求ip
* @param remark 备注
* @return
*/
@Override
public JSONObject transPreOrder(String merchantNo, String termNo, String xcxAppId, String openId, String orderId, String subject, String totalAmount, String notifyURL, String requestIP, String remark) {
// 1. 配置初始化
initLKLSDK();
if (StrUtil.isBlank(merchantNo)) {
merchantNo = this.merchantNo;
}
if (StrUtil.isBlank(termNo)) {
termNo = this.termNo;
}
//2. 装配数据
/*** 微信主扫场景示例 */
V3LabsTransPreorderRequest v3LabsTransPreorderWechatReq = new V3LabsTransPreorderRequest();
v3LabsTransPreorderWechatReq.setMerchantNo(merchantNo);
v3LabsTransPreorderWechatReq.setTermNo(termNo);
v3LabsTransPreorderWechatReq.setOutTradeNo(orderId);
v3LabsTransPreorderWechatReq.setSubject(subject);
//微信WECHAT 支付宝ALIPAY 银联UQRCODEPAY 翼支付: BESTPAY 苏宁易付宝: SUNING 拉卡拉支付账户LKLACC 网联小钱包NUCSPAY 京东钱包JD
v3LabsTransPreorderWechatReq.setAccountType("WECHAT");
// 41:NATIVEALIPAY云闪付支持京东白条分期51:JSAPI微信公众号支付支付宝服务窗支付银联JS支付翼支付JS支付拉卡拉钱包支付71:微信小程序支付 61:APP支付微信APP支付
v3LabsTransPreorderWechatReq.setTransType("51");
v3LabsTransPreorderWechatReq.setTotalAmount(totalAmount);
v3LabsTransPreorderWechatReq.setSettleType("1"); //0或者空常规结算方式如需接拉卡拉分账通需传1商户未开通分账之前切记不用上送此参数
v3LabsTransPreorderWechatReq.setNotifyUrl(notifyURL);
v3LabsTransPreorderWechatReq.setRemark(remark);
//地址位置信息
V3LabsTradeLocationInfo v3LabsTradePreorderLocationInfo = new V3LabsTradeLocationInfo(requestIP);
v3LabsTransPreorderWechatReq.setLocationInfo(v3LabsTradePreorderLocationInfo);
//微信主扫场景下 acc_busi_fields 域内容
V3LabsTradePreorderWechatBus wechatBus = new V3LabsTradePreorderWechatBus();
wechatBus.setSubAppid(xcxAppId); // 小程序appId
wechatBus.setUserId(openId); // 微信 openId
wechatBus.setDeviceInfo("WEB"); // 终端设备号(门店号或收银设备ID)注意PC网页或JSAPI支付请传WEB
v3LabsTransPreorderWechatReq.setAccBusiFields(wechatBus);
try {
log.info("拉卡拉预下单请求参数:{}", JSONUtil.toJsonStr(v3LabsTransPreorderWechatReq));
//3. 发送请求
String responseStr = LKLSDK.httpPost(v3LabsTransPreorderWechatReq);
log.info("拉卡拉预下单响应数据:{}", responseStr);
if (StrUtil.isBlank(responseStr)) {
return null;
}
JSONObject lakalaRespJSON = JSONUtil.parseObj(responseStr);
// || !lakalaRespJSON.getStr("code").equals("BBS00000")
//4. 响应
return lakalaRespJSON;
} catch (SDKException e) {
log.error("拉卡拉支付出错:", e);
throw new ApiException(I18nUtil._("支付失败!"), e);
}
}
/**
* 聚合扫码-交易查询
*
* @param storeId
* @param orderId
* @return
*/
@Override
public JSONObject tradeQuery(Integer storeId, String orderId) {
if (ObjectUtil.isEmpty(storeId) || StrUtil.isBlank(orderId)) {
return null;
}
// 1. 配置初始化
initLKLSDK();
// 这里获取店铺的拉卡拉的商户号和终端号码
ShopStoreBase shopStoreBase = shopService.getLklMerchantNoAndTermNo(storeId);
if (shopStoreBase == null || StrUtil.isBlank(shopStoreBase.getLkl_merchant_no()) || StrUtil.isBlank(shopStoreBase.getLkl_term_no())) {
log.error("缺少参数,拉卡拉交易查询失败!");
return null;
}
//2. 装配数据
V3LabsQueryTradequeryRequest v3LabsQueryTradequeryRequest = new V3LabsQueryTradequeryRequest();
v3LabsQueryTradequeryRequest.setMerchantNo(shopStoreBase.getLkl_merchant_no());
v3LabsQueryTradequeryRequest.setTermNo(shopStoreBase.getLkl_term_no());
v3LabsQueryTradequeryRequest.setOutTradeNo(orderId);
try {
//3. 发送请求
String responseStr = LKLSDK.httpPost(v3LabsQueryTradequeryRequest);
JSONObject lakalaRespJSON = JSONUtil.parseObj(responseStr);
// || !lakalaRespJSON.getStr("code").equals("BBS00000")
return lakalaRespJSON;
} catch (SDKException e) {
log.error("交易查询失败:", e);
throw new ApiException(I18nUtil._("交易查询失败!"), e);
}
}
/**
* 聚合扫码-退款交易
* 主被扫交易发生后因商家或消费者原因需要退款时商家调用此接口退还消费者支付款项
* 注意 1调用退款接口时请保证商户/账户余额大于等于本次退款金额
*
* @param storeId
* @param out_trade_no
* @param origin_trade_no // 原拉卡拉交易流水号
* @param refund_amount 单位分整数数字型字符
* @param refund_reason
* @param requestIP
* @return
*/
@Override
public JSONObject refund(Integer storeId, String out_trade_no, String origin_trade_no, String refund_amount, String refund_reason, String requestIP) {
if (ObjectUtil.isEmpty(storeId) || StrUtil.isBlank(out_trade_no) || StrUtil.isBlank(refund_amount) || StrUtil.isBlank(origin_trade_no) || StrUtil.isBlank(requestIP)) {
return null;
}
// 1. 配置初始化
initLKLSDK();
// 这里获取店铺的拉卡拉的商户号和终端号码
ShopStoreBase shopStoreBase = shopService.getLklMerchantNoAndTermNo(storeId);
if (shopStoreBase == null || StrUtil.isBlank(shopStoreBase.getLkl_merchant_no()) || StrUtil.isBlank(shopStoreBase.getLkl_term_no())) {
log.error("缺少参数,退款交易失败!");
return null;
}
//2. 装配数据
V3LabsRelationIdmrefundRequest req = new V3LabsRelationIdmrefundRequest();
req.setOutRefundOrderNo(out_trade_no);
req.setMerchantNo(shopStoreBase.getLkl_merchant_no());
req.setTermNo(shopStoreBase.getLkl_term_no());
req.setRefundAmount(refund_amount);
req.setRefundReason(refund_reason);
req.setOriginTradeNo(origin_trade_no);
V3LabsTradeLocationInfo v3LabsTradeLocationInfo = new V3LabsTradeLocationInfo(requestIP, null, "");
req.setLocationInfo(v3LabsTradeLocationInfo);
try {
//3. 发送请求
String responseStr = LKLSDK.httpPost(req);
JSONObject lakalaRespJSON = JSONUtil.parseObj(responseStr);
return lakalaRespJSON;
} catch (SDKException e) {
log.error("退款交易失败:", e);
throw new ApiException(I18nUtil._("退款交易!"), e);
}
}
/**
* 账户余额查询
* 参考https://o.lakala.com/#/home/document/detail?id=364
*
* @param orgNo bmcp机构号 测试 1
* @param merchantNo 商户号 receiveNo 商户用户编号
* @param payNo 账号若该参数上送则payType将无效
* @param payType 账号类型01收款账户02付款账户03分账商户账户04分账接收方账户05充值代付账户06结算代付账户- 未上送则默认为01
* @return
*/
@Override
public JSONObject ewalletBalanceQuery(String orgNo, String merchantNo, String payNo, String payType) {
if (StrUtil.isBlank(orgNo) || StrUtil.isBlank(merchantNo) || (StrUtil.isBlank(payNo) && StrUtil.isBlank(payType))) {
return null;
}
// 1. 配置初始化
initLKLSDK();
//2. 装配数据
V2LaepIndustryEwalletBalanceQueryRequest req = new V2LaepIndustryEwalletBalanceQueryRequest();
req.setOrgNo(orgNo);
req.setMerchantNo(merchantNo);
req.setPayNo(payNo);
req.setPayType(payType);
try {
//3. 发送请求
String responseStr = LKLSDK.httpPost(req);
JSONObject lakalaRespJSON = JSONUtil.parseObj(responseStr);
return lakalaRespJSON;
} catch (SDKException e) {
log.error("账户余额查询失败:", e);
throw new ApiException(I18nUtil._("账户余额查询!"), e);
}
}
/**
* 文件上传
* 参考https://o.lakala.com/#/home/document/detail?id=90
*
* @param orderNo
* @param attType
* @param attExtName
* @param attContext
* @return
*/
@Override
public JSONObject uploadFile(String orderNo, String attType, String attExtName, String attContext) {
// 1. 配置初始化
initLKLSDK();
//2. 装配数据
V2MmsOpenApiUploadFileRequest req = new V2MmsOpenApiUploadFileRequest();
req.setVersion("2.0");
req.setOrgCode(orgCode);
req.setOrderNo(orderNo);
req.setAttType(attType);
req.setAttExtName(attExtName);
req.setAttContext(attContext);
try {
//3. 发送请求
String responseStr = LKLSDK.httpPost(req);
JSONObject lakalaRespJSON = JSONUtil.parseObj(responseStr);
if (lakalaRespJSON == null || !lakalaRespJSON.getStr("retCode").equals(lklSuccessCode)) {
throw new ApiException(I18nUtil._(lakalaRespJSON.getStr("retMsg")));
}
return (JSONObject) lakalaRespJSON.get("respData");
} catch (SDKException e) {
log.error("文件上传失败:", e);
throw new ApiException(I18nUtil._("文件上传失败!"), e);
}
}
@Override
public CommonResult applyLedgerMer(JSONObject paramsJSON) {
// 1. 配置初始化
initLKLSDK();
//2. 装配数据
V2MmsOpenApiLedgerApplyLedgerMerRequest req = new V2MmsOpenApiLedgerApplyLedgerMerRequest();
req.setVersion("2.0");
req.setOrderNo(StringUtils.genLklOrderNo(8));// 14位年月日时24小时制分秒+8位的随机数
req.setOrgCode(orgCode);
req.setMerInnerNo(paramsJSON.getStr("merInnerNo"));
req.setMerCupNo(paramsJSON.getStr("merCupNo"));
req.setContactMobile(paramsJSON.getStr("contactMobile"));
req.setSplitLowestRatio(new BigDecimal(paramsJSON.getStr("splitLowestRatio")));
String fileName = paramsJSON.getStr("splitEntrustFileName");
req.setSplitEntrustFileName(fileName);
// 分账结算委托书文件上传到拉卡拉服务器
JSONObject fileUploadResp = uploadFile(req.getOrderNo(), "SPLIT_ENTRUST_FILE", StringUtils.getFileExt(fileName), paramsJSON.getStr("splitEntrustFile"));
if (fileUploadResp == null || StrUtil.isBlank(fileUploadResp.getStr("attFileId"))) {
throw new ApiException(I18nUtil._("分账结算委托书上传失败!"));
}
String splitEntrustFilePath = fileUploadResp.getStr("attFileId");
req.setSplitEntrustFilePath(splitEntrustFilePath); //比如G1/M00/06/64/CrFdEmBQc-aAGc_XAAAiIbS3WIE960.pdf;
if (isProd()) {
projectDomain = projectDomain + "/api";
}
// 给拉卡拉通知的回调地址
String retUrl = projectDomain + "/mobile/shop/lakala/ledger/applyLedgerMerNotify";
req.setRetUrl(retUrl);
paramsJSON.set("orderNo", req.getOrderNo());
paramsJSON.set("version", "2.0");
paramsJSON.set("ret_url", retUrl);
paramsJSON.set("org_code", orgCode);
paramsJSON.set("split_entrust_file_path", splitEntrustFilePath);
try {
//3. 发送请求
String responseStr = LKLSDK.httpPost(req);
JSONObject lakalaRespJSON = JSONUtil.parseObj(responseStr);
if (lakalaRespJSON == null || !lakalaRespJSON.getStr("retCode").equals(lklSuccessCode)) {
throw new ApiException(I18nUtil._(lakalaRespJSON.getStr("retMsg")));
// responseStr="{'retCode':'000000','retMsg':'申请已受理,请等待审核结果','respData':{'version':'1.0','orderNo':'KFPT20230223181025407788734','orgCode':'1','applyId':681201215598657536}}";
// lakalaRespJSON = JSONUtil.parseObj(responseStr);
}
paramsJSON.set("apply_id", lakalaRespJSON.getByPath("respData.applyId"));
paramsJSON.set("remark", lakalaRespJSON.getStr("retMsg"));
paramsJSON.set("audit_status_text", paramsJSON.get("remark"));
// 新增数据
// JSON 对象的键名转换为下划线命名
LklLedgerMember lklLedgerMember = JSONUtil.toBean(StringUtils.convertCamelToSnake(paramsJSON.toString()), LklLedgerMember.class);
lklLedgerMemberService.saveOrUpdateByMerCupNo(lklLedgerMember);
return CommonResult.success(null, "提交成功,待审核中!");
} catch (SDKException e) {
log.error("分账申请失败:", e);
throw new ApiException(I18nUtil._("申请失败!"), e);
}
}
/**
* 商户分账业务开通申请回调
* 参考https://o.lakala.com/#/home/document/detail?id=379
*
* @param request
* @return
*/
@Override
public JSONObject applyLedgerMerNotify(HttpServletRequest request) {
log.info("商户分账申请业务回调收到通知");
// 验签
String authorization = request.getHeader("Authorization");
String requestBody = LakalaUtil.getBody(request);
log.info("商户分账申请业务回调返回参数:{}", requestBody);
boolean checkSuccess = LakalaUtil.verify(authorization, requestBody, lklNotifyCerPath);
if (!checkSuccess) {
log.info("商户分账申请业务回调:验签失败");
return JSONUtil.createObj().set("retCode", "OP90002").set("retMsg", "验签失败!");
}
JSONObject paramsJSON = JSONUtil.parseObj(requestBody);
JSONObject respData = new JSONObject();
respData.put("retCode", "OP90003");
respData.put("retMsg", "响应处理失败!");
if (paramsJSON != null) {
JSONObject reqData = (JSONObject) paramsJSON.get("respData");
if (ObjectUtil.isEmpty(reqData)) {
return respData;
}
// 更改本地分账记录状态数据
Boolean success = lklLedgerMemberService.updateAuditResult(reqData.getStr("applyId"),
reqData.getStr("merInnerNo"),
reqData.getStr("merCupNo"),
reqData.getStr("entrustFileName"),
reqData.getStr("entrustFilePath"),
reqData.getStr("auditStatus"),
reqData.getStr("auditStatusText"),
reqData.getStr("remark"));
if (success) {
respData.put("retCode", lklSuccessCode);
respData.put("retMsg", "操作成功!");
log.info("商户分账申请业务回调:处理成功");
}
}
return respData;
}
/**
* 分账接收方创建申请
* 参考https://o.lakala.com/#/home/document/detail?id=380
*
* @param paramsJSON
* @return
*/
@Override
public CommonResult applyLedgerReceiver(JSONObject paramsJSON) {
// 1. 配置初始化
initLKLSDK();
//2. 装配数据
V2MmsOpenApiLedgerApplyLedgerReceiverRequest req = new V2MmsOpenApiLedgerApplyLedgerReceiverRequest();
String orderNo = StringUtils.genLklOrderNo(8); // 8位随机数
req.setOrderNo(orderNo);
req.setOrgCode(orgCode);
req.setVersion("2.0");
req.setReceiverName(paramsJSON.getStr("receiverName"));
req.setContactMobile(paramsJSON.getStr("contactMobile"));
req.setLicenseNo(paramsJSON.getStr("licenseNo"));
req.setLicenseName(paramsJSON.getStr("licenseName"));
req.setLegalPersonName(paramsJSON.getStr("legalPersonName"));
req.setLegalPersonCertificateType(paramsJSON.getStr("legalPersonCertificateType"));
req.setLegalPersonCertificateNo(paramsJSON.getStr("legalPersonCertificateNo"));
req.setAcctNo(paramsJSON.getStr("acctNo"));
req.setAcctName(paramsJSON.getStr("acctName"));
req.setAcctTypeCode(paramsJSON.getStr("acctTypeCode"));
req.setAcctCertificateType(paramsJSON.getStr("acctCertificateType"));
req.setAcctCertificateNo(paramsJSON.getStr("acctCertificateNo"));
req.setAcctOpenBankCode(paramsJSON.getStr("acctOpenBankCode"));
req.setAcctOpenBankName(paramsJSON.getStr("acctOpenBankName"));
req.setAcctClearBankCode(paramsJSON.getStr("acctClearBankCode"));
if (paramsJSON.getJSONArray("attachList") != null && paramsJSON.getJSONArray("attachList").size() > 0) {
List<V2MmsOpenApiLedgerApplyLedgerReceiverRequest.AttachInfo> attachList = new ArrayList<>();
V2MmsOpenApiLedgerApplyLedgerReceiverRequest.AttachInfo attachInfo = new V2MmsOpenApiLedgerApplyLedgerReceiverRequest.AttachInfo();
for (JSONObject attachJSON : paramsJSON.getJSONArray("attachList").jsonIter()) {
String fileName = attachJSON.getStr("attachName");
String attachType = attachJSON.getStr("attachType");
String fileBase64 = attachJSON.getStr("attachStoreFile");
attachInfo.setAttachName(fileName);
attachInfo.setAttachType(attachType);
JSONObject fileUploadResp = uploadFile(StringUtils.genLklOrderNo(8), attachType,
StringUtils.getFileExt(fileName), fileBase64);
if (fileUploadResp == null || StrUtil.isBlank(fileUploadResp.getStr("attFileId"))) {
throw new ApiException(I18nUtil._("附件上传失败!"));
}
attachInfo.setAttachStorePath(fileUploadResp.getStr("attFileId"));
attachList.add(attachInfo);
}
req.setAttachList(attachList);
paramsJSON.set("attach_list", JSONUtil.toJsonStr(attachList));
}
paramsJSON.set("orderNo", orderNo);
paramsJSON.set("version", "2.0");
paramsJSON.set("org_code", orgCode);
try {
//3. 发送请求申请创建分账接收方
String responseStr = LKLSDK.httpPost(req);
JSONObject lakalaRespJSON = JSONUtil.parseObj(responseStr);
if (lakalaRespJSON == null || !lakalaRespJSON.getStr("retCode").equals(lklSuccessCode)) {
throw new ApiException(I18nUtil._(lakalaRespJSON.getStr("retMsg")));
}
paramsJSON.set("receiver_no", lakalaRespJSON.getByPath("respData.receiverNo"));
paramsJSON.set("org_id", lakalaRespJSON.getByPath("respData.orgId"));
paramsJSON.set("org_name", lakalaRespJSON.getByPath("respData.orgName"));
// 新增数据
// JSON 对象的键名转换为下划线命名
LklLedgerReceiver lklLedgerReceiver = JSONUtil.toBean(StringUtils.convertCamelToSnake(paramsJSON.toString()), LklLedgerReceiver.class);
// 新增或修改本地数据
lklLedgerReceiverService.saveOrUpdateByReceiverNo(lklLedgerReceiver);
return CommonResult.success(null, "接收方创建成功!");
} catch (SDKException e) {
log.error("接收方创建失败:", e);
throw new ApiException(I18nUtil._("接收方创建失败!"), e);
}
}
/**
* 分账关系绑定申请
* 参考https://o.lakala.com/#/home/document/detail?id=386
*
* @param paramsJSON
* @return
*/
@Override
public CommonResult applyLedgerMerReceiverBind(JSONObject paramsJSON) {
// 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 = paramsJSON.getStr("entrustFile");
req.setEntrustFileName(fileName);
String retUrl = projectDomain + "/mobile/pay/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 || !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(null, "提交成功,待审核中!");
} catch (SDKException e) {
log.error("分账绑定关系申请失败:", e);
throw new ApiException(I18nUtil._("分账绑定关系申请失败!"), e);
}
}
/**
* 分账关系绑定申请回调
* 参考https://o.lakala.com/#/home/document/detail?id=379
*
* @param request
* @return
*/
@Override
public JSONObject applyLedgerMerReceiverBindNotify(HttpServletRequest request) {
// 验签
String authorization = request.getHeader("Authorization");
String requestBody = LakalaUtil.getBody(request);
boolean checkSuccess = LakalaUtil.verify(authorization, requestBody, lklNotifyCerPath);
if (!checkSuccess) {
return JSONUtil.createObj().set("retCode", "OP90002").set("retMsg", "验签失败!");
}
// String requestBody = LakalaUtil.getBody(request);
JSONObject paramsJSON = JSONUtil.parseObj(requestBody);
JSONObject respData = new JSONObject();
respData.put("retCode", "OP90003");
respData.put("retMsg", "响应处理失败!");
if (paramsJSON != null && paramsJSON.get("respData") != null) {
JSONObject reqData = (JSONObject) paramsJSON.get("respData");
Boolean success = lklLedgerMerReceiverBindService.updateAuditResult(reqData.getStr("applyId"),
reqData.getStr("merInnerNo"),
reqData.getStr("merCupNo"),
reqData.getStr("receiverNo"),
reqData.getStr("entrustFileName"),
reqData.getStr("entrustFilePath"),
reqData.getStr("auditStatus"),
reqData.getStr("auditStatusText"),
reqData.getStr("remark"));
if (success) {
respData.put("retCode", lklSuccessCode);
respData.put("retMsg", "操作成功!");
}
}
return respData;
}
}

View File

@ -0,0 +1,87 @@
/*
* Copyright (c) 2025. Lorem ipsum dolor sit amet, consectetur adipiscing elit.
* Morbi non lorem porttitor neque feugiat blandit. Ut vitae ipsum eget quam lacinia accumsan.
* Etiam sed turpis ac ipsum condimentum fringilla. Maecenas magna.
* Proin dapibus sapien vel ante. Aliquam erat volutpat. Pellentesque sagittis ligula eget metus.
* Vestibulum commodo. Ut rhoncus gravida arcu.
*/
package com.suisung.mall.shop.lakala.service.impl;
import cn.hutool.core.collection.CollectionUtil;
import cn.hutool.core.util.StrUtil;
import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import com.baomidou.mybatisplus.core.conditions.update.UpdateWrapper;
import com.suisung.mall.common.modules.lakala.LklLedgerMember;
import com.suisung.mall.core.web.service.impl.BaseServiceImpl;
import com.suisung.mall.shop.lakala.mapper.LklLedgerMemberMapper;
import com.suisung.mall.shop.lakala.service.LklLedgerMemberService;
import lombok.extern.slf4j.Slf4j;
import org.springframework.stereotype.Service;
import java.util.List;
@Slf4j
@Service
public class LklLedgerMemberServiceImpl extends BaseServiceImpl<LklLedgerMemberMapper, LklLedgerMember> implements LklLedgerMemberService {
/**
* 根据银联商户号新增或修改记录
*
* @param record
* @return
*/
@Override
public Boolean saveOrUpdateByMerCupNo(LklLedgerMember record) {
if (record == null || StrUtil.isBlank(record.getMer_cup_no())) {
return false;
}
QueryWrapper<LklLedgerMember> queryWrapper = new QueryWrapper<>();
queryWrapper.eq("mer_cup_no", record.getMer_cup_no());
List<LklLedgerMember> existsRecordList = list(queryWrapper);
if (!CollectionUtil.isEmpty(existsRecordList)
&& existsRecordList.get(0) != null
&& existsRecordList.get(0).getId() > 0) {
// update
record.setId(existsRecordList.get(0).getId());
return updateById(record);
}
return add(record);
}
/**
* 更新审核结果
*
* @param applyId
* @param merInnerNo
* @param merCupNo
* @param entrustFileName
* @param entrustFilePath
* @param auditStatus
* @param auditStatusText
* @param remark
* @return
*/
@Override
public Boolean updateAuditResult(String applyId, String merInnerNo, String merCupNo, String entrustFileName, String entrustFilePath, String auditStatus, String auditStatusText, String remark) {
if (StrUtil.isBlank(applyId) || StrUtil.isBlank(merCupNo) || StrUtil.isBlank(auditStatus)) {
log.error("缺少参数applyId={}, merCupNo={}, auditStatus={}", applyId, merCupNo, auditStatus);
return false;
}
UpdateWrapper<LklLedgerMember> updateWrapper = new UpdateWrapper<>();
updateWrapper.eq("apply_id", applyId);
updateWrapper.set("mer_inner_no", merInnerNo);
updateWrapper.set("mer_cup_no", merCupNo);
updateWrapper.set("split_entrust_file_name", entrustFileName);
updateWrapper.set("split_entrust_file_path", entrustFilePath);
updateWrapper.set("audit_status", auditStatus);
updateWrapper.set("audit_status_text", auditStatusText);
updateWrapper.set("remark", remark);
return update(updateWrapper);
}
}

View File

@ -0,0 +1,85 @@
/*
* Copyright (c) 2025. Lorem ipsum dolor sit amet, consectetur adipiscing elit.
* Morbi non lorem porttitor neque feugiat blandit. Ut vitae ipsum eget quam lacinia accumsan.
* Etiam sed turpis ac ipsum condimentum fringilla. Maecenas magna.
* Proin dapibus sapien vel ante. Aliquam erat volutpat. Pellentesque sagittis ligula eget metus.
* Vestibulum commodo. Ut rhoncus gravida arcu.
*/
package com.suisung.mall.shop.lakala.service.impl;
import cn.hutool.core.collection.CollectionUtil;
import cn.hutool.core.util.StrUtil;
import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import com.baomidou.mybatisplus.core.conditions.update.UpdateWrapper;
import com.suisung.mall.common.modules.lakala.LklLedgerMerReceiverBind;
import com.suisung.mall.core.web.service.impl.BaseServiceImpl;
import com.suisung.mall.shop.lakala.mapper.LklLedgerMerReceiverBindMapper;
import com.suisung.mall.shop.lakala.service.LklLedgerMerReceiverBindService;
import org.springframework.stereotype.Service;
import java.util.List;
@Service
public class LklLedgerMerReceiverBindServiceImpl extends BaseServiceImpl<LklLedgerMerReceiverBindMapper, LklLedgerMerReceiverBind> implements LklLedgerMerReceiverBindService {
/**
* 根据接收方编号新增或更新记录
*
* @param record
* @return
*/
@Override
public Boolean saveOrUpdateByMerCupNoReceiverNo(LklLedgerMerReceiverBind record) {
if (record == null || StrUtil.isBlank(record.getReceiver_no())) {
return false;
}
QueryWrapper<LklLedgerMerReceiverBind> queryWrapper = new QueryWrapper<>();
queryWrapper.eq("mer_cup_no", record.getMer_cup_no());
queryWrapper.eq("receiver_no", record.getReceiver_no());
List<LklLedgerMerReceiverBind> existsRecordList = list(queryWrapper);
if (!CollectionUtil.isEmpty(existsRecordList)
&& existsRecordList.get(0) != null
&& existsRecordList.get(0).getId() > 0) {
// update
record.setId(existsRecordList.get(0).getId());
return updateById(record);
}
return save(record);
}
/**
* 更新审核结果
*
* @param applyId
* @param merInnerNo
* @param merCupNo
* @param receiverNo
* @param entrustFileName
* @param entrustFilePath
* @param auditStatus
* @param auditStatusText
* @param remark
* @return
*/
@Override
public Boolean updateAuditResult(String applyId, String merInnerNo, String merCupNo, String receiverNo, String entrustFileName, String entrustFilePath, String auditStatus, String auditStatusText, String remark) {
if (StrUtil.isBlank(applyId) || StrUtil.isBlank(merCupNo) || StrUtil.isBlank(receiverNo) || StrUtil.isBlank(auditStatus)) {
return false;
}
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("split_entrust_file_name", entrustFileName);
updateWrapper.set("split_entrust_file_path", entrustFilePath);
updateWrapper.set("audit_status", auditStatus);
updateWrapper.set("audit_status_text", auditStatusText);
updateWrapper.set("remark", remark);
return update(updateWrapper);
}
}

View File

@ -0,0 +1,55 @@
/*
* Copyright (c) 2025. Lorem ipsum dolor sit amet, consectetur adipiscing elit.
* Morbi non lorem porttitor neque feugiat blandit. Ut vitae ipsum eget quam lacinia accumsan.
* Etiam sed turpis ac ipsum condimentum fringilla. Maecenas magna.
* Proin dapibus sapien vel ante. Aliquam erat volutpat. Pellentesque sagittis ligula eget metus.
* Vestibulum commodo. Ut rhoncus gravida arcu.
*/
package com.suisung.mall.shop.lakala.service.impl;
import cn.hutool.core.collection.CollectionUtil;
import cn.hutool.core.util.StrUtil;
import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import com.suisung.mall.common.modules.lakala.LklLedgerReceiver;
import com.suisung.mall.core.web.service.impl.BaseServiceImpl;
import com.suisung.mall.shop.lakala.mapper.LklLedgerReceiverMapper;
import com.suisung.mall.shop.lakala.service.LklLedgerReceiverService;
import org.springframework.stereotype.Service;
import java.util.List;
@Service
public class LklLedgerReceiverServiceImpl extends BaseServiceImpl<LklLedgerReceiverMapper, LklLedgerReceiver> implements LklLedgerReceiverService {
/**
* 根据接收方编号新增或更新记录
*
* @param record
* @return
*/
@Override
public Boolean saveOrUpdateByReceiverNo(LklLedgerReceiver record) {
if (record == null || (StrUtil.isBlank(record.getLicense_no()) && StrUtil.isBlank(record.getContact_mobile()))) {
return false;
}
QueryWrapper<LklLedgerReceiver> queryWrapper = new QueryWrapper<>();
if (StrUtil.isNotBlank(record.getLicense_no())) {
queryWrapper.eq("license_no", record.getLicense_no());
}
if (StrUtil.isNotBlank(record.getContact_mobile())) {
queryWrapper.eq("contact_mobile", record.getContact_mobile());
}
List<LklLedgerReceiver> existsRecordList = list(queryWrapper);
if (!CollectionUtil.isEmpty(existsRecordList)
&& existsRecordList.get(0) != null
&& existsRecordList.get(0).getId() > 0) {
// update
record.setId(existsRecordList.get(0).getId());
return updateById(record);
}
return save(record);
}
}

View File

@ -0,0 +1,238 @@
/*
* Copyright (c) 2025. Lorem ipsum dolor sit amet, consectetur adipiscing elit.
* Morbi non lorem porttitor neque feugiat blandit. Ut vitae ipsum eget quam lacinia accumsan.
* Etiam sed turpis ac ipsum condimentum fringilla. Maecenas magna.
* Proin dapibus sapien vel ante. Aliquam erat volutpat. Pellentesque sagittis ligula eget metus.
* Vestibulum commodo. Ut rhoncus gravida arcu.
*/
package com.suisung.mall.shop.lakala.utils;
import cn.hutool.core.util.StrUtil;
import com.lkl.laop.sdk.Config2;
import com.lkl.laop.sdk.LKLSDK;
import com.suisung.mall.common.exception.ApiException;
import com.suisung.mall.common.utils.I18nUtil;
import lombok.extern.slf4j.Slf4j;
import org.apache.commons.codec.binary.Base64;
import org.springframework.core.io.ClassPathResource;
import javax.servlet.http.HttpServletRequest;
import java.io.BufferedReader;
import java.io.IOException;
import java.io.InputStream;
import java.io.InputStreamReader;
import java.nio.charset.StandardCharsets;
import java.security.InvalidKeyException;
import java.security.NoSuchAlgorithmException;
import java.security.Signature;
import java.security.SignatureException;
import java.security.cert.*;
import java.util.HashMap;
import java.util.Map;
@Slf4j
public class LakalaUtil {
/**
* 初始化 拉卡拉 SDK全局只需设置一次
*
* @return
*/
public static boolean initLKLSDK(String appId, String serialNo, String priKeyPath, String lklCerPath, String lklNotifyCerPath, String serverUrl) {
Config2 config = new Config2();
config.setAppId(appId);
config.setSerialNo(serialNo);
config.setPriKey(getResourceFile(priKeyPath));
config.setLklCer(getResourceFile(lklCerPath));
config.setLklNotifyCer(getResourceFile(lklNotifyCerPath));
config.setServerUrl(serverUrl);
return LKLSDK.init(config);
}
/**
* 读取证书文件内容
*
* @param fileName recource 文件夹下的路径palyKey/wx/lakala_public_key.cer
* @return
*/
public static String getResourceFile(String fileName) {
StringBuilder stringBuilder = new StringBuilder();
try (InputStream inputStream = new ClassPathResource(fileName).getInputStream();
InputStreamReader inputStreamReader = new InputStreamReader(inputStream);
BufferedReader bufferedReader = new BufferedReader(inputStreamReader)) {
String line;
while ((line = bufferedReader.readLine()) != null) {
stringBuilder.append(line).append("\n");
}
String content = stringBuilder.toString();
// log.info("证书内容:{}", content);
return content;
} catch (IOException e) {
// 记录异常信息
log.error(e.getMessage());
return "";
}
}
/**
* 获取 body 请求数据
*
* @param request
* @return
*/
public static String getBody(HttpServletRequest request) {
InputStreamReader in = null;
try {
in = new InputStreamReader(request.getInputStream(), StandardCharsets.UTF_8);
StringBuffer bf = new StringBuffer();
int len;
char[] chs = new char[1024];
while ((len = in.read(chs)) != -1) {
bf.append(new String(chs, 0, len));
}
return bf.toString();
} catch (Exception e) {
log.error("请求头部取数据异常:{}", e);
throw new ApiException(I18nUtil._("获取请求数据失败!"), e);
} finally {
if (null != in) {
try {
in.close();
} catch (Exception e) {
log.error("流关闭异常:{}", e);
}
}
}
}
/**
* 获取证书信息
*
* @param inputStream
* @return
*/
public static X509Certificate loadCertificate(InputStream inputStream) {
try {
CertificateFactory cf = CertificateFactory.getInstance("X509");
X509Certificate cert = (X509Certificate) cf.generateCertificate(inputStream);
// String publicKeyBase64 = Base64.encodeBase64String(cert.getPublicKey().getEncoded());
// System.out.println(publicKeyBase64);
cert.checkValidity();
return cert;
} catch (CertificateExpiredException e) {
throw new RuntimeException("证书已过期", e);
} catch (CertificateNotYetValidException e) {
throw new RuntimeException("证书尚未生效", e);
} catch (CertificateException e) {
throw new RuntimeException("无效的证书", e);
}
}
/**
* 签名验证
*
* @param certificate
* @param message
* @param signature
* @return
*/
public static boolean verify(X509Certificate certificate, byte[] message, String signature) {
try {
Signature sign = Signature.getInstance("SHA256withRSA");
sign.initVerify(certificate);
sign.update(message);
byte[] signatureB = Base64.decodeBase64(signature);
return sign.verify(signatureB);
} catch (NoSuchAlgorithmException e) {
throw new RuntimeException("当前Java环境不支持SHA256withRSA", e);
} catch (SignatureException e) {
throw new RuntimeException("签名验证过程发生了错误", e);
} catch (InvalidKeyException e) {
throw new RuntimeException("无效的证书", e);
}
}
/**
* 签名校验
*
* @param authorization
* @param reqBody
* @param lklNotifyCerPath
* @return
*/
public static boolean verify(String authorization, String reqBody, String lklNotifyCerPath) {
try {
log.debug("拉卡拉 Authorization 内容:{}", authorization);
Map<String, String> headerMap = getLakalaAuthorizationMap(authorization);
String timestamp = headerMap.get("timestamp");
String nonceStr = headerMap.get("nonce_str");
String signature = headerMap.get("signature");
X509Certificate lklNotifyCer = loadCertificate(new ClassPathResource(lklNotifyCerPath).getInputStream());
if (StrUtil.isBlank(timestamp) || StrUtil.isBlank(nonceStr) || StrUtil.isBlank(signature) || lklNotifyCer == null) {
return false;
}
String preSignDataStr = timestamp + "\n" +
nonceStr + "\n" +
reqBody + "\n";
log.debug("拉卡拉签名明文内容:{}", preSignDataStr);
if (verify(lklNotifyCer, preSignDataStr.getBytes(StandardCharsets.UTF_8), signature)) {
log.debug("验签成功");
return true;
}
log.debug("验签失败");
return false;
} catch (Exception e) {
log.error("验签发生异常:{}", e);
return false;
}
}
/**
* 解析请求头中的认证签名等信息
* 参考https://o.lakala.com/#/home/document/detail?id=36
*
* @param authorization 格式如下
* LKLAPI-SHA256withRSA timestamp="1643271327",
* nonce_str="rQCbASKattHx",
* signature="
* iPSycbakMt7AgjmwbtaweDVI/RLsQnGvOGiVM93haFkPpT/BxUprYx/GKFLQZebSQMvBfbeWinmnOJlqd3bXgye41BUAVmbItSTOzaQhNyS2kbDwXXGJWmT84aeJWHUB05BWB8ng
* /+X7jrPtsenC6aO7Xgh8jNylJlkU59TKCi7BPGbyHo6pAWJl/Bus0IQps1ay+Eo6Ks3Ins3COV7
* /lmu5p5FD7TAZsfP+ZvMFObLJOrDQeBTMFKFFWj4ZkjNzNlQqZWlfLv4yLns
* /dKTDLDy5tRO5zwunW+li5YLcwOVf3tbevNFtg53WoBhQnwf838WNvY9zfRhOpCc4fBlWAA=="
* @return
*/
public static Map<String, String> getLakalaAuthorizationMap(String authorization) {
Map<String, String> map = new HashMap();
authorization = authorization.trim();
int bpos = authorization.indexOf(" ");
String authType = authorization.substring(0, bpos);
String[] typeArr = authType.split("-");
if (typeArr.length > 1) {
map.put("signSystemCode", typeArr[0]);
map.put("signAlgorithm", typeArr[1]);
}
String signInfo = authorization.substring(bpos + 1);
String[] infoArr = signInfo.split(",");
String[] var7 = infoArr;
int var8 = infoArr.length;
for (int var9 = 0; var9 < var8; ++var9) {
String info = var7[var9];
if (info.contains("=")) {
int fpos = info.indexOf("=");
String value = info.substring(fpos + 1).trim();
value = value.substring(1, value.length() - 1);
map.put(info.substring(0, fpos).trim(), value);
}
}
return map;
}
}

View File

@ -307,7 +307,7 @@ public class ShopMessageTemplateServiceImpl extends BaseServiceImpl<ShopMessageT
smsDto.setContent(message_row.getMessage_sms());
smsDto.setParamMap(args); //传入模板对应参数
smsDto.setTengxunTemplateId(NumberUtil.parseInt(message_row.getMessage_tpl_id(), 0));
smsDto.setTengxunTemplateId(NumberUtil.parseInt(message_row.getMessage_tpl_id()));
try {
ThirdUtil.send(smsDto);

View File

@ -129,6 +129,8 @@ getui:
masterSecret: ybdUcVJJKw5bAcQB4DpC0A
logstash:
host: @logstash.host@
project:
domain: @project.domain@
feieyun:
url: http://api.feieyun.cn/Api/Open/
user: 17777525395@163.com
@ -141,6 +143,25 @@ sf-express:
enable: 2
#拉卡拉进件配置
lakala:
#服务地址
server_url: https://test.wsmsd.cn/sit
#应用Id
app_id: OP00000003
#商户证书序列号
serial_no: 00dfba8194c41b84cf
#商户证书
api_cert_path: payKey/lakala/dev/OP00000003_cert.cer
#商户私钥
api_pri_key_path: payKey/lakala/dev/OP00000003_private_key.pem
#拉卡拉平台证书
lkl_platform_cer_path: payKey/lakala/dev/lkl_notify_cert_v2.cer
#机构代码
org_code: 1
#商户号
merchant_no: 82229007392000A
#终端号
term_no: D9296400
# 拉卡拉拓客进件配置
tk:
#服务地址
server_url: https://test.wsmsd.cn/sit/htkauth

View File

@ -129,6 +129,8 @@ getui:
masterSecret: ybdUcVJJKw5bAcQB4DpC0A
logstash:
host: @logstash.host@
project:
domain: @project.domain@
feieyun:
url: http://api.feieyun.cn/Api/Open/
user: 17777525395@163.com
@ -141,6 +143,25 @@ sf-express:
enable: 2
#拉卡拉进件配置
lakala:
#服务地址
server_url: https://test.wsmsd.cn/sit
#应用Id
app_id: OP00000003
#商户证书序列号
serial_no: 00dfba8194c41b84cf
#商户证书
api_cert_path: payKey/lakala/dev/OP00000003_cert.cer
#商户私钥
api_pri_key_path: payKey/lakala/dev/OP00000003_private_key.pem
#拉卡拉平台证书
lkl_platform_cer_path: payKey/lakala/dev/lkl_notify_cert_v2.cer
#机构代码
org_code: 1
#商户号
merchant_no: 82229007392000A
#终端号
term_no: D9296400
# 拉卡拉拓客进件配置
tk:
#服务地址
server_url: https://test.wsmsd.cn/sit/htkauth

View File

@ -135,6 +135,8 @@ getui:
masterSecret: ybdUcVJJKw5bAcQB4DpC0A
logstash:
host: @logstash.host@
project:
domain: @project.domain@
feieyun:
url: http://api.feieyun.cn/Api/Open/
user: 17777525395@163.com
@ -150,6 +152,25 @@ sf-express:
enable: 2
#拉卡拉进件配置
lakala:
#服务地址
server_url: https://s2.lakala.com
#应用Id
app_id: OP10000439
#商户证书序列号
serial_no: 1737359895636
#商户证书
api_cert_path: payKey/lakala/prod/api_cert.cer
#商户私钥
api_pri_key_path: payKey/lakala/prod/api_private_key.pem
#拉卡拉平台证书
lkl_platform_cer_path: payKey/lakala/prod/lkl_platform.cer
#机构代码
org_code: 980688
#商户号
merchant_no: 8226330599900LN
#终端号码M0780629B2B收银台 M0780798专业化扫码
term_no: M0780798
#拉卡拉拓客进件配置
tk:
#服务地址
server_url: https://test.wsmsd.cn/sit/htkauth

View File

@ -133,6 +133,8 @@ getui:
masterSecret: ybdUcVJJKw5bAcQB4DpC0A
logstash:
host: @logstash.host@
project:
domain: @project.domain@
feieyun:
url: http://api.feieyun.cn/Api/Open/
user: 17777525395@163.com
@ -145,6 +147,25 @@ sf-express:
enable: 2
#拉卡拉进件配置
lakala:
#服务地址
server_url: https://test.wsmsd.cn/sit
#应用Id
app_id: OP00000003
#商户证书序列号
serial_no: 00dfba8194c41b84cf
#商户证书
api_cert_path: payKey/lakala/dev/OP00000003_cert.cer
#商户私钥
api_pri_key_path: payKey/lakala/dev/OP00000003_private_key.pem
#拉卡拉平台证书
lkl_platform_cer_path: payKey/lakala/dev/lkl_notify_cert_v2.cer
#机构代码
org_code: 1
#商户号
merchant_no: 82229007392000A
#终端号
term_no: D9296400
# 拉卡拉拓客进件配置
tk:
#服务地址
server_url: https://test.wsmsd.cn/sit/htkauth

View File

@ -133,6 +133,8 @@ getui:
masterSecret: ybdUcVJJKw5bAcQB4DpC0A
logstash:
host: @logstash.host@
project:
domain: @project.domain@
feieyun:
url: http://api.feieyun.cn/Api/Open/
user: 17777525395@163.com
@ -145,6 +147,25 @@ sf-express:
enable: 2
#拉卡拉进件配置
lakala:
#服务地址
server_url: https://test.wsmsd.cn/sit
#应用Id
app_id: OP00000003
#商户证书序列号
serial_no: 00dfba8194c41b84cf
#商户证书
api_cert_path: payKey/lakala/dev/OP00000003_cert.cer
#商户私钥
api_pri_key_path: payKey/lakala/dev/OP00000003_private_key.pem
#拉卡拉平台证书
lkl_platform_cer_path: payKey/lakala/dev/lkl_notify_cert_v2.cer
#机构代码
org_code: 1
#商户号
merchant_no: 82229007392000A
#终端号
term_no: D9296400
# 拉卡拉拓客进件配置
tk:
#服务地址
server_url: https://test.wsmsd.cn/sit/htkauth

View File

@ -0,0 +1,4 @@
<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE mapper PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN" "http://mybatis.org/dtd/mybatis-3-mapper.dtd">
<mapper namespace="com.suisung.mall.shop.lakala.mapper.LklLedgerMemberMapper">
</mapper>

View File

@ -0,0 +1,4 @@
<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE mapper PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN" "http://mybatis.org/dtd/mybatis-3-mapper.dtd">
<mapper namespace="com.suisung.mall.shop.lakala.mapper.LklLedgerMerReceiverBindMapper">
</mapper>

View File

@ -0,0 +1,4 @@
<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE mapper PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN" "http://mybatis.org/dtd/mybatis-3-mapper.dtd">
<mapper namespace="com.suisung.mall.shop.lakala.mapper.LklLedgerReceiverMapper">
</mapper>