拉卡拉支付调试修正

This commit is contained in:
Jack 2025-01-29 23:48:53 +08:00
parent b9f4325c51
commit 81e4341276
4 changed files with 104 additions and 178 deletions

View File

@ -17,18 +17,6 @@ import javax.servlet.http.HttpServletResponse;
public interface LakalaService { public interface LakalaService {
/**
* 初始化拉卡拉支付参数
*/
void doInit();
/**
* 初始化微信V3支付参数
*
* @return
*/
NativePayService initWxV3SDK();
JSONObject transPreOrder(HttpServletRequest request, HttpServletResponse response, String orderId); JSONObject transPreOrder(HttpServletRequest request, HttpServletResponse response, String orderId);
/** /**

View File

@ -13,167 +13,37 @@ import cn.hutool.core.util.StrUtil;
import cn.hutool.json.JSONObject; import cn.hutool.json.JSONObject;
import cn.hutool.json.JSONUtil; import cn.hutool.json.JSONUtil;
import com.ijpay.core.kit.IpKit; import com.ijpay.core.kit.IpKit;
import com.lkl.laop.sdk.Config2;
import com.lkl.laop.sdk.LKLSDK; import com.lkl.laop.sdk.LKLSDK;
import com.lkl.laop.sdk.exception.SDKException; import com.lkl.laop.sdk.exception.SDKException;
import com.lkl.laop.sdk.request.V3LabsTransPreorderRequest; import com.lkl.laop.sdk.request.V3LabsTransPreorderRequest;
import com.lkl.laop.sdk.request.model.V3LabsTradeLocationInfo; import com.lkl.laop.sdk.request.model.V3LabsTradeLocationInfo;
import com.lkl.laop.sdk.request.model.V3LabsTradePreorderWechatBus; import com.lkl.laop.sdk.request.model.V3LabsTradePreorderWechatBus;
import com.suisung.mall.common.exception.ApiException; import com.suisung.mall.common.exception.ApiException;
import com.suisung.mall.common.pojo.res.PayAccRespFieldsRes;
import com.suisung.mall.common.utils.I18nUtil; import com.suisung.mall.common.utils.I18nUtil;
import com.suisung.mall.pay.service.LakalaService; import com.suisung.mall.pay.service.LakalaService;
import com.wechat.pay.java.core.exception.ServiceException; import com.suisung.mall.pay.utils.LakalaUtil;
import lombok.extern.slf4j.Slf4j; import lombok.extern.slf4j.Slf4j;
import org.apache.commons.codec.binary.Base64;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.core.io.ClassPathResource;
import org.springframework.stereotype.Service; import org.springframework.stereotype.Service;
import com.wechat.pay.java.core.Config;
import com.wechat.pay.java.core.RSAAutoCertificateConfig;
import com.wechat.pay.java.service.payments.nativepay.NativePayService;
import com.wechat.pay.java.service.payments.nativepay.model.Amount;
import com.wechat.pay.java.service.payments.nativepay.model.PrepayRequest;
import com.wechat.pay.java.service.payments.nativepay.model.PrepayResponse;
import javax.servlet.http.HttpServletRequest; import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse; import javax.servlet.http.HttpServletResponse;
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.*;
@Slf4j @Slf4j
@Service @Service
public class LakalaServiceImpl implements LakalaService { public class LakalaServiceImpl implements LakalaService {
private static volatile boolean init = false;
private static volatile NativePayService wxV3Service= null;
/**
* 服务地址
*/
@Value("${lakala.server_url}")
private String serverUrl;
@Value("${lakala.app_id}")
private String appId; // 拉卡拉appId
@Value("${lakala.merchant_no}")
private String merchantNo;
@Value("${lakala.serial_no}")
private String serialNo; // 你的证书序列号
@Value("${lakala.term_no}")
private String termNo;
/**
* 商户私钥信息地址
*/
@Value("${lakala.api_pri_key_path}")
private String priKeyPath;
/**
* 拉卡拉支付平台证书地址
*/
@Value("${lakala.lkl_platform_cer_path}")
private String lklCerPath;
/**
* 拉卡拉支付平台证书地址2(用于拉卡拉通知验签)
*/
@Value("${lakala.lkl_platform_cer_path}")
private String lklNotifyCerPath;
/***
* @Description: 初始化设置商户公共参数全局只需设置一次
* @throws Exception
*/
public void doInit() {
if (!init) {
init = initLKLSDK();
}
}
/**
* 读取证书文件内容
*
* @param fileName
* @return
*/
private 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 "";
}
}
/**
* 初始化 拉卡拉 SDK
*
* @return
*/
public boolean initLKLSDK() {
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);
}
@Override
public NativePayService initWxV3SDK() {
if (wxV3Service!=null) {
return wxV3Service;
}
Config config =
new RSAAutoCertificateConfig.Builder()
.merchantId("1684833481")
.privateKey(getResourceFile("payKey/wx/apiclient_key.pem"))
.privateKeyFromPath("privateKeyPath")
.merchantSerialNumber("30314B93B394352C6A4616B7611C23402041ADE2")
.apiV3Key("n8tgyMKKAov9lVJuczMOLUjXr5IeZjce")
.build();
// 构建service
NativePayService service = new NativePayService.Builder().config(config).build();
if(service==null){
throw new ApiException(I18nUtil._("微信SDKV3初始化失败"));
}
wxV3Service = service;
return service;
}
@Override @Override
public cn.hutool.json.JSONObject transPreOrder(HttpServletRequest request, HttpServletResponse response, String orderId) { public cn.hutool.json.JSONObject transPreOrder(HttpServletRequest request, HttpServletResponse response, String orderId) {
// 1. 配置初始化 // 1. 配置初始化
doInit(); LakalaUtil.doInit();
//2. 装配数据 //2. 装配数据
/*** 微信主扫场景示例 */ /*** 微信主扫场景示例 */
V3LabsTransPreorderRequest v3LabsTransPreorderWechatReq = new V3LabsTransPreorderRequest(); V3LabsTransPreorderRequest v3LabsTransPreorderWechatReq = new V3LabsTransPreorderRequest();
v3LabsTransPreorderWechatReq.setMerchantNo(merchantNo); v3LabsTransPreorderWechatReq.setMerchantNo(LakalaUtil.merchantNo);
v3LabsTransPreorderWechatReq.setTermNo(termNo); v3LabsTransPreorderWechatReq.setTermNo(LakalaUtil.termNo);
v3LabsTransPreorderWechatReq.setOutTradeNo(orderId); v3LabsTransPreorderWechatReq.setOutTradeNo(orderId);
v3LabsTransPreorderWechatReq.setSubject("油麦菜5斤装特惠"); v3LabsTransPreorderWechatReq.setSubject("油麦菜5斤装特惠");
v3LabsTransPreorderWechatReq.setAccountType("WECHAT"); v3LabsTransPreorderWechatReq.setAccountType("WECHAT");
@ -224,14 +94,13 @@ public class LakalaServiceImpl implements LakalaService {
@Override @Override
public JSONObject transPreOrder(String merchantNo, String termNo, String xcxAppId, String openId, String orderId, String subject, String totalAmount, String notifyURL, String requestIP, String remark) { public JSONObject transPreOrder(String merchantNo, String termNo, String xcxAppId, String openId, String orderId, String subject, String totalAmount, String notifyURL, String requestIP, String remark) {
// 1. 配置初始化 // 1. 配置初始化
doInit(); LakalaUtil.doInit();
if (StrUtil.isBlank(merchantNo)) { if (StrUtil.isBlank(merchantNo)) {
merchantNo = this.merchantNo; merchantNo = LakalaUtil.merchantNo;
} }
if (StrUtil.isBlank(termNo)) { if (StrUtil.isBlank(termNo)) {
termNo = this.termNo; termNo = LakalaUtil.termNo;
} }
//2. 装配数据 //2. 装配数据

View File

@ -1256,7 +1256,7 @@ public class PayUserPayServiceImpl extends BaseServiceImpl<PayUserPayMapper, Pay
public String lklNotifyUrl(HttpServletRequest request) { public String lklNotifyUrl(HttpServletRequest request) {
Map<String, String> params; Map<String, String> params;
try { try {
lakalaService.doInit(); LakalaUtil.doInit();
// spring-boot 2.x 直接调用读取请求体并验签方法,返回请求体 // spring-boot 2.x 直接调用读取请求体并验签方法,返回请求体
String body = LKLSDK.notificationHandle(request); String body = LKLSDK.notificationHandle(request);
@ -1268,8 +1268,8 @@ public class PayUserPayServiceImpl extends BaseServiceImpl<PayUserPayMapper, Pay
// 拉卡拉返回 json 格式的 数据 // 拉卡拉返回 json 格式的 数据
params = Convert.toMap(String.class, String.class, JSONUtil.parseObj(body)); params = Convert.toMap(String.class, String.class, JSONUtil.parseObj(body));
String order_id = getParameter("out_trade_no"); String order_id = getParameter("out_trade_no");
if(StrUtil.isBlank(order_id)){ if (StrUtil.isBlank(order_id)) {
order_id = params.getOrDefault("out_trade_no",""); order_id = params.getOrDefault("out_trade_no", "");
} }
// logger.debug("支付回调 params 数据:{}", params); // logger.debug("支付回调 params 数据:{}", params);
@ -1284,18 +1284,21 @@ public class PayUserPayServiceImpl extends BaseServiceImpl<PayUserPayMapper, Pay
// 判断是门店 店铺 平台 // 判断是门店 店铺 平台
Integer payment_store_id = 0; Integer payment_store_id = 0;
Integer payment_chain_id = 0; Integer payment_chain_id = 0;
String orderSubject =""; String orderSubject = "";
if (!accountBaseConfigService.getTradeModePlantform()) { Integer userId = 0;
// 不可以联合支付 // 交易模式 2直接交易:商家直接收款 1担保交易平台收款平台和商家结算
QueryWrapper<PayConsumeTrade> tradeQueryWrapper = new QueryWrapper<>(); // if (!accountBaseConfigService.getTradeModePlantform()) {
tradeQueryWrapper.eq("order_id", order_id); // 不可以联合支付
PayConsumeTrade trade_row_tmp = payConsumeTradeService.findOne(tradeQueryWrapper); QueryWrapper<PayConsumeTrade> tradeQueryWrapper = new QueryWrapper<>();
tradeQueryWrapper.eq("order_id", order_id);
PayConsumeTrade trade_row_tmp = payConsumeTradeService.findOne(tradeQueryWrapper);
if(trade_row_tmp!=null) { if (trade_row_tmp != null) {
payment_store_id = trade_row_tmp.getStore_id(); payment_store_id = trade_row_tmp.getStore_id();
orderSubject = trade_row_tmp.getTrade_title(); orderSubject = trade_row_tmp.getTrade_title();
} userId = trade_row_tmp.getBuyer_id();
} }
// }
QueryWrapper<PayPaymentChannel> channelQueryWrapper = new QueryWrapper<>(); QueryWrapper<PayPaymentChannel> channelQueryWrapper = new QueryWrapper<>();
channelQueryWrapper.eq("payment_channel_code", "lakala"); channelQueryWrapper.eq("payment_channel_code", "lakala");
@ -1311,6 +1314,9 @@ public class PayUserPayServiceImpl extends BaseServiceImpl<PayUserPayMapper, Pay
notify_row.setPayment_channel_id(payment_channel_id); notify_row.setPayment_channel_id(payment_channel_id);
notify_row.setDeposit_subject(orderSubject); notify_row.setDeposit_subject(orderSubject);
notify_row.setDeposit_body(orderSubject); notify_row.setDeposit_body(orderSubject);
notify_row.setUser_id(userId);
notify_row.setDeposit_async(1); // 是否同步:0-同步; 1-异步回调使用
notify_row.setDeposit_state(1);// 支付状态:0-默认; 1-接收正确数据处理完逻辑; 9-异常订单
BigDecimal zero = BigDecimal.ZERO; BigDecimal zero = BigDecimal.ZERO;
@ -1521,14 +1527,12 @@ public class PayUserPayServiceImpl extends BaseServiceImpl<PayUserPayMapper, Pay
notify_row.setDeposit_trade_no(params.get("trade_no")); notify_row.setDeposit_trade_no(params.get("trade_no"));
notify_row.setOrder_id(params.get("out_trade_no")); notify_row.setOrder_id(params.get("out_trade_no"));
notify_row.setDeposit_quantity(1); notify_row.setDeposit_quantity(0);
notify_row.setDeposit_seller_id(params.get("sub_mch_id")); notify_row.setDeposit_seller_id(params.get("sub_mch_id"));
notify_row.setDeposit_is_total_fee_adjust(0); notify_row.setDeposit_is_total_fee_adjust(0);
notify_row.setDeposit_total_fee(deposit_total_fee); notify_row.setDeposit_total_fee(deposit_total_fee);
notify_row.setDeposit_price(BigDecimal.ZERO); notify_row.setDeposit_price(deposit_total_fee);
notify_row.setDeposit_buyer_id(params.get("user_id2"));// openid notify_row.setDeposit_buyer_id(params.get("user_id2"));// openid
// notify_row.setDeposit_body();
// notify_row.setDeposit_subject();
notify_row.setDeposit_gmt_create(deposit_gmt_payment); notify_row.setDeposit_gmt_create(deposit_gmt_payment);
notify_row.setDeposit_gmt_payment(deposit_gmt_payment); notify_row.setDeposit_gmt_payment(deposit_gmt_payment);
notify_row.setDeposit_service("JSAPI"); notify_row.setDeposit_service("JSAPI");

View File

@ -8,12 +8,14 @@
package com.suisung.mall.pay.utils; package com.suisung.mall.pay.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.exception.ApiException;
import com.suisung.mall.common.utils.I18nUtil; import com.suisung.mall.common.utils.I18nUtil;
import com.wechat.pay.java.service.payments.nativepay.NativePayService;
import lombok.extern.slf4j.Slf4j; import lombok.extern.slf4j.Slf4j;
import org.apache.commons.codec.binary.Base64; import org.apache.commons.codec.binary.Base64;
import org.apache.commons.lang3.StringUtils; import org.springframework.beans.factory.annotation.Value;
import org.springframework.core.io.ClassPathResource; import org.springframework.core.io.ClassPathResource;
import javax.servlet.http.HttpServletRequest; import javax.servlet.http.HttpServletRequest;
@ -33,6 +35,67 @@ import java.util.Map;
@Slf4j @Slf4j
public class LakalaUtil { public class LakalaUtil {
private static volatile boolean init = false;
private static volatile NativePayService wxV3Service;
/**
* 服务地址
*/
@Value("${lakala.server_url}")
private static String serverUrl;
@Value("${lakala.app_id}")
private static String appId; // 拉卡拉appId
@Value("${lakala.merchant_no}")
public static String merchantNo;
@Value("${lakala.serial_no}")
private static String serialNo; // 你的证书序列号
@Value("${lakala.term_no}")
public static String termNo;
/**
* 商户私钥信息地址
*/
@Value("${lakala.api_pri_key_path}")
private static String priKeyPath;
/**
* 拉卡拉支付平台证书地址
*/
@Value("${lakala.lkl_platform_cer_path}")
private static String lklCerPath;
/**
* 拉卡拉支付平台证书地址2(用于拉卡拉通知验签)
*/
@Value("${lakala.lkl_platform_cer_path}")
private static String lklNotifyCerPath;
/***
* @Description: 初始化设置商户公共参数全局只需设置一次
* @throws Exception
*/
public static void doInit() {
if (!init) {
init = initLKLSDK();
}
}
/**
* 初始化 拉卡拉 SDK
*
* @return
*/
public static boolean initLKLSDK() {
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);
}
/** /**
* 读取证书文件内容 * 读取证书文件内容
* *
@ -91,6 +154,7 @@ public class LakalaUtil {
/** /**
* 获取证书信息 * 获取证书信息
*
* @param inputStream * @param inputStream
* @return * @return
*/ */
@ -114,6 +178,7 @@ public class LakalaUtil {
/** /**
* 签名验证 * 签名验证
*
* @param certificate * @param certificate
* @param message * @param message
* @param signature * @param signature
@ -138,15 +203,15 @@ public class LakalaUtil {
/** /**
* 解析请求头中的认证签名等信息 * 解析请求头中的认证签名等信息
* 参考https://o.lakala.com/#/home/document/detail?id=36 * 参考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=="
* *
* @param authorization 格式如下
* LKLAPI-SHA256withRSA timestamp="1643271327",
* nonce_str="rQCbASKattHx",
* signature="
* iPSycbakMt7AgjmwbtaweDVI/RLsQnGvOGiVM93haFkPpT/BxUprYx/GKFLQZebSQMvBfbeWinmnOJlqd3bXgye41BUAVmbItSTOzaQhNyS2kbDwXXGJWmT84aeJWHUB05BWB8ng
* /+X7jrPtsenC6aO7Xgh8jNylJlkU59TKCi7BPGbyHo6pAWJl/Bus0IQps1ay+Eo6Ks3Ins3COV7
* /lmu5p5FD7TAZsfP+ZvMFObLJOrDQeBTMFKFFWj4ZkjNzNlQqZWlfLv4yLns
* /dKTDLDy5tRO5zwunW+li5YLcwOVf3tbevNFtg53WoBhQnwf838WNvY9zfRhOpCc4fBlWAA=="
* @return * @return
*/ */
public static Map<String, String> getLakalaAuthorizationMap(String authorization) { public static Map<String, String> getLakalaAuthorizationMap(String authorization) {
@ -165,7 +230,7 @@ public class LakalaUtil {
String[] var7 = infoArr; String[] var7 = infoArr;
int var8 = infoArr.length; int var8 = infoArr.length;
for(int var9 = 0; var9 < var8; ++var9) { for (int var9 = 0; var9 < var8; ++var9) {
String info = var7[var9]; String info = var7[var9];
if (info.contains("=")) { if (info.contains("=")) {
int fpos = info.indexOf("="); int fpos = info.indexOf("=");