小程序微信授权获取用户信息

福兮祸所伏,祸兮福所倚

关于微信授权这块都有固定的几个步骤

  1. 首先调用官方API获取登录凭证code
  2. 通过code去换取openId(openId就是当前用户针对于微信官方(某一环境 比如小程序  网页等  要和unionId区分开)的唯一)和session_key等信息
  3. 通过 openId去获取用户基本信息或者私密信息

接下来我们就来完成第一步(获取code):

  来看官方给的API解释和实例吧

调用接口获取登录凭证(code)。通过凭证进而换取用户登录态信息,包括用户的唯一标识(openid)及本次登录的会话密钥(session_key)等。用户数据的加解密通讯需要依赖会话密钥完成。更多使用方法详见 小程序登录

wx.login({
  success (res) {
    if (res.code) {
      //发起网络请求
    } else {
      console.log('登录失败!' + res.errMsg)
    }
  }
})

很简单吧   我们直接调用wx.login  微信服务器就会返回对应的code(会变化的, 有时间限制)到这里的话 咱们第一步就完成

已经可以拿到code     res.code就是咱们需要的。

接下来我们就来完成第二步(通过code会获取相对应的openId):

首先来理下思路: code我们已经获取到了  那上面在获取code之后  官方有行注释:(// 发起网络请求)这个是干嘛用的呢???

网络请求肯定是往服务器发    谁的服务器呢? 我们是针对微信来开发的  也就是和微信服务器来交互 那直接wx.request像微信发

送不就行了吗  但是:官方是不建议在小程序端发送这样的请求 ,所以我们就改变思路  用我们的服务端去和微信服务器去交互

那现在我们就差个请求地址对不对 稍等  马上奉上

auth.code2Session

本接口应在服务器端调用,详细说明参见服务端API

登录凭证校验。通过 wx.login 接口获得临时登录凭证 code 后传到开发者服务器调用此接口完成登录流程。更多使用方法详见 小程序登录

请求地址

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

 

好了, 目前的话  咱们的思路相当清晰 来上服务端的代码

@ApiOperation("获取微信登录凭证")
@ApiImplicitParam(name = "code", value = "编号", required = true, dataType = "String", paramType = "query")
@GetMapping("/app/weChat/session")
public JsonResult<WeChatSessionVO> getWeChatSession(@RequestParam String code,@RequestParam String appId) {
    log.debug("进入/app/weChat/session");
    WeChatSessionVO weChatSessionVO = this.userService.getWeChatSession(code, appId);
    return JsonResultTool.success(weChatSessionVO);
}

 其中getWeChatSession方法

@Override
    public WeChatSessionVO getWeChatSession(String code, String appId) {

        logger.debug("当前你的code是:" + code);
        logger.debug("当前你的请求appId是:" + appId);
        WeChatSessionVO sessionVo = new WeChatSessionVO();

        Map<String, Object> wxParams = new HashMap<>();
        JSONObject json = new JSONObject();
        // 判断是哪种类型的小程序 (头条是tt  微信vx)
        if (appId.startsWith("tt")) {
            // 当前appId为头条的appId
            wxParams = pickTtParams(code, appId);
            json = sendGetBackJson(weChatConfig.getTokenUrlTt(), wxParams, null);
        } else {
            wxParams = pickWxParams(code, true, appId);
            json = sendGetBackJson(weChatConfig.getTokenUrl(), wxParams, null);

            logger.debug("获取到的json数据信息:" + json.toJSONString());
            if (json.containsKey("unionid")) {
                sessionVo.setUnionId(json.getString("unionid"));
            }
        }
        if (json.containsKey("session_key")) {
            sessionVo.setSessionKey(json.getString("session_key"));
        }
        sessionVo = setOpendId(sessionVo, json);
        return sessionVo;
    }

 其中pickWxParams和sendGetBackJson

/**
     *
     * @param code
     * @param isJsCode  是否为小程序code
     * @return
     */
    public Map<String, Object> pickWxParams(String code, Boolean isJsCode, String appId) {
        Map<String, Object> params = new HashMap<>();
        // 如果是小程序的话
        params = pickWxAppIdSecret(isJsCode, params, appId);
        params.put(isJsCode ? WxConstanst.JS_CODE_STR : WxConstanst.CODE_STR, code);
        params.put(WxConstanst.GRANT_TYPE_STR, WxConstanst.GRANT_TYPE_VALUE);
        return params;
    }
    private Map<String, Object> pickWxAppIdSecret(Boolean isJsCode, Map<String, Object> params, String appId) {
        if (isJsCode) {
            logger.debug("isJsCode==true");
            // 判断appId  确认是哪个小程序
            if (weChatConfig.getAppId().equals(appId)) {
                params.put(WxConstanst.APPID_STR, weChatConfig.getAppId());
                params.put(WxConstanst.SECRET_STR, weChatConfig.getAppSecret());
            } else if (weChatConfig.getAppIdSk().equals(appId)) {
                params.put(WxConstanst.APPID_STR, weChatConfig.getAppIdSk());
                params.put(WxConstanst.SECRET_STR, weChatConfig.getAppSecretSk());
            } else {
                params.put(WxConstanst.APPID_STR, weChatConfig.getAppIdAI());
                params.put(WxConstanst.SECRET_STR, weChatConfig.getAppSecretAI());
            }
        } else {
            params.put(WxConstanst.APPID_STR, WxConstanst.APPID);
            params.put(WxConstanst.SECRET_STR, WxConstanst.SECRET);
        }
        return params;
    }

/**
     * 发送get请求  返回json数据
     * @param url
     * @param wxParams
     * @param headers
     * @return
     */
    public JSONObject sendGetBackJson(String url, Map<String, Object> wxParams, Map<String,String> headers) {
        String result = HttpUtils.sendGet(url, wxParams, headers);
        JSONObject json = JSONObject.parseObject(result);
        return json;
    }

sendGet

/**
     * 发送get请求
     * @param urlParam url地址
     * @param params 参数
     * @return
     */
    public static String sendGet(String urlParam, Map<String, Object> params,Map<String,String> headers) {
        StringBuffer resultBuffer = null;
        // 构建请求参数
        StringBuffer sbParams = new StringBuffer();
        if (params != null && params.size() > 0) {
            for (Map.Entry<String, Object> entry : params.entrySet()) {
                sbParams.append(entry.getKey());
                sbParams.append("=");
                sbParams.append(entry.getValue());
                sbParams.append("&");
            }
        }
        HttpURLConnection con = null;
        BufferedReader br = null;
        try {
            URL url = null;
            if (sbParams != null && sbParams.length() > 0) {
                url = new URL(urlParam + "?" + sbParams.substring(0, sbParams.length() - 1));
            } else {
                url = new URL(urlParam);
            }
            con = (HttpURLConnection) url.openConnection();
            if(headers != null){
                Iterator entries = headers.entrySet().iterator();
                while (entries.hasNext()){
                    Map.Entry entry  = (Map.Entry) entries.next();
                    String key = (String)entry.getKey();
                    String value = (String)entry.getValue();
                    con.setRequestProperty(key,value);
                }
            }
            con.setRequestProperty("Content-Type", "application/x-www-form-urlencoded");
            con.connect();
            resultBuffer = new StringBuffer();
            br = new BufferedReader(new InputStreamReader(con.getInputStream(), "utf-8"));
            String temp;
            while ((temp = br.readLine()) != null) {
                resultBuffer.append(temp);
            }
        } catch (Exception e) {
            throw new RuntimeException(e);
        } finally {
            if (br != null) {
                try {
                    br.close();
                } catch (IOException e) {
                    br = null;
                    throw new RuntimeException(e);
                } finally {
                    if (con != null) {
                        con.disconnect();
                        con = null;
                    }
                }
            }
        }
        return resultBuffer.toString();
    }

setOpenId 

public WeChatSessionVO setOpendId(WeChatSessionVO sessionVo, JSONObject json) {
        if (json.containsKey(WxConstanst.OPENDID_STR)) {
            sessionVo.setOpenId(json.getString(WxConstanst.OPENDID_STR));
        }
        return sessionVo;
}

这样操作下来 我们服务端就拿到了openId和sessionkey

那接下来咱们来操作第3步

通过 openId去获取用户基本信息或者私密信息:

withCredentials如果为false的话  是获取到昵称等   为true的时候  可以获取到加密信息

在小程序端直接wx.getUserInfo  然后拿到签名和加密数据  咱们去服务端解密 获取详细信息  服务端代码来了

public void getUnionIDAndSaveUser(UserDTO userDTO) throws Exception{

        // 解密
        logger.debug("当前的userDTO.getEncryptedData():" + userDTO.getEncryptedData());
        logger.debug("当前的userDTO.getSessionKey():" + userDTO.getSessionKey());
        logger.debug("当前的userDTO.getIv():" + userDTO.getIv());
        String result = AesCbcUtil.decrypt(userDTO.getEncryptedData(), userDTO.getSessionKey(), userDTO.getIv(),"UTF-8");
        logger.debug("当前的result=====================================》》》》》》》:" + result);
        if (null != result && result.length() > 0) {
            JSONObject  jsonObject = JSONObject.parseObject(result);
            if (jsonObject.containsKey("unionId")) {
                logger.debug("MAP当前的unionId:" + jsonObject.get("unionId").toString());
                userDTO.setUnionId(jsonObject.get("unionId").toString());
            } else {
                logger.debug("当前的unionId:" + result);
                if (userDTO.getAppId() != null && userDTO.getAppId().startsWith(weChatConfig.getAppIdTt())) {

                } else {
                    throw new Exception("json字符串不包含unionId");
                }

            }
        } else {
            throw new Exception("获取unionId失败");
        }
        this.save(userDTO);
    }

decrypt方法

/**
     * AES解密
     *
     * @param data           //密文,被加密的数据
     * @param key            //秘钥
     * @param iv             //偏移量
     * @param encodingFormat //解密后的结果需要进行的编码
     * @return
     * @throws Exception
     */
    public static String decrypt(String data, String key, String iv, String encodingFormat) throws Exception {
//        initialize();

        //被加密的数据
        byte[] dataByte = Base64.decodeBase64(data);
        //加密秘钥
        byte[] keyByte = Base64.decodeBase64(key);
        //偏移量
        byte[] ivByte = Base64.decodeBase64(iv);


        try {
            Cipher cipher = Cipher.getInstance("AES/CBC/PKCS7Padding");

            SecretKeySpec spec = new SecretKeySpec(keyByte, "AES");

            AlgorithmParameters parameters = AlgorithmParameters.getInstance("AES");
            parameters.init(new IvParameterSpec(ivByte));

            cipher.init(Cipher.DECRYPT_MODE, spec, parameters);// 初始化

            byte[] resultByte = cipher.doFinal(dataByte);
            if (null != resultByte && resultByte.length > 0) {
                String result = new String(resultByte, encodingFormat);
                return result;
            }
            return null;
        } catch (NoSuchAlgorithmException e) {
            e.printStackTrace();
        } catch (NoSuchPaddingException e) {
            e.printStackTrace();
        } catch (InvalidParameterSpecException e) {
            e.printStackTrace();
        } catch (InvalidKeyException e) {
            e.printStackTrace();
        } catch (InvalidAlgorithmParameterException e) {
            e.printStackTrace();
        } catch (IllegalBlockSizeException e) {
            e.printStackTrace();
        } catch (BadPaddingException e) {
            e.printStackTrace();
        } catch (UnsupportedEncodingException e) {
            e.printStackTrace();
        }

        return null;
    }

最后直接调用自己的save方法  就可以保存数据了    对了   如果你昵称中出现了特殊的表情  我这里也处理了 直接转为base64存库   使用的时候  再转过来发给小程序端   微信授权的大体就是这样   思路可用于H5授权等  希望可以帮到你们   点波关注或者打赏下  老铁们

 

  • 1
    点赞
  • 4
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值