微信支付宝添加灵枢商户,培训班报名用灵枢

This commit is contained in:
wuchunlei
2025-10-21 17:33:07 +08:00
parent a45511e0f0
commit 439ac950f3
21 changed files with 416 additions and 171 deletions

View File

@@ -67,7 +67,9 @@ public class ShiroConfig {
filterMap.put("book/task/list","anon"); // 网站接口
filterMap.put("/pay/aliPay/notify","anon"); // 支付宝回调接口
filterMap.put("/pay/payNotify","anon"); // 微信回调接口
filterMap.put("/pay/lsPayNotify","anon"); // 微信回调接口
filterMap.put("/pay/refundNotify","anon"); // 微信退款回调接口
filterMap.put("/pay/lsRefundNotify","anon"); // 微信退款回调接口
filterMap.put("/pay/paypal/receivePaypalStatus","anon"); // paypal回调接口
filterMap.put("/weChat/**","anon");
filterMap.put("/book/baseArea/getAllBaseArea","anon");//登录前获取全部区域

View File

@@ -153,7 +153,7 @@ public class BuyOrder implements Serializable {
private String buyType;
/**
* vip order point aiVip upgradeAiVip
* vip order point relearn trainingClass aiVip upgradeAiVip
*/
private String orderType;

View File

@@ -14,29 +14,30 @@ public class AliPayConfig {
* 花生appId 沙箱id 2021002161620176
*/
public static final String HS_APP_ID ="2021003191621137";
/**
* 花生应用私钥
*/
//花生应用私钥
public static final String HS_MERCHANT_PRIVATE_KEY = "MIIEvQIBADANBgkqhkiG9w0BAQEFAASCBKcwggSjAgEAAoIBAQCa+oIVGBAKp+VjHIeE/IFUFWifnUWQYBPwffWEC5+EKJbqEC/wcVSfZPKXpPAB3T0c6V6yxCOMxguUZEdeRM5W93Wf0jktrtius34Xo79vgnLXsj2TtAN1ku9Qp5ebVVw+WPdpIl1nOFNwCoiaSPmwXOsVIT5MccxUvmGUDNUg8dYVoD9WHYu13O30c4vm+jYGCu7lviRqcjnEFooJ/ORocLqJbHFaTzWMGiiAYnUUSTL1BI5vhDNJDhm3B5wUZ7/j49EWQYZbV0fXlCrZRerfPLrAgXYR95P+62K9Xh8edzThTrPXmLXP9/jTqz2118ijXSoF8EgfhVD2NLCSDid3AgMBAAECggEAR3cPN0TyWMeVer+0Knn59Vkt9rSiWHJFn5el+K8Xbuz8spCmWp0YJax6Rb10Q5fOz5854PubXRYSTupzEqBt+iKApiNd5JgFKYJxudrzsysXZCm4RX00PypzmuC9g464S7Pg2yVSpv+NUlQ5K9RM96vRZ9v9i2jKjaWA/7FvMpI3auOJgrJVoSbPYNx6/QIN1b9imukCMSga9OzF66LhfzACWxJx+DzgAX+7GcfhTF8PbhytPPg9LhlfcGq2gA/TcG6zUorFz5Qy+k//g4rxIvjcPnGfcRgoT+Xgi7I8wnm3O5icIZ6k6+B+wwN3zRTBSmXwbwsgdncGA1RUhe2tAQKBgQDweYu2ij8Io/g7KCvCtVpGHqhzKxgaOZXy0nvPFXY5KFcrrapACriztCaxjvRTXm7t25KJQazICs50OvyTZL5+U3GHp/8GK7KwzZKz5NkHHMtKoKwQADBNau/nHdro4E+PnvL9ucaFX69JF4DZqiw2aDkQkDB/BablHyvuTagJgQKBgQCk++uzero6bXOxFMadLLyWTvlOJP71U1fVSf4Nou+L4ce7k2bMpSDyEDNDOUW3WOO7zz9i8mFGCTUaoX3mhC+B9UQqKZXK2rjFgZtkNDumoCTzvjuPIWTMNN6ABetiLxbq/UD0O1xwThVQNmYwTOzwMHUMkT21ynD23KXE0JL89wKBgGg1Q8YmwooMBFYeYlhOHoCkaHsAAcHbko9Xhy+GLWU3hg73gv+dpcy6FMp9GIPIOGn67NVuEGHfzPexWCLHVYWIw3n14x3ZceYML7alRSc/4xjD58xHSKdD4BJXbbXc/p1OVB5/kvfZLyyNctjgVah+Ibx7v4hL+rbveyoZnOgBAoGAG34je+giqmPc2JB2vHBdCMsmPkBqACWgSFmpLUqOkofQSdC5W7bUs6HBeR1NIc19Pam+jVWIoiwcnlB083nplMVzU3dUj9Y83iTH6T3PBug+4CM+N47ABkt1HG5gGB9yuTv0m/5cXBaW9KPsCXZ4MVpR1wNI/kc65dhFA3QiWmcCgYEA6CfUjOWe201IC332e142WfPGp7hy8p6RHrPtlXS5YnuxVsJVusyuncVdG10kPkvPHakFokqNNUW76Trf++IPnNooMP9ucYj060hYTM7JK9F0mAdx0Mo/+nDC7voXw8rBSsLZHAWfxMh/KjQ5D7L6E2S71wP6ep25hoOuuuLTnrI=";
/**
* 应用公钥
*/
//应用公钥
public static final String HS_ALI_PUBLIC_KEY = "MIIBIjANBgkqhkiG9w0BAQEFAAOCAQ8AMIIBCgKCAQEAmvqCFRgQCqflYxyHhPyBVBVon51FkGAT8H31hAufhCiW6hAv8HFUn2Tyl6TwAd09HOlessQjjMYLlGRHXkTOVvd1n9I5La7YrrN+F6O/b4Jy17I9k7QDdZLvUKeXm1VcPlj3aSJdZzhTcAqImkj5sFzrFSE+THHMVL5hlAzVIPHWFaA/Vh2Ltdzt9HOL5vo2Bgru5b4kanI5xBaKCfzkaHC6iWxxWk81jBoogGJ1FEky9QSOb4QzSQ4ZtwecFGe/4+PRFkGGW1dH15Qq2UXq3zy6wIF2EfeT/utivV4fHnc04U6z15i1z/f406s9tdfIo10qBfBIH4VQ9jSwkg4ndwIDAQAB";
//支付宝公钥
public static final String HS_ALIPAY_PUBLIC_KEY = "MIIBIjANBgkqhkiG9w0BAQEFAAOCAQ8AMIIBCgKCAQEAiVLUVTnNuq+2C1FRtcIRcG3rCgtVVulkz2QljKbPr7NNWTJJIIfGwyhNuH76s5D1lvNmn2NkuoqM0cMJCSd+W+JW9KpdQ0dgumFHCoRA/OWUoqpLvEOmm2hRMaWpvd+OQq2aPz+p+z6pqZ9SAlgUIolzrUn4idCvgIycqRaGsf1sEJFR5W+rneqtMhNYHdwemqaqnysInwshHR3cHs1AC6y/eL6pcQhaYJ5qVMIRg54/6Lr4CU114Rmph7UM9C28ulmHkFMN/DKPUDbM1+glxjzmqHQChY293Db0dlwZeiDWF3Tli2BVd6pz5KEkQlUsGeLW1O0rT9T9sxzsavxArwIDAQAB";
/**
* 支付宝公钥
* 灵枢appId 沙箱id 2021002161620176
*/
public static final String LS_APP_ID ="2021003191621137";
//灵枢应用私钥
public static final String LS_MERCHANT_PRIVATE_KEY = "MIIEvQIBADANBgkqhkiG9w0BAQEFAASCBKcwggSjAgEAAoIBAQCa+oIVGBAKp+VjHIeE/IFUFWifnUWQYBPwffWEC5+EKJbqEC/wcVSfZPKXpPAB3T0c6V6yxCOMxguUZEdeRM5W93Wf0jktrtius34Xo79vgnLXsj2TtAN1ku9Qp5ebVVw+WPdpIl1nOFNwCoiaSPmwXOsVIT5MccxUvmGUDNUg8dYVoD9WHYu13O30c4vm+jYGCu7lviRqcjnEFooJ/ORocLqJbHFaTzWMGiiAYnUUSTL1BI5vhDNJDhm3B5wUZ7/j49EWQYZbV0fXlCrZRerfPLrAgXYR95P+62K9Xh8edzThTrPXmLXP9/jTqz2118ijXSoF8EgfhVD2NLCSDid3AgMBAAECggEAR3cPN0TyWMeVer+0Knn59Vkt9rSiWHJFn5el+K8Xbuz8spCmWp0YJax6Rb10Q5fOz5854PubXRYSTupzEqBt+iKApiNd5JgFKYJxudrzsysXZCm4RX00PypzmuC9g464S7Pg2yVSpv+NUlQ5K9RM96vRZ9v9i2jKjaWA/7FvMpI3auOJgrJVoSbPYNx6/QIN1b9imukCMSga9OzF66LhfzACWxJx+DzgAX+7GcfhTF8PbhytPPg9LhlfcGq2gA/TcG6zUorFz5Qy+k//g4rxIvjcPnGfcRgoT+Xgi7I8wnm3O5icIZ6k6+B+wwN3zRTBSmXwbwsgdncGA1RUhe2tAQKBgQDweYu2ij8Io/g7KCvCtVpGHqhzKxgaOZXy0nvPFXY5KFcrrapACriztCaxjvRTXm7t25KJQazICs50OvyTZL5+U3GHp/8GK7KwzZKz5NkHHMtKoKwQADBNau/nHdro4E+PnvL9ucaFX69JF4DZqiw2aDkQkDB/BablHyvuTagJgQKBgQCk++uzero6bXOxFMadLLyWTvlOJP71U1fVSf4Nou+L4ce7k2bMpSDyEDNDOUW3WOO7zz9i8mFGCTUaoX3mhC+B9UQqKZXK2rjFgZtkNDumoCTzvjuPIWTMNN6ABetiLxbq/UD0O1xwThVQNmYwTOzwMHUMkT21ynD23KXE0JL89wKBgGg1Q8YmwooMBFYeYlhOHoCkaHsAAcHbko9Xhy+GLWU3hg73gv+dpcy6FMp9GIPIOGn67NVuEGHfzPexWCLHVYWIw3n14x3ZceYML7alRSc/4xjD58xHSKdD4BJXbbXc/p1OVB5/kvfZLyyNctjgVah+Ibx7v4hL+rbveyoZnOgBAoGAG34je+giqmPc2JB2vHBdCMsmPkBqACWgSFmpLUqOkofQSdC5W7bUs6HBeR1NIc19Pam+jVWIoiwcnlB083nplMVzU3dUj9Y83iTH6T3PBug+4CM+N47ABkt1HG5gGB9yuTv0m/5cXBaW9KPsCXZ4MVpR1wNI/kc65dhFA3QiWmcCgYEA6CfUjOWe201IC332e142WfPGp7hy8p6RHrPtlXS5YnuxVsJVusyuncVdG10kPkvPHakFokqNNUW76Trf++IPnNooMP9ucYj060hYTM7JK9F0mAdx0Mo/+nDC7voXw8rBSsLZHAWfxMh/KjQ5D7L6E2S71wP6ep25hoOuuuLTnrI=";
//应用公钥
public static final String LS_ALI_PUBLIC_KEY = "MIIBIjANBgkqhkiG9w0BAQEFAAOCAQ8AMIIBCgKCAQEAmvqCFRgQCqflYxyHhPyBVBVon51FkGAT8H31hAufhCiW6hAv8HFUn2Tyl6TwAd09HOlessQjjMYLlGRHXkTOVvd1n9I5La7YrrN+F6O/b4Jy17I9k7QDdZLvUKeXm1VcPlj3aSJdZzhTcAqImkj5sFzrFSE+THHMVL5hlAzVIPHWFaA/Vh2Ltdzt9HOL5vo2Bgru5b4kanI5xBaKCfzkaHC6iWxxWk81jBoogGJ1FEky9QSOb4QzSQ4ZtwecFGe/4+PRFkGGW1dH15Qq2UXq3zy6wIF2EfeT/utivV4fHnc04U6z15i1z/f406s9tdfIo10qBfBIH4VQ9jSwkg4ndwIDAQAB";
//支付宝公钥
public static final String LS_ALIPAY_PUBLIC_KEY = "MIIBIjANBgkqhkiG9w0BAQEFAAOCAQ8AMIIBCgKCAQEAiVLUVTnNuq+2C1FRtcIRcG3rCgtVVulkz2QljKbPr7NNWTJJIIfGwyhNuH76s5D1lvNmn2NkuoqM0cMJCSd+W+JW9KpdQ0dgumFHCoRA/OWUoqpLvEOmm2hRMaWpvd+OQq2aPz+p+z6pqZ9SAlgUIolzrUn4idCvgIycqRaGsf1sEJFR5W+rneqtMhNYHdwemqaqnysInwshHR3cHs1AC6y/eL6pcQhaYJ5qVMIRg54/6Lr4CU114Rmph7UM9C28ulmHkFMN/DKPUDbM1+glxjzmqHQChY293Db0dlwZeiDWF3Tli2BVd6pz5KEkQlUsGeLW1O0rT9T9sxzsavxArwIDAQAB";
public static final String HS_ALIPAY_PUBLIC_KEY = "MIIBIjANBgkqhkiG9w0BAQEFAAOCAQ8AMIIBCgKCAQEAiVLUVTnNuq+2C1FRtcIRcG3rCgtVVulkz2QljKbPr7NNWTJJIIfGwyhNuH76s5D1lvNmn2NkuoqM0cMJCSd+W+JW9KpdQ0dgumFHCoRA/OWUoqpLvEOmm2hRMaWpvd+OQq2aPz+p+z6pqZ9SAlgUIolzrUn4idCvgIycqRaGsf1sEJFR5W+rneqtMhNYHdwemqaqnysInwshHR3cHs1AC6y/eL6pcQhaYJ5qVMIRg54/6Lr4CU114Rmph7UM9C28ulmHkFMN/DKPUDbM1+glxjzmqHQChY293Db0dlwZeiDWF3Tli2BVd6pz5KEkQlUsGeLW1O0rT9T9sxzsavxArwIDAQAB";
/**
* 回调地址 因为是内网开发 目前为内网穿透地址
*/
// public static final String NOTIFY_URL = "http://59.110.212.44:9100/pb/pay/aliPay/notify";
public static final String NOTIFY_URL = "https://api.nuttyreading.com/pay/aliPay/notify";
public static final String NOTIFY_URL = "http://z6f8f828.natappfree.cc/pb/pay/aliPay/notify";
// public static final String NOTIFY_URL = "https://api.nuttyreading.com/pay/aliPay/notify";
/**
@@ -64,19 +65,18 @@ public class AliPayConfig {
*/
public static final String GATEWAYURL = "https://openapi.alipay.com/gateway.do";
private static AlipayClient alipayClient = null;
public static AlipayClient getAliPayClient() throws AlipayApiException {
//实例化客户端
if (alipayClient == null) {
synchronized (AliPayUtil.class) {
if (null == alipayClient) {
alipayClient = new DefaultAlipayClient(GATEWAYURL, HS_APP_ID, HS_MERCHANT_PRIVATE_KEY,
FORMAT, CHARSET, HS_ALIPAY_PUBLIC_KEY, SIGN_TYPE);
}
}
public static AlipayClient getAliPayClient(String mchName) throws AlipayApiException {
if ("LS".equals(mchName)) {
return new DefaultAlipayClient(GATEWAYURL, LS_APP_ID, LS_MERCHANT_PRIVATE_KEY,
FORMAT, CHARSET, LS_ALIPAY_PUBLIC_KEY, SIGN_TYPE);
}else {
return new DefaultAlipayClient(GATEWAYURL, HS_APP_ID, HS_MERCHANT_PRIVATE_KEY,
FORMAT, CHARSET, HS_ALIPAY_PUBLIC_KEY, SIGN_TYPE);
}
return alipayClient;
}
}

View File

@@ -51,7 +51,7 @@ public class AliPayUtil {
request.setNotifyUrl(AliPayConfig.NOTIFY_URL);
try {
//这里和普通的接口调用不同使用的是sdkExecute
AlipayTradeAppPayResponse responseStr = AliPayConfig.getAliPayClient().sdkExecute(request);
AlipayTradeAppPayResponse responseStr = AliPayConfig.getAliPayClient(aliPayDto.getMchName()).sdkExecute(request);
//可以直接给客户端请求,无需再做处理。
map.put("msg", responseStr.getBody());
} catch (AlipayApiException e) {
@@ -69,7 +69,7 @@ public class AliPayUtil {
*/
public AlipayTradeWapPayResponse aliPayH5(AlipayDTO h5PayDto) {
try {
AlipayClient alipayClient = AliPayConfig.getAliPayClient();
AlipayClient alipayClient = AliPayConfig.getAliPayClient(h5PayDto.getMchName());
AlipayTradeWapPayRequest request = new AlipayTradeWapPayRequest();
request.setNotifyUrl(AliPayConfig.NOTIFY_URL);
request.setBizContent(getAliPayRequest(h5PayDto).toString());
@@ -108,7 +108,7 @@ public class AliPayUtil {
AlipayTradeRefundResponse response = null;
try {
response = AliPayConfig.getAliPayClient().execute(request);
response = AliPayConfig.getAliPayClient(reFundDTO.getMchName()).execute(request);
map.put("msg", response.getBody());
} catch (Exception e) {
log.info(">>>>>>>>>>退款出现异常 exception = {}", e);
@@ -121,7 +121,7 @@ public class AliPayUtil {
* 功能描述 查询订单
* @param outTradeNo
*/
public AlipayTradeQueryResponse getAliPayOrder(String outTradeNo) {
public AlipayTradeQueryResponse getAliPayOrder(String outTradeNo,String mchName) {
log.info(">>>>>>>>>查询支付宝订单 订单号 = {}", outTradeNo);
Map map = new HashMap();
AlipayTradeQueryRequest request = new AlipayTradeQueryRequest();
@@ -130,7 +130,7 @@ public class AliPayUtil {
request.setBizModel(model);
AlipayTradeQueryResponse response = null;
try {
response = AliPayConfig.getAliPayClient().execute(request);
response = AliPayConfig.getAliPayClient(mchName).execute(request);
return response;
} catch (Exception e) {
log.info(">>>>>>>>>>查询订单出现异常 exception = {}", e);

View File

@@ -54,4 +54,6 @@ public class AlipayDTO {
private String customerId;
private String relevanceoid;
private String mchName;//商户名 ""为默认商户号,"ls"为灵枢商户
}

View File

@@ -40,4 +40,6 @@ public class ReFundDTO {
*/
private String outRequestNo;
private String mchName;//商户名 ""为默认商户号,"ls"为灵枢商户
}

View File

@@ -87,6 +87,15 @@ public class AliPayServiceImpl implements AliPayService {
@Override
public String pay(AlipayDTO payDto) {
Integer type = payDto.getType();
//培训班订单用灵枢商户收款
BuyOrder buyOrder = buyOrderService.getOne(new LambdaQueryWrapper<BuyOrder>()
.eq(BuyOrder::getOrderSn,payDto.getRelevanceoid()));
String mchName = "";
if (buyOrder != null && "trainingClass".equals(buyOrder.getOrderType())) {
mchName = "LS";
}
payDto.setMchName(mchName);
String orderInfo = "";
if (type == 1) {
// 走H5请求支付宝支付接口
@@ -98,7 +107,8 @@ public class AliPayServiceImpl implements AliPayService {
if (type == 2) {
// 走APP请求支付宝支付接口
log.info(">>>>>>>>>>App请求支付宝支付接口");
payDto.setOutTradeNo(OrderUtils.getOrderCode(Integer.valueOf(payDto.getCustomerId())));
// payDto.setOutTradeNo(OrderUtils.getOrderCode(Integer.valueOf(payDto.getCustomerId())));
payDto.setOutTradeNo(payDto.getRelevanceoid());
Map<String, Object> map = aliPayUtil.aliPayOrder(payDto);
Object obj = map.get("msg");
String resJson = obj.toString();
@@ -136,7 +146,13 @@ public class AliPayServiceImpl implements AliPayService {
log.info(">>>>>>>>>>支付宝回调 sign = {}, trade_status = {}, out_trade_no = {}, 参数 = {}", params.get("sign"),
params.get("trade_status"), params.get("out_trade_no"), params.toString());
//调用SDK验证签名验证是阿里回调而不是其他恶意回调
boolean flag = AlipaySignature.rsaCheckV1(params, AliPayConfig.HS_ALIPAY_PUBLIC_KEY, AliPayConfig.CHARSET, AliPayConfig.SIGN_TYPE);
BuyOrder buyOrder = buyOrderService.getOne(new LambdaQueryWrapper<BuyOrder>()
.eq(BuyOrder::getOrderSn,params.get("out_trade_no")));
String alipayPublicKey = AliPayConfig.HS_ALIPAY_PUBLIC_KEY;
if (buyOrder != null && "trainingClass".equals(buyOrder.getOrderType())) {
alipayPublicKey = AliPayConfig.LS_ALIPAY_PUBLIC_KEY;
}
boolean flag = AlipaySignature.rsaCheckV1(params, alipayPublicKey, AliPayConfig.CHARSET, AliPayConfig.SIGN_TYPE);
// log.error(">>>>>>>>>>验签结果 flag = {}", flag);
if (flag) {
log.info(">>>>>>>>>>验签通过");
@@ -380,6 +396,13 @@ public class AliPayServiceImpl implements AliPayService {
reFundDTO.setRefundAmount(new BigDecimal(params.get("refundFee").toString()));
// reFundDTO.setOutRequestNo(params.get("outRequestNo").toString());
reFundDTO.setOutRequestNo(UUID.randomUUID().toString());
BuyOrder buyOrder = buyOrderService.getOne(new LambdaQueryWrapper<BuyOrder>()
.eq(BuyOrder::getOrderSn,params.get("orderSn")));
String mchName = "";
if (buyOrder != null && "trainingClass".equals(buyOrder.getOrderType())) {
mchName = "LS";
}
reFundDTO.setMchName(mchName);
Map<String, Object> map = aliPayUtil.aliPayRefund(reFundDTO);
Object obj = map.get("msg");
String resJson = obj.toString();

View File

@@ -51,76 +51,60 @@ public class WechatPayConfig implements Serializable {
private String xlkjappId;
@Value("${wxpay.thyyappId}")
private String thyyappId;
/**
* 商户号
*/
@Value("${wxpay.mchId}")
private String mchId;
private String mchId;//商户号
@Value("${wxpay.serialNo}")
private String serialNo;//api证书序列号
@Value("${wxpay.apiV3Key}")
private String apiV3Key;//与灵枢相同
@Value("${wxpay.keyPemPath}")
private String keyPemPath;
@Value("${wxpay.privateKeyUrl}")
private String privateKeyUrl;
@Value("${wxpay.wechatPayCertificateUrl}")
private String wechatPayCertificateUrl;//平台证书,写命令获取
@Value("${wxpay.notifyUrl}")
private String notifyUrl;//付款回调
@Value("${wxpay.refundNotifyUrl}")
private String refundNotifyUrl;//退款回调
//灵枢
@Value("${wxpay.lsMchId}")
private String lsMchId;
@Value("${wxpay.lsSerialNo}")
private String lsSerialNo;
@Value("${wxpay.lsApiV3Key}")
private String lsApiV3Key;//与众妙相同
@Value("${wxpay.lsKeyPemPath}")
private String lsKeyPemPath;
@Value("${wxpay.lsPrivateKeyUrl}")
private String lsPrivateKeyUrl;
@Value("${wxpay.lsWechatPayCertificateUrl}")
private String lsWechatPayCertificateUrl;
@Value("${wxpay.lsNotifyUrl}")
private String lsNotifyUrl;
@Value("${wxpay.lsRefundNotifyUrl}")
private String lsRefundNotifyUrl;
/**
* pay url
*/
@Value("${wxpay.payUrl}")
private String payUrl;
/**
* pay url
* 退款 url
*/
@Value("${wxpay.refundUrl}")
private String refundUrl;
/**
* 回调地址
*/
@Value("${wxpay.notifyUrl}")
private String notifyUrl;
/**
* key
*/
@Value("${wxpay.apiV3Key}")
private String apiV3Key;
/**
* 退款回调地址
*/
@Value("${wxpay.refundNotifyUrl}")
private String refundNotifyUrl;
/**
* API 证书中的 key.pem 商户私钥
*/
@Value("${wxpay.keyPemPath}")
private String keyPemPath;
/**
* 商户序列号
*/
@Value("${wxpay.serialNo}")
private String serialNo;
@Value("${wxpay.wechatPayCertificateUrl}")
private String wechatPayCertificateUrl;
@Value("${wxpay.privateKeyUrl}")
private String privateKeyUrl;
@Bean
public static PropertySourcesPlaceholderConfigurer propertySourcesPlaceholderConfigurer() {
return new PropertySourcesPlaceholderConfigurer();
}
/**
* 获取私钥
*
* @param keyPemPath
* @return
*/
public PrivateKey getPrivateKey(String keyPemPath) {
try {
return PemUtil.loadPrivateKey(ResourceUtils.getURL(keyPemPath).openStream());
} catch (FileNotFoundException e) {
throw new RuntimeException("私钥文件不存在", e);
} catch (IOException e) {
throw new RuntimeException("私钥文件流失败", e);
}
}
/**
* 获取证书管理器实例 签名验证器
@@ -141,47 +125,38 @@ public class WechatPayConfig implements Serializable {
certificatesManager.putMerchant(mchId, wechatPay2Credentials, apiV3Key.getBytes(StandardCharsets.UTF_8));
return certificatesManager.getVerifier(mchId);
}
@Bean
public Verifier getLSVerifier() throws GeneralSecurityException, IOException, HttpCodeException, NotFoundException {
log.info("获取证书管理器实例");
//获取商户私钥
PrivateKey privateKey = getPrivateKey(lsKeyPemPath);
//私钥签名对象
PrivateKeySigner privateKeySigner = new PrivateKeySigner(lsSerialNo, privateKey);
//身份认证对象
WechatPay2Credentials wechatPay2Credentials = new WechatPay2Credentials(lsMchId, privateKeySigner);
// 使用定时更新的签名验证器,不需要传入证书
CertificatesManager certificatesManager = CertificatesManager.getInstance();
certificatesManager.putMerchant(lsMchId, wechatPay2Credentials, lsApiV3Key.getBytes(StandardCharsets.UTF_8));
return certificatesManager.getVerifier(lsMchId);
}
/**
* 获取支付http请求对象
* 获取私钥
*
* @param verifier
* @param keyPemPath
* @return
*/
@Bean(name = "wxPayClient")
public CloseableHttpClient getWxPayClient(Verifier verifier) {
log.info("获取HttpClient");
//获取商户私钥
PrivateKey privateKey = getPrivateKey(keyPemPath);
WechatPayHttpClientBuilder builder = WechatPayHttpClientBuilder.create()
.withMerchant(mchId, serialNo, privateKey)
.withValidator(new WechatPay2Validator(verifier));
CloseableHttpClient httpClient = builder.build();
// 通过WechatPayHttpClientBuilder构造的HttpClient会自动的处理签名和验签并进行证书自动更新
return httpClient;
public PrivateKey getPrivateKey(String keyPemPath) {
try {
return PemUtil.loadPrivateKey(ResourceUtils.getURL(keyPemPath).openStream());
} catch (FileNotFoundException e) {
throw new RuntimeException("私钥文件不存在", e);
} catch (IOException e) {
throw new RuntimeException("私钥文件流失败", e);
}
}
/**
* 获取HttpClient无需进行应答签名验证跳过验签的流程
*/
public CloseableHttpClient getWxPayNoSignClient() {
PrivateKey privateKey = getPrivateKey(keyPemPath);
//用于构造HttpClient
WechatPayHttpClientBuilder builder = WechatPayHttpClientBuilder.create()
//设置商户信息
.withMerchant(mchId, serialNo, privateKey)
//无需进行签名验证、通过withValidator((response) -> true)实现
.withValidator((response) -> true);
// 通过WechatPayHttpClientBuilder构造的HttpClient会自动的处理签名和验签并进行证书自动更新
return builder.build();
}
}

View File

@@ -80,7 +80,7 @@ public class WeChatPayController {
map.put("noncestr", nonceStr);
map.put("package", "Sign=WXPay");
paramMap.put("mchid", wechatPayConfig.getMchId());
if ("trainingClass".equals(paymentInfo.getOrderType())){
if ("trainingClass".equals(order.getOrderType())){
paramMap.put("mchid", wechatPayConfig.getLsMchId());
}
QueryWrapper<PayWechatOrderEntity> wechatOrderQueryWrapper = new QueryWrapper<>();
@@ -90,7 +90,12 @@ public class WeChatPayController {
map.put("prepayid", prepayId);
long timestamp = System.currentTimeMillis() / 1000;
map.put("timestamp", timestamp);
String sign = wxPayUtil.getSign(appid, timestamp, nonceStr, prepayId);
String sign = "";
if ("trainingClass".equals(order.getOrderType())){
sign = wxPayUtil.getSign(appid, timestamp, nonceStr, prepayId, "LS");
}else {
sign = wxPayUtil.getSign(appid, timestamp, nonceStr, prepayId, "");
}
map.put("sign", sign);
Map<String, Object> result = new HashMap<>();
result.put("paramMap", paramMap);
@@ -110,6 +115,11 @@ public class WeChatPayController {
public void payNotify(HttpServletRequest request, HttpServletResponse response) throws Exception {
wxpayService.payNotify(request);
}
@PostMapping("/lsPayNotify")
@Transactional
public void lsPayNotify(HttpServletRequest request, HttpServletResponse response) throws Exception {
wxpayService.lsPayNotify(request);
}
/**
* 微信退款申请
@@ -127,6 +137,10 @@ public class WeChatPayController {
public void refundNotify(HttpServletRequest request){
wxpayService.refundNotify(request);
}
@PostMapping("/lsRefundNotify")
public void lsRefundNotify(HttpServletRequest request){
wxpayService.lsRefundNotify(request);
}

View File

@@ -15,8 +15,12 @@ public interface WxpayService extends IService<PayWechatOrderEntity> {
void payNotify(HttpServletRequest request) throws Exception;
void lsPayNotify(HttpServletRequest request) throws Exception;
String refund(Map<String,Object> map);
void refundNotify(HttpServletRequest request);
void lsRefundNotify(HttpServletRequest request);
}

View File

@@ -109,15 +109,16 @@ public class WxpayServiceImpl extends ServiceImpl<PayWechatOrderDao, PayWechatOr
paramMap.put("appid", appid);
// 商户 id
paramMap.put("mchid", wechatPayConfig.getMchId());
if ("trainingClass".equals(paymentInfo.getOrderType())){
paramMap.put("mchid", wechatPayConfig.getLsMchId());
}
// 描述
paramMap.put("description", "微信支付");
// 订单编号
paramMap.put("out_trade_no", paymentInfo.getOrderSn());
// 微信回调地址
paramMap.put("notify_url", wechatPayConfig.getNotifyUrl());
if ("trainingClass".equals(paymentInfo.getOrderType())){
paramMap.put("mchid", wechatPayConfig.getLsMchId());
paramMap.put("notify_url", wechatPayConfig.getLsNotifyUrl());
}
BigDecimal totalAmount = paymentInfo.getTotalAmount();
// 这里 * 100 单位为 ‘分’
BigDecimal hand = new BigDecimal("100");
@@ -129,7 +130,12 @@ public class WxpayServiceImpl extends ServiceImpl<PayWechatOrderDao, PayWechatOr
JSONObject json = JSONObject.parseObject(JSON.toJSONString(paramMap));
log.info("请求参数:{}", paramMap);
JSONObject responseJson = wxPayUtil.doPostWexinV3(wechatPayConfig.getPayUrl(), json.toJSONString());
JSONObject responseJson = null;
if ("trainingClass".equals(paymentInfo.getOrderType())){
responseJson = wxPayUtil.doPostWexinV3(wechatPayConfig.getPayUrl(), json.toJSONString(),"LS");
}else {
responseJson = wxPayUtil.doPostWexinV3(wechatPayConfig.getPayUrl(), json.toJSONString(),"");
}
String prepayId = responseJson.getString("prepay_id");
if (paymentInfo.getBuyOrderId() == null) {
payWechatOrderService.add(paymentInfo.getOrderSn(), prepayId);
@@ -144,7 +150,7 @@ public class WxpayServiceImpl extends ServiceImpl<PayWechatOrderDao, PayWechatOr
public void payNotify(HttpServletRequest request) throws Exception {
log.info("微信支付回调");
// 处理通知参数
Map<String, Object> bodyMap = getNotifyBody(request);
Map<String, Object> bodyMap = getNotifyBody(request,"");
// 解密resource中的通知数据
String resource = bodyMap.get("resource").toString();
Map<String, Object> resourceMap = WechatPayValidator.decryptFromResource(resource, wechatPayConfig.getApiV3Key(), 1);
@@ -342,6 +348,45 @@ public class WxpayServiceImpl extends ServiceImpl<PayWechatOrderDao, PayWechatOr
}
}
@Override
@Transactional
public void lsPayNotify(HttpServletRequest request) throws Exception {
log.info("微信支付回调");
// 处理通知参数
Map<String, Object> bodyMap = getNotifyBody(request,"LS");
// 解密resource中的通知数据
String resource = bodyMap.get("resource").toString();
Map<String, Object> resourceMap = WechatPayValidator.decryptFromResource(resource, wechatPayConfig.getApiV3Key(), 1);
String orderNo = resourceMap.get("out_trade_no").toString();
//修改微信订单表
MPJLambdaWrapper<PayWechatOrderEntity> wrapper = new MPJLambdaWrapper();
wrapper.eq(PayWechatOrderEntity::getOrderSn,orderNo);
PayWechatOrderEntity payWechatOrderEntity = payWechatOrderService.getOne(wrapper);
payWechatOrderEntity.setOrderId(resourceMap.get("transaction_id").toString());
payWechatOrderService.updateById(payWechatOrderEntity);
// 根据订单号,做幂等处理,并且在对业务数据进行状态检查和处理之前,要采用数据锁进行并发控制,以避免函数重入造成的数据混乱
BuyOrder order = this.buyOrderService.getOne(new QueryWrapper<BuyOrder>().eq("order_sn", orderNo));
if ("3".equals(order.getOrderStatus())){
return;
}
//使用优惠券
if (order.getCouponId()!=null&&order.getCouponId()!=0){
CouponHistory couponHistory = couponHistoryService.getById(order.getCouponId());
couponHistory.setOrderId(order.getOrderId());
couponService.useCouponAmount(couponHistory);
}
//处理抵扣积分
if(order.getJfDeduction().compareTo(BigDecimal.ZERO)>0){
userCoinJf(order);
}
if("trainingClass".equals(order.getOrderType())){
//更新 订单 记录
buyOrderService.updateOrderStatus(order.getUserId(),orderNo,"2");
//插入培训班
trainingClassService.addTrainingClassForUser(order);
}
}
@Override
public String refund(Map<String,Object> map){
LambdaQueryWrapper<PayWechatOrderEntity> wrapper = new LambdaQueryWrapper();
@@ -372,7 +417,14 @@ public class WxpayServiceImpl extends ServiceImpl<PayWechatOrderDao, PayWechatOr
JSONObject json = JSONObject.parseObject(JSON.toJSONString(paramMap));
log.info("微信退款申请请求参数:{}", paramMap);
log.info(">>>>>>>>>>App请求微信退款申请接口");
JSONObject responseJson = wxPayUtil.doPostWexinV3(wechatPayConfig.getRefundUrl(), json.toJSONString());
//培训班订单用灵枢商户收款
BuyOrder buyOrder = buyOrderService.getOne(new LambdaQueryWrapper<BuyOrder>()
.eq(BuyOrder::getOrderSn,map.get("orderSn").toString()));
String mchName = "";
if (buyOrder != null && "trainingClass".equals(buyOrder.getOrderType())) {
mchName = "LS";
}
JSONObject responseJson = wxPayUtil.doPostWexinV3(wechatPayConfig.getRefundUrl(), json.toJSONString(),mchName);
log.info(">>>>>>>>>>>微信退款返回的信息是 resJson = {}", responseJson.toJSONString());
if ("SUCCESS".equals(responseJson.get("status"))){
//退款申请成功,等待到账
@@ -399,7 +451,34 @@ public class WxpayServiceImpl extends ServiceImpl<PayWechatOrderDao, PayWechatOr
public void refundNotify(HttpServletRequest request){
log.info("微信退款回调");
// 处理通知参数
Map<String, Object> bodyMap = getNotifyBody(request);
Map<String, Object> bodyMap = getNotifyBody(request,"");
// 解密resource中的通知数据
String resource = bodyMap.get("resource").toString();
Map<String, Object> resourceMap = WechatPayValidator.decryptFromResource(resource, wechatPayConfig.getApiV3Key(), 2);
log.info("微信退款回调结果 msg={}",resourceMap);
if ("SUCCESS".equals(resourceMap.get("refund_status").toString())){
log.info(">>>>>>>>>>>微信退款成功!<<<<<<<<<<<<<");
MPJLambdaWrapper<BuyOrder> w = new MPJLambdaWrapper();
w.selectAll(BuyOrder.class);
w.leftJoin(PayWechatOrderEntity.class,PayWechatOrderEntity::getOrderSn, BuyOrder::getOrderSn);
w.eq("t1.order_id",resourceMap.get("transaction_id").toString());
BuyOrder order = buyOrderService.getOne(w);
PayRefundOrder refund = new PayRefundOrder();
refund.setPayType("1");
refund.setOrderId(order.getOrderId());
refund.setTradeNo(resourceMap.get("transaction_id").toString());
refund.setOutTradeNo(resourceMap.get("out_trade_no").toString());
refund.setRefundFee(((Map)resourceMap.get("amount")).get("refund").toString());
refundOrderService.save(refund);
refundOrderService.businessOpt(order);
}
}
@Override
@Transactional
public void lsRefundNotify(HttpServletRequest request){
log.info("微信退款回调");
// 处理通知参数
Map<String, Object> bodyMap = getNotifyBody(request,"LS");
// 解密resource中的通知数据
String resource = bodyMap.get("resource").toString();
Map<String, Object> resourceMap = WechatPayValidator.decryptFromResource(resource, wechatPayConfig.getApiV3Key(), 2);
@@ -423,7 +502,7 @@ public class WxpayServiceImpl extends ServiceImpl<PayWechatOrderDao, PayWechatOr
}
private Map<String, Object> getNotifyBody(HttpServletRequest request) {
private Map<String, Object> getNotifyBody(HttpServletRequest request,String mchName) {
// 处理通知参数
String body = HttpUtils.readData(request);
log.info("支付回调参数:{}", body);
@@ -434,7 +513,12 @@ public class WxpayServiceImpl extends ServiceImpl<PayWechatOrderDao, PayWechatOr
String notifyId = bodyMap.get("id").toString();
// 验证签名信息
try {
WechatPayValidator wechatPayValidator = new WechatPayValidator(wechatPayConfig.getVerifier(), notifyId, body);
WechatPayValidator wechatPayValidator = null;
if ("LS".equals(mchName)) {
wechatPayValidator = new WechatPayValidator(wechatPayConfig.getLSVerifier(), notifyId, body);
}else{
wechatPayValidator = new WechatPayValidator(wechatPayConfig.getVerifier(), notifyId, body);
}
if (!wechatPayValidator.validate(request)) {
log.error("通知验签失败");
return null;

View File

@@ -32,15 +32,24 @@ public class WxPayUtil {
private CloseableHttpClient httpClient;
public void setup() {
public void setup(String mchName) {
PrivateKey merchantPrivateKey = null;
X509Certificate wechatPayCertificate = null;
String privateKeyUrl = wechatPayConfig.getPrivateKeyUrl();
String wechatPayCertificateUrl = wechatPayConfig.getWechatPayCertificateUrl();
String mchId = wechatPayConfig.getMchId();
String serialNo = wechatPayConfig.getSerialNo();
if ("LS".equals(mchName)) {
privateKeyUrl = wechatPayConfig.getLsPrivateKeyUrl();
wechatPayCertificateUrl = wechatPayConfig.getLsWechatPayCertificateUrl();
mchId = wechatPayConfig.getLsMchId();
serialNo = wechatPayConfig.getLsSerialNo();
}
try {
merchantPrivateKey = PemUtil.loadPrivateKey(
new FileInputStream(wechatPayConfig.getPrivateKeyUrl()));
new FileInputStream(privateKeyUrl));
wechatPayCertificate = PemUtil.loadCertificate(
new FileInputStream(wechatPayConfig.getWechatPayCertificateUrl()));
new FileInputStream(wechatPayCertificateUrl));
} catch (FileNotFoundException e) {
e.printStackTrace();
@@ -50,7 +59,7 @@ public class WxPayUtil {
listCertificates.add(wechatPayCertificate);
WechatPayHttpClientBuilder builder = WechatPayHttpClientBuilder.create()
.withMerchant(wechatPayConfig.getMchId(), wechatPayConfig.getSerialNo(), merchantPrivateKey)
.withMerchant(mchId, serialNo, merchantPrivateKey)
.withWechatPay(listCertificates);
httpClient = builder.build();
}
@@ -63,11 +72,8 @@ public class WxPayUtil {
* url 下单地址
* body 构造好的消息体
*/
public JSONObject doPostWexinV3(String url, String body) {
if (httpClient == null) {
setup();
}
public JSONObject doPostWexinV3(String url, String body, String mchName) {
setup(mchName);
HttpPost httpPost = new HttpPost(url);
httpPost.addHeader("Content-Type", "application/json;chartset=utf-8");
httpPost.addHeader("Accept", "application/json");
@@ -96,11 +102,11 @@ public class WxPayUtil {
}
//获取签名
public String getSign(String appId, long timestamp, String nonceStr, String pack) {
public String getSign(String appId, long timestamp, String nonceStr, String pack,String mchName) {
String message = buildMessage(appId, timestamp, nonceStr, pack);
String paySign = null;
try {
paySign = sign(message.getBytes("utf-8"));
paySign = sign(message.getBytes("utf-8"),mchName);
} catch (Exception e) {
e.printStackTrace();
}
@@ -114,16 +120,20 @@ public class WxPayUtil {
+ pack + "\n";
}
private String sign(byte[] message) throws Exception {
private String sign(byte[] message,String mchName) throws Exception {
PrivateKey merchantPrivateKey = null;
X509Certificate wechatPayCertificate = null;
String privateKeyUrl = wechatPayConfig.getPrivateKeyUrl();
String wechatPayCertificateUrl = wechatPayConfig.getWechatPayCertificateUrl();
if ("LS".equals(mchName)) {
privateKeyUrl = wechatPayConfig.getLsPrivateKeyUrl();
wechatPayCertificateUrl = wechatPayConfig.getLsWechatPayCertificateUrl();
}
try {
merchantPrivateKey = PemUtil.loadPrivateKey(
new FileInputStream(wechatPayConfig.getPrivateKeyUrl()));
new FileInputStream(privateKeyUrl));
wechatPayCertificate = PemUtil.loadCertificate(
new FileInputStream(wechatPayConfig.getWechatPayCertificateUrl()));
new FileInputStream(wechatPayCertificateUrl));
} catch (FileNotFoundException e) {
e.printStackTrace();
}

View File

@@ -94,19 +94,27 @@ wxpay:
wumenappId: wx6b17b40171dea988
xlkjappId: wxd6bfeec65bc7abee
thyyappId: wx5c50e3696028d2ec
#众妙商户号
mchId: 1612860909
#灵枢商户号
lsMchId: 1612860909
payUrl: https://api.mch.weixin.qq.com/v3/pay/transactions/app
notifyUrl: http://c6f94c98.natappfree.cc/pb/pay/payNotify
refundUrl: https://api.mch.weixin.qq.com/v3/refund/domestic/refunds
refundNotifyUrl: https://testapi.nuttyreading.com/pay/refundNotify
keyPemPath: F:\ideaProject\peanutBook\src\main\resources\cent\apiclient_key.pem
serialNo: 679AECB2F7AC4183033F713828892BA640E4EEE3
apiV3Key: 4aYFklzaULeGlr7oJPZ6rHWKcxjihZUF
wechatPayCertificateUrl: F:\ideaProject\peanutBook\src\main\resources\cent\wechatpay_7B5676E3CDF56680D0414A009CE501C844DBE2D6.pem
privateKeyUrl: F:\ideaProject\peanutBook\src\main\resources\cent\apiclient_key.pem
keyPemPath: F:\ideaProject\peanutBook\src\main\resources\cent\apiclient_key.pem
notifyUrl: http://z6f8f828.natappfree.cc/pb/pay/payNotify
refundNotifyUrl: https://testapi.nuttyreading.com/pay/refundNotify
#灵枢商户号
lsMchId: 1700371158
lsSerialNo: 3132D23C3130B74B87890DC6E7C80256C75113B9
lsApiV3Key: 4aYFklzaULeGlr7oJPZ6rHWKcxjihZUF
lsWechatPayCertificateUrl: F:\ideaProject\peanutBook\src\main\resources\cent\lscent\wechatpay_30CFE19A12EDB4D9E0C7DF01DBF457C657566D04.pem
lsPrivateKeyUrl: F:\ideaProject\peanutBook\src\main\resources\cent\lscent\apiclient_key.pem
lsKeyPemPath: F:\ideaProject\peanutBook\src\main\resources\cent\lscent\apiclient_key.pem
lsNotifyUrl: http://z6f8f828.natappfree.cc/pb/pay/lsPayNotify
lsRefundNotifyUrl: https://testapi.nuttyreading.com/pay/refundNotify
payUrl: https://api.mch.weixin.qq.com/v3/pay/transactions/app
refundUrl: https://api.mch.weixin.qq.com/v3/refund/domestic/refunds
redisAddress: redis://47.93.127.115:6379
redisPassword: Jgll2015

View File

@@ -94,16 +94,27 @@ wxpay:
wumenappId: wx6b17b40171dea988
xlkjappId: wxd6bfeec65bc7abee
thyyappId: wx5c50e3696028d2ec
#众妙商户号
mchId: 1612860909
payUrl: https://api.mch.weixin.qq.com/v3/pay/transactions/app
notifyUrl: https://testapi.nuttyreading.com/pay/payNotify
refundUrl: https://api.mch.weixin.qq.com/v3/refund/domestic/refunds
refundNotifyUrl: https://testapi.nuttyreading.com/pay/refundNotify
keyPemPath: F:\hs\nuttyreading-java\src\main\resources\cent\apiclient_key.pem
serialNo: 679AECB2F7AC4183033F713828892BA640E4EEE3
apiV3Key: 4aYFklzaULeGlr7oJPZ6rHWKcxjihZUF
wechatPayCertificateUrl: F:\hs\nuttyreading-java\src\main\resources\cent\wechatpay_7B5676E3CDF56680D0414A009CE501C844DBE2D6.pem
privateKeyUrl: F:\hs\nuttyreading-java\src\main\resources\cent\apiclient_key.pem
keyPemPath: F:\hs\nuttyreading-java\src\main\resources\cent\apiclient_key.pem
notifyUrl: http://z6f8f828.natappfree.cc/pb/pay/payNotify
refundNotifyUrl: https://testapi.nuttyreading.com/pay/refundNotify
#灵枢商户号
lsMchId: 1700371158
lsSerialNo: 3132D23C3130B74B87890DC6E7C80256C75113B9
lsApiV3Key: 4aYFklzaULeGlr7oJPZ6rHWKcxjihZUF
lsWechatPayCertificateUrl: F:\hs\nuttyreading-java\src\main\resources\cent\lscent\wechatpay_30CFE19A12EDB4D9E0C7DF01DBF457C657566D04.pem
lsPrivateKeyUrl: F:\hs\nuttyreading-java\src\main\resources\cent\lscent\apiclient_key.pem
lsKeyPemPath: F:\hs\nuttyreading-java\src\main\resources\cent\lscent\apiclient_key.pem
lsNotifyUrl: http://z6f8f828.natappfree.cc/pb/pay/lsPayNotify
lsRefundNotifyUrl: https://testapi.nuttyreading.com/pay/refundNotify
payUrl: https://api.mch.weixin.qq.com/v3/pay/transactions/app
refundUrl: https://api.mch.weixin.qq.com/v3/refund/domestic/refunds
#redisAddress: redis://127.0.0.1:6379

View File

@@ -92,20 +92,27 @@ wxpay:
wumenappId: wx6b17b40171dea988
xlkjappId: wxd6bfeec65bc7abee
thyyappId: wx5c50e3696028d2ec
#众妙商户号
mchId: 1612860909
#灵枢商户号
lsMchId: 1612860909
payUrl: https://api.mch.weixin.qq.com/v3/pay/transactions/app
notifyUrl: https://api.nuttyreading.com/pay/payNotify
refundUrl: https://api.mch.weixin.qq.com/v3/refund/domestic/refunds
refundNotifyUrl: http://pjm6m9.natappfree.cc/pay/refundNotify
keyPemPath: /usr/local/hs/peanut_book/target/classes/cent/apiclient_key.pem
serialNo: 679AECB2F7AC4183033F713828892BA640E4EEE3
apiV3Key: 4aYFklzaULeGlr7oJPZ6rHWKcxjihZUF
wechatPayCertificateUrl: /usr/local/hs/peanut_book/target/classes/cent/wechatpay_7B5676E3CDF56680D0414A009CE501C844DBE2D6.pem
privateKeyUrl: /usr/local/hs/peanut_book/target/classes/cent/apiclient_key.pem
keyPemPath: /usr/local/hs/peanut_book/target/classes/cent/apiclient_key.pem
notifyUrl: https://api.nuttyreading.com/pay/payNotify
refundNotifyUrl: https://api.nuttyreading.com/pay/refundNotify
#灵枢商户号
lsMchId: 1700371158
lsSerialNo: 3132D23C3130B74B87890DC6E7C80256C75113B9
lsApiV3Key: 4aYFklzaULeGlr7oJPZ6rHWKcxjihZUF
lsWechatPayCertificateUrl: /usr/local/hs/peanut_book/target/classes/cent/lscent/wechatpay_30CFE19A12EDB4D9E0C7DF01DBF457C657566D04.pem
lsPrivateKeyUrl: /usr/local/hs/peanut_book/target/classes/cent/lscent/apiclient_key.pem
lsKeyPemPath: /usr/local/hs/peanut_book/target/classes/cent/lscent/apiclient_key.pem
lsNotifyUrl: https://api.nuttyreading.com/pay/lsPayNotify
lsRefundNotifyUrl: https://api.nuttyreading.com/pay/lsRefundNotify
payUrl: https://api.mch.weixin.qq.com/v3/pay/transactions/app
refundUrl: https://api.mch.weixin.qq.com/v3/refund/domestic/refunds
redisAddress: redis://59.110.212.44:6379
redisPassword: Jgll2015

View File

@@ -93,19 +93,27 @@ wxpay:
wumenappId: wx6b17b40171dea988
xlkjappId: wxd6bfeec65bc7abee
thyyappId: wx5c50e3696028d2ec
#众妙商户号
mchId: 1612860909
payUrl: https://api.mch.weixin.qq.com/v3/pay/transactions/app
notifyUrl: https://testapi.nuttyreading.com/pay/payNotify
refundUrl: https://api.mch.weixin.qq.com/v3/refund/domestic/refunds
refundNotifyUrl: http://pjm6m9.natappfree.cc/pay/refundNotify
# keyPemPath: /usr/local/hs/peanut_book/target/classes/cent/apiclient_key.pem
keyPemPath: /home/www/nuttyreading/cent/apiclient_key.pem
serialNo: 679AECB2F7AC4183033F713828892BA640E4EEE3
apiV3Key: 4aYFklzaULeGlr7oJPZ6rHWKcxjihZUF
wechatPayCertificateUrl: /home/www/nuttyreading/cent/wechatpay_7B5676E3CDF56680D0414A009CE501C844DBE2D6.pem
privateKeyUrl: /home/www/nuttyreading/cent/apiclient_key.pem
keyPemPath: /home/www/nuttyreading/cent/apiclient_key.pem
notifyUrl: https://testapi.nuttyreading.com/pay/payNotify
refundNotifyUrl: https://testapi.nuttyreading.com/pay/refundNotify
#灵枢商户号
lsMchId: 1700371158
lsSerialNo: 3132D23C3130B74B87890DC6E7C80256C75113B9
lsApiV3Key: 4aYFklzaULeGlr7oJPZ6rHWKcxjihZUF
lsWechatPayCertificateUrl: /home/www/nuttyreading/cent/lscent/wechatpay_30CFE19A12EDB4D9E0C7DF01DBF457C657566D04.pem
lsPrivateKeyUrl: /home/www/nuttyreading/cent/lscent/apiclient_key.pem
lsKeyPemPath: /home/www/nuttyreading/cent/lscent/apiclient_key.pem
lsNotifyUrl: https://testapi.nuttyreading.com/pay/lsPayNotify
lsRefundNotifyUrl: https://testapi.nuttyreading.com/pay/lsRefundNotify
payUrl: https://api.mch.weixin.qq.com/v3/pay/transactions/app
refundUrl: https://api.mch.weixin.qq.com/v3/refund/domestic/refunds
redisAddress: redis://47.93.127.115:6379
redisPassword: Jgll2015

Binary file not shown.

View File

@@ -0,0 +1,25 @@
-----BEGIN CERTIFICATE-----
MIIERjCCAy6gAwIBAgIUMTLSPDEwt0uHiQ3G58gCVsdRE7kwDQYJKoZIhvcNAQEL
BQAwXjELMAkGA1UEBhMCQ04xEzARBgNVBAoTClRlbnBheS5jb20xHTAbBgNVBAsT
FFRlbnBheS5jb20gQ0EgQ2VudGVyMRswGQYDVQQDExJUZW5wYXkuY29tIFJvb3Qg
Q0EwHhcNMjUxMDIwMDUxNzQ5WhcNMzAxMDE5MDUxNzQ5WjCBnzETMBEGA1UEAwwK
MTcwMDM3MTE1ODEbMBkGA1UECgwS5b6u5L+h5ZWG5oi357O757ufMUswSQYDVQQL
DELlpKnmtKXluILljZflvIDljLrngbXmnqLmlZnogrLnp5HmioDlt6XkvZzlrqTv
vIjkuKrkvZPlt6XllYbmiLfvvIkxCzAJBgNVBAYTAkNOMREwDwYDVQQHDAhTaGVu
WmhlbjCCASIwDQYJKoZIhvcNAQEBBQADggEPADCCAQoCggEBAKcXnuZX5EIL0kPD
Uw+nUqLEJh4bjYtKcYs1XbSV4+Ej3fSb0qzo+Zo4GK7NGhx13Vkqzvx0xITMS8T1
RhLOIrwib3v7+U+2LwQDAyFwMkmyfGSOGDJRPia4Buv/i+oKwk7+61wFdulrOz7F
Co5KkPIK3H/Iqe5zgrnlcv8TW1ytJBNLJPTsIrPdbtz8bM9ovzemn8VXf9tOkII6
tx4tqpmm+MoSMO9xhK8UdhAPf/xuqR2K8NKdd7JL6XtT6FXfUGznct8VA/9sxUql
fC/v0zDaAzuU2O8R28PSw2Kznc84M59CfGkLF2D8PNaFf5sX0k9dWTJfcdgephaA
XspbNLUCAwEAAaOBuTCBtjAJBgNVHRMEAjAAMAsGA1UdDwQEAwID+DCBmwYDVR0f
BIGTMIGQMIGNoIGKoIGHhoGEaHR0cDovL2V2Y2EuaXRydXMuY29tLmNuL3B1Ymxp
Yy9pdHJ1c2NybD9DQT0xQkQ0MjIwRTUwREJDMDRCMDZBRDM5NzU0OTg0NkMwMUMz
RThFQkQyJnNnPUhBQ0M0NzFCNjU0MjJFMTJCMjdBOUQzM0E4N0FEMUNERjU5MjZF
MTQwMzcxMA0GCSqGSIb3DQEBCwUAA4IBAQAvSYQqMWSbk183gT+uDYhYs+VdzzVn
JOR8hUahHeZAgzvexdScQiUJcUVivRWeEKetN7bPNZ8NX91mmAw0XTR9qLMCphVv
9/6gdi8+tZZF7khJUL9I3wqhOhbOgn/h1wIhQAA/0Pl1RJyhrpNRQbmalDdX82T9
G5JlAKbNNAs/HdMpXY/LvngoF10hjfAvc/WdEYW5OAJgA5Y7LsymKuB01yBe/ptw
8y+hLcV1gk/7IcPpEKGJAkm5tZHSiNwt0NQDu+ik/0E524I1LYuKbJJ/0xj8EH6J
ZLqqS0TztH5B+xZA3rEJTjhLe9Sy9Bp3ILAeApHRh34B4j5bfvYsu2+7
-----END CERTIFICATE-----

View File

@@ -0,0 +1,28 @@
-----BEGIN PRIVATE KEY-----
MIIEvgIBADANBgkqhkiG9w0BAQEFAASCBKgwggSkAgEAAoIBAQCnF57mV+RCC9JD
w1MPp1KixCYeG42LSnGLNV20lePhI930m9Ks6PmaOBiuzRocdd1ZKs78dMSEzEvE
9UYSziK8Im97+/lPti8EAwMhcDJJsnxkjhgyUT4muAbr/4vqCsJO/utcBXbpazs+
xQqOSpDyCtx/yKnuc4K55XL/E1tcrSQTSyT07CKz3W7c/GzPaL83pp/FV3/bTpCC
OrceLaqZpvjKEjDvcYSvFHYQD3/8bqkdivDSnXeyS+l7U+hV31Bs53LfFQP/bMVK
pXwv79Mw2gM7lNjvEdvD0sNis53PODOfQnxpCxdg/DzWhX+bF9JPXVkyX3HYHqYW
gF7KWzS1AgMBAAECggEAIN3hkJd7O46NtmyGOw8DjyacBNIQnnRvLx25J9tP7qoa
b5Hy97X/2tjr6f5IA48fkfl8q2XgfeqdgMlqFirb5Du1yCKBIK/KQbTB+eLS0XI9
S54znjoiyoTqP6ONhuTE4br82qXshO9lwOwLLn/2UNXYF36GBnRMI3rBivDoyKqo
jl8jLF43UuuducjIs38WnAQKR39XnX9fnOu2NQ7Bt/p46BTNNbClRYtlQ0hKcCVC
uCLA1WKAt6NAzjby53h2VDXTDDSB4uvMA9MtksfTdnQuaXPhWqMmPHvDJTchFbYj
y6DiJcM/4EPfkEASs8wO/iWN7mN9uRLvpALx6o5vQQKBgQDRGz3uAdTbDk8oWUOq
IbahVqgtZyThInZrR+PAFR2QEzONI1LhqCeSeT1BA2cNAWLPd9amQHPrsgpJPEnP
L8EM8GQmyOFK2Ro6er8BvthAE12Od9hQal4VSB6/IB3c6OAna02P96gInhGmttz2
AJDG0I6Y77PKpXgKPIOAFBnEhQKBgQDMkFrfJMoxrh25AzSH5A20FsI6nRQJAnYP
fxq19m+hA61AbXXdsjYq4jOxjP6aLFyZS/4bbGJXUBHMELvK5ZbzGrmbH818/SQ7
lTvIqp16U2jwBAN+Hza0/rEk/OUad1k6qEa056NoS2k1qryitS7L50EOi4YtZHu9
QU0zR9p+cQKBgCc7fTsSjOUsoh1n4hIhkSpkH9mk6H51ANLQAiMf0xQdBicM4ZgE
/Ke2p49zG/qMsAVM7rDyls058kQbU53Tz9ylnaTJO7vXT9x4+y1QqTIccAky4xrz
WgOULHCfjfrMloHO2BaS2KwFPDqTRJHDOWaT6q03C/yRXxxMjj+RheQhAoGBAIrc
01L23mqrD3IwQtCcdtDxQhgX2SnkidArMC6lg1GB9XHu3DwKZcrmksDMPWjbBGDr
vStQf9FVgT9NfK1W/Qk58xTimdNm49mujE7DwvLu/CUyFEzhU3m6CvZY1g0JR4ES
Ci1zsPFzf4/2vuaUp5ey++6ruAHIXFc0pPtSo3eBAoGBAMCVpHmJ1Yl6Jd5Wijq/
sFHMy0V12LZL5FtiMrxU2Ha9qJf20peyA+u02uLvi7BuVBFYceLfNg14CFVMekmm
UsljhtDYTegakEINI2qfxWKcZnC933sJxAZE21qQ4MXPIj9+mwQ60xaY7m+9qbZ1
LX6+929u0+9Uok5kFtQv646i
-----END PRIVATE KEY-----

View File

@@ -0,0 +1,24 @@
-----BEGIN CERTIFICATE-----
MIIEFDCCAvygAwIBAgIUMM/hmhLttNngx98B2/RXxldWbQQwDQYJKoZIhvcNAQEL
BQAwXjELMAkGA1UEBhMCQ04xEzARBgNVBAoTClRlbnBheS5jb20xHTAbBgNVBAsT
FFRlbnBheS5jb20gQ0EgQ2VudGVyMRswGQYDVQQDExJUZW5wYXkuY29tIFJvb3Qg
Q0EwHhcNMjUxMDIwMDUxNzQ4WhcNMzAxMDE5MDUxNzQ4WjBuMRgwFgYDVQQDDA9U
ZW5wYXkuY29tIHNpZ24xEzARBgNVBAoMClRlbnBheS5jb20xHTAbBgNVBAsMFFRl
bnBheS5jb20gQ0EgQ2VudGVyMQswCQYDVQQGEwJDTjERMA8GA1UEBwwIU2hlblpo
ZW4wggEiMA0GCSqGSIb3DQEBAQUAA4IBDwAwggEKAoIBAQD2k129wosXUWJcweqi
FhqWPVmdE9sJxyRfAai9at5oLL+4+0UEaTSCCSlBwd9ILJ5IXEGiClKc9eZgMdi2
O0aqISye7KkCu2FlSgZVML3OVP82QLf/eRirxoYjrVQ0W33kpHyjeKV25M4VmHCi
7AmMyGVMX/Pf2HTw4TnGeoLUCR/3nAXUO3SsLtqPGC8M5mOC5p73Qot0Zp1SRuKF
d0zSF9G4iPMDqUvAkgtRRp6DivW9e/v/Or8H9oVg+x6oG/SSo4mK9428m45tcDSd
1FzzTvdpS9ApBLKzYlF9cg1dsIXdt9AypBHj0tQRa3CkBIgxP0chU8luT7VBBpv9
8JB5AgMBAAGjgbkwgbYwCQYDVR0TBAIwADALBgNVHQ8EBAMCA/gwgZsGA1UdHwSB
kzCBkDCBjaCBiqCBh4aBhGh0dHA6Ly9ldmNhLml0cnVzLmNvbS5jbi9wdWJsaWMv
aXRydXNjcmw/Q0E9MUJENDIyMEU1MERCQzA0QjA2QUQzOTc1NDk4NDZDMDFDM0U4
RUJEMiZzZz1IQUNDNDcxQjY1NDIyRTEyQjI3QTlEMzNBODdBRDFDREY1OTI2RTE0
MDM3MTANBgkqhkiG9w0BAQsFAAOCAQEARZTIJ36KOviKGttOhZe+w7k0KknQ67PD
DCseZ64L99lE/V6mOOUFAqI7o2lYlXaPedf1eQOf3UI62fom6CqjvSCeC8QNKVeB
5MLZHwKyMesgLiOEFb8JusgWma8yK0Bo7o0z+7bXxpFPSXoh8ayU6Bkk4CYNRD4u
nWZFeE5IiDshPSHDGG08jlJmKcsuTZVOKGwoVKn9zhpBiesKa0Sfwi5TffBJUUBM
XTJfX0P0E36QXjM3UWqrEFd5trBZwQTuhuc8j3eStmamsQVr6X4HIOstIp5cLGVZ
UrpW1faphcDhgUG5dlTRS27JiJjvNyG2DPOJhAtabU5+dDyJ++pujA==
-----END CERTIFICATE-----

View File

@@ -0,0 +1,18 @@
欢迎使用微信支付!
附件中的三份文件证书pkcs12格式、证书pem格式、证书密钥pem格式,为接口中强制要求时需携带的证书文件。
证书属于敏感信息,请妥善保管不要泄露和被他人复制。
不同开发语言下的证书格式不同,以下为说明指引:
证书pkcs12格式apiclient_cert.p12
包含了私钥信息的证书文件为p12(pfx)格式,由微信支付签发给您用来标识和界定您的身份
部分安全性要求较高的API需要使用该证书来确认您的调用身份
windows上可以直接双击导入系统导入过程中会提示输入证书密码证书密码默认为您的商户号1900006031
证书pem格式apiclient_cert.pem
从apiclient_cert.p12中导出证书部分的文件为pem格式请妥善保管不要泄漏和被他人复制
部分开发语言和环境不能直接使用p12文件而需要使用pem所以为了方便您使用已为您直接提供
您也可以使用openssl命令来自己导出openssl pkcs12 -clcerts -nokeys -in apiclient_cert.p12 -out apiclient_cert.pem
证书密钥pem格式apiclient_key.pem
从apiclient_cert.p12中导出密钥部分的文件为pem格式
部分开发语言和环境不能直接使用p12文件而需要使用pem所以为了方便您使用已为您直接提供
您也可以使用openssl命令来自己导出openssl pkcs12 -nocerts -in apiclient_cert.p12 -out apiclient_key.pem
备注说明:
由于绝大部分操作系统已内置了微信支付服务器证书的根CA证书, 2018年3月6日后, 不再提供CA证书文件rootca.pem下载