记录一下go语言微信小程序登录

我这边主要是已有账号跟微信账号去进行绑定的一个流程
思路:
1、小程序通过code调用接口获取token。
2、如果是第一次登录,那么通过入参已有账号、密码、code,通过第三方接口得到OpenId进行绑定并且返回token。

  • golang端
//小程序登录传入的数据
type ConfirmLoginDto struct {
	Iv        string `json:"iv"`
	WxCode    string `json:"wx_code"`
	Token     string `json:"token"`    //账号登录认证
	Nickname  string `json:"nickname"`  //微信昵称
	Headimage string `json:"headimage"` //微信头像
	User      string `json:"user"`      //账号
	Passwd    string `json:"passwd"`    //密码
}
//账号信息
type User struct {
    这里自己去写
}
/*微信小程序登录 返回值*/
type WXLoginResp struct {
	OpenId     string `json:"openid"`
	SessionKey string `json:"session_key"`
	UnionId    string `json:"unionid"`
	ErrCode    int    `json:"errcode"`
	ErrMsg     string `json:"errmsg"`
	Token      string `json:"token"`
	Auth       uint32 `json:"auth"`
	Name       string `json:"name"`
	Phone      string `json:"phone"`
	Nickname   string `json:"nickname"`  //微信昵称
	Headimage  string `json:"headimage"` //微信头像
}

func wxLoginHandler(ctx iris.Context) {
	var user ConfirmLoginDto
	var err error
	// user.Token = ctx.GetHeader("token")
	if err = ctx.ReadJSON(&user); err != nil {
		ctx.StatusCode(iris.StatusBadRequest)
	} else if user.WxCode == "" {
		err = errors.New("code值不能为空")
	}
	if err != nil {
		ctx.JSON(iris.Map{"result_code": 500, "result_msg": err.Error()})
		return
	}
	users, err := wxLogin(&user)
	if err == nil {
		ctx.JSON(iris.Map{"result_code": 200, "result_msg": "success", "data": users})
	} else {
		ctx.JSON(iris.Map{"result_code": 500, "result_msg": err.Error()})
	}
}

/*根据wx_code返回token ...*/
func wxLogin(user *ConfirmLoginDto) (*WXLoginResp, error) {
	session := GetConnection()
	defer session.Close()
	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", user.WxCode)
	// 创建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))
	}
	var userInfo User
    session, err := mgo.Dial("mongodb://账号:密码@ip:端口/名称") //要连接的服务器和端口
    if err != nil {
	 	panic(err)
    }
	c := session.DB("名称").C("user_info")
	err = c.Find(bson.M{"open_id": wxResp.OpenId}).One(&userInfo)
	if user.User != "" && user.Passwd != "" { //账号绑定微信,更新
		err := c.Find(bson.M{"user": user.User}).One(&userInfo)
		if err != nil {
			return nil, errors.New("该账号不存在")
		} else if userInfo.Passwd != user.Passwd {
			return nil, errors.New("密码错误")
		} else {
			userInfo.Open_id = wxResp.OpenId
			userInfo.Nickname = user.Nickname
			userInfo.Headimage = user.Headimage
			c.Update(bson.M{"token": userInfo.Token}, userInfo)
		}
	} else if err != nil {
		return nil, errors.New("请先登录")
	}
	wxResp.Auth = userInfo.Auth
	wxResp.Token = userInfo.Token
	wxResp.Name = userInfo.Name
	wxResp.Phone = userInfo.Phone
	wxResp.Nickname = userInfo.Nickname
	wxResp.Headimage = userInfo.Headimage
	wxResp.OpenId = ""
	wxResp.SessionKey = ""

	return &wxResp, nil
}
  • 小程序

config.js 用来存放公共数据

var config = {
  token:"",
  name:"",//账号昵称
  auth:null,//账号权限 0:管理员  1:打工人
  userInfo:null,//微信账号信息
}

module.exports = config;

app.js

// 登录
	var http = require('./utils/request.js'); 
	var config = require('./config');
    wx.login({
      success: res => {
        // console.log('登陆login',res)
        // 发送 res.code 到后台换取 openId, sessionKey, unionId
          var params = {//请求参数
            wx_code: res.code,//用户登录凭证(有效期五分钟)
          }
          http.postRequest("user/wxlogin", params, res => {
            console.log("code登录接口");
            if(res.result_msg== "请先登录"){//第一次进入小程序,那么我们去登录页
                // wx.reLaunch({
                //   url: '../../login/login'
                // })
                var pages = getCurrentPages() //获取加载的页面
                var currentPage = pages[pages.length-1] //获取当前页面的对象
                var url = currentPage.route //当前页面url   
                var skipUrl = ""
                for(let I = 1; I < url.split("/").length-1; I++){
                  skipUrl = skipUrl + '../'
                }
                wx.reLaunch({
                  url: skipUrl+'login/login'
                })
              }else{
              	//存起来
                config.name = res.data.name
                config.auth = res.data.auth
                config.token = res.data.token
                config.userInfo = {
                  nickname:res.data.nickname,
                  headimage:res.data.headimage
                }
              }
            console.log(res,config);
          }, res => {
            console.log("请求失败了傻瓜")
          })
      }
    })

pages/login/login.js

var http = require('../../utils/request.js'); 
var config = require('../../config');
Page({
	data() {
      return {
        username: '',
        password: '',
      };
    },
    onChange1(event) {
      // event.detail 为当前输入的值
      console.log(event.detail);
      this.setData({ username: event.detail })
    },
    onChange2(event) {
      // event.detail 为当前输入的值
      console.log(event.detail);
      this.setData({ password: event.detail })
    },
    login(){
      if(config.userInfo){
        this.postLogin()
      }else{
        wx.getUserProfile({
          desc: '用于完善会员资料', // 声明获取用户个人信息后的用途,后续会展示在弹窗中,请谨慎填写
          success: (res) => {
            console.log(res.userInfo)
            let userInfo = res.userInfo
            config.userInfo = userInfo
            this.postLogin()
          }
        })
      }
    },
    postLogin(){
      wx.login({
        success: res => {
          // console.log('登陆login',res)
          // 发送 res.code 到后台换取 openId, sessionKey, unionId
            var params = {//请求参数
              wx_code: res.code,//用户登录凭证(有效期五分钟)
              user:this.data.username,
              passwd:this.data.password,
              nickname:config.userInfo.nickName,
              headimage:config.userInfo.avatarUrl
            }
            http.postRequest("user/wxlogin", params, res => {
              console.log("登录接口");
              console.log(res);
              if(res.result_code == 200){
                config.name = res.data.name
                config.auth = res.data.auth
                config.token = res.data.token
                wx.reLaunch({
                  url: '../indexs/my'
                })
              }
            }, res => {
              console.log("请求登录失败了")
            })
        }
      })
    },
})




//附带一下login.wxml
  <van-field
    value="{{ username }}"
    placeholder="请输入用户名"
    border="{{ false }}"
    bind:change="onChange1"
  />
  <van-field
    value="{{ password }}"
    placeholder="请输入密码"
    border="{{ false }}"
    bind:change="onChange2"
  />
  <van-button type="primary" bindtap="login">登录</van-button>

utils/request.js

var app = getApp(); //获取小程序全局唯一app实例
var config = require('../config');

// 非开发环境的服务器域名
let host = 'http://xiaohongdechuanr.com:8001/'; //接口地址
// platform 用来判断是否是开发环境
const {platform} = wx.getSystemInfoSync()
// 开发环境的服务器域名
if(platform === 'devtools'){
  host = 'http://190.161.8.9:8001/';//小红的本地
}
//url:接口
//postData:参数
//doSuccess:成功的回调函数
//doFail:失败的回调函数
 
//POST请求
function post(url, postData, doSuccess, doFail) {
  request(url, postData, "POST", doSuccess, doFail);
}
 
//GET请求
function get(url, postData, doSuccess, doFail) {
  request(url, postData, "GET", doSuccess, doFail);
}
 
function request(url, postData, method, doSuccess, doFail) {
  wx.showLoading({
    title: "正在加载中...",
  })
  wx.request({
    url: host + url, //请求地址
    method: method, //请求方法
    header: { //请求头
      "Content-Type": "application/json;charset=UTF-8",
      "token":config.token
    },
    data: postData, //请求参数    
    dataType: 'json', //返回数据格式
    responseType: 'text', //响应的数据类型
    success: function(res) {
      // console.log(res)
      wx.hideLoading();
      if(res.data.result_code == 200){
        //成功执行方法,参数值为res.data,直接将返回的数据传入
        doSuccess(res.data);
      }else{
        wx.showToast({
          title: res.data.result_msg,
          icon:'error'
        })
        doSuccess(res.data);
      }
    },
    fail: function() {
      wx.hideLoading();
      //失败执行方法
      doFail();
    },
  })
}
//module.exports用来导出代码
//js文件中通过var http = require("../../util/request.js")加载
module.exports = {
  postRequest: post,
  getRequest: get,
}


// 使用实例
// var http = require('../../utils/request.js'); //相对路径
// var params = {//请求参数
//   aid: this.optionaid, //id
//   aname: this.data.receiving, //收货人
//   atell: this.data.tell, //联系方式
//   adetailed: this.data.detailed, //详细地址
// }
// http.postRequest("EditAddress/EditAddressInfo", params, function(res) {
//   console.log("修改成功!");
//   wx.navigateTo({
//     url: '/pages/address/address',
//   })
// }, function(res) {
//   console.log("修改失败!!!")
// })