微信支付v3,php代码,包含签名,验签,获取token
<?php
//设置为常量方便使用
const v3key = '*********';//v3秘钥
const pr = '******';//商户私钥文件apiclient_key.pem
const mchid = '*******';//商户号
const serial_no = '*********';//证书序列号
$url = 'https://api.mch.weixin.qq.com/v3/certificates';
$url_parts = parse_url($url);
$canonical_url = ($url_parts['path'] . (!empty($url_parts['query']) ? "?${url_parts['query']}" : ""));
/*
HTTP请求方法\n
URL\n
请求时间戳\n
请求随机串\n
请求报文主体\n
GET需要多一个换行符,有body就少一个换行符
*/
$stime =time();//时间戳
$nostr = md5(time().mt_rand(000,999));//随机字符串
$message = "GET"."\n".
$canonical_url."\n".
$stime ."\n".
$nostr ."\n"."\n";
//var_dump($message);
openssl_sign($message, $sign, file_get_contents(pr), 'sha256WithRSAEncryption');
$sign = base64_encode($sign);//签名信息进行编码
$token = sprintf('mchid="%s",nonce_str="%s",timestamp="%d",serial_no="%s",signature="%s"',
mchid, str_replace("\n","",$nostr), str_replace("\n","",$stime), serial_no, $sign);//格式化字符串
//var_dump($token,$sign);exit;
$ch = curl_init();
curl_setopt($ch,CURLOPT_URL,$url);//设置请求网址
curl_setopt($ch,CURLOPT_RETURNTRANSFER,1);//返回数据流不输出
curl_setopt($ch,CURLOPT_HEADER,1);//返回header信息
curl_setopt($ch,CURLOPT_HTTPHEADER,array('Authorization: WECHATPAY2-SHA256-RSA2048 ' .$token,
'Accept:application/json',
'User-Agent:Mozilla/5.0 (Windows NT 6.1; WOW64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/78.0.3904.108 Safari/537.36'));//设置header信息
$crt = curl_exec($ch);
if (curl_getinfo($ch, CURLINFO_HTTP_CODE) == '200') {
$headerSize = curl_getinfo($ch, CURLINFO_HEADER_SIZE);
$header = substr($crt, 0, $headerSize);//把header信息单独拿出来
$body = substr($crt, $headerSize);}//把返回的数据拿出来
curl_close($ch);
/*
echo "<pre>";
var_dump("这是返回的body:\n".$body);
echo "<hr>";
var_dump("这是header数据:\n".$header);
*/
//var_dump($crt);
//echo $crt;
//var_dump( getallheaders());
$str = get_header($header);//把header信息解析成数组
/*
echo "<pre>";
var_dump($str);
var_dump($body);
*/
$crs = json_decode($body,true);//把返回的数据解析成数组
//echo "<pre>";
$m = $crs['data'][0]['encrypt_certificate']['ciphertext'];//密文,需要解密
$m = base64_decode($m);//必须需要解码,不然会失败
$add_data = $crs['data'][0]['encrypt_certificate']['associated_data'];//额外数据
$nonce = $crs['data'][0]['encrypt_certificate']['nonce'];//解密字符串
//var_dump($crs['data'][0]['encrypt_certificate']['ciphertext']);
// var_dump($crs);
$crt = sodium_crypto_aead_aes256gcm_decrypt($m,$add_data,$nonce,v3key);//解密后获取的是证书
$res = openssl_pkey_get_public($crt);//从证书里面读取公钥资源
$ttr= openssl_pkey_get_details($res);//解析并获取公钥
$ttr = $ttr['key'];//证书公钥
//var_dump($ttr);
//下面是验证是否为微信发来的信息
//var_dump($str);
$v_sj =$str['Wechatpay-Timestamp']."\n".
$str['Wechatpay-Nonce']."\n".
$body."\n";
//var_dump($v_sj);exit;
/*
应答时间戳\n
应答随机串\n
应答报文主体\n
v_sj 是根据返回值生成的数据
$str['Wechatpay-Signature']是从请求头里面拿出来的数据
ttr就是证书解析出来的公钥
sha256WithRSAEncryption 验签方式
*/
$wx_k = openssl_verify($v_sj,base64_decode($str['Wechatpay-Signature']),$ttr,'sha256WithRSAEncryption');
if($wx_k === 1){
echo '数据获取成功,你的微信支付平台证书序列号为:'.$str['Wechatpay-Serial']."<br>"."CR证书为:"."<br>".$crt."<br>"."公共秘钥为:"."<br>".$ttr."<br>"."已为你保存到文件,青岛系统里面进行查看。";
file_put_contents('wx.crt',$crt);
file_put_contents('wx.pub',$ttr);
}else{
echo '验签不通过,所有数据不予展示,请联系管理员';
}