微信公众号授权登录

本随笔为个人总结,相对较易理解,经验不深,如果有不正确的地方,请指出,谢谢
学习视频:https://www.imooc.com/learn/483
在thinkphp5.1使用的视频:https://www.bilibili.com/video/BV134411V7NC/?p=9&t=727

一、微信公众平台

1.1 开发概述

文档网页:https://developers.weixin.qq.com/doc/offiaccount/Getting_Started/Global_Return_Code.html

  1. 微信公众平台开发是指为微信公众号进行业务开发,为移动应用、PC端网站、公众号第三方平台(为各行各业公众号运营者提供服务)的开发,需要使用微信开放平台接入,这两个想使用微信授权登录等接口都要300每年

  2. 在申请到认证公众号之前,你以先通过测试号申请系统,快速申请一个接口测试号(可以使用微信授权登录),立即开始接口测试开发。

  3. 公众平台以access_token为接口调用凭据,来调用接口,所有接口的调用需要先获取access_token,access_token在2小时内有效,过期需要重新获取,但1天内获取次数有限自行存储

1.2 前提

网址:https://mp.weixin.qq.com/debug/cgi-bin/sandboxinfo?action=showinfo&t=sandbox/index

申请好了测试号,填写接口配置信息的URL,是用来让微信发送GET请求,GET请求中,带有几个参数,在这个PHP文件中我们要把GET参数中的echostr参数原封不动的输出出来,echo $_GET['echostr']; 此时便可校验成功,另外几个参数用来让我们校验是否是微信发送的请求,具体可以看文档

UTOOLS1587483355378.png

这里可以使用utoos(一个工具宝箱)工具里的内网穿透,需要配置一下host文件

UTOOLS1587535092632.png

1.3 接口调用实质

重点:通过GET地址栏传参,POST,取得xml文档、json等方式进行数据传输。

由于使用的是测试号,无法使用直接使用页面来添加公众号菜单,所以需要使用微信提供的接口来创建公众号的菜单,而使用这个接口,就需要获取access_token

1.4 获取access_token

1.5 curl(重点)

​ 我们需要使用到curl,简单来说能使用cURL实现Get和Post请求的方法,能获取访问的页面的信息,模拟访问网页,进一步了解:https://blog.csdn.net/weixin_39616995/article/details/82346526,

  /**
     * @param $url  要爬的地址
     * @param string $type 请求方式,get还是post
     * @param string $res  决定返回类型,对象("json")否则数组
     * @param string $arr  要进行post传输的json字符串
     * @return mixed 爬到的内容
     */
function httpCurl($url, $type="get", $res="json", $arr='')
    {
        //1.初始化curl
        $ch = curl_init();
        //2.设置curl参数
        curl_setopt($ch, CURLOPT_URL, $url);			//设置要访问的URL
        curl_setopt($ch, CURLOPT_RETURNTRANSFER, 1);	//设置使用curl_exec()获取访问到信息时,为1时以字符串返回,不直接输出
        if ($type == 'post') {
            curl_setopt($ch, CURLOPT_POST, 1);			//为1,设置为post访问
            curl_setopt($ch, CURLOPT_POSTFIELDS, $arr); //把$arr字符串当做表单数据post传输过去
        }
        //3.采集,正式进行页面访问,把页面输出的结果返回
        $output = curl_exec($ch);	
        //4.关闭
        curl_close($ch);
        
        if ($res == 'json') {
            return json_decode($output, false);			//false:把页面的json字符串返回结果输出成对象	
        }
        return json_decode($output, true);				//true:把页面的json字符串返回结果输出成数组
    }

在上面,我们可以知道,直接通过地址栏访问的话可以看到access_token,于是,我们也可以通过curl进行get访问该地址,并获取该页面的信息,但是,这是个json字符串,我们比较习惯使用数组,因此,我们通过json_decode()把这个获取到的json字符串转换为数组,用上面这个方法就会获取得方便一些,如:

$data = httpCurl("https://api.weixin.qq.com/cgi-bin/token?grant_type=client_credential&appid=wxada87&secret=7e88d8ba3c", "get", "arr", "");

这样便取得了access_token,有效时间为两个小时,这段时间里我们可以使用它调用接口。

1.6 创建菜单

UTOOLS1587559086640.png

接口调用请求说明

http请求方式:POST(请使用https协议) https://api.weixin.qq.com/cgi-bin/menu/create?access_token=ACCESS_TOKEN

click和view的请求示例

{
     "button":[
     {	
          "type":"click",
          "name":"今日歌曲",
          "key":"V1001_TODAY_MUSIC"
      },
      {
           "name":"菜单",
           "sub_button":[
           {	
               "type":"view",
               "name":"搜索",
               "url":"http://www.soso.com/"
            },
            {
                 "type":"miniprogram",
                 "name":"wxa",
                 "url":"http://mp.weixin.qq.com",
                 "appid":"wx286b93c14bbf93aa",
                 "pagepath":"pages/lunar/index"
             },
            {
               "type":"click",
               "name":"赞一下我们",
               "key":"V1001_GOOD"
            }]
       }]
 }

简单介绍type类型

  • type为view时,点击按钮会直接跳转到url中
  • 为click时,会向我们的填写的接口URL地址发送xml文档我们进行接收分析,再发送我们的xml文档到微信

让我们把带有刚刚获取的access_token接入该URL中,把创建菜单的json字符串post过去,现在构建json

$postArr = [
                "button" => [
                    [
                        'name' => urlencode('菜单'),			
                        'sub_button' => [
                            [
                                'type' => 'view',
                                'name' => urlencode('百度'),
                                'url'  => 'https://www.baidu.cn'
                            ],
                            [
                                'type' => 'click',
                                'name' => urlencode('联系我'),
                                'key'  => 'connect_me'
                            ]
                        ]
                    ],
                    [
                        'type' => 'view',
                        'name' => urlencode('百度'),
                        'url'  => 'https://www.baidu.cn'
                    ]
                ],
           ];
$postJson = urldecode(json_encode($postArr));
$res = httpCurl($url, 'post', 'json', $postJson);
var_dump($res);

讲解:

嗯?不是写json么,怎么变成了写数组,json是字符串,像这样:

{"button":[{"name":"菜单","sub_button":[{"type":"view","name":"百度","url":"https:\/\/www.baidu.cn"},{"type":"click","name":"联系我","key":"connect_me"}]},{"type":"view","name":"百度","url":"https:\/\/www.baidu.cn"}]}

也就是上面微信要求传输的数据,但是构建这个json字符串如果要嵌入变量或者在其中使用函数,就会相对麻烦,所以我们构建成数组,但是数组怎么变成json字符串呢?我们可以使用json_encode()函数进行转换,但是使用json_encode会造成新的问题,像这样"name":"\u83dc\u5355"

json_encode()会把其中的中文转化为unicode编码,但是我们要post过去的就是中文,因此我们可以要他变成不是中文,使用urlencode("菜单"),将所有中文转换为url编码,%E8%8F%9C%E5%8D%95,这时候再进行urldecode()会变成"name":"%E8%8F%9C%E5%8D%95",emmm,我们要传输的是中文。。。所以我们需要把这些url编码再转换成中文,使用urldecode()就能实现把其中的url编码转换成中文。综上$postJson = urldecode(json_encode($postArr));

终于把这个json字符串弄出来了,接下来就要把这个json字符串,传输给微信服务器

http请求方式:POST(请使用https协议) https://api.weixin.qq.com/cgi-bin/menu/create?access_token=ACCESS_TOKEN

要使用post,那就使用刚刚写好的httpCurl($url, 'post', 'json', $postJson)进行传输吧,就获得了微信服务器的json字符串,如果返回的是{"errcode":0,"errmsg":"ok"},那我们就设置菜单成功了,可以打开测试公众号进行查看啦(取消关注再进行关注会更新的快一些),错误的话就看一下返回的错误提示吧

1.7 网页授权

需要先到公众平台官网中的“开发 - 接口权限 - 网页服务 - 网页帐号 - 网页授权获取用户基本信息”的配置选项中,进行回调地址配置,填写域名就行,不用写http等

UTOOLS1587535763034.png UTOOLS1587535840099.png

授权步骤

  1. 引导用户进入授权页面同意授权,获取code

  2. 通过code换取网页授权access_token(与基础支持中的access_token不同)

  3. 通过网页授权access_token和openid获取用户基本信息

此处的access_token与前面的access_token不同,这里access_token的是用来获取用户基本信息的.

1.引导用户进入授权界面

在创建菜单时,其中一个按钮使用view

[
    'type' => 'view',
    'name' => urlencode('授权登录'),
    'url'  => 'https://www.yourdomain.cn/wxlogin.php'
]

此处的url使用自己要处理登录的php页面,成功创建菜单,并在公众号成功更新(不更新的话可以重新关注),我们点击这个按钮之后就会跳转到我们自己的页面,当然,啥也没有,我们现在就要在这个页面获取code

2.获取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

如果链接的参数顺序不对,授权页面将无法正常访问

我们在wxLogin.php这个页面中,需要构建这个并跳转到这个url,注意到,redirect_uri=http%3A%2F%2Fnba.bluewebgame.com%2Foauth_response.php,是一些看不懂的字符,我们需要使用urlencode( )将传输的地址的一些符号转化成这种形式才能进行传输,否则分不清url的参数到底是哪个url中的参数,因为都是使用&进行参数分割

redirect_url必须要在我们填写的回调地址域名下,否则会失败,在我们进行该url访问后,页面将跳转至 redirect_uri/?code=CODE&state=STATE,也就是会带有这些参数跳转到这个redirect_url网址,这个网址就应该用$_GET['code']来取得url参数中的code

参数详细介绍

参数 是否必须 说明
appid 公众号的唯一标识
redirect_uri 授权后重定向的回调链接地址, 请使用 urlEncode 对链接进行处理
response_type 返回类型,请填写code
scope 应用授权作用域,snsapi_base (不弹出授权页面,直接跳转,只能获取用户openid),snsapi_userinfo (弹出授权页面,可通过openid拿到昵称、性别、所在地。并且, 即使在未关注的情况下,只要用户授权,也能获取其信息 )
state 重定向后会带上state参数,开发者可以填写a-zA-Z0-9的参数值,最多128字节
#wechat_redirect 无论直接打开还是做页面302重定向时候,必须带此参数

把地址拼接好之后,直接header("Location:" . $url)跳转即可,接下来,微信对get过去的数据进行判断,并将参数code和state通过get传输到redirect_url上,如:http:www.mingyue.cn/wxCallback.php,参数state与我们传送过去的state一样,可以用来校验,该网址上,我们使用$_GET['code']来获取code

code说明 : code作为换取access_token的票据,每次用户授权带上的code将不一样,code只能使用一次,5分钟未被使用自动过期。

code的目的是用来获取access_token,access_token才是真正用来获取用户信息的令牌。

3.通过code获取access_token

获取code后,请求以下链接获取access_token: https://api.weixin.qq.com/sns/oauth2/access_token?appid=APPID&secret=SECRET&code=CODE&grant_type=authorization_code

参数说明

参数 是否必须 说明
appid 公众号的唯一标识
secret 公众号的appsecret
code 填写第一步获取的code参数
grant_type 填写为authorization_code

正确时该网页显示的JSON数据包如下:

{
  "access_token":"ACCESS_TOKEN",
  "expires_in":7200,
  "refresh_token":"REFRESH_TOKEN",
  "openid":"OPENID",
  "scope":"SCOPE" 
}
参数 描述
access_token 网页授权接口调用凭证,注意:此access_token与基础支持的access_token不同
expires_in access_token接口调用凭证超时时间,单位(秒)
refresh_token 用户刷新access_token
openid 用户唯一标识,请注意,在未关注公众号时,用户访问公众号的网页,也会产生一个用户和公众号唯一的OpenID
scope 用户授权的作用域,使用逗号(,)分隔
这里的步骤就和前面获取基础access_token(用来使用创建菜单接口的)的步骤一样,先连接对应参数的url,这个url可以直接地址栏进行访问,会看到对应的json数据,但是这是在微信的网站上的,我们需要使用curl进行获取json字符串并返回,再通过json_decode($ouput, true);//true为转换为数组,否则为对象将json字符串转换为数组(这些操作都正在上面自己写的httpCurl函数中完成:httpCurl($cur, "get", "arr")),就能通过数组下标将access_token和openid(用户的唯一标识)取出来,存入session等进行存放,在获取用户信息时需要使用到

注意:access_token的过期时间为expire_in(7200秒,2小时)

4.拉取用户信息(需scope为 snsapi_userinfo)

http:GET(请使用https协议) https://api.weixin.qq.com/sns/userinfo?access_token=ACCESS_TOKEN&openid=OPENID&lang=zh_CN

参数说明

参数 描述
access_token 网页授权接口调用凭证,注意:此access_token与基础支持的access_token不同
openid 用户的唯一标识
lang 返回国家地区语言版本,zh_CN 简体,zh_TW 繁体,en 英语

正确时返回的JSON数据包如下:

{   
  "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"
}

也是一样的,访问构造该url的地址时,该页面会显示json字符串,我们直接通过httpCurl($url, "get", "arr");返回的便是存有这个用户信息的数组,通过数组下标便可取出。

到这里,我们就把网页授权重要的部分弄完啦。

1.8 消息管理

当普通微信用户向公众账号发消息时,微信服务器将POST消息的XML数据包到开发者填写的URL上。

接收文本信息

<xml>
  <ToUserName><![CDATA[toUser]]></ToUserName>
  <FromUserName><![CDATA[fromUser]]></FromUserName>
  <CreateTime>1348831860</CreateTime>
  <MsgType><![CDATA[text]]></MsgType>
  <Content><![CDATA[this is a test]]></Content>
  <MsgId>1234567890123456</MsgId>
</xml>
参数 描述
ToUserName 开发者微信号
FromUserName 发送方帐号(一个OpenID)
CreateTime 消息创建时间 (整型)
MsgType 消息类型,文本为text
Content 文本消息内容
MsgId 消息id,64位整型

这里是post过来的xml数据包,不能直接使用$_POST获取

$postObj = file_get_contents("php://input");        //接收post过来的xml字符串
$postArr = simplexml_load_string($postObj, "SimpleXMLElement", LIBXML_NOCDATA); //将XML字符串解释为对象
$toUserName = $postArr->ToUserName;				//获取到xml中的开发者微信号
$fromUserName = $postArr->FromUserName;			//获取到xml的发送方帐号(一个OpenID))
$content = $postArr->Content;					//获取发送过来的内容
//参数列表的参数都能通过对象->属性的方式获取

这样我们就获取达到用户在微信公众号发送的信息啦。

回复文本信息

格式:

<xml>
  <ToUserName><![CDATA[toUser]]></ToUserName>
  <FromUserName><![CDATA[fromUser]]></FromUserName>
  <CreateTime>12345678</CreateTime>
  <MsgType><![CDATA[text]]></MsgType>
  <Content><![CDATA[你好]]></Content>
</xml>
参数 是否必须 描述
ToUserName 接收方帐号(收到的OpenID)
FromUserName 开发者微信号
CreateTime 消息创建时间 (整型)
MsgType 消息类型,文本为text
Content 回复的消息内容(换行:在content中能够换行,微信客户端就支持换行显示)

接受到用户发送过来的xml信息的页面中,我们需要构造这种xml格式的字符串,把其中的参数都替换掉,并将其输出到该页面,微信会将该xml字符串带走回应给用户。

构建该xml

我们可以直接将字符串和其中的微信需要修改的变量(如ToUserName,就是最初发送过来的FromUserName)进行替换和连接,这里使用sprintf

//构建回复新信息
$toUserName = $postArr->ToUserName;
$fromUserName = $postArr->FromUserName;
$content = "还没开通该功能"
$xml = "<xml>
          <ToUserName><![CDATA[%s]]></ToUserName>
          <FromUserName><![CDATA[%s]]></FromUserName>
          <CreateTime> .time(). </CreateTime>
          <MsgType><![CDATA[text]]></MsgType>
          <Content><![CDATA[%s]]></Content>
        </xml>";
$info = sprintf($xml, $fromUserName, $toUserName, $content);//把字符串中的%s逐个替换
echo $info;	//让微信直接在该页面拿走xml数据包

返回根据格式化字符串格式生成的字符串,如果成功的话微信公众号就会回复消息啦

看到这,其他地方的看文档应该看文档也能解决啦,下面只是潦草的介绍企业微信授权登录~

二、企业微信

文档地址:https://work.weixin.qq.com/api/doc/90000/90135/90664

2.1 相关概念介绍

  • corpid:每个企业都拥有唯一的corpid,获取此信息可在管理后台“我的企业”-“企业信息”下查看“企业ID”(需要有管理员权限)

  • userid:每个成员都有唯一的userid,即所谓“帐号”。在管理后台->“通讯录”->点进某个成员的详情页,可以看到。

  • agentid:每个应用都有唯一的agentid。在管理后台->“应用与小程序”->“应用”,点进某个应用,即可看到agentid。

  • secret:secret是企业应用里面用于保障数据安全的“钥匙”,每一个应用都有一个独立的访问密钥

  • access_token:access_token是企业后台去企业微信的后台获取信息时的重要票据,由corpid和secret产生。所有接口在通信时都需要携带此信息用于验证接口的访问权限

与微信公众号的不同之处:

  • 企业微信中只有一个access_token,而微信公众号中有两个(一个是调用各种接口的,一个是仅能用来获取用户信息的)

2.2 获取access_token

获取access_token是调用企业微信API接口的第一步,相当于创建了一个登录凭证,其它的业务API接口,都需要依赖于access_token来鉴权调用者身份。

获取用户信息直接就要用到这个access_token

请求方式: GET(HTTPS
请求地址: https://qyapi.weixin.qq.com/cgi-bin/gettoken?corpid=ID&corpsecret=SECRET
注:此处标注大写的单词ID和SECRET,为需要替换的变量,根据实际获取值更新。其它接口也采用相同的标注,不再说明。

参数说明:

参数 必须 说明
corpid 企业ID,获取方式参考:术语说明-corpid
corpsecret 应用的凭证密钥,获取方式参考:术语说明-secret

权限说明:
每个应用有独立的secret,获取到的access_token只能本应用使用,所以每个应用的access_token应该分开来获取

实现

当我们构造好上面的URL地址后,直接访问该URL地址就会看到相应的json字符串:

{    
     "errcode": 0,   
     "errmsg": "ok",   
     "access_token": "accesstoken000001",   
     "expires_in": 7200
}

参数说明:

参数 说明
errcode 出错返回码,为0表示成功,非0表示调用失败
errmsg 返回码提示语
access_token 获取到的凭证,最长为512字节
expires_in 凭证的有效时间(秒)

获取其他网页的字符串和微信公众号的一样,都是通过curl完成,这里再贴一次

  /**
     * @param $url  要爬的地址
     * @param string $type 请求方式,get还是post
     * @param string $res  决定返回类型,对象("json")否则数组
     * @param string $arr  要进行post传输的json字符串
     * @return mixed 爬到的内容
     */
function httpCurl($url, $type="get", $res="json", $arr='')
    {
        //1.初始化curl
        $ch = curl_init();
        //2.设置curl参数
        curl_setopt($ch, CURLOPT_URL, $url);			//设置要访问的URL
        curl_setopt($ch, CURLOPT_RETURNTRANSFER, 1);	//设置使用curl_exec()获取访问到信息时,为1时以字符串返回,不直接输出
        if ($type == 'post') {
            curl_setopt($ch, CURLOPT_POST, 1);			//为1,设置为post访问
            curl_setopt($ch, CURLOPT_POSTFIELDS, $arr); //把$arr字符串当做表单数据post传输过去
        }
        //3.采集,正式进行页面访问,把页面输出的结果返回
        $output = curl_exec($ch);	
        //4.关闭
        curl_close($ch);
        
        if ($res == 'json') {
            return json_decode($output, false);			//false:把页面的json字符串返回结果输出成对象	
        }
        return json_decode($output, true);				//true:把页面的json字符串返回结果输出成数组

使用该方法,httpCurl($url, 'get', 'arr')直接将url页面中的json字符串转换为数组,通过数组下标即可获取access_token,将其存起来(session,redis),过期时间2小时,后面的接口调用需要使用到

2.3 网页授权登录

步骤

与前面有些相似,所以就不详细介绍了

  1. 用户点击按钮,跳转网页页面(该网页能够进行构造url并跳转)
  2. 填写的回调地址上接收code
  3. 通过code和access_token获取用户身份:userid(是企业用户)或openid(不是企业用户)
  4. 为企业成员时,通过access_token和userid读取成员信息

1. 获取code

构建URL并跳转(header)

https://open.weixin.qq.com/connect/oauth2/authorize?appid=CORPID&redirect_uri=REDIRECT_URI&response_type=code&scope=snsapi_base&state=STATE#wechat_redirect

参数说明:

参数 必须 说明
appid 企业的CorpID
redirect_uri 授权后重定向的回调链接地址,请使用urlencode对链接进行处理
response_type 返回类型,此时固定为:code
scope 应用授权作用域。企业自建应用固定填写:snsapi_base
state 重定向后会带上state参数,企业可以填写a-zA-Z0-9的参数值,长度不可超过128个字节
#wechat_redirect 终端使用此参数判断是否需要带上身份信息

跳转到该url后,微信将通过get方式回调到redirect_uri,向我们传输 redirect_uri?code=CODE&state=STATE

2.回调页接收code

直接$_GET['code']即可获取

3.通过code和access_token获取用户身份

这里的用户有两种身份:非企业成员、企业成员

对于非企业成员返回的是openid,企业成员返回的是userid

请求方式:GET(HTTPS
请求地址:https://qyapi.weixin.qq.com/cgi-bin/user/getuserinfo?access_token=ACCESS_TOKEN&code=CODE

参数说明:

参数 必须 说明
access_token 调用接口凭证
code 通过成员授权获取到的code,最大为512字节。每次成员授权带上的code将不一样,code只能使用一次,5分钟未被使用自动过期。

a) 当用户为企业成员时返回示例如下:

{   "errcode": 0,   "errmsg": "ok",   "UserId":"USERID",   "DeviceId":"DEVICEID"}
参数 说明
errcode 返回码
errmsg 对返回码的文本描述内容
UserId 成员UserID。若需要获得用户详情信息,可调用通讯录接口:读取成员
DeviceId 手机设备号(由企业微信在安装时随机生成,删除重装会改变,升级不受影响)

b) 非企业成员授权时返回示例如下:

{   "errcode": 0,   "errmsg": "ok",   "OpenId":"OPENID",   "DeviceId":"DEVICEID"}
参数 说明
errcode 返回码
errmsg 对返回码的文本描述内容
OpenId 非企业成员的标识,对当前企业唯一
DeviceId 手机设备号(由企业微信在安装时随机生成,删除重装会改变,升级不受影响)

使用httpCurl获取该json并转换该字符串为数组,这里不再详细介绍,与前面的一样哒~

4.读取成员

在通讯录同步助手中此接口可以读取企业通讯录的所有成员信息,而自建应用可以读取该应用设置的可见范围内的成员信息。

请求方式:GET(HTTPS
请求地址:https://qyapi.weixin.qq.com/cgi-bin/user/get?access_token=ACCESS_TOKEN&userid=USERID

参数说明:

参数 必须 说明
access_token 调用接口凭证
userid 成员UserID。对应管理端的帐号,企业内必须唯一。不区分大小写,长度为1~64个字节

访问后显示的是json字符串,使用httpCurl访问url并获取该json并转换该字符串为数组,获取完成。

希望我的文章能对大家有所帮助,谢谢你的阅读~

posted @ 2020-04-22 20:46  明月复苏  阅读(3635)  评论(0编辑  收藏  举报
不见了