최근 WeChat 결제에 어려움을 겪고 있는데 인증서가 여전히 꽤 짜증스럽기 때문에 WeChat 결제를 개발할 때 함정을 줄이기 위해 몇 가지 경험을 공유해야 합니다. 현재 WeChat 결제 API는 대중적인 Restful 스타일을 채택하여 V3 버전으로 개발되었습니다.
오늘은 WeChat 결제 - Signature의 어려움을 공유하겠습니다. 유용한 SDK가 많지만 WeChat 결제를 깊이 이해하려면 그래도 이해해야 합니다.
민감한 금융 데이터의 보안을 보장하고 비즈니스의 금융 거래가 완벽하게 이루어지도록 보장합니다. 현재 위챗페이는 제3자가 발급한 신뢰할 수 있는 CA 인증서(API 인증서)에서 제공하는 개인 키를 서명용으로 사용하고 있습니다. 판매자 플랫폼을 통해 API 인증서를 설정하고 얻을 수 있습니다.
처음 설정할 때 다운로드하라는 메시지가 표시된다는 점을 기억하세요. 자세한 내용은 더 이상 다운로드가 제공되지 않습니다.
설정 후 zip
压缩包解压,里面有很多文件,对于JAVA开发来说只需要关注apiclient_cert.p12
这个证书文件就行了,它包含了公私钥
,我们需要把它放在服务端并利用Java解析.p12
파일을 찾아 공개키와 개인키를 받으세요.
금융적인 보안과 관련된 서버 측 인증서의 보안을 반드시 보장하세요.
다음 단계는 인증서를 구문 분석하는 것입니다. 인터넷에서 인증서를 구문 분석하는 방법에는 java.security를 사용하여 보다 "공식적인" 방법을 사용합니다. JDK 보안 패키지의 KeyStore 코드>를 구문 분석합니다. <code>java.security.KeyStore
来解析。
微信支付Java에서의 WeChat 결제에 대한 자세한 설명(1): API V3 버전 서명使用了PKCS12
算法,我们通过KeyStore
来获取公私钥对的载体KeyPair
以及证书序列号serialNumber
,我封装了工具类:
import org.springframework.core.io.ClassPathResource;import java.security.KeyPair;import java.security.KeyStore;import java.security.PrivateKey;import java.security.PublicKey;import java.security.cert.X509Certificate;/** * KeyPairFactory * * @author dax * @since 13:41 **/public class KeyPairFactory { private KeyStore store; private final Object lock = new Object(); /** * 获取公私钥. * * @param keyPath the key path * @param keyAlias the key alias * @param keyPass password * @return the key pair */ public KeyPair createPKCS12(String keyPath, String keyAlias, String keyPass) { ClassPathResource resource = new ClassPathResource(keyPath); char[] pem = keyPass.toCharArray(); try { synchronized (lock) { if (store == null) { synchronized (lock) { store = KeyStore.getInstance("PKCS12"); store.load(resource.getInputStream(), pem); } } } X509Certificate certificate = (X509Certificate) store.getCertificate(keyAlias); certificate.checkValidity(); // 证书的序列号 也有用 String serialNumber = certificate.getSerialNumber().toString(16).toUpperCase(); // 证书的 公钥 PublicKey publicKey = certificate.getPublicKey(); // 证书的私钥 PrivateKey storeKey = (PrivateKey) store.getKey(keyAlias, pem); return new KeyPair(publicKey, storeKey); } catch (Exception e) { throw new IllegalStateException("Cannot load keys from store: " + resource, e); } } }复制代码
眼熟的可以看出是胖哥Spring Security教程中JWT用的公私钥提取方法的修改版本,你可以对比下不同之处。
这个方法中有三个参数,这里必须要说明一下:
keyPath
Java에서의 WeChat 결제에 대한 자세한 설명(1): API V3 버전 서명apiclient_cert.p12
的classpath
路径,一般我们会放在resources
路径下,当然你可以修改获取证书输入流的方式。keyAlias
证书的别名,这个微信的文档是没有的,胖哥通过加载证书时进行DEBUG获取到该值固定为Tenpay Certificate
。keyPass
证书密码,这个默认就是商户号,在其它配置中也需要使用就是mchid
,就是你用超级管理员登录微信商户平台在个人资料中的一串数字。微信支付V3版本的签名是我们在调用具体的微信支付的API时在HTTP请求头中携带特定的编码串供微信支付服务器进行验证请求来源,确保请求是真实可信的。
签名串的具体格式,一共五行一行也不能少,每一行以换行符n
结束。
HTTP请求方法\n URL\n 请求时间戳\n 请求随机串\n 请求报文主体\n复制代码
POST
。https://api.mch.weixin.qq.com/v3/pay/transactions/app
,除去域名部分得到参与签名的URL。如果请求中有查询参数,URL末尾应附加有'?'和对应的查询字符串。这里为/v3/pay/transactions/app
。System.currentTimeMillis() / 1000
获取即可。593BEC0C930BF1AFEB40B4A08C8FB242
的字符串就行了。""
;当请求方法为POST
或PUT
时,请使用真实发送的JSON
报文。图片上传API,请使用meta
对应的JSON
报文。然后我们使用商户私钥对按照上面格式的待签名串进行SHA256 with RSA签名,并对签名结果进行Base64编码得到签名值。对应的核心Java代码为:
/** * V3 SHA256withRSA 签名. * * @param method 请求方法 GET POST PUT DELETE 等 * @param canonicalUrl 例如 https://api.mch.weixin.qq.com/v3/pay/transactions/app?version=1 ——> /v3/pay/transactions/app?version=1 * @param timestamp 当前时间戳 因为要配置到TOKEN 中所以 签名中的要跟TOKEN 保持一致 * @param nonceStr 随机字符串 要和TOKEN中的保持一致 * @param body 请求体 GET 为 "" POST 为JSON * @param keyPair 商户API 证书解析的密钥对 实际使用的是其中的私钥 * @return the string */@SneakyThrowsString sign(String method, String canonicalUrl, long timestamp, String nonceStr, String body, KeyPair keyPair) { String signatureStr = Stream.of(method, canonicalUrl, String.valueOf(timestamp), nonceStr, body) .collect(Collectors.joining("\n", "", "\n")); Signature sign = Signature.getInstance("SHA256withRSA"); sign.initSign(keyPair.getPrivate()); sign.update(signatureStr.getBytes(StandardCharsets.UTF_8)); return Base64Utils.encodeToString(sign.sign()); }复制代码
签名生成后会同一些参数组成一个Token
放置到对应HTTP请求的Authorization
请求头中,格式为:
Authorization: WECHATPAY2-SHA256-RSA2048 {Token}复制代码
Token
由以下五部分组成:
发起请求的商户(包括直连商户、服务商或渠道商)的商户号mchid
商户Java에서의 WeChat 결제에 대한 자세한 설명(1): API V3 버전 서명序列号serial_no
,用于声明所使用的证书
请求随机串nonce_str
时间戳timestamp
签名值signature
Token
生成的核心代码:
/** * 生成Token. * * @param mchId 商户号 * @param nonceStr 随机字符串 * @param timestamp 时间戳 * @param serialNo 证书序列号 * @param signature 签名 * @return the string */String token(String mchId, String nonceStr, long timestamp, String serialNo, String signature) { final String TOKEN_PATTERN = "mchid=\"%s\",nonce_str=\"%s\",timestamp=\"%d\",serial_no=\"%s\",signature=\"%s\""; // 生成token return String.format(TOKEN_PATTERN, wechatPayProperties.getMchId(), nonceStr, timestamp, serialNo, signature); }复制代码
将生成的Token
PKCS12
알고리즘을 사용하여 KeyStore
를 사용하여 공개 및 개인 키 쌍 KeyPair
와 인증서 일련번호 serialNumber
, 도구 클래스를 캡슐화했습니다. 익숙해 보이면 Spring에서 JWT에서 사용하는 공개 키 및 개인 키 추출 방법을 수정한 버전임을 알 수 있습니다. 보안 튜토리얼의 차이점을 비교할 수 있습니다.
WeChat Pay V3 버전의 서명은 특정 WeChat Pay API A를 호출할 때입니다. 특정 인코딩 문자열은 WeChat 결제 서버의 HTTP 요청 헤더에 전달되어 요청 소스를 확인하여 요청이 확실하고 신뢰할 수 있는지 확인합니다.그런 다음 판매자의 개인 키를 사용하여 서명할 문자열에 대해 RSA 서명으로 SHA256을 수행합니다. 위 형식으로 서명 결과에 대해 Base64 인코딩을 수행하여 서명 값을 얻습니다. 해당 핵심 Java 코드는 다음과 같습니다. 🎜rrreee서명 형식서명 문자열의 특정 형식은 총 5줄 이상이며, 각 줄은 개행 문자
n
으로 끝납니다.
rrreee
- HTTP 요청 방법 호출하는 WeChat 결제 API에 필요한 요청 방법(예: APP 결제)은
POST
입니다.- URL 예를 들어 APP 결제 문서는
https://api.mch.weixin.qq.com/v3/pay/transactions/app
입니다. >, 서명에 참여하는 URL을 얻으려면 도메인 이름 부분을 제거하십시오. 요청에 쿼리 매개변수가 있는 경우 '?' 및 해당 쿼리 문자열을 URL 끝에 추가해야 합니다./v3/pay/transactions/app
입니다.- 요청 타임스탬프 서버 시스템 타임스탬프, 서버 시간이 올바른지 확인하고
System.currentTimeMillis() / 1000
을 사용하여 가져옵니다.- 임의의 문자열 요청
593BEC0C930BF1AFEB40B4A08C8FB242
와 유사한 문자열을 생성하는 도구 클래스를 찾으세요.- 요청 메시지 본문 GET 요청인 경우 바로 널 문자
"" code>; 요청 방법이
POST
또는PUT
인 경우 실제로 전송되는JSON
메시지를 사용하세요. 이미지 업로드 API의 경우meta
에 해당하는JSON
메시지를 사용하세요.서명 생성
토큰을 형성합니다. code>를 HTTP 요청에 해당하는 <code>에 배치합니다. code>Authorization
요청 헤더에 형식은 다음과 같습니다. 🎜rrreee🎜Token
은 다음 5개 부분으로 구성됩니다. 🎜mchid
🎜serial_no
, 사용된 인증서를 선언하는 데 사용됨🎜nonce_str
🎜timestamp code>🎜
서명
🎜Token
생성된 핵심코드 : 🎜rrreee🎜생성된 코드를 넣어주세요 위 형식에 따라 요청 헤더에 토큰
을 삽입하면 서명 사용이 완료됩니다. 🎜🎜5. 요약🎜🎜이 글에서는 WeChat Pay V3 버전의 어려운 서명과 서명 사용에 대해 완벽하게 분석했으며, API 인증서 분석도 설명했습니다. 결제 개발 관련 특정 문제. 🎜🎜🎜관련 무료 학습 추천: 🎜Basic Java Tutorial🎜🎜🎜관련 기사 소개: 🎜미니 프로그램 결제 기능 구현 방법🎜🎜🎜🎜
위 내용은 Java에서의 WeChat 결제에 대한 자세한 설명(1): API V3 버전 서명의 상세 내용입니다. 자세한 내용은 PHP 중국어 웹사이트의 기타 관련 기사를 참조하세요!