最近公司又一个项目需要微信扫码支付,之前没做过这种东西所以我先去看了文档,先说明一下本人只是一个菜鸟,遇事直接百度的那种,于是这次我像往常一样打开百度搜索微信扫码支付。此时我发现了一丝不对劲,怎么百度搜到的文档和微信官方的文档不一样呢?一个是用xml传递参数一个是用json传递参数,这一下给我搞蒙了,于是我去微信开放社区问了问,结果是微信支付有V2和V3之分,有没有V1我不清楚,用xml传参的是V2用json传参的是V3。建议我用V3,不过这个看个人喜好,也有人说V2更好。但是对比了两个文档后我还是选择了V3,因为文档看起来要传的参数少。。。。。。(只是看起来)
首先贴个文档: 微信支付-开发者文档
然后在贴个图
这个图是业务流程图自己看看理解,因为是扫码支付所以我需要用户下单后获取code_url然后使用code_url来生成二维码
看起来很简单是吧,然后这个是文档中给出的参数
{
"mchid": "1900006XXX",
"out_trade_no": "native12177525012014070332333",
"appid": "wxdace645e0bc2cXXX",
"description": "Image形象店-深圳腾大-QQ公仔",
"notify_url": "https://weixin.qq.com/",
"amount": {
"total": 1,
"currency": "CNY"
}
}
看起来也很少,但是如果我按照文档中写得发出请求呢?
答案是会报错: 400 "Http头缺少Accept或User-Agent" ,ok,因为我在写这块代码的时候公众号并没有申请下来,所以我觉得很正常,但是后来一想不对劲,没申请下来应该报的是 appid和mch_id不匹配 才对啊,于是我在请求里又加了accept和user-agent,然后报 401 Http头Authorization值格式错误,请参考《微信支付商户REST API签名规则》 我当时直接黑人问号,这是个什么东西啊?于是我又去微信开发社区问,结果是V3接口在调用的时候需要签名。好家伙刚说完你V3接口简单,结果你偷摸藏了个规则
关于签名的文档在这: 签名生成
要签名就必须要申请证书,方法在上面这个文档里,写得更详细,下载好证书之后保存好,之后就可以进行我们的开发了
接下来我就直接上代码了
public function xiadan(Request $request){//测试下单哦,根据需要自己改
$data=[];
$data['mchid']='';
$data['out_trade_no']='pai1234567';
$data['appid']='';
$data['description']='商品描述:测试用';
$data['notify_url']='';//通知地址
$data['amount']['total']=1;//订单总金额,单位为分。
$data['amount']['currency']='CNY';
$url="https://api.mch.weixin.qq.com/v3/pay/transactions/native";
$data_string=json_encode($data);
$qianming=$this->qianming('POST',$url,$data_string);
$code=$this->http_post_data($url,$data_string,$qianming);
// dd($qianming);
return $code;
// return json_encode($data);
}
public function qianming($http_method,$url,$body){
// Authorization: <schema> <token>
//获取HTTP请求的方法(GET,POST,PUT等)$http_method
//获取请求的绝对URL
$url_parts = parse_url($url);
$canonical_url = ($url_parts['path'] . (!empty($url_parts['query']) ? "?${url_parts['query']}" : ""));
//时间戳
$timestamp=time();
//生成随机串
$nonce=$this->createNoncestr();
$message = $http_method."\n".
$canonical_url."\n".
$timestamp."\n".
$nonce."\n".
$body."\n";
$mch_private_key=$this->getPrivateKey();
openssl_sign($message, $raw_sign, $mch_private_key, 'sha256WithRSAEncryption');
$sign = base64_encode($raw_sign);//计算签名
$schema = 'WECHATPAY2-SHA256-RSA2048';
//serial_no为商户证书序列号
$serial_no = '你商户证书的序列号';
$merchant_id = $this->mch_id;
$token = sprintf('mchid="%s",nonce_str="%s",timestamp="%d",serial_no="%s",signature="%s"',
$merchant_id, $nonce, $timestamp, $serial_no, $sign);
$msg['schema']=$schema;
$msg['token']=$token;
return $msg['schema'].' '.$token;;
}
/**
* 作用:产生随机字符串,不长于32位
*/
public function createNoncestr( $length = 32 )
{
$chars = "abcdefghijklmnopqrstuvwxyz0123456789";
$str ="";
for ( $i = 0; $i < $length; $i++ ) {
$str.= substr($chars, mt_rand(0, strlen($chars)-1), 1);
}
return $str;
}
//查看证书序列号
public static function getCertificate($filepath="apiclient_cert.pem") {//改成自己的地址哦
// return file_get_contents($filepath);die;
$str = openssl_x509_parse(file_get_contents($filepath));
return $str['serialNumberHex'];
// return openssl_x509_read(file_get_contents($filepath));
}
//获取私钥
public static function getPrivateKey($filepath="apiclient_key.pem") {//改成自己的地址哦
$private_key=openssl_get_privatekey(file_get_contents($filepath));
return $private_key;
}
/**
* 发送数据
*/
public function http_post_data($url,$data_string,$qianming) {
$ch = curl_init();
curl_setopt($ch, CURLOPT_POST, 1);
curl_setopt($ch, CURLOPT_URL, $url);
curl_setopt($ch, CURLOPT_POSTFIELDS, $data_string);
curl_setopt($ch, CURLOPT_HTTPHEADER, array(
'User-Agent:Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/91.0.4472.77 Safari/537.36',
'Accept:*/*',
'Authorization:' ."$qianming",
'Content-Type: application/json; charset=utf-8',
'Content-Length: ' . strlen($data_string))
);
ob_start();
curl_exec($ch);
$return_content = ob_get_contents();
ob_end_clean();
$return_code = curl_getinfo($ch, CURLINFO_HTTP_CODE);
return array($return_code, $return_content);
}
这样起码报错是 appid和mch_id不匹配 了,之后可能有更新,但感觉悬哈哈
评论 (0)