小程序获取AppID和AppSecret的申请步骤就省略了,网上搜索一下会出来很多,就不赘述了
首先 前端页面上调用 wx.login() 获取 临时登录凭证code 。 参考:小程序获取code
在调用wx.getUserInfo(Object object) 获取 encryptedData 和 iv 。参考:获取用户数据的签名验证和加解密
现在接口需要准备的参数都准备齐了,java代码如下:
public class wxSmallProgram {
private static final Log LOG = LogFactory.getLogger(wxSmallProgram.class);
//接口地址
public final static String SESSIONKEY_OPENID = "https://api.weixin.qq.com/sns/jscode2session";
public Object doGetUserInfo(String code, String encryptedData, String iv, ModelMap model) {
//获取微信sessionKey 和 openId
Map<String, String> resultJson = getSessionKeyAndOpenId("你的AppId", "你的AppSecret", code);
if (resultJson.get("errcode") != null) {
throw new EcRuntimeException("获取sessionId出错");
}
String sessionKey = resultJson.get("session_key");
String openId = resultJson.get("openid");
//解密
String userInfoJson = AES.wxDecrypt(encryptedData, sessionKey, iv);
Map<String, Object> jsonMap = JSONHelper.in.convert(userInfoJson, new TypeReference<Map<String, Object>>() {
});
//实体
Customer authCustomer = findWxUserForWechat(jsonMap);
if (authCustomer == null) {
LOG.error("解密用户信息出错");
return null;
}
model.put("authCustomer", authCustomer);
return model;
}
/**
* 获取微信sessionKey 和 openId
*
* @param appid
* @param secret
* @param jsCode
* @return
*/
public Map<String, String> getSessionKeyAndOpenId(String appid, String secret, String jsCode) {
try {
HttpResponse<JsonNode> jsonResponse = Unirest
.get(SESSIONKEY_OPENID)
.queryString("appid", appid)
.queryString("secret", secret)
.queryString("js_code", jsCode)
.queryString("grant_type", "authorization_code")
.asJson();
JSONObject jb = jsonResponse.getBody().getObject();
if (jb != null) {
return JSONHelper.in.convert(jb.toString(), new TypeReference<Map<String, String>>() {
});
}
return null;
} catch (Exception e) {
LOG.error("接口获取session_key和openid报错,appSecret:" + appid + " appSecret:" + secret + " js_code:" + jsCode, e);
}
return null;
}
/**
* 获取信息并存入实体
*
* @param jb
* @return
*/
public Customer findWxUserForWechat(Map<String, Object> jb) {
Customer customer = new Customer ();
if (jb.get("openId") != null && !"".equals(jb.get("openId"))) {
customer.setOpenid(jb.get("openId").toString());
}
if (jb.get("nickName") != null && !"".equals(jb.get("nickName"))) {
customer.setNickname(jb.get("nickName").toString());
}
if (jb.get("gender") != null && !"".equals(jb.get("gender"))) {
customer.setSex(Integer.parseInt(jb.get("gender").toString()));
}
if (jb.get("province") != null && !"".equals(jb.get("province"))) {
customer.setProvince(jb.get("province").toString());
}
if (jb.get("city") != null && !"".equals(jb.get("city"))) {
customer.setCity(jb.get("city").toString());
}
if (jb.get("openId") != null && !"".equals(jb.get("openId"))) {
customer.setCountry(jb.get("country").toString());
}
if (jb.get("avatarUrl") != null && !"".equals(jb.get("avatarUrl"))) {
customer.setHeadImageUrl(jb.get("avatarUrl").toString());
}
if (jb.get("unionId") != null && !"".equals(jb.get("unionId"))) {
customer.setUnionid(jb.get("unionId").toString());
}
if (jb != null) {
customer.setExtend(jb.toString());
}
return ;
}
}
实体类:
public class Customer implements java.io.Serializable {
// Fields
private String openid;
private String nickname;
private Integer sex;
private String city;
private String province;
private String country;
private String headImageUrl;
private Timestamp subscribeTime;
private Timestamp unsubscribeTime;
private String groupId = "0";
private String remark;
private String unionid;
private String appId;
private int subscribed;
private String extend;
/** default constructor */
public Customer() {
}
public String getOpenid() {
return openid;
}
public void setOpenid(String openid) {
this.openid = openid;
}
public String getNickname() {
return nickname;
}
public void setNickname(String nickname) {
this.nickname = nickname;
}
public Integer getSex() {
return sex;
}
public void setSex(Integer sex) {
this.sex = sex;
}
public String getCity() {
return city;
}
public void setCity(String city) {
this.city = city;
}
public String getProvince() {
return province;
}
public void setProvince(String province) {
this.province = province;
}
public String getCountry() {
return country;
}
public void setCountry(String country) {
this.country = country;
}
public String getHeadImageUrl() {
return headImageUrl;
}
public void setHeadImageUrl(String headImageUrl) {
this.headImageUrl = headImageUrl;
}
public Timestamp getSubscribeTime() {
return subscribeTime;
}
public void setSubscribeTime(Timestamp subscribeTime) {
this.subscribeTime = subscribeTime;
}
public Timestamp getUnsubscribeTime() {
return unsubscribeTime;
}
public void setUnsubscribeTime(Timestamp unsubscribeTime) {
this.unsubscribeTime = unsubscribeTime;
}
public String getGroupId() {
return groupId;
}
public void setGroupId(String groupId) {
this.groupId = groupId;
}
public String getRemark() {
return remark;
}
public void setRemark(String remark) {
this.remark = remark;
}
public String getUnionid() {
return unionid;
}
public void setUnionid(String unionid) {
this.unionid = unionid;
}
public String getAppId() {
return appId;
}
public void setAppId(String appId) {
this.appId = appId;
}
public int getSubscribed() {
return subscribed;
}
public void setSubscribed(int subscribed) {
this.subscribed = subscribed;
}
public String getExtend() {
return extend;
}
public void setExtend(String extend) {
this.extend = extend;
}
}
小程序AES加解密算法:
public class AES {
// 算法名
public static final String KEY_NAME = "AES";
// 加解密算法/模式/填充方式
// ECB模式只用密钥即可对数据进行加密解密,CBC模式需要添加一个iv
public static final String CIPHER_ALGORITHM = "AES/CBC/PKCS7Padding";
/**
* 微信 数据解密<br/>
* 对称解密使用的算法为 AES-128-CBC,数据采用PKCS#7填充<br/>
* 对称解密的目标密文:encrypted=Base64_Decode(encryptData)<br/>
* 对称解密秘钥:key = Base64_Decode(session_key),aeskey是16字节<br/>
* 对称解密算法初始向量:iv = Base64_Decode(iv),同样是16字节<br/>
*
* @param encrypted 目标密文
* @param session_key 会话ID
* @param iv 加密算法的初始向量
*/
public static String wxDecrypt(String encrypted, String session_key, String iv) {
return wxDecrypt(encrypted, session_key, iv, "UTF-8");
}
public static String wxDecrypt(String encrypted, String session_key, String iv, String encoding) {
String json = null;
byte[] encrypted64 = Base64.decodeBase64(encrypted.getBytes());
byte[] key64 = Base64.decodeBase64(session_key.getBytes());
byte[] iv64 = Base64.decodeBase64(iv.getBytes());
byte[] data;
try {
init();
byte[] bytes = decrypt(encrypted64, key64, generateIV(iv64));
json = new String(bytes, encoding);
} catch (Exception e) {
e.printStackTrace();
}
return json;
}
/**
* 初始化密钥
*/
public static void init() throws Exception {
Security.addProvider(new org.bouncycastle.jce.provider.BouncyCastleProvider());
KeyGenerator.getInstance(KEY_NAME).init(128);
}
/**
* 生成iv
*/
public static AlgorithmParameters generateIV(byte[] iv) throws Exception {
// iv 为一个 16 字节的数组,这里采用和 iOS 端一样的构造方法,数据全为0
// Arrays.fill(iv, (byte) 0x00);
AlgorithmParameters params = AlgorithmParameters.getInstance(KEY_NAME);
params.init(new IvParameterSpec(iv));
return params;
}
/**
* 生成解密
*/
public static byte[] decrypt(byte[] encryptedData, byte[] keyBytes, AlgorithmParameters iv)
throws Exception {
Key key = new SecretKeySpec(keyBytes, KEY_NAME);
Cipher cipher = Cipher.getInstance(CIPHER_ALGORITHM);
// 设置为解密模式
cipher.init(Cipher.DECRYPT_MODE, key, iv);
return cipher.doFinal(encryptedData);
}
}
获取到自己需要的信息,在接着做自己的功能就可以了! 是不是很简单~~