From 40f45b483d9d46523a1895d61d53d670d5a05373 Mon Sep 17 00:00:00 2001 From: Binary Wang Date: Fri, 31 Jul 2026 03:33:59 +0000 Subject: [PATCH 1/3] =?UTF-8?q?test:=20=E4=B8=BA=20weixin-java-open=20?= =?UTF-8?q?=E4=B8=8E=20weixin-java-channel=20=E8=A1=A5=E5=85=85=E5=8D=95?= =?UTF-8?q?=E5=85=83=E6=B5=8B=E8=AF=95?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit 覆盖率最低的两个模块补充纯逻辑单元测试: - open: WxOpenCryptUtil、WxOpenXmlMessage、WxOpenGsonBuilder 适配器 - channel: XmlUtils、WxChCryptUtils Co-Authored-By: Devin AI <158243242+devin-ai-integration[bot]@users.noreply.github.com> --- .../channel/util/WxChCryptUtilsTest.java | 100 +++++++++++++ .../weixin/channel/util/XmlUtilsTest.java | 75 ++++++++++ .../bean/message/WxOpenXmlMessageTest.java | 138 ++++++++++++++++++ .../weixin/open/util/WxOpenCryptUtilTest.java | 87 +++++++++++ .../open/util/json/WxOpenGsonBuilderTest.java | 92 ++++++++++++ 5 files changed, 492 insertions(+) create mode 100644 weixin-java-channel/src/test/java/me/chanjar/weixin/channel/util/WxChCryptUtilsTest.java create mode 100644 weixin-java-channel/src/test/java/me/chanjar/weixin/channel/util/XmlUtilsTest.java create mode 100644 weixin-java-open/src/test/java/me/chanjar/weixin/open/bean/message/WxOpenXmlMessageTest.java create mode 100644 weixin-java-open/src/test/java/me/chanjar/weixin/open/util/WxOpenCryptUtilTest.java create mode 100644 weixin-java-open/src/test/java/me/chanjar/weixin/open/util/json/WxOpenGsonBuilderTest.java diff --git a/weixin-java-channel/src/test/java/me/chanjar/weixin/channel/util/WxChCryptUtilsTest.java b/weixin-java-channel/src/test/java/me/chanjar/weixin/channel/util/WxChCryptUtilsTest.java new file mode 100644 index 0000000000..0e3b9da080 --- /dev/null +++ b/weixin-java-channel/src/test/java/me/chanjar/weixin/channel/util/WxChCryptUtilsTest.java @@ -0,0 +1,100 @@ +package me.chanjar.weixin.channel.util; + +import static org.testng.Assert.assertEquals; +import static org.testng.Assert.assertNotNull; +import static org.testng.Assert.assertTrue; +import static org.testng.Assert.expectThrows; + +import java.nio.charset.StandardCharsets; +import java.util.regex.Matcher; +import java.util.regex.Pattern; +import javax.crypto.Cipher; +import javax.crypto.spec.IvParameterSpec; +import javax.crypto.spec.SecretKeySpec; +import me.chanjar.weixin.channel.config.impl.WxChannelDefaultConfigImpl; +import me.chanjar.weixin.common.error.WxRuntimeException; +import me.chanjar.weixin.common.util.crypto.SHA1; +import org.apache.commons.codec.binary.Base64; +import org.testng.annotations.Test; + +/** + * {@link WxChCryptUtils} 单元测试 + */ +public class WxChCryptUtilsTest { + + private static final String APP_ID = "wx0000000000000002"; + private static final String TOKEN = "test_channel_token"; + /** 43 位 EncodingAESKey 占位值,非真实密钥 */ + private static final String AES_KEY = "MDEyMzQ1Njc4OWFiY2RlZjAxMjM0NTY3ODlhYmNkZWY"; + + private static final Pattern ENCRYPT_PATTERN = Pattern.compile(""); + private static final Pattern SIGNATURE_PATTERN = + Pattern.compile(""); + private static final Pattern TIMESTAMP_PATTERN = Pattern.compile("(.*?)"); + private static final Pattern NONCE_PATTERN = Pattern.compile(""); + + private WxChCryptUtils cryptUtils() { + WxChannelDefaultConfigImpl config = new WxChannelDefaultConfigImpl(); + config.setAppid(APP_ID); + config.setToken(TOKEN); + config.setAesKey(AES_KEY); + return new WxChCryptUtils(config); + } + + private String group(Pattern pattern, String text) { + Matcher matcher = pattern.matcher(text); + assertTrue(matcher.find(), "未匹配到期望的节点:" + pattern.pattern()); + return matcher.group(1); + } + + @Test + public void testEncryptThenDecrypt() { + WxChCryptUtils cryptUtils = cryptUtils(); + String plainText = "" + + ""; + + String encryptedXml = cryptUtils.encrypt(plainText); + assertNotNull(encryptedXml); + + String encrypt = group(ENCRYPT_PATTERN, encryptedXml); + String signature = group(SIGNATURE_PATTERN, encryptedXml); + String timestamp = group(TIMESTAMP_PATTERN, encryptedXml); + String nonce = group(NONCE_PATTERN, encryptedXml); + + assertEquals(signature, SHA1.gen(TOKEN, timestamp, nonce, encrypt)); + assertEquals(cryptUtils.decryptXml(signature, timestamp, nonce, encryptedXml), plainText); + } + + @Test + public void testDecryptXmlWithWrongSignature() { + WxChCryptUtils cryptUtils = cryptUtils(); + String encryptedXml = cryptUtils.encrypt(""); + String timestamp = group(TIMESTAMP_PATTERN, encryptedXml); + String nonce = group(NONCE_PATTERN, encryptedXml); + + expectThrows(WxRuntimeException.class, + () -> cryptUtils.decryptXml("wrong_signature", timestamp, nonce, encryptedXml)); + } + + @Test + public void testDecryptWithSessionKey() throws Exception { + byte[] keyBytes = "0123456789abcdef".getBytes(StandardCharsets.UTF_8); + byte[] ivBytes = "fedcba9876543210".getBytes(StandardCharsets.UTF_8); + String plainText = "{\"openid\":\"o0000000000000000000\"}"; + + Cipher cipher = Cipher.getInstance("AES/CBC/PKCS5Padding"); + cipher.init(Cipher.ENCRYPT_MODE, new SecretKeySpec(keyBytes, "AES"), new IvParameterSpec(ivBytes)); + String encryptedData = Base64.encodeBase64String(cipher.doFinal(plainText.getBytes(StandardCharsets.UTF_8))); + + String decrypted = WxChCryptUtils.decrypt(Base64.encodeBase64String(keyBytes), encryptedData, + Base64.encodeBase64String(ivBytes)); + assertEquals(decrypted, plainText); + } + + @Test + public void testDecryptWithInvalidSessionKey() { + expectThrows(RuntimeException.class, + () -> WxChCryptUtils.decrypt(Base64.encodeBase64String("short_key".getBytes(StandardCharsets.UTF_8)), + "invalid", Base64.encodeBase64String("fedcba9876543210".getBytes(StandardCharsets.UTF_8)))); + } +} diff --git a/weixin-java-channel/src/test/java/me/chanjar/weixin/channel/util/XmlUtilsTest.java b/weixin-java-channel/src/test/java/me/chanjar/weixin/channel/util/XmlUtilsTest.java new file mode 100644 index 0000000000..e22e31760a --- /dev/null +++ b/weixin-java-channel/src/test/java/me/chanjar/weixin/channel/util/XmlUtilsTest.java @@ -0,0 +1,75 @@ +package me.chanjar.weixin.channel.util; + +import static org.testng.Assert.assertEquals; +import static org.testng.Assert.assertNotNull; +import static org.testng.Assert.assertNull; + +import com.fasterxml.jackson.core.type.TypeReference; +import com.fasterxml.jackson.dataformat.xml.XmlMapper; +import java.io.ByteArrayInputStream; +import java.io.InputStream; +import java.nio.charset.StandardCharsets; +import me.chanjar.weixin.channel.bean.base.AttrInfo; +import org.testng.annotations.Test; + +/** + * {@link XmlUtils} 单元测试 + */ +public class XmlUtilsTest { + + private static final String XML = "这是Key这是Value"; + + @Test + public void testEncode() { + String xml = XmlUtils.encode(new AttrInfo("这是Key", "这是Value")); + assertNotNull(xml); + assertEquals(xml, XML); + } + + @Test + public void testEncodeWithObjectMapper() { + String xml = XmlUtils.encode(new XmlMapper(), new AttrInfo("这是Key", "这是Value")); + assertNotNull(xml); + assertEquals(XmlUtils.decode(xml, AttrInfo.class).getKey(), "这是Key"); + } + + @Test + public void testDecode() { + AttrInfo info = XmlUtils.decode(XML, AttrInfo.class); + assertNotNull(info); + assertEquals(info.getKey(), "这是Key"); + assertEquals(info.getValue(), "这是Value"); + } + + @Test + public void testDecodeUnknownProperty() { + String xml = "kv"; + AttrInfo info = XmlUtils.decode(xml, AttrInfo.class); + assertNotNull(info); + assertEquals(info.getKey(), "k"); + assertNull(info.getValue()); + } + + @Test + public void testDecodeEmptyOrInvalidXml() { + assertNull(XmlUtils.decode((String) null, AttrInfo.class)); + assertNull(XmlUtils.decode("", AttrInfo.class)); + assertNull(XmlUtils.decode("not a xml", AttrInfo.class)); + } + + @Test + public void testDecodeWithTypeReference() { + AttrInfo info = XmlUtils.decode(XML, new TypeReference() { + }); + assertNotNull(info); + assertEquals(info.getValue(), "这是Value"); + } + + @Test + public void testDecodeInputStream() { + InputStream is = new ByteArrayInputStream(XML.getBytes(StandardCharsets.UTF_8)); + AttrInfo info = XmlUtils.decode(is, AttrInfo.class); + assertNotNull(info); + assertEquals(info.getKey(), "这是Key"); + } +} diff --git a/weixin-java-open/src/test/java/me/chanjar/weixin/open/bean/message/WxOpenXmlMessageTest.java b/weixin-java-open/src/test/java/me/chanjar/weixin/open/bean/message/WxOpenXmlMessageTest.java new file mode 100644 index 0000000000..26bc8a505a --- /dev/null +++ b/weixin-java-open/src/test/java/me/chanjar/weixin/open/bean/message/WxOpenXmlMessageTest.java @@ -0,0 +1,138 @@ +package me.chanjar.weixin.open.bean.message; + +import me.chanjar.weixin.common.util.crypto.SHA1; +import me.chanjar.weixin.open.api.impl.WxOpenInMemoryConfigStorage; +import me.chanjar.weixin.open.util.WxOpenCryptUtil; +import org.testng.annotations.Test; + +import java.io.ByteArrayInputStream; +import java.io.InputStream; +import java.nio.charset.StandardCharsets; +import java.util.regex.Matcher; +import java.util.regex.Pattern; + +import static org.testng.Assert.assertEquals; +import static org.testng.Assert.assertNotNull; +import static org.testng.Assert.assertTrue; + +/** + * {@link WxOpenXmlMessage} 单元测试 + */ +public class WxOpenXmlMessageTest { + + private static final String COMPONENT_APP_ID = "wx0000000000000001"; + private static final String COMPONENT_TOKEN = "test_component_token"; + /** 43 位 EncodingAESKey 占位值,非真实密钥 */ + private static final String COMPONENT_AES_KEY = "MDEyMzQ1Njc4OWFiY2RlZjAxMjM0NTY3ODlhYmNkZWY"; + + private static final Pattern ENCRYPT_PATTERN = Pattern.compile(""); + private static final Pattern TIMESTAMP_PATTERN = Pattern.compile("(.*?)"); + private static final Pattern NONCE_PATTERN = Pattern.compile(""); + + private static final String VERIFY_TICKET_XML = "\n" + + " \n" + + " 1413192605\n" + + " \n" + + " \n" + + ""; + + private WxOpenInMemoryConfigStorage config() { + WxOpenInMemoryConfigStorage config = new WxOpenInMemoryConfigStorage(); + config.setComponentAppId(COMPONENT_APP_ID); + config.setComponentToken(COMPONENT_TOKEN); + config.setComponentAesKey(COMPONENT_AES_KEY); + return config; + } + + private String group(Pattern pattern, String text) { + Matcher matcher = pattern.matcher(text); + assertTrue(matcher.find(), "未匹配到期望的节点:" + pattern.pattern()); + return matcher.group(1); + } + + @Test + public void testFromXmlComponentVerifyTicket() { + WxOpenXmlMessage message = WxOpenXmlMessage.fromXml(VERIFY_TICKET_XML); + assertNotNull(message); + assertEquals(message.getAppId(), COMPONENT_APP_ID); + assertEquals(message.getCreateTime(), Long.valueOf(1413192605L)); + assertEquals(message.getInfoType(), "component_verify_ticket"); + assertEquals(message.getComponentVerifyTicket(), "ticket@@@abcdefg"); + } + + @Test + public void testFromXmlAuthorized() { + String xml = "\n" + + " \n" + + " 1413192760\n" + + " \n" + + " \n" + + " \n" + + " 600\n" + + " \n" + + ""; + + WxOpenXmlMessage message = WxOpenXmlMessage.fromXml(xml); + assertNotNull(message); + assertEquals(message.getInfoType(), "authorized"); + assertEquals(message.getAuthorizerAppid(), "wx0000000000000002"); + assertEquals(message.getAuthorizationCode(), "auth_code_value"); + assertEquals(message.getAuthorizationCodeExpiredTime(), Long.valueOf(600L)); + assertEquals(message.getPreAuthCode(), "pre_auth_code_value"); + } + + @Test + public void testFromXmlFastRegisterWeApp() { + String xml = "\n" + + " \n" + + " 1535442403\n" + + " \n" + + " wx0000000000000003\n" + + " 0\n" + + " auth_code_value\n" + + " \n" + + " \n" + + " \n" + + " \n" + + ""; + + WxOpenXmlMessage message = WxOpenXmlMessage.fromXml(xml); + assertNotNull(message); + assertEquals(message.getSubAppId(), "wx0000000000000003"); + assertEquals(message.getRegistAppId(), "wx0000000000000003"); + assertEquals(message.getStatus(), 0); + assertEquals(message.getAuthCode(), "auth_code_value"); + assertEquals(message.getMsg(), "OK"); + assertNotNull(message.getInfo()); + assertEquals(message.getInfo().getName(), "тест"); + } + + @Test + public void testFromXmlInputStream() { + InputStream is = new ByteArrayInputStream(VERIFY_TICKET_XML.getBytes(StandardCharsets.UTF_8)); + WxOpenXmlMessage message = WxOpenXmlMessage.fromXml(is); + assertNotNull(message); + assertEquals(message.getComponentVerifyTicket(), "ticket@@@abcdefg"); + } + + @Test + public void testFromEncryptedXml() { + WxOpenInMemoryConfigStorage config = config(); + String encryptedXml = new WxOpenCryptUtil(config).encrypt(VERIFY_TICKET_XML); + + String encrypt = group(ENCRYPT_PATTERN, encryptedXml); + String timestamp = group(TIMESTAMP_PATTERN, encryptedXml); + String nonce = group(NONCE_PATTERN, encryptedXml); + String signature = SHA1.gen(COMPONENT_TOKEN, timestamp, nonce, encrypt); + + WxOpenXmlMessage message = WxOpenXmlMessage.fromEncryptedXml(encryptedXml, config, timestamp, nonce, signature); + assertNotNull(message); + assertEquals(message.getComponentVerifyTicket(), "ticket@@@abcdefg"); + assertEquals(message.getContext(), VERIFY_TICKET_XML); + + InputStream is = new ByteArrayInputStream(encryptedXml.getBytes(StandardCharsets.UTF_8)); + WxOpenXmlMessage fromStream = WxOpenXmlMessage.fromEncryptedXml(is, config, timestamp, nonce, signature); + assertNotNull(fromStream); + assertEquals(fromStream.getInfoType(), "component_verify_ticket"); + } +} diff --git a/weixin-java-open/src/test/java/me/chanjar/weixin/open/util/WxOpenCryptUtilTest.java b/weixin-java-open/src/test/java/me/chanjar/weixin/open/util/WxOpenCryptUtilTest.java new file mode 100644 index 0000000000..d6135d6044 --- /dev/null +++ b/weixin-java-open/src/test/java/me/chanjar/weixin/open/util/WxOpenCryptUtilTest.java @@ -0,0 +1,87 @@ +package me.chanjar.weixin.open.util; + +import me.chanjar.weixin.common.error.WxRuntimeException; +import me.chanjar.weixin.common.util.crypto.SHA1; +import me.chanjar.weixin.open.api.impl.WxOpenInMemoryConfigStorage; +import org.testng.annotations.Test; + +import java.util.regex.Matcher; +import java.util.regex.Pattern; + +import static org.testng.Assert.assertEquals; +import static org.testng.Assert.assertNotNull; +import static org.testng.Assert.assertTrue; +import static org.testng.Assert.expectThrows; + +/** + * {@link WxOpenCryptUtil} 单元测试 + */ +public class WxOpenCryptUtilTest { + + private static final String COMPONENT_APP_ID = "wx0000000000000001"; + private static final String COMPONENT_TOKEN = "test_component_token"; + /** 43 位 EncodingAESKey 占位值,非真实密钥 */ + private static final String COMPONENT_AES_KEY = "MDEyMzQ1Njc4OWFiY2RlZjAxMjM0NTY3ODlhYmNkZWY"; + + private static final Pattern ENCRYPT_PATTERN = Pattern.compile(""); + private static final Pattern SIGNATURE_PATTERN = + Pattern.compile(""); + private static final Pattern TIMESTAMP_PATTERN = Pattern.compile("(.*?)"); + private static final Pattern NONCE_PATTERN = Pattern.compile(""); + + private WxOpenInMemoryConfigStorage config(String aesKey) { + WxOpenInMemoryConfigStorage config = new WxOpenInMemoryConfigStorage(); + config.setComponentAppId(COMPONENT_APP_ID); + config.setComponentToken(COMPONENT_TOKEN); + config.setComponentAesKey(aesKey); + return config; + } + + private String group(Pattern pattern, String text) { + Matcher matcher = pattern.matcher(text); + assertTrue(matcher.find(), "未匹配到期望的节点:" + pattern.pattern()); + return matcher.group(1); + } + + @Test + public void testEncryptThenDecrypt() { + WxOpenCryptUtil cryptUtil = new WxOpenCryptUtil(config(COMPONENT_AES_KEY)); + String plainText = "" + + ""; + + String encryptedXml = cryptUtil.encrypt(plainText); + assertNotNull(encryptedXml); + + String encrypt = group(ENCRYPT_PATTERN, encryptedXml); + String signature = group(SIGNATURE_PATTERN, encryptedXml); + String timestamp = group(TIMESTAMP_PATTERN, encryptedXml); + String nonce = group(NONCE_PATTERN, encryptedXml); + + assertEquals(signature, SHA1.gen(COMPONENT_TOKEN, timestamp, nonce, encrypt)); + assertEquals(cryptUtil.decryptXml(signature, timestamp, nonce, encryptedXml), plainText); + assertEquals(cryptUtil.decryptContent(signature, timestamp, nonce, encrypt), plainText); + } + + @Test + public void testDecryptWithWrongSignature() { + WxOpenCryptUtil cryptUtil = new WxOpenCryptUtil(config(COMPONENT_AES_KEY)); + String encryptedXml = cryptUtil.encrypt(""); + + String timestamp = group(TIMESTAMP_PATTERN, encryptedXml); + String nonce = group(NONCE_PATTERN, encryptedXml); + + expectThrows(WxRuntimeException.class, + () -> cryptUtil.decryptXml("wrong_signature", timestamp, nonce, encryptedXml)); + } + + @Test + public void testAesKeyWithSpaces() { + String plainText = ""; + WxOpenCryptUtil cryptUtil = new WxOpenCryptUtil(config(COMPONENT_AES_KEY)); + WxOpenCryptUtil cryptUtilWithSpaces = new WxOpenCryptUtil( + config(" " + COMPONENT_AES_KEY.substring(0, 10) + " " + COMPONENT_AES_KEY.substring(10) + " ")); + + String randomStr = "1234567890123456"; + assertEquals(cryptUtilWithSpaces.encrypt(randomStr, plainText), cryptUtil.encrypt(randomStr, plainText)); + } +} diff --git a/weixin-java-open/src/test/java/me/chanjar/weixin/open/util/json/WxOpenGsonBuilderTest.java b/weixin-java-open/src/test/java/me/chanjar/weixin/open/util/json/WxOpenGsonBuilderTest.java new file mode 100644 index 0000000000..c8ead8c09d --- /dev/null +++ b/weixin-java-open/src/test/java/me/chanjar/weixin/open/util/json/WxOpenGsonBuilderTest.java @@ -0,0 +1,92 @@ +package me.chanjar.weixin.open.util.json; + +import com.google.gson.Gson; +import me.chanjar.weixin.open.bean.WxOpenAuthorizerAccessToken; +import me.chanjar.weixin.open.bean.WxOpenComponentAccessToken; +import me.chanjar.weixin.open.bean.auth.WxOpenAuthorizationInfo; +import me.chanjar.weixin.open.bean.result.WxOpenQueryAuthResult; +import org.testng.annotations.Test; + +import java.util.Arrays; + +import static org.testng.Assert.assertEquals; +import static org.testng.Assert.assertNotNull; +import static org.testng.Assert.assertSame; +import static org.testng.Assert.assertTrue; + +/** + * {@link WxOpenGsonBuilder} 及其注册的反序列化适配器单元测试 + */ +public class WxOpenGsonBuilderTest { + + @Test + public void testCreateReturnsSameInstance() { + assertSame(WxOpenGsonBuilder.create(), WxOpenGsonBuilder.create()); + } + + @Test + public void testComponentAccessToken() { + String json = "{\"component_access_token\":\"component_access_token_value\",\"expires_in\":7200}"; + WxOpenComponentAccessToken token = WxOpenGsonBuilder.create().fromJson(json, WxOpenComponentAccessToken.class); + assertNotNull(token); + assertEquals(token.getComponentAccessToken(), "component_access_token_value"); + assertEquals(token.getExpiresIn(), 7200); + } + + @Test + public void testAuthorizerAccessToken() { + String json = "{\"authorizer_access_token\":\"access_token_value\"," + + "\"authorizer_refresh_token\":\"refresh_token_value\",\"expires_in\":7200}"; + WxOpenAuthorizerAccessToken token = WxOpenGsonBuilder.create().fromJson(json, WxOpenAuthorizerAccessToken.class); + assertNotNull(token); + assertEquals(token.getAuthorizerAccessToken(), "access_token_value"); + assertEquals(token.getAuthorizerRefreshToken(), "refresh_token_value"); + assertEquals(token.getExpiresIn(), 7200); + } + + @Test + public void testAuthorizationInfo() { + String json = "{\"authorizer_appid\":\"wx0000000000000002\"," + + "\"authorizer_access_token\":\"access_token_value\"," + + "\"authorizer_refresh_token\":\"refresh_token_value\"," + + "\"expires_in\":7200," + + "\"func_info\":[{\"funcscope_category\":{\"id\":1}},{\"funcscope_category\":{\"id\":15}},{}]}"; + + WxOpenAuthorizationInfo info = WxOpenGsonBuilder.create().fromJson(json, WxOpenAuthorizationInfo.class); + assertNotNull(info); + assertEquals(info.getAuthorizerAppid(), "wx0000000000000002"); + assertEquals(info.getAuthorizerAccessToken(), "access_token_value"); + assertEquals(info.getAuthorizerRefreshToken(), "refresh_token_value"); + assertEquals(info.getExpiresIn(), 7200); + assertEquals(info.getFuncInfo(), Arrays.asList(1, 15)); + } + + @Test + public void testAuthorizationInfoWithoutFuncInfo() { + WxOpenAuthorizationInfo info = WxOpenGsonBuilder.create() + .fromJson("{\"authorizer_appid\":\"wx0000000000000002\"}", WxOpenAuthorizationInfo.class); + assertNotNull(info); + assertNotNull(info.getFuncInfo()); + assertTrue(info.getFuncInfo().isEmpty()); + } + + @Test + public void testQueryAuthResult() { + String json = "{\"authorization_info\":{\"authorizer_appid\":\"wx0000000000000002\"," + + "\"authorizer_access_token\":\"access_token_value\",\"expires_in\":7200," + + "\"authorizer_refresh_token\":\"refresh_token_value\"," + + "\"func_info\":[{\"funcscope_category\":{\"id\":1}}]}}"; + + WxOpenQueryAuthResult result = WxOpenGsonBuilder.create().fromJson(json, WxOpenQueryAuthResult.class); + assertNotNull(result); + assertNotNull(result.getAuthorizationInfo()); + assertEquals(result.getAuthorizationInfo().getAuthorizerAppid(), "wx0000000000000002"); + assertEquals(result.getAuthorizationInfo().getFuncInfo(), Arrays.asList(1)); + } + + @Test + public void testHtmlEscapingDisabled() { + Gson gson = WxOpenGsonBuilder.create(); + assertEquals(gson.toJson("a&b"), "\"a&b\""); + } +} From 75f347ce0794bfc39db04ae785e2e26e6ca5e717 Mon Sep 17 00:00:00 2001 From: Binary Wang Date: Fri, 31 Jul 2026 03:50:40 +0000 Subject: [PATCH 2/3] =?UTF-8?q?test:=20=E5=B0=86=E6=96=B0=E5=A2=9E?= =?UTF-8?q?=E5=8D=95=E5=85=83=E6=B5=8B=E8=AF=95=E5=8A=A0=E5=85=A5=E4=B8=A4?= =?UTF-8?q?=E4=B8=AA=E6=A8=A1=E5=9D=97=E7=9A=84=20testng.xml=20suite?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Co-Authored-By: Devin AI <158243242+devin-ai-integration[bot]@users.noreply.github.com> --- weixin-java-channel/src/test/resources/testng.xml | 8 ++++++++ weixin-java-open/src/test/resources/testng.xml | 7 +++++++ 2 files changed, 15 insertions(+) diff --git a/weixin-java-channel/src/test/resources/testng.xml b/weixin-java-channel/src/test/resources/testng.xml index afa0aa32f2..819ebcf5f9 100644 --- a/weixin-java-channel/src/test/resources/testng.xml +++ b/weixin-java-channel/src/test/resources/testng.xml @@ -8,4 +8,12 @@ --> + + + + + + + + diff --git a/weixin-java-open/src/test/resources/testng.xml b/weixin-java-open/src/test/resources/testng.xml index 8ade76f3e3..4fc5e6b52e 100644 --- a/weixin-java-open/src/test/resources/testng.xml +++ b/weixin-java-open/src/test/resources/testng.xml @@ -8,4 +8,11 @@ + + + + + + + From 4e761a2e4677aa3d289d8109f9c8a260fc5156c8 Mon Sep 17 00:00:00 2001 From: Binary Wang Date: Fri, 31 Jul 2026 15:41:29 +0000 Subject: [PATCH 3/3] =?UTF-8?q?fix(open):=20=E4=BF=AE=E5=A4=8D=20WxFastMaC?= =?UTF-8?q?anSetCategoryResult=20=E4=B8=8E=E7=88=B6=E7=B1=BB=20errcode=20?= =?UTF-8?q?=E5=AD=97=E6=AE=B5=E5=86=B2=E7=AA=81=E5=AF=BC=E8=87=B4=E7=9A=84?= =?UTF-8?q?=20Gson=20=E5=8F=8D=E5=BA=8F=E5=88=97=E5=8C=96=E5=BC=82?= =?UTF-8?q?=E5=B8=B8?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Co-Authored-By: Devin AI <158243242+devin-ai-integration[bot]@users.noreply.github.com> --- .../result/WxFastMaCanSetCategoryResult.java | 23 +++++++++++++++++-- .../WxFastMaCanSetCategoryResultTest.java | 6 +++++ 2 files changed, 27 insertions(+), 2 deletions(-) diff --git a/weixin-java-open/src/main/java/me/chanjar/weixin/open/bean/result/WxFastMaCanSetCategoryResult.java b/weixin-java-open/src/main/java/me/chanjar/weixin/open/bean/result/WxFastMaCanSetCategoryResult.java index b3d0dd9d94..18e885d671 100644 --- a/weixin-java-open/src/main/java/me/chanjar/weixin/open/bean/result/WxFastMaCanSetCategoryResult.java +++ b/weixin-java-open/src/main/java/me/chanjar/weixin/open/bean/result/WxFastMaCanSetCategoryResult.java @@ -3,6 +3,7 @@ import com.google.gson.annotations.SerializedName; import lombok.Data; import lombok.EqualsAndHashCode; +import org.apache.commons.lang3.math.NumberUtils; import java.util.List; @@ -16,11 +17,29 @@ @EqualsAndHashCode(callSuper = false) public class WxFastMaCanSetCategoryResult extends WxOpenResult { private static final long serialVersionUID = -2469386233538980102L; - @SerializedName("errcode") - private int errCode; @SerializedName("categories_list") private CategoriesListBean categoriesList; + /** + * 错误码,已弃用,未来将删除 + * + * @see WxOpenResult#getErrcode() 应使用此方法 + */ + @Deprecated + public int getErrCode() { + return NumberUtils.toInt(this.errcode); + } + + /** + * 错误码,已弃用,未来将删除 + * + * @see WxOpenResult#setErrcode(String) 应使用此方法 + */ + @Deprecated + public void setErrCode(int errCode) { + this.errcode = String.valueOf(errCode); + } + @Data public static class CategoriesListBean { private List categories; diff --git a/weixin-java-open/src/test/java/me/chanjar/weixin/open/bean/result/WxFastMaCanSetCategoryResultTest.java b/weixin-java-open/src/test/java/me/chanjar/weixin/open/bean/result/WxFastMaCanSetCategoryResultTest.java index 11ae649699..aa9f86722d 100644 --- a/weixin-java-open/src/test/java/me/chanjar/weixin/open/bean/result/WxFastMaCanSetCategoryResultTest.java +++ b/weixin-java-open/src/test/java/me/chanjar/weixin/open/bean/result/WxFastMaCanSetCategoryResultTest.java @@ -3,7 +3,9 @@ import me.chanjar.weixin.open.util.json.WxOpenGsonBuilder; import org.testng.annotations.Test; +import static org.testng.Assert.assertEquals; import static org.testng.Assert.assertNotNull; +import static org.testng.Assert.assertTrue; public class WxFastMaCanSetCategoryResultTest { @@ -73,6 +75,10 @@ public void testFromJson() throws Exception { assertNotNull(res); assertNotNull(res.getCategoriesList()); + assertEquals(res.getErrcode(), "0"); + assertEquals(res.getErrmsg(), "ok"); + assertEquals(res.getErrCode(), 0); + assertTrue(res.isSuccess()); System.out.println(res); }