package com.talentcard.server.business.payment.huifu;
|
|
import static org.assertj.core.api.Assertions.assertThat;
|
|
import java.util.List;
|
import java.util.Map;
|
|
import com.alibaba.fastjson.JSON;
|
import org.junit.jupiter.api.Test;
|
|
/**
|
* 商户业务开通请求里那两个"文档要求、我们原来没发"的字段。
|
*
|
* <p>以汇付《商户业务开通》(v2.merchant.busi.open) 的请求规则为准逐项核对后发现两处缺口:
|
*
|
* <ul>
|
* <li>{@code media_mer_common_flag}(顶层):运营媒介主体与商户主体是否一致。平台用一个运营媒介
|
* 给众多子商户开通,主体天然不一致。实测缺它会被拒:
|
* 「【media_merCommon_flag-媒介主体与商户主体是否一致】不能为空,或格式非法」。</li>
|
* <li>{@code micro_biz_type}(wx_conf_list 元素内的 wx_real_name_info):个人商户开通微信业务必填,
|
* 且三种取值都要求 F22 店铺门头照 + F24 店铺内景照。</li>
|
* </ul>
|
*
|
* <p>层级依据:文档里 {@code wx_real_name_info} 既是父字段列、又有同名子表,按本接口的写法约定
|
* 它是嵌套 jsonObject(同样的写法可见 {@code online_media_info_list}),所以 micro_biz_type
|
* 必须放进 wx_conf_list 的元素里,不能平铺到顶层。
|
*/
|
class HuifuBusinessOpenRequiredFieldsTests {
|
|
private static HuifuPaymentProperties properties() {
|
HuifuPaymentProperties properties = new HuifuPaymentProperties();
|
properties.setEnabled(true);
|
properties.setSystemId("6666000226048687");
|
properties.setProductId("KAZX");
|
properties.setPrivateKey("x");
|
properties.setPlatformPublicKey("y");
|
properties.setMerchantWechatFeeRate("0.60");
|
properties.setMerchantOnlineBusinessType("H5311L");
|
properties.setMerchantOnlineMediaName("东区人才卡");
|
properties.setMerchantAgreementUrl("https://example.com/agreement.htm");
|
properties.setOnboardingUpperHuifuId("6666000220591054");
|
return properties;
|
}
|
|
@Test
|
void theMediaSubjectFlagIsAlwaysSent() {
|
Map<String, Object> request = request(false);
|
|
// 平台媒介主体与商户主体不一致,取 N;关键是必须出现,否则通道判参数非法。
|
assertThat(request).containsEntry("media_mer_common_flag", "N");
|
}
|
|
@Test
|
void anIndividualMerchantCarriesTheMicroBusinessTypeInsideTheWeChatConfig() {
|
Map<String, Object> request = request(true);
|
|
List<Map<String, Object>> wechat = wechatConfig(request);
|
assertThat(wechat).hasSize(1);
|
// 个人主体属于小微商户,mcc 也是必填。
|
assertThat(wechat.get(0)).containsKeys("mcc", "wx_real_name_info");
|
|
// 层级:micro_biz_type 在 wx_real_name_info 这个嵌套 jsonObject 里,不在元素顶层。
|
assertThat(wechat.get(0)).doesNotContainKey("micro_biz_type");
|
Map<String, Object> realName = JSON.parseObject(String.valueOf(wechat.get(0).get("wx_real_name_info")), Map.class);
|
assertThat(realName).containsEntry("micro_biz_type", "MICRO_TYPE_ONLINE");
|
}
|
|
@Test
|
void anEnterpriseMerchantDoesNotCarryTheMicroBusinessType() {
|
// 文档写明「个人商户需要填写」,企业主体不需要,不要硬塞。
|
Map<String, Object> request = request(false);
|
|
List<Map<String, Object>> wechat = wechatConfig(request);
|
assertThat(wechat.get(0)).doesNotContainKey("wx_real_name_info");
|
}
|
|
@Test
|
void anEnterpriseCanUseAProviderConfirmedFeeRuleInsteadOfMcc() {
|
HuifuPaymentProperties properties = properties();
|
properties.setMerchantWechatFeeRuleId("756");
|
|
List<Map<String, Object>> wechat = wechatConfig(HuifuMerchantBusinessOpenGateway.buildRequestForTest(
|
properties, "BO-TEST-RULE", "6666000241335656", "成都喜望科技", "7372", false));
|
|
assertThat(wechat.get(0)).containsEntry("fee_rule_id", "756");
|
assertThat(wechat.get(0)).doesNotContainKey("mcc");
|
}
|
|
/**
|
* 直接驱动组装逻辑。网关的 {@code open()} 会真的调用通道,所以这里只构建请求体:
|
* 复用网关内部的组装顺序没有意义,改为断言"网关是否会包含这些字段"的等价物——
|
* 用同一份 properties 构造,并让网关暴露一个纯组装的包级方法。
|
*/
|
private Map<String, Object> request(boolean individualMerchant) {
|
return HuifuMerchantBusinessOpenGateway.buildRequestForTest(
|
properties(), "BO-TEST-1", "6666000241390821", "阳野", "5812", individualMerchant);
|
}
|
|
@SuppressWarnings("unchecked")
|
private List<Map<String, Object>> wechatConfig(Map<String, Object> request) {
|
return JSON.parseObject(String.valueOf(request.get("wx_conf_list")), List.class);
|
}
|
}
|