微信小程序获取openid的两种方法
发布于 4 年前 作者 na84 2269 次浏览 来自 分享

第一种:使用云开发

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

调用云函数 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](/user/RequestMapping)("/testopenid")
    public String getUserInfo([@RequestParam](/user/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)
          }
        })  
  })
}

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

技术有限,欢迎交流。

觉得有用请点个赞。

参考请加本文引用 :> URL --by Pt.

回到顶部