|
|
@@ -0,0 +1,377 @@
|
|
|
+package com.payment.platform.module.payment.unified.util;
|
|
|
+
|
|
|
+import com.payment.platform.common.exception.BusinessException;
|
|
|
+import org.junit.jupiter.api.Test;
|
|
|
+import org.junit.jupiter.api.function.Executable;
|
|
|
+
|
|
|
+import java.util.LinkedHashMap;
|
|
|
+import java.util.Map;
|
|
|
+import java.util.Set;
|
|
|
+
|
|
|
+import static org.junit.jupiter.api.Assertions.assertEquals;
|
|
|
+import static org.junit.jupiter.api.Assertions.assertFalse;
|
|
|
+import static org.junit.jupiter.api.Assertions.assertNotNull;
|
|
|
+import static org.junit.jupiter.api.Assertions.assertNull;
|
|
|
+import static org.junit.jupiter.api.Assertions.assertThrows;
|
|
|
+import static org.junit.jupiter.api.Assertions.assertTrue;
|
|
|
+
|
|
|
+/**
|
|
|
+ * {@code channelExtra} 组装与 16 种 {@code wayCode}(spec §4.6 / Task 8 brief,裁定 R19/R32/R33)。
|
|
|
+ *
|
|
|
+ * <p>三条容易写错的边界:
|
|
|
+ * <ul>
|
|
|
+ * <li>spec 表里的「默认 codeUrl/payUrl」是**上游缺省行为**,本组装器不注入默认值(R33①);</li>
|
|
|
+ * <li>{@code payDataType} 只做大小写不敏感匹配并输出规范拼写;未知值丢弃并 warn,**不 400**(R19①);</li>
|
|
|
+ * <li>付款码两个键名都给且值不同 → 400;{@code authCodeKey="both"} 时输出两个键、同一值(R33②)。</li>
|
|
|
+ * </ul>
|
|
|
+ */
|
|
|
+class UnifiedChannelExtraAssemblerTest {
|
|
|
+
|
|
|
+ private static final Set<String> ALL_WAY_CODES = Set.of(
|
|
|
+ "QR_CASHIER", "AUTO_BAR", "ALI_BAR", "ALI_JSAPI", "ALI_APP", "ALI_WAP", "ALI_PC", "ALI_QR",
|
|
|
+ "WX_BAR", "WX_JSAPI", "WX_LITE", "WX_APP", "WX_H5", "WX_NATIVE", "YSF_BAR", "YSF_JSAPI");
|
|
|
+
|
|
|
+ private static final Set<String> BARCODE_WAY_CODES =
|
|
|
+ Set.of("AUTO_BAR", "ALI_BAR", "WX_BAR", "YSF_BAR");
|
|
|
+
|
|
|
+ /** 插入顺序稳定的入参 map;{@code Map.of} 不收 null 值,这里要覆盖 null 场景。 */
|
|
|
+ private static Map<String, Object> extras(Object... pairs) {
|
|
|
+ Map<String, Object> map = new LinkedHashMap<>();
|
|
|
+ for (int i = 0; i < pairs.length; i += 2) {
|
|
|
+ map.put((String) pairs[i], pairs[i + 1]);
|
|
|
+ }
|
|
|
+ return map;
|
|
|
+ }
|
|
|
+
|
|
|
+ private static BusinessException assert400(Executable call) {
|
|
|
+ BusinessException e = assertThrows(BusinessException.class, call);
|
|
|
+ assertEquals(400, e.getCode(), "实测消息: " + e.getMessage());
|
|
|
+ return e;
|
|
|
+ }
|
|
|
+
|
|
|
+ /** 每个 wayCode 的最小合法入参(只有必传项;可选/无参数类给空 map)。 */
|
|
|
+ private static Map<String, Object> minimalExtras(String wayCode) {
|
|
|
+ return switch (wayCode) {
|
|
|
+ case "AUTO_BAR", "ALI_BAR", "WX_BAR", "YSF_BAR" -> extras("auth_code", "123456");
|
|
|
+ case "ALI_JSAPI" -> extras("buyerUserId", "buyer-1");
|
|
|
+ case "WX_JSAPI", "WX_LITE" -> extras("openid", "openid-1");
|
|
|
+ default -> Map.of();
|
|
|
+ };
|
|
|
+ }
|
|
|
+
|
|
|
+ private static boolean producesOutputForMinimalExtras(String wayCode) {
|
|
|
+ return switch (wayCode) {
|
|
|
+ case "AUTO_BAR", "ALI_BAR", "WX_BAR", "YSF_BAR",
|
|
|
+ "ALI_JSAPI", "WX_JSAPI", "WX_LITE" -> true;
|
|
|
+ default -> false;
|
|
|
+ };
|
|
|
+ }
|
|
|
+
|
|
|
+ // ─────────────────────────── wayCode 集合 ───────────────────────────
|
|
|
+
|
|
|
+ @Test
|
|
|
+ void supportedContainsExactlySixteenVerbatimWayCodes() {
|
|
|
+ Set<String> expected = Set.of(
|
|
|
+ "QR_CASHIER", "AUTO_BAR", "ALI_BAR", "ALI_JSAPI", "ALI_APP", "ALI_WAP", "ALI_PC", "ALI_QR",
|
|
|
+ "WX_BAR", "WX_JSAPI", "WX_LITE", "WX_APP", "WX_H5", "WX_NATIVE", "YSF_BAR", "YSF_JSAPI");
|
|
|
+
|
|
|
+ assertEquals(16, expected.size(), "测试自身的期望集合必须是 16 个");
|
|
|
+ assertEquals(16, UnifiedChannelExtraAssembler.SUPPORTED.size(),
|
|
|
+ "实测: " + UnifiedChannelExtraAssembler.SUPPORTED);
|
|
|
+ assertTrue(UnifiedChannelExtraAssembler.SUPPORTED.containsAll(expected),
|
|
|
+ "实测: " + UnifiedChannelExtraAssembler.SUPPORTED);
|
|
|
+ assertFalse(UnifiedChannelExtraAssembler.SUPPORTED.contains("qr_cashier"),
|
|
|
+ "wayCode 逐字大小写敏感,小写不得被接受");
|
|
|
+ }
|
|
|
+
|
|
|
+ @Test
|
|
|
+ void allSixteenWayCodesAcceptedWithMinimalExtras() {
|
|
|
+ for (String wayCode : ALL_WAY_CODES) {
|
|
|
+ UnifiedChannelExtraAssembler.Result result =
|
|
|
+ UnifiedChannelExtraAssembler.assemble(wayCode, minimalExtras(wayCode), "auth_code");
|
|
|
+
|
|
|
+ if (producesOutputForMinimalExtras(wayCode)) {
|
|
|
+ assertNotNull(result.json(), wayCode + " 的必传项已给,应产生 channelExtra");
|
|
|
+ assertNotNull(result.keysCsv(), wayCode);
|
|
|
+ } else {
|
|
|
+ assertNull(result.json(), wayCode + " 没有必传/已给参数,键不应出现");
|
|
|
+ assertNull(result.keysCsv(), wayCode);
|
|
|
+ }
|
|
|
+ }
|
|
|
+ }
|
|
|
+
|
|
|
+ @Test
|
|
|
+ void unknownWayCode_rejected() {
|
|
|
+ for (String wayCode : new String[]{"XX", "qr_cashier", "", null}) {
|
|
|
+ BusinessException e = assert400(
|
|
|
+ () -> UnifiedChannelExtraAssembler.assemble(wayCode, Map.of(), "auth_code"));
|
|
|
+ assertTrue(e.getMessage().contains("不支持的 wayCode"), "实测消息: " + e.getMessage());
|
|
|
+ }
|
|
|
+ }
|
|
|
+
|
|
|
+ // ─────────────────────────── 条码类:付款码键名 ───────────────────────────
|
|
|
+
|
|
|
+ @Test
|
|
|
+ void barcodeWayCodes_acceptBothPaymentCodeKeyNames() {
|
|
|
+ for (String wayCode : BARCODE_WAY_CODES) {
|
|
|
+ UnifiedChannelExtraAssembler.Result underscore =
|
|
|
+ UnifiedChannelExtraAssembler.assemble(wayCode, extras("auth_code", "123456"), null);
|
|
|
+ assertEquals("{\"auth_code\":\"123456\"}", underscore.json(), wayCode);
|
|
|
+ assertEquals("auth_code", underscore.keysCsv(), wayCode);
|
|
|
+
|
|
|
+ UnifiedChannelExtraAssembler.Result camel =
|
|
|
+ UnifiedChannelExtraAssembler.assemble(wayCode, extras("authCode", "123456"), "auth_code");
|
|
|
+ assertEquals("{\"auth_code\":\"123456\"}", camel.json(),
|
|
|
+ wayCode + ":对外两个键名都收,转上游按配置发 auth_code");
|
|
|
+ assertEquals("auth_code", camel.keysCsv(), wayCode);
|
|
|
+ }
|
|
|
+ }
|
|
|
+
|
|
|
+ @Test
|
|
|
+ void barcodeWayCodes_missingPaymentCode_throws400() {
|
|
|
+ for (String wayCode : BARCODE_WAY_CODES) {
|
|
|
+ BusinessException e = assert400(
|
|
|
+ () -> UnifiedChannelExtraAssembler.assemble(wayCode, Map.of(), "auth_code"));
|
|
|
+ assertTrue(e.getMessage().contains("付款码"), wayCode + " 实测消息: " + e.getMessage());
|
|
|
+
|
|
|
+ assert400(() -> UnifiedChannelExtraAssembler.assemble(wayCode, null, "auth_code"));
|
|
|
+ assert400(() -> UnifiedChannelExtraAssembler.assemble(
|
|
|
+ wayCode, extras("auth_code", " "), "auth_code"));
|
|
|
+ }
|
|
|
+ }
|
|
|
+
|
|
|
+ @Test
|
|
|
+ void barcode_bothPaymentCodeKeysEqual_accepted() {
|
|
|
+ UnifiedChannelExtraAssembler.Result result = UnifiedChannelExtraAssembler.assemble(
|
|
|
+ "AUTO_BAR", extras("auth_code", "123456", "authCode", "123456"), "auth_code");
|
|
|
+
|
|
|
+ assertEquals("{\"auth_code\":\"123456\"}", result.json());
|
|
|
+ assertEquals("auth_code", result.keysCsv());
|
|
|
+ }
|
|
|
+
|
|
|
+ @Test
|
|
|
+ void barcode_bothPaymentCodeKeysDiffer_throws400() {
|
|
|
+ BusinessException e = assert400(() -> UnifiedChannelExtraAssembler.assemble(
|
|
|
+ "WX_BAR", extras("auth_code", "123456", "authCode", "654321"), "auth_code"));
|
|
|
+ assertTrue(e.getMessage().contains("不一致"), "实测消息: " + e.getMessage());
|
|
|
+ }
|
|
|
+
|
|
|
+ @Test
|
|
|
+ void barcode_authCodeKeyAuthCode_emitsCamelCaseKey() {
|
|
|
+ UnifiedChannelExtraAssembler.Result result = UnifiedChannelExtraAssembler.assemble(
|
|
|
+ "ALI_BAR", extras("auth_code", "123456"), "authCode");
|
|
|
+
|
|
|
+ assertEquals("{\"authCode\":\"123456\"}", result.json());
|
|
|
+ assertEquals("authCode", result.keysCsv());
|
|
|
+ }
|
|
|
+
|
|
|
+ @Test
|
|
|
+ void barcode_authCodeKeyBoth_emitsBothKeysWithSameValue() {
|
|
|
+ UnifiedChannelExtraAssembler.Result result = UnifiedChannelExtraAssembler.assemble(
|
|
|
+ "YSF_BAR", extras("auth_code", "123456"), "both");
|
|
|
+
|
|
|
+ assertEquals("{\"auth_code\":\"123456\",\"authCode\":\"123456\"}", result.json());
|
|
|
+ // 自然序(ASCII):'C' < '_',所以 authCode 在前
|
|
|
+ assertEquals("authCode,auth_code", result.keysCsv());
|
|
|
+ }
|
|
|
+
|
|
|
+ @Test
|
|
|
+ void barcode_authCodeKeyBoth_withOnlyCamelInput_emitsBothKeys() {
|
|
|
+ UnifiedChannelExtraAssembler.Result result = UnifiedChannelExtraAssembler.assemble(
|
|
|
+ "AUTO_BAR", extras("authCode", "123456"), "both");
|
|
|
+
|
|
|
+ assertEquals("{\"auth_code\":\"123456\",\"authCode\":\"123456\"}", result.json());
|
|
|
+ assertEquals("authCode,auth_code", result.keysCsv());
|
|
|
+ }
|
|
|
+
|
|
|
+ @Test
|
|
|
+ void barcode_authCodeKeyBoth_differingValues_throws400() {
|
|
|
+ assert400(() -> UnifiedChannelExtraAssembler.assemble(
|
|
|
+ "AUTO_BAR", extras("auth_code", "1", "authCode", "2"), "both"));
|
|
|
+ }
|
|
|
+
|
|
|
+ @Test
|
|
|
+ void barcode_authCodeKeyNullOrBlankOrUnknown_fallsBackToUnderscore() {
|
|
|
+ for (String authCodeKey : new String[]{null, "", " ", "AUTHCODE", "unexpected"}) {
|
|
|
+ UnifiedChannelExtraAssembler.Result result = UnifiedChannelExtraAssembler.assemble(
|
|
|
+ "AUTO_BAR", extras("auth_code", "123456"), authCodeKey);
|
|
|
+ assertEquals("{\"auth_code\":\"123456\"}", result.json(), "配置=" + authCodeKey);
|
|
|
+ }
|
|
|
+ }
|
|
|
+
|
|
|
+ // ─────────────────────────── JSAPI 类 ───────────────────────────
|
|
|
+
|
|
|
+ @Test
|
|
|
+ void aliJsapi_requiresBuyerUserId() {
|
|
|
+ assert400(() -> UnifiedChannelExtraAssembler.assemble("ALI_JSAPI", Map.of(), null));
|
|
|
+ assert400(() -> UnifiedChannelExtraAssembler.assemble(
|
|
|
+ "ALI_JSAPI", extras("buyerUserId", " "), null));
|
|
|
+
|
|
|
+ UnifiedChannelExtraAssembler.Result result = UnifiedChannelExtraAssembler.assemble(
|
|
|
+ "ALI_JSAPI", extras("buyerUserId", "buyer-1"), null);
|
|
|
+ assertEquals("{\"buyerUserId\":\"buyer-1\"}", result.json());
|
|
|
+ assertEquals("buyerUserId", result.keysCsv());
|
|
|
+ }
|
|
|
+
|
|
|
+ @Test
|
|
|
+ void wxJsapiAndLite_requireOpenid() {
|
|
|
+ for (String wayCode : new String[]{"WX_JSAPI", "WX_LITE"}) {
|
|
|
+ assert400(() -> UnifiedChannelExtraAssembler.assemble(wayCode, Map.of(), null));
|
|
|
+
|
|
|
+ UnifiedChannelExtraAssembler.Result result = UnifiedChannelExtraAssembler.assemble(
|
|
|
+ wayCode, extras("openid", "openid-1"), null);
|
|
|
+ assertEquals("{\"openid\":\"openid-1\"}", result.json(), wayCode);
|
|
|
+ assertEquals("openid", result.keysCsv(), wayCode);
|
|
|
+ }
|
|
|
+ }
|
|
|
+
|
|
|
+ @Test
|
|
|
+ void wxJsapi_withWxAppId_emitsBothKeys() {
|
|
|
+ UnifiedChannelExtraAssembler.Result result = UnifiedChannelExtraAssembler.assemble(
|
|
|
+ "WX_LITE", extras("openid", "openid-1", "wxAppId", "wx-app-1"), null);
|
|
|
+
|
|
|
+ assertEquals("{\"openid\":\"openid-1\",\"wxAppId\":\"wx-app-1\"}", result.json());
|
|
|
+ assertEquals("openid,wxAppId", result.keysCsv(), "keysCsv 按字母序");
|
|
|
+ assertFalse(result.json().contains(" "), "JSON 必须紧凑,不能有空白");
|
|
|
+ }
|
|
|
+
|
|
|
+ @Test
|
|
|
+ void ysfJsapi_openidIsOptional() {
|
|
|
+ UnifiedChannelExtraAssembler.Result absent =
|
|
|
+ UnifiedChannelExtraAssembler.assemble("YSF_JSAPI", Map.of(), null);
|
|
|
+ assertNull(absent.json());
|
|
|
+ assertNull(absent.keysCsv());
|
|
|
+
|
|
|
+ UnifiedChannelExtraAssembler.Result present = UnifiedChannelExtraAssembler.assemble(
|
|
|
+ "YSF_JSAPI", extras("openid", "openid-1"), null);
|
|
|
+ assertEquals("{\"openid\":\"openid-1\"}", present.json());
|
|
|
+ assertEquals("openid", present.keysCsv());
|
|
|
+ }
|
|
|
+
|
|
|
+ // ─────────────────────────── 主扫 / PC / WAP 的 payDataType ───────────────────────────
|
|
|
+
|
|
|
+ @Test
|
|
|
+ void qrCashier_withoutExtras_returnsNullJsonAndKeys() {
|
|
|
+ UnifiedChannelExtraAssembler.Result result =
|
|
|
+ UnifiedChannelExtraAssembler.assemble("QR_CASHIER", Map.of(), null);
|
|
|
+
|
|
|
+ assertNull(result.json(), "未传 payDataType 时不注入默认值(默认值是上游行为)");
|
|
|
+ assertNull(result.keysCsv());
|
|
|
+ assertNull(UnifiedChannelExtraAssembler.assemble("QR_CASHIER", null, null).json());
|
|
|
+ }
|
|
|
+
|
|
|
+ @Test
|
|
|
+ void qrCashier_payDataTypeIsCaseInsensitiveAndCanonical() {
|
|
|
+ UnifiedChannelExtraAssembler.Result lower = UnifiedChannelExtraAssembler.assemble(
|
|
|
+ "QR_CASHIER", extras("payDataType", "codeimgurl"), null);
|
|
|
+ assertEquals("{\"payDataType\":\"codeImgUrl\"}", lower.json());
|
|
|
+ assertEquals("payDataType", lower.keysCsv());
|
|
|
+
|
|
|
+ UnifiedChannelExtraAssembler.Result upper = UnifiedChannelExtraAssembler.assemble(
|
|
|
+ "QR_CASHIER", extras("payDataType", "CODEURL"), null);
|
|
|
+ assertEquals("{\"payDataType\":\"codeUrl\"}", upper.json());
|
|
|
+ }
|
|
|
+
|
|
|
+ @Test
|
|
|
+ void qrCashier_unknownPayDataTypeIsDroppedNotRejected() {
|
|
|
+ for (Object value : new Object[]{"form", "garbage", null, " "}) {
|
|
|
+ UnifiedChannelExtraAssembler.Result result = UnifiedChannelExtraAssembler.assemble(
|
|
|
+ "QR_CASHIER", extras("payDataType", value), null);
|
|
|
+ assertNull(result.json(), "未知值必须丢弃而不是 400,实测值=" + value);
|
|
|
+ assertNull(result.keysCsv(), "未知值必须丢弃而不是 400,实测值=" + value);
|
|
|
+ }
|
|
|
+ }
|
|
|
+
|
|
|
+ @Test
|
|
|
+ void aliQrAndWxNative_acceptOnlyCodeUrlAndCodeImgUrl() {
|
|
|
+ for (String wayCode : new String[]{"ALI_QR", "WX_NATIVE"}) {
|
|
|
+ assertEquals("{\"payDataType\":\"codeUrl\"}", UnifiedChannelExtraAssembler.assemble(
|
|
|
+ wayCode, extras("payDataType", "codeUrl"), null).json(), wayCode);
|
|
|
+ assertEquals("{\"payDataType\":\"codeImgUrl\"}", UnifiedChannelExtraAssembler.assemble(
|
|
|
+ wayCode, extras("payDataType", "CODEIMGURL"), null).json(), wayCode);
|
|
|
+ assertNull(UnifiedChannelExtraAssembler.assemble(
|
|
|
+ wayCode, extras("payDataType", "payUrl"), null).json(),
|
|
|
+ wayCode + " 不接受 payUrl");
|
|
|
+ }
|
|
|
+ }
|
|
|
+
|
|
|
+ @Test
|
|
|
+ void aliWap_acceptsFormCodeImgUrlPayUrl_andCanonicalizesPayurl() {
|
|
|
+ assertEquals("{\"payDataType\":\"form\"}", UnifiedChannelExtraAssembler.assemble(
|
|
|
+ "ALI_WAP", extras("payDataType", "FORM"), null).json());
|
|
|
+ assertEquals("{\"payDataType\":\"codeImgUrl\"}", UnifiedChannelExtraAssembler.assemble(
|
|
|
+ "ALI_WAP", extras("payDataType", "codeimgurl"), null).json());
|
|
|
+ assertEquals("{\"payDataType\":\"payUrl\"}", UnifiedChannelExtraAssembler.assemble(
|
|
|
+ "ALI_WAP", extras("payDataType", "payurl"), null).json(),
|
|
|
+ "调用方传 payurl 一律按规范拼写 payUrl 输出");
|
|
|
+ assertNull(UnifiedChannelExtraAssembler.assemble(
|
|
|
+ "ALI_WAP", extras("payDataType", "codeUrl"), null).json(),
|
|
|
+ "ALI_WAP 不接受 codeUrl");
|
|
|
+ }
|
|
|
+
|
|
|
+ @Test
|
|
|
+ void aliPc_acceptsFormAndPayUrlOnly() {
|
|
|
+ assertEquals("{\"payDataType\":\"form\"}", UnifiedChannelExtraAssembler.assemble(
|
|
|
+ "ALI_PC", extras("payDataType", "form"), null).json());
|
|
|
+ assertEquals("{\"payDataType\":\"payUrl\"}", UnifiedChannelExtraAssembler.assemble(
|
|
|
+ "ALI_PC", extras("payDataType", "PAYURL"), null).json());
|
|
|
+ assertNull(UnifiedChannelExtraAssembler.assemble(
|
|
|
+ "ALI_PC", extras("payDataType", "codeImgUrl"), null).json(),
|
|
|
+ "ALI_PC 不接受 codeImgUrl");
|
|
|
+ }
|
|
|
+
|
|
|
+ @Test
|
|
|
+ void payDataTypeOnOtherWayCodes_isDroppedNotRejected() {
|
|
|
+ UnifiedChannelExtraAssembler.Result barcode = UnifiedChannelExtraAssembler.assemble(
|
|
|
+ "AUTO_BAR", extras("auth_code", "123456", "payDataType", "codeUrl"), null);
|
|
|
+ assertEquals("{\"auth_code\":\"123456\"}", barcode.json());
|
|
|
+ assertEquals("auth_code", barcode.keysCsv());
|
|
|
+
|
|
|
+ assertEquals("{\"buyerUserId\":\"buyer-1\"}", UnifiedChannelExtraAssembler.assemble(
|
|
|
+ "ALI_JSAPI", extras("buyerUserId", "buyer-1", "payDataType", "codeUrl"), null).json());
|
|
|
+ assertEquals("{\"openid\":\"openid-1\"}", UnifiedChannelExtraAssembler.assemble(
|
|
|
+ "WX_H5", extras("openid", "openid-1", "payDataType", "payUrl"), null).json());
|
|
|
+
|
|
|
+ assertNull(UnifiedChannelExtraAssembler.assemble(
|
|
|
+ "ALI_APP", extras("payDataType", "codeUrl"), null).json());
|
|
|
+ assertNull(UnifiedChannelExtraAssembler.assemble(
|
|
|
+ "WX_APP", extras("payDataType", "codeUrl"), null).json());
|
|
|
+ }
|
|
|
+
|
|
|
+ // ─────────────────────────── H5 / APP 与未知键 ───────────────────────────
|
|
|
+
|
|
|
+ @Test
|
|
|
+ void wxH5_openidIsOptional() {
|
|
|
+ UnifiedChannelExtraAssembler.Result absent =
|
|
|
+ UnifiedChannelExtraAssembler.assemble("WX_H5", Map.of(), null);
|
|
|
+ assertNull(absent.json());
|
|
|
+ assertNull(absent.keysCsv());
|
|
|
+
|
|
|
+ UnifiedChannelExtraAssembler.Result present = UnifiedChannelExtraAssembler.assemble(
|
|
|
+ "WX_H5", extras("openid", "openid-1"), null);
|
|
|
+ assertEquals("{\"openid\":\"openid-1\"}", present.json());
|
|
|
+ }
|
|
|
+
|
|
|
+ @Test
|
|
|
+ void appWayCodes_haveNoChannelExtraParameters() {
|
|
|
+ for (String wayCode : new String[]{"ALI_APP", "WX_APP"}) {
|
|
|
+ UnifiedChannelExtraAssembler.Result result = UnifiedChannelExtraAssembler.assemble(
|
|
|
+ wayCode, extras("foo", "bar"), null);
|
|
|
+ assertNull(result.json(), wayCode);
|
|
|
+ assertNull(result.keysCsv(), wayCode);
|
|
|
+ }
|
|
|
+ }
|
|
|
+
|
|
|
+ @Test
|
|
|
+ void unknownKeysDropped_knownKeysKept() {
|
|
|
+ UnifiedChannelExtraAssembler.Result wx = UnifiedChannelExtraAssembler.assemble(
|
|
|
+ "WX_JSAPI", extras("openid", "openid-1", "foo", "bar"), null);
|
|
|
+ assertEquals("{\"openid\":\"openid-1\"}", wx.json());
|
|
|
+ assertEquals("openid", wx.keysCsv(), "keysCsv 不得包含未知键 foo");
|
|
|
+
|
|
|
+ UnifiedChannelExtraAssembler.Result qr = UnifiedChannelExtraAssembler.assemble(
|
|
|
+ "QR_CASHIER", extras("foo", "bar"), null);
|
|
|
+ assertNull(qr.json(), "只给未知键时不抛错,结果为空");
|
|
|
+ assertNull(qr.keysCsv());
|
|
|
+ }
|
|
|
+}
|