前端頁面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; } } ?>