微信小程序——获取用户信息

   微信小程序基于微信进行开发,而微信又存有用户信息,我们是否可以直接通过微信端获取用户信息,则无需用户进行再次输入个人信息。

   微信小程序可以通过wx.getUserInfo()接口来获取部分用户信息,我们可以参考微信文档之wx.getUserInfo()。

   但是通过该接口能获取的数据只有:

// 必须是在用户已经授权的情况下调用
wx.getUserInfo({
  success(res) {
    const userInfo = res.userInfo  //整体user对象
    const nickName = userInfo.nickName  //用户昵称
    const avatarUrl = userInfo.avatarUrl   //用户头像
    const gender = userInfo.gender // 性别 0:未知、1:男、2:女
    const province = userInfo.province  //用户国家  
    const city = userInfo.city       //用户所在城市
    const country = userInfo.country   
  }
})

  但是如果我们要获取用户在该程序的唯一性标志openid,又或者用户在所有微信小程序的唯一性标志unionid,则无法直接通过该接口获取。另外,wx.getUserInfo()接口经过改版,无法一登录就会弹窗让用户授权,现在要通过编程设置按钮引导用户点击获取用户信息,这样子的改版被很多程序猿吐槽,我们也看看官方说明。

  在解决新版本带来的问题之前,我们先来说一下除了这些基本用户信息以外,openid和unionid也是很多微信小程序所要获得存储的,先来说明一下两个id的含义:

   (1) openid:一个用户在一个微信小程序下都有唯一标志,这个标志是证明该用户在该小程序的唯一性存在的标志。小程序可以通过获取openid来确定该用户在小程序中的身份

   (2)unionid:微信下不同产品(如公众号和小程序),用户在不同产品下都有着唯一性的标志unionid,我们可以通过该标志确定用户在不同产品下唯一身份,这样就打通所有的小程序和公众号的账号系统。小程序可以通过获取unionid来绑定自身公众号,而用户要支付等操作时也需要有unionid的证明。

 

   获取用户普通信息(就是昵称这类)虽然受到改版影响,但是实际上获取困难性并无增加多少,只需要通过设置按钮通过点击按钮事件触发wx.getUserInfo()j即可。而两个私密id才是这次获取困难性的来源。当然,在说明获取两个id的时候也会讲解一下获取用户普通信息。


   在说明获取用户openid和unionid之前,我们先说一下微信小程序在我们建立程序的时候给的标准模板,该模板里面就是设置有按钮和获取用户信息的代码,而且我们可以通过查看简书文章:微信小程序登陆个人信息授权app与page的执行顺序先了解一下该小程序模板运行的模式。但是该模板中没有说明如何获取openid和unionid,而且没有和数据库后端交互。

 

(重点关注下面内容)

   获取了用户的unionid的过程中自然要获取用户的openid,我们可以查看掘金:微信小程序之获取并解密用户数据(获取 openId、unionId),文章是17年编写的,当时版本还未改变,所以里面微信小程序的操作时不起作用的。但是在后端使用spring boot进行操作的过程是可以借鉴的。

  unionid的获取是要先通过wx.login()接口(可通过微信小程序文档查看)获取code,发送get请求到微信小程序后端获取openid和session_key,这时候就获得了openid了,但是unionid作为更为隐秘的信息,则这时候是还未获得的。这时候我们就要再通过wx.getUserInfo()获取encryptedData和iv(查看微信小程序文档),其中encryptedData封装了用户信息和unionid(查看微信小程序文档),但是使用了AES进行加密,这时候我们要将encryptedData和iv发送到后端进行AES解密出unionid进行存储即可。

   在掘金文章中并没有说明其中要导入了两个依赖,这里说明一下:

        
        
        
            org.bouncycastle
            bcprov-jdk15on
            1.61
        
         
        
            net.sf.json-lib
            json-lib
            2.4
            jdk15
        

  在掘金文章中是将wx.getUserInfo()封装在wx.login()中,而该方法是在小程序运行开始即进行,则在新版小程序是不一样的,我们应该先在app.js中先进行wx.login()获取code和openid发送到后台进行存储,   而在设置按钮的js文件中才进行wx.getUserInfo()获取encryptedData和iv进行解密获得unionid。

 

 

   由于我并不需要确定用户在不同小程序和公众号之间的唯一性,而我只需要确定用户在我程序中的唯一性,即只需要获得openid进行存储即可。所以我通过上面掘金文章解决方法说一下获取用户openid的过程:

  小程序中app.js中onLaunch()中进行设置:

onLaunch: function () {
    // 登录
    wx.login({
      success: function (r) {
        //获取code
        var code = r.code;
        //debugger;
        if (code) {
          //发送code到后台,分析openid
          wx.request({
            url: 'http://xxxxxx/login/regist?code=' + code,
            method: 'POST',
            header: {
              'content-type': 'application/json'
            },
            success: function (res) {
              //debugger;
              if (res.data.status == 0) {
                //status为空时登录凭证code为空
                wx.showToast({
                   title: '登录凭证code为空...',
                   icon: "none",
                   duration: 2500
                })
              } else if (res.data.status == 1) {
                //status为1时openid已存在
                this.globalData.userInfo=res.data.userInfo;
                console.log(userInfo);
              } else if (res.data.status == 2) {
                //status为2时openid不存在
                this.globalData.userInfo=res.data.userInfo;
                console.log(userInfo);
              }
            }
          })
        }
      }
    })
 }

 

  后端controller的编写:

import com.xie.video.entity.Users;
import com.xie.video.service.UsersService;
import com.xie.video.untils.HttpRequest;
import net.sf.json.JSONObject;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.web.bind.annotation.PostMapping;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RequestParam;
import org.springframework.web.bind.annotation.RestController;

import java.util.HashMap;
import java.util.Map;

@RestController
@RequestMapping("/login")
public class LoginController {

    @Autowired
    private UsersService usersService;

    @PostMapping("/regist")
    public Map gettingOpenID(@RequestParam("code") String code){
        Map map=new HashMap();
        //登录凭证不能为空
        if (code == null || code.length() == 0) {
            map.put("status", 0);
            map.put("msg", "code 不能为空");
            return map;
        }
        //小程序唯一标识   (在微信小程序管理后台获取)
        String wxspAppid = "xxxxx";
        //小程序的 app secret (在微信小程序管理后台获取)
        String wxspSecret = "xxxxx";
        //授权(必填)
        String grant_type = "authorization_code";

        //////////////// 1、向微信服务器 使用登录凭证 code 获取 session_key 和 openid ////////////////
        //请求参数
        String params = "appid=" + wxspAppid + "&secret=" + wxspSecret + "&js_code=" + code + "&grant_type=" + grant_type;
        //发送请求
        String sr = HttpRequest.sendGet("https://api.weixin.qq.com/sns/jscode2session", params);
        //解析相应内容(转换成json对象)
        JSONObject json = JSONObject.fromObject(sr);
        //用户的唯一标识(openid)
        String openid = (String) json.get("openid");

        //查询数据库中该openid是否存在
        if(usersService.queryOpenIdIsExist(openid)){
            //openid存在,则查找该user对象进行返回
            Users users=usersService.queryUserByOpenID(openid);
            //status为1,用户openid已存在
            map.put("status", 1);
            map.put("userInfo",users);
        }else{
            //openid不存在,则创建新user对象
            Users users=new Users();
            users.setOpenId(openid);
            users=usersService.saveUsers(users);
            //status为2,用户openid未存在
            map.put("status", 2);
            map.put("userInfo",users);
        }
        return map;
    }
}

注意导入JSONObject的依赖(上面有说)

 

   工具类HttpRequest(用于发送get或post请求)

import java.io.BufferedReader;
import java.io.IOException;
import java.io.InputStreamReader;
import java.io.PrintWriter;
import java.net.URL;
import java.net.URLConnection;
import java.util.List;
import java.util.Map;

public class HttpRequest {

    /**
     * 向指定URL发送GET方法的请求
     *
     * @param url
     *            发送请求的URL
     * @param param
     *            请求参数,请求参数应该是 name1=value1&name2=value2 的形式。
     * @return URL 所代表远程资源的响应结果
     */
    public static String sendGet(String url, String param) {
        String result = "";
        BufferedReader in = null;
        try {
            String urlNameString = url + "?" + param;
            URL realUrl = new URL(urlNameString);
            // 打开和URL之间的连接
            URLConnection connection = realUrl.openConnection();
            // 设置通用的请求属性
            connection.setRequestProperty("accept", "*/*");
            connection.setRequestProperty("connection", "Keep-Alive");
            connection.setRequestProperty("user-agent",
                    "Mozilla/4.0 (compatible; MSIE 6.0; Windows NT 5.1;SV1)");
            // 建立实际的连接
            connection.connect();
            // 获取所有响应头字段
            Map> map = connection.getHeaderFields();
            // 遍历所有的响应头字段
            for (String key : map.keySet()) {
                System.out.println(key + "--->" + map.get(key));
            }
            // 定义 BufferedReader输入流来读取URL的响应
            in = new BufferedReader(new InputStreamReader(
                    connection.getInputStream()));
            String line;
            while ((line = in.readLine()) != null) {
                result += line;
            }
        } catch (Exception e) {
            System.out.println("发送GET请求出现异常!" + e);
            e.printStackTrace();
        }
        // 使用finally块来关闭输入流
        finally {
            try {
                if (in != null) {
                    in.close();
                }
            } catch (Exception e2) {
                e2.printStackTrace();
            }
        }
        return result;
    }

    /**
     * 向指定 URL 发送POST方法的请求
     *
     * @param url
     *            发送请求的 URL
     * @param param
     *            请求参数,请求参数应该是 name1=value1&name2=value2 的形式。
     * @return 所代表远程资源的响应结果
     */
    public static String sendPost(String url, String param) {
        PrintWriter out = null;
        BufferedReader in = null;
        String result = "";
        try {
            URL realUrl = new URL(url);
            // 打开和URL之间的连接
            URLConnection conn = realUrl.openConnection();
            // 设置通用的请求属性
            conn.setRequestProperty("accept", "*/*");
            conn.setRequestProperty("connection", "Keep-Alive");
            conn.setRequestProperty("user-agent",
                    "Mozilla/4.0 (compatible; MSIE 6.0; Windows NT 5.1;SV1)");
            // 发送POST请求必须设置如下两行
            conn.setDoOutput(true);
            conn.setDoInput(true);
            // 获取URLConnection对象对应的输出流
            out = new PrintWriter(conn.getOutputStream());
            // 发送请求参数
            out.print(param);
            // flush输出流的缓冲
            out.flush();
            // 定义BufferedReader输入流来读取URL的响应
            in = new BufferedReader(
                    new InputStreamReader(conn.getInputStream()));
            String line;
            while ((line = in.readLine()) != null) {
                result += line;
            }
        } catch (Exception e) {
            System.out.println("发送 POST 请求出现异常!"+e);
            e.printStackTrace();
        }
        //使用finally块来关闭输出流、输入流
        finally{
            try{
                if(out!=null){
                    out.close();
                }
                if(in!=null){
                    in.close();
                }
            }
            catch(IOException ex){
                ex.printStackTrace();
            }
        }
        return result;
    }
}

  我们设置好数据库和持久层即可将数据存入数据库就完成了。

  

 

 

 

 

 

你可能感兴趣的:(学习笔记,openid,unionid,微信小程序)