拉卡拉支付调试修正

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 {
/**
* 初始化拉卡拉支付参数
*/
void doInit();
/**
* 初始化微信V3支付参数
*
* @return
*/
NativePayService initWxV3SDK();
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.JSONUtil;
import com.ijpay.core.kit.IpKit;
import com.lkl.laop.sdk.Config2;
import com.lkl.laop.sdk.LKLSDK;
import com.lkl.laop.sdk.exception.SDKException;
import com.lkl.laop.sdk.request.V3LabsTransPreorderRequest;
import com.lkl.laop.sdk.request.model.V3LabsTradeLocationInfo;
import com.lkl.laop.sdk.request.model.V3LabsTradePreorderWechatBus;
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.pay.service.LakalaService;
import com.wechat.pay.java.core.exception.ServiceException;
import com.suisung.mall.pay.utils.LakalaUtil;
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 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.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
@Service
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
public cn.hutool.json.JSONObject transPreOrder(HttpServletRequest request, HttpServletResponse response, String orderId) {
// 1. 配置初始化
doInit();
LakalaUtil.doInit();
//2. 装配数据
/*** 微信主扫场景示例 */
V3LabsTransPreorderRequest v3LabsTransPreorderWechatReq = new V3LabsTransPreorderRequest();
v3LabsTransPreorderWechatReq.setMerchantNo(merchantNo);
v3LabsTransPreorderWechatReq.setTermNo(termNo);
v3LabsTransPreorderWechatReq.setMerchantNo(LakalaUtil.merchantNo);
v3LabsTransPreorderWechatReq.setTermNo(LakalaUtil.termNo);
v3LabsTransPreorderWechatReq.setOutTradeNo(orderId);
v3LabsTransPreorderWechatReq.setSubject("油麦菜5斤装特惠");
v3LabsTransPreorderWechatReq.setAccountType("WECHAT");
@ -224,14 +94,13 @@ public class LakalaServiceImpl implements LakalaService {
@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. 配置初始化
doInit();
LakalaUtil.doInit();
if (StrUtil.isBlank(merchantNo)) {
merchantNo = this.merchantNo;
merchantNo = LakalaUtil.merchantNo;
}
if (StrUtil.isBlank(termNo)) {
termNo = this.termNo;
termNo = LakalaUtil.termNo;
}
//2. 装配数据

View File

@ -1256,7 +1256,7 @@ public class PayUserPayServiceImpl extends BaseServiceImpl<PayUserPayMapper, Pay
public String lklNotifyUrl(HttpServletRequest request) {
Map<String, String> params;
try {
lakalaService.doInit();
LakalaUtil.doInit();
// spring-boot 2.x 直接调用读取请求体并验签方法,返回请求体
String body = LKLSDK.notificationHandle(request);
@ -1268,8 +1268,8 @@ public class PayUserPayServiceImpl extends BaseServiceImpl<PayUserPayMapper, Pay
// 拉卡拉返回 json 格式的 数据
params = Convert.toMap(String.class, String.class, JSONUtil.parseObj(body));
String order_id = getParameter("out_trade_no");
if(StrUtil.isBlank(order_id)){
order_id = params.getOrDefault("out_trade_no","");
if (StrUtil.isBlank(order_id)) {
order_id = params.getOrDefault("out_trade_no", "");
}
// logger.debug("支付回调 params 数据:{}", params);
@ -1284,18 +1284,21 @@ public class PayUserPayServiceImpl extends BaseServiceImpl<PayUserPayMapper, Pay
// 判断是门店 店铺 平台
Integer payment_store_id = 0;
Integer payment_chain_id = 0;
String orderSubject ="";
if (!accountBaseConfigService.getTradeModePlantform()) {
// 不可以联合支付
QueryWrapper<PayConsumeTrade> tradeQueryWrapper = new QueryWrapper<>();
tradeQueryWrapper.eq("order_id", order_id);
PayConsumeTrade trade_row_tmp = payConsumeTradeService.findOne(tradeQueryWrapper);
String orderSubject = "";
Integer userId = 0;
// 交易模式 2直接交易:商家直接收款 1担保交易平台收款平台和商家结算
// if (!accountBaseConfigService.getTradeModePlantform()) {
// 不可以联合支付
QueryWrapper<PayConsumeTrade> tradeQueryWrapper = new QueryWrapper<>();
tradeQueryWrapper.eq("order_id", order_id);
PayConsumeTrade trade_row_tmp = payConsumeTradeService.findOne(tradeQueryWrapper);
if(trade_row_tmp!=null) {
payment_store_id = trade_row_tmp.getStore_id();
orderSubject = trade_row_tmp.getTrade_title();
}
if (trade_row_tmp != null) {
payment_store_id = trade_row_tmp.getStore_id();
orderSubject = trade_row_tmp.getTrade_title();
userId = trade_row_tmp.getBuyer_id();
}
// }
QueryWrapper<PayPaymentChannel> channelQueryWrapper = new QueryWrapper<>();
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.setDeposit_subject(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;
@ -1521,14 +1527,12 @@ public class PayUserPayServiceImpl extends BaseServiceImpl<PayUserPayMapper, Pay
notify_row.setDeposit_trade_no(params.get("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_is_total_fee_adjust(0);
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_body();
// notify_row.setDeposit_subject();
notify_row.setDeposit_gmt_create(deposit_gmt_payment);
notify_row.setDeposit_gmt_payment(deposit_gmt_payment);
notify_row.setDeposit_service("JSAPI");

View File

@ -8,12 +8,14 @@
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.utils.I18nUtil;
import com.wechat.pay.java.service.payments.nativepay.NativePayService;
import lombok.extern.slf4j.Slf4j;
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 javax.servlet.http.HttpServletRequest;
@ -33,6 +35,67 @@ import java.util.Map;
@Slf4j
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
* @return
*/
@ -114,6 +178,7 @@ public class LakalaUtil {
/**
* 签名验证
*
* @param certificate
* @param message
* @param signature
@ -138,15 +203,15 @@ public class LakalaUtil {
/**
* 解析请求头中的认证签名等信息
* 参考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
*/
public static Map<String, String> getLakalaAuthorizationMap(String authorization) {
@ -165,7 +230,7 @@ public class LakalaUtil {
String[] var7 = infoArr;
int var8 = infoArr.length;
for(int var9 = 0; var9 < var8; ++var9) {
for (int var9 = 0; var9 < var8; ++var9) {
String info = var7[var9];
if (info.contains("=")) {
int fpos = info.indexOf("=");