PHP
PHP在微信支付API v3环境下请求接口
PHP在微信支付API v3环境下请求接口
今天接到一个需求,需要调用微信商家券接口,看了下文档,起初也是有点懵逼,因为代码示例或者SDK都很少,百度上也几乎没有,最终决定自己写。
大概看了下文档介绍,主要难题还是在签名生成,只要这个解决,其他都不是问题,看了下签名生成的步骤,跟之前自己写的上传图片到腾讯云COS上的过程有点类似,所以也参考了下,并根据文档的介绍,最终成功完成调用,下面贴出详细的代码,封装调用方法:
<?php
/**
* 微信公共配置方法
* Created by PhpStorm.
* User: pc001
* Date: 2020/5/20
* Time: 14:20
*/
/*备注:apiclient_cert.p12是商户证书文件,除PHP外的开发均使用此证书文件*/
#微信基础信息
$wxMerchantId = "商户号"; //商户号
$wxMerchantApiCertificate = __DIR__ . "/cert/apiclient_cert.pem"; //商户证书
$wxMerchantApiPrivateKey = __DIR__ . "/cert/apiclient_key.pem"; //商户私钥
$wxApiV3Key = "微信API v3密钥"; //微信API v3密钥
$wxApiSerialNo = "商户API证书序列号"; //商户API证书序列号
#############微信构造签名流程#############
/**
* 生成签名
* @param string $method 请求方法 POST 或者GET
* @param string $url 请求URL
* @param string $request 请求中的请求报文主体
* @param $wxMerchantId商户号
* @param $certKey商户私钥
* @param $wxApiSerialNo商户API证书序列号
* @return string
*/
function RequestSign($method = "POST", $url = "", $request = "", $wxMerchantId, $certKey, $wxApiSerialNo)
{
#截取获取当前请求地址【去除域名】
$url_parts = parse_url($url);
$path = ($url_parts['path'] . (!empty($url_parts['query']) ? "?${url_parts['query']}" : ""));
#获取当前时间戳
$timeStamp = time();
#生成一个随机字符串
$nonceStr = getNonceStr();
#构造签名串
$requestSign = sprintf("%s\n%s\n%s\n%s\n%s\n", $method, $path, $timeStamp, $nonceStr, $request);
#计算计算签名值
$sign = calculateSignatureValue($requestSign, $certKey);
#设置HTTP头获取Authorization
$token = createToken($wxMerchantId, $nonceStr, $timeStamp, $wxApiSerialNo, $sign);
#返回
return $token;
}
/**
* 计算签名值
* @param $requestSign
* @param $certKey
* @return string
* 使用商户私钥对待签名串进行SHA256 with RSA签名,并对签名结果进行Base64编码得到签名值
*/
function calculateSignatureValue($requestSign, $certKey)
{
$certKey = file_get_contents($certKey);
openssl_sign($requestSign, $raw_sign, $certKey, 'sha256WithRSAEncryption');
$sign = base64_encode($raw_sign);
return $sign;
}
/**
* 获取token
* @param $merchant_id
* @param $nonce
* @param $timestamp
* @param $serial_no
* @param $sign
* @return string
*/
function createToken($merchant_id, $nonce, $timestamp, $serial_no, $sign)
{
$schema = 'WECHATPAY2-SHA256-RSA2048';
$token = sprintf('mchid="%s",nonce_str="%s",timestamp="%d",serial_no="%s",signature="%s"',
$merchant_id, $nonce, $timestamp, $serial_no, $sign);
return $token;
}
/**
* 产生随机字符串,不长于32位
* @param int $length
* @return string
*/
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;
}
/**
* post请求
* @param $url
* @param $authorization
* @return mixed
*/
function curlPostWithWx($url, $authorization)
{
$paramsString = json_encode($params);
// 初始化curl
$ch = curl_init();
// 设置超时
curl_setopt($ch, CURLOPT_TIMEOUT, $timeout);
curl_setopt($ch, CURLOPT_URL, $url);
curl_setopt($ch, CURLOPT_SSL_VERIFYPEER, FALSE);
curl_setopt($ch, CURLOPT_SSL_VERIFYHOST, FALSE);
curl_setopt($ch, CURLOPT_HEADER, FALSE);
curl_setopt($ch, CURLOPT_RETURNTRANSFER, TRUE);
// post数据
curl_setopt($ch, CURLOPT_POST, 1);
// post的变量
curl_setopt($ch, CURLOPT_POSTFIELDS, $paramsString);
curl_setopt($ch, CURLOPT_HTTPHEADER, array(
'Content-Type: application/json; charset=utf-8',
'Content-Length: ' . strlen($paramsString),
'Authorization: ' . "WECHATPAY2-SHA256-RSA2048 " . $authorization,
'Accept: application/json',
'User-Agent:Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/81.0.4044.138 Safari/537.36'
)
);
// 运行curl,结果以jason形式返回
$res = curl_exec($ch);
curl_close($ch);
// 取出数据
$data = json_decode($res, true);
return $data;
}
/**
* get请求
* @param $url
* @param $authorization
* @return mixed
*/
function curlGetWithWx($url, $authorization)
{
// 初始化curl
$ch = curl_init();
// 设置超时
curl_setopt($ch, CURLOPT_TIMEOUT, 60);
curl_setopt($ch, CURLOPT_URL, $url);
curl_setopt($ch, CURLOPT_SSL_VERIFYPEER, FALSE);
curl_setopt($ch, CURLOPT_SSL_VERIFYHOST, FALSE);
curl_setopt($ch, CURLOPT_HEADER, FALSE);
curl_setopt($ch, CURLOPT_RETURNTRANSFER, TRUE);
curl_setopt($ch, CURLOPT_HTTPHEADER, array(
'Content-Type: application/json; charset=utf-8',
'Content-Length: ' . strlen($paramsString),
'Authorization: ' . "WECHATPAY2-SHA256-RSA2048 " . $authorization,
'Accept: application/json',
'User-Agent:Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/81.0.4044.138 Safari/537.36'
)
);
// 运行curl,结果以jason形式返回
$res = curl_exec($ch);
curl_close($ch);
// 取出数据
$data = json_decode($res, true);
//返回
return $data;
}下面我们调用的demo:
#引入文件
require __DIR__ . "/wxComm.php";
#请求接口地址
$url = "https://api.mch.weixin.qq.com/v3/certificates";
#组合基本信息
$params = array();
$request = json_encode($params);
#获取authorization
$authorization = RequestSign("GET", $url, "", $wxMerchantId, $wxMerchantApiPrivateKey, $wxApiSerialNo);
#请求接口
$data = curlGetWithWx($url, $authorization);
#输出
echo json_encode($data);这样我们就成功的在微信支付API v3环境下请求接口,这里是在GET情况下调用接口,其实POST情况下也差不多,只是调用http请求时换了另一个方法,实现过程其实不难,主要是参考的东西太少。
这里要注意一点,这里的证书是指API证书,要在后台申请,而不是以前的证书,具体申请可以查看官方文档。
0条评论