Middleware Guzzle HttpClient dari WeChat Payment API v3 mengimplementasikan pembuatan tanda tangan permintaan dan verifikasi tanda tangan respons.
Jika Anda adalah pengembang pedagang yang menggunakan Guzzle, Anda dapat meneruskan WechatPayGuzzleMiddleware
saat membuat GuzzleHttpClient
. Instance GuzzleHttpClient
yang dihasilkan akan secara otomatis membawa informasi autentikasi identitas saat menjalankan permintaan, dan memeriksa tanda tangan WeChat Pay sebagai respons.
Versi saat ini adalah versi pengujian 0.2.0
. Harap perhatikan kebenaran dan kompatibilitas sistem dan perangkat lunak, serta risiko yang ada, saat menggunakan tenaga profesional dan teknis pedagang.
Proyek ini sedang dalam pemeliharaan . Kami menyarankan agar semua pengembang memberikan prioritas untuk menggunakan perpustakaan pengembangan PHP WeChat Pay yang baru, wechatpay-php.
Lingkungan yang kami gunakan untuk pengembangan dan pengujian adalah sebagai berikut:
Catatan: Alasan spesifik mengapa guzzle7 tidak didukung dapat ditemukan dalam pembahasan di #54. Pengembang yang mengandalkan guzzle7 silakan gunakan wechatpay-php.
Anda dapat menggunakan komposer alat manajemen paket PHP untuk memperkenalkan SDK ke dalam proyek:
Metode 1: Di direktori proyek, tambahkan melalui baris perintah komposer:
composer require wechatpay/wechatpay-guzzle-middleware
Metode 2: Tambahkan konfigurasi berikut ke composer.json proyek:
"require" : {
"wechatpay/wechatpay-guzzle-middleware" : " ^0.2.0 "
}
Setelah menambahkan konfigurasi, lakukan instalasi
composer install
Pertama, buat WechatPayMiddleware
melalui WechatPayMiddlewareBuilder
, lalu tambahkan ke HandlerStack
dari GuzzleHttpClient
. Kami menyediakan metode yang sesuai untuk menyampaikan informasi dengan mudah seperti kunci pribadi pedagang dan sertifikat platform pembayaran 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 );
Jika metode penandatanganan dan verifikasi lokal default tidak sesuai untuk sistem Anda, Anda dapat menyesuaikan penandatanganan dan verifikasi dengan menerapkan Signer
atau Verifier
. Misalnya, jika sistem Anda menyimpan kunci pribadi pedagang secara terpusat, dan sistem bisnis perlu melakukan penandatanganan melalui panggilan jarak jauh, Anda dapat melakukan hal ini.
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 ();
Penggunaan WechatPayMiddlewareBuilder
memerlukan panggilan withWechatpay
untuk mengatur sertifikat platform pembayaran WeChat, dan sertifikat platform hanya dapat diunduh dengan memanggil API Dapatkan Sertifikat Platform. Untuk memutus "lingkaran tak terbatas", Anda dapat "melewati" sementara verifikasi tanda tangan respons saat mengunduh sertifikat platform untuk pertama kalinya sebagai berikut.
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 ();
Catatan : Harap gunakan proses inisialisasi standar untuk permintaan bisnis, dan pastikan untuk memverifikasi tanda tangan respons.
Silakan merujuk ke AesUtil.php.
Disarankan untuk meningkatkan ke swoole 4.6+. Swoole menambahkan dukungan native-curl (swoole/swoole-src#3863) di 4.6.0. Untuk informasi lebih rinci, silakan merujuk ke #36.
Jika Anda menemukan BUG atau memiliki pertanyaan atau saran, silakan berikan umpan balik melalui masalah.
Selamat datang juga di komunitas pengembang kami.