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 パッケージ管理ツールの Composer を使用して、SDK をプロジェクトに導入できます。
方法 1: プロジェクト ディレクトリに、composer コマンド ラインを使用して次のコマンドを追加します。
composer require wechatpay/wechatpay-guzzle-middleware
方法 2: 次の構成をプロジェクトのcomposer.jsonに追加します。
"require" : {
"wechatpay/wechatpay-guzzle-middleware" : " ^0.2.0 "
}
構成を追加した後、インストールを実行します
composer install
まず、 WechatPayMiddlewareBuilder
を通じてWechatPayMiddleware
を構築し、それをGuzzleHttpClient
のHandlerStack
に追加します。当社は、販売者の秘密キーや WeChat 支払いプラットフォーム証明書などの情報を便利に渡すための対応する方法を提供します。
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を参照してください。
swoole 4.6.0でnative-curl (swoole/swoole-src#3863) のサポートが追加されたので、swoole 4.6以降にアップグレードすることを推奨します。 詳細については、#36 を参照してください。
バグを見つけた場合、または質問や提案がある場合は、問題を通じてフィードバックを提供してください。
開発者コミュニティへもようこそ。