Mock Gateway
本项目是 独立 Git 仓库 的本地 Mock 网关,用于模拟 eWallet 后端依赖的 Bally/EDIP 接口,避免在 Backend 主代码中持续保留绕过逻辑。
已内置的 Mock 接口
POST /edip/v1/token/getPOST /edip/v1/token/refreshPOST /ewl/bal/v1/cardpin/validatePOST /ewl/promotion/v1/promotion/allPOST /ewl/bal/v1/promotion/all(兼容旧地址)POST /ewl/promotion/v1/promotion/backdate/allPOST /ewl/bal/v1/promotion/backdate/all(兼容旧地址)POST /ewl/mkt-rm/v1/team/hierarchyPOST /ewl/bal/v1/prize/redeemPOST /ewl/bal/v1/point/voidPOST /ewl/promotion/v1/redeemedpromotion/detailPOST /ewl/bal/v1/redeemedpromotion/detail(兼容旧地址)POST /ewl/promotion/v1/playerpromotion/redeemPOST /ewl/bal/v1/playerpromotion/redeem(兼容旧地址)POST /ewl/promotion/v1/redeemedpromotion/voidPOST /ewl/bal/v1/redeemedpromotion/void(兼容旧地址)POST /ewl/edip/v1/member/profilePOST /ewl/bal/v1/player/imagePOST /ewl/bal/v1/player/earnPOST /api/v1/prize-redemptions/syncGET /healthz
已内置的 LDAP Mock(新增)
- 协议:LDAPv3
- 默认监听:
ldap://0.0.0.0:1389 - 支持能力:
Simple Bind+Search
固定行为(与对接约定一致):
- manager bind DN:
cn=s-cicd-app,OU=ServiceAccount,dc=macausjm-glp,dc=com - 用户搜索:base
dc=macausjm-glp,dc=com+ filter(sAMAccountName={username}) - 组搜索:base
OU=SecurityGroups,OU=GLPUsers,dc=macausjm-glp,dc=com+ filter(member={userDn}) - 用户条目属性:
sAMAccountName/cn/mail/memberOf - 组条目属性:
cn/member
并且支持用户 DN + 密码直接 bind 成功(基于内置默认用户或 MOCK_LDAP_USERS_JSON 配置用户)。
另外默认开启“任意用户名/密码放行”联调模式(MOCK_LDAP_ALLOW_ANY_USER_MODE=true):
- 前端输入任意账号密码都可通过后端 LDAP 认证
(sAMAccountName={username})会按{username}动态返回用户条目(member={userDn})会返回组条目(默认SG-APP-EWALLET-SUPER-ADMIN)
推荐做法:通过 MOCK_LDAP_USERS_JSON / MOCK_LDAP_GROUPS_JSON 在 Mock_Gateway 侧配置用户与用户组,不要再在 Backend 代码里硬编码开发账号或组别。
本地启动
cd Mock_Gateway
npm install
cp .env.example .env
npm run start
开发联调建议使用自动重启模式(监听 src/ 与 .env 变更):
npm run dev
默认监听:http://127.0.0.1:19090
LDAP 默认监听:ldap://0.0.0.0:1389
Promotion 完整链路 mock
默认的 playerpromotion/redeem 仍然只是静态回包。
如果你要在本地继续联调 promotion 首打、redeemed history、reprint 这一整条链路,可以开启下面这组桥接配置,让 Mock_Gateway 在 promotion redeem 成功后继续:
- 登录本地
Backend - 调用真实
POST /api/v1/prize-redemptions - 把同一笔
redemptionId记录进 mock 的redeemedpromotion/detail
建议同时满足以下前提:
- 本地
Backend已启动 - 本地
Backend已接到当前Mock_Gateway的 LDAP mock - 测试会员在本地 wallet 里对
MOCK_PROMOTION_REDEMPTION_SOURCE_BUCKET有足够余额
推荐配置:
MOCK_PROMOTION_REDEMPTION_BRIDGE_ENABLED=true
MOCK_PROMOTION_REDEMPTION_BRIDGE_BASE_URL=http://127.0.0.1:8080
MOCK_PROMOTION_REDEMPTION_BRIDGE_LOGIN_PASSWORD=mock-password
MOCK_PROMOTION_REDEMPTION_BRIDGE_TIMEOUT_MS=30000
MOCK_PROMOTION_REDEMPTION_INITIATE_SOURCE=PROMOTION_MODULE
MOCK_PROMOTION_REDEMPTION_SOURCE_BUCKET=m-comp
说明:
MOCK_PROMOTION_REDEMPTION_BRIDGE_LOGIN_USERNAME留空时,默认复用本次 redeem 请求里的loginIdMOCK_PROMOTION_REDEMPTION_SOURCE_BUCKET默认用m-comp作为 source wallet bucket- 桥接成功后,
/ewl/bal/v1/redeemedpromotion/detail会优先返回本次实际生成的 mock redeemed record
Promotion issue-to-wallet 控制
当前 Mock_Gateway 已支持两层控制 promotion redeem -> 本地 prize-redemptions 的 issueTargetToWallet:
- 显式覆盖,优先级最高
- 现有推断,作为兜底
显式覆盖支持两种写法:
- 请求级:
data.issueTargetToWallet: [true, false, ...],按outcomeId顺序逐项覆盖;同一个outcomeId重复出现且每次选择不同Open Item / Auto Settle时,必须走这个数组data.issueTargetToWalletByOutcomeId: { "11330011": true, "11330012": false },按 outcomeId 精确覆盖
- fixture 级:
outcomeList[].mockIssueTargetToWalletoutcomeList[].prize.mockIssueTargetToWallet
当以上显式覆盖都没有提供时,才回退到现有推断规则:
gisPrizeIdentifier[index]非空 ->issueTargetToWallet=false- 否则
deliveryMode=EXTERNAL_ONLY->false - 其他情况 ->
true
这意味着:
- 对
USER_CHOICEprize,如需稳定复现同一个 outcome 在 openitem / autosettle 之间切换,推荐直接在 mock 请求或 fixture 中提供显式覆盖,不要只依赖deliveryMode - 如果一个请求里允许同一个
outcomeId重复出现且每次选择不同,优先使用issueTargetToWallet数组;issueTargetToWalletByOutcomeId只适合一个 outcomeId 对应一个固定值的场景 - 如果调用方需要,也可以通过 body 的
issueTargetToWalletByOutcomeId/issueTargetToWallet,或自定义 headerX-Ewallet-Mock-Issue-Target-To-Wallet-By-Outcome-Id给 mock 传入显式覆盖;未提供时仍按当前默认推断执行 - 旧链路不受影响;未提供覆盖时仍保持当前默认行为
UI 点测同一个 outcome 的本地预设
如果不改 Backend,但希望在 UI 上对同一个 outcome 反复点测 Open Item / Auto Settle,可以先写入 mock runtime override:
curl -s -X POST http://127.0.0.1:19090/mock-api/promotion-redeem/fulfillment-overrides \
-H 'Content-Type: application/json' \
-d '{
"accountNum": "80010991",
"promotionId": 11330,
"promotionRuleId": 1133001,
"outcomeId": 11330011,
"issueTargetToWallet": false
}'
说明:
issueTargetToWallet=true表示本次同一个 outcome 走Open ItemissueTargetToWallet=false表示本次同一个 outcome 走Auto Settle- 写入后,直接在 UI 点同一个 outcome 即可;mock 会优先使用这份 runtime override
- override 默认会持久化到
./runtime/promotion-redeem-fulfillment-overrides.json,重启Mock_Gateway后仍会保留 - 可通过
GET /mock-api/promotion-redeem/fulfillment-overrides查看当前预设 - 可通过
DELETE /mock-api/promotion-redeem/fulfillment-overrides?accountNum=80010991&promotionId=11330&promotionRuleId=1133001&outcomeId=11330011清除单条预设
与 Backend 集成
在 Backend 启动环境中设置:
MOCK_GATEWAY_BASE_URL=http://127.0.0.1:19090
BALLY_BASE_URL=${MOCK_GATEWAY_BASE_URL}
EDIP_BASE_URL=${MOCK_GATEWAY_BASE_URL}
BALLY_REDEEM_BASE_URL=${MOCK_GATEWAY_BASE_URL}
BALLY_PROMOTION_BASE_URL=${MOCK_GATEWAY_BASE_URL}
# 建议关闭旧的本地 member 直返 mock,改走网关
BALLY_MEMBER_QUERY_LOCAL_MOCK_ENABLED=false
Task12085 本地故障注入
当前 Mock_Gateway 已支持直接注入 Member Profile 两类关键故障:
503/ 服务不可用
MOCK_MEMBER_PROFILE_FORCE_STATUS_CODE=503
MOCK_MEMBER_PROFILE_FORCE_ERROR_CODE=MOCK_503
MOCK_MEMBER_PROFILE_FORCE_ERROR_MSG='Mock member profile unavailable'
- 响应超时
MOCK_MEMBER_PROFILE_DELAY_MS=15000
建议:
MOCK_MEMBER_PROFILE_DELAY_MS需要大于 Backend 当前 member profile 调用的阻塞超时,才能稳定触发超时- 如果你只想打 member profile 故障,保持
MOCK_EDIP_FORCE_ERROR_CODE为空,让 token 继续正常返回 - 测完后把这些变量清空并重启
Mock_Gateway
快速验证
curl -s http://127.0.0.1:19090/healthz
curl -s -X POST http://127.0.0.1:19090/edip/v1/token/get \
-H 'Content-Type: application/json' \
-d '{"schema":{},"data":{"account":"a","password":"b","key":"k","secret":"s"}}'
curl -s -X POST http://127.0.0.1:19090/ewl/bal/v1/cardpin/validate \
-H 'Content-Type: application/json' \
-d '{"schema":{},"data":{"accountNum":"810006843","pin":"1234"}}'
curl -s -X POST http://127.0.0.1:19090/ewl/promotion/v1/promotion/all \
-H 'Content-Type: application/json' \
-d '{"schema":{},"data":{"accountNum":"800048718"}}'
curl -s -X POST http://127.0.0.1:19090/ewl/bal/v1/promotion/all \
-H 'Content-Type: application/json' \
-d '{"schema":{},"data":{"accountNum":"800048718"}}'
curl -s -X POST http://127.0.0.1:19090/ewl/mkt-rm/v1/team/hierarchy \
-H 'Content-Type: application/json' \
-d '{"schema":{"terminalCode":"MOCK-PC"},"data":{"userName":"mock.user","staffId":"M000001"}}'
curl -s -X POST http://127.0.0.1:19090/ewl/bal/v1/prize/redeem \
-H 'Content-Type: application/json' \
-d '{"schema":{},"data":{"accountNum":"800048718","prizeCode":"MOCK"}}'
curl -s -X POST http://127.0.0.1:19090/api/v1/prize-redemptions/sync \
-H 'Content-Type: application/json' \
-d '{"schema":{},"data":{"correlationId":"mock-correlation-id"}}'
curl -s -X POST http://127.0.0.1:19090/ewl/bal/v1/point/void \
-H 'Content-Type: application/json' \
-d '{"schema":{},"data":{"transId":"mock-redeem-id"}}'
curl -s -X POST http://127.0.0.1:19090/ewl/bal/v1/redeemedpromotion/detail \
-H 'Content-Type: application/json' \
-d '{"schema":{},"data":{"accountNum":"800048718"}}'
curl -s -X POST http://127.0.0.1:19090/ewl/promotion/v1/playerpromotion/redeem \
-H 'Content-Type: application/json' \
-d '{"schema":{},"data":{"accountNum":"800048718","promotionId":100002}}'
curl -s -X POST http://127.0.0.1:19090/ewl/bal/v1/playerpromotion/redeem \
-H 'Content-Type: application/json' \
-d '{
"schema": {},
"data": {
"accountNum": "80010991",
"promotionId": 11330,
"promotionRuleId": 1133001,
"outcomeId": [11330011, 11330012, 11330013],
"issueTargetToWalletByOutcomeId": {
"11330011": true,
"11330012": false,
"11330013": false
}
}
}'
curl -s -X POST http://127.0.0.1:19090/ewl/bal/v1/playerpromotion/redeem \
-H 'Content-Type: application/json' \
-d '{"schema":{},"data":{"accountNum":"800048718","promotionId":100002}}'
curl -s -X POST http://127.0.0.1:19090/ewl/promotion/v1/redeemedpromotion/void \
-H 'Content-Type: application/json' \
-d '{"schema":{},"data":{"redeemedId":<上一步 detail 响应里的 redemptionId>}}'
curl -s -X POST http://127.0.0.1:19090/ewl/bal/v1/redeemedpromotion/void \
-H 'Content-Type: application/json' \
-d '{"schema":{},"data":{"redeemedId":<上一步 detail 响应里的 redemptionId>}}'
# LDAP manager bind(默认 manager 密码可留空,便于 Backend 只改 LDAP_URL)
ldapsearch -x -H ldap://127.0.0.1:1389 \
-D "cn=s-cicd-app,OU=ServiceAccount,dc=macausjm-glp,dc=com" \
-w "any-password" \
-b "dc=macausjm-glp,dc=com" \
"(sAMAccountName=mock.user)" sAMAccountName cn mail memberOf
# LDAP user bind(DN + 密码)
ldapsearch -x -H ldap://127.0.0.1:1389 \
-D "cn=mock.user,OU=GLPUsers,dc=macausjm-glp,dc=com" \
-w "mock-user-password" \
-b "OU=SecurityGroups,OU=GLPUsers,dc=macausjm-glp,dc=com" \
"(member=cn=mock.user,OU=GLPUsers,dc=macausjm-glp,dc=com)" cn member
# 建议把默认组名设置成 Backend 角色表已有 code(如 `SG-APP-EWALLET-SUPER-ADMIN`),更容易看到非空 permissions
页面数据模板(JSON)
fixtures/token.get.json:/edip/v1/token/get成功响应模板fixtures/member.profile.json:/ewl/edip/v1/member/profile成功响应模板fixtures/promotions.capture.800048718.json:/ewl/promotion/v1/promotion/all抓包模板fixtures/promotions.capture.<account>.json:按会员号隔离的 promotion fixture;存在同名文件时,mock 会优先对该会员返回该文件内容- promotion fixture 可额外带
outcomeList[].mockIssueTargetToWallet或outcomeList[].prize.mockIssueTargetToWallet,用于稳定指定某个 outcome 走 openitem / autosettle
当前已补一条专用于完整链路测试的会员:
80010991- promotionId:
10991 - promotion:
LP-MOCK-REPRINT-CHAIN - ruleId:
1099101 - outcomeId:
10991011 - targetPrizeCode:
lp-ee-nsuwr-5pts-20-fb - 另有 3-outcome 的
USER_CHOICE测试 promotion: - promotionId:
11330 - promotion:
LP-MOCK-USER-CHOICE-3-OUTCOMES - ruleId:
1133001 - outcomeId:
11330011->it-test-fb-$1 - outcomeId:
11330012->it-test-nnpc-$1 - outcomeId:
11330013->it-test-ebo-$1 - 这 3 个 outcome 都可在 UI 上分别切
Open Item / Auto Settle,用于本地验证 promotion redeem -> prize-redemptions -> redeemed detail 整条链路
说明:
- 以上模板用于维护响应“静态骨架”
- 动态字段仍由网关运行时覆盖(如
accessToken、refreshToken、accountNum、playerId、以及 LDAP 用户相关字段)
代码结构(已拆分)
src/server.js:仅保留启动、路由装配、404 与 LDAP 启动src/ldap/createMockLdapService.js:LDAP 相关逻辑独立维护src/context/createMockContext.js:共享配置、fixture 加载、通用工具函数src/routes/**:每个接口路径一个独立文件(便于新增与变更)
常用环境变量
MOCK_PROMOTION_CAPTURE_FILE:promotion 抓包文件路径(默认读取仓库内./fixtures/promotions.capture.800048718.json)MOCK_PROMOTION_MAX_ITEMS:promotion 返回上限(eligible/entitled 各自限制,默认30)MOCK_TASK_10766_ENABLED:开启 Task 10766 复现场景(默认false)MOCK_TASK_10766_ACCOUNT_NUM:Task 10766 固定 mock 会员号(默认80010766)MOCK_TASK_10766_PROMOTION_CAPTURE_FILE:Task 10766 promotion fixture(默认./fixtures/promotions.capture.10766.json)MOCK_TASK_10766_MEMBER_EBONUS:Task 10766 会员资料接口返回的 eBonus 数值(默认8888)MOCK_TASK_10766_REDEEM_ERROR_CODE/MOCK_TASK_10766_REDEEM_ERROR_MSG/MOCK_TASK_10766_REDEEM_RESULT:Task 10766 的playerpromotion/redeem定向失败控制MOCK_TASK_10852_ENABLED:开启 Task 10852 多 outcome promotion 复现场景(默认false)MOCK_TASK_10852_ACCOUNT_NUM:Task 10852 固定 mock 会员号(默认80010852)MOCK_TASK_10852_PROMOTION_CAPTURE_FILE:Task 10852 promotion fixture,默认使用隔离的 entitled 双 outcome 抓包./fixtures/promotions.capture.10852.jsonMOCK_TASK_10852_MEMBER_EBONUS:Task 10852 会员资料接口返回的 eBonus 数值(默认188)MOCK_TOKEN_GET_FIXTURE_FILE:/edip/v1/token/getJSON 模板文件路径(默认./fixtures/token.get.json)MOCK_MEMBER_PROFILE_FIXTURE_FILE:/ewl/edip/v1/member/profileJSON 模板文件路径(默认./fixtures/member.profile.json)MOCK_MEMBER_PROFILE_FORCE_STATUS_CODE:/ewl/edip/v1/member/profile强制返回指定 HTTP 状态码,例如503MOCK_MEMBER_PROFILE_FORCE_ERROR_CODE:配合MOCK_MEMBER_PROFILE_FORCE_STATUS_CODE返回错误码MOCK_MEMBER_PROFILE_FORCE_ERROR_MSG:配合MOCK_MEMBER_PROFILE_FORCE_STATUS_CODE返回错误信息MOCK_MEMBER_PROFILE_DELAY_MS:/ewl/edip/v1/member/profile延迟响应毫秒数,可用于本地模拟超时MOCK_TEAM_HIERARCHY_STATUS:team/hierarchy的status(默认true)MOCK_TEAM_HIERARCHY_ERROR_CODE/MOCK_TEAM_HIERARCHY_MESSAGE:team/hierarchy错误模拟MOCK_TEAM_HIERARCHY_ROLE/MOCK_TEAM_HIERARCHY_DEPARTMENT/MOCK_TEAM_HIERARCHY_TAGS:team/hierarchy返回字段MOCK_PRIZE_REDEEM_ERROR_CODE/MOCK_PRIZE_REDEEM_ERROR_MSG/MOCK_PRIZE_REDEEM_VALUE:prize/redeem返回控制(MOCK_PRIZE_REDEEM_VALUE留空时自动生成交易号)MOCK_POINT_VOID_ERROR_CODE/MOCK_POINT_VOID_ERROR_MSG/MOCK_POINT_VOID_RESULT:point/void返回控制MOCK_REDEEMED_PROMOTION_DETAIL_ERROR_CODE/MOCK_REDEEMED_PROMOTION_DETAIL_ERROR_MSG:redeemedpromotion/detail返回控制MOCK_REDEEMED_PROMOTION_DETAIL_INCLUDE_DEFAULT_RECORD:是否返回默认一条outcomeList(默认true)MOCK_REDEEMED_PROMOTION_DETAIL_VOIDED:默认记录是否标记已作废(默认false)MOCK_PLAYERPROMOTION_REDEEM_ERROR_CODE/MOCK_PLAYERPROMOTION_REDEEM_ERROR_MSG/MOCK_PLAYERPROMOTION_REDEEM_RESULT:playerpromotion/redeem返回控制MOCK_PROMOTION_REDEMPTION_BRIDGE_ENABLED:开启 promotion redeem -> 本地prize-redemptions桥接(默认false)MOCK_PROMOTION_REDEMPTION_BRIDGE_BASE_URL:本地 Backend 基地址(默认http://127.0.0.1:8080)MOCK_PROMOTION_REDEMPTION_BRIDGE_LOGIN_USERNAME/MOCK_PROMOTION_REDEMPTION_BRIDGE_LOGIN_PASSWORD:桥接调用 Backend 登录用账号;用户名留空时默认复用本次 redeem 的loginIdMOCK_PROMOTION_REDEMPTION_BRIDGE_TIMEOUT_MS:桥接调用超时毫秒数(默认30000);本地完整链路联调建议至少保留30000MOCK_PROMOTION_REDEMPTION_INITIATE_SOURCE:桥接到prize-redemptions时写入的initiateSource(默认PROMOTION_MODULE)MOCK_PROMOTION_REDEMPTION_SOURCE_BUCKET:桥接到prize-redemptions时使用的 source wallet bucket(默认m-comp)MOCK_PROMOTION_REDEMPTION_ID_START:mock redeemed history 的起始redemptionId;留空时默认用进程启动时的 Unix 秒级时间戳作为 seed,且会限制在 Backendint可解析范围内,避免 Mock_Gateway 重启后重复复用旧redemptionIdMOCK_REDEEMEDPROMOTION_VOID_ERROR_CODE/MOCK_REDEEMEDPROMOTION_VOID_ERROR_MSG/MOCK_REDEEMEDPROMOTION_VOID_RESULT:redeemedpromotion/void返回控制MOCK_PRIZE_REDEMPTIONS_SYNC_SUCCESS/MOCK_PRIZE_REDEMPTIONS_SYNC_MESSAGE:/api/v1/prize-redemptions/sync返回控制MOCK_LDAP_ENABLED:是否启用 LDAP mock(默认true)MOCK_LDAP_HOST:LDAP 监听地址(默认0.0.0.0)MOCK_LDAP_PORT:LDAP 监听端口(默认1389)MOCK_LDAP_BASE_DN:LDAP 基础 DN(默认dc=macausjm-glp,dc=com)MOCK_LDAP_MANAGER_DN:manager bind DN(默认cn=s-cicd-app,OU=ServiceAccount,dc=macausjm-glp,dc=com)MOCK_LDAP_GROUP_BASE_DN:组搜索 base(默认OU=SecurityGroups,OU=GLPUsers,dc=macausjm-glp,dc=com)MOCK_LDAP_ALLOW_ANY_USER_MODE:任意用户名/密码放行模式(默认true)MOCK_LDAP_ALLOW_ANY_USER_OU:动态用户 DN 的 OU 段(默认OU=GLPUsers)MOCK_LDAP_ALLOW_ANY_USER_GROUP_CN:动态用户默认组名(默认SG-APP-EWALLET-SUPER-ADMIN)MOCK_LDAP_ALLOW_ANY_USER_MAIL_DOMAIN:动态用户邮箱域名(默认macausjm-glp.com)MOCK_LDAP_MANAGER_PASSWORD:manager bind 密码;留空时允许任意密码(便于仅改LDAP_URL联调)MOCK_LDAP_DEFAULT_USER_*:默认单用户 mock 配置MOCK_LDAP_USERS_JSON:JSON 数组,多用户覆盖配置
Task 10766 复现场景
打开 .env,加入或覆盖以下配置:
MOCK_TASK_10766_ENABLED=true
MOCK_TASK_10766_ACCOUNT_NUM=80010766
MOCK_TASK_10766_PROMOTION_CAPTURE_FILE=./fixtures/promotions.capture.10766.json
MOCK_TASK_10766_MEMBER_EBONUS=8888
MOCK_TASK_10766_REDEEM_ERROR_CODE=EWALLET_HTTP_ERROR
MOCK_TASK_10766_REDEEM_ERROR_MSG=ewallet connection failed: 404 NOT_FOUND, {"success":false,"message":"Prize definition not found"}
MOCK_TASK_10766_REDEEM_RESULT=false
复现方式:
- 启动
Mock_Gateway - 前后端联调继续指向本地 mock 网关
- 在
Wallet页面搜索会员80010766 - 切到
Promotion - 搜索
cny - 选择
CNY Gift Set Earn & Get-2026 / GS-8pts-LCH Gift Set Abalone + Scallop - 点击
Redeem并完成确认
预期:
-
会员资料接口返回
eBonus=8888 -
promotion 列表固定返回 Task 10766 专用 fixture
-
POST /ewl/promotion/v1/playerpromotion/redeem固定返回Prize definition not found场景 -
可稳定复现 10766 对应的 promotion redeem 失败明细展示问题
Task 10852 复现场景
打开 .env,加入或覆盖以下配置:
MOCK_TASK_10852_ENABLED=true
MOCK_TASK_10852_ACCOUNT_NUM=80010852
MOCK_TASK_10852_PROMOTION_CAPTURE_FILE=./fixtures/promotions.capture.10852.json
MOCK_TASK_10852_MEMBER_EBONUS=188
复现方式:
- 启动
Mock_Gateway - 前后端联调继续指向本地 mock 网关
- 在
Wallet页面搜索会员80010852 - 切到
Promotion - 搜索
cny - 选择
CNY Gift Set Earn & Get-2026 - 勾选两个 outcome 后继续兑换流程
预期:
- 会员资料接口返回
eBonus=188 POST /ewl/promotion/v1/promotion/all固定返回可点击的 entitled 双 outcome promotion- 前端会稳定走到
targetPrizes多项场景,便于验证 10852 的最小修复
按会员号自动注入 Promotion Fixture
除了现有的 Task 10766 / 10852 专用开关外,Mock_Gateway 现在还支持按会员号自动加载 fixture:
- 文件命名:
fixtures/promotions.capture.<customerId>.json - 命中规则:当
/ewl/promotion/v1/promotion/all的accountNum与文件名中的会员号一致时,自动返回该 fixture - backdate 文件命名:
fixtures/promotions.backdate.<customerId>.json - backdate 命中规则:当
/ewl/promotion/v1/promotion/backdate/all的accountNum与文件名中的会员号一致时,自动返回该 fixture - 优先级:Task 10766 / 10852 专用场景优先,其次才是按会员号自动加载的 fixture
示例:
fixtures/promotions.capture.800038008.jsonfixtures/promotions.capture.80010852.jsonfixtures/promotions.backdate.800038008.json
适用场景:
- 需要保留某个会员的真实采样 promotion 规则
- 想快速补充新的
minOutcome / maxOutcome / outcomeList / prize组合 - 不希望影响默认共享 mock 数据
使用本地测试开发网关的时候可以使用以下会员号
按 Mock_Gateway 当前代码中的“定向逻辑 / 定向 fixture / 固定路由”统计,特别会员号共有 5 个(不含默认模板/示例号):
800038008- backdate 固定会员号。/ewl/promotion/v1/promotion/entitledBackDate和/ewl/promotion/v1/promotion/entitledBackDate/all会固定返回这个会员号的 backdate promotion;仓库里也有它的普通 promotion fixture 和 backdate fixture。80010766- Task 10766 专用复现号。 开启MOCK_TASK_10766_ENABLED=true后,会员资料固定返回eBonus=8888,promotion 列表走专用 fixture,playerpromotion/redeem固定复现Prize definition not found失败场景。80010852- Task 10852 专用复现号。 开启MOCK_TASK_10852_ENABLED=true后,会员资料固定返回eBonus=188,promotion 列表走专用 fixture,并强制提供可点击的 entitled 双 outcome 场景,用于验证多 outcome redeem。80010991- 完整链路 / 同 outcome 切换场景号。 命中专用promotions.capture.80010991.json,内含单 outcome reprint chain 和 3-outcomeUSER_CHOICEpromotion;也用于 runtime fulfillment override,方便在 UI 上反复验证同一个 outcome 的Open Item / Auto Settle切换。100000059- redeemed promotion detail 专用号。 命中award.promotions.100000059.json,用于redeemedpromotion/detail返回账户级已兑 promotion 明细。
以下号码也出现在 Mock_Gateway 中,但更适合视为默认模板 / 示例数据,不计入上面的“特别会员号”:
-
800048718- 默认 promotion 抓包模板来源。 没有专属定向逻辑,未命中其他专用场景时,普通账号会回落到这份默认 promotion fixture。 -
800049052- 默认 redeemed promotions 示例号。 只在redeemedpromotion/detail没传账号且没有账户级记录时,作为默认示例数据中的customerId出现。800048718 老会员----换新账号----910700001