1、下载官方提供的sdk(https://github.com/wechatpay-apiv3/wechatpay-php)
2、创建订单
use WeChatPay\Builder;
use WeChatPay\Crypto\AesGcm;
use WeChatPay\Crypto\Rsa;
use WeChatPay\Formatter;
use WeChatPay\Util\PemUtil;
/**
* @param $out_trade_no 订单号
* @param $total_fee 支付金额
* @param $attach 扩展字段
* @param $body 描述
* @return mixed
*/
public static function h5($out_trade_no, $total_fee, $attach, $body){
// 商户号
$merchantId = 'xxx';
// 从本地文件中加载「商户API私钥」,「商户API私钥」会用来生成请求的签名
$merchantPrivateKeyFilePath = 'file://这里写apiclient_key.pem文件地址绝对路径';
$merchantPrivateKeyInstance = Rsa::from($merchantPrivateKeyFilePath, Rsa::KEY_TYPE_PRIVATE);
// 「商户API证书」的「证书序列号」
$merchantCertificateSerial = 'xxx';
// 从本地文件中加载「微信支付平台证书」,用来验证微信支付应答的签名(php需要用工具或者时接口获取,见我的另一篇文章记录)
$platformCertificateFilePath = 'file://这里写平台证书地址绝对路径';
$platformPublicKeyInstance = Rsa::from($platformCertificateFilePath, Rsa::KEY_TYPE_PUBLIC);
// 从「微信支付平台证书」中获取「证书序列号」
$platformCertificateSerial = PemUtil::parseCertificateSerialNo($platformCertificateFilePath);
// 构造一个 APIv3 客户端实例
$instance = Builder::factory([
'mchid' => $merchantId,
'serial' => $merchantCertificateSerial,
'privateKey' => $merchantPrivateKeyInstance,
'certs' => [
$platformCertificateSerial => $platformPublicKeyInstance,
],
]);
try {
$resp = $instance
->chain('v3/pay/transactions/h5')
->post(['json' => [
'mchid' => '',
'attach' => $attach,
'out_trade_no' => $out_trade_no,
'appid' => '',
'description' => $body,
'notify_url' => '',
'amount' => [
'total' => $total_fee,
'currency' => 'CNY'
],
'scene_info' => [
'payer_client_ip' => '',
'h5_info' => [
'type' => 'Wap',
],
],
]]);
$res = json_decode($resp->getBody(),true);
return $res['h5_url']; // 返回给前端,前端在浏览器跳转该地址就可以唤起微信支付
} catch (\Exception $e) {
// 进行错误处理
echo $e->getMessage(), PHP_EOL;
if ($e instanceof \GuzzleHttp\Exception\RequestException && $e->hasResponse()) {
$r = $e->getResponse();
echo $r->getStatusCode() . ' ' . $r->getReasonPhrase(), PHP_EOL;
echo $r->getBody(), PHP_EOL, PHP_EOL, PHP_EOL;
}
echo $e->getTraceAsString(), PHP_EOL;
}
}
/**
* 微信支付回调
* @param $input 获取的body数据
* @param $header 获取的请求头数据
* @return bool
*/
public function notify($input,$header)
{
$inWechatpaySignature = $header['wechatpay-signature'];// 请根据实际情况获取
$inWechatpayTimestamp = $header['wechatpay-timestamp'];// 请根据实际情况获取
$inWechatpaySerial = $header['wechatpay-serial'];// 请根据实际情况获取
$inWechatpayNonce = $header['wechatpay-nonce'];// 请根据实际情况获取
$inBody = $input;// 请根据实际情况获取,例如: file_get_contents('php://input');
$apiv3Key = '';// 在商户平台上设置的APIv3密钥
// 根据通知的平台证书序列号,查询本地平台证书文件,
// 假定为 `/path/to/wechatpay/inWechatpaySerial.pem`
$platformPublicKeyInstance = Rsa::from('file://平台证书地址', 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数组
$inBodyResourceArray = (array)json_decode($inBodyResource, true);
if ($inBodyResourceArray['trade_state'] == 'SUCCESS') {
// 这里写业务逻辑
$result = [
'code'=>'SUCCESS',
'message'=>'成功',
];
echo json_encode($result);exit;
}
}
}
// 获取header头的方法
public function get_all_header()
{
// 忽略获取的header数据。这个函数后面会用到。主要是起过滤作用
$ignore = array('host','accept','content-length','content-type','connection','accept-encoding'); $headers = array(); //这里大家有兴趣的话,可以打印一下。会出来很多的header头信息。咱们想要的部分,都是‘http_'开头的。所以下面会进行过滤输出。/* var_dump($_SERVER);
foreach($_SERVER as $key=>$value){ if(substr($key, 0, 5)==='HTTP_'){ //这里取到的都是'http_'开头的数据。
//前去开头的前5位
$key = substr($key, 5); //把$key中的'_'下划线都替换为空字符串
$key = str_replace('_', ' ', $key); //再把$key中的空字符串替换成‘-’
$key = str_replace(' ', '-', $key); //把$key中的所有字符转换为小写
$key = strtolower($key); //这里主要是过滤上面写的$ignore数组中的数据
if(!in_array($key, $ignore)){ $headers[$key] = $value;
}
}
}//输出获取到的header
return $headers;
}