parent
32fe7eacfc
commit
a92790886a
@ -0,0 +1,55 @@
|
|||||||
|
package com.luoo.user.config;
|
||||||
|
|
||||||
|
import lombok.Data;
|
||||||
|
import org.springframework.boot.context.properties.ConfigurationProperties;
|
||||||
|
import org.springframework.stereotype.Component;
|
||||||
|
|
||||||
|
@Data
|
||||||
|
@Component
|
||||||
|
@ConfigurationProperties(prefix = "wx.pay")
|
||||||
|
public class WxPayConfig {
|
||||||
|
/**
|
||||||
|
* appId
|
||||||
|
*/
|
||||||
|
private String appId;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 商户号
|
||||||
|
*/
|
||||||
|
private String mchId;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 商户证书序列号
|
||||||
|
*/
|
||||||
|
private String mchSerialNo;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* apiv3密钥
|
||||||
|
*/
|
||||||
|
private String apiV3Key;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 支付回调地址
|
||||||
|
*/
|
||||||
|
private String notifyUrl;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 微信支付请求url
|
||||||
|
*/
|
||||||
|
// private String wxJsapiUrl;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 私钥路径
|
||||||
|
*/
|
||||||
|
private String privateKeyPath;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 商户证书路径
|
||||||
|
*/
|
||||||
|
private String privateCertPath;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 微信平台证书路径
|
||||||
|
*/
|
||||||
|
private String platformCertPath;
|
||||||
|
}
|
@ -0,0 +1,105 @@
|
|||||||
|
package com.luoo.user.service;
|
||||||
|
|
||||||
|
import cn.hutool.json.JSONArray;
|
||||||
|
import cn.hutool.json.JSONObject;
|
||||||
|
import cn.hutool.json.JSONUtil;
|
||||||
|
import com.ijpay.core.IJPayHttpResponse;
|
||||||
|
import com.ijpay.core.enums.RequestMethodEnum;
|
||||||
|
import com.ijpay.core.kit.AesUtil;
|
||||||
|
import com.ijpay.core.kit.PayKit;
|
||||||
|
import com.ijpay.core.kit.WxPayKit;
|
||||||
|
import com.ijpay.wxpay.WxPayApi;
|
||||||
|
import com.ijpay.wxpay.enums.WxDomainEnum;
|
||||||
|
import com.ijpay.wxpay.enums.v3.OtherApiEnum;
|
||||||
|
import com.luoo.user.config.WxPayConfig;
|
||||||
|
import lombok.extern.slf4j.Slf4j;
|
||||||
|
import org.springframework.stereotype.Service;
|
||||||
|
|
||||||
|
import javax.annotation.Resource;
|
||||||
|
import java.io.ByteArrayInputStream;
|
||||||
|
import java.io.FileWriter;
|
||||||
|
import java.nio.charset.StandardCharsets;
|
||||||
|
import java.security.cert.X509Certificate;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @program: luoo_parent
|
||||||
|
* @description:
|
||||||
|
* @author: yawei.huang
|
||||||
|
* @create: 2024-11-12 12:00
|
||||||
|
**/
|
||||||
|
@Slf4j
|
||||||
|
@Service
|
||||||
|
public class WxPayService {
|
||||||
|
|
||||||
|
@Resource
|
||||||
|
private WxPayConfig wxPayConfig;
|
||||||
|
|
||||||
|
public void v3Get() {
|
||||||
|
// 获取平台证书列表
|
||||||
|
try {
|
||||||
|
IJPayHttpResponse response = WxPayApi.v3(
|
||||||
|
RequestMethodEnum.GET,
|
||||||
|
WxDomainEnum.CHINA.toString(),
|
||||||
|
OtherApiEnum.GET_CERTIFICATES.toString(),
|
||||||
|
wxPayConfig.getMchId(),
|
||||||
|
wxPayConfig.getMchSerialNo(),
|
||||||
|
null,
|
||||||
|
wxPayConfig.getPrivateKeyPath(),
|
||||||
|
""
|
||||||
|
);
|
||||||
|
|
||||||
|
String timestamp = response.getHeader("Wechatpay-Timestamp");
|
||||||
|
String nonceStr = response.getHeader("Wechatpay-Nonce");
|
||||||
|
String serialNumber = response.getHeader("Wechatpay-Serial");
|
||||||
|
String signature = response.getHeader("Wechatpay-Signature");
|
||||||
|
|
||||||
|
String body = response.getBody();
|
||||||
|
int status = response.getStatus();
|
||||||
|
|
||||||
|
log.info("serialNumber: {}", serialNumber);
|
||||||
|
log.info("status: {}", status);
|
||||||
|
log.info("body: {}", body);
|
||||||
|
if (status == 200) {
|
||||||
|
JSONObject jsonObject = JSONUtil.parseObj(body);
|
||||||
|
JSONArray dataArray = jsonObject.getJSONArray("data");
|
||||||
|
// 默认认为只有一个平台证书
|
||||||
|
JSONObject encryptObject = dataArray.getJSONObject(0);
|
||||||
|
JSONObject encryptCertificate = encryptObject.getJSONObject("encrypt_certificate");
|
||||||
|
String associatedData = encryptCertificate.getStr("associated_data");
|
||||||
|
String cipherText = encryptCertificate.getStr("ciphertext");
|
||||||
|
String nonce = encryptCertificate.getStr("nonce");
|
||||||
|
String serialNo = encryptObject.getStr("serial_no");
|
||||||
|
final String platSerialNo = savePlatformCert(associatedData, nonce, cipherText, wxPayConfig.getPlatformCertPath());
|
||||||
|
log.info("平台证书序列号: {} serialNo: {}", platSerialNo, serialNo);
|
||||||
|
}
|
||||||
|
// 根据证书序列号查询对应的证书来验证签名结果
|
||||||
|
boolean verifySignature = WxPayKit.verifySignature(response, wxPayConfig.getPlatformCertPath());
|
||||||
|
System.out.println("verifySignature:" + verifySignature);
|
||||||
|
} catch (Exception e) {
|
||||||
|
e.printStackTrace();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private String savePlatformCert(String associatedData, String nonce, String cipherText, String certPath) {
|
||||||
|
try {
|
||||||
|
AesUtil aesUtil = new AesUtil(wxPayConfig.getApiV3Key().getBytes(StandardCharsets.UTF_8));
|
||||||
|
// 平台证书密文解密
|
||||||
|
// encrypt_certificate 中的 associated_data nonce ciphertext
|
||||||
|
String publicKey = aesUtil.decryptToString(
|
||||||
|
associatedData.getBytes(StandardCharsets.UTF_8),
|
||||||
|
nonce.getBytes(StandardCharsets.UTF_8),
|
||||||
|
cipherText
|
||||||
|
);
|
||||||
|
// 保存证书
|
||||||
|
FileWriter writer = new FileWriter(certPath);
|
||||||
|
writer.write(publicKey);
|
||||||
|
writer.close();
|
||||||
|
// 获取平台证书序列号
|
||||||
|
X509Certificate certificate = PayKit.getCertificate(new ByteArrayInputStream(publicKey.getBytes()));
|
||||||
|
return certificate.getSerialNumber().toString(16).toUpperCase();
|
||||||
|
} catch (Exception e) {
|
||||||
|
e.printStackTrace();
|
||||||
|
return e.getMessage();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
Loading…
Reference in new issue