当前位置:网站首页>PHP wechat payment V3 interface
PHP wechat payment V3 interface
2022-06-12 10:21:00 【Qu Shuai 369】
matters needing attention
1, Request interface signature method ——RSA, Yes API Certificate serial number , The suffix is key.pem Key file for ,cert The file needs to be java Make your own , Specific reference :https://developers.weixin.qq.com/community/develop/doc/000e4a0d5dc1486acc19c6fd15bc00?_at=1569021781371
2, Return to applet or H5 The signature of the payment parameters should also RSA encryption , And only support RSA encryption .
3, The data of successful payment callback shall be decrypted , according to php Some versions need to be installed libsodium-php Expand :http://pecl.php.net/package/libsodium The server of our company is php7.0 Of
wget http://pecl.php.net/get/libsodium-2.0.10.tgzpecl install libsodium-2.0.10.tgzphp.ini File add extension , restart php That's all right.
extension=sodium.soInstall official sdk
composer require wechatpay/wechatpay-guzzle-middlewareCode
<?php
namespace app\store\controller\api;
use GuzzleHttp\Exception\RequestException;
use WechatPay\GuzzleMiddleware\WechatPayMiddleware;
use WechatPay\GuzzleMiddleware\Util\PemUtil;
use GuzzleHttp\HandlerStack;
use GuzzleHttp\Client;
/**
*
* Class PayV3
* @package app\store\controller\api
*/
class PayV3
{
// Merchant related configuration
public $spAppId;
public $subAppId;
public $merchantId; // Merchant number
public $merchantSerialNumber = ''; // Merchant API Certificate serial number
public $merchantPrivateKey ; // Merchant certificate private key
public $wechatpayCertificateV3; // Wechat payment platform certificate
public $key ;
public $keyV3 ;
public $out_trade_no;
public function __construct()
{
// Service provider appid
$this->spAppId = 'wxxxxxxxxxxxxxxxxx';
// Special merchants appid
$this->subAppId = 'wxxxxxxxxxxxxxxxxx';
// Service provider account No
$this->merchantId = '160xxxxxxx';
// Merchant ID of special merchant ( The test is made into variables in the project )
$this->subMerchantId = '160xxxxxxx';
$this->key = 'xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx';
//apiV3 key
$this->keyV3 = 'xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx';
// Wechat merchant ID view
$this->merchantSerialNumber = 'xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx';
// Wechat merchant ID download
$this->merchantPrivateKey = PemUtil::loadPrivateKey('config/01jh_cert/apiclient_key.pem');
// This file is java The environment is not generated by the merchant ID , For specific reference :https://developers.weixin.qq.com/community/develop/doc/000e4a0d5dc1486acc19c6fd15bc00?_at=1569021781371
// Be careful java edition Before me was 1.8.0_131 It's hard to follow the new path 1.8.0_291 The generation was successful
$this->wechatpayCertificateV3 = PemUtil::loadCertificate('config/01jh_cert/v3_cert.pem');
}
private function client() {
$wechatpayMiddleware = WechatPayMiddleware::builder()
->withMerchant($this->merchantId, $this->merchantSerialNumber, $this->merchantPrivateKey) // Incoming merchant related configuration
->withWechatPay([ $this->wechatpayCertificateV3 ]) // Multiple wechat payment platform certificates can be imported , Parameter type is array
->build();
// take WechatPayMiddleware Add to Guzzle Of HandlerStack in
$stack = HandlerStack::create();
$stack->push($wechatpayMiddleware, 'wechatpay');
// establish Guzzle HTTP Client when , take HandlerStack Pass in
return new Client(['handler' => $stack]);
}
private function request($url,$data,$method='POST') {
$client = $this->client();
// Next , Normal use Guzzle launch API request ,WechatPayMiddleware The signature and verification will be processed automatically
try {
$resp = $client->request($method, $url, [
'headers' => ['Accept' => 'application/json', 'Content-Type' => 'application/json'],
'json' => $data,
]);
//echo $resp->getStatusCode().' '.$resp->getReasonPhrase()."\n";
//echo $resp->getBody()."\n";
if($resp->getReasonPhrase() == 'OK') {
return $resp->getBody();
}
return false;
} catch (RequestException $e) {
// Error handling
echo $e->getMessage();
// echo $e->getMessage()."\n";
// if ($e->hasResponse()) {
// echo $e->getResponse()->getStatusCode().' '.$e->getResponse()->getReasonPhrase()."\n";
// echo $e->getResponse()->getBody();
// }
}
}
// The applet gets the payment parameters ( When using this method, you can call it directly ok 了 )
public function jsapiParams($data) {
$this->out_trade_no = $data['out_trade_no'];
// This allows you to set the default parameters , It can also be set without
$d = [
'sp_appid' => $this->spAppId ,
'sp_mchid' => $this->merchantId,
'sub_appid' => $this->subAppId,
// Pay to the special merchant
'sub_mchid' => $this->subMerchantId,
'description' =>' Custom product description ',
'out_trade_no' => $this->out_trade_no,
'notify_url' => 'https://xxxxx.xxxxx.com/ygyAdmin/public/store/api.v3pay/notify',
'amount' => ['total' => 1000],
//'payer' => ['sp_openid' => 'o8MCu5UvKGRs8gJsP_VNFLvZj_fM'],
'payer' => ['sub_openid' => 'ogD1q5Hz0bNdoPac0DYfV6jLcR0s'],
// Sub Ledger
//'settle_info' =>['profit_sharing' => true]
];
foreach ($data as $k=>$v) $d[$k] = $v;
$body = $this->request('https://api.mch.weixin.qq.com/v3/pay/partner/transactions/jsapi',$d);
if($body === false) return false;
$nonce_str = $this->getNoncestr();
$prepay_id = json_decode($body,true)['prepay_id'];
$time = time();
// Under which applet
//$tmp['appId'] = $this->appid;
$tmp['appId'] = $this->subAppId;
$tmp['timeStamp'] = $time;
$tmp['nonceStr'] = $nonce_str;
$tmp['package'] = 'prepay_id='.$prepay_id;
$data = array();
$data['state'] = 200;
$data['timeStamp'] = "$time";
$data['nonceStr'] = $nonce_str;
$data['package'] = 'prepay_id='.$prepay_id;// Unified order interface returns prepay_id Parameter values , The submission format is as follows :prepay_id=*
$data['paySign'] = $this->sign($tmp);
$data['out_trade_no'] = $this->out_trade_no;
return $data;
}
// Signature $data Order first
private function sign($data){
$string = '';
foreach ($data as $key=>$value){
if(!$value) continue;
$string .= $value."\n";
}
$private_key = $this->merchantPrivateKey;
openssl_sign($string, $raw_sign, $private_key, 'sha256WithRSAEncryption');
$sign = base64_encode($raw_sign);
return $sign;
}
/**
* Get random numbers
*/
public function getNoncestr($length = 32)
{
$chars = "abcdefghijklmnopqrstuvwxyz0123456789";
$str = "";
for ($i = 0; $i < $length; $i++) {
$str .= substr($chars, mt_rand(0, strlen($chars) - 1), 1);
}
return $str;
}
/**
* Payment callback data decryption
* @param string $associatedData AES GCM additional authentication data
* @param string $nonceStr AES GCM nonce
* @param string $ciphertext AES GCM cipher text
* @return string|bool Decrypted string on success or FALSE on failure
*/
public function decryptToString($associatedData, $nonceStr, $ciphertext)
{
$ciphertext = \base64_decode($ciphertext);
if (strlen($ciphertext) <= self::AUTH_TAG_LENGTH_BYTE) {
return false;
}
// ext-sodium (default installed on >= PHP 7.2)
if (function_exists('\sodium_crypto_aead_aes256gcm_is_available') &&
\sodium_crypto_aead_aes256gcm_is_available()) {
return \sodium_crypto_aead_aes256gcm_decrypt($ciphertext, $associatedData, $nonceStr, $this->aesKeyV3);
}
// ext-libsodium (need install libsodium-php 1.x via pecl)
if (function_exists('\Sodium\crypto_aead_aes256gcm_is_available') &&
\Sodium\crypto_aead_aes256gcm_is_available()) {
return \Sodium\crypto_aead_aes256gcm_decrypt($ciphertext, $associatedData, $nonceStr, $this->aesKeyV3);
}
// openssl (PHP >= 7.1 support AEAD)
if (PHP_VERSION_ID >= 70100 && in_array('aes-256-gcm', \openssl_get_cipher_methods())) {
$ctext = substr($ciphertext, 0, -self::AUTH_TAG_LENGTH_BYTE);
$authTag = substr($ciphertext, -self::AUTH_TAG_LENGTH_BYTE);
return \openssl_decrypt($ctext, 'aes-256-gcm', $this->aesKeyV3, \OPENSSL_RAW_DATA, $nonceStr,
$authTag, $associatedData);
}
throw new \RuntimeException('AEAD_AES_256_GCM need PHP 7.1 Above or installed libsodium-php');
}
}
边栏推荐
- Detailed explanation and use of redis data types: key and string types
- Remote link software xshell and xftp download address
- [experiment] MySQL master-slave replication and read-write separation
- 2021-02-12
- 2021-03-26
- JVM (VIII) Thread safety and lock optimization
- JVM (V) Virtual machine class loading (parental delegation mechanism)
- QT custom window fillets
- Auto. JS learning notes 8: some common and important APIs
- Jump to wechat in app and open wechat
猜你喜欢

MQTT 协议中文版

4. creator mode

HALCON联合C#检测表面缺陷——仿射变换(三)

MySQL III Configuration file & log file

2022淘宝618超级喵运会玩法来了 超级喵运会有哪些攻略方法

Introduction to IOT

conda 安装tensorflow 测试tensorflow

Mqtt protocol Chinese version

Qt自定义窗口圆角

Autojs learning notes 6:text (txt) Findone() will report an error when switching apps. Finally, solve the implementation effect and switch any app until the script finds the control with the specified
随机推荐
Auto. JS learning note 4: after autojs is packaged, most Huawei and other big brand mobile phones cannot be installed? This problem can be solved by using the simulator to remotely sign and package in
C# break continue return 三者区别
Explication du principe d'appariement le plus à gauche de MySQL
How high can C language reach by self-study alone?
2021-02-12
远程桌面不能复制粘贴解决办法
pycharm 查看opencv当前的版本
【实验】MySQL主从复制及读写分离
[untitled]
FPGA VGA display based on de2-115 platform
reflex
验收标准到底是不是测试用例?
93. 獲得內網的所有IP地址
Antique mfc/gdi+ Frame LCD display control
【ParquetEncodingException: empty fields are illegal, the field should be ommited completely instead
2022京东618预售定金怎么退?京东618定金能退吗?
QT custom window fillets
Pandorabox uses firewall rules to define non internet time
Auto. JS learning notes 8: some common and important APIs
Halcon combined with C # to detect surface defects -- affine transformation (III)