1. 程式人生 > 實用技巧 >h5內嵌微信小程式,呼叫微信支付功能

h5內嵌微信小程式,呼叫微信支付功能

在小程式中不能使用之前在瀏覽器中配置的支付功能,只能呼叫小程式專屬的api進行支付。

因為需要在現在實現的基礎上,再新增在小程式中呼叫微信支付功能,所以我的思路是這樣的

1.在點選支付按鈕時,判斷是不是在小程式中

2.呼叫小程式支付的頁面,並傳過去需要的值

3.在小程式支付的js檔案中進行呼叫

實現:

首先需要引入wx的解析檔案

下載地址:https://github.com/wangvv9264/jweixin

<script type="text/javascript" src="/index/js/jweixin-1.3.2.js"></script>

判斷是不是在小程式中

var
ua = navigator.userAgent.toLowerCase(); if(ua.match(/MicroMessenger/i)=="micromessenger") { //ios的ua中無miniProgram,但都有MicroMessenger(表示是微信瀏覽器) wx.miniProgram.getEnv((res)=>{ if (res.miniprogram) { console.log('在小程式內') wx.miniProgram.navigateTo({ url:
"/pages/prowxpay/prowxpay?info="+queryParam //小程式的支付地址,queryParam是需要傳遞的商品id等資料 }); return false; }else{ console.log('在微信內,但是不在小程式內') return false; } }) }else{ console.log('在微信外') return false; }

在小程式支付的js檔案中進行呼叫

var app = getApp();
Page({
  data: {
    bt: 'bt'
  },

  onLoad: 
function (options) { var that = this; if (options.goods_id) { that.setLoading(options); } else { wx.navigateBack();} }, setLoading: function(a) { var that = this wx.login({ success: function(res) { // 成功會返回: // {errMsg: "login:ok", code: "獲取使用者OpenID的ticket"} that.getOpenId(res.code,a) } }) }, getOpenId: function (jsCode,a) { var that = this wx.request({ url: baseURL + '/index/Xcxpay/login', //baseURL引入的https地址 data: { js_code: jsCode // wx.login()時得到的ticket }, success: function (res) { that.getPrePayId(res.data.openid,a) }, fail: function (res) { console.log(res) that.setData({ bt: '' }), wx.showModal({ title: "網路超時", content: "重新整理重試", showCancel: !1 }); } }) }, getPrePayId: function (openId, a) {var that = this wx.request({ url: baseURL + '/index/Xcxpay/index?openid='+openId+'&goods_id=' + a.goods_id , success: function (res) { console.log(res.data); if(res.data.status == 1) { that.pay(res.data.data,a); } else { var msg = String(res.data.msg); wx.showModal({ title: "提醒", content: msg, showCancel: !1, success(res) { if(res.confirm) { wx.navigateBack({ delta: 1 }) } } }) return false; } }, fail:function (res) { console.log(res); that.setData({ bt: '' }) } }) }, // data是服務端返回的JSON // 加上success、fail回撥後,正好符合wx.requestPayment()引數的格式 pay: function (res, a) { console.log(res) wx.requestPayment({ //成功之後,呼叫小程式微信支付 'timeStamp': res.timeStamp, 'nonceStr': res.nonceStr, 'package': res.package, 'signType': 'MD5', 'paySign': res.paySign, success: function (res) { console.log(res) wx.request({ url: baseURL + '/index/Xcxpay/callback?goods_id=' + a.goods_id + '&msg=' + res.errMsg, success: function(res){ console.log(res.data.status) if(res.data.status == 1) { wx.showToast({ title: '支付成功', icon: 'success', duration: 2000 }) setTimeout(()=>{ wx.redirectTo({ url: '/pages/order/order', }) },2001) } }, fail: function(){} }) }, fail: function (res) { console.log('付款失敗'); console.log(res) wx.showModal({ title: '提醒', content: '付款失敗', showCancel: false, success:function(res){ if(res.confirm) { wx.navigateBack({ delta: 1 }) } } }) return }, }) }, wdxreload: function(){ var pages = getCurrentPages(); var currentPage = pages[pages.length - 1]; //獲取當前頁面的物件 var url = currentPage.route; //當前頁面url var options = currentPage.options; //如果要獲取url中所帶的引數可以檢視options wx.navigateTo({ url: "/pages/wxpay/wxpay?goods_id=" + options.goods_id}); } })

我對接的後臺是php,下面附上程式碼

public function login() {
        $appid='微信小程式的appId';
        $secret='微信小程式的金鑰';

        $params = array(
          'appid' => $appid,
          'secret' => $secret,
          'js_code' => $_GET['js_code'], // 小程式傳來的ticket
          'grant_type' => 'authorization_code',
        );

        $ch = curl_init();
        curl_setopt($ch, CURLOPT_URL, 'https://api.weixin.qq.com/sns/jscode2session');
        curl_setopt($ch, CURLOPT_RETURNTRANSFER, 1);
        curl_setopt($ch, CURLOPT_POST, 1);
        curl_setopt($ch, CURLOPT_POSTFIELDS, $params);
        $output = curl_exec($ch);

        if (false === $output) {
          echo 'CURL Error:' . curl_error($ch);
        }
        echo $output;
        
    }

    //https://blog.csdn.net/u010505805/article/details/76861853
    public function index(){
        $order_id = isset($_GET['goods_id']) ? intval($_GET['goods_id']) : '';
        $openid = $_GET['openid'];

        $this->pub_index($openid,$order_id);

    }
    public function pub_index($openid,$order_id){
        $appid='小程式appId';
        $secret='微信小程式的金鑰';
        $url="https://api.mch.weixin.qq.com/pay/unifiedorder";

        $mch_id = '';//受理商ID(即微信支付商戶號)
        $mch_key = '';//商戶支付金鑰Key
        $order = $orderinfo=Db::name('order_info')->where('order_code="'.$order_id.'"')->find();
        $total_fee=$order['order_amount'] * 100;

        $params = array(
          'appid' => $appid,  // 小程式appid
          'mch_id' => $mch_id,
          'nonce_str' => (string)mt_rand(10000, 99999),   // 隨機串,32字元以內
          'body' => ' ',   // 商品名
          'out_trade_no' => $order['order_code'], 
          //'out_trade_no' => substr( $order['order_code'].'A'.($order['order_amount']*100).'B' ,0,32),  
          //訂單號32字元以內。串接後取前32位。多次支付時如果重複的話,微信會返回“重複下單”
          'spbill_create_ip' => $_SERVER['REMOTE_ADDR'],
          'notify_url' => '',  // 支付成功後的回撥地址,由騰訊服務端回撥
          'trade_type' => 'JSAPI',
          'openid' => $openid,  // 小程式傳來的OpenID
          'total_fee' =>(string)$total_fee,  // 訂單費用,單位:分
        );

        //var_dump($params);die;
        // 按照要求計算sign
        ksort($params);
        $sequence = '';
        foreach ($params as $key => $value) {
          $sequence .= "$key=$value&";
        }

        $sequence = $sequence . "key=".$mch_key;
        //echo $sequence;die;
        $params['sign'] = strtoupper(md5($sequence));

        $xml =$this->arrayToXml($params);


        $ch = curl_init();
        curl_setopt($ch, CURLOPT_URL,$url);
        curl_setopt($ch, CURLOPT_RETURNTRANSFER, 1);
        curl_setopt($ch, CURLOPT_POST, 1);
        curl_setopt($ch, CURLOPT_POSTFIELDS, $xml);
        curl_setopt($ch, CURLOPT_SSL_VERIFYPEER, false);
        curl_setopt($ch, CURLOPT_SSL_VERIFYHOST, false);
        $output = curl_exec($ch);


        if (false === $output) {
          echo 'CURL Error:' . curl_error($ch);
        }
        // 下單成功的話,微信返回個XML,裡面包含prepayID,提取出來

        $match=$this->xml_to_array($output);
        //var_dump($match);die;

        if($match['result_code']=='FAIL'){
            $result['status']=3;
            $result['msg']=$match['err_code_des'];
            die(json_encode($result));
        }

        // 這裡不是給小程式返回個prepayID,而是返回一個包含其他欄位的JSON
        // 這個JSON小程式自己也可以生成,放在服務端生成是出於兩個考慮:
        // 1. 小程式的appid不用寫在小程式的程式碼裡,appid、secret資訊全部由伺服器管理,比較安全
        // 2. 計算paySign需要用到md5,小程式端使用的是JavaScript,沒有內建的md5函式,放在服務端計算md5比較方便

        @$prepayId = $match['prepay_id'];

        if(!$match['prepay_id']){
            $result['status']=4;
            $result['msg']='prepay_id為空,請檢視具體原因';
            die(json_encode($result));
        }
        $response= array(
          'appId' => $appid,        //小程式appid
          'nonceStr' => (string) mt_rand(10000, 99999),          // 隨機串,32個字元以內
          'package' => (string)'prepay_id=' . $prepayId,
          'signType' => 'MD5',
          'timeStamp' => (string) time(),          // 時間戳,注意得是字串形式的
        );
        $sequence = '';
        foreach ($response as $key => $value) {
          $sequence .= "$key=$value&";
        }
        $response['paySign'] = strtoupper(md5("{$sequence}key=".$mch_key));


        //$info['aaa']=(string)$prepayId;

        $result['status']=1;
        $result['msg']='成功';
        $result['data']=$response;
        die(json_encode($result));
    }
function callback(){
        $order_id = $_GET['goods_id'];
        
        $result = Db::name('')->where("order_code='".$order_id."'")->update(array('pay_status'=>1,'order_status'=>1,'pay_time'=>time(),'pay_id'=>1,'pay_name'=>'微信','pay_platform'=>'小程式支付'));

        $orderinfo = Db::name("")->field('order_amount,add_time')->where("order_code='".$order_id."'")->find();
        Db::name('order_log')->insert(array('order_code'=>$order_id,'type'=>'小程式微信支付','addtime'=>date('Y-m-d H:i:s',$orderinfo['add_time']),'paytime'=>date('Y-m-d H:i:s',time()),'order_amount'=>$orderinfo['order_amount'],'remark'=>'SUCCESS'));
        $data['status']=1;
        die(json_encode($data));
    }
    function notify($data)
    {
        $inputdata = file_get_contents("php://input");
        if (! empty($inputdata)) {
            
            $payment = model('Payment')->get_payment("wxpay");
            $postdata = json_decode(json_encode(simplexml_load_string($inputdata, 'SimpleXMLElement', LIBXML_NOCDATA)), true);
            /* 檢查外掛檔案是否存在,如果存在則驗證支付是否成功,否則則返回失敗資訊 */
            // 微信端簽名
            $wxsign = $postdata['sign'];
            unset($postdata['sign']);

            // 微信附加引數
            $attach = $postdata['attach'];

            foreach ($postdata as $k => $v) {
                $Parameters[$k] = $v;
            }
            // 簽名步驟一:按字典序排序引數
            ksort($Parameters);

            $buff = "";
            foreach ($Parameters as $k => $v) {
                $buff .= $k . "=" . $v . "&";
            }
            $String;
            if (strlen($buff) > 0) {
                $String = substr($buff, 0, strlen($buff) - 1);
            }
            // 簽名步驟二:在string後加入KEY
            $String = $String . "&key=" . $payment['wxpay_key'];
            // 簽名步驟三:MD5加密
            $String = md5($String);
            // 簽名步驟四:所有字元轉為大寫
            $sign = strtoupper($String);
            // 驗證成功
            if ($wxsign == $sign) {
                // 交易成功
                $returndata['return_code'] = 'SUCCESS';
            } else {
                $returndata['return_code'] = 'FAIL';
            }
        } else {
            $returndata['return_code'] = 'FAIL';
            $returndata['return_msg'] = '無資料返回';
        }
        // 陣列轉化為xml
        $xml =$this->arrayToXml($returndata);

        echo $xml;
        exit();       
    }    
    function arrayToXml($arr)
    {

        $xml = "<xml>";
        foreach ($arr as $key=>$val)
        { 
            if (is_array($val)){
                $xml.="<".$key.">".arrayToXml($val)."</".$key.">";
            }else{
                $xml.="<".$key.">".$val."</".$key.">";
            }
        }
        $xml.="</xml>";
        
        return $xml;
    }
    function xml_to_array($xml){
        if(!$xml){
            return false;
        }
        //將XML轉為array
        //禁止引用外部xml實體
        libxml_disable_entity_loader(true);
        $data = json_decode(json_encode(simplexml_load_string($xml, 'SimpleXMLElement', LIBXML_NOCDATA)), true);
        return $data;
    } 

歡迎各位同仁交流~

加油哦~小王