php微信開發之帶參數二維碼的使用_php執行個體

來源:互聯網
上載者:User
最近做PC端網頁相關功能的開發,從一個新手的角度來說,公眾號的文檔還是不好理解的,網上找的文章大都也都基本上是複製公眾平台上給的文檔,開發帶參數二維碼過程中還是遇到不少坑的,在此把我的開發過程比較詳細的記錄下,希望對大家有所協助。

我本次開發使用的是認證服務號。

1 接入
首先進入公眾號 -> 基本配置
下面是基本配置的頁面,在URL中填寫伺服器位址,這個地址就是接受推送事件的一個介面,我是使用thinkPHP架構開發的程式,在其中一個Module(Decoration)的Action目錄下建立一個類,比如叫: WechatAction.class.php ,在該Action中建立一個public方法,比如叫: URLRedirect() ,那麼在這個URL中填寫的就是 http://[IP]:[port]/index.php/Decoration/Wechat/UrlRedirect ,然後填寫Token,Token隨意填,EncodingAESKey要不要都行,然後點擊確認,會往這個URL上發送一個get請求,裡麵包含很多參數,其中大部分都是讓我們自己核對這次訪問是不是伺服器請求的,我自己沒有驗證,他的要求是如果我們核對成功,即原樣返回get請求中的一個參數echostr,這裡的返回不是return,也不是ajaxReturn,而使用echo,如果用thinkPHP開發的話,直接使用 echo I('echostr'); 即可。然後介面即驗證成功了。

2 帶參數二維碼的作用
的帶參數二維碼有兩種,一種是臨時二維碼,一種是永久二維碼,但是永久二維碼的產生是有個數限制的,我這次要實現的功能是使用者未登入的情況下在網站上使用產品,比如獲得某商品的詳細報價,但是又不想註冊,然而又想儲存這個報價單,這個時候網頁可以產生一張二維碼,使用者只要用掃一掃這個二維碼,官方公眾號就會給這個使用者發送一天圖文訊息,圖文訊息點開後就是使用者剛剛獲得的報價單,而且可以隨時點擊查看並且分享給朋友進行比價。所以臨時二維碼即可正常使用。
上面是我是怎麼使用的,下面介紹一下整個互動的流程

當使用者掃描這個二維碼,如果使用者關注了公眾號,使用者會直接進入與公眾號的會話頁面,伺服器會給我們在上一步設定的伺服器URL中推送一條訊息,其中可以攜帶一個我們自訂的參數。如果使用者未關注公眾號,則使用者首先會跳轉到公眾號關注頁面,使用者點擊關注後,會直接進入公眾號的會話頁面,伺服器這時也會給我們設定的URL推送一個事件訊息,攜帶我們自訂參數,我們可以根據這個參數和事件類型做控制下一步動作。

3 具體開發過程

3.1 擷取access_token
這個access_token是我們程式調用介面的憑證,目前的有效期間是7200秒,所以我們需要定時更新access_token。
獲得方法:
方法 : GET
url :https://api.weixin.qq.com/cgi-bin/token?grant_type=client_credential&appid=APPID&secret=APPSECRET
其中的參數APPID和APPSECRET是我們公眾號的APPID和APPSECRET,在公眾號 -> 基本配置中可以查到,調用成功會返回如下JSON資料:
{"access_token":"ACCESS_TOKEN","expires_in":7200}

其中access_token就是調用介面憑證,expire_in是token有效時間。
我本人是把access_token存在資料庫中,同時儲存到期時間,然後封裝公用函數 getWechatAccessToken() ,每次先檢查access_token是否到期,如果到期則重新擷取,否則直接使用資料庫儲存的access_token即可,我忘了在哪兒看加過,這個access_token每天的擷取次數應該是有限制的。下面是 getWechatAccessToken() 的具體實現:

//擷取access_tokenfunction getWechatAccessToken(){ $wechatInfo = M('wechat_info')->select(); $wechatInfo = array_reduce($wechatInfo, create_function('$result, $v', '$result[$v["conf_name"]] = $v;return $result;')); $expireTime = $wechatInfo['PUBLIC_WECHAT_ACCESSTOKEN_EXPIRES']['conf_value'];        //前面不用管,是我資料庫相應設定 if (time() < $expireTime){    //access_token未到期  return $wechatInfo['PUBLIC_WECHAT_ACCESSTOKEN']['conf_value']; }else{         //access_token到期,重新擷取  $baseUrl = C('WECHAT_PUBLIC_GET_ACCESS_TOKEN');  $url = str_replace("##APPSECRET##", $wechatInfo['PUBLIC_WECHAT_APPSECRET']['conf_value'], str_replace("##APPID##", $wechatInfo['PUBLIC_WECHAT_APPID']['conf_value'], $baseUrl));  $result = file_get_contents($url);  $result = json_decode($result, true);  if (array_key_exists('errorcode', $result)){  //失敗重試一次   return false;  }else{   M('wechat_info')->where(array('conf_name' => 'PUBLIC_WECHAT_ACCESSTOKEN'))->save(array('conf_value' => $result['access_token']));   M('wechat_info')->where(array('conf_name' => 'PUBLIC_WECHAT_ACCESSTOKEN_EXPIRES'))->save(array('conf_value' => time()+$result['expires_in']-200));   return $result['access_token'];  } }}

C('WECHAT_PUBLIC_GET_ACCESS_TOKEN') = https://api.weixin.qq.com/cgi-bin/token?grant_type=client_credential&appid=APPID&secret=APPSECRET

封裝好這個之後,我們每次就可以安心的使用了。

.2 建立臨時二維碼

3.2.1 擷取ticket3

請求方式: POST
介面:https://api.weixin.qq.com/cgi-bin/qrcode/create?access_token=TOKEN
POST資料: {"expire_seconds": 604800, "action_name": "QR_SCENE", "action_info": {"scene": {"scene_id": 123}}}
介面URL中的TOKEN即我們在3.1中擷取的access_token,post資料中expire_seconds是二維碼的有效時間,最多為30天,action_name臨時二維碼的話固定就是QR_SCENE,scene_id即我們自訂參數,是個32位非0整數,我在應用中把它設為訂單的ID,伺服器推送事件的時候會把這個值返回給我們設定的介面中,然後我會根據這個值去拿相應的訂單資料展示在網頁上,這是後話。

下面是封裝的產生臨時二維碼的方法:

//建立臨時二維碼function getTemporaryQrcode($orderId){ $accessToken = getWechatAccessToken(); $url = str_replace("##TOKEN##", $accessToken, C('WECHAT_PUBLIC_GET_TEMPORARY_TICKET')); $qrcode = '{"expire_seconds": 1800, "action_name": "QR_SCENE", "action_info": {"scene": {"scene_id": '.$orderId.'}}}'; $result = api_notice_increment($url, $qrcode); $result = json_decode($result, true); return urldecode($result['url']);}

其中的方法 api_notice_increment() 是我封裝的一個POST方法函數,我試過很多POST的方法,可能由於介面對POST方法和參數的限制比較嚴格,這個浪費了好久時間,最後在網上找到了一個可以使用的封裝好的POST方法,建議大家先自己試試,如果返回錯誤嗎,就用這個吧,起碼我測試這個介面的時候用postman測試返回的都是錯誤,而且一定要用JSON字串,一定要是非常嚴格的JSON字串。下面是這個方法:

function api_notice_increment($url, $data){ $ch = curl_init(); $header = "Accept-Charset: utf-8"; curl_setopt($ch, CURLOPT_URL, $url); curl_setopt($ch, CURLOPT_CUSTOMREQUEST, "POST"); curl_setopt($ch, CURLOPT_SSL_VERIFYPEER, FALSE); curl_setopt($ch, CURLOPT_SSL_VERIFYHOST, FALSE); curl_setopt($ch, CURLOPT_HTTPHEADER, $header); curl_setopt($ch, CURLOPT_USERAGENT, 'Mozilla/5.0 (compatible; MSIE 5.01; Windows NT 5.0)'); curl_setopt($ch, CURLOPT_FOLLOWLOCATION, 1); curl_setopt($ch, CURLOPT_AUTOREFERER, 1); curl_setopt($ch, CURLOPT_POSTFIELDS, $data); curl_setopt($ch, CURLOPT_RETURNTRANSFER, true); $tmpInfo = curl_exec($ch); if (curl_errno($ch)) {  curl_close( $ch );  return $ch; }else{  curl_close( $ch );  return $tmpInfo; }}

getTemporaryQrcode() 中有一個在設定檔中的參數給大家看下,其實就是介面連結:
C('WECHAT_PUBLIC_GET_TEMPORARY_TICKET') = https://api.weixin.qq.com/cgi-bin/qrcode/create?access_token=##TOKEN##

這個介面的傳回值是:
{"ticket":"gQH47joAAAAAAAAAASxodHRwOi8vd2VpeGluLnFxLmNvbS9xL2taZ2Z3TVRtNzJXV1Brb3ZhYmJJAAIEZ23sUwMEmm3sUw==","expire_seconds":60,"url":"http:\/\/weixin.qq.com\/q\/kZgfwMTm72WWPkovabbI"}

其中ticket是讓我們用來進行下一步調用的憑證,expire_seconds是二維碼的有效期間,url是我們產生的二維碼掃描後開啟的連結。所以如果我們自己實現了產生二維碼的方法,就不用再進行下一步調用,我本人即在這一步就停止了,直接返回url的值,然後利用這個url的值產生二維碼存在本地即可。PHP產生二維碼可以使用phpqrcode,挺好用的。下一步也大致提一下:

3.2.2 擷取二維碼地址
請求方式: GET
介面:https://mp.weixin.qq.com/cgi-bin/showqrcode?ticket=TICKET
這個介面的傳回值是一張圖片,可以直接展示或者下載,我們有具體使用過,所以也不知道應該怎麼展示。

3.3 使用者掃描二維碼之後發生的事情
3.3.1 掃描後發生了什麼
上面提到了,使用者掃描我們產生的臨時二維碼,如果使用者未關注公眾號,則首先會跳轉到公眾號的關注頁面,點擊關注後,會進入公眾號的會話頁面,同時會給我們設定的介面推送一個事件。如果使用者已經關注了,使用者會直接跳轉到公眾號會話頁面,然後伺服器會給我們設定的介面推送一個事件。

使用者關注與否伺服器給我們推送的事件是差不多的,只是新關注使用者推送的事件中scene_id前面會加一個首碼。下面是公眾平台文檔的說明:

使用者未關注時,進行關注後的事件推送

toUser        //開發人員號FromUser       //寄件者帳號(openid)123456789                //訊息建立時間(整型)event              //訊息類型 eventsubscribe              //事件類型(subscribe)qrscene_123123        //事件KEY值,qrscene_為首碼,後面為二維碼參數值TICKET               //二維碼ticke值,可以用來換取二維碼圖片 

使用者已關注時的事件推送

toUser        //開發人員號FromUser     //寄件者帳號(openid)123456789             //訊息建立時間event     //訊息類型eventSCAN               //事件類型 eventSCENE_VALUE   //事件key值,是一個32位不帶正負號的整數,即建立二維碼時的二維碼scene_idTICKET      //二維碼的ticke,可以用來換取二維碼圖片

3.3.2 我們要做些什麼

我們需要在自己填寫的URL介面中接收這個事件,然後拿到我們需要的東西做我們想乾的事兒。因為我要實現的功能比較簡單,只需要拿到scene_id即可,因為這是我要展示給使用者看的訂單資料。下面是我寫的接收和處理部分,比較簡單,主要看一下應該怎麼接收推送的事件:

public function urlRedirect(){  $postStr = $GLOBALS["HTTP_RAW_POST_DATA"];  $postObj = simplexml_load_string($postStr, 'SimpleXMLElement', LIBXML_NOCDATA);  $fromUsername = (string)$postObj->FromUserName;  $EventKey = trim((string)$postObj->EventKey);  $keyArray = explode("_", $EventKey);  if (count($keyArray) == 1){   //已粉絲掃描   $this->sendMessage($fromUsername, $EventKey);  }else{                   //未粉絲關注後推送事件   $this->sendMessage($fromUsername, $keyArray[1]);  } }

我沒有使用其他參數,只是根據不同的推送事件拿到我想要的訂單ID,然後這時候其實相當於你在這裡用公眾號的客服在跟掃碼的這個使用者對話,上段代碼中調用的sendMessage()是使用客戶帳號給掃碼使用者發送一個圖文訊息,因為我在拿scen_id的同時也拿到了使用者的openid,可以利用這個給使用者發送訊息。

下面是sendMessage()方法:

//給使用者發送圖文訊息,點擊跳轉到報價頁面 public function sendMessage($openid,$orderId){  $url = str_replace('##TOKEN##', getWechatAccessToken(), C('WECHAT_SEND_MESSAGE'));  $redirectUrl = str_replace("##ORDERID##", $orderId, str_replace("##OPENID##", $openid, C('WECHAT_REDIRECT_URL_PRE')));  $orderInfo = M('order')->where(array('orderid' => $orderId))->field(array('totalMoney', 'savedMoney', 'roomarea'))->find();  $description = str_replace("##ROOMAREA##", intval($orderInfo['roomarea'] * 1.25), C('WECHAT_MESSAGE_BRIEF'));  $description = str_replace("##TOTALBUDGET##", $orderInfo['totalMoney'], $description);  $description = str_replace("##MARKETBUDGET##", $orderInfo['totalMoney']+$orderInfo['savedMoney'], $description);  $description = str_replace("##SAVEMONEY##", $orderInfo['savedMoney'], $description);  $dataStr = '{"touser":"' . $openid . '","msgtype":"news","news":{"articles":[{"title":"' . C('WECHAT_MESSAGE_TITLE') .   '","description":"' . $description . '","url":"' . $redirectUrl . '","picurl":"' . C('WECHAT_MESSAGE_PICURL') . '""}]}}';  api_notice_increment($url, $dataStr); }

其中 C('WECHAT_SEND_MESSAGE') = 'https://api.weixin.qq.com/cgi-bin/message/custom/send?access_token=##TOKEN##' 至於下面的一大段str_replace,就是在組給使用者發送的文字而已,需要注意$dataStr的格式,這裡面要求JSON字串比較嚴格,必須所有的字串都用雙引號括起來。介面對POST參數的限制真心嚴格。

下面是公眾平台開發人員文檔中要求發送圖文訊息的POST data格式:

{ "touser":"OPENID", "msgtype":"news", "news":{  "articles": [   {    "title":"Happy Day",    "description":"Is Really A Happy Day",    "url":"URL",    "picurl":"PIC_URL"   },   {    "title":"Happy Day",    "description":"Is Really A Happy Day",    "url":"URL",    "picurl":"PIC_URL"   }   ] }}

其中url是使用者點擊這個訊息之後開啟的地址,這個時候我就組了一個自己網站的地址,是一個get請求地址,裡面攜帶參數是使用者的openid和訂單id,這樣使用者點擊開圖文訊息就可以看到自己剛才下單的內容了,因為需要在網頁上展示使用者的頭像和暱稱,所以我把openid也放到參數裡,在頁面載入前先拿到使用者的個人資訊和訂單資料,再展示網頁。這樣流程:使用者未登入下單 -> 產生二維碼 -> 使用者掃碼關注公眾號 -> 查看訂單詳細資料 就完成了。而且因為這個圖文訊息開啟後的連結攜帶的參數是這個使用者的額openid和其下單的訂單ID,不管分享到哪兒,用什麼瀏覽器開啟都是可以訪問的,且展示的也是這個使用者的頭像和暱稱資訊,這也是我要實現的一個效果。

以上就是本文的全部內容,希望對大家的學習有所協助,也希望大家多多支援指令碼之家。

  • 聯繫我們

    該頁面正文內容均來源於網絡整理,並不代表阿里雲官方的觀點,該頁面所提到的產品和服務也與阿里云無關,如果該頁面內容對您造成了困擾,歡迎寫郵件給我們,收到郵件我們將在5個工作日內處理。

    如果您發現本社區中有涉嫌抄襲的內容,歡迎發送郵件至: info-contact@alibabacloud.com 進行舉報並提供相關證據,工作人員會在 5 個工作天內聯絡您,一經查實,本站將立刻刪除涉嫌侵權內容。

    A Free Trial That Lets You Build Big!

    Start building with 50+ products and up to 12 months usage for Elastic Compute Service

    • Sales Support

      1 on 1 presale consultation

    • After-Sales Support

      24/7 Technical Support 6 Free Tickets per Quarter Faster Response

    • Alibaba Cloud offers highly flexible support services tailored to meet your exact needs.