美文网首页
微信开发

微信开发

作者: 书上得来终觉浅 | 来源:发表于2020-03-29 09:47 被阅读0次

    微信有4种类型的服务:

    • 订阅号,针对媒体和个人,偏向于向用户传达咨询即发消息(一般是推文),每天可以群发一条消息,消息被放在“订阅号消息”栏中。
    • 服务号,针对企业和组织,偏向于交互服务,因为偏向于服务,所以每月只能发4次推文。
    • 企业号,所有功能都支持
    • 小程序

    订阅号和服务号在开发者接口权限上有所不同,服务号更全面。不过对于一些基本的接口权限,订阅号都能满足,具体可以参考权限接口说明

    对于有支付需求的应用,不管是服务号还是订阅号都需要做支付申请,但是尽量选择服务号。

    出于用户体验和安全性方面的考虑,微信公众号的注册有一定门槛,某些高级接口的权限需要微信认证后才可以获取。所以,为了帮助开发者快速了解和上手微信公众号开发,熟悉各个接口的调用,微信推出了微信公众帐号测试号,通过手机微信扫描二维码即可获得测试号。

    接入微信公众平台

    环境准备:

    • 公众平台测试账号(参考上一节)
    • 内网映射,在接入公众平台时,需要提供服务器的URL地址,这里使用Natapp做内网映射

    natapp隧道搭建

    微信公众平台开发者模式需要提供服务器的URL地址,这里使用NATAPP做内网穿透。

    打开NATAPP官网,注册登录后,点击购买隧道,可以使用免费隧道,也可购买付费隧道。免费隧道与付费隧道不同的是,付费隧道支持固定的二级域名(当然,这个二级域名也是需要你购买的),这样我们每次启动natapp做内网穿透时,域名不会改变的,方便调试。

    购买隧道后,我们做客户端的配置,这里我是Mac环境,其他环境参考官网

    下载natapp客户端,添加执行权限

    # 解压
    ➜  Desktop unzip natapp_darwin_amd64_2_3_9.zip 
    Archive:  natapp_darwin_amd64_2_3_9.zip
      inflating: natapp  
    # 移动natapp到natapp目录下
    ➜  Desktop mkdir ~/natapp && mv natapp ~/natapp/
    ➜  Desktop cd ~/natapp 
    ➜  natapp chmod +x natapp 
    

    运行natapp

    ./natapp -authtoken=xxxxxxxxxx
    

    authtoken的值在我的隧道列表中可以查看。至此,natapp隧道搭建完成,总的流程如下:

    • 购买隧道(可以使用免费的隧道),设置域名和本地应用端口
    • 在本地启动natapp客户端做穿透

    配置后台服务器信息

    微信服务器使用应用服务器配置信息来与其做交互,配置信息主要包括URL地址、token和EncodingAESKey,其中:

    • URL 是应用服务器的地址,它是微信服务器与应用服务器的交互入口,公众号产生的任何消息(如用户关注该公众号,或用户向公众号发送消息等),都会调用该地址通知应用服务器。
    • token 表示令牌,在填写了URL地址后,微信服务器需要验证该地址是否有效,这是就需要用到这个token
    • EncodingAESKey 消息加密密钥,用户在公众号上产生的所有事件,都会以消息的形式发送了上面的URL地址,这个消息可以选择加密,这个EncodingAESKey就是消息加密的密钥。
    image-20200326151044920.png

    编写服务器验证接口

    微信会验证我们提供的服务器URL是否有效,具体流程如下:

    • 微信服务器向URL发送GET请求
    • 服务器验证该请求,并返回指定的值

    GET请求附带了一些参数,包括:

    • signature 签名,作为我们验证结果的比对
    • timestamp 时间戳,验证参数之一
    • nonce 随机数,验证参数之一
    • echostr 如果成功返回该参数

    具体的验证算法伪代码如下:

    if(sha1(token+timestamp+nonce) == signature){
      return echostr;
    }
    return "";
    

    将token、timestamp和nonce按顺序组成一个字符串,使用sha1加密。如果加密后的字符串与signature相同,则返回echostr。微信服务器在收到echostr后,表示该开发服务器已经接入了微信服务器。

    @RestController
    @RequestMapping("/auth/wechat")
    public class WeChatMakeController {
    
        @GetMapping("/mkserver")
        public String makeServer(String signature,
                                 String timestamp,
                                 String nonce,
                                 String echostr){
            return echostr;
        }
    }
    

    这里为了方面,我直接返回了echostr。

    获取access_token

    调用各微信接口时都需使用access_token,access_token的有效期目前为2个小时,需定时刷新,每天只能刷新2000次,接口为GET https://api.weixin.qq.com/cgi-bin/token?grant_type=client_credential&appid=APPID&secret=APPSECRET。一般的处理方式是,将access_token存储在内存的某一个地方(实例或redis中)统一管理。向外提供获取access_token的方法,方法内部需要考虑token过期与多线程的情况。参考me.chanjar.weixin.mp.api.impl.WxMpServiceHttpClientImpl#getAccessToken

    public String getAccessToken(boolean forceRefresh) throws WxErrorException {
        // 微信配置存储器
        final WxMpConfigStorage config = this.getWxMpConfigStorage();
        // 是否获取 或 强制刷新
        if (!config.isAccessTokenExpired() && !forceRefresh) {
          // 未过期直接返回数据
          return config.getAccessToken();
        }
    
        // 多线程情况
        Lock lock = config.getAccessTokenLock();
        lock.lock();
        try {
          if (!config.isAccessTokenExpired() && !forceRefresh) {
            return config.getAccessToken();
          }
          // 调用微信接口获取access_token
          // 更新存储器中的token
          // 返回token
         
        } finally {
          lock.unlock();
        }
    }
    

    配置菜单

    公众号下的菜单栏最多包括3个一级菜单,每个一级菜单最多包含5个二级菜单。菜单有多种类型

    • click 点击事件
    • view 跳转url
    • miniprogram 跳转到小程序
    • scancode_push 扫码推事件
    • scancode_waitmsg 扫码推事件且弹出“消息接收中”提示框.
    • pic_sysphoto 弹出系统拍照发图
    • pic_photo_or_album 弹出拍照或者相册发图
    • pic_weixin 弹出微信相册发图器
    • location_select 弹出地理位置选择器
    • location_select 弹出地理位置选择器
    • media_id 下发消息(除文本消息)
    • view_limited 跳转图文消息URL

    其中最常用的是click、view和miniprogram。不同的菜单类型需要加的不同的参数,比如,view类型的菜单是跳转url的,所以,我们需要附加url项。而click类型的菜单,我们需要附加一个key,以标识该菜单。

     {
         // button代表的是菜单栏,是一个数组,里面的元素表示菜单
         "button":[
           // click类型的菜单,使用key标识该菜单,方便后台处理对应的业务
           {    
                "type":"click",
                "name":"今日歌曲",
                "key":"V1001_TODAY_MUSIC"
            },
           // view类型的菜单,url表示要跳转的地址
            {   
               "type":"view",
               "name":"搜索",
               "url":"http://www.soso.com/"
            },
           // 使用子菜单,sub_button是一个数组,里面的元素是其子菜单
            {
              "name":"其他",
              "sub_button": []
            }
         ]
     }
    

    生成菜单时,需要向以下地址发送post请求

    https://api.weixin.qq.com/cgi-bin/menu/create?access_token=ACCESS_TOKEN
    

    获取用户信息

    公众号获取用户信息有两种方式,通过openid获取以及通过OAuth2获取。

    通过OpenID获取用户信息

    当用户关注公众号后,微信服务器会为该用户对于公众号产生一个openid,这个openid是唯一的,同一个用户在不同的公众号中openid是不同的。后台可根据该openid来获取用户信息。

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

    access_token是我们上面章节介绍获取的。openid是微信服务器向后台配置的URL发送的请求参数,比如,当用户关注了公众号,微信服务器会调用后台的url地址,其中FromUserName就是该用户的OpenID。

    通过OAuth2获取用户信息

    1 订阅号不能使用该接口,服务号需要认证后才能使用该接口

    2 必须使用微信内置浏览器

    关于OAuth2.0 授权可以参考阮一峰的理解OAuth 2.0,因为这里采用的是OAuth2.0的授权码模式,所以这里简要的说一下使用授权码模式的步骤。

    1. 获取授权码(code)
    2. 使用code换access_token
    3. 获取用户信息

    获取授权码

    获取授权码的地址如下:

    https://open.weixin.qq.com/connect/oauth2/authorize?appid=APPID
    &redirect_uri=REDIRECT_URI
    &response_type=code
    &scope=SCOPE
    &state=STATE#wechat_redirect
    
    • appid为公众号的appid

    • redirect_uri 为微信授权后的回调页,该回调页的域名部分需要在公众号的后台设置(接口权限/网页授权)

      注意:在公众号后台设置的回调地址时,填写的是域名,而不是URL,因此请勿加 http:// 等协议头。

    • response_type 授权类型,这里填固定值code,因为微信采用的是OAuth2.0的授权码模式

    • scope 授权的作用域,有两种取值

      snsapi_base snsapi_userinfo
      用户信息 用户的OpenID 用户基本信息(昵称、头像等)
      感知度 用户无感知,直接进入回调页 1 用户未关注公众号,弹出授权页面,用户手动授权<br />2 用户已关注公众号,且通过点击公众号的菜单进入,无需授权页,即无感知

      由上可以看出,用户即使未关注公众号(已认证的服务号),也可以获取用户信息。

    • state 表示客户端的状态,微信服务器会原封不动的返回该值

    获取access_token

    注意这里的网页授权access_token与前面所讲的access_token是不同的,这里的access_token只适合在OAuth2.0授权流程中使用。

    通过第一步后,微信服务器会调用回调也的地址,并附带code和state两个参数

    redirect_uri/?code=CODE&state=STATE。
    

    回调页使用这个code从微信服务器上获取access_token。这一步是后台服务器和微信服务器做交互,可以认为是安全的通信。

    https://api.weixin.qq.com/sns/oauth2/access_token?appid=APPID
    &secret=SECRET
    &code=CODE
    &grant_type=authorization_code
    
    • appid 公众号的appid
    • secret 公众号的appsecret
    • code 第一步获取的code
    • grant_type 授权类型,授权码模式,所以这里是固定值authorization_code

    返回如下信息

    {
      "access_token":"访问token",
      "expires_in":7200,
      "refresh_token":"刷新token",
      "openid":"OPENID",
      "scope":"SCOPE" 
    }
    

    当用户未关注公众号时,访问公众号的网页,也会产生OpenID,且这个OpenID与关注后的OpenID相同。

    获取用户信息

    使用以下地址获取用户信息

    https://api.weixin.qq.com/sns/userinfo?
    access_token=ACCESS_TOKEN
    &openid=OPENID
    &lang=zh_CN
    
    • access_token 访问令牌,上一步得到
    • openid 用户的唯一标识,上一步得到

    返回的用户信息

    {   
      "openid":" OPENID",
      "nickname": "NICKNAME",
      "sex":"1男,2女,0未知",
      "province":"PROVINCE",
      "city":"CITY",
      "country":"COUNTRY",
      "headimgurl": "headimgurl",
      "privilege":[ "PRIVILEGE1" "PRIVILEGE2"     ],
      "unionid": "o6_bmasdasdsad6_2sgVt7hMZOPfL"
    }
    

    前后端分离获取用户信息

    先后端分离时,微信登录的解决办法:

    • 前端请求微信的code
    • 收到code后,将code发送给后端
    • 后端通过code换取access-token
    • 通过access-token,获取当前登录的用户信息,返回给前端

    相关文章

      网友评论

          本文标题:微信开发

          本文链接:https://www.haomeiwen.com/subject/xtjyuhtx.html