文档还是要看一看的,虽然看完还不能马上写,熟悉下流程和概念
微软文档中心:产品能力概览 | 微信支付服务商平台文档中心
微信提供了SDK,有JAVA和PHP,安装后可使用,然而我不喜欢那么大块的程序,只要需要的那部分。
准备好服务商mchid,子账号mchid,公众号APPID,商户密钥,商户证书号,不懂请自行百度
第一步,生产prepay_id
$post_data = [
"sp_mchid" => $sp_mchid,//服务商MCHID
"sub_mchid" => $sub_mchid,//子账号MCHID
"out_trade_no" => $query['sn'],//订单号
"sp_appid" => $sp_appid,//公众号APPID
"sub_appid" => "",//子账号APPID
"description" => "七算宝车辆管理",
"notify_url" => $notify_url,//支付通知URL
"amount" => [
"total" => $amount * 100,//支付金额
"currency" => "CNY"
],
"payer" => [
"sp_openid" => $wxopenid//付款人opendid,如果未登录状态可静默获取
],
'attach' => '',
];
$result = $this->wx_post($url, json_encode($post_data));
$result = json_decode($result, true);
if (isset($result['prepay_id'])) {
return $result['prepay_id'];
}
return json_encode($result, JSON_UNESCAPED_UNICODE);
第二步:构建H5端需要的参数,跟V2版差不多,直连模式也是这样。
注意参数中的大小写,不能错,服务商版需多返回appId这个
$pay_body = 'prepay_id=' . $this->getwxpayv3_payid($query);
$timestamp = time();
$nonce = createNonceStr(32);
$sslKeyPath = '../partnerwxcert/apiclient_key.pem';//服务商私钥路径
$private_key = $this->getPrivateKey($sslKeyPath);
$message = $sp_appid . "\n" . $timestamp . "\n" . $nonce . "\n" . $pay_body . "\n";
//获得签名
openssl_sign($message, $signature, $private_key, 'sha256WithRSAEncryption');
$sign = base64_encode($signature);
$data = array(
'appId' => $this->sp_appid,
'timeStamp' => $timestamp,
'nonceStr' => $nonce,
'package' => $pay_body,
'signType' => 'RSA',
'paySign' => $sign,
);
return json_encode($data, JSON_UNESCAPED_UNICODE);
补充:V3版发送的参数需要在header加入验签和2个参数
private function wx_post($url, $param)
{
$authorization = $this->getV3Sign($url, "POST", $param);
$curl = curl_init();
$headers = [
'Authorization:' . $authorization,
'Accept:application/json',
'Content-Type:application/json;charset=utf-8',
'User-Agent:Mozilla/5.0 (Windows NT 10.0; WOW64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/63.0.3239.132 Safari/537.36',
];
curl_setopt($curl, CURLOPT_HTTPHEADER, $headers);
curl_setopt($curl, CURLOPT_RETURNTRANSFER, true);
curl_setopt($curl, CURLOPT_TIMEOUT, 500);
curl_setopt($curl, CURLOPT_SSL_VERIFYPEER, false);
curl_setopt($curl, CURLOPT_SSL_VERIFYHOST, false);
curl_setopt($curl, CURLOPT_URL, $url);
curl_setopt($curl, CURLOPT_POSTFIELDS, $param);
curl_setopt($curl, CURLOPT_POST, true);
$res = curl_exec($curl);
curl_close($curl);
return $res;
}
private function getV3Sign($url, $http_method, $body)
{
$mchid = $this->sp_mchid;
$nonce = strtoupper(createNonceStr(32));
$serialNo = $this->serial;
$timestamp = time();
$url_parts = parse_url($url);
$canonical_url = ($url_parts['path'] . (!empty($url_parts['query']) ? "?${url_parts['query']}" : ""));
$sslKeyPath = '../partnerwxcert/apiclient_key.pem';
//拼接参数
$message = $http_method . "\n" .
$canonical_url . "\n" .
$timestamp . "\n" .
$nonce . "\n" .
$body . "\n";
$private_key = $this->getPrivateKey($sslKeyPath);
openssl_sign($message, $raw_sign, $private_key, 'sha256WithRSAEncryption');
$sign = base64_encode($raw_sign);
$token = sprintf('WECHATPAY2-SHA256-RSA2048 mchid="%s",nonce_str="%s",timestamp="%s",serial_no="%s",signature="%s"', $this->sp_mchid, $nonce, $timestamp, $this->serial, $sign);
return $token;
}
32位随机数
function createNonceStr($length = 16) { //生成随机16个字符的字符串
$chars = "abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789";
$str = "";
for ($i = 0; $i < $length; $i++) {
$str .= substr($chars, mt_rand(0, strlen($chars) - 1), 1);
}
return $str;
}
获取密钥
private function getPrivateKey($filepath = '')
{
if (empty($filepath)) {
$filepath = '../partnerwxcert/apiclient_key.pem';
}
return openssl_get_privatekey(file_get_contents($filepath));
}