前期小程序开发只进行到根据微信用户登录获取的code 去微信的API去获取到该用户的openId和session_key,到了第二阶段,老大让我重写OAuthManager的代码来实现微信小程序和微信公众号平台获取用户信息的优化,即将OAuthManager重写成父类抽象类,微信小程序(WechatAppManager)和微信公众号(PublicAccountMananger)来继承并开发,具体方法不赘述。。。
在开发微信小程序的时候,由于对于需求的不理解,导致半天都发在获取用户信息的方法上,由于微信小程序没有access_token,所以,用户信息只能从前台发出,后台负责接收并封装JSON格式的用户信息。。。
在这里,我要重点阐述我在发送JSON信息时候所遇到的低级错误!!!
1.发送JSON格式信息,需要Headers添加
Content-Type:application/json
后台始终接收不到,就因为少了一个这个headers,接着因为JSON的格式是
{
"code": "CODE",
"wechatAppUserInfo": {
"errMsg": "getUserInfo:ok",
"rawData": "{\"nickName\":\"NICKNAME\",\"gender\":0,\"language\":\"LANGUAGE\",\"city\":\"CITY\",\"province\":\"PROVINCE\",\"country\":\"COUNTRY\",\"avatarUrl\":\"AVATARURL\"}",
"signature": "SIGNATURE",
"encryptData": "ENCRYPTDATA"
}
}
请注意好JSON格式,格式错了也是发不过去的,可以上网在线监测自己的JSON格式,后台接收的时候,我出于方便的目的,用dto的形式接收将json数据封装成一个dto,直接接收
public String getSessionByCode(@RequestBody WechatAppUser wechatAppUser, HttpServletRequest request)
WechatAppUser里只有两个属性(code , wechatAppUserInfo(wechatAppUserInfo)是一个封装类)
我将rawData和encryptData也进行了封装。。。
经过一系列的封装,反序列化之后,我们需要将encryptData数据进行解密,这个解密的过程让我心焦。。。
整了两天才发现原来是自己的数据出问题。。。
加密数据解密算法
接口如果涉及敏感数据(如wx.getUserInfo当中的 openid ),接口的明文内容将不包含敏感数据。开发者如需要获取敏感数据,需要对接口返回的加密数据( encryptData )进行对称解密。 解密算法如下:
1.对称解密使用的算法为 AES-128-CBC,数据采用PKCS#7填充。
2.对称解密的目标密文为 Base64_Decode(encryptData),
3.对称解密秘钥 aeskey = Base64_Decode(session_key), aeskey 是16字节
4.对称解密算法初始向量 iv = aeskey, 同样是16字节
上网各种百度该解密算法,让我在千万条链接中找到了它
http://blog.csdn.net/aflight/article/details/13626385
这个链接的key和iv是自动生成的,需要自己手动修改代码(iv的生成需要传入session_key转化的byte[])
//生成iv
public static AlgorithmParameters generateIV(byte [] iv) throws Exception{
//iv 为一个 16 字节的数组,这里采用和 iOS 端一样的构造方法,数据全为0
AlgorithmParameters params = AlgorithmParameters.getInstance(KEY_ALGORITHM);
params.init(new IvParameterSpec(iv));
return params;
}
//转化成JAVA的密钥格式
public static Key convertToKey(byte[] keyBytes) throws Exception{
SecretKey secretKey = new SecretKeySpec(keyBytes,KEY_ALGORITHM);
return secretKey;
}
解密的代码
byte[] data = WechatAppDecryptor.decrypt(wechatAppUser.getWechatAppUserInfo().getEncryptData(),
oAuthResult.getSession_key());
logger.debug("解密得到的数据 : " + new String(data,"UTF-8"));
wechatAppUser.getWechatAppUserInfo().setEncryptDatas(CacheUtil.doJacksonDeserialize(new String(data,"UTF-8"),EncryptData.class));
灰常好,这里我们就可以得到微信用户的基本信息以及最重要的unionId
UnionID机制说明:
如果开发者拥有多个移动应用、网站应用、和公众帐号(包括小程序),可通过unionid来区分用户的唯一性,因为只要是同一个微信开放平台帐号下的移动应用、网站应用和公众帐号(包括小程序),用户的unionid是唯一的。换句话说,同一用户,对同一个微信开放平台下的不同应用,unionid是相同的。
简而言之就是根据这个字段,用户在数据库中只会存在一条数据!!!
encryptData 解密后为以下 json 结构
{
"openId": "OPENID",
"nickName": "NICKNAME",
"gender": 1,
"city": "CITY",
"province": "PROVINCE",
"country": "COUNTRY",
"avatarUrl": "AVATARURL",
"unionId": "UNIONID"
}