h5內嵌微信小程式,呼叫微信支付功能
阿新 • • 發佈:2020-09-10
在小程式中不能使用之前在瀏覽器中配置的支付功能,只能呼叫小程式專屬的api進行支付。
因為需要在現在實現的基礎上,再新增在小程式中呼叫微信支付功能,所以我的思路是這樣的
實現:
首先需要引入wx的解析檔案
下載地址:https://github.com/wangvv9264/jweixin
<script type="text/javascript" src="/index/js/jweixin-1.3.2.js"></script>
判斷是不是在小程式中
varua = 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; }
歡迎各位同仁交流~
加油哦~小王