提前准备
- 下载微信支付官方sdk 压缩包
- 商户api证书:获取方式https://kf.qq.com/faq/161222NneAJf161222U7fARv.html
- 商户私钥:获取证书时,生成的apiclient_key.pem文件
- 商户证书序列号——商户平台查看
- 商户号——商户平台查看
- 微信支付平台证书
获取方式
运行 sdk 包中的CertificateDownloader.php 文件
php -f ./bin/CertificateDownloader.php -- -k ${apiV3key} -m ${mchId} -f ${mchPrivateKeyFilePath} -s ${mchSerialNo} -o ${outputFilePath}
参数说明
-m, --mchid=<merchantId> 商户号
-s, --serialno=<serialNo> 商户证书的序列号——商户平台查看
-f, --privatekey=<privateKeyFilePath>
apiclient_key.pem文件的位置
-k, --key=<apiV3key> ApiV3Key
-o, --output=[outputFilePath]
下载成功后保存证书的路径,可选参数,默认为临时文件目录夹
-u, --baseuri=[baseUri] 接入点,默认为 https://api.mch.weixin.qq.com/
-V, --version Print version information and exit.
-h, --help Show this help message and exit.
安装微信支付sdk
composer require wechatpay/wechatpay
step1:获取支付实例
// 商户号
$merchantId = env('WECHAT_PAYMENT_MCH_ID');
// 从本地文件中加载「商户API私钥」,「商户API私钥」会用来生成请求的签名
$merchantPrivateKeyFilePath = 'apiclient_key.pem';
$merchantPrivateKeyInstance = Rsa::from(file_get_contents($merchantPrivateKeyFilePath), Rsa::KEY_TYPE_PRIVATE);
// 「商户API证书」的「证书序列号」
$merchantCertificateSerial = env('WECHAT_PAYMENT_SER_NO');
// 从本地文件中加载「微信支付平台证书」,用来验证微信支付应答的签名
//通过CertificateDownloader.php获取的问价位置
$platformCertificateFilePath = '7E58755DC38BDB33CFDEA564E6A9A.pem';
$platformPublicKeyInstance = Rsa::from(file_get_contents($platformCertificateFilePath), Rsa::KEY_TYPE_PUBLIC);
// 从「微信支付平台证书」中获取「证书序列号」
$platformCertificateSerial = PemUtil::parseCertificateSerialNo(file_get_contents($platformCertificateFilePath));
$payapp = Builder::factory([
'mchid' => $merchantId,
'serial' => $merchantCertificateSerial,
'privateKey' => $merchantPrivateKeyInstance,
'certs' => [
$platformCertificateSerial => $platformPublicKeyInstance,
],
]);;
step2:获取预订单id
$notify_url = 'https://api.xinchengxinwuye.com/api/wechat/order-notify';
//$ordernumber = 'JF' . date("YmdHis") . time() . rand(10000, 99999);
$resp = $payapp
->chain('v3/pay/transactions/jsapi')
->post(['json' => [
'mchid' => env('WECHAT_PAYMENT_MCH_ID'),
'out_trade_no' => $param['ordernumber'],
'appid' => env('WECHAT_PAYMENT_APPID'),
'description' => 'Image形象店-深圳腾大-QQ公仔',
'notify_url' => $notify_url,
'amount' => [
'total' => $param['total'],
'currency' => 'CNY'
],
'payer' => [
'openid' => $param['openid']//"oCItw6bCmDtAdIJf2HT4gE2zT2os"
]
]
]);
// echo $resp->getStatusCode(), PHP_EOL;
// echo $resp->getBody(), PHP_EOL;
// $this->GetWxPayConfig(json_decode($resp->getBody(),true)['prepay_id']);
return json_decode($resp->getBody(),true);
step2 获取支付参数
$merchantPrivateKeyFilePath ='apiclient_key.pem';
$merchantPrivateKeyInstance = Rsa::from(file_get_contents($merchantPrivateKeyFilePath));
$timeStamp = (string)Formatter::timestamp();
$nonceStr = Formatter::nonce();
$params = [
'appId' => env('WECHAT_PAYMENT_APPID'),
'timeStamp' =>$timeStamp,
'nonceStr' => $nonceStr,
'package' => 'prepay_id='.$prey_id,//step2中获取的预订单id
];
$params += ['sign' => Rsa::sign(
Formatter::joinedByLineFeed(...array_values($params)),
$merchantPrivateKeyInstance
), 'signType' => 'RSA'];
// 用时间戳和随机字符串计算signature
//url是前端传过来的url 通过post 或request接受
$signature = get_jsapi_signature($url,$timeStamp,$nonceStr);
$package = 'prepay_id='.$prey_id;
$wxconfig = [
'nonceStr' => $nonceStr,
"package"=> $package,
"prepay_id"=> $prey_id,
'sign'=>$params['sign'],
"signature"=> $signature,
'timestamp' =>intval($timeStamp),
];
return $wxconfig;
step4 用step3中的时间戳和随机字符串计算signature
function get_service_access_token()
{
$redis_service_access_token = Cache::get('wechat_service_access_token');
if ($redis_service_access_token) {
return $redis_service_access_token;
}
$url = 'https://api.weixin.qq.com/cgi-bin/token?grant_type=client_credential&appid='
. env("WECHAT_OFFICIAL_ACCOUNT_APPID")
. '&secret='
. env("WECHAT_OFFICIAL_ACCOUNT_SECRET");
$res = request_get($url);
$errcode = json_decode($res,true);
if (!isset($errcode['access_token'])) {
return False;
}else{
$access_token = $errcode['access_token'];
Cache::set('wechat_service_access_token', $access_token, 7200);
return $access_token;
}
}
function get_jsapi_ticke
t()
{
$redis_jsapi_ticket = Cache::get('wechat_service_jsapi_ticket');
if ($redis_jsapi_ticket) {
return $redis_jsapi_ticket;
}
$access_token = get_service_access_token();
$url = 'https://api.weixin.qq.com/cgi-bin/ticket/getticket?access_token=' . $access_token . '&type=jsapi';
$res = json_decode(request_get($url),true);
if ($res['errcode'] and $res['errcode'] != 0) {
return False;
}
$ticket = $res['ticket'];
Cache::set('wechat_service_jsapi_ticket', $ticket, 7200);
return $ticket;
}
function get_jsapi_sig
nature($url,$timestamp,$noncestr)
{
$jsapi_ticket = get_jsapi_ticket();
//$timestamp = time();
// $noncestr = md5(time() . round(10000, 9999));
$string = 'jsapi_ticket=' . $jsapi_ticket
. '&noncestr=' . $noncestr
. '×tamp='
. $timestamp . 'url=' . $url;
$signature = sha1($string);
return $signature;
}