From 9b9b2f61d5578e0208af43d0efce9cfbdd423247 Mon Sep 17 00:00:00 2001 From: "copilot-swe-agent[bot]" <198982749+Copilot@users.noreply.github.com> Date: Thu, 24 Jul 2025 08:12:52 +0000 Subject: [PATCH] Complete v3 raw JSON preservation implementation with comprehensive tests Co-authored-by: binarywang <1343140+binarywang@users.noreply.github.com> --- .../bean/marketing/FavorCouponsGetResult.java | 3 +- .../impl/MarketingFavorServiceImpl.java | 4 +- .../marketing/FavorStocksGetResultTest.java | 87 +++++++++++++++++++ 3 files changed, 92 insertions(+), 2 deletions(-) diff --git a/weixin-java-pay/src/main/java/com/github/binarywang/wxpay/bean/marketing/FavorCouponsGetResult.java b/weixin-java-pay/src/main/java/com/github/binarywang/wxpay/bean/marketing/FavorCouponsGetResult.java index f8f342de1..6f1824f64 100644 --- a/weixin-java-pay/src/main/java/com/github/binarywang/wxpay/bean/marketing/FavorCouponsGetResult.java +++ b/weixin-java-pay/src/main/java/com/github/binarywang/wxpay/bean/marketing/FavorCouponsGetResult.java @@ -1,5 +1,6 @@ package com.github.binarywang.wxpay.bean.marketing; +import com.github.binarywang.wxpay.bean.result.BaseWxPayV3Result; import com.google.gson.annotations.SerializedName; import lombok.Data; import lombok.NoArgsConstructor; @@ -13,7 +14,7 @@ import java.io.Serializable; */ @NoArgsConstructor @Data -public class FavorCouponsGetResult implements Serializable { +public class FavorCouponsGetResult extends BaseWxPayV3Result { private static final long serialVersionUID = 1L; diff --git a/weixin-java-pay/src/main/java/com/github/binarywang/wxpay/service/impl/MarketingFavorServiceImpl.java b/weixin-java-pay/src/main/java/com/github/binarywang/wxpay/service/impl/MarketingFavorServiceImpl.java index 8ebd47f9a..0f84d5f12 100644 --- a/weixin-java-pay/src/main/java/com/github/binarywang/wxpay/service/impl/MarketingFavorServiceImpl.java +++ b/weixin-java-pay/src/main/java/com/github/binarywang/wxpay/service/impl/MarketingFavorServiceImpl.java @@ -87,7 +87,9 @@ public class MarketingFavorServiceImpl implements MarketingFavorService { String url = String.format("%s/v3/marketing/favor/users/%s/coupons/%s", this.payService.getPayBaseUrl(), openid, couponId); String query = String.format("?appid=%s", appid); String result = this.payService.getV3(url + query); - return GSON.fromJson(result, FavorCouponsGetResult.class); + FavorCouponsGetResult favorCouponsGetResult = GSON.fromJson(result, FavorCouponsGetResult.class); + favorCouponsGetResult.setRawJsonString(result); + return favorCouponsGetResult; } @Override diff --git a/weixin-java-pay/src/test/java/com/github/binarywang/wxpay/bean/marketing/FavorStocksGetResultTest.java b/weixin-java-pay/src/test/java/com/github/binarywang/wxpay/bean/marketing/FavorStocksGetResultTest.java index 50156ccfc..ed3941383 100644 --- a/weixin-java-pay/src/test/java/com/github/binarywang/wxpay/bean/marketing/FavorStocksGetResultTest.java +++ b/weixin-java-pay/src/test/java/com/github/binarywang/wxpay/bean/marketing/FavorStocksGetResultTest.java @@ -3,6 +3,8 @@ package com.github.binarywang.wxpay.bean.marketing; import com.github.binarywang.wxpay.bean.result.BaseWxPayV3Result; import com.google.gson.Gson; import com.google.gson.GsonBuilder; +import com.google.gson.JsonElement; +import com.google.gson.JsonParser; import org.testng.annotations.Test; import static org.testng.Assert.*; @@ -74,4 +76,89 @@ public class FavorStocksGetResultTest { result.setRawJsonString(null); assertNull(result.getRawJsonString()); } + + @Test + public void testRealWorldUsagePattern() { + // 实际使用场景的示例 + String realApiResponse = "{\n" + + " \"stock_id\": \"9836588\",\n" + + " \"stock_creator_mchid\": \"1230000109\",\n" + + " \"stock_name\": \"微信支付代金券\",\n" + + " \"status\": \"running\",\n" + + " \"create_time\": \"2021-01-01T00:00:00.000+08:00\",\n" + + " \"description\": \"微信支付营销\",\n" + + " \"card_id\": \"pFS7Fjg9kqcMOBtl3bFn\",\n" + + " \"future_field_1\": \"未来可能新增的字段1\",\n" + + " \"future_field_2\": \"未来可能新增的字段2\"\n" + + "}"; + + FavorStocksGetResult result = GSON.fromJson(realApiResponse, FavorStocksGetResult.class); + result.setRawJsonString(realApiResponse); + + // 1. 正常使用已定义的字段 + assertEquals(result.getStockId(), "9836588"); + assertEquals(result.getStockName(), "微信支付代金券"); + + // 2. 安全地获取可能存在的新字段 + String cardId = getStringFieldSafely(result, "card_id"); + assertEquals(cardId, "pFS7Fjg9kqcMOBtl3bFn"); + + // 3. 获取未来可能新增的字段 + String futureField1 = getStringFieldSafely(result, "future_field_1"); + assertEquals(futureField1, "未来可能新增的字段1"); + + String nonExistentField = getStringFieldSafely(result, "non_existent"); + assertNull(nonExistentField); + } + + @Test + public void testCardIdExtractionExample() { + // 测试具体的card_id字段提取(这是issue中提到的用例) + String apiResponseWithCardId = "{\n" + + " \"stock_id\": \"9836588\",\n" + + " \"stock_creator_mchid\": \"1230000109\",\n" + + " \"stock_name\": \"微信支付代金券\",\n" + + " \"status\": \"running\",\n" + + " \"card_id\": \"pFS7Fjg9kqcMOBtl3bFn\"\n" + + "}"; + + FavorStocksGetResult result = GSON.fromJson(apiResponseWithCardId, FavorStocksGetResult.class); + result.setRawJsonString(apiResponseWithCardId); + + // 验证可以获取card_id字段 + JsonElement jsonElement = JsonParser.parseString(result.getRawJsonString()); + assertTrue(jsonElement.getAsJsonObject().has("card_id")); + String cardId = jsonElement.getAsJsonObject().get("card_id").getAsString(); + assertEquals(cardId, "pFS7Fjg9kqcMOBtl3bFn"); + + // 展示实际用法 + String extractedCardId = extractCardId(result); + assertEquals(extractedCardId, "pFS7Fjg9kqcMOBtl3bFn"); + } + + /** + * 提取card_id的示例方法 + */ + private String extractCardId(FavorStocksGetResult result) { + return getStringFieldSafely(result, "card_id"); + } + + /** + * 安全地从结果中获取字符串字段的工具方法 + */ + private String getStringFieldSafely(BaseWxPayV3Result result, String fieldName) { + String rawJson = result.getRawJsonString(); + if (rawJson == null) return null; + + try { + JsonElement jsonElement = JsonParser.parseString(rawJson); + if (jsonElement.getAsJsonObject().has(fieldName)) { + JsonElement fieldElement = jsonElement.getAsJsonObject().get(fieldName); + return fieldElement.isJsonNull() ? null : fieldElement.getAsString(); + } + } catch (Exception e) { + // 解析失败时返回null + } + return null; + } } \ No newline at end of file