微信小程序-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; } }
效果: