在小程序中不能使用之前在瀏覽器中配置的支付功能,只能調用小程序專屬的api進行支付。
因為需要在現在實現的基礎上,再添加在小程序中調用微信支付功能,所以我的思路是這樣的
實現:
首先需要引入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; }
歡迎各位同仁交流~
加油哦~小王