微信小程序-getUserProfile示例与后台(已纠正)

前段时间,微信更改了授权方式,采用用户主动式授权,也就是可授权多次,并不像之前的取消就不弹了

下面代码效果:检测是否授权,未授权时出现授权按钮,已授权则直接显示用户信息,方式使用了缓存,有更好的方案请在评论区回复一下,(文中appid,appsecret均为测试小程序)

index.js

Page({
  data: {
    hasUserInfo: false,
    canIUseGetUserProfile: false,
  },

  onLoad() {
    /* 从缓存中取出去数据 */
    let userInfo = wx.getStorageSync('userInfo');
    let wxInfos = wx.getStorageSync('wxInfos');
    if (0 == Object.keys(userInfo).length) {
      this.setData({canIUseGetUserProfile: true})
      wx.login({success:(rs) => {wx.setStorageSync("code",rs.code); } });
    }else{
      this.setData({
        hasUserInfo:true,
        userInfo:userInfo,
        wxInfos:wxInfos
      })
    }
  },

  getUserProfile(e) {
    wx.getUserProfile({
      desc: '授权', 
      success: (wrs) => {
       var code = wx.getStorageSync("code")
        if(code){
          let dataJson = {
            appId: app.globalData.appId,
            code : code,
            iv : wrs.iv,
            encryptedData : wrs.encryptedData
          }
          /* 发起用户微信开放信息请求 */
          request.requestPost(true, app, '/xxx', dataJson, data =>{
            if(data.stateCode=="0"){
              var result = JSON.parse(data.result);
              _self.setData({
                hasUserInfo: true,
                userInfo:result,
                wxInfos:JSON.parse(result.wxInfos)
              })
              /* 使用缓存记录信息 */
              wx.setStorageSync('userInfo', result);
              wx.setStorageSync('wxInfos', JSON.parse(result.wxInfos));
            }else {
              console.log(data)
            }
          });
        }
      },fail:()=>{
        console.log("用户拒绝授权");
      }
    });
  }
})

 

 

index.wxml

<view class="container">
  <view class="userinfo">
    <block wx:if="{{!hasUserInfo}}">
      <button wx:if="{{canIUseGetUserProfile}}" bindtap="getUserProfile"> 获取头像昵称 </button>
    </block>
    <block wx:else>
      <image bindtap="bindViewTap" class="userinfo-avatar" src="{{wxInfos.avatarUrl}}" mode="cover"></image>
      <text class="userinfo-nickname">{{wxInfos.nickName}}</text>
      <text class="userinfo-nickname">openId=> {{userInfo.openid}}</text>
      <text class="userinfo-nickname">unionId=> {{userInfo.unionid}}</text>
    </block>
  </view>
</view>

后台:

GetWxInfoServlet.java

import org.apache.commons.lang.StringUtils;

import com.alibaba.fastjson.JSONObject;
import com.src.minback.utils.HttpRequest;
import com.src.minback.utils.WxAesUtil;

/**
 * 模拟获取微信用户信息及微信小程序版本信息
 * 
 * @author liuwl
 */
public class GetWxInfoServlet extends HttpServlet {

    private static final long serialVersionUID = 1L;

    static String wxspAppid = "wxfc5a797bc1295c71";
    static String wxspSecret = "47067172d687958df709f9396b83e3ed";
    static String grant_type = "authorization_code";

    @Override
    protected void doGet(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
        
        // 设置字符集
        req.setCharacterEncoding("UTF-8");
        resp.setCharacterEncoding("UTF-8");

        // 获取输出
        PrintWriter out = resp.getWriter();
        JSONObject jsonObj = new JSONObject();
        JSONObject result = new JSONObject();
        System.out.println("wx.login 返回的code:" + req.getParameter("code"));
        String code = req.getParameter("code");
        // 登录凭证不能为空
        if (code != null && code.length() > 0) {
            // 请求参数
            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.parseObject(sr);
            // 获取会话密钥(session_key)
            String session_key = json.get("session_key").toString();
            System.out.println("session_key:" + session_key);
            // 用户的唯一标识(openid)
            String openid = (String) json.get("openid");
            System.out.println("openid:" + openid);
            result.put("openid", openid);
            // 开放平台的唯一标识符(unionid)
            String unionid = (String) json.get("unionid");
            System.out.println("unionid:" + unionid);
            result.put("unionid", unionid);
            if (StringUtils.isNotEmpty(openid)) {
                jsonObj.put("stateCode", "0");
                jsonObj.put("stateDesc", "操作成功");
                // 解密encryptedData
                try {
                    String encryptedData = req.getParameter("encryptedData");
                    String iv = req.getParameter("iv");
                    System.out.println("iv:" + iv);
                    System.out.println("encryptedData:" + encryptedData);
                    JSONObject decryptData = WxAesUtil.decrypt(encryptedData, session_key, iv, "UTF-8");
                    System.out.println("-->" + decryptData);
                    if (decryptData!=null) {
                        result.put("wxInfos", decryptData.toString());
                    }
                    jsonObj.put("result", result.toJSONString());
                } catch (Exception e) {
                    e.printStackTrace();
                }
            } else {
                jsonObj.put("stateCode", "1");
                jsonObj.put("stateDesc", "获取失败");
            }
        } else {
            jsonObj.put("stateCode", "3");
            jsonObj.put("stateDesc", "code为空");
        }

        System.out.println("仅获取微信用户所有信息(userData):" + jsonObj);

        out.print(jsonObj);
    }

    @Override
    protected void doPost(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
        doGet(req, resp);
    }
}

工具类:WxAesUtil.java

import org.apache.commons.codec.binary.Base64;
import org.bouncycastle.jce.provider.BouncyCastleProvider;

import com.alibaba.fastjson.JSONObject;

import javax.crypto.BadPaddingException;
import javax.crypto.Cipher;
import javax.crypto.IllegalBlockSizeException;
import javax.crypto.NoSuchPaddingException;
import javax.crypto.spec.IvParameterSpec;
import javax.crypto.spec.SecretKeySpec;
import java.io.UnsupportedEncodingException;
import java.security.*;
import java.security.spec.InvalidParameterSpecException;
import java.util.Arrays;

public class WxAesUtil {
    static {
        //BouncyCastle是一个开源的加解密解决方案,主页在http://www.bouncycastle.org/
        Security.addProvider(new BouncyCastleProvider());
    }
 
    /**
     * AES解密
     *
     * @param data           //密文,被加密的数据
     * @param key            //秘钥
     * @param iv             //偏移量
     * @param encodingFormat //解密后的结果需要进行的编码
     * @return
     * @throws Exception
     */
    public static JSONObject decrypt(String data, String key, String iv, String encodingFormat) throws Exception {
 
        //被加密的数据
        byte[] dataByte = Base64.decodeBase64(data);
        //加密秘钥
        byte[] keyByte = Base64.decodeBase64(key);
        //偏移量
        byte[] ivByte = Base64.decodeBase64(iv);
        try {
            // 如果密钥不足16位,那么就补足. 这个if 中的内容很重要
            int base = 16;
            if (keyByte.length % base != 0) {
                int groups = keyByte.length / base + (keyByte.length % base != 0 ? 1 : 0);
                byte[] temp = new byte[groups * base];
                Arrays.fill(temp, (byte) 0);
                System.arraycopy(keyByte, 0, temp, 0, keyByte.length);
                keyByte = temp;
            }
            
            Cipher cipher = Cipher.getInstance("AES/CBC/PKCS7Padding", "BC");
            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, "UTF-8");
                return JSONObject.parseObject(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;
    }
}

效果:

 

posted @ 2021-05-07 17:57  eRrsr  阅读(1921)  评论(0编辑  收藏  举报