微信小程序java后台解码获取信息
由于小程序开发多个地方都需要使用到解码获取信息的需求,但由于本人从事java的开发然后去官网下载的sdk中竟然没有java的。哎-_-。所以准备写一篇关于java解码的blog吧。
一、我们解码前需要获取到几个小程序前端传过来的数据
登录凭证code:调用wx.login()可以获得;
秘钥iv和需要解码的encryptedData字符串:这个根据自己项目的需求定了,比如:获取openid和unionid可以在 wx.getUserInfo()中获得iv和encryptedData。
如果获取微信群ID:则通过wx.getShareInfo()获得iv和encryptedData。
微信小程序前端这里就不做详细的分析了。二 、 java后端的实现
/**
* 获取微信群ID(Gid)
* data:2018/1/24
* @return
* @throws Exception
*/
public String wxGetGroupGid() throws Exception{
String code=request.getParameter("code");接受小程序传过来的登录凭证code,
String iv=request.getParameter("iv");
String encryptedData=request.getParameter("encryptedData");
String OPENID_URL = "https://api.weixin.qq.com/sns/jscode2session?appid=APPID&secret"
+ "=SECRET&js_code=JSCODE&grant_type=authorization_code";// 获取openid的地址
String url = OPENID_URL.replace("APPID", Pkcs7Encoder.APPID)
.replace("SECRET", Pkcs7Encoder.APPSECRET)
.replace("JSCODE", code);
JSONObject jsonObject = null;
//向微信后台发起请求的url
jsonObject = Pkcs7Encoder.doGetStr(url);// 调取Get提交方法
String session_key = jsonObject.getString("session_key");
String result = Pkcs7Encoder.decrypt(encryptedData, session_key, iv,
"UTF-8");
JSONObject userInfoJSON = JSONObject.fromObject(result);
String openGid=userInfoJSON.getString("openGId");
System.out.println(openGid);
String JData="{\"openGid\":\""+openGid+"\"}";
//response.getWriter().write(openGid);
Struts2Utils.renderJsonNoDown(response, JData);
return null;
}
解码的帮助类
public class Pkcs7Encoder {
public final static String APPID = "***"; //小程序的APPID
public final static String APPSECRET = "***"; //小程序的appsecret
public final static String grant_type = "authorization_code";//授权(必填)
// 算法名称
static final String KEY_ALGORITHM = "AES";
// 加解密算法/模式/填充方式
static final String algorithmStr = "AES/CBC/PKCS7Padding";
private static Key key;
private static Cipher cipher;
boolean isInited = false;
//默认对称解密算法初始向量 iv
static byte[] iv = { 0x30, 0x31, 0x30, 0x32, 0x30, 0x33, 0x30, 0x34, 0x30, 0x35, 0x30, 0x36, 0x30, 0x37, 0x30, 0x38 };
public static String decrypt(String encryptedData, String sessionKey, String iv, String encodingFormat)
throws Exception {
// 被加密的数据
byte[] dataByte = Base64.decode(encryptedData);
// 加密秘钥
byte[] keyByte = Base64.decode(sessionKey);
// 偏移量
byte[] ivByte = Base64.decode(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;
}
// 初始化
Security.addProvider(new BouncyCastleProvider());
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, "UTF-8");
return JSONObject.fromObject(result).toString();
}
}catch (Exception e) {
e.printStackTrace();
}
return null;
}
/**
* 返回openid,unionid
* @param url
* @return
*/
public static JSONObject doGetStr(String url){
DefaultHttpClient httpClient = new DefaultHttpClient();
HttpGet httpGet = new HttpGet(url);
JSONObject jsonObject = null;
try {
HttpResponse response = httpClient.execute(httpGet);
HttpEntity entity = response.getEntity(); //接受结果
if(entity != null){
String result = EntityUtils.toString(entity,"UTF-8");
jsonObject = JSONObject.fromObject(result);
}
} catch (IOException e) {
e.printStackTrace();
}
return jsonObject;
}
public static void init(byte[] keyBytes) {
// 如果密钥不足16位,那么就补足. 这个if 中的内容很重要
int base = 16;
if (keyBytes.length % base != 0) {
int groups = keyBytes.length / base + (keyBytes.length % base != 0 ? 1 : 0);
byte[] temp = new byte[groups * base];
Arrays.fill(temp, (byte) 0);
System.arraycopy(keyBytes, 0, temp, 0, keyBytes.length);
keyBytes = temp;
}
// 初始化
Security.addProvider(new BouncyCastleProvider());
// 转化成JAVA的密钥格式
key = new SecretKeySpec(keyBytes, KEY_ALGORITHM);
try {
// 初始化cipher
cipher = Cipher.getInstance(algorithmStr, "BC");
} catch (NoSuchAlgorithmException e) {
// TODO Auto-generated catch block
e.printStackTrace();
} catch (NoSuchPaddingException e) {
// TODO Auto-generated catch block
e.printStackTrace();
} catch (NoSuchProviderException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
}
/**
* 加密方法
* --使用默认iv时
* @param content
* 要加密的字符串
* @param keyBytes
* 加密密钥
* @return
*/
public static byte[] encrypt(byte[] content, byte[] keyBytes) {
byte[] encryptedText = encryptOfDiyIV(content,keyBytes,iv);
return encryptedText;
}
/**
* 解密方法
* --使用默认iv时
* @param encryptedData
* 要解密的字符串
* @param keyBytes
* 解密密钥
* @return
*/
public static byte[] decrypt(byte[] encryptedData, byte[] keyBytes) {
byte[] encryptedText = decryptOfDiyIV(encryptedData,keyBytes,iv);
return encryptedText;
}
/**
* 加密方法
* ---自定义对称解密算法初始向量 iv
* @param content
* 要加密的字符串
* @param keyBytes
* 加密密钥
* @param ivs
* 自定义对称解密算法初始向量 iv
* @return 加密的结果
*/
public static byte[] encryptOfDiyIV(byte[] content, byte[] keyBytes, byte[] ivs) {
byte[] encryptedText = null;
init(keyBytes);
System.out.println("IV:" + new String(ivs));
try {
cipher.init(Cipher.ENCRYPT_MODE, key, new IvParameterSpec(ivs));
encryptedText = cipher.doFinal(content);
} catch (Exception e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
return encryptedText;
}
/**
* 解密方法
*
* @param encryptedData
* 要解密的字符串
* @param keyBytes
* 解密密钥
* @param ivs
* 自定义对称解密算法初始向量 iv
* @return
*/
public static byte[] decryptOfDiyIV(byte[] encryptedData, byte[] keyBytes,byte[] ivs) {
byte[] encryptedText = null;
init(keyBytes);
System.out.println("IV:" + new String(ivs));
try {
cipher.init(Cipher.DECRYPT_MODE, key, new IvParameterSpec(ivs));
encryptedText = cipher.doFinal(encryptedData);
} catch (Exception e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
return encryptedText;
}
/**
* 向指定 URL 发送POST方法的请求
*
* @param url 发送请求的 URL
* @param param 请求参数
* @return 所代表远程资源的响应结果
*/
public static String sendPost(String url, Map<String, ?> paramMap) {
PrintWriter out = null;
BufferedReader in = null;
String result = "";
String param = "";
Iterator<String> it = paramMap.keySet().iterator();
while(it.hasNext()) {
String key = it.next();
param += key + "=" + paramMap.get(key) + "&";
}
try {
URL realUrl = new URL(url);
// 打开和URL之间的连接
URLConnection conn = realUrl.openConnection();
// 设置通用的请求属性
conn.setRequestProperty("accept", "*/*");
conn.setRequestProperty("connection", "Keep-Alive");
conn.setRequestProperty("Accept-Charset", "utf-8");
conn.setRequestProperty("user-agent", "Mozilla/4.0 (compatible; MSIE 6.0; Windows NT 5.1;SV1)");
// 发送POST请求必须设置如下两行
conn.setDoOutput(true);
conn.setDoInput(true);
// 获取URLConnection对象对应的输出流
out = new PrintWriter(conn.getOutputStream());
// 发送请求参数
out.print(param);
// flush输出流的缓冲
out.flush();
// 定义BufferedReader输入流来读取URL的响应
in = new BufferedReader(new InputStreamReader(conn.getInputStream(), "UTF-8"));
String line;
while ((line = in.readLine()) != null) {
result += line;
}
} catch (Exception e) {
e.printStackTrace();
}
//使用finally块来关闭输出流、输入流
finally{
try{
if(out!=null){
out.close();
}
if(in!=null){
in.close();
}
}
catch(IOException ex){
ex.printStackTrace();
}
}
return result;
}
}
只要涉及到小程序解码的都是通用的,所以到这里已经完成了。