微信小程序登录后端开发流程(附go后端实现代码)

2019-11-02  本文已影响0人  Medlen

参考:
微信官方文档 * 小程序登录流程
微信官方文档 * 小程序

本文参考以上文档, 加上自己理解整合写出.

登录流程

  1. 前端调用wx.login() 获取 临时登录凭证code ,并回传到开发者服务器。
  2. 后端调用 auth.code2Session 接口,换取 用户唯一标识OpenID会话密钥 session_key
  3. 开发者服务器可以根据用户标识来生成自定义登录态,用于后续业务逻辑中前后端交互时识别用户身份。
    在这里插入图片描述
    上图就是小程序登录的基本流程.

作为一个后端开发人员, 看完上述描述后, 内心是这样的:


image

嗯, 道理我都懂, 代码怎么写?

接下来我们用go实现这个流程:

首先code是前端获取传到后端的, 我们不用管, 只要在HTTP请求种拿到这个参数即可.
ok, 第一步的code已经拿到.

然后第二步, 利用code获取openIDsession_key, 这里我们看微信官方文档给的接口:

https://api.weixin.qq.com/sns/jscode2session?appid=APPID&secret=SECRET&js_code=JSCODE&grant_type=authorization_code

在这里插入图片描述
在这里插入图片描述
在这里插入图片描述
到这里有接口. 有返回值, 我们就可以通过HTTP请求获取openIDsession_key了.

现在开始写代码实现, 我使用的是go语言, 其实道理都是一样的.

定义返回值数据结构:

type WXLoginResp struct {
    OpenId string           `json:"openid"`
    SessionKey string       `json:"session_key"`
    UnionId string          `json:"unionid"`
    ErrCode int             `json:"errcode"`
    ErrMsg string           `json:"errmsg"`
}

定义实现函数:

// 这个函数以 code 作为输入, 返回调用微信接口得到的对象指针和异常情况
func WXLogin(code string) (*WXLoginResp, error) {
    url := "https://api.weixin.qq.com/sns/jscode2session?appid=%s&secret=%s&js_code=%s&grant_type=authorization_code"
    
    // 合成url, 这里的appId和secret是在微信公众平台上获取的
    url = fmt.Sprintf(url, appId, secret, code)  

    // 创建http get请求
    resp,err := http.Get(url)
    if err != nil {
        return nil, err
    }
    defer resp.Body.Close()

    // 解析http请求中body 数据到我们定义的结构体中
    wxResp := WXLoginResp{}
    decoder := json.NewDecoder(resp.Body)
    if err := decoder.Decode(&wxResp); err != nil {
        return nil, err
    }
        
    // 判断微信接口返回的是否是一个异常情况
    if wxResp.ErrCode != 0 {
        return nil, errors.New(fmt.Sprintf("ErrCode:%s  ErrMsg:%s", wxResp.ErrCode, wxResp.ErrMsg))
    }

    return &wxResp, nil
}

ok, 到这里, 我们已经获得了openidsession_key .

接下来实现第三步, 这一步比较灵活, 根据自己的需求生成自定义登录态, 并返回前端;

这里我们用gin框架实现一个路由接口, 将上面的内容串联起来, 形成一个完整的流程;下面的代码仅供参考

// /wechat/applet_login?code=xxx [get]  路由
// 微信小程序登录
func AppletWeChatLogin(c *gin.Context) {
    code := c.Query("code")     //  获取code
    // 根据code获取 openID 和 session_key
    wxLoginResp,err := models.WXLogin(code)
    if err != nil {
        c.JSON(400, util.Fail(err.Error()))
        return
    }
    // 保存登录态
    session := sessions.Default(c)
    session.Set("openid", wxLoginResp.OpenId)
    session.Set("sessionKey", wxLoginResp.SessionKey )
    
    // 这里用openid和sessionkey的串接 进行MD5之后作为该用户的自定义登录态
    mySession := GetMD5Encode(wxLoginResp.OpenId + wxLoginResp.SessionKey)
    // 接下来可以将openid 和 sessionkey, mySession 存储到数据库中, 
    // 但这里要保证mySession 唯一, 以便于用mySession去索引openid 和sessionkey
    c.String(200, mySession)
    
}
// 将一个字符串进行MD5加密后返回加密后的字符串
func GetMD5Encode(data string) string {
    h := md5.New()
    h.Write([]byte(data))
    return hex.EncodeToString(h.Sum(nil))
}

可能代码部分不太能看懂, 这里再用文字解释一下:

  1. 获取路由中的code 参数
  2. 利用code调用我们之前写好的函数获取openidsession_key
  3. 利用得到的 openidsession_key 生成我们自定义的登录态(这里方式有很多, 保证生成的值全局唯一即可, 这里我们简单化了, 直接利用openidsession_key进行MD5加密, 将得到的字符串作为我们的登录态(这里登录态理解为索引即可, 本质是一个字符串))
  4. 最后将我们定义的登录态以及openidsession_key存储到数据库中, 并且保证能用自定义的登录态唯一查询到该用户的openidsession_key. 以便我们后期用到的时候可以查询到.

到这里微信小程序登录已经基本完成了.

这里, 微信官方还提供了一个校验接口, 用于校验小程序端获取的用户信息是否完整,这个也是我们之前获得的session_key的意义,

这里可以参考: 微信官方文档 * 后台校验与解密数据

我们也给出校验代码, 非常简单:
实际上就是将前端提供的微信原始数据和我们之前获取的session_key进行MD5加密, 得到signature2, 与微信加密的结果进行比较, 相同即为没有改变, 不同即是原始数据发生了改变.

// 校验微信返回的用户数据
func ValidateUserInfo(rawData, sessionKey, signature string) bool {
    signature2 := GetSha1(rawData + sessionKey)
    return signature == signature2
}
// SHA-1 加密
func GetSha1(str string) string {
    data := []byte(str)
    has := sha1.Sum(data)
    res := fmt.Sprintf("%x", has) //将[]byte转成16进制
    return res
}

以上就是微信小程序登录, 后台涉及到的所有操作.

上一篇 下一篇

猜你喜欢

热点阅读