thinkphp微信浏览器内拉起微信支付
Posted Champion-水龙果
tags:
篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了thinkphp微信浏览器内拉起微信支付相关的知识,希望对你有一定的参考价值。
vendor/wxpay/pay.php
<?php /* +-----------------------------------+ | 微信支付类 | +-----------------------------------+ */ require_once \'config.php\'; class pay{ public $params = array(); private $url = \'https://api.mch.weixin.qq.com/pay/unifiedorder\'; private $prepay_id; //统一下单号 /** * * 获取jsapi支付的参数 * @param array $UnifiedOrderResult 统一支付接口返回的数据 * @throws WxPayException * @return json数据,可直接填入js函数作为参数 */ public function GetJsApiParameters() { $this->doneOrder(); $timeStamp = time(); $this->params = array( \'appId\' => Config::APPID, \'timeStamp\'=> "$timeStamp", \'nonceStr\' => $this->getNonceStr(), \'package\' => \'prepay_id=\' . $this->prepay_id, \'signType\' => \'MD5\' ); $this->params[\'paySign\'] = $this->MakeSign(); } /** * 统一下单 * @return array */ public function doneOrder(){ $this->params[\'mch_id\'] = Config::MCHID; $this->params[\'appid\'] = Config::APPID; $this->params[\'sign\'] = $this->MakeSign($this->params); $response = $this->FromXml($this->postXmlCurl($this->ToXml(), $this->url, false)); $this->prepay_id = $response[\'prepay_id\']; } /** * 验证 * @return array 返回数组格式的notify数据 */ public function notify(){ //获取xml $xml = file_get_contents(\'php://input\'); //转成php数组 $this->params = $this->FromXml($xml); //保存原sign $data_sign = $this->params[\'sign\']; //sign不参与签名 unset($this->params[\'sign\']); $sign = $this->makeSign(); //判断签名是否正确 判断支付状态 if ($sign===$data_sign && $this->params[\'return_code\']==\'SUCCESS\' && $this->params[\'result_code\']==\'SUCCESS\') { $result = $this->params; $str = \'<xml><return_code><![CDATA[SUCCESS]]></return_code><return_msg><![CDATA[OK]]></return_msg></xml>\'; }else{ $result = false; $str = \'<xml><return_code><![CDATA[FAIL]]></return_code><return_msg><![CDATA[签名失败]]></return_msg></xml>\'; } echo $str; return $result; } /** * 生成签名 * @return 签名,本函数不覆盖sign成员变量,如要设置签名需要调用SetSign方法赋值 */ public function MakeSign() { //签名步骤一:按字典序排序参数 ksort($this->params); $string = $this->ToUrlParams(); //签名步骤二:在string后加入KEY $string = $string . \'&key=\' . Config::KEY; //签名步骤三:MD5加密 $string = md5($string); //签名步骤四:所有字符转为大写 $result = strtoupper($string); return $result; } /** * 格式化参数格式化成url参数 */ public function ToUrlParams() { $buff = \'\'; foreach($this->params as $k => $v) { if($k!=\'sign\' && $v!=\'\' && !is_array($v)){ $buff .= $k . \'=\' . $v . \'&\'; } } $buff = trim($buff, \'&\'); return $buff; } /** * 以post方式提交xml到对应的接口url * @param string $xml 需要post的xml数据 * @param string $url url * @param bool $useCert 是否需要证书,默认不需要 * @param int $second url执行超时时间,默认30s * @throws WxPayException */ private static function postXmlCurl($xml, $url, $useCert = false, $second = 30) { $ch = curl_init(); //设置超时 curl_setopt($ch, CURLOPT_TIMEOUT, $second); //如果有配置代理这里就设置代理 if(Config::CURL_PROXY_HOST != "0.0.0.0" && Config::CURL_PROXY_PORT != 0){ curl_setopt($ch,CURLOPT_PROXY, Config::CURL_PROXY_HOST); curl_setopt($ch,CURLOPT_PROXYPORT, Config::CURL_PROXY_PORT); } curl_setopt($ch,CURLOPT_URL, $url); curl_setopt($ch,CURLOPT_SSL_VERIFYPEER,FALSE); curl_setopt($ch,CURLOPT_SSL_VERIFYHOST,FALSE);//严格校验 //设置header curl_setopt($ch, CURLOPT_HEADER, FALSE); //要求结果为字符串且输出到屏幕上 curl_setopt($ch, CURLOPT_RETURNTRANSFER, TRUE); if($useCert == true){ //设置证书 //使用证书:cert 与 key 分别属于两个.pem文件 curl_setopt($ch,CURLOPT_SSLCERTTYPE,\'PEM\'); curl_setopt($ch,CURLOPT_SSLCERT, Config::SSLCERT_PATH); curl_setopt($ch,CURLOPT_SSLKEYTYPE,\'PEM\'); curl_setopt($ch,CURLOPT_SSLKEY, Config::SSLKEY_PATH); } //post提交方式 curl_setopt($ch, CURLOPT_POST, TRUE); curl_setopt($ch, CURLOPT_POSTFIELDS, $xml); //运行curl $data = curl_exec($ch); //返回结果 if($data){ curl_close($ch); return $data; } else { $error = curl_errno($ch); curl_close($ch); throw new Exception("curl出错,错误码:$error"); } } /** * 输出xml字符 * @throws WxPayException **/ public function ToXml() { if(!is_array($this->params) || count($this->params) <= 0) { throw new Exception(\'数组数据异常!\'); } $xml = \'<xml>\'; foreach($this->params as $key=>$val) { if(is_numeric($val)){ $xml .= \'<\'.$key.\'>\'.$val.\'</\'.$key.\'>\'; }else{ $xml .= \'<\'.$key.\'><![CDATA[\'.$val.\']]></\'.$key.\'>\'; } } $xml .= \'</xml>\'; return $xml; } /** * 将xml转为array * @param string $xml * @throws WxPayException */ public function FromXml($xml) { if(!$xml){ throw new Exception(\'xml数据异常!\'); } //将XML转为array //禁止引用外部xml实体 libxml_disable_entity_loader(true); $this->params = json_decode(json_encode(simplexml_load_string($xml, \'SimpleXMLElement\', LIBXML_NOCDATA)), true); return $this->params; } /** * * 产生随机字符串,不长于32位 * @param int $length * @return 产生的随机字符串 */ public function getNonceStr($length = 32) { $chars = \'abcdefghijklmnopqrstuvwxyz0123456789\'; $str = \'\'; for($i = 0; $i<$length; $i++){ $str .= substr($chars, mt_rand(0, strlen($chars)-1), 1); } return $str; } } ?>
vendor/wxpay/config.php
<?php /** * 配置账号信息 */ class Config { //=======【基本信息设置】===================================== // /** * TODO: 修改这里配置为您自己申请的商户信息 * 微信公众号信息配置 * * APPID:绑定支付的APPID(必须配置,开户邮件中可查看) * * MCHID:商户号(必须配置,开户邮件中可查看) * * KEY:商户支付密钥,参考开户邮件设置(必须配置,登录商户平台自行设置) * 设置地址:https://pay.weixin.qq.com/index.php/account/api_cert * * APPSECRET:公众帐号secert(仅JSAPI支付的时候需要配置, 登录公众平台,进入开发者中心可设置), * 获取地址:https://mp.weixin.qq.com/advanced/advanced?action=dev&t=advanced/dev&token=2005451881&lang=zh_CN * @var string */ const APPID = \'wx000000000000\'; const MCHID = \'xxxxxxx\'; const KEY = \'xxxxxxxxxxxxxxxxxxxxxxxxxxx\'; const APPSECRET = \'xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx\'; //=======【证书路径设置】===================================== /** * TODO:设置商户证书路径 * 证书路径,注意应该填写绝对路径(仅退款、撤销订单时需要,可登录商户平台下载, * API证书下载地址:https://pay.weixin.qq.com/index.php/account/api_cert,下载之前需要安装商户操作证书) * @var path */ const SSLCERT_PATH = \'cert/apiclient_cert.pem\'; const SSLKEY_PATH = \'cert/apiclient_key.pem\'; //=======【curl代理设置】=================================== /** * TODO:这里设置代理机器,只有需要代理的时候才设置,不需要代理,请设置为0.0.0.0和0 * 本例程通过curl使用HTTP POST方法,此处可修改代理服务器, * 默认CURL_PROXY_HOST=0.0.0.0和CURL_PROXY_PORT=0,此时不开启代理(如有需要才设置) * @var unknown_type */ const CURL_PROXY_HOST = "0.0.0.0";//"10.152.18.220"; const CURL_PROXY_PORT = 0;//8080; //=======【上报信息配置】=================================== /** * TODO:接口调用上报等级,默认紧错误上报(注意:上报超时间为【1s】,上报无论成败【永不抛出异常】, * 不会影响接口调用流程),开启上报之后,方便微信监控请求调用的质量,建议至少 * 开启错误上报。 * 上报等级,0.关闭上报; 1.仅错误出错上报; 2.全量上报 * @var int */ const REPORT_LEVENL = 0; }
vendor/cert/apiclient_cert.pem vendor/cert/apiclient_key.pem 控制器Controller
Vendor(\'wechat.pay\'); class Wechat extends Base { public function wxPay(){ $payobj = new \\pay(); $openid = input(\'post.openid/s\'); $needMoney = input(\'post.money/s\'); if (!empty($openid)) { //统一下单 $orderid = $this->build_order_no(); $notify_url = \'http://xxxxxx/Wechat/notify\'; $payobj->params = [ \'openid\' => $openid, \'body\' => \'body\', \'out_trade_no\' => $orderid, \'total_fee\' => $needMoney * 100, \'nonce_str\' => $this->getNonceStr(), \'spbill_create_ip\' => getIp(), \'notify_url\' => $notify_url, \'trade_type\' => \'JSAPI\' ]; $payobj->GetJsApiParameters(); $data = [ \'order_num\' => $orderid, \'user_open_id\' => $openid, \'pay_money\' => $needMoney, ]; $oid = Db::name(\'order_pay\')->insert($data); if($oid){ return [\'status\'=>\'0\',\'info\'=>\'ok\',\'data\'=>json_encode($payobj->params)]; } return [\'status\'=>\'-1\',\'info\'=>\'下单失败,请重试\']; } } //微信支付回调 public function notify(){ $payobj = new \\pay(); $result = $payobj->notify(); if($result){ //成功后回调 $where[\'order_num\'] = $result[\'out_trade_no\']; //根据需求处理逻辑 } } /** * 生成订单号码 * @return string */ public function build_order_no() { return date(\'Ymd\') . substr(implode(NULL, array_map(\'ord\', str_split(substr(uniqid(), 7, 6), 1))), 0, 8) . mt_rand(100,999); } /** * 产生随机字符串,不长于32位 * @param int $length * @return 产生的随机字符串 */ public function getNonceStr($length = 32) { $chars = \'abcdefghijklmnopqrstuvwxyz0123456789\'; $str = \'\'; for($i = 0; $i<$length; $i++){ $str .= substr($chars, mt_rand(0, strlen($chars)-1), 1); } return $str; } }
页面上View 引用jquery; 引用layui.js 引用jweixin-1.1.0.js
<script type="text/javascript"> $.ajax({ url:"http://xxxxxx/Wechat/wxPay", type:\'post\', data:{\'money\':money,\'openid\':openid}, async : false, dataType: "JSON", success:function(data){ if(data.status === \'0\'){ var params = $.parseJSON(data.data); // alert(data.url); WeixinJSBridge.invoke(\'getBrandWCPayRequest\', params, function(res){ if(res.err_msg == \'get_brand_wcpay_request:cancel\'){ layer.open({ content: \'您消了此次支付\' ,skin: \'msg\' ,time: 5 //2秒后自动关闭 }); }else if(res.err_msg == \'get_brand_wcpay_request:fail\'){ layer.open({ content: \'支付失败,请重新支付\' ,skin: \'msg\' ,time: 5 //2秒后自动关闭 }); }else if(res.err_msg == \'get_brand_wcpay_request:ok\'){ layer.open({ content: \'支付成功\' ,skin: \'msg\' ,time: 5 //2秒后自动关闭 }); setTimeout(function(){ window.location.href = \'index.html\'; },2000); }else{ layer.open({ content: "未知错误"+res.error_msg ,skin: \'msg\' ,time: 5 //2秒后自动关闭 }); } }); }else{ layer.open({ content: data.info ,skin: \'msg\' ,time: 5 //2秒后自动关闭 }); return false; } } }); </script>
以上是关于thinkphp微信浏览器内拉起微信支付的主要内容,如果未能解决你的问题,请参考以下文章