Skip to content

Commit 983e4f1

Browse files
authored
🎨 #3659 【微信支付】新增BaseWxPayV3Result基类,提供rawJsonString字段保存原始API响应
1 parent 7ffc1b3 commit 983e4f1

File tree

6 files changed

+221
-6
lines changed

6 files changed

+221
-6
lines changed

weixin-java-pay/src/main/java/com/github/binarywang/wxpay/bean/marketing/FavorCouponsGetResult.java

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,6 @@
11
package com.github.binarywang.wxpay.bean.marketing;
22

3+
import com.github.binarywang.wxpay.bean.result.BaseWxPayV3Result;
34
import com.google.gson.annotations.SerializedName;
45
import lombok.Data;
56
import lombok.NoArgsConstructor;
@@ -13,7 +14,7 @@
1314
*/
1415
@NoArgsConstructor
1516
@Data
16-
public class FavorCouponsGetResult implements Serializable {
17+
public class FavorCouponsGetResult extends BaseWxPayV3Result {
1718

1819
private static final long serialVersionUID = 1L;
1920

weixin-java-pay/src/main/java/com/github/binarywang/wxpay/bean/marketing/FavorStocksCreateResult.java

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,6 @@
11
package com.github.binarywang.wxpay.bean.marketing;
22

3+
import com.github.binarywang.wxpay.bean.result.BaseWxPayV3Result;
34
import com.google.gson.annotations.SerializedName;
45
import lombok.Data;
56
import lombok.NoArgsConstructor;
@@ -13,7 +14,7 @@
1314
*/
1415
@NoArgsConstructor
1516
@Data
16-
public class FavorStocksCreateResult implements Serializable {
17+
public class FavorStocksCreateResult extends BaseWxPayV3Result {
1718

1819
private static final long serialVersionUID = 1L;
1920

weixin-java-pay/src/main/java/com/github/binarywang/wxpay/bean/marketing/FavorStocksGetResult.java

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,6 @@
11
package com.github.binarywang.wxpay.bean.marketing;
22

3+
import com.github.binarywang.wxpay.bean.result.BaseWxPayV3Result;
34
import com.google.gson.annotations.SerializedName;
45
import lombok.Data;
56
import lombok.NoArgsConstructor;
@@ -14,7 +15,7 @@
1415
*/
1516
@NoArgsConstructor
1617
@Data
17-
public class FavorStocksGetResult implements Serializable {
18+
public class FavorStocksGetResult extends BaseWxPayV3Result {
1819

1920
private static final long serialVersionUID = 1L;
2021

Lines changed: 42 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,42 @@
1+
package com.github.binarywang.wxpay.bean.result;
2+
3+
import lombok.Data;
4+
5+
import java.io.Serializable;
6+
7+
/**
8+
* <pre>
9+
* 微信支付v3结果共用属性类.
10+
* 用于保存原始JSON响应内容,便于访问API返回的新增字段.
11+
* </pre>
12+
*
13+
* @author Binary Wang
14+
*/
15+
@Data
16+
public abstract class BaseWxPayV3Result implements Serializable {
17+
private static final long serialVersionUID = 1L;
18+
19+
/**
20+
* 原始JSON字符串.
21+
* 保存微信支付v3 API返回的原始JSON内容,便于访问未在Result类中定义的字段.
22+
*/
23+
private String rawJsonString;
24+
25+
/**
26+
* 获取原始JSON响应内容.
27+
*
28+
* @return 原始JSON字符串
29+
*/
30+
public String getRawJsonString() {
31+
return rawJsonString;
32+
}
33+
34+
/**
35+
* 设置原始JSON响应内容.
36+
*
37+
* @param rawJsonString 原始JSON字符串
38+
*/
39+
public void setRawJsonString(String rawJsonString) {
40+
this.rawJsonString = rawJsonString;
41+
}
42+
}

weixin-java-pay/src/main/java/com/github/binarywang/wxpay/service/impl/MarketingFavorServiceImpl.java

Lines changed: 9 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -34,7 +34,9 @@ public FavorStocksCreateResult createFavorStocksV3(FavorStocksCreateRequest requ
3434
String url = String.format("%s/v3/marketing/favor/coupon-stocks", this.payService.getPayBaseUrl());
3535
RsaCryptoUtil.encryptFields(request, this.payService.getConfig().getVerifier().getValidCertificate());
3636
String result = this.payService.postV3WithWechatpaySerial(url, GSON.toJson(request));
37-
return GSON.fromJson(result, FavorStocksCreateResult.class);
37+
FavorStocksCreateResult favorStocksCreateResult = GSON.fromJson(result, FavorStocksCreateResult.class);
38+
favorStocksCreateResult.setRawJsonString(result);
39+
return favorStocksCreateResult;
3840
}
3941

4042
@Override
@@ -75,15 +77,19 @@ public FavorStocksGetResult getFavorStocksV3(String stockId, String stockCreator
7577
String url = String.format("%s/v3/marketing/favor/stocks/%s", this.payService.getPayBaseUrl(), stockId);
7678
String query = String.format("?stock_creator_mchid=%s", stockCreatorMchid);
7779
String result = this.payService.getV3(url + query);
78-
return GSON.fromJson(result, FavorStocksGetResult.class);
80+
FavorStocksGetResult favorStocksGetResult = GSON.fromJson(result, FavorStocksGetResult.class);
81+
favorStocksGetResult.setRawJsonString(result);
82+
return favorStocksGetResult;
7983
}
8084

8185
@Override
8286
public FavorCouponsGetResult getFavorCouponsV3(String couponId, String appid, String openid) throws WxPayException {
8387
String url = String.format("%s/v3/marketing/favor/users/%s/coupons/%s", this.payService.getPayBaseUrl(), openid, couponId);
8488
String query = String.format("?appid=%s", appid);
8589
String result = this.payService.getV3(url + query);
86-
return GSON.fromJson(result, FavorCouponsGetResult.class);
90+
FavorCouponsGetResult favorCouponsGetResult = GSON.fromJson(result, FavorCouponsGetResult.class);
91+
favorCouponsGetResult.setRawJsonString(result);
92+
return favorCouponsGetResult;
8793
}
8894

8995
@Override
Lines changed: 164 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,164 @@
1+
package com.github.binarywang.wxpay.bean.marketing;
2+
3+
import com.github.binarywang.wxpay.bean.result.BaseWxPayV3Result;
4+
import com.google.gson.Gson;
5+
import com.google.gson.GsonBuilder;
6+
import com.google.gson.JsonElement;
7+
import com.google.gson.JsonParser;
8+
import org.testng.annotations.Test;
9+
10+
import static org.testng.Assert.*;
11+
12+
/**
13+
* 测试FavorStocksGetResult的原始JSON保存功能
14+
*
15+
* @author Binary Wang
16+
*/
17+
public class FavorStocksGetResultTest {
18+
19+
private static final Gson GSON = new GsonBuilder().create();
20+
21+
@Test
22+
public void testRawJsonPreservation() {
23+
// 模拟微信API返回的JSON(包含未在Result类中定义的字段)
24+
String mockJson = "{\n" +
25+
" \"stock_id\": \"9836588\",\n" +
26+
" \"stock_creator_mchid\": \"1230000109\",\n" +
27+
" \"stock_name\": \"微信支付代金券\",\n" +
28+
" \"status\": \"running\",\n" +
29+
" \"create_time\": \"2021-01-01T00:00:00.000+08:00\",\n" +
30+
" \"description\": \"微信支付营销\",\n" +
31+
" \"card_id\": \"pFS7Fjg9kqcMOBtl3bFn\",\n" +
32+
" \"extra_field\": \"这是一个新增字段\"\n" +
33+
"}";
34+
35+
// 模拟服务调用:反序列化JSON
36+
FavorStocksGetResult result = GSON.fromJson(mockJson, FavorStocksGetResult.class);
37+
38+
// 模拟服务调用:设置原始JSON
39+
result.setRawJsonString(mockJson);
40+
41+
// 验证基本字段正常解析
42+
assertEquals(result.getStockId(), "9836588");
43+
assertEquals(result.getStockCreatorMchId(), "1230000109");
44+
assertEquals(result.getStockName(), "微信支付代金券");
45+
assertEquals(result.getStatus(), "running");
46+
47+
// 验证原始JSON被保存
48+
assertNotNull(result.getRawJsonString());
49+
assertEquals(result.getRawJsonString(), mockJson);
50+
51+
// 验证可以从原始JSON中获取未定义的字段
52+
assertTrue(result.getRawJsonString().contains("\"card_id\": \"pFS7Fjg9kqcMOBtl3bFn\""));
53+
assertTrue(result.getRawJsonString().contains("\"extra_field\": \"这是一个新增字段\""));
54+
}
55+
56+
@Test
57+
public void testBaseV3ResultInheritance() {
58+
FavorStocksGetResult result = new FavorStocksGetResult();
59+
60+
// 验证继承关系
61+
assertTrue(result instanceof BaseWxPayV3Result);
62+
63+
// 验证基类方法可用
64+
result.setRawJsonString("test json");
65+
assertEquals(result.getRawJsonString(), "test json");
66+
}
67+
68+
@Test
69+
public void testNullRawJson() {
70+
FavorStocksGetResult result = new FavorStocksGetResult();
71+
72+
// 验证初始状态下rawJsonString为null
73+
assertNull(result.getRawJsonString());
74+
75+
// 验证设置null不会出错
76+
result.setRawJsonString(null);
77+
assertNull(result.getRawJsonString());
78+
}
79+
80+
@Test
81+
public void testRealWorldUsagePattern() {
82+
// 实际使用场景的示例
83+
String realApiResponse = "{\n" +
84+
" \"stock_id\": \"9836588\",\n" +
85+
" \"stock_creator_mchid\": \"1230000109\",\n" +
86+
" \"stock_name\": \"微信支付代金券\",\n" +
87+
" \"status\": \"running\",\n" +
88+
" \"create_time\": \"2021-01-01T00:00:00.000+08:00\",\n" +
89+
" \"description\": \"微信支付营销\",\n" +
90+
" \"card_id\": \"pFS7Fjg9kqcMOBtl3bFn\",\n" +
91+
" \"future_field_1\": \"未来可能新增的字段1\",\n" +
92+
" \"future_field_2\": \"未来可能新增的字段2\"\n" +
93+
"}";
94+
95+
FavorStocksGetResult result = GSON.fromJson(realApiResponse, FavorStocksGetResult.class);
96+
result.setRawJsonString(realApiResponse);
97+
98+
// 1. 正常使用已定义的字段
99+
assertEquals(result.getStockId(), "9836588");
100+
assertEquals(result.getStockName(), "微信支付代金券");
101+
102+
// 2. 安全地获取可能存在的新字段
103+
String cardId = getStringFieldSafely(result, "card_id");
104+
assertEquals(cardId, "pFS7Fjg9kqcMOBtl3bFn");
105+
106+
// 3. 获取未来可能新增的字段
107+
String futureField1 = getStringFieldSafely(result, "future_field_1");
108+
assertEquals(futureField1, "未来可能新增的字段1");
109+
110+
String nonExistentField = getStringFieldSafely(result, "non_existent");
111+
assertNull(nonExistentField);
112+
}
113+
114+
@Test
115+
public void testCardIdExtractionExample() {
116+
// 测试具体的card_id字段提取(这是issue中提到的用例)
117+
String apiResponseWithCardId = "{\n" +
118+
" \"stock_id\": \"9836588\",\n" +
119+
" \"stock_creator_mchid\": \"1230000109\",\n" +
120+
" \"stock_name\": \"微信支付代金券\",\n" +
121+
" \"status\": \"running\",\n" +
122+
" \"card_id\": \"pFS7Fjg9kqcMOBtl3bFn\"\n" +
123+
"}";
124+
125+
FavorStocksGetResult result = GSON.fromJson(apiResponseWithCardId, FavorStocksGetResult.class);
126+
result.setRawJsonString(apiResponseWithCardId);
127+
128+
// 验证可以获取card_id字段
129+
JsonElement jsonElement = JsonParser.parseString(result.getRawJsonString());
130+
assertTrue(jsonElement.getAsJsonObject().has("card_id"));
131+
String cardId = jsonElement.getAsJsonObject().get("card_id").getAsString();
132+
assertEquals(cardId, "pFS7Fjg9kqcMOBtl3bFn");
133+
134+
// 展示实际用法
135+
String extractedCardId = extractCardId(result);
136+
assertEquals(extractedCardId, "pFS7Fjg9kqcMOBtl3bFn");
137+
}
138+
139+
/**
140+
* 提取card_id的示例方法
141+
*/
142+
private String extractCardId(FavorStocksGetResult result) {
143+
return getStringFieldSafely(result, "card_id");
144+
}
145+
146+
/**
147+
* 安全地从结果中获取字符串字段的工具方法
148+
*/
149+
private String getStringFieldSafely(BaseWxPayV3Result result, String fieldName) {
150+
String rawJson = result.getRawJsonString();
151+
if (rawJson == null) return null;
152+
153+
try {
154+
JsonElement jsonElement = JsonParser.parseString(rawJson);
155+
if (jsonElement.getAsJsonObject().has(fieldName)) {
156+
JsonElement fieldElement = jsonElement.getAsJsonObject().get(fieldName);
157+
return fieldElement.isJsonNull() ? null : fieldElement.getAsString();
158+
}
159+
} catch (Exception e) {
160+
// 解析失败时返回null
161+
}
162+
return null;
163+
}
164+
}

0 commit comments

Comments
 (0)