|
|
@@ -46,11 +46,13 @@ public class PaymentMethodGateService {
|
|
|
public static final String GROUP_LINE_PAY = "LINE_PAY";
|
|
|
/** 支付方式组代码:线下转账(payType=6)。 */
|
|
|
public static final String GROUP_OFFLINE = "OFFLINE_TRANSFER";
|
|
|
+ /** 支付方式组代码:现金(payType=4);仅商家勾选管控,无平台开关行与就绪度(031 US7/FR-006)。 */
|
|
|
+ public static final String GROUP_CASH = "CASH";
|
|
|
|
|
|
- /** 现金 payType=4:仅商家建单场景,明确不纳入闸门管控,直接放行(spec FR-006)。 */
|
|
|
+ /** 现金 payType=4:原 assertUsable 路径(商家建单/闪送缺省现金)直接放行;用户单经 assertUsableForOrder 按订单类型管控。 */
|
|
|
public static final String PAY_TYPE_CASH = "4";
|
|
|
|
|
|
- /** payType 数值 → 组代码;不在表内的值视为非法。 */
|
|
|
+ /** payType 数值 → 组代码;不在表内的值视为非法(现金"4"仅走专门分支,不进映射)。 */
|
|
|
private static final Map<String, String> PAY_TYPE_TO_GROUP = Map.of(
|
|
|
"1", GROUP_COD,
|
|
|
"2", GROUP_CARD_OMG,
|
|
|
@@ -58,9 +60,9 @@ public class PaymentMethodGateService {
|
|
|
"5", GROUP_CARD_OMG,
|
|
|
"6", GROUP_OFFLINE);
|
|
|
|
|
|
- /** 各维度可管控的组集合;RIDER_FLASH 无线上卡支付(闪送资金直达骑手)。 */
|
|
|
+ /** 各维度可管控的组集合;RIDER_FLASH 无线上卡支付(闪送资金直达骑手)且不含现金(缺省支付不经勾选)。 */
|
|
|
private static final Map<GateScope, List<String>> SCOPE_GROUPS = Map.of(
|
|
|
- GateScope.MERCHANT, List.of(GROUP_COD, GROUP_CARD_OMG, GROUP_LINE_PAY, GROUP_OFFLINE),
|
|
|
+ GateScope.MERCHANT, List.of(GROUP_COD, GROUP_CARD_OMG, GROUP_LINE_PAY, GROUP_OFFLINE, GROUP_CASH),
|
|
|
GateScope.RIDER_FLASH, List.of(GROUP_COD, GROUP_LINE_PAY, GROUP_OFFLINE));
|
|
|
|
|
|
/** 闸门维度:商家餐饮单(用户向商家付款)与骑手闪送(用户直达骑手)独立开关。 */
|
|
|
@@ -123,16 +125,51 @@ public class PaymentMethodGateService {
|
|
|
}
|
|
|
}
|
|
|
|
|
|
+ /**
|
|
|
+ * 带订单类型的校验重载(031 US7):用户餐饮下单统一调用。
|
|
|
+ * 现金在此口径下按订单类型与商家勾选管控:自取/堂食查商家选择,外送拒绝,
|
|
|
+ * orderType 缺失(商家建单/闪送缺省现金)与原 {@link #assertUsable} 口径一致放行。
|
|
|
+ *
|
|
|
+ * @param orderType 订单类型(PosOrder.type:0外送 1自取 2堂食);无类型上下文传 null
|
|
|
+ */
|
|
|
+ public void assertUsableForOrder(String payType, GateScope scope, Long storeId, Long payeeUserId, Long orderType) {
|
|
|
+ if (!isUsableForOrder(payType, scope, storeId, payeeUserId, orderType)) {
|
|
|
+ throw new ServiceException(MessageUtils.message("pay.method.not.available"));
|
|
|
+ }
|
|
|
+ }
|
|
|
+
|
|
|
+ /** 现金订单类型口径的单一判定;非现金支付方式与原 isUsable 完全同路径。 */
|
|
|
+ private boolean isUsableForOrder(String payType, GateScope scope, Long storeId, Long payeeUserId, Long orderType) {
|
|
|
+ if (PAY_TYPE_CASH.equals(payType)) {
|
|
|
+ if (orderType == null || scope == GateScope.RIDER_FLASH) return true;
|
|
|
+ if (orderType != 1L && orderType != 2L) return false;
|
|
|
+ Set<String> selected = selectedGroups(scope, payeeUserId);
|
|
|
+ return selected == null || selected.contains(GROUP_CASH);
|
|
|
+ }
|
|
|
+ return isUsable(payType, scope, storeId, payeeUserId);
|
|
|
+ }
|
|
|
+
|
|
|
/**
|
|
|
* 列出某维度对收款方当前可用的支付方式(结算页可选项、骑手端可选集共用)。
|
|
|
* 返回平台开关 ∩ 收款方选择的全部项并附就绪度;RIDER_FLASH 维度就绪度恒 true
|
|
|
* (收款方未定或即骑手本人,线下卡是否就绪由骑手自选方式时自行把握,抢单过滤兜底)。
|
|
|
*/
|
|
|
public List<PayMethodOption> listAvailable(GateScope scope, Long storeId, Long payeeUserId) {
|
|
|
+ return listAvailable(scope, storeId, payeeUserId, null);
|
|
|
+ }
|
|
|
+
|
|
|
+ /**
|
|
|
+ * orderType 感知重载(031 US7):MERCHANT 维度且 orderType∈{1自取,2堂食} 时结果含现金项
|
|
|
+ * (仍受商家勾选约束);其余 orderType 或原签名口径不含现金,老客户端零变化。
|
|
|
+ */
|
|
|
+ public List<PayMethodOption> listAvailable(GateScope scope, Long storeId, Long payeeUserId, Long orderType) {
|
|
|
Map<String, Boolean> disabled = platformDisabledMap(scope);
|
|
|
Set<String> selected = selectedGroups(scope, payeeUserId);
|
|
|
+ boolean cashVisible = scope == GateScope.MERCHANT && orderType != null
|
|
|
+ && (orderType == 1L || orderType == 2L);
|
|
|
List<PayMethodOption> result = new ArrayList<>();
|
|
|
for (String group : SCOPE_GROUPS.get(scope)) {
|
|
|
+ if (GROUP_CASH.equals(group) && !cashVisible) continue;
|
|
|
if (disabled.containsKey(group)) continue;
|
|
|
if (selected != null && !selected.contains(group)) continue;
|
|
|
boolean ready = isReady(group, scope, storeId, payeeUserId);
|
|
|
@@ -188,7 +225,7 @@ public class PaymentMethodGateService {
|
|
|
* RIDER_FLASH 维度恒满足(收款方未定,由骑手选择层与抢单过滤兜底)。
|
|
|
*/
|
|
|
private boolean isReady(String group, GateScope scope, Long storeId, Long payeeUserId) {
|
|
|
- if (group.equals(GROUP_COD)) return true;
|
|
|
+ if (group.equals(GROUP_COD) || group.equals(GROUP_CASH)) return true;
|
|
|
if (scope == GateScope.RIDER_FLASH) return true;
|
|
|
switch (group) {
|
|
|
case GROUP_CARD_OMG:
|
|
|
@@ -212,6 +249,7 @@ public class PaymentMethodGateService {
|
|
|
case GROUP_CARD_OMG: return List.of("2", "5");
|
|
|
case GROUP_LINE_PAY: return List.of("3");
|
|
|
case GROUP_OFFLINE: return List.of("6");
|
|
|
+ case GROUP_CASH: return List.of(PAY_TYPE_CASH);
|
|
|
default: return List.of();
|
|
|
}
|
|
|
}
|
|
|
@@ -226,6 +264,15 @@ public class PaymentMethodGateService {
|
|
|
return SCOPE_GROUPS.get(scope);
|
|
|
}
|
|
|
|
|
|
+ /** 平台开关矩阵的组集合:值域剔除 CASH——现金无平台开关行(spec FR-006/US7);选择值域仍用 {@link #groupsOf}。 */
|
|
|
+ public static List<String> platformGroupsOf(GateScope scope) {
|
|
|
+ List<String> result = new ArrayList<>();
|
|
|
+ for (String group : groupsOf(scope)) {
|
|
|
+ if (!GROUP_CASH.equals(group)) result.add(group);
|
|
|
+ }
|
|
|
+ return result;
|
|
|
+ }
|
|
|
+
|
|
|
/** payType → 组代码映射查询(保存/展示场景用);未知返回 null。 */
|
|
|
public static String groupOfPayType(String payType) {
|
|
|
return PAY_TYPE_TO_GROUP.get(payType);
|