各位好,以下教程适合初次接触微信支付的小白,这是一个小白都能看懂,并且立即复制就能用的demo,本文从鹅厂复杂难懂的sdk中剥离解析,以几乎原生的方式呈现给你一份微信支付大餐。当然这只是微信支付其中的一种,但是所有鹅厂提供的微信支付,套路都是一样,比如电脑端的扫码支付,都是一个套路。大家看了这篇文章就知道微信支付是怎么一回事了。基本流程是这样的:
步骤1:用户选择微信支付。例如:
步骤2:商户后台收到用户支付单,调用微信支付统一下单接口。
步骤3:统一下单接口返回正常的prepay_id,再按签名规范重新生成签名后返回json字符串。
步骤4:商户公众号调起微信支付。
第一步:前端代码:
前端使用微信自定义的一个方法:WeixinJSBridge.invoke(),不需要额外引用任何第三方js,这个函数只在微信中生效,可以引用微信专用js:http://res.wx.qq.com/open/js/jweixin-1.4.0.js ,可以使用web开发者工具查看效果,网页中会报错。这里面的几个参数需要写正确,后面用YII写一个php的接口传给前端。
div style="text-align:center;size:30px;" input type="button" style="width:200px;height:80px;" value="微信支付" onclick="callpay()"/divscript type="text/javascript" function callpay(){ WeixinJSBridge.invoke('getBrandWCPayRequest',{ "appId":"公众号appID", "timeStamp":"1564389542", "nonceStr":"dBMPdafhPvospBoRPbSZcIobiLncQdya", "package":"prepay_id=wx291639019757571e2762612e1533749100", "signType" : "MD5", "paySign":"78CB396C8FE94FD3F0C51AE8BB53F326" },function(res){ WeixinJSBridge.log(res.err_msg); if(res.err_msg == "get_brand_wcpay_request:ok"){ alert("微信支付成功!"); }else if(res.err_msg == "get_brand_wcpay_request:cancel"){ alert("用户取消支付!"); }else{ alert("支付失败!"); } }) }/script第二步:后端PHP代码
先调用统一下单接口获取必要参数。Yii接口写的,只需要调用第一个函数$this-actionTestwxpay();其他函数是该函数的引用。
大家可以参考微信支付之JSAPI支付SDK与DEMO ,这里面写的超级详细的。下载地址:https://pay.weixin.qq.com/wiki/doc/api/jsapi.php?chapter=11_1
但是现在我写的是一个小白都能看懂的demo。复制代码马上能出效果的demo。
//统一下单 public function actionTestwxpay(){ $post = []; $post['appid'] = $appid = '';//重要参数 $post['body'] = $body = 'JSAPI支付测试'; //比如说会员充值,是一个签名,随便定义 $post['mch_id'] = $mch_id = '1424126202';//商户ID ,重要参数 ,跟appid一样是最重要的参数之一,以后别人给你打钱都在这里存着 $post['nonce_str'] = $nonce_str = $this-tesfsfsd();//随机字符串 ,随便定义 $post['notify_url'] = $notify_url = 'http://wxpay.wxutil.com/pub_v2/pay/notify.v2.php'; //回调地址,随便写$post['openid'] = $openid = 'oRG0ZxPPF0fbH1KCmMV5goJ69W8I';//明良的openid ,重要参数之三,不能错,自己去后台找,关注列表中有 $post['out_trade_no'] = $out_trade_no = time();//商户订单号,随便定义 $post['spbill_create_ip'] = $spbill_create_ip = '123.12.12.123';//服务器的ip,随便定义 $post['total_fee'] = $total_fee = '10000';//支付金额,最低为一分钱,即0.01元, 必须是整数,这里设置100块,你也可以设置1,显示为0.01元 $post['trade_type'] = $trade_type = 'JSAPI';//交易类型,默认必写 $sign = $this-sign($post);//签名,以上字段的顺序不能乱 $post_xml = 'xml appid' . $appid . '/appid body' . $body . '/body mch_id' . $mch_id . '/mch_id nonce_str' . $nonce_str . '/nonce_str notify_url' . $notify_url . '/notify_url openid' . $openid . '/openid out_trade_no' . $out_trade_no . '/out_trade_no spbill_create_ip' . $spbill_create_ip . '/spbill_create_ip total_fee' . $total_fee . '/total_fee trade_type' . $trade_type . '/trade_type sign' . $sign . '/sign /xml '; //统一接口prepay_id $url = 'https://api.mch.weixin.qq.com/pay/unifiedorder'; $xml = $this-http_request_json($url, $post_xml); $array = $this-xml($xml);//全要大写 if ($array['RETURN_CODE'] == 'SUCCESS' && $array['RESULT_CODE'] == 'SUCCESS') { $time = time(); $tmp = [];//临时数组用于签名 $tmp['appId'] = $appid; $tmp['nonceStr'] = $nonce_str; $tmp['package'] = 'prepay_id=' . $array['PREPAY_ID']; $tmp['signType'] = 'MD5'; $tmp['timeStamp'] = "$time"; $data['state'] = 1; $data['timeStamp'] = "$time";//时间戳 $data['nonceStr'] = $nonce_str;//随机字符串 $data['signType'] = 'MD5';//签名算法,暂支持 MD5 $data['package'] = 'prepay_id=' . $array['PREPAY_ID'];//统一下单接口返回的 prepay_id 参数值,提交格式如:prepay_id=* $data['paySign'] = $this-sign($tmp);//签名,具体签名方案参见微信公众号支付帮助文档; $data['out_trade_no'] = $out_trade_no; } else { $data['state'] = 0; $data['text'] = "错误"; $data['RETURN_CODE'] = $array['RETURN_CODE']; $data['RETURN_MSG'] = $array['RETURN_MSG']; } return json_encode($data); //小程序或公众号需要的数据 返回前端 } //随机字符串 public function tesfsfsd(){ $result = ''; $str = 'QWERTYUIOPASDFGHJKLZXVBNMqwertyuioplkjhgfdsamnbvcxz';//自己随便写 for ($i=0;$i32;$i++){ $result .= $str[rand(0,48)]; } return $result; } /** * 签名函数 *方法: 签名步骤一:按字典序排序参数 ksort($this-values); $string = $this-ToUrlParams(); 签名步骤二:在string后加入KEY $string = $string . "&key=".WxPayConfig::KEY; 签名步骤三:MD5加密 $string = md5($string); 签名步骤四:所有字符转为大写 $result = strtoupper($string); * @return string */ public function sign($data){ $stringA = ''; foreach ($data as $key=$value){ if(!$value) continue; if($stringA) $stringA .= '&'.$key."=".$value; else $stringA = $key."=".$value; } $wx_key = 'xxxxxxxxxxxxxxxxxxx';//这个密匙请正确填写,自己在公众号后台找,会跟着你的appid在一起 $stringSignTemp = $stringA.'&key='.$wx_key; return strtoupper(md5($stringSignTemp)); } //curl请求 function http_request_json($url,$data = null,$headers=array()){ $curl = curl_init(); if( count($headers) = 1 ){ curl_setopt($curl, CURLOPT_HTTPHEADER, $headers); } curl_setopt($curl, CURLOPT_URL, $url); curl_setopt($curl, CURLOPT_SSL_VERIFYPEER, FALSE); curl_setopt($curl, CURLOPT_SSL_VERIFYHOST, FALSE); if (!empty($data)){ curl_setopt($curl, CURLOPT_POST, 1); curl_setopt($curl, CURLOPT_POSTFIELDS, $data); } curl_setopt($curl, CURLOPT_RETURNTRANSFER, 1); $output = curl_exec($curl); curl_close($curl); return $output; } //获取xml private function xml($xml){ $p = xml_parser_create(); xml_parse_into_struct($p, $xml, $vals, $index); xml_parser_free($p); $data = ""; foreach ($index as $key=$value) { if($key == 'xml' || $key == 'XML') continue; $tag = $vals[$value[0]]['tag']; $value = $vals[$value[0]]['value']; $data[$tag] = $value; } return $data; }这里PHP返回 的接口参数是这样的,用postman调试后显示的是一个json字符串:
{"state": 1,"timeStamp": "1564389542","nonceStr": "dBMPdafhPvospBoRPbSZcIobiLncQdya","signType": "MD5","package": "prepay_id=wx291639019757571e2762612e1533749100","paySign": "78CB396C8FE94FD3F0C51AE8BB53F326","out_trade_no": 1564389541}
然后大家把这个字符串里面的参数复制到前端文件中,就可以正常调用微信支付了。
下面我用我的测试公众号(没有测试号的可以自己去申请一个测试号)去点击一下前端页面微信支付那个按钮,马上就出现了这样的一个界面:(如果没有出现这个界面,看下报了什么错,反馈给我,一般都是参数错了,或者签名不正确)

到这里基本就说明调用微信支付成功了。我这个是公众号的,小程序微信支付跟这个差不多,调用的函数是这个:
wx.requestPayment({ timeStamp: '1564371379', nonceStr: 'JoTcEhgphkSAXPcpSqYFqKFUDMktGulc', package: 'prepay_id=wx29113619598850b0682884011250194100', signType: 'MD5', paySign: '86BFA0E44B87FF783BB575F0B9FE584C', success (res) { }, fail (res) { } })最后需要注明的一点是:在微信支付的后台里面,网址:https://pay.weixin.qq.com/index.php/extend/pay_setting
我们要设置一点

大家按要求设置一个微信支付授权的域名就行了。
有很多朋友会问,为什么会出现这样那样的错误,其实开发中遇到的错误一般会有很明显的提示,这个是微信返回给你的提示。
比如说:
签名错误,这个有很多原因,但是微信一般就是说签名错误,他不会具体到哪里,主要是参数错误或者没按照要求排序了。
第一,可能是商户密匙错误,在申请支付后系统会给予一个商户账号和密码,这个密码是单独不能跟app的密匙混淆。
第二,没有按照要求去签名,请注意微信支付中的两次签名。
第一次签名有10个参数,必须按字典顺序排序,然后把生成的签名当做一个参数传给xml
这11个参数中只有三个是重要的【
$appid // 这个不用说了,公众号ID。
$mch_id // 商户号,开通微信支付,这个就是V信给你的银行卡号
$openid //自己去公众号后台看下关注列表,一定要是自己的,谁支付就是谁的
】,其他都是随便写的。
//签名方法再次说明: 签名步骤一:按字典序排序参数 ksort($this-values); $string = $this-ToUrlParams(); 签名步骤二:在string后加入KEY $string = $string . "&key=".WxPayConfig::KEY; 签名步骤三:MD5加密 $string = md5($string); 签名步骤四:所有字符转为大写 $result = strtoupper($string);请注意两次签名都是用这个方法,其中的key=WxPayConfig::KEY是唯一的,一定不能错。
谢谢大家,希望各位能快速玩转微信支付。













