微信小程序API文檔:https://mp.weixin.qq.com/debug/wxadoc/dev/api/api-login.html
openId : 用戶在當(dāng)前小程序的唯一標(biāo)識(shí)
因?yàn)樽罱鶕?jù)API調(diào)用https://api.weixin.qq.com/sns/jscode2session所以需要配置以下服務(wù),但是官方是不贊成這種做法的,
而且最近把在服務(wù)器配置的方法給關(guān)閉了。也就是說要獲取用戶openid,地區(qū)等信息只能在后臺(tái)獲取。
一下是官方的流程
那么問題來了,代碼怎么實(shí)現(xiàn)呢,以下是用java后臺(tái)的實(shí)現(xiàn)
微信客戶端的代碼實(shí)現(xiàn)是這樣的
-
wx.login({
-
success: function (r) {
-
if (r.code) {
-
var code = r.code;//登錄憑證
-
if (code) {
-
//2、調(diào)用獲取用戶信息接口
-
wx.getUserInfo({
-
success: function (res) {
-
//發(fā)起網(wǎng)絡(luò)請(qǐng)求
-
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('獲取用戶登錄態(tài)失敗!' + r.errMsg)
-
}
-
-
} else {
-
}
-
}
-
})
(服務(wù)端 java)自己的服務(wù)器發(fā)送code到微信服務(wù)器獲取openid(用戶唯一標(biāo)識(shí))和session_key(會(huì)話密鑰),
最后將encryptedData、iv、session_key通過AES解密獲取到用戶敏感數(shù)據(jù)
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;
-
}
-
-
}
發(fā)送請(qǐng)求的工具類HttpRequest
另外由于需求使用解密的工具類所有要在pom文件加上這個(gè)依賴
-
<dependency>
-
<groupId>org.bouncycastle</groupId>
-
<artifactId>bcprov-ext-jdk16</artifactId>
-
<version>1.46</version>
-
<type>jar</type>
-
<scope>compile</scope>
-
</dependency>
這樣才能引入bcprov這個(gè)jar包。網(wǎng)上參考了一下,個(gè)人感覺加這個(gè)依賴是最容易解決問題的。
最近打算弄個(gè)關(guān)于微信運(yùn)動(dòng)的小程序,解密這塊估計(jì)也要用到。大家有疑問可以一起留言交流