h5内嵌微信小程序,调用微信支付功能
在小程序中不能使用之前在浏览器中配置的支付功能,只能调用小程序专属的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; }
欢迎各位同仁交流~
加油哦~小王
版权声明:本文为wangvv原创文章,遵循 CC 4.0 BY-SA 版权协议,转载请附上原文出处链接和本声明。