手把手實(shí)現(xiàn)微信網(wǎng)頁(yè)授權(quán)和微信支付,附源代碼(VUE and thinkPHP)

wechat

github
手把手實(shí)現(xiàn)微信網(wǎng)頁(yè)授權(quán)和微信支付,附源代碼(VUE and thinkPHP)

概述

公眾號(hào)開(kāi)發(fā)是痛苦的,痛苦在好多問(wèn)題開(kāi)發(fā)者文檔是沒(méi)有提到的,是需要你的. 在開(kāi)發(fā)過(guò)程中翻了好多的文檔,都是說(shuō)明其中的一部分問(wèn)題的,很費(fèi)時(shí)間,所以在此總結(jié)大體過(guò)程。我們模擬的是一個(gè)支付的商城,在實(shí)現(xiàn)購(gòu)買(mǎi)過(guò)程中基本是把微信公眾號(hào)最主要模塊實(shí)現(xiàn)了,其余的功能我們沒(méi)有涉及,但應(yīng)該是觸類(lèi)旁通的。

我們敘述的過(guò)程是按開(kāi)發(fā)流程進(jìn)行敘述的,不會(huì)是按照開(kāi)發(fā)文檔的形式敘述,希望您能結(jié)合微信的開(kāi)發(fā)文檔一起閱讀,當(dāng)然在流程中我們會(huì)提醒你閱讀的部分

目錄

  • 概述
    • [解決的問(wèn)題]
    • [前端技術(shù)棧]
    • [后端技術(shù)棧]
    • [基本說(shuō)明]
  • [開(kāi)發(fā)過(guò)程]
    • [0.準(zhǔn)備]
    • [1.基本配置]
    • [2.網(wǎng)頁(yè)授權(quán)]
  • JS-SDK
    • [簽名]
    • [簽名后臺(tái)]
    • [簽名前臺(tái)]
    • [微信支付]

解決的問(wèn)題

  • [x] 微信網(wǎng)頁(yè)授權(quán)
  • [x] 公眾號(hào)支付
  • [x] 公眾號(hào)分享
  • [x] 公眾號(hào)掃一掃
  • [x] 微信后臺(tái)獲取webapp(spa-vue)路由,導(dǎo)致 invalid 問(wèn)題
  • [x] 前端history.pushState()導(dǎo)致ios失效問(wèn)題
  • [x] 換取微信openID 順序問(wèn)題
  • [x] 網(wǎng)頁(yè)授權(quán)后強(qiáng)制登錄官網(wǎng)賬戶(hù),全局進(jìn)行攔截

前端技術(shù)棧

vue2 + vuex + vue-router + webpack + ES6/7 + axios + sass + flex

后端技術(shù)棧

thinkPHP3.2 + mysql + 阿里云Linux Ubuntu

基本說(shuō)明

開(kāi)發(fā)環(huán)境 macOS 10.13.3 nodejs 8.0.0 centOS 7.4

本文中使用的url是m.example.com (demo), 開(kāi)發(fā)過(guò)程中需要替換成你的URL。

如有問(wèn)題請(qǐng)直接在 Issues 中提,或者您發(fā)現(xiàn)問(wèn)題并有非常好的解決方案,歡迎 PR

本著線上線下一樣的原則,最好申請(qǐng)兩個(gè)認(rèn)證微信公眾號(hào),一個(gè)是發(fā)布使用,一個(gè)是本地開(kāi)發(fā)使用。微信自帶提供的微信測(cè)試功能也不太好用

可以添加群交流 544958637

開(kāi)發(fā)過(guò)程

0.準(zhǔn)備

請(qǐng)閱讀以下微信開(kāi)發(fā)者文檔

首頁(yè)

開(kāi)發(fā)者規(guī)范

公眾號(hào)接口權(quán)限說(shuō)明

全局返回碼說(shuō)明

附:參數(shù)說(shuō)明

appid:公眾號(hào)唯一標(biāo)識(shí)id(公眾號(hào)-開(kāi)發(fā)-基本配置中查看)。

secret:公眾號(hào)開(kāi)發(fā)密鑰(初次請(qǐng)保存本地,忘記請(qǐng)重置)。

openid: 每個(gè)微信用戶(hù)關(guān)注此公眾號(hào)后會(huì)生成openid,并且在此公眾號(hào)中每個(gè)用戶(hù)得openid是唯一的。

code : code作為換取access_token的票據(jù),每次用戶(hù)授權(quán)帶上的code將不一樣,code只能使用一次,5分鐘未被使用自動(dòng)過(guò)期。

IP 白名單:允許訪問(wèn)微信服務(wù)器的ip(linux 公網(wǎng)ip 注意如果服務(wù)器有CDN加速,CDN請(qǐng)?zhí)砑影酌麊危?/p>

1.基本配置

此部分對(duì)應(yīng)文檔的 入門(mén)指引 接入指南

  1. 基礎(chǔ)工具

  2. 設(shè)置web開(kāi)發(fā)者工具

    開(kāi)發(fā)-開(kāi)發(fā)者工具-web開(kāi)發(fā)者工具設(shè)置開(kāi)發(fā)者賬號(hào)

  3. 設(shè)置IP 白名單

    設(shè)置-安全中心-IP白名單設(shè)置你服務(wù)器的IP,通過(guò)開(kāi)發(fā)者ID及密碼調(diào)用獲取access_token接口時(shí),需要設(shè)置訪問(wèn)來(lái)源IP為白名單。

  4. 設(shè)置基本配置-開(kāi)發(fā)者ID

    設(shè)置開(kāi)發(fā)者密碼(AppSecret)

    image

    我們獲取到的AppSecret (eg) a66b789009df271cde47aaaaaaa

  5. 設(shè)置服務(wù)器基本配置

    這部的目的是為了和微信服務(wù)器建立聯(lián)系, 通過(guò)微信平臺(tái)實(shí)現(xiàn)我們的業(yè)務(wù)邏輯。

server.png
詳細(xì)版:

![image](http://upload-images.jianshu.io/upload_images/2491178-87d4e2f74ea3da4b?imageMogr2/auto-orient/strip%7CimageView2/2/w/1240)

接入微信公眾平臺(tái)開(kāi)發(fā),開(kāi)發(fā)者需要按照如下步驟完成:

1、填寫(xiě)服務(wù)器配置

2、驗(yàn)證服務(wù)器地址的有效性

3、依據(jù)接口文檔實(shí)現(xiàn)業(yè)務(wù)邏輯

下面詳細(xì)介紹這3個(gè)步驟。

**第一步:填寫(xiě)服務(wù)器配置**

    * 登錄微信公眾平臺(tái)官網(wǎng)后,在公眾平臺(tái)官網(wǎng)的開(kāi)發(fā)-基本設(shè)置頁(yè)面,勾選協(xié)議成為開(kāi)發(fā)者,點(diǎn)擊“修改配置”按鈕、。

    * 填寫(xiě)服務(wù)器地址(URL)、Token和EncodingAESKey

    * URL是開(kāi)發(fā)者用來(lái)接收微信消息和事件的接口URL。

    * Token可由開(kāi)發(fā)者可以任意填寫(xiě),用作生成簽名(該Token會(huì)和接口URL中包含的Token進(jìn)行比對(duì),從而驗(yàn)證安全性)

    * EncodingAESKey由開(kāi)發(fā)者手動(dòng)填寫(xiě)或隨機(jī)生成,將用作消息體加解密密鑰。

    * 同時(shí),開(kāi)發(fā)者可選擇消息加解密方式:明文模式、兼容模式和安全模式。模式的選擇與服務(wù)器配置在提交后都會(huì)立即生效

    * 加解密方式的默認(rèn)狀態(tài)為明文模式,選擇兼容模式和安全模式需要提前配置好相關(guān)加解密代碼
image

第二步:驗(yàn)證消息的確來(lái)自微信服務(wù)器
?
現(xiàn)在如果你點(diǎn)擊確認(rèn) 按鈕,肯定會(huì)報(bào)認(rèn)證錯(cuò)誤。因?yàn)槲覀儧](méi)有做微信認(rèn)證請(qǐng)求 接收。 開(kāi)發(fā)者提交信息后,微信服務(wù)器將發(fā)送GET請(qǐng)求到填寫(xiě)的服務(wù)器地址URL上,GET請(qǐng)求攜帶參數(shù)如下表所示:
?

參數(shù) 描述
signature 微信加密簽名,signature結(jié)合了開(kāi)發(fā)者填寫(xiě)的token參數(shù)和請(qǐng)求中的timestamp參數(shù)、nonce參數(shù)。
timestamp 時(shí)間戳
nonce 隨機(jī)數(shù)
echostr 隨機(jī)字符串

開(kāi)發(fā)者通過(guò)檢驗(yàn)signature對(duì)請(qǐng)求進(jìn)行校驗(yàn)(下面有校驗(yàn)方式)。若確認(rèn)此次GET請(qǐng)求來(lái)自微信服務(wù)器,請(qǐng)?jiān)瓨臃祷豦chostr參數(shù)內(nèi)容,則接入生效,成為開(kāi)發(fā)者成功,否則接入失敗。加密/校驗(yàn)流程如下:

  1. 將token、timestamp、nonce三個(gè)參數(shù)進(jìn)行字典序排序
  2. 將三個(gè)參數(shù)字符串拼接成一個(gè)字符串進(jìn)行sha1加密
  3. 開(kāi)發(fā)者獲得加密后的字符串可與signature對(duì)比,標(biāo)識(shí)該請(qǐng)求來(lái)源于微信

微信官方提供在文檔中提供了PHP原生示例 PHP原生驗(yàn)證demo

Thinkphp 3.2 驗(yàn)證示例

<?php
namespace Home\Controller;//命名空間注意用自己的
use Think\Controller; //引入Think Controller

/**
 * Class IndexController
 * @package Home\Controller
 * @name 微信服務(wù)器驗(yàn)證類(lèi)
 * @author weikai
 */
class IndexController extends Controller {
    //微信服務(wù)器接入 
    public function index()
    {
        //這個(gè)echostr呢  只有說(shuō)驗(yàn)證的時(shí)候才會(huì)echo  如果是驗(yàn)證過(guò)之后這個(gè)echostr是不存在的字段了
        if($_GET['echostr']){
            $echoStr = $_GET["echostr"];
            if ($this->checkSignature()) {
                ob_clean();//防止之前緩存區(qū)數(shù)據(jù)影響
                echo $echoStr;
                exit; 
            }
        }else{
            $this->responseMsg(); //如果沒(méi)有echostr,則返回消息
        }
    }
    //驗(yàn)證微信開(kāi)發(fā)者模式接入是否成功
    private function checkSignature()
    {
        //signature 是微信傳過(guò)來(lái)的簽名
        $signature = $_GET["signature"];
        //微信發(fā)過(guò)來(lái)的時(shí)間戳
        $timestamp = $_GET["timestamp"];
        //微信傳過(guò)來(lái)的值隨機(jī)字符串
        $nonce     = $_GET["nonce"];
        //定義你在微信公眾號(hào)開(kāi)發(fā)者模式里面定義的token 這里舉例為weixin
        $token  = "weixin";
        //三個(gè)變量 按照字典排序 形成一個(gè)數(shù)組
        $tmpArr = array(
            $token,
            $timestamp,
            $nonce
        );
        // 字典排序
        sort($tmpArr, SORT_STRING);
        $tmpStr = implode($tmpArr);
        //哈希加密  在laravel里面是Hash::
        $tmpStr = sha1($tmpStr);
        //哈希加密后的數(shù)據(jù) 和微信服務(wù)器傳過(guò)來(lái)的簽名比較
        if ($tmpStr == $signature) {
            return true;
        } else {
            return false;
        }
    }

    /**
     * @name 消息接收
     * @author weikai
     */
    public function responseMsg()//執(zhí)行接收器方法
    {
      //獲取微信服務(wù)器的XML數(shù)據(jù) 轉(zhuǎn)化為對(duì)象 判斷消息類(lèi)型
        $postStr = $GLOBALS["HTTP_RAW_POST_DATA"];
        if (!empty($postStr)){
            $postObj = simplexml_load_string($postStr, 'SimpleXMLElement', LIBXML_NOCDATA);
            $RX_TYPE = trim($postObj->MsgType);
            switch($RX_TYPE){
                case "event":
                    $result = $this->receiveEvent($postObj);
                    break;
                case "text":
                    $result = $this->handleText($postObj);
                    break;
            }
            echo $result;
        }else{
            echo "";
            exit;
        }
    }

} //classend




**注意:示例代碼中 Token 要與微信公眾號(hào)基本配置中的Token 一致 **

微信公眾號(hào)基本配置中點(diǎn)擊啟用配置,如果驗(yàn)證失敗可能是網(wǎng)絡(luò)延遲導(dǎo)致,再點(diǎn)擊啟用多試幾次,3次以上不成功,請(qǐng)檢查代碼。

2.網(wǎng)頁(yè)授權(quán)

如果使用支付功能,必須先授權(quán)

大家應(yīng)該經(jīng)歷過(guò),我們?cè)诠娞?hào)打開(kāi)頁(yè)面,一般都會(huì)彈出一個(gè)按鈕需要我們點(diǎn)擊同意才會(huì)繼續(xù)瀏覽頁(yè)面

WechatIMG190.jpeg

但是我們第二次點(diǎn)擊的時(shí)候是不需要點(diǎn)擊授權(quán)的,這兩個(gè)過(guò)程是不同的,是兩種授權(quán):(樣例不可直接使用,是demo)

  • 非靜默授權(quán)的 URL 樣例:(scope=snsapi_userinfo

請(qǐng)注意加粗部分

https://open.weixin.qq.com/connect/oauth2/authorize?appid=wx841a97238d9e17b2&redirect_uri=http://cps.dianping.com/weiXinRedirect&response_type=code&scope=snsapi_userinfo&state=type%3Dquan%2Curl%3Dhttp%3A%2F%2Fmm.dianping.com%2Fweixin%2Faccount%2Fhome

點(diǎn)擊`允許`即可帶著用戶(hù)信息跳轉(zhuǎn)到第三方頁(yè)面,如上圖. 
作用: 是用來(lái)獲取用戶(hù)的基本信息的
  • 靜默授權(quán)的 URL 樣例: (scope=snsapi_base)

請(qǐng)注意加粗部分

https://open.weixin.qq.com/connect/oauth2/authorize?appid=wx841a97238d9e17b2&redirect_uri=http://cps.dianping.com/weiXinRedirect&response_type=code&scope=snsapi_base&state=type%3Dquan%2Curl%3Dhttp%3A%2F%2Fmm.dianping.com%2Fweixin%2Faccount%2Fhome

在微信 web 開(kāi)發(fā)者工具中打開(kāi)類(lèi)似的授權(quán)頁(yè) URL 則會(huì)`自動(dòng)跳轉(zhuǎn)`到第三方頁(yè)面。
作用:是用來(lái)獲取進(jìn)入頁(yè)面的用戶(hù)的openid的

注意:倆者授權(quán)區(qū)別

非靜默授權(quán):可獲取微信用戶(hù)基礎(chǔ)信息如 用戶(hù)微信昵稱(chēng) 、城市、語(yǔ)言、頭像、關(guān)注公眾號(hào)時(shí)間、openid等。

靜默授權(quán):用戶(hù)體驗(yàn)好,用戶(hù)不知覺(jué)間完成授權(quán),但只可以獲取到用戶(hù)得openid。


網(wǎng)頁(yè)授權(quán)

請(qǐng)通讀微信網(wǎng)頁(yè)授權(quán)

請(qǐng)注意 關(guān)于網(wǎng)頁(yè)授權(quán)access_token和普通access_token的區(qū)別 章節(jié)

具體而言,網(wǎng)頁(yè)授權(quán)流程分為四步:

注意: 步驟一是由前臺(tái)完成的,前臺(tái)獲取code 之后需要傳給后臺(tái),由后臺(tái)完成 2 3 4

1. 引導(dǎo)用戶(hù)進(jìn)入授權(quán)頁(yè)面同意授權(quán)后微信跳轉(zhuǎn)回調(diào)地址并傳遞參數(shù)code 獲取code

2. 通過(guò)code換取網(wǎng)頁(yè)授權(quán)access_token(與基礎(chǔ)支持中的access_token不同)

3. 如果需要,開(kāi)發(fā)者可以刷新網(wǎng)頁(yè)授權(quán)access_token,避免過(guò)期

4. 通過(guò)網(wǎng)頁(yè)授權(quán)access_token和openid獲取用戶(hù)基本信息(支持UnionID機(jī)制)
getcode.png

1、引導(dǎo)用戶(hù)進(jìn)入授權(quán)頁(yè)面同意授權(quán),獲取code

建議:如果路由由vue管理,建議code由前臺(tái)獲取并發(fā)送給后臺(tái)。 在公眾賬號(hào)中配置授權(quán)回調(diào)域名

redirect_uri_config.png

(${redirect_url}看下面)

微信授權(quán)是前端發(fā)起的,

  • 時(shí)機(jī): 是在你需要獲取微信信息之前的頁(yè)面發(fā)起請(qǐng)求,當(dāng)然大部分情況是用戶(hù)進(jìn)入webapp 我們就開(kāi)始授權(quán),我們的dome中就是進(jìn)入立馬授權(quán)

  • 前臺(tái)(Vue): 前臺(tái)做引導(dǎo)到授權(quán)頁(yè)面,使用location.href 就可以實(shí)現(xiàn)。授權(quán)過(guò)程中會(huì)有幾次這頁(yè)面跳轉(zhuǎn)。我們把授權(quán)函數(shù)放在router.beforeEach((to, from, next)=> {}) 函數(shù)中,好控制。

  • 跳轉(zhuǎn): 我們剛才提到前臺(tái)需要引導(dǎo),這個(gè)引導(dǎo)路徑是需要后臺(tái)提供,基本的形式是location.href = http://m.example.com/Home/WxSignature/getBaseInfos?redirect_url=${redirect_url}。要注意redirect_url=${redirect_url}${redirect_url} 是告訴后臺(tái)回調(diào)到前臺(tái)的URL(請(qǐng)encodeURIComponent).

  • 后臺(tái)(PHP): 前臺(tái)調(diào)到了后臺(tái),后臺(tái)此時(shí)需要獲取code了。后臺(tái)要通過(guò) 特定的URL(見(jiàn)官網(wǎng)第一步:用戶(hù)同意授權(quán),獲取code)獲取code.

    api參數(shù)解釋?zhuān)?/strong>

    • appid : 請(qǐng)查看本文 參數(shù)說(shuō)明

    • redirect_uri : 回調(diào)鏈接,完成用戶(hù)授權(quán)后微信服務(wù)器自動(dòng)回調(diào)得uri,一般為業(yè)務(wù)首頁(yè)鏈接(注意請(qǐng)轉(zhuǎn)義)。

    • response_type : 固定為code 。

    • scope : 授權(quán)方式 可選靜默(snsapi_base) 或者非靜默(snsapi_userinfo)

    • state : 此參數(shù)可為業(yè)務(wù)需求使用,根據(jù)業(yè)務(wù)需要傳入。

    • 靜默授權(quán)方式獲取code: https://open.weixin.qq.com/connect/oauth2/authorize?appid=你的appid&redirect_uri=https%3A%2F%2Fchong.qq.com%2Fphp%2Findex.php%3Fd%3D%26c%3DwxAdapter%26m%3DmobileDeal%26showwxpaytitle%3D1%26vb2ctag%3D4_2030_5_1194_60&response_type=code&scope=snsapi_base&state=123#wechat_redirect

    • 非靜默授權(quán)方式獲取code:https://open.weixin.qq.com/connect/oauth2/authorize?appid=wxf0e81c3bee622d60&redirect_uri=http%3A%2F%2Fnba.bluewebgame.com%2Foauth_response.php&response_type=code&scope=snsapi_userinfo&state=STATE#wechat_redirect

   /**
     * @name 授權(quán)引導(dǎo)后微信會(huì)跳轉(zhuǎn)到回調(diào)地址并攜帶code參數(shù)
     * @author weikai
     */

public function getBaseInfos(){
    $redirect_url = I('get.redirect_url');//獲取前臺(tái)傳遞的回調(diào)地址
    $app_id = C('WX_APPID');//獲取自己公眾號(hào)的 appid
    $redirect_uri = urlencode($redirect_url);//處理url
    $url = "https://open.weixin.qq.com/connect/oauth2/authorize?appid=".$app_id."&redirect_uri=".$redirect_uri."&response_type=code&scope=snsapi_userinfo&state=1#wechat_redirect";
    header('location:'.$url);

}

錯(cuò)誤返回碼說(shuō)明如下:

返回碼 說(shuō)明
10003 redirect_uri域名與后臺(tái)配置不一致
10004 此公眾號(hào)被封禁
10005 此公眾號(hào)并沒(méi)有這些scope的權(quán)限
10006 必須關(guān)注此測(cè)試號(hào)
10009 操作太頻繁了,請(qǐng)稍后重試
10010 scope不能為空
10011 redirect_uri不能為空
10012 appid不能為空
10013 state不能為空
10015 公眾號(hào)未授權(quán)第三方平臺(tái),請(qǐng)檢查授權(quán)狀態(tài)
10016 不支持微信開(kāi)放平臺(tái)的Appid,請(qǐng)使用公眾號(hào)Appid
  • 前臺(tái)獲取code

    引導(dǎo)用戶(hù)到授權(quán)頁(yè)面后 微信服務(wù)器會(huì)根據(jù)redirect_uri參數(shù)跳轉(zhuǎn),并且攜帶code參數(shù)和值

code.jpeg

前臺(tái)截取出code 就可以了,傳給后臺(tái),到這里基本就可以了。但是我們通常是用戶(hù)每次登陸都需要進(jìn)行授權(quán),我們判斷url中的參數(shù)就可以實(shí)現(xiàn)了。往往我們也要監(jiān)聽(tīng)用戶(hù)是否登錄判斷用戶(hù)是否需要賬號(hào)密碼登錄也需要在 router.beforeEach((to, from, next)=> {}) 實(shí)現(xiàn),beforeEach()有些復(fù)雜了,請(qǐng)大家閱讀具體代碼。請(qǐng)結(jié)合自己具體的業(yè)務(wù)書(shū)寫(xiě)


/**
 * 判斷用戶(hù)是否需要賬號(hào)密碼登錄,login頁(yè)面監(jiān)聽(tīng)
 * @Author   Hybrid
 * @DateTime 2018-02-28
 */
let checkIsLoginGotologin = function(to, next) {
    // isRelation 判斷用戶(hù)微信賬戶(hù)是否關(guān)聯(lián)官網(wǎng)賬戶(hù)
    // routeArr 是一些路由是不需要受監(jiān)聽(tīng)的
    // !res ? 已經(jīng)授權(quán) :沒(méi)有授權(quán)
  isRelation().then(res => {
    if (routeArr.includes(to.path)) {
      !res ? next('index') : next();
    } else {
      // 沒(méi)有授權(quán)且不是授權(quán)頁(yè)                             // 當(dāng)在授權(quán)的情況下是不允許訪問(wèn)login頁(yè)面
      (res && to.path !== '/login') ? next('/login'): ((!res && to.path === '/login') ? next('index') : next())
    }
  })
}

/**
 * 獲取和推送code
 * @Author   Hybrid
 * @DateTime 2018-02-28
 * @param    {}   url 路徑   
 */
let getCodePullCode = async function(url) {
  let mycode = url.substring(url.indexOf('code=') + 5, url.indexOf('state=') - 1);// 前臺(tái)截取code
  selfStore.set('wechatCodeStr', mycode); // 存儲(chǔ)code
  //傳送給后臺(tái)code
  await axios
    .get("/home/WxSignature/getCode", {
      params: {
        code: mycode
      }
    })
    .then(res => {
      //需要登錄
      var res = res.data;
      if (res && res.status === 1) {
        selfStore.set('openId', res.data);//本地存儲(chǔ)Openid,也可以不存儲(chǔ)。由后臺(tái)調(diào)配

        location.href = `http://m.example.com/?a=1#${location.href.split('#')[1]}`; // 增加a=1 防止支付錯(cuò)誤 防止前臺(tái)死循環(huán)
      }
    });
}

/**
 * 全局路由
 * @Author   Hybrid
 * @DateTime 2018-02-28
 */
if (process.env.NODE_ENV == 'production') {
  router.beforeEach((to, from, next) => {
    let url = location.href;
    // 同時(shí)判斷'a=1' 和code= 防止前臺(tái)死循環(huán) 
    // wechatCode沒(méi)有 發(fā)起授權(quán)
    if ((url.indexOf('a=1') < 1) && (url.indexOf('code=') < 1)) {
      let redirect_url = encodeURIComponent(`http://m.example.com#${to.path}`);
      location.href = `http://m.example.com/Home/WxSignature/getBaseInfos?redirect_url=${redirect_url}`;
    } else {
      // 后臺(tái)重定向頁(yè)面,授權(quán)登錄
      (!(url.indexOf('code=') < 1)) ? getCodePullCode(url): checkIsLoginGotologin(to, next)
    }
  })
}

2、通過(guò)code換取網(wǎng)頁(yè)授權(quán)access_token(與基礎(chǔ)支持中的access_token不同)

appid : 請(qǐng)查看本文 參數(shù)說(shuō)明

secret : 請(qǐng)查看本文 參數(shù)說(shuō)明

code :獲取到得code。

grant_type : 固定為authorization_code

獲取code后,請(qǐng)求以下鏈接獲取access_token以及用戶(hù)得openid:

 https://api.weixin.qq.com/sns/oauth2/access_token?appid=你的appid&secret=你的sercret&code=剛剛獲取得code&grant_type=authorization_code
  /**
     * 前臺(tái)傳遞code,后臺(tái)存儲(chǔ)
     * @Author   weikai
     * @DateTime 2017-11-23
     * @return   [type]     [description]
     */
    public function getCode() {
        $code = I('get.code');//授權(quán)用code
        $appid = C('WX_APPID');//你的公眾號(hào)appid
        $secret = C('WX_APPSECRET');//你的公眾號(hào)secret
         // 組合獲取的url
            $url="https://api.weixin.qq.com/sns/oauth2/access_token?                appid=$appid&secret=$secret&code=$code&grant_type=authorization_code";
            // curl獲取access_token 和openid
            $result=$this->curl_get_contents($url);//curl get請(qǐng)求函數(shù)請(qǐng)自行百度
            $result=json_decode($result,true);//json轉(zhuǎn)數(shù)組
            $data['openid']=$result['openid'];
            $data['access_token'] = $result['access_token'];
            $data['refresh_token'] = $result['refresh_token'];
        if($data){
            return $this->ajaxReturn(show(1,'獲取access_token 和openid',$data));//show()方法為自定義封裝消息
        }else{
            return $this->ajaxReturn(show(0,'沒(méi)有access_token 和openid')); 
        }
    }

正確時(shí)返回的JSON數(shù)據(jù)包如下:

{ "access_token":"ACCESS_TOKEN",
"expires_in":7200,
"refresh_token":"REFRESH_TOKEN",
"openid":"OPENID",
"scope":"SCOPE" }

有些數(shù)據(jù)是需要存儲(chǔ)到后臺(tái)數(shù)據(jù)庫(kù)的如openid

參數(shù) 描述
access_token 網(wǎng)頁(yè)授權(quán)接口調(diào)用憑證,注意:此access_token與基礎(chǔ)支持的access_token不同
expires_in access_token接口調(diào)用憑證超時(shí)時(shí)間,單位(秒)
refresh_token 用戶(hù)刷新access_token
openid 用戶(hù)唯一標(biāo)識(shí),請(qǐng)注意,在未關(guān)注公眾號(hào)時(shí),用戶(hù)訪問(wèn)公眾號(hào)的網(wǎng)頁(yè),也會(huì)產(chǎn)生一個(gè)用戶(hù)和公眾號(hào)唯一的OpenID
scope 用戶(hù)授權(quán)的作用域,使用逗號(hào)(,)分隔

錯(cuò)誤時(shí)微信會(huì)返回JSON數(shù)據(jù)包如下(示例為Code無(wú)效錯(cuò)誤):

{"errcode":40029,"errmsg":"invalid code"}

其實(shí)完成第二步就完成了基本的網(wǎng)頁(yè)授權(quán)但是還沒(méi)有獲取到用戶(hù)的信息,授權(quán)也沒(méi)有實(shí)際作用了。

3、刷新access_token(如果需要)

由于獲取用戶(hù)信息所用得access_token有效時(shí)常比較短,如果想獲取access_token后間隔時(shí)間較長(zhǎng)獲取微信用戶(hù)基本信息請(qǐng)請(qǐng)求刷新access_token api

我這里沒(méi)有采用授權(quán)后拉取用戶(hù)信息的api,而是采用用戶(hù)信息獲取的api。

請(qǐng)求方法

獲取第二步的refresh_token后,請(qǐng)求以下鏈接獲取access_token:
https://api.weixin.qq.com/sns/oauth2/refresh_token?appid=APPID&grant_type=refresh_token&refresh_token=REFRESH_TOKEN
參數(shù) 是否必須 說(shuō)明
appid 公眾號(hào)的唯一標(biāo)識(shí)
grant_type 填寫(xiě)為refresh_token
refresh_token 填寫(xiě)通過(guò)access_token獲取到的refresh_token參數(shù)
  /**
     * 刷新access_token
     * @Author   weikai
     * @refresh_token 用與刷新access_token的參數(shù)
     * @DateTime 2017-11-23
     * @return   [type]     [description]
     */
    public function reAccessToken($refresh_token) {
        $appid = C('WX_APPID');//你的公眾號(hào)appid
         // 組合獲取的url
            $url="https://api.weixin.qq.com/sns/oauth2/refresh_token?appid=$appid&grant_type=refresh_token&refresh_token=$refresh_token";
            // curl請(qǐng)求刷新access_token 
            $result=$this->curl_get_contents($url);//curl get請(qǐng)求函數(shù)請(qǐng)自行百度
            $result=json_decode($result,true);//json轉(zhuǎn)數(shù)組
            $data['access_token'] = $result['access_token'];
        if($data){
            return $this->ajaxReturn(show(1,'獲取access_token' ,$data));//show()方法為自定義封裝消息
        }else{
            return $this->ajaxReturn(show(0,'沒(méi)有access_token')); 
        }
    }

返回說(shuō)明

正確時(shí)返回的JSON數(shù)據(jù)包如下:

{ "access_token":"ACCESS_TOKEN",
"expires_in":7200,
"refresh_token":"REFRESH_TOKEN",
"openid":"OPENID",
"scope":"SCOPE" }

和上步返回的數(shù)據(jù)相同,目的就是刷新了access_token 的有效時(shí)間,有效期內(nèi)可以使用access_token 和openid獲取微信用戶(hù)信息

4、通過(guò)網(wǎng)頁(yè)授權(quán)access_token和openid獲取用戶(hù)基本信息

注意:

這里微信提供了兩個(gè)不同的api

1.在微信授權(quán)里微信提供拉取用戶(hù)信息的api(access_token時(shí)間限制為五分鐘失效)

http:GET

https://api.weixin.qq.com/sns/userinfo?access_token=ACCESS_TOKEN&openid=OPENID&lang=zh_CN

參數(shù)說(shuō)明

參數(shù) 描述
access_token 網(wǎng)頁(yè)授權(quán)接口調(diào)用憑證,注意:此access_token與基礎(chǔ)支持的access_token不同
openid 用戶(hù)的唯一標(biāo)識(shí)
lang 返回國(guó)家地區(qū)語(yǔ)言版本,zh_CN 簡(jiǎn)體,zh_TW 繁體,en 英語(yǔ)

2.微信用戶(hù)管理提供的獲取用戶(hù)信息api(只需要使用全局access_token有效期2小時(shí),和openid)

推薦使用這個(gè)接口獲取用戶(hù)信息

http: GET

https://api.weixin.qq.com/cgi-bin/user/info?access_token=ACCESS_TOKEN&openid=OPENID&lang=zh_CN

參數(shù)說(shuō)明

參數(shù) 描述
access_token 全局access_token 有效期7200秒
openid 用戶(hù)的唯一標(biāo)識(shí)
lang 返回國(guó)家地區(qū)語(yǔ)言版本,zh_CN 簡(jiǎn)體,zh_TW 繁體,en 英語(yǔ)

如果網(wǎng)頁(yè)授權(quán)參數(shù)為snsapi_userinfo(非靜默授權(quán)),則此時(shí)可以通過(guò)access_token和openid獲取用戶(hù)信息了。

PHP示例

    /**
     * @return mixed
     * @name 使用全局access_token獲取用戶(hù)詳細(xì)信息 
     * @author weikai
     */
    public function getWxUserInfo($openid){
        $access_token = $this->getAccess_Token();
        $url = "https://api.weixin.qq.com/cgi-bin/user/info?access_token=".$access_token."&openid=".$openid."&lang=zh_CN";
        $data = $this->cUrl($url);
        $data = json_decode($data);
      if($data){
        return $data;  
      }     
    }

返回說(shuō)明

正確時(shí)返回的JSON數(shù)據(jù)包如下:

{    "openid":" OPENID",
" nickname": NICKNAME,
"sex":"1",
"province":"PROVINCE"
"city":"CITY",
"country":"COUNTRY",
"headimgurl":    "http://thirdwx.qlogo.cn/mmopen/g3MonUZtNHkdmzicIlibx6iaFqAc56vxLSUfpb6n5WKSYVY0ChQKkiaJSgQ1dZuTOgvLLrhJbERQQ4eMsv84eavHiaiceqxibJxCfHe/46",
"privilege":[ "PRIVILEGE1" "PRIVILEGE2"     ],
"unionid": "o6_bmasdasdsad6_2sgVt7hMZOPfL"
}

參數(shù) 描述
openid 用戶(hù)的唯一標(biāo)識(shí)
nickname 用戶(hù)昵稱(chēng)
sex 用戶(hù)的性別,值為1時(shí)是男性,值為2時(shí)是女性,值為0時(shí)是未知
province 用戶(hù)個(gè)人資料填寫(xiě)的省份
city 普通用戶(hù)個(gè)人資料填寫(xiě)的城市
country 國(guó)家,如中國(guó)為CN
headimgurl 用戶(hù)頭像,最后一個(gè)數(shù)值代表正方形頭像大小(有0、46、64、96、132數(shù)值可選,0代表640*640正方形頭像),用戶(hù)沒(méi)有頭像時(shí)該項(xiàng)為空。若用戶(hù)更換頭像,原有頭像URL將失效。
privilege 用戶(hù)特權(quán)信息,json 數(shù)組,如微信沃卡用戶(hù)為(chinaunicom)
unionid 只有在用戶(hù)將公眾號(hào)綁定到微信開(kāi)放平臺(tái)帳號(hào)后,才會(huì)出現(xiàn)該字段。

錯(cuò)誤時(shí)微信會(huì)返回JSON數(shù)據(jù)包如下(示例為openid無(wú)效):

{"errcode":40003,"errmsg":" invalid openid "}

最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請(qǐng)聯(lián)系作者
【社區(qū)內(nèi)容提示】社區(qū)部分內(nèi)容疑似由AI輔助生成,瀏覽時(shí)請(qǐng)結(jié)合常識(shí)與多方信息審慎甄別。
平臺(tái)聲明:文章內(nèi)容(如有圖片或視頻亦包括在內(nèi))由作者上傳并發(fā)布,文章內(nèi)容僅代表作者本人觀點(diǎn),簡(jiǎn)書(shū)系信息發(fā)布平臺(tái),僅提供信息存儲(chǔ)服務(wù)。

相關(guān)閱讀更多精彩內(nèi)容

友情鏈接更多精彩內(nèi)容