最近项目中需要使用微信支付,决定使用微信官方V3 SDK版本接口
项目支持的环境如下:
composer require wechatpay/wechatpay
ℹ️ 以下是 微信支付 API v3 的指引。如果你是 API v2 的使用者,请看 README_APIv2。
商户 API 证书,是用来证实商户身份的。证书中包含商户号、证书序列号、证书有效期等信息,由证书授权机构(Certificate Authority ,简称 CA)签发,以防证书被伪造或篡改。详情见 什么是商户API证书?如何获取商户API证书? 。
商户 API 私钥。你申请商户 API 证书时,会生成商户私钥,并保存在本地证书文件夹的文件 apiclient_key.pem 中。为了证明 API 请求是由你发送的,你应使用商户 API 私钥对请求进行签名。
⚠️ 不要把私钥文件暴露在公共场合,如上传到 Github,写在 App 代码中等。
ℹ️ 你需要先手工 下载平台证书 才能使用 SDK 发起请求。
按官方文档使用各种报错,估计是因为有其他的库引起的
composer exec CertificateDownloader.php -- -k ${apiV3key} -m ${mchId} -f ${mchPrivateKeyFilePath} -s ${mchSerialNo} -o ${outputFilePath}
/**
* 获取证书
* @return mixed
*/
public static function certificates()
{
$wxPayConfig = config('wx_pay_config');
$api_v3_key = $wxPayConfig['api_v3_key'] ?? ''; // 商户号
$result = self::wx_curl_query('v3/certificates','GET');
$result = json_decode($result, true);
$ciphertext = $result['data'][0]['encrypt_certificate']['ciphertext'] ?? '';
$nonce = $result['data'][0]['encrypt_certificate']['nonce'] ?? '';
$associated_data = $result['data'][0]['encrypt_certificate']['associated_data'] ?? '';
$decryptedMsg = AesGcm::decrypt($ciphertext, $api_v3_key, $nonce, $associated_data);
$result['decryptedMsg'] = ($decryptedMsg); //解密后的内容,就是证书内容
dump($result);
}
//get请求
public static function wx_curl_query($urlV3 = '', $http_method = 'POST', $body = '')
{
$url = 'https://api.mch.weixin.qq.com/' . $urlV3;
$config = config('wx_pay_config');;
$mchId = $config['mchid'] ?? ''; // 商户ID
$serial_no = $config['cert_serial'] ?? ''; // 证书序列号
$certPath = 'file://' . ROOT_PATH . 'cert/wx/' . $mchId;
// 从本地文件中加载「商户API私钥」,「商户API私钥」会用来生成请求的签名
$merchantPrivateKeyFilePath = $certPath . '/apiclient_key.pem';
$mch_private_key = openssl_get_privatekey(file_get_contents($merchantPrivateKeyFilePath));;//私钥
if(is_array($body)){
$body = json_encode($body); // 接口参数
}
// 生成token 验签
$timestamp = time();//时间戳
$nonce = Formatter::nonce(32);//随机串
$url_parts = parse_url($url);
$canonical_url = ($url_parts['path'] . (!empty($url_parts['query']) ? "?${url_parts['query']}" : ""));
//构造签名串
$message = $http_method . "\n" .
$canonical_url . "\n" .
$timestamp . "\n" .
$nonce . "\n" .
$body . "\n";//报文主体
//计算签名值
openssl_sign($message, $raw_sign, $mch_private_key, 'sha256WithRSAEncryption');
$sign = base64_encode($raw_sign);
//设置HTTP头
$token = sprintf('WECHATPAY2-SHA256-RSA2048 mchid="%s",nonce_str="%s",timestamp="%d",serial_no="%s",signature="%s"',
$mchId, $nonce, $timestamp, $serial_no, $sign);
$headers = [
'Accept: application/json',
'User-Agent: */*',
'Content-Type: application/json; charset=utf-8',
'Authorization: ' . $token,
"Wechatpay-Serial:{$serial_no}"
];
$info = curl_init();
curl_setopt($info, CURLOPT_RETURNTRANSFER, true);
curl_setopt($info, CURLOPT_HEADER, 0);
curl_setopt($info, CURLOPT_NOBODY, 0);
curl_setopt($info, CURLOPT_SSL_VERIFYPEER, false);
curl_setopt($info, CURLOPT_SSL_VERIFYHOST, false);
if ($http_method == 'POST') {
curl_setopt($info, CURLOPT_POST, 1);
curl_setopt($info, CURLOPT_POSTFIELDS, json_encode($body));
}
//设置header头
curl_setopt($info, CURLOPT_HTTPHEADER, $headers);
curl_setopt($info, CURLOPT_URL, $url);
$output = curl_exec($info);
curl_close($info);
return $output;
}
/**
* 获取平台证书列表
* @return void
* @author wzb
* @date 2023/8/8 11:01
*/
static function getCert()
{
// 设置参数
[$instance, $wxPayConfig] = self::init();
$api_v3_key = $wxPayConfig['api_v3_key'] ?? ''; // 「商户API证书」的「证书序列号」
// 发送请求
$resp = $instance->chain('v3/certificates')->get(
// ['debug' => true] // 调试模式,https://docs.guzzlephp.org/en/stable/request-options.html#debug
);
$result = json_decode($resp->getBody(), true);
$ciphertext = $result['data'][0]['encrypt_certificate']['ciphertext'] ?? '';
$nonce = $result['data'][0]['encrypt_certificate']['nonce'] ?? '';
$associated_data = $result['data'][0]['encrypt_certificate']['associated_data'] ?? '';
$decryptedMsg = AesGcm::decrypt($ciphertext, $api_v3_key, $nonce, $associated_data);
$result['ciphertext_msg'] = $decryptedMsg;
dump($result);
}
static $merchantPrivateKeyInstance; // 从本地文件中加载「商户API私钥」,「商户API私钥」会用来生成请求的签名
/**
* 初始化
* @return array [$instance,$wxPayConfig];
* @author wzb
* @date 2023/8/8 11:05
*/
public static function init()
{
// 设置参数
$wxPayConfig = config('wx_pay_config');
$mchId = $wxPayConfig['mchid'] ?? ''; // 商户号
$serial = $wxPayConfig['cert_serial'] ?? ''; // 「商户API证书」的「证书序列号」
$certPath = 'file://' . ROOT_PATH . 'cert/wx/' . $mchId;
// 从本地文件中加载「商户API私钥」,「商户API私钥」会用来生成请求的签名
$merchantPrivateKeyFilePath = $certPath . '/apiclient_key.pem';
self::$merchantPrivateKeyInstance = $merchantPrivateKeyInstance = Rsa::from($merchantPrivateKeyFilePath, Rsa::KEY_TYPE_PRIVATE);
// 从本地文件中加载「微信支付平台证书」,用来验证微信支付应答的签名
$platformCertificateFilePath = $certPath . '/cert.pem';
$platformPublicKeyInstance = Rsa::from($platformCertificateFilePath, Rsa::KEY_TYPE_PUBLIC);
// 从「微信支付平台证书」中获取「证书序列号」
$platformCertificateSerial = PemUtil::parseCertificateSerialNo($platformCertificateFilePath);
// 构造一个 APIv3 客户端实例
$instance = Builder::factory([
'mchid' => $mchId,
'serial' => $serial,
'privateKey' => $merchantPrivateKeyInstance,
'certs' => [
$platformCertificateSerial => $platformPublicKeyInstance,
],
]);
return [$instance, $wxPayConfig];
}
/**
* 支付
* @param $payData
* @param $notifyUrl
* @return array
* @author wzb
* @date 2023/8/8 11:01
*/
static function pay($payData = [], $notifyUrl = '')
{
$notifyUrl = $notifyUrl ?? (config('host_api') . '/v1/notify/wx_notify');
[$instance, $wxPayConfig] = self::init(); // 赋值给变量
$merchantId = $wxPayConfig['mchid'] ?? ''; // 商户号
$appid = $wxPayConfig['appid'] ?? ''; // 商户号
// 调用下单
$payJsonData = [
'mchid' => $merchantId,
'appid' => $appid,
'out_trade_no' => $payData['out_trade_no'] ?? 0,
'description' => $payData['description'] ?? 0,
'notify_url' => $notifyUrl,
'amount' => [
'total' => $payData['money'] ?? 0, // 分
'currency' => 'CNY'
],
];
try {
$resp = $instance
->chain('v3/pay/transactions/app')
->post(['json' => $payJsonData]);
if ($resp->getStatusCode() == 200) {
$wo = json_decode($resp->getBody(), true); //prepay_id
$params = [
'partnerId' => $appid,
'timeStamp' => (string)Formatter::timestamp(),
'nonceStr' => Formatter::nonce(),
'prepayId' => $wo["prepay_id"],
];
$params += ['sign' => Rsa::sign(
Formatter::joinedByLineFeed(...array_values($params)),
self::$merchantPrivateKeyInstance
)];
return [1, $params];
} else {
return [0, '微信支付失败'];
}
} catch (\Exception $e) {
$code = $e->getCode();
$data = '';
// 进行错误处理
if ($e instanceof \GuzzleHttp\Exception\RequestException && $e->hasResponse()) {
$r = $e->getResponse();
$data = json_decode($r->getBody(), true);
LogHelperUtil::outLog("wx_pay_error", $data, "wx_pay");
}
}
return [$code, $data];
// end
}
/**
* 回调
* @param $header
* @param $inBody
* @return array|string[]|void
* @author wzb
* @date 2023/8/8 11:01
*/
static function notify($header, $inBody)
{
$inWechatpaySignature = $header['wechatpay-signature'];
$inWechatpayTimestamp = $header['wechatpay-timestamp'];
$inWechatpaySerial = $header['wechatpay-serial'];
$inWechatpayNonce = $header['wechatpay-nonce'];
if (!$inWechatpaySignature or !$inWechatpayTimestamp or !$inWechatpaySerial or !$inWechatpayNonce) {
header("Location:/404.html");
exit;
}
$wxPayConfig = config('wx_pay_config');
$merchantId = $wxPayConfig['mchid'] ?? ''; // 商户号
$apiv3Key = $wxPayConfig['api_v3_key'] ?? '';// 在商户平台上设置的APIv3密钥
$certPath = 'file://' . ROOT_PATH . 'cert/wx/' . $merchantId;
// 从本地文件中加载「微信支付平台证书」,用来验证微信支付应答的签名
$platformCertificateFilePath = $certPath . '/cert.pem';
// 根据通知的平台证书序列号,查询本地平台证书文件,这里是自己生成的证书
$platformPublicKeyInstance = Rsa::from(file_get_contents($platformCertificateFilePath), Rsa::KEY_TYPE_PUBLIC);
// 检查通知时间偏移量,允许5分钟之内的偏移
$timeOffsetStatus = 300 >= abs(Formatter::timestamp() - (int)$inWechatpayTimestamp);
$verifiedStatus = Rsa::verify(
// 构造验签名串
Formatter::joinedByLineFeed($inWechatpayTimestamp, $inWechatpayNonce, $inBody),
$inWechatpaySignature,
$platformPublicKeyInstance
);
if ($timeOffsetStatus && $verifiedStatus) {
// 转换通知的JSON文本消息为PHP Array数组
$inBodyArray = (array)json_decode($inBody, true);
// 使用PHP7的数据解构语法,从Array中解构并赋值变量
['resource' => [
'ciphertext' => $ciphertext,
'nonce' => $nonce,
'associated_data' => $aad
]] = $inBodyArray;
// 加密文本消息解密
$inBodyResource = AesGcm::decrypt($ciphertext, $apiv3Key, $nonce, $aad);
// 把解密后的文本转换为PHP Array数组
return (array)json_decode($inBodyResource, true);
} else {
return ['trade_state' => 'FAIL'];
}
}
/**
* 退款
* @param $orderSn
* @param $tradeNo
* @param $refundMoney
* @return array|mixed array [$code,$data] $code=1 成功
* @author wzb
* @date 2023/8/8 9:09
*/
static function refundOrder($orderSn, $tradeNo, $refundMoney)
{
[$instance, $wxPayConfig] = self::init();
try {
$response = $instance
->chain('v3/refund/domestic/refunds')
->post([
'json' => [
'transaction_id' => $tradeNo,
'out_refund_no' => $orderSn,
'amount' => [
'refund' => $refundMoney,
'total' => $refundMoney,
'currency' => 'CNY',
],
],
]);
// 正常逻辑回调处理
$code = $response->getStatusCode();
$response = json_decode($response->getBody(), true);
$status = $response['status'] ?? '';
if ($code != 200) {
DingDingUtil::sendDingtalkText("微信退款未知原因!订单号:{$orderSn} 错误原因:" . json_encode($response));
}
return [1, $response];
} catch (\Exception $e) {
// 异常错误处理
if ($e instanceof \GuzzleHttp\Exception\RequestException && $e->hasResponse()) {
$r = $e->getResponse();
$code = $r->getStatusCode();
$response = json_decode($r->getBody(), true);
$subCode = $response['code'] ?? '';
$subMsg = $response['message'] ?? '';
$listErrorCode = [
'NOT_ENOUGH', // 余额不足',
'MCH_NOT_EXISTS', //MCHID不存在',
'NO_AUTH', //没有退款权限',
];
if (in_array($subCode, $listErrorCode)) {
DingDingUtil::sendDingtalkText("微信退款失败!\n订单号:{$orderSn} \n错误原因:" . $subMsg);
}
return [$code, $response];
}
}
return [0, '退款失败'];
}
namespace pay;
use util\DingDingUtil;
use util\LogHelperUtil;
use WeChatPay\Builder;
use WeChatPay\ClientJsonTrait;
use WeChatPay\Crypto\AesGcm;
use WeChatPay\Crypto\Rsa;
use WeChatPay\Formatter;
use WeChatPay\Util\PemUtil;
class PayWxUtil
{
static $merchantPrivateKeyInstance; // 从本地文件中加载「商户API私钥」,「商户API私钥」会用来生成请求的签名
/**
* 初始化
* @return array [$instance,$wxPayConfig];
* @author wzb
* @date 2023/8/8 11:05
*/
public static function init()
{
// 设置参数
$wxPayConfig = config('wx_pay_config');
$mchId = $wxPayConfig['mchid'] ?? ''; // 商户号
$serial = $wxPayConfig['cert_serial'] ?? ''; // 「商户API证书」的「证书序列号」
$certPath = 'file://' . ROOT_PATH . 'cert/wx/' . $mchId;
// 从本地文件中加载「商户API私钥」,「商户API私钥」会用来生成请求的签名
$merchantPrivateKeyFilePath = $certPath . '/apiclient_key.pem';
self::$merchantPrivateKeyInstance = $merchantPrivateKeyInstance = Rsa::from($merchantPrivateKeyFilePath, Rsa::KEY_TYPE_PRIVATE);
// 从本地文件中加载「微信支付平台证书」,用来验证微信支付应答的签名
$platformCertificateFilePath = $certPath . '/cert.pem';
$platformPublicKeyInstance = Rsa::from($platformCertificateFilePath, Rsa::KEY_TYPE_PUBLIC);
// 从「微信支付平台证书」中获取「证书序列号」
$platformCertificateSerial = PemUtil::parseCertificateSerialNo($platformCertificateFilePath);
// 构造一个 APIv3 客户端实例
$instance = Builder::factory([
'mchid' => $mchId,
'serial' => $serial,
'privateKey' => $merchantPrivateKeyInstance,
'certs' => [
$platformCertificateSerial => $platformPublicKeyInstance,
],
]);
return [$instance, $wxPayConfig];
}
/**
* 支付
* @param $payData
* @param $notifyUrl
* @return array
* @author wzb
* @date 2023/8/8 11:01
*/
static function pay($payData = [], $notifyUrl = '')
{
$notifyUrl = $notifyUrl ?? (config('host_api') . '/v1/notify/wx_notify');
[$instance, $wxPayConfig] = self::init(); // 赋值给变量
$merchantId = $wxPayConfig['mchid'] ?? ''; // 商户号
$appid = $wxPayConfig['appid'] ?? ''; // 商户号
// 调用下单
$payJsonData = [
'mchid' => $merchantId,
'appid' => $appid,
'out_trade_no' => $payData['out_trade_no'] ?? 0,
'description' => $payData['description'] ?? 0,
'notify_url' => $notifyUrl,
'amount' => [
'total' => $payData['money'] ?? 0, // 分
'currency' => 'CNY'
],
];
try {
$resp = $instance
->chain('v3/pay/transactions/app')
->post(['json' => $payJsonData]);
if ($resp->getStatusCode() == 200) {
$wo = json_decode($resp->getBody(), true); //prepay_id
$params = [
'partnerId' => $appid,
'timeStamp' => (string)Formatter::timestamp(),
'nonceStr' => Formatter::nonce(),
'prepayId' => $wo["prepay_id"],
];
$params += ['sign' => Rsa::sign(
Formatter::joinedByLineFeed(...array_values($params)),
self::$merchantPrivateKeyInstance
)];
return [1, $params];
} else {
return [0, '微信支付失败'];
}
} catch (\Exception $e) {
$code = $e->getCode();
$data = '';
// 进行错误处理
if ($e instanceof \GuzzleHttp\Exception\RequestException && $e->hasResponse()) {
$r = $e->getResponse();
$data = json_decode($r->getBody(), true);
LogHelperUtil::outLog("wx_pay_error", $data, "wx_pay");
}
}
return [$code, $data];
// end
}
/**
* 退款
* @param $orderSn
* @param $tradeNo
* @param $refundMoney
* @return array|mixed array [$code,$data] $code=1 成功
* @author wzb
* @date 2023/8/8 9:09
*/
static function refundOrder($orderSn, $tradeNo, $refundMoney)
{
[$instance, $wxPayConfig] = self::init();
try {
$response = $instance
->chain('v3/refund/domestic/refunds')
->post([
'json' => [
'transaction_id' => $tradeNo,
'out_refund_no' => $orderSn,
'amount' => [
'refund' => $refundMoney,
'total' => $refundMoney,
'currency' => 'CNY',
],
],
]);
// 正常逻辑回调处理
$code = $response->getStatusCode();
$response = json_decode($response->getBody(), true);
$status = $response['status'] ?? '';
if ($code != 200) {
DingDingUtil::sendDingtalkText("微信退款未知原因!订单号:{$orderSn} 错误原因:" . json_encode($response));
}
return [1, $response];
} catch (\Exception $e) {
// 异常错误处理
if ($e instanceof \GuzzleHttp\Exception\RequestException && $e->hasResponse()) {
$r = $e->getResponse();
$code = $r->getStatusCode();
$response = json_decode($r->getBody(), true);
$subCode = $response['code'] ?? '';
$subMsg = $response['message'] ?? '';
$listErrorCode = [
'NOT_ENOUGH', // 余额不足',
'MCH_NOT_EXISTS', //MCHID不存在',
'NO_AUTH', //没有退款权限',
];
if (in_array($subCode, $listErrorCode)) {
DingDingUtil::sendDingtalkText("微信退款失败!\n订单号:{$orderSn} \n错误原因:" . $subMsg);
}
return [$code, $response];
}
}
return [0, '退款失败'];
}
/**
* 回调
* @param $header
* @param $inBody
* @return array|string[]|void
* @author wzb
* @date 2023/8/8 11:01
*/
static function notify($header, $inBody)
{
$inWechatpaySignature = $header['wechatpay-signature'];
$inWechatpayTimestamp = $header['wechatpay-timestamp'];
$inWechatpaySerial = $header['wechatpay-serial'];
$inWechatpayNonce = $header['wechatpay-nonce'];
if (!$inWechatpaySignature or !$inWechatpayTimestamp or !$inWechatpaySerial or !$inWechatpayNonce) {
header("Location:/404.html");
exit;
}
$wxPayConfig = config('wx_pay_config');
$merchantId = $wxPayConfig['mchid'] ?? ''; // 商户号
$apiv3Key = $wxPayConfig['api_v3_key'] ?? '';// 在商户平台上设置的APIv3密钥
$certPath = 'file://' . ROOT_PATH . 'cert/wx/' . $merchantId;
// 从本地文件中加载「微信支付平台证书」,用来验证微信支付应答的签名
$platformCertificateFilePath = $certPath . '/cert.pem';
// 根据通知的平台证书序列号,查询本地平台证书文件,这里是自己生成的证书
$platformPublicKeyInstance = Rsa::from(file_get_contents($platformCertificateFilePath), Rsa::KEY_TYPE_PUBLIC);
// 检查通知时间偏移量,允许5分钟之内的偏移
$timeOffsetStatus = 300 >= abs(Formatter::timestamp() - (int)$inWechatpayTimestamp);
$verifiedStatus = Rsa::verify(
// 构造验签名串
Formatter::joinedByLineFeed($inWechatpayTimestamp, $inWechatpayNonce, $inBody),
$inWechatpaySignature,
$platformPublicKeyInstance
);
if ($timeOffsetStatus && $verifiedStatus) {
// 转换通知的JSON文本消息为PHP Array数组
$inBodyArray = (array)json_decode($inBody, true);
// 使用PHP7的数据解构语法,从Array中解构并赋值变量
['resource' => [
'ciphertext' => $ciphertext,
'nonce' => $nonce,
'associated_data' => $aad
]] = $inBodyArray;
// 加密文本消息解密
$inBodyResource = AesGcm::decrypt($ciphertext, $apiv3Key, $nonce, $aad);
// 把解密后的文本转换为PHP Array数组
return (array)json_decode($inBodyResource, true);
} else {
return ['trade_state' => 'FAIL'];
}
}
/**
* 获取平台证书列表
* @return void
* @author wzb
* @date 2023/8/8 11:01
*/
static function getCert()
{
// 设置参数
[$instance, $wxPayConfig] = self::init();
$api_v3_key = $wxPayConfig['api_v3_key'] ?? ''; // 「商户API证书」的「证书序列号」
// 发送请求
$resp = $instance->chain('v3/certificates')->get(
// ['debug' => true] // 调试模式,https://docs.guzzlephp.org/en/stable/request-options.html#debug
);
$result = json_decode($resp->getBody(), true);
$ciphertext = $result['data'][0]['encrypt_certificate']['ciphertext'] ?? '';
$nonce = $result['data'][0]['encrypt_certificate']['nonce'] ?? '';
$associated_data = $result['data'][0]['encrypt_certificate']['associated_data'] ?? '';
$decryptedMsg = AesGcm::decrypt($ciphertext, $api_v3_key, $nonce, $associated_data);
$result['ciphertext_msg'] = $decryptedMsg;
dump($result);
}
/**
* 获取证书
* @return mixed
*/
public static function certificates()
{
$wxPayConfig = config('wx_pay_config');
$api_v3_key = $wxPayConfig['api_v3_key'] ?? ''; // 商户号
$result = self::wx_curl_query('v3/certificates','GET');
$result = json_decode($result, true);
$ciphertext = $result['data'][0]['encrypt_certificate']['ciphertext'] ?? '';
$nonce = $result['data'][0]['encrypt_certificate']['nonce'] ?? '';
$associated_data = $result['data'][0]['encrypt_certificate']['associated_data'] ?? '';
$decryptedMsg = AesGcm::decrypt($ciphertext, $api_v3_key, $nonce, $associated_data);
$result['decryptedMsg'] = ($decryptedMsg); //解密后的内容,就是证书内容
dump($result);
}
//get请求
public static function wx_curl_query($urlV3 = '', $http_method = 'POST', $body = '')
{
$url = 'https://api.mch.weixin.qq.com/' . $urlV3;
$config = config('wx_pay_config');;
$mchId = $config['mchid'] ?? ''; // 商户ID
$serial_no = $config['cert_serial'] ?? ''; // 证书序列号
$certPath = 'file://' . ROOT_PATH . 'cert/wx/' . $mchId;
// 从本地文件中加载「商户API私钥」,「商户API私钥」会用来生成请求的签名
$merchantPrivateKeyFilePath = $certPath . '/apiclient_key.pem';
$mch_private_key = openssl_get_privatekey(file_get_contents($merchantPrivateKeyFilePath));;//私钥
if(is_array($body)){
$body = json_encode($body); // 接口参数
}
// 生成token 验签
$timestamp = time();//时间戳
$nonce = Formatter::nonce(32);//随机串
$url_parts = parse_url($url);
$canonical_url = ($url_parts['path'] . (!empty($url_parts['query']) ? "?${url_parts['query']}" : ""));
//构造签名串
$message = $http_method . "\n" .
$canonical_url . "\n" .
$timestamp . "\n" .
$nonce . "\n" .
$body . "\n";//报文主体
//计算签名值
openssl_sign($message, $raw_sign, $mch_private_key, 'sha256WithRSAEncryption');
$sign = base64_encode($raw_sign);
//设置HTTP头
$token = sprintf('WECHATPAY2-SHA256-RSA2048 mchid="%s",nonce_str="%s",timestamp="%d",serial_no="%s",signature="%s"',
$mchId, $nonce, $timestamp, $serial_no, $sign);
$headers = [
'Accept: application/json',
'User-Agent: */*',
'Content-Type: application/json; charset=utf-8',
'Authorization: ' . $token,
"Wechatpay-Serial:{$serial_no}"
];
$info = curl_init();
curl_setopt($info, CURLOPT_RETURNTRANSFER, true);
curl_setopt($info, CURLOPT_HEADER, 0);
curl_setopt($info, CURLOPT_NOBODY, 0);
curl_setopt($info, CURLOPT_SSL_VERIFYPEER, false);
curl_setopt($info, CURLOPT_SSL_VERIFYHOST, false);
if ($http_method == 'POST') {
curl_setopt($info, CURLOPT_POST, 1);
curl_setopt($info, CURLOPT_POSTFIELDS, json_encode($body));
}
//设置header头
curl_setopt($info, CURLOPT_HTTPHEADER, $headers);
curl_setopt($info, CURLOPT_URL, $url);
$output = curl_exec($info);
curl_close($info);
return $output;
}
}
服务端SDK