评论

微信小程序获取openid的两种方法

两种方法获取小程序用户openid,一种使用云开发,一种使用自己的后台。

第一种:使用云开发

这种比较简单,只需要开通云开发,创建云函数,调用云函数就可获得。

调用云函数 Promise Cloud.callFunction(Object object) 返回一个Promise对象,所以不用考虑异步问题。

callFunction说明 https://developers.weixin.qq.com/miniprogram/dev/wxcloud/reference-sdk-api/functions/Cloud.callFunction.html

具体代码如下:

我这里云函数名为helloCloud

// helloCloud-index.js 云函数入口函数
exports.main = async (event, context) => {
 let{ APPID,OPENID}=cloud.getWXContext()
  return {
    APPID,
    OPENID
  }

//------------------------------------------------------
//云函数调用
wx.cloud.callFunction({
  name:'helloCloud',
  data:{
    message:'helloCloud',
  }
}).then(res=>{
  console.log(res)//res就将appid和openid返回了
    //做一些后续操作,不用考虑代码的异步执行问题。
})

第二种:不使用云开发

这种方式就需要开发者有自己的后台了。

首先需要在微信小程序调用登录开放接口 wx.login() 获取用户登陆凭证code。

wx.login()接口说明 https://developers.weixin.qq.com/miniprogram/dev/api/open-api/login/wx.login.html


然后,向自己的服务器发送请求,并将code一起发送过去。

wx.login({
  success (res) {
    if (res.code) {
      //发起网络请求
      wx.request({
        url: '自己的服务器请求接口',
        data: {
          code: res.code
        }
      })
    } else {
      console.log('登录失败!' + res.errMsg)
    }
  }
})

接下来,在自己的服务端调用auth.code2Session接口,我这里是用Java后台。

auth.code2Session接口说明 https://developers.weixin.qq.com/miniprogram/dev/api-backend/open-api/login/auth.code2Session.html


 @RequestMapping("/testopenid")
    public String getUserInfo(@RequestParam(name = "code") String code) throws Exception {
        System.out.println("code" + code);
        String url = "https://api.weixin.qq.com/sns/jscode2session";
        url += "?appid=xxxxxxxxxxxxx";//自己的appid
        url += "&secret=xxxxxxxxxxxxxxxxxxx";//自己的appSecret
        url += "&js_code=" + code;
        url += "&grant_type=authorization_code";
        url += "&connect_redirect=1";
        String res = null;
        CloseableHttpClient httpClient = HttpClientBuilder.create().build();
        // DefaultHttpClient();
        HttpGet httpget = new HttpGet(url);    //GET方式
        CloseableHttpResponse response = null;
        // 配置信息
        RequestConfig requestConfig = RequestConfig.custom()          // 设置连接超时时间(单位毫秒)
                .setConnectTimeout(5000)                    // 设置请求超时时间(单位毫秒)
                .setConnectionRequestTimeout(5000)             // socket读写超时时间(单位毫秒)
                .setSocketTimeout(5000)                    // 设置是否允许重定向(默认为true)
                .setRedirectsEnabled(false).build();           // 将上面的配置信息 运用到这个Get请求里
        httpget.setConfig(requestConfig);                         // 由客户端执行(发送)Get请求
        response = httpClient.execute(httpget);                   // 从响应模型中获取响应实体
        HttpEntity responseEntity = response.getEntity();
        System.out.println("响应状态为:" + response.getStatusLine());
        if (responseEntity != null) {
            res = EntityUtils.toString(responseEntity);
            System.out.println("响应内容长度为:" + responseEntity.getContentLength());
            System.out.println("响应内容为:" + res);
        }
        // 释放资源
        if (httpClient != null) {
            httpClient.close();
        }
        if (response != null) {
            response.close();
        }
        JSONObject jo = JSON.parseObject(res);
        String openid = jo.getString("openid");
        System.out.println("openid" + openid);
        return openid;
    }

部分参考 https://blog.csdn.net/qq_42940875/article/details/82706638?depth_1-utm_source=distribute.pc_relevant.none-task&utm_source=distribute.pc_relevant.none-task

这样就获得openid了。

但是在实际应用场景中,往往需要在界面展示之前获得openid来做一些操作或者什么。

用以上代码会发现,openid后台虽然获取到了,但是小程序端页面刚展示时好像并没有获取到openid,但是之后查看数据能看到openid。

这是因为wx.request()是异步请求。也就是在请求的过程中,小程序的其他工作没有因为请求而停止。

所以,我们需要将请求封装成一个返回Promise对象的函数。

廖雪峰老师讲的Promise使用 https://www.liaoxuefeng.com/wiki/1022910821149312/1023024413276544


这样就能在请求完做一些后续操作。

代码如下:

//封装wx.request() 
function request(requestMapping, data, requestWay, contentType) {
  wx.showLoading({
    title: '请稍后',
  })
  return new Promise(function(resolve, reject) {
    console.log('请求中。。。。。')
    wx.request({
      url: '自己的服务器地址' + requestMapping,
      data: data,
      header: {
        'content-type': contentType // 默认值
      },
      timeout: 3000,
      method: requestWay,
      success(res) {
        //console.log(res)
        if (res.data.success == false || res.data.statusCode == 404) {
          reject(res)
        } else {
          resolve(res)
        }
      },
      fail: (e) => {  
        wx.showToast({
          title: '连接失败',
          icon: 'none'
        })},
      complete: () => {
        wx.hideLoading()
      }
    })
  })
}

//获取openid
function getOpenId(app, that){
  return new Promise(function (resolve, reject) {
        wx.login({
          success: function (yes) {
            // 发送 res.code 到后台换取 openId, sessionKey, unionId
            var requestMapping = '/testopenid'
            var data = {
              code: yes.code
            }
            var requestWay = 'GET'
            var contentType = 'application/json'
            var p =request(requestMapping, data, requestWay, contentType)
            p.then(res => {
              //console.log(res) 做一些后续操作
              app.globalData.openId = res.data;
                    resolve(res)
            }).catch(e => {
              reject(e)  
            })
          },
          fail(e) {
            console.log(e)
          }
        })  
  })
}


这样就解决了因为异步获取不到数据的问题。

技术有限,欢迎交流。

觉得有用请点个赞。

最后一次编辑于  2020-12-05  
点赞 27
收藏
评论

10 个评论

  • 古新华
    古新华
    03-26

    创作不易,先点赞,再看文章,

    03-26
    赞同 1
    回复
  • 长风
    长风
    04-08

    好棒!java代码复制就能用

    04-08
    赞同 1
    回复 1
    • Pt.
      Pt.
      04-11
      有用就好,谢谢支持
      04-11
      1
      回复
  • 华仔
    华仔
    11-11

    本人是后端开发,请教一下如果封装wx.request() 后是不是所有的请求都变成同步了?

    11-11
    赞同
    回复 1
    • Pt.
      Pt.
      11-13
      你好,封装的wx.request()返回了一个promise对象,后续操作在then()里面写就能保持同步
      11-13
      回复
  • 外星飞碟
    外星飞碟
    07-13

    如何收藏这篇文章

    07-13
    赞同
    回复 1
    • Pt.
      Pt.
      07-14
      文章末尾有个收藏点一下就可以收藏了
      07-14
      回复
  • 张大胖
    张大胖
    05-07

    帮了大忙 ,点赞收藏评论,三连走起

    05-07
    赞同
    回复 1
    • Pt.
      Pt.
      05-10
      谢谢支持
      05-10
      回复
  • 超神的小石
    超神的小石
    04-22

    我想问下,我用自己的小程序登录微信开发者工具,然后调用后台接口,获取code,我后台用别人的appid和appsecret,怎么在小程序这边不能获取openid呢

    04-22
    赞同
    回复 1
    • Pt.
      Pt.
      04-25
      不可以用别人的appid和secret,只能用当前小程序账号主体的
      04-25
      回复
  • 🦁
    🦁
    04-08

    你好,用云开发的res返回没有_openid,请问是为啥


    04-08
    赞同
    回复 1
    • Pt.
      Pt.
      04-11
      你好,配置云环境并创建对应云函数了吗,截图发一下res
      04-11
      回复
  • 我迷路啦
    我迷路啦
    04-02

    想问下接口是不是改了呀,突然获取不了了

    04-02
    赞同
    回复 1
    • Pt.
      Pt.
      发表于小程序端
      04-02

      哪一个接口

      04-02
      回复
  • d金辉
    d金辉
    03-31
    https://api.weixin.qq.com/sns/jscode2session 这个地址直接用wx.request在前端请求不行吗?一定的在后台转一下吗?
    


    03-31
    赞同
    回复 1
    • Pt.
      Pt.
      04-01
      开发时前端可以请求,但是这样不安全,小程序上线审核时不会通过。
      04-01
      回复
  • 古新华
    古新华
    03-26

    有没有php后台的,java看不懂

    03-26
    赞同
    回复 1
登录 后发表内容