WeChat Payment API v3의 Guzzle HttpClient 미들웨어는 요청 서명 생성 및 응답 서명 확인을 구현합니다.
Guzzle을 사용하는 판매자 개발자인 경우 GuzzleHttpClient
생성 시 WechatPayGuzzleMiddleware
전달할 수 있습니다. 결과 GuzzleHttpClient
인스턴스는 요청 실행 시 자동으로 ID 인증 정보를 전달하고 응답의 WeChat Pay 서명을 확인합니다.
현재 버전은 0.2.0
테스트 버전입니다. 가맹점의 전문기술인력을 활용하실 때에는 시스템과 소프트웨어의 정확성과 호환성, 그리고 그에 수반되는 위험에 주의하시기 바랍니다.
이 프로젝트는 유지 관리 중입니다. 모든 개발자는 WeChat Pay의 새로운 PHP 개발 라이브러리 wechatpay-php를 우선적으로 사용할 것을 권장합니다.
개발 및 테스트에 사용되는 환경은 다음과 같습니다.
참고: guzzle7이 지원되지 않는 구체적인 이유는 #54의 토론에서 찾을 수 있습니다. guzzle7을 사용하는 개발자는 wechatpay-php를 사용하시기 바랍니다.
PHP 패키지 관리 도구 작성기를 사용하여 프로젝트에 SDK를 도입할 수 있습니다.
방법 1: 프로젝트 디렉터리에서 작성기 명령줄을 통해 추가합니다.
composer require wechatpay/wechatpay-guzzle-middleware
방법 2: 프로젝트의 작곡가.json에 다음 구성을 추가합니다.
"require" : {
"wechatpay/wechatpay-guzzle-middleware" : " ^0.2.0 "
}
구성을 추가한 후 설치를 수행합니다.
composer install
먼저 WechatPayMiddlewareBuilder
통해 WechatPayMiddleware
를 빌드한 후 GuzzleHttpClient
의 HandlerStack
에 추가합니다. 가맹점 개인키, 위챗 결제 플랫폼 인증서 등의 정보를 편리하게 전달할 수 있는 해당 방법을 제공합니다.
use GuzzleHttp Exception RequestException ;
use WechatPay GuzzleMiddleware WechatPayMiddleware ;
use WechatPay GuzzleMiddleware Util PemUtil ;
// 商户相关配置
$ merchantId = ' 1000100 ' ; // 商户号
$ merchantSerialNumber = ' XXXXXXXXXX ' ; // 商户API证书序列号
$ merchantPrivateKey = PemUtil:: loadPrivateKey ( ' /path/to/mch/private/key.pem ' ); // 商户私钥
// 微信支付平台配置
$ wechatpayCertificate = PemUtil:: loadCertificate ( ' /path/to/wechatpay/cert.pem ' ); // 微信支付平台证书
// 构造一个WechatPayMiddleware
$ wechatpayMiddleware = WechatPayMiddleware:: builder ()
-> withMerchant ( $ merchantId , $ merchantSerialNumber , $ merchantPrivateKey ) // 传入商户相关配置
-> withWechatPay ([ $ wechatpayCertificate ]) // 可传入多个微信支付平台证书,参数类型为array
-> build ();
// 将WechatPayMiddleware添加到Guzzle的HandlerStack中
$ stack = GuzzleHttp HandlerStack:: create ();
$ stack -> push ( $ wechatpayMiddleware , ' wechatpay ' );
// 创建Guzzle HTTP Client时,将HandlerStack传入
$ client = new GuzzleHttp Client ([ ' handler ' => $ stack ]);
// 接下来,正常使用Guzzle发起API请求,WechatPayMiddleware会自动地处理签名和验签
try {
$ resp = $ client -> request ( ' GET ' , ' https://api.mch.weixin.qq.com/v3/... ' , [ // 注意替换为实际URL
' headers ' => [ ' Accept ' => ' application/json ' ]
]);
echo $ resp -> getStatusCode (). ' ' . $ resp -> getReasonPhrase (). "n" ;
echo $ resp -> getBody (). "n" ;
$ resp = $ client -> request ( ' POST ' , ' https://api.mch.weixin.qq.com/v3/... ' , [
' json ' => [ // JSON请求体
' field1 ' => ' value1 ' ,
' field2 ' => ' value2 '
],
' headers ' => [ ' Accept ' => ' application/json ' ]
]);
echo $ resp -> getStatusCode (). ' ' . $ resp -> getReasonPhrase (). "n" ;
echo $ resp -> getBody (). "n" ;
} catch ( RequestException $ e ) {
// 进行错误处理
echo $ e -> getMessage (). "n" ;
if ( $ e -> hasResponse ()) {
echo $ e -> getResponse ()-> getStatusCode (). ' ' . $ e -> getResponse ()-> getReasonPhrase (). "n" ;
echo $ e -> getResponse ()-> getBody ();
}
return ;
}
// 参考上述指引说明,并引入 `MediaUtil` 正常初始化,无额外条件
use WechatPay GuzzleMiddleware Util MediaUtil ;
// 实例化一个媒体文件流,注意文件后缀名需符合接口要求
$ media = new MediaUtil ( ' /your/file/path/with.extension ' );
// 正常使用Guzzle发起API请求
try {
$ resp = $ client -> request ( ' POST ' , ' https://api.mch.weixin.qq.com/v3/[merchant/media/video_upload|marketing/favor/media/image-upload] ' , [
' body ' => $ media -> getStream (),
' headers ' => [
' Accept ' => ' application/json ' ,
' content-type ' => $ media -> getContentType (),
]
]);
// POST 语法糖
$ resp = $ client -> post ( ' merchant/media/upload ' , [
' body ' => $ media -> getStream (),
' headers ' => [
' Accept ' => ' application/json ' ,
' content-type ' => $ media -> getContentType (),
]
]);
echo $ resp -> getStatusCode (). ' ' . $ resp -> getReasonPhrase (). "n" ;
echo $ resp -> getBody (). "n" ;
} catch ( Exception $ e ) {
echo $ e -> getMessage (). "n" ;
if ( $ e -> hasResponse ()) {
echo $ e -> getResponse ()-> getStatusCode (). ' ' . $ e -> getResponse ()-> getReasonPhrase (). "n" ;
echo $ e -> getResponse ()-> getBody ();
}
return ;
}
// 参考上上述说明,引入 `SensitiveInfoCrypto`
use WechatPay GuzzleMiddleware Util SensitiveInfoCrypto ;
// 上行加密API 多于 下行解密,默认为加密,实例后直接当方法用即可
$ encryptor = new SensitiveInfoCrypto (PemUtil:: loadCertificate ( ' /path/to/wechatpay/cert.pem ' ));
// 正常使用Guzzle发起API请求
try {
// POST 语法糖
$ resp = $ client -> post ( ' /v3/applyment4sub/applyment/ ' , [
' json ' => [
' business_code ' => ' APL_98761234 ' ,
' contact_info ' => [
' contact_name ' => $ encryptor ( ' value of `contact_name` ' ),
' contact_id_number ' => $ encryptor ( ' value of `contact_id_number ' ),
' mobile_phone ' => $ encryptor ( ' value of `mobile_phone` ' ),
' contact_email ' => $ encryptor ( ' value of `contact_email` ' ),
],
//...
],
' headers ' => [
// 命令行获取证书序列号
// openssl x509 -in /path/to/wechatpay/cert.pem -noout -serial | awk -F= '{print $2}'
// 或者使用工具类获取证书序列号 `PemUtil::parseCertificateSerialNo($certificate)`
' Wechatpay-Serial ' => ' must be the serial number via the downloaded pem file of `/v3/certificates` ' ,
' Accept ' => ' application/json ' ,
],
]);
echo $ resp -> getStatusCode (). ' ' . $ resp -> getReasonPhrase (). "n" ;
echo $ resp -> getBody (). "n" ;
} catch ( Exception $ e ) {
echo $ e -> getMessage (). "n" ;
if ( $ e -> hasResponse ()) {
echo $ e -> getResponse ()-> getStatusCode (). ' ' . $ e -> getResponse ()-> getReasonPhrase (). "n" ;
echo $ e -> getResponse ()-> getBody ();
}
return ;
}
// 单例加解密示例如下
$ crypto = new SensitiveInfoCrypto ( $ wechatpayCertificate , $ merchantPrivateKey );
$ encrypted = $ crypto ( ' Alice ' );
$ decrypted = $ crypto -> setStage ( ' decrypt ' )( $ encrypted );
기본 로컬 서명 및 확인 방법이 시스템에 적합하지 않은 경우 Signer
또는 Verifier
구현하여 서명 및 확인을 사용자 정의할 수 있습니다. 예를 들어 시스템이 판매자 개인 키를 중앙에 저장하고 비즈니스 시스템이 원격 호출을 통해 서명을 수행해야 하는 경우 이렇게 할 수 있습니다.
use WechatPay GuzzleMiddleware Auth Signer ;
use WechatPay GuzzleMiddleware Auth SignatureResult ;
use WechatPay GuzzleMiddleware Auth WechatPay2Credentials ;
class CustomSigner implements Signer
{
public function sign ( $ message )
{
// 调用签名RPC服务,然后返回包含签名和证书序列号的SignatureResult
return new SignatureResult ( ' xxxx ' , ' yyyyy ' );
}
}
$ credentials = new WechatPay2Credentials ( $ merchantId , new CustomSigner );
$ wechatpayMiddleware = WechatPayMiddleware:: builder ()
-> withCredentials ( $ credentials )
-> withWechatPay ([ $ wechatpayCertificate ])
-> build ();
WechatPayMiddlewareBuilder
사용하려면 withWechatpay
호출하여 WeChat 결제 플랫폼 인증서를 설정해야 하며 플랫폼 인증서는 Get Platform Certificate API를 호출해야만 다운로드할 수 있습니다. "무한 루프"를 끊기 위해 다음과 같이 처음으로 플랫폼 인증서를 다운로드할 때 응답 서명 확인을 일시적으로 "건너뛰기"할 수 있습니다.
use WechatPay GuzzleMiddleware Validator ;
class NoopValidator implements Validator
{
public function validate ( Psr Http Message ResponseInterface $ response )
{
return true ;
}
}
$ wechatpayMiddleware = WechatPayMiddleware:: builder ()
-> withMerchant ( $ merchantId , $ merchantSerialNumber , $ merchantPrivateKey )
-> withValidator ( new NoopValidator ) // NOTE: 设置一个空的应答签名验证器,**不要**用在业务请求
-> build ();
참고 : 비즈니스 요청에는 표준 초기화 프로세스를 사용하고 응답 서명을 반드시 확인하십시오.
AesUtil.php를 참조하세요.
4.6.0에서 기본 컬(swoole/swoole-src#3863) 지원이 추가되어 swoole 4.6 이상으로 업그레이드하는 것이 좋습니다. 자세한 내용은 #36을 참조하세요.
버그를 발견하거나 질문이나 제안 사항이 있는 경우 이슈를 통해 피드백을 제공해 주세요.
개발자 커뮤니티에 오신 것을 환영합니다.