在小程序中不能使用之前在浏览器中配置的支付功能,只能调用小程序专属的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; }
欢迎各位同仁交流~
加油哦~小王