微信小程序API文档:https://mp.weixin.qq.com/debug/wxadoc/dev/api/api-login.html
openId : 用户在当前小程序的唯一标识
因为最近根据API调用https://api.weixin.qq.com/sns/jscode2session所以需要配置以下服务,但是官方是不赞成这种做法的,
而且最近把在服务器配置的方法给关闭了。也就是说要获取用户openid,地区等信息只能在后台获取。
一下是官方的流程
那么问题来了,代码怎么实现呢,以下是用java后台的实现
微信客户端的代码实现是这样的
-
wx.login({
-
success: function (r) {
-
if (r.code) {
-
var code = r.code;//登录凭证
-
if (code) {
-
//2、调用获取用户信息接口
-
wx.getUserInfo({
-
success: function (res) {
-
//发起网络请求
-
wx.request({
-
url: that.data.net + '/decodeUser.json',
-
header: {
-
"content-type": "application/x-www-form-urlencoded"
-
},
-
method: "POST",
-
data: {
-
encryptedData: res.encryptedData,
-
iv: res.iv,
-
code: code
-
},
-
success: function (result) {
-
// wx.setStorage({
-
// key: 'openid',
-
// data: res.data.openid,
-
// })
-
console.log(result)
-
}
-
})
-
},
-
fail: function () {
-
console.log('获取用户信息失败')
-
}
-
})
-
} else {
-
console.log('获取用户登录态失败!' + r.errMsg)
-
}
-
-
} else {
-
}
-
}
-
})
(服务端 java)自己的服务器发送code到微信服务器获取openid(用户唯一标识)和session_key(会话密钥),
最后将encryptedData、iv、session_key通过AES解密获取到用户敏感数据
1、获取秘钥并处理解密的controller
-
-
-
-
-
-
-
-
-
@ResponseBody
-
@RequestMapping(value = "/decodeUser", method = RequestMethod.POST)
-
public Map decodeUser(String encryptedData, String iv, String code) {
-
-
Map map = new HashMap();
-
-
-
if (code == null || code.length() == 0) {
-
map.put("status", 0);
-
map.put("msg", "code 不能为空");
-
return map;
-
}
-
-
-
String wxspAppid = "wxd8980e77d335c871";
-
-
String wxspSecret = "85d29ab4fa8c797423f2d7da5dd514cf";
-
-
String grant_type = "authorization_code";
-
-
-
-
-
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);
-
-
JSONObject json = JSONObject.fromObject(sr);
-
-
String session_key = json.get("session_key").toString();
-
-
String openid = (String) json.get("openid");
-
-
-
try {
-
String result = AesCbcUtil.decrypt(encryptedData, session_key, iv, "UTF-8");
-
if (null != result && result.length() > 0) {
-
map.put("status", 1);
-
map.put("msg", "解密成功");
-
-
JSONObject userInfoJSON = JSONObject.fromObject(result);
-
Map userInfo = new HashMap();
-
userInfo.put("openId", userInfoJSON.get("openId"));
-
userInfo.put("nickName", userInfoJSON.get("nickName"));
-
userInfo.put("gender", userInfoJSON.get("gender"));
-
userInfo.put("city", userInfoJSON.get("city"));
-
userInfo.put("province", userInfoJSON.get("province"));
-
userInfo.put("country", userInfoJSON.get("country"));
-
userInfo.put("avatarUrl", userInfoJSON.get("avatarUrl"));
-
userInfo.put("unionId", userInfoJSON.get("unionId"));
-
map.put("userInfo", userInfo);
-
return map;
-
}
-
} catch (Exception e) {
-
e.printStackTrace();
-
}
-
map.put("status", 0);
-
map.put("msg", "解密失败");
-
return map;
-
}
解密工具类 AesCbcUtil
-
import org.apache.commons.codec.binary.Base64;
-
import org.bouncycastle.jce.provider.BouncyCastleProvider;
-
-
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;
-
-
-
-
-
-
-
-
-
public class AesCbcUtil {
-
-
-
static {
-
-
Security.addProvider(new BouncyCastleProvider());
-
}
-
-
-
-
-
-
-
-
-
-
-
-
public static String 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 {
-
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;
-
}
-
-
}
发送请求的工具类HttpRequest
另外由于需求使用解密的工具类所有要在pom文件加上这个依赖
-
<dependency>
-
<groupId>org.bouncycastle</groupId>
-
<artifactId>bcprov-ext-jdk16</artifactId>
-
<version>1.46</version>
-
<type>jar</type>
-
<scope>compile</scope>
-
</dependency>
这样才能引入bcprov这个jar包。网上参考了一下,个人感觉加这个依赖是最容易解决问题的。
最近打算弄个关于微信运动的小程序,解密这块估计也要用到。大家有疑问可以一起留言交流