公众号,小程序微信支付基于PHP后端,附完整流程【小白教程,大神绕道,附支付错误解决办法】

各位好,以下教程适合初次接触微信支付的小白,这是一个小白都能看懂,并且立即复制就能用的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()">
</div>

<script 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;$i<32;$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是唯一的,一定不能错。

谢谢大家,希望各位能快速玩转微信支付。

评论 2
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

Jason Ho

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值