PHP实现微信支付(微信小程序版)

先解答上一篇博客中form_id的获取方法:
js代码


Page({
  formSubmit: function (e) {
    console.log("formid:"+e.detail.formId)
  },
})

wxml代码

结果:
PHP实现微信支付(微信小程序版)_第1张图片

注意两点

  1. 表单wxml中需要加入,普通表单是不携带formId。
  2. formId只在真器中才能获取,开发者工具无法获取。

下面开始讲解PHP实现微信小程序支付

准备工作:

1.你的小程序做过微信认证并且开通微信支付(相信能学编程的都不是愚笨之人,跟着微信指引填写资料就行,剩下就等他客服打电话给你)
2.微信小程序appid
3.微信商户号mch_id(开户邮件里面有)
4.微信API密钥key(登录商户平台->账户中心->API安全自行设置)

开发步骤:

1.获取prepay_id
2.获取paySign

封装方法代码:

self::appid,     //appid
            "mch_id"=>self::mch_id, //商户号
            "nonce_str"=>$nonce_str,  //随机字符串
            "sign"=>$SignTemp,    //签名
            "body"=>self::body,   //商品描述
            "out_trade_no"=>$out_trade_no, //订单号
            "total_fee"=>self::total_fee,   //金额
            "trade_type"=>"JSAPI",  //支付类型 小程序取值如下:JSAPI 其他支付参照官方文档
            "notify_url"=>self::notify_url,  //异步接收微信支付结果通知的回调地址
            "openid"=>$openid   //用户对应小程序的openid
        ];
        $result=HttpUtils::curl(self::url,$params=self::XmlAndArray($data,"array"),$ispost=1,$https=1);//请求接口得到预支付信息,curl方法在前一篇文章已经贴出,参数必须为xml格式,方法已给出XmlAndArray()
        return self::XmlAndArray($result,"xml"); //转化为数组方便取值,返回结果
    }
    public static function getPaySign($prepay_id,$nonce_str){
        $timeStamp=time();//时间戳
        $PaySign=md5("appId=".self::appid."&nonceStr=".$nonce_str."&package=prepay_id=".$prepay_id."&signType=MD5&timeStamp=".(string)$timeStamp."&key=".self::key);//生成支付签名,严格按照官方要求填写参数
        return ["PaySign"=>$PaySign,"timeStamp"=>$timeStamp];//返回签名以及时间戳
    }

    private static function getSignTemp($nonce_str,$openid,$out_trade_no){
        $SignTemp="appid=".self::appid."&body=".self::body."&mch_id=".self::mch_id."&nonce_str=".$nonce_str."¬ify_url=".self::notify_url."&openid=".$openid."&out_trade_no=".$out_trade_no."&total_fee=".self::total_fee."&trade_type=JSAPI";//生成下单签名,严格按照官方要求填写参数
        $SignTemp=md5($SignTemp."&key=".self::key);
        return $SignTemp; //返回签名,统一下单需要调用
    }

    /**
     * 数组与XML互转 方便取数据
     * @param $data
     * @param $type 转换对象
     * return 数组或XML
     */

    private static function XmlAndArray($data,$type)
    {
        if(!$data){
            return false;
        }
        else if($type=="xml"){
            libxml_disable_entity_loader(true);
            $values = json_decode(json_encode(simplexml_load_string($data, 'SimpleXMLElement', LIBXML_NOCDATA)), true);
            return $values;
        }
        else if($type=="array"){
            $xml="";
            foreach ($data as $key=>$val){

                $xml.="<".$key.">".$val."";

            }
            $xml.="";
            return $xml;
        }
    }
    /**
     * 随机字符串生成
     * @param $length 字符串长度
     * @param $char  字符集
     * return $string 随机字符串
     */

    private static function str_rand($length = 32, $char = 'abcdefghijklmnopqrstuvwxyz0123456789') {
        $str ="";
        for ( $i = 0; $i < $length; $i++ )  {
            $str .= substr($char, mt_rand(0, strlen($char)-1), 1);
        }
        return $str;
    }
}

调用代码,我用的laravel框架,可以自行重构

get("openid");    //接收openid
        $out_trade_no="";  //订单号
        $PrePay=WxPay::PrePay($out_trade_no,$openid);  //统一下单
        if($PrePay["return_code"]=="FAIL"){
            /*返回错误*/
        }
        else{
            $PrePayId=$PrePay["prepay_id"];  // 获取预支付id
            $PaySign=WxPay::getPaySign($PrePayId,$PrePay["nonce_str"]); 生成支付签名
            echo json_encode(["prepay_id"=>$PrePayId,"paySign"=>$PaySign["PaySign"],"nonce_str"=>$PrePay["nonce_str"],"timeStamp"=>$PaySign["timeStamp"],"order_no"=>$out_trade_no]); //返回小程序中拉起支付所需要的信息
        }
    }
}

小程序调用代码:

 wx.request({
      url: "你的服务器端接口地址",
      data: {
        openid: "用户的openid",
      },
      header: {
        'content-type': 'application/json'
      },
      success: function (res) {
        let prepay_id = res.data.prepay_id  //预支付id
        let order_no = res.data.order_no    //订单号
        let timeStamp = String(res.data.timeStamp)  //服务器端返回的时间戳,必须强转字符串,微信要求的
        let nonceStr = res.data.nonce_str //服务器返回的随机字符串
        let package = 'prepay_id=' + res.data.prepay_id //package需要这么填写,自己注意
        let paySign = res.data.paySign //支付签名
        if (res.data.code == "") {  
         //服务器端预支付处理失败提示 
          wx.showToast({
            title: '下单失败',
            icon: 'none',
            duration: 1000
          })
        }
        else {
          // 拉起微信支付
          wx.requestPayment({
            'timeStamp': timeStamp,
            'nonceStr': nonceStr,
            'package': package,
            'signType': 'MD5',
            'paySign': paySign,
             success: function (res) {
              //接口调用成功的回调函数
             },
             fail:function(res){
               //接口调用失败的回调函数
             },
             complete:function(res){
               //接口调用结束的回调函数(调用成功、失败都会执行)
             }
          })
        }
      }
    })

总结

  1. 最重要的就是生成签名一定要按照官方给出的文档,参数顺序不能搞错!!!
  2. 所有接口返回的都是xml,为了方便我都转化成数组,方法也在代码中给出。
  3. 随机字符串生成后,会在统一下单接口返回值中给出,生成PaySign签名时延用就行,第一次开发就卡在这,能拉起支付,然后闪退说PaySign错误
  4. 统一下单接口返回的prepay_id就是模板消息需要的参数,支付成功后就可以用此参数调用模板消息提示用户
  5. 作者自己写了个小程序BadBoy,有兴趣的可以搜索来玩玩,其中的代码可找作者索取
  6. 微信小程序交流群:895964328 php交流群:165728481

你可能感兴趣的:(微信支付,微信小程序,PHP,Laravel,模板消息)