前端页面php
//验证是不是微信内置浏览器 function is_weixn(){ var ua = navigator.userAgent.toLowerCase(); if(ua.match(/MicroMessenger/i) == "micromessenger"){ return true; } else { return false; } }
PHPhtml
case '3': //微信内置浏览器JSAPI支付 $sHtml = '<form id="orderSubmit" name="orderSubmit" action="'.U('Wechat/wxpayJsApi').'" method="post">'; $sHtml .= '<input type="hidden" name="out_trade_no" value="'.$order['order_sn'].'" />'; $sHtml .= '<input type="hidden" name="body" value="萄萄汇商城 - '.$goods_name.'" />'; $sHtml .= '<input type="hidden" name="total_fee" value="'.$order['payable_amount'].'" />'; $sHtml .= '<input type="submit" value="Submit" style="display:none;" /></form>'; $sHtml .= '<script>document.forms["orderSubmit"].submit();</script>'; echo $sHtml; break;
DEOM前端
<?php namespace Mobile\Controller; use Think\Controller; class WechatController extends Controller{ //$stime = microtime(true); //$etime = microtime(true); echo ($etime - $stime); //需先设置好微信支付受权目录和网页受权域名,扫码支付模式一需设置支付回调URL,模式二不须要设置 const TOKEN = 'StupidLi'; //token令牌 //const ORIGINAL_ID = 'gh_63e349ac0af5'; //微信公众号原始ID const APP_ID = 'wx8d7d0d6d81dc5056'; //微信公众号应用ID const APP_SECRET = 'cc41f16e6620443dcb7a4f6e85efbbca'; //微信公众号应用密钥 //const ENCODING_AES_KEY = 'S1X0CAP7JlNInE6NKyglXdZWt2rrh0g1oIIpOOil3rH'; //消息加解密密钥 const MCH_ID = '1420243602'; //微信支付商户号 const MCH_KEY = '0MrxTO6bhOikziaGnAMgr1xec9bIFRxP'; //微信支付商户密钥 const RETURN_URL = 'http://m.tthwine.com/Wechat/wxpayReturn.html'; //支付结果同步通知地址 const NOTIFY_URL = 'http://m.tthwine.com/Wechat/wxpayNotify.html'; //支付结果异步通知地址 /** * TODO:设置商户证书路径 * 证书路径,注意应该填写绝对路径(仅退款、撤销订单时须要,可登陆商户平台下载, * API证书下载地址:https://pay.weixin.qq.com/index.php/account/api_cert,下载以前须要安装商户操做证书) */ const SSLCERT_PATH = './ThinkPHP/Library/Vendor/Wechat/cert/apiclient_cert.pem'; const SSLKEY_PATH = './ThinkPHP/Library/Vendor/Wechat/cert/apiclient_key.pem'; /** * TODO:这里设置CURL代理机器,只有须要代理的时候才设置,不须要代理,请设置为0.0.0.0和0 * 本例程经过curl使用HTTP POST方法,此处可修改代理服务器, * 默认CURL_PROXY_HOST=0.0.0.0和CURL_PROXY_PORT=0,此时不开启代理(若有须要才设置) */ const CURL_PROXY_HOST = '0.0.0.0'; //"10.152.18.220" const CURL_PROXY_PORT = 0; //8080 private $access_token = ''; //公共基础开发的access_token private $access_token_a = ''; //用户受权凭证,即用code换取的access_token, private $curl_timeout = 30; //curl超时 public function _initialize(){ header("Content-type: text/html; charset=utf-8"); vendor("Wechat.WxPayException"); //异常处理类 vendor("Wechat.WxPayFunction"); //基础方法类 } //微信应用基础开发服务地址 public function index(){ //file_put_contents('./Data/paylog/wechatlog.txt', $_SERVER['REMOTE_ADDR'].' '.$_SERVER['QUERY_STRING']."\r\n", FILE_APPEND); if(isset($_GET['echostr'])){ //验证token $checkResult = $this->checkSignature($_GET['signature'], TOKEN, $_GET['timestamp'], $_GET['nonce']); if($checkResult == true){ echo $_GET['echostr']; exit; } }else{ $this->reponseMsg(); //其余基础开发程序 //libxml_disable_entity_loader(true); //$values = json_decode(json_encode(simplexml_load_string($res, 'SimpleXMLElement', LIBXML_NOCDATA)), true); //file_put_contents("./Data/paylog/TEXTQ.txt", "1111333", FILE_APPEND ); } } //应用开发验证签名 protected function checkSignature($signature, $token, $timestamp, $nonce){ $tmpArr = array($token, $timestamp, $nonce); sort($tmpArr, SORT_STRING); $tmpStr = implode($tmpArr); $tmpStr = sha1($tmpStr); if($tmpStr == $signature){ return true; }else{ return false; } } //回复事件 public function reponseMsg(){ //1.获取到微信推送过来post数据(xml格式) $postArr = $GLOBALS['HTTP_RAW_POST_DATA']; //2.处理消息类型,并设置回复类型和内容 $postObj = simplexml_load_string( $postArr ); //判断该数据包是不是订阅的事件推送 if( strtolower( $postObj->MsgType) == 'event'){ //若是是关注 subscribe 事件 if( strtolower($postObj->Event == 'subscribe') ){ //回复用户消息(纯文本格式) $toUser = $postObj->FromUserName; $fromUser = $postObj->ToUserName; $arr = array( array( 'title'=>'中秋月醇-月饼礼盒套装可预约啦', 'description'=>"中秋月醇-十二星座红酒配月饼礼盒套装能够预约了", 'picUrl'=>'https://mmbiz.qlogo.cn/mmbiz_jpg/gOCpHN587Z330josics98BkbFntIeVHq795A4ibqicANzzicdOico79kqOaHHicdMeFD9CwyKhk1BYTw4sS7icuTg0V1g/0?wx_fmt=jpeg', 'url'=>'https://mp.weixin.qq.com/s?__biz=MzIzMTY5MzI3Ng==&mid=2247483661&idx=1&sn=7e51c19aa3ec2672986c4b35d07e74b1&chksm=e8a10fbedfd686a8cd571951b64abcf2f680e6bdcbfdf4fb764dae22a961d9c91b78e471b5a3#rd', ), array( 'title'=>'百葡汇--名庄红酒价格搜索中心', 'description'=>"百葡汇--名庄红酒价格搜索中心", 'picUrl'=>'http://www.baipuhui.com/Public/Home/Images/logo.png', 'url'=>'http://www.baipuhui.com/', ), array( 'title'=>'萄萄汇--红酒商城', 'description'=>"葡葡汇--红酒商城", 'picUrl'=>'http://www.tthwine.com/Public/Home/img/logo.png', 'url'=>'http://m.tthwine.com', ), ); $template = "<xml> <ToUserName><![CDATA[%s]]></ToUserName> <FromUserName><![CDATA[%s]]></FromUserName> <CreateTime>%s</CreateTime> <MsgType><![CDATA[%s]]></MsgType> <ArticleCount>".count($arr)."</ArticleCount> <Articles>"; foreach($arr as $k=>$v){ $template .="<item> <Title><![CDATA[".$v['title']."]]></Title> <Description><![CDATA[".$v['description']."]]></Description> <PicUrl><![CDATA[".$v['picUrl']."]]></PicUrl> <Url><![CDATA[".$v['url']."]]></Url> </item>"; } $template .="</Articles> </xml> "; echo sprintf($template, $toUser, $fromUser, time(), 'news'); }elseif( strtolower($postObj->Event == 'unsubscribe') ){ //回复用户消息(纯文本格式) $toUser = $postObj->FromUserName; $fromUser = $postObj->ToUserName; $time = time(); $msgType = 'event'; $event = 'unsubscribe'; $content = '欢迎关注咱们的微信公众帐号'; $template = "<xml> <ToUserName><![CDATA[%s]]></ToUserName> <FromUserName><![CDATA[%s]]></FromUserName> <CreateTime>%s</CreateTime> <MsgType><![CDATA[%s]]></MsgType> <Event><![CDATA[%s]]></Event> </xml>"; $info = sprintf($toUser, $fromUser, $time, $msgType, $event, $content, $template); echo $info; } } //内容的回复多图文的 if( strtolower($postObj->MsgType) == 'text' && strtolower($postObj->Content)=='tw' ){ $toUser = $postObj->FromUserName; $fromUser = $postObj->ToUserName; $arr = array( array( 'title'=>'再见科比,再见青春', 'description'=>"再见科比,再见青春", 'picUrl'=>'http://img1.gtimg.com/sports/pics/hv1/226/138/2052/133466716.jpg', 'url'=>'http://sports.qq.com/a/20160414/040599.htm', ), array( 'title'=>'百葡汇--红酒搜索中心', 'description'=>"百葡汇--红酒搜索中心", 'picUrl'=>'http://www.baipuhui.com/Public/Home/Images/logo.png', 'url'=>'http://www.baipuhui.com/', ), array( 'title'=>'淘淘wine', 'description'=>"淘淘wine", 'picUrl'=>'http://www.tthwine.com/Public/Home/img/logo.png', 'url'=>'http://www.tthwine.com/', ), ); $template = "<xml> <ToUserName><![CDATA[%s]]></ToUserName> <FromUserName><![CDATA[%s]]></FromUserName> <CreateTime>%s</CreateTime> <MsgType><![CDATA[%s]]></MsgType> <ArticleCount>".count($arr)."</ArticleCount> <Articles>"; foreach($arr as $k=>$v){ $template .="<item> <Title><![CDATA[".$v['title']."]]></Title> <Description><![CDATA[".$v['description']."]]></Description> <PicUrl><![CDATA[".$v['picUrl']."]]></PicUrl> <Url><![CDATA[".$v['url']."]]></Url> </item>"; } $template .="</Articles> </xml> "; echo sprintf($template, $toUser, $fromUser, time(), 'news'); //注意:进行多图文发送时,子图文个数不能超过10个 }else{ switch( strtolower($postObj->Content) ){ case 1: $content = '您输入的数字是1'; break; case 2: $content = '您输入的数字是2'; break; case 3: $content = '您输入的数字是3'; break; case 4: $content = "<a href='http://www.imooc.com'>慕课</a>"; break; case '英文': $content = 'imooc is ok'; break; } $template = "<xml> <ToUserName><![CDATA[%s]]></ToUserName> <FromUserName><![CDATA[%s]]></FromUserName> <CreateTime>%s</CreateTime> <MsgType><![CDATA[%s]]></MsgType> <Content><![CDATA[%s]]></Content> </xml>"; //注意模板中的中括号 不能少 也不能多 $fromUser = $postObj->ToUserName; $toUser = $postObj->FromUserName; $time = time(); $msgType = 'text'; echo sprintf($template, $toUser, $fromUser, $time, $msgType, $content); }//if end // 付款推送 if( strtolower( $postObj->MsgType) == 'event'){ if( strtolower( $postObj->Event) == 'merchant_order'){ $toUser = $postObj->FromUserName; $fromUser = $postObj->ToUserName; $time = time(); $msgType = 'event'; $event = 'merchant_order'; $OrderId = $postObj->OrderId; $OrderStatus = '2'; $ProductId = $postObj->ProductId; $SkuInfo = $postObj->SkuInfo; $template = "<xml> <ToUserName><![CDATA[%s]]></ToUserName> <FromUserName><![CDATA[%s]]></FromUserName> <CreateTime>%s</CreateTime> <MsgType><![CDATA[%s]]></MsgType> <Event><![CDATA[%s]]></Event> <OrderId><![CDATA[%s]]></OrderId> <OrderStatus>%s</OrderStatus> <ProductId><![CDATA[%s]]></ProductId> <SkuInfo><![CDATA[%s]]></SkuInfo> </xml>"; echo sprintf($template, $toUser, $fromUser, $time, $msgType, $event, $OrderId, $OrderStatus, $ProductId, $SkuInfo); } } return $postArr; }//reponseMsg 括号 //获取AccessToken public function getWxAccessToken(){ //1.请求url地址 $appid = 'wx8d7d0d6d81dc5056'; $appsecret = 'cc41f16e6620443dcb7a4f6e85efbbca'; if (time()-S('expires_in')<7000) { $access_token = S('access_token'); //var_dump($access_token); return $access_token; }else{ $url = "https://api.weixin.qq.com/cgi-bin/token?grant_type=client_credential&appid=" . $appid . "&secret=" . $appsecret . ""; $data = webCurl($url); $arr = json_decode($data,true); S('access_token',$arr['access_token'],7000); $access_token = S('access_token'); $data = array( "access_token" => $access_token, "expires_in"=> time(), ); S('expires_in',$data['expires_in'],7000); //var_dump($access_token); //$_SESSION['access_token_expires_in'] = $data['expires_in']; return $data['access_token']; } } //自定义菜单栏 public function setmenu() { $access_token = $this->getWxAccessToken(); $url = "https://api.weixin.qq.com/cgi-bin/menu/create?access_token=".$access_token; $data = array( 'button'=>array( array( "name"=>"微信商城", "sub_button"=>array( array( "type"=>"view", "name"=>"中秋月醇", "url"=>"http://m.tthwine.com/Goods/index/W_category/376.html" ), array( "type"=>"view", "name"=>"生肖套装", "url"=>"http://m.tthwine.com/Goods/detail/id/413.html" ), array( "type"=>"view", "name"=>"萄萄汇商城", "url"=>"http://m.tthwine.com/" ), array( "type"=>"view", "name"=>"特价优惠", "url"=>"http://m.tthwine.com/Goods/index.html" ), ) ), array( "name"=>"名庄报价", "sub_button"=>array( array( "type"=>"view", "name"=>"价格查询", "url"=>"http://m.baipuhui.com/" ), array( "type"=>"view", "name"=>"供应商报价", "url"=>"http://m.baipuhui.com/ProductPrice/indexs.html" ), array( "type"=>"view", "name"=>"全球货源", "url"=>"http://m.baipuhui.com/BusinessList/index.html" ), ) ), array( "name"=>"用户中心", "sub_button"=>array( // array( // "type"=>"view", // "name"=>"小店订单", // "url"=>"http://mp.weixin.qq.com/bizmall/mallshelf?id=&t=mall/list&biz=MzIzMTY5MzI3Ng==&shelf_id=2&showwxpaytitle=1#wechat_redirect" // ), array( "type"=>"view", "name"=>"商城订单", "url"=>"http://m.tthwine.com/Member/order.html" ), array( "type"=>"view", "name"=>"物流跟踪", "url"=>"https://m.kuaidi100.com/index.jsp" ), array( "type"=>"view", "name"=>"我的中心", "url"=>"http://m.tthwine.com/Member/index.html" ), ) ), ), ); $data = webCurl($url,1,json_encode($data,JSON_UNESCAPED_UNICODE)); } //登陆获取用户信息 public function login() { $appid = 'wx8d7d0d6d81dc5056'; $redirect_uri = "http://m.tthwine.com/index.php/Wechat/weixinreturn"; $redirect_uri = urlencode($redirect_uri); $url = "https://open.weixin.qq.com/connect/oauth2/authorize?appid=".$appid."&redirect_uri=".$redirect_uri."&response_type=code&scope=snsapi_userinfo&state=1&connect_redirect=1#wechat_redirect"; header('Location: ' . $url . ''); } public function weixinreturn() { $appid = 'wx8d7d0d6d81dc5056'; $SECRET = 'cc41f16e6620443dcb7a4f6e85efbbca'; $code = $_GET['code']; $url = "https://api.weixin.qq.com/sns/oauth2/access_token?appid=" .$appid. "&secret=" .$SECRET. "&code=". $code ."&grant_type=authorization_code"; $data = json_decode(wcurl($url),true); $_SESSION['access_token'] = $data['access_token']; $_SESSION['openid'] = $data['openid']; $url = "https://api.weixin.qq.com/sns/userinfo?access_token=".$_SESSION['access_token']."&openid=".$_SESSION['openid']."&lang=zh_CN"; $user = json_decode(wcurl($url),true); $this->assign('user',$user); $this->display(); return $user; } //微信小店下单信息 public function order(){ $obj = $this-> gOrderAll($data = array()); foreach ($obj['order_list'] as $key => $value) { $sql = " SELECT order_id FROM oph_wxshop WHERE order_id = '{$value['order_id']}' "; $res = M('wxshop')->query($sql); if ($res[0]['order_id'] == $value['order_id'] ) { unset($value); }else{ M('wxshop')->add($value); } } $get['type']= $_GET['type'] ? $_GET['type'] : 0 ; switch ($get['type']){ case 0: $where = ''; break; case 1: $where = ' AND order_status = 1 '; break; case 2: $where = ' AND order_status = 2 '; break; case 3: $where = ' AND order_status = 3 '; break; case 4: $where = ' AND order_status = 4 '; break; default: break; } $orderlist = M('wxshop')->query(" SELECT * FROM oph_wxshop WHERE buyer_openid = '{$_SESSION['openid']}' $where"); $this->assign('orderlist',$orderlist); $this->assign('get',$get); $this->display(); } //微信小店的订单详情 public function orderinfo(){ $oid = $_GET['order_id'] ? $_GET['order_id'] : $this->error("非法访问"); $info = M('wxshop')->query(" SELECT * FROM oph_wxshop WHERE order_id = '{$oid}' "); $this->assign('info', $info); $this->display(); } //获取微信订单信息 public function gOrderAll($data = array()){ $access_token = $this->getWxAccessToken(); $url = "https://api.weixin.qq.com/merchant/order/getbyfilter?access_token=".$access_token; if(!empty($data)){ $data = json_encode($data); } else{ $firstday = strtotime(date("Y-m-01",time())); $data = array('begintime' => $firstday,'endtime' => strtotime("$firstday +1 month -1 day")); $data = json_encode($data); } $ResData = $this->cUrlRequest($url,$data); $obj = objarray_to_array(json_decode($ResData)); return $obj; } public function cUrlRequest($url,$data = null){ $curl = curl_init(); curl_setopt($curl, CURLOPT_URL, $url); curl_setopt($curl, CURLOPT_SSL_VERIFYPEER, FALSE); curl_setopt($curl, CURLOPT_SSL_VERIFYHOST, FALSE); if (!empty($data)){ curl_setopt($curl, CURLOPT_POST, 1); curl_setopt($curl, CURLOPT_POSTFIELDS, $data); } curl_setopt($curl, CURLOPT_RETURNTRANSFER, 1); $output = curl_exec($curl); curl_close($curl); return $output; } //微信订单确认 public function returnInfo(){ if($_GET['oid']){ M()->execute("UPDATE oph_wxshop SET order_status = 4 WHERE order_id = '{$_GET['oid']}'"); } $orderlist = M('wxshop')->query(" SELECT * FROM oph_wxshop WHERE buyer_openid = '{$_SESSION['openid']}' AND order_status = 4"); $this->assign('orderlist',$orderlist); $this->display('wechat/order'); } //微信小店发货 public function sLogisticsList(){ $this->Logistics['Fsearch_code'] = "邮政EMS"; $this->Logistics['002shentong'] = "申通快递"; $this->Logistics['066zhongtong'] = "中通速递"; $this->Logistics['056yuantong'] = "圆通速递"; $this->Logistics['042tiantian'] = "每天快递"; $this->Logistics['003shunfeng'] = "顺丰速运"; $this->Logistics['059Yunda'] = "韵达快运"; $this->Logistics['064zhaijisong'] = "宅急送"; $this->Logistics['020huitong'] = "汇通快运"; $this->Logistics['zj001yixun'] = "易迅快递"; } //发货设置 public function sOrderDelivery($data = array("need_delivery" => '0')){ $access_token = $this->getWxAccessToken(); $url = "https://api.weixin.qq.com/merchant/order/setdelivery?access_token=".$access_token; if(!empty($data)){ $data = json_encode($data); } else{ $data = array("need_delivery" => '0'); $data = json_encode($data); } $ResData = $this->cUrlRequest($url,$data); print_r( json_decode($ResData) ); } //发货订单 public function send() { $data['need_delivery'] = '1'; $data['order_id'] = '13880016931595576467'; $data['delivery_company'] = '003shunfeng'; $data['delivery_track_no'] = '5185457726'; $data['is_others'] = '0'; $this->sOrderDelivery($data); } //获取订单详情 // public function gOrderInfo($order){ // $access_token = $this->getWxAccessToken(); // $url = "https://api.weixin.qq.com/merchant/order/getbyid?access_token=".$access_token; // $ResData = $this->cUrlRequest($url,'{"order_id": "'.$order.'"}'); // return(objarray_to_array(json_decode($ResData)) ); // } //模板消息发送 public function sendtpl_msg(){ if (is_weixin() == false) { echo "<p style='font-size:32px;color:red;text-align:center'>请用微信浏览器打开</p>"; exit; } $access_token = $this->getWxAccessToken(); $getOpenid = $this->getOpenid(); //$postArr = $this->reponseMsg(); //$res = $this->gOrderInfo($postArr['OrderId']); //模板消息 $template=array( 'touser'=>$getOpenid, 'template_id'=>"t2j4tatkUhqCvsTVr290P04rXNWg3WnMWXOHiLW6tSg", 'url'=>"http://m.tthwine.com/index.php/Wechat/login/", 'topcolor'=>"#7B68EE", 'data'=>array( 'first' => array( 'value' => '尊敬的用户,您好,欢迎购买咱们的产品', 'color' => '#FF0000' ), 'keyword1' => array( 'value' => $data['order_no'], 'color' => '#000' ), 'keyword2' => array( 'value' => $data['pay_amount'].元, 'color' => '#000000' ), 'remark' => array( 'value' => '广州欧葡汇祝您节日快乐!', 'color' => '#FF0000' ) ) ); $json_template=json_encode($template); $url = "https://api.weixin.qq.com/cgi-bin/message/template/send?access_token=".$access_token; $res = http_request($url,urldecode($json_template)); } /** * 以post方式提交xml到对应的接口url * @param string $xml 须要post的xml数据 * @param string $url url * @param bool $useCert 是否须要证书,默认不须要 * @param int $second url执行超时时间,默认30s * @throws WxPayException */ protected static function curlPostXml($xml, $url, $useCert = false, $second = 30){ $ch = curl_init(); curl_setopt($ch, CURLOPT_TIMEOUT, $second); //设置超时 if(self::CURL_PROXY_HOST != "0.0.0.0" && self::CURL_PROXY_PORT != 0){ //若是有配置代理这里就设置代理 curl_setopt($ch, CURLOPT_PROXY, self::CURL_PROXY_HOST); curl_setopt($ch, CURLOPT_PROXYPORT, self::CURL_PROXY_PORT); } curl_setopt($ch, CURLOPT_URL, $url); curl_setopt($ch, CURLOPT_SSL_VERIFYPEER, FALSE); curl_setopt($ch, CURLOPT_SSL_VERIFYHOST, FALSE); //严格校验2 curl_setopt($ch, CURLOPT_HEADER, FALSE); //设置header curl_setopt($ch, CURLOPT_RETURNTRANSFER, TRUE); //要求结果为字符串且输出到屏幕上 if($useCert == true){ //设置证书,使用证书:cert 与 key 分别属于两个.pem文件 curl_setopt($ch, CURLOPT_SSLCERTTYPE, 'PEM'); curl_setopt($ch, CURLOPT_SSLCERT, self::SSLCERT_PATH); curl_setopt($ch, CURLOPT_SSLKEYTYPE, 'PEM'); curl_setopt($ch, CURLOPT_SSLKEY, self::SSLKEY_PATH); } curl_setopt($ch, CURLOPT_POST, TRUE); //post提交方式 curl_setopt($ch, CURLOPT_POSTFIELDS, $xml); $result = curl_exec($ch); //运行curl if($result){ //返回结果 curl_close($ch); return $result; }else{ $error = curl_errno($ch); curl_close($ch); throw new \WxPayException("curl出错,错误码:".$error); } } /** * 经过跳转获取用户的openid,跳转流程以下: * 一、设置本身须要调回的url及其其余参数,跳转到微信服务器https://open.weixin.qq.com/connect/oauth2/authorize * 二、微信服务处理完成以后会跳转回用户redirect_uri地址,此时会带上一些参数,如:code * 三、经过code请求微信服务器https://api.weixin.qq.com/sns/oauth2/access_token获取openid和access_token用户受权凭证 * @param string $state 自定义参数 * @return 用户的openid */ protected function getOpenid($state=''){ $tools = new \WxPayFunction(); if(!isset($_GET['code'])){ //触发微信返回code码 $redirectUrl = urlencode('http://'.$_SERVER['HTTP_HOST'].$_SERVER['REQUEST_URI'].$_SERVER['QUERY_STRING']); $urlObj = array( 'appid' => self::APP_ID, 'redirect_uri' => $redirectUrl, 'response_type' => 'code', 'scope' => 'snsapi_base', 'state' => $state.'#wechat_redirect' ); $bizString = $tools->ToUrlStr($urlObj); $url = 'https://open.weixin.qq.com/connect/oauth2/authorize?'.$bizString; header('Location:'.$url); exit(); }else{ //获取code码,以获取openid $urlObj = array( 'appid' => self::APP_ID, 'secret' => self::APP_SECRET, 'code' => $_GET['code'], 'grant_type' => 'authorization_code' ); $bizString = $tools->ToUrlStr($urlObj); $url = 'https://api.weixin.qq.com/sns/oauth2/access_token?'.$bizString; $ch = curl_init(); //初始化curl curl_setopt($ch, CURLOPT_TIMEOUT, $this->curl_timeout); //设置超时 curl_setopt($ch, CURLOPT_URL, $url); curl_setopt($ch, CURLOPT_SSL_VERIFYPEER, FALSE); curl_setopt($ch, CURLOPT_SSL_VERIFYHOST, FALSE); curl_setopt($ch, CURLOPT_HEADER, FALSE); curl_setopt($ch, CURLOPT_RETURNTRANSFER, TRUE); if(self::CURL_PROXY_HOST != '0.0.0.0' && self::CURL_PROXY_PORT != 0){ curl_setopt($ch,CURLOPT_PROXY, self::CURL_PROXY_HOST); curl_setopt($ch,CURLOPT_PROXYPORT, self::CURL_PROXY_PORT); } $result = curl_exec($ch); //运行curl,结果以json形式返回 curl_close($ch); $data = json_decode($result, true); $this->access_token_a = $data['access_token']; //赋值access_token_a属性,此access_token为用户受权凭证,与基础开发的access_token不一样 return $data['openid']; //返回openid } } /** * 统一下单,unifiedOrder中out_trade_no、body、total_fee、trade_type必填 * appid、mchid、spbill_create_ip、nonce_str不须要填入 * @param WxPayUnifiedOrder $inputObj * @param int $timeOut * @throws WxPayException 抛出异常 * @return array 成功时返回结果 */ protected function unifiedOrder($requestArr, $timeOut = 10){ //检测参数 if(!array_key_exists('out_trade_no', $requestArr)){ throw new \WxPayException("缺乏统一支付接口必填参数out_trade_no!"); }else if(!array_key_exists('body', $requestArr)){ throw new \WxPayException("缺乏统一支付接口必填参数body!"); }else if(!array_key_exists('total_fee', $requestArr)){ throw new \WxPayException("缺乏统一支付接口必填参数total_fee!"); }else if(!array_key_exists('trade_type', $requestArr)){ throw new \WxPayException("缺乏统一支付接口必填参数trade_type!"); } //关联参数 if($requestArr['trade_type'] == "JSAPI" && !array_key_exists('openid', $requestArr)){ throw new WxPayException("统一支付接口中,缺乏必填参数openid!trade_type为JSAPI时,openid为必填参数!"); } if($requestArr['trade_type'] == "NATIVE" && !array_key_exists('product_id', $requestArr)){ throw new WxPayException("统一支付接口中,缺乏必填参数product_id!trade_type为JSAPI时,product_id为必填参数!"); } $tools = new \WxPayFunction(); $url= 'https://api.mch.weixin.qq.com/pay/unifiedorder'; //统一下单API请求地址 $requestArr['appid'] = self::APP_ID; //String(32) 应用ID $requestArr['mch_id'] = self::MCH_ID; //String(32) 商户ID $requestArr['nonce_str'] = $tools->createNonceStr(32); //String(32) 随机字符串 $requestArr['spbill_create_ip'] = $_SERVER['REMOTE_ADDR']; //String(16) 终端IP $requestArr['notify_url'] = self::NOTIFY_URL; //String(256) 异步通知地址 $requestArr['sign'] = $tools->createSign($requestArr, self::MCH_KEY); //String(32) 签名 $requestXml = $tools->arrToXml($requestArr); $responseXml = self::curlPostXml($requestXml, $url, false, $timeOut); $responseArr = $tools->xmlToArr($responseXml); return $responseArr; } /** * 获取jsApi的json参数 * @param string $prepay_id 预支付交易标识 * @return jsApi前端json参数 */ protected function getJsApiParameters($prepay_id){ $tools = new \WxPayFunction(); $jsApiArr = array( 'appId' => self::APP_ID, //String(16) 应用ID 'timeStamp' => strval(time()), //String(32) 时间戳 'nonceStr' => $tools->createNonceStr(32), //String(32) 随机字符串 'package' => 'prepay_id='.$prepay_id, //String(128) 订单详情扩展字符串 'signType' => 'MD5' //String(32) 签名方式 ); $jsApiArr['paySign'] = $tools->createSign($jsApiArr, self::MCH_KEY); //String(64) 签名 return json_encode($jsApiArr); } /** * 获取共享地址json参数 * @param string $access_token 用户受权凭证 * @return 共享地址前段json参数 */ protected function getEditAddrParameters($access_token){ $tools = new \WxPayFunction(); $addrSignArr = array( 'appid' => self::APP_ID, //String(16) 应用ID 'url' => 'http://'.$_SERVER['HTTP_HOST'].$_SERVER['REQUEST_URI'], //当前网页URL 'timestamp' => strval(time()), //String(32) 时间戳 'noncestr' => $tools->createNonceStr(32), //String(32) 随机字符串 'accesstoken' => $access_token //String(256) 用户受权凭证 ); ksort($addrSignArr); $addrSignStr = $tools->toUrlStr($addrSignArr); $addrSign = sha1($addrSignStr); $editAddrArr = array( 'appId' => self::APP_ID, //String(16) 应用ID 'scope' => 'jsapi_address', //String(32) 编辑地址权限 'signType' => 'sha1', //String(32) 签名方式 'addrSign' => $addrSign, //String(40) 签名 'timeStamp' => $addrSignArr['timestamp'], //String(32) 时间戳 'nonceStr' => $addrSignArr['noncestr'] //String(32) 随机字符串 ); return json_encode($editAddrArr); } //微信支付外部浏览器H5页面MWEB支付接口(微信内测阶段,还未对外开放) public function wxpayH5Api(){ $requestArr = array( 'body' => $_POST['body'], //String(128) 商品描述 'out_trade_no' => $_POST['out_trade_no'], //String(32) 商户订单号 'total_fee' => intval(floatval($_POST['total_fee'])*100), //Int 订单金额(单位为分) 'trade_type' => 'MWEB' //String(16) 交易类型 ); $responseArr = $this->unifiedOrder($requestArr); //统一下单API $tools = new \WxPayFunction(); if($responseArr['return_code'] == 'SUCCESS'){ //判断返回是否成功 if(array_key_exists('sign', $responseArr) && $tools->createSign($responseArr, self::MCH_KEY) == $responseArr['sign']){ header('Location:'.$responseArr['mweb_url'].'&redirect_url='.urlencode(self::RETURN_URL)); //跳转启动微信APP支付 }else{ throw new \WxPayException("签名验证失败!"); } }else{ //$responseArr['return_code'] == 'FAIL' //记录日志$responseArr;打印出错参数 //file_put_contents('./Data/paylog/wechatlog.txt', $_SERVER['REMOTE_ADDR'].' '.$_SERVER['QUERY_STRING']."\r\n", FILE_APPEND); throw new \WxPayException("响应失败!"); foreach($responseArr as $key => $val){ echo $key.': '.$val.'<br />'; } } } //微信支付内置浏览器H5页面JSAPI支付接口 public function wxpayJsApi(){ //获取openId需跳转,因此将post参数存入获取openid的自定义参数中 if(!empty($_POST['body']) && !empty($_POST['out_trade_no']) && !empty($_POST['total_fee'])){ $state = json_encode($_POST); } //解析获取openid返回的自定义参数,从而获取最初的订单信息 if(!empty($_GET['state'])){ $orderData = json_decode($_GET['state'], true); } $openid = $this->getOpenid($state); //获取openid $requestArr = array( 'body' => $orderData['body'], //String(128) 商品描述 'out_trade_no' => $orderData['out_trade_no'], //String(32) 商户订单号 'total_fee' => intval(floatval($orderData['total_fee'])*100), //Int 订单金额(单位为分) 'trade_type' => 'JSAPI', //String(16) 交易类型 'openid' => $openid //String(128) trade_type=JSAPI时(即公众号支付),此参数必传,此参数为微信用户在商户对应appid下的惟一标识 ); $responseArr = $this->unifiedOrder($requestArr); //统一下单API if(!array_key_exists('appid', $responseArr) || !array_key_exists('prepay_id', $responseArr) || $responseArr['prepay_id'] == ""){ throw new \WxPayException("参数错误!"); } //获取调用jsApi的参数(json格式输出) $jsApiParameters = $this->getJsApiParameters($responseArr['prepay_id']); //获取共享收货地址的参数(json格式输出)(因为支付场景不适合,暂不使用) //$editAddrParameters = $this->getEditAddrParameters($this->access_token_a); //传递给同步通知页面的信息 $returnData = array( // 'out_trade_no' => $orderData['body'], 'out_trade_no' => $orderData['out_trade_no'], 'total_fee' => $orderData['total_fee'], 'return_url' => self::RETURN_URL ); $this->assign('jsApiParameters', $jsApiParameters); //$this->assign('editAddrParameters', $editAddrParameters); $this->assign('returnData', $returnData); $this->display('Order/wxpay_js'); } //微信支付原生支付接口(采用模式二扫码支付) public function wxpayNativeApi(){ $requestArr = array( 'body' => $_POST['body'], //String(128) 商品描述 'out_trade_no' => $_POST['out_trade_no'], //String(32) 商户订单号 'total_fee' => intval(floatval($_POST['total_fee'])*100), //Int 订单金额(单位为分) 'trade_type' => 'NATIVE', //String(16) 交易类型 'product_id' => $_POST['out_trade_no'] //String(32) 商品标识,商户自定义 ); $responseArr = $this->unifiedOrder($requestArr); //统一下单API $tools = new \WxPayFunction(); if($responseArr['return_code'] == 'SUCCESS'){ //判断返回是否成功 if(array_key_exists('sign', $responseArr) && $tools->createSign($responseArr, self::MCH_KEY) == $responseArr['sign']){ //验证签名 $returnData = array( //获取订单信息和扫码支付地址 'out_trade_no' => $_POST['out_trade_no'], 'total_fee' => $_POST['total_fee'], 'code_url' => $responseArr['code_url'] ); }else{ throw new \WxPayException("签名验证失败!"); } }else{ //$responseArr['return_code'] == 'FAIL' throw new \WxPayException("响应失败!"); foreach($responseArr as $key => $val){ echo $key.': '.$val.'<br />'; } } $this->assign('returnData', $returnData); $this->display('Order/wxpay_native'); } //微信支付同步通知 public function wxpayReturn(){ $payResult = array( 'order_no' => htmlspecialchars($_GET['out_trade_no']), 'status' => $_GET['status'], 'pay_type' => '微信支付', 'pay_amount' => $_GET['total_fee'] ); if($payResult['status'] == 'success'){ //支付完成 M('order')->where('`order_sn`="'.$payResult['order_no'].'" AND `pay_status`=0')->setField('pay_status', 1); $crowd = M('order')->alias('o')->where('(o.`is_crowd`<>0 OR o.`is_cab`<>0) AND o.`order_sn`="'.$payResult['order_no'].'"')->join('`oph_order_goods` AS og ON og.`order_id`=o.`id`','left')->join('`oph_crowd` AS c ON (c.`id`=o.`is_crowd` OR c.`id`=o.`is_cab`)','left')->field('og.`goods_id`,og.`number`,og.`box`,o.`id` oid,o.`is_crowd`,o.`is_cab`,c.*')->find(); // var_dump($crowd);exit; if(!$_COOKIE[$payResult['order_no']]){ setcookie($payResult['order_no'],1); if ($crowd) { $upNum['nownum'] = $crowd['nownum'] + $crowd['number']; $myCrowd = array(); M()->startTrans(); if ($crowd['is_crowd']) { $res = M('crowd')->where('id='.$crowd['is_crowd'])->setField($upNum); $myCrowd['cid'] = $crowd['is_crowd']; }else{ $res = M('crowd')->where('id='.$crowd['is_cab'])->setField($upNum); $myCrowd['cid'] = $crowd['is_cab']; } $myCrowd['myprice'] = $payResult['pay_amount']; $myCrowd['uid'] = $_SESSION['user']['uid']; $myCrowd['mobile'] = $_SESSION['user']['mobile']; $myCrowd['num'] = $crowd['number']; $order['total'] = $myCrowd['num']; $myCrowd['create_time'] = time(); $myCrowd['oid'] = $crowd['oid']; if ($res) { M('crowd_join')->add($myCrowd); M()->commit(); }else{ M()->rollback(); } } $order['total'] = M('order')->alias('o')->where('o.`order_sn`="'.$payResult['order_no'].'" AND og.`goods_id`<>0')->join('oph_order_goods AS og ON og.`order_id`=o.`id`')->sum('number'); $jiage = $payResult['pay_amount']; D('member')->upLevel($jiage,$order['total']); } $payResult['msg'] = '付款完成!咱们将第一时间安排发货!'; //发送模板消息 $access_token = $this->getWxAccessToken(); $getOpenid = $this->getOpenid(); //模板消息 $template=array( 'touser'=>$getOpenid, 'template_id'=>"t2j4tatkUhqCvsTVr290P04rXNWg3WnMWXOHiLW6tSg", 'url'=>"http://m.tthwine.com/Member/order", 'topcolor'=>"#7B68EE", 'data'=>array( 'first' => array( 'value' => '尊敬的用户,您好,欢迎购买咱们的产品', 'color' => '#FF0000' ), 'keyword1' => array( 'value' => $payResult['pay_amount'].元, 'color' => '#000' ), 'keyword2' => array( 'value' => $payResult['order_no'], 'color' => '#000000' ), 'remark' => array( 'value' => '广州十二星祝您节日快乐!', 'color' => '#FF0000' ) ) ); $json_template=json_encode($template); $url = "https://api.weixin.qq.com/cgi-bin/message/template/send?access_token=".$access_token; http_request($url,urldecode($json_template)); }else if($payResult['status'] == 'failure'){ //支付失败或出错 $payResult['msg'] = '支付失败,请到个人订单从新发起支付!'; } $this->assign('payResult', $payResult); //print_r($payResult); $this->display('Order/result'); } //微信支付异步通知 public function wxpayNotify(){ $notifyXml = $GLOBALS['HTTP_RAW_POST_DATA']; //获取返回的xml数据 $tools = new \WxPayFunction(); $notifyArr = $tools->xmlToArr($notifyXml); if($notifyArr['return_code'] == 'SUCCESS'){ //判断通知成功 if($notifyArr['result_code'] == 'SUCCESS' && $tools->createSign($notifyArr, self::MCH_KEY) == $notifyArr['sign']){ //支付成功和验证签名 $pay_status = M('order')->where('`order_sn`="'.$notifyArr['out_trade_no'].'"')->getField('pay_status'); if(self::MCH_ID == $notifyArr['mch_id'] && $pay_status != 1){ $data = array( 'pay_type' => 3, 'pay_status' => 1, 'payreal_amount' => floatval($notifyArr['total_fee']/100), //单位为分,换算成元 'pay_sn' => $notifyArr['transaction_id'], 'pay_time' => strtotime($notifyArr['time_end']) ); $result = M('order')->where('order_sn="'.$notifyArr['out_trade_no'].'"')->save($data); } } //写入日志文件(订单编号,微信交易号,交易状态,交易金额,微信用户openId,付款时间) file_put_contents('./Data/paylog/wxpaylog.txt', $notifyArr['out_trade_no'].' '.$data['pay_sn'].' '.$notifyArr['result_code'].' '.$data['payreal_amount'].' '.$notifyArr['openid'].' '.$data['pay_time'].' 微信支付'."\r\n", FILE_APPEND); $responseXml = $tools->arrToXml(array('return_code'=>'SUCCESS', 'return_msg'=>'OK')); echo $responseXml; }else{ return false; } } //分享接口 public function sharOne(){ //获取商品id $shopId = I('get.sid'); $getgm = I('get.gm'); $jsapi_ticket = $this->getJsApiTicket(); $timestamp = time(); $noncestr = $this->getRandCode(); // 注意 URL 必定要动态获取,不能 hardcode. $protocol = (!empty($_SERVER['HTTPS']) && $_SERVER['HTTPS'] !== 'off' || $_SERVER['SERVER_PORT'] == 443) ? "https://" : "http://"; $url = "$protocol$_SERVER[HTTP_HOST]$_SERVER[REQUEST_URI]"; $signature = "jsapi_ticket=$jsapi_ticket&noncestr=$noncestr×tamp=$timestamp&url=$url"; $signature = sha1( $signature ); if($shopId > 0){ //获取用户微信getOpenid $getOpenid = $this->getOpenid(); $getOpenid = str_replace('-','',$getOpenid); //获取上级分享的用户openid if($upOpenid = I('get.u')) $this->assign('upOpenid',$upOpenid); $newUrl = $protocol.$_SERVER[HTTP_HOST].'/Wechat/sharOne/u/'.$getOpenid.'/sid/'.$shopId.'.html'; $this->assign('shopId',$shopId); $this->assign('getOpenid',$getOpenid); $this->assign('newUrl',$newUrl); } //获取地区三级联动 $province = M('region_china')->where('pid=0')->getField('id,region_name'); $showVive = 'sharOne'.$shopId; $this->assign('getgm',$getgm); $this->assign('province',$province); $this->assign('timestamp',$timestamp); $this->assign('noncestr',$noncestr); $this->assign('signature',$signature); $this->assign('sharOnesid',$shopId); $this->display($showVive); } //获取随机码 public function getRandCode(){ $array = array( 'A','B','C','D','E','F','G','H','I','J','K','L','M','N','O','P','Q','R','S','T','U','V','W','X','Y','Z', 'a','b','c','d','e','f','g','h','i','j','k','l','m','n','o','p','q','r','s','d','u','v','w','x','y','z', '0','1','2','3','4','5','6','7','8','9' ); $tmpstr = ''; $max = count($array); for($i =1; $i <= 16; $i++){ $key = rand(0,$max-1); $tmpstr .= $array[$key]; } return $tmpstr; } public function getJsApiTicket(){ //若是session中保存有效的jsapi_ticket $access_token = $this->getWxAccessToken(); if($_SESSION['jsapi_ticket_expire_time'] > time()){ $jsapi_ticket = S('jsapi_ticket'); }else{ $url = "https://api.weixin.qq.com/cgi-bin/ticket/getticket?access_token=$access_token&type=jsapi"; $data = webCurl($url); $res = json_decode($data,true); $jsapi_ticket = $res['ticket']; S('jsapi_ticket',$jsapi_ticket,7000); $_SESSION['jsapi_ticket_expire_time'] = time()+7000; } return $jsapi_ticket; } } ?>