Add WXBizDataCrypt for WeChat Mini Program.
This commit is contained in:
parent
6382fe6195
commit
75c10cb035
8
.gitignore
vendored
8
.gitignore
vendored
@ -12,9 +12,9 @@ hs_err_pid*
|
||||
*~
|
||||
|
||||
# eclipse ignore
|
||||
*.settings/*
|
||||
/.project
|
||||
/.classpath
|
||||
.settings/
|
||||
.project
|
||||
.classpath
|
||||
/.tomcatplugin
|
||||
|
||||
# idea ignore
|
||||
@ -22,7 +22,7 @@ hs_err_pid*
|
||||
*.iml
|
||||
|
||||
# maven ignore
|
||||
target/*
|
||||
target/
|
||||
|
||||
# other ignore
|
||||
*.log
|
||||
|
||||
@ -18,7 +18,11 @@ weixin4j
|
||||
* **weixin4j-qy[1.7.8]**
|
||||
|
||||
`企业号API封装`
|
||||
|
||||
|
||||
* **weixin4j-wxa[1.7.9]**
|
||||
|
||||
`小程序 API 封装`
|
||||
|
||||
* **weixin4j-server[1.1.8]**
|
||||
|
||||
`netty服务器&消息分发`
|
||||
|
||||
1
pom.xml
1
pom.xml
@ -43,6 +43,7 @@
|
||||
<module>weixin4j-base</module>
|
||||
<module>weixin4j-mp</module>
|
||||
<module>weixin4j-qy</module>
|
||||
<module>weixin4j-wxa</module>
|
||||
<module>weixin4j-server</module>
|
||||
<module>weixin4j-example</module>
|
||||
<module>weixin4j-serverX</module>
|
||||
|
||||
49
weixin4j-wxa/pom.xml
Normal file
49
weixin4j-wxa/pom.xml
Normal file
@ -0,0 +1,49 @@
|
||||
<?xml version="1.0"?>
|
||||
<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
|
||||
xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
|
||||
<modelVersion>4.0.0</modelVersion>
|
||||
<parent>
|
||||
<groupId>com.foxinmy</groupId>
|
||||
<artifactId>weixin4j</artifactId>
|
||||
<version>1.7.9</version>
|
||||
</parent>
|
||||
<artifactId>weixin4j-wxa</artifactId>
|
||||
<name>weixin4j-wxa</name>
|
||||
<url>https://github.com/foxinmy/weixin4j/tree/master/weixin4j-wxa</url>
|
||||
<description>微信小程序 API 支持</description>
|
||||
<build>
|
||||
<plugins>
|
||||
<plugin>
|
||||
<groupId>org.apache.maven.plugins</groupId>
|
||||
<artifactId>maven-assembly-plugin</artifactId>
|
||||
</plugin>
|
||||
</plugins>
|
||||
</build>
|
||||
<dependencies>
|
||||
<dependency>
|
||||
<groupId>com.foxinmy</groupId>
|
||||
<artifactId>weixin4j-base</artifactId>
|
||||
<version>${project.version}</version>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>commons-codec</groupId>
|
||||
<artifactId>commons-codec</artifactId>
|
||||
<version>1.10</version>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>org.bouncycastle</groupId>
|
||||
<artifactId>bcprov-jdk15on</artifactId>
|
||||
<version>1.55</version>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>junit</groupId>
|
||||
<artifactId>junit</artifactId>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>ch.qos.logback</groupId>
|
||||
<artifactId>logback-core</artifactId>
|
||||
<version>1.1.8</version>
|
||||
<scope>test</scope>
|
||||
</dependency>
|
||||
</dependencies>
|
||||
</project>
|
||||
@ -0,0 +1,58 @@
|
||||
package com.foxinmy.weixin4j.wxa;
|
||||
|
||||
import java.security.AlgorithmParameters;
|
||||
import java.security.InvalidAlgorithmParameterException;
|
||||
import java.security.Key;
|
||||
import java.security.NoSuchProviderException;
|
||||
import java.security.Security;
|
||||
|
||||
import javax.crypto.Cipher;
|
||||
import javax.crypto.spec.IvParameterSpec;
|
||||
import javax.crypto.spec.SecretKeySpec;
|
||||
|
||||
import org.bouncycastle.jce.provider.BouncyCastleProvider;
|
||||
|
||||
final class AESUtils {
|
||||
|
||||
private static boolean initialized = false;
|
||||
|
||||
private AESUtils() {
|
||||
}
|
||||
|
||||
/**
|
||||
* AES解密
|
||||
*
|
||||
* @param content 密文
|
||||
* @return 明文
|
||||
* @throws InvalidAlgorithmParameterException
|
||||
* @throws NoSuchProviderException
|
||||
*/
|
||||
static byte[] decrypt(byte[] content, byte[] keyByte, byte[] ivByte)
|
||||
throws InvalidAlgorithmParameterException {
|
||||
initialize();
|
||||
try {
|
||||
Cipher cipher = Cipher.getInstance("AES/CBC/PKCS7Padding");
|
||||
Key sKeySpec = new SecretKeySpec(keyByte, "AES");
|
||||
|
||||
cipher.init(Cipher.DECRYPT_MODE, sKeySpec, generateIV(ivByte)); // 初始化
|
||||
byte[] result = cipher.doFinal(content);
|
||||
return result;
|
||||
} catch (Exception e) {
|
||||
throw new RuntimeException(e);
|
||||
}
|
||||
}
|
||||
|
||||
private static void initialize() {
|
||||
if (initialized)
|
||||
return;
|
||||
Security.addProvider(new BouncyCastleProvider());
|
||||
initialized = true;
|
||||
}
|
||||
|
||||
private static AlgorithmParameters generateIV(byte[] iv) throws Exception {
|
||||
AlgorithmParameters params = AlgorithmParameters.getInstance("AES");
|
||||
params.init(new IvParameterSpec(iv));
|
||||
return params;
|
||||
}
|
||||
|
||||
}
|
||||
@ -0,0 +1,48 @@
|
||||
package com.foxinmy.weixin4j.wxa;
|
||||
|
||||
import java.nio.charset.Charset;
|
||||
import java.security.InvalidAlgorithmParameterException;
|
||||
|
||||
import org.apache.commons.codec.binary.Base64;
|
||||
|
||||
import com.alibaba.fastjson.JSON;
|
||||
import com.alibaba.fastjson.JSONObject;
|
||||
|
||||
/**
|
||||
* @see <a href="https://developers.weixin.qq.com/miniprogram/dev/api/signature.html#wxchecksessionobject">加密数据解密算法</a>
|
||||
*/
|
||||
public class WXBizDataCrypt {
|
||||
|
||||
private final String appid;
|
||||
|
||||
private final String sessionKey;
|
||||
|
||||
public WXBizDataCrypt(String appid, String sessionKey) {
|
||||
this.appid = appid;
|
||||
this.sessionKey = sessionKey;
|
||||
}
|
||||
|
||||
public JSONObject decryptData(final String encryptedData, final String iv) {
|
||||
final byte[] aesKey = Base64.decodeBase64(sessionKey);
|
||||
final byte[] aesCipher = Base64.decodeBase64(encryptedData);
|
||||
final byte[] aesIV = Base64.decodeBase64(iv);
|
||||
|
||||
final byte[] resultByte;
|
||||
try {
|
||||
resultByte = AESUtils.decrypt(aesCipher, aesKey, aesIV);
|
||||
} catch (InvalidAlgorithmParameterException e) {
|
||||
throw new RuntimeException(e);
|
||||
}
|
||||
|
||||
final String decryptedText = new String(resultByte, Charset.forName("UTF-8"));
|
||||
final JSONObject decrypted = JSON.parseObject(decryptedText);
|
||||
|
||||
final String appId = decrypted.getJSONObject("watermark").getString("appid");
|
||||
if (!appId.equals(this.appid)) {
|
||||
throw new IllegalArgumentException("Invalid Buffer");
|
||||
}
|
||||
|
||||
return decrypted;
|
||||
}
|
||||
|
||||
}
|
||||
@ -0,0 +1,4 @@
|
||||
/**
|
||||
* <a href="https://developers.weixin.qq.com/miniprogram/dev/api/">WeChat Mini Program</a> support library.
|
||||
*/
|
||||
package com.foxinmy.weixin4j.wxa;
|
||||
@ -0,0 +1,55 @@
|
||||
package com.foxinmy.weixin4j.wxa;
|
||||
|
||||
import static org.junit.Assert.assertEquals;
|
||||
|
||||
import org.junit.Test;
|
||||
|
||||
import com.alibaba.fastjson.JSONObject;
|
||||
|
||||
public class WXBizDataCryptTest {
|
||||
|
||||
@Test
|
||||
public void testDecryptData() {
|
||||
String appId = "wx4f4bc4dec97d474b";
|
||||
String sessionKey = "tiihtNczf5v6AKRyjwEUhQ==";
|
||||
|
||||
WXBizDataCrypt biz = new WXBizDataCrypt(appId, sessionKey);
|
||||
|
||||
String encryptedData
|
||||
= "CiyLU1Aw2KjvrjMdj8YKliAjtP4gsMZM"
|
||||
+ "QmRzooG2xrDcvSnxIMXFufNstNGTyaGS"
|
||||
+ "9uT5geRa0W4oTOb1WT7fJlAC+oNPdbB+"
|
||||
+ "3hVbJSRgv+4lGOETKUQz6OYStslQ142d"
|
||||
+ "NCuabNPGBzlooOmB231qMM85d2/fV6Ch"
|
||||
+ "evvXvQP8Hkue1poOFtnEtpyxVLW1zAo6"
|
||||
+ "/1Xx1COxFvrc2d7UL/lmHInNlxuacJXw"
|
||||
+ "u0fjpXfz/YqYzBIBzD6WUfTIF9GRHpOn"
|
||||
+ "/Hz7saL8xz+W//FRAUid1OksQaQx4CMs"
|
||||
+ "8LOddcQhULW4ucetDf96JcR3g0gfRK4P"
|
||||
+ "C7E/r7Z6xNrXd2UIeorGj5Ef7b1pJAYB"
|
||||
+ "6Y5anaHqZ9J6nKEBvB4DnNLIVWSgARns"
|
||||
+ "/8wR2SiRS7MNACwTyrGvt9ts8p12PKFd"
|
||||
+ "lqYTopNHR1Vf7XjfhQlVsAJdNiKdYmYV"
|
||||
+ "oKlaRv85IfVunYzO0IKXsyl7JCUjCpoG"
|
||||
+ "20f0a04COwfneQAGGwd5oa+T8yO5hzuy"
|
||||
+ "Db/XcxxmK01EpqOyuxINew==";
|
||||
String iv = "r7BXXKkLb8qrSNn05n0qiA==";
|
||||
|
||||
JSONObject data = biz.decryptData(encryptedData, iv);
|
||||
|
||||
assertEquals("CN", data.getString("country"));
|
||||
assertEquals("ocMvos6NjeKLIBqg5Mr9QjxrP1FA", data.getString("unionId"));
|
||||
assertEquals(1, data.getIntValue("gender"));
|
||||
assertEquals("Guangdong", data.getString("province"));
|
||||
assertEquals("Guangzhou", data.getString("city"));
|
||||
assertEquals("http://wx.qlogo.cn/mmopen/vi_32/aSKcBBPpibyKNicHNTMM0qJVh8Kjgiak2AHWr8MHM4WgMEm7GFhsf8OYrySdbvAMvTsw3mo8ibKicsnfN5pRjl1p8HQ/0", data.getString("avatarUrl"));
|
||||
assertEquals("oGZUI0egBJY1zhBYw2KhdUfwVJJE", data.getString("openId"));
|
||||
assertEquals("Band", data.getString("nickName"));
|
||||
assertEquals("zh_CN", data.getString("language"));
|
||||
|
||||
JSONObject watermark = data.getJSONObject("watermark");
|
||||
assertEquals("wx4f4bc4dec97d474b", watermark.getString("appid"));
|
||||
assertEquals(1477314187L, watermark.getLongValue("timestamp"));
|
||||
}
|
||||
|
||||
}
|
||||
Loading…
x
Reference in New Issue
Block a user