上传文件至「/」
This commit is contained in:
@@ -0,0 +1,481 @@
|
||||
# Mock Gateway
|
||||
|
||||
本项目是 **独立 Git 仓库** 的本地 Mock 网关,用于模拟 eWallet 后端依赖的 Bally/EDIP 接口,避免在 `Backend` 主代码中持续保留绕过逻辑。
|
||||
|
||||
## 已内置的 Mock 接口
|
||||
|
||||
- `POST /edip/v1/token/get`
|
||||
- `POST /edip/v1/token/refresh`
|
||||
- `POST /ewl/bal/v1/cardpin/validate`
|
||||
- `POST /ewl/promotion/v1/promotion/all`
|
||||
- `POST /ewl/bal/v1/promotion/all` (兼容旧地址)
|
||||
- `POST /ewl/promotion/v1/promotion/backdate/all`
|
||||
- `POST /ewl/bal/v1/promotion/backdate/all` (兼容旧地址)
|
||||
- `POST /ewl/mkt-rm/v1/team/hierarchy`
|
||||
- `POST /ewl/bal/v1/prize/redeem`
|
||||
- `POST /ewl/bal/v1/point/void`
|
||||
- `POST /ewl/promotion/v1/redeemedpromotion/detail`
|
||||
- `POST /ewl/bal/v1/redeemedpromotion/detail` (兼容旧地址)
|
||||
- `POST /ewl/promotion/v1/playerpromotion/redeem`
|
||||
- `POST /ewl/bal/v1/playerpromotion/redeem` (兼容旧地址)
|
||||
- `POST /ewl/promotion/v1/redeemedpromotion/void`
|
||||
- `POST /ewl/bal/v1/redeemedpromotion/void` (兼容旧地址)
|
||||
- `POST /ewl/edip/v1/member/profile`
|
||||
- `POST /ewl/bal/v1/player/image`
|
||||
- `POST /ewl/bal/v1/player/earn`
|
||||
- `POST /api/v1/prize-redemptions/sync`
|
||||
- `GET /healthz`
|
||||
|
||||
## 已内置的 LDAP Mock(新增)
|
||||
|
||||
- 协议:LDAPv3
|
||||
- 默认监听:`ldap://0.0.0.0:1389`
|
||||
- 支持能力:`Simple Bind` + `Search`
|
||||
|
||||
固定行为(与对接约定一致):
|
||||
|
||||
1. manager bind DN:`cn=s-cicd-app,OU=ServiceAccount,dc=macausjm-glp,dc=com`
|
||||
2. 用户搜索:base `dc=macausjm-glp,dc=com` + filter `(sAMAccountName={username})`
|
||||
3. 组搜索:base `OU=SecurityGroups,OU=GLPUsers,dc=macausjm-glp,dc=com` + filter `(member={userDn})`
|
||||
4. 用户条目属性:`sAMAccountName` / `cn` / `mail` / `memberOf`
|
||||
5. 组条目属性:`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` 代码里硬编码开发账号或组别。
|
||||
|
||||
## 本地启动
|
||||
|
||||
```bash
|
||||
cd Mock_Gateway
|
||||
npm install
|
||||
cp .env.example .env
|
||||
npm run start
|
||||
```
|
||||
|
||||
开发联调建议使用自动重启模式(监听 `src/` 与 `.env` 变更):
|
||||
|
||||
```bash
|
||||
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 成功后继续:
|
||||
|
||||
1. 登录本地 `Backend`
|
||||
2. 调用真实 `POST /api/v1/prize-redemptions`
|
||||
3. 把同一笔 `redemptionId` 记录进 mock 的 `redeemedpromotion/detail`
|
||||
|
||||
建议同时满足以下前提:
|
||||
|
||||
- 本地 `Backend` 已启动
|
||||
- 本地 `Backend` 已接到当前 `Mock_Gateway` 的 LDAP mock
|
||||
- 测试会员在本地 wallet 里对 `MOCK_PROMOTION_REDEMPTION_SOURCE_BUCKET` 有足够余额
|
||||
|
||||
推荐配置:
|
||||
|
||||
```bash
|
||||
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 请求里的 `loginId`
|
||||
- `MOCK_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`:
|
||||
|
||||
1. 显式覆盖,优先级最高
|
||||
2. 现有推断,作为兜底
|
||||
|
||||
显式覆盖支持两种写法:
|
||||
|
||||
- 请求级:
|
||||
- `data.issueTargetToWallet: [true, false, ...]`,按 `outcomeId` 顺序逐项覆盖;同一个 `outcomeId` 重复出现且每次选择不同 `Open Item / Auto Settle` 时,必须走这个数组
|
||||
- `data.issueTargetToWalletByOutcomeId: { "11330011": true, "11330012": false }`,按 outcomeId 精确覆盖
|
||||
- fixture 级:
|
||||
- `outcomeList[].mockIssueTargetToWallet`
|
||||
- `outcomeList[].prize.mockIssueTargetToWallet`
|
||||
|
||||
当以上显式覆盖都没有提供时,才回退到现有推断规则:
|
||||
|
||||
- `gisPrizeIdentifier[index]` 非空 -> `issueTargetToWallet=false`
|
||||
- 否则 `deliveryMode=EXTERNAL_ONLY` -> `false`
|
||||
- 其他情况 -> `true`
|
||||
|
||||
这意味着:
|
||||
|
||||
- 对 `USER_CHOICE` prize,如需稳定复现同一个 outcome 在 openitem / autosettle 之间切换,推荐直接在 mock 请求或 fixture 中提供显式覆盖,不要只依赖 `deliveryMode`
|
||||
- 如果一个请求里允许同一个 `outcomeId` 重复出现且每次选择不同,优先使用 `issueTargetToWallet` 数组;`issueTargetToWalletByOutcomeId` 只适合一个 outcomeId 对应一个固定值的场景
|
||||
- 如果调用方需要,也可以通过 body 的 `issueTargetToWalletByOutcomeId` / `issueTargetToWallet`,或自定义 header `X-Ewallet-Mock-Issue-Target-To-Wallet-By-Outcome-Id` 给 mock 传入显式覆盖;未提供时仍按当前默认推断执行
|
||||
- 旧链路不受影响;未提供覆盖时仍保持当前默认行为
|
||||
|
||||
### UI 点测同一个 outcome 的本地预设
|
||||
|
||||
如果不改 Backend,但希望在 UI 上对同一个 outcome 反复点测 `Open Item / Auto Settle`,可以先写入 mock runtime override:
|
||||
|
||||
```bash
|
||||
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 Item`
|
||||
- `issueTargetToWallet=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 启动环境中设置:
|
||||
|
||||
```bash
|
||||
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 两类关键故障:
|
||||
|
||||
1. `503` / 服务不可用
|
||||
|
||||
```bash
|
||||
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'
|
||||
```
|
||||
|
||||
2. 响应超时
|
||||
|
||||
```bash
|
||||
MOCK_MEMBER_PROFILE_DELAY_MS=15000
|
||||
```
|
||||
|
||||
建议:
|
||||
|
||||
- `MOCK_MEMBER_PROFILE_DELAY_MS` 需要大于 Backend 当前 member profile 调用的阻塞超时,才能稳定触发超时
|
||||
- 如果你只想打 member profile 故障,保持 `MOCK_EDIP_FORCE_ERROR_CODE` 为空,让 token 继续正常返回
|
||||
- 测完后把这些变量清空并重启 `Mock_Gateway`
|
||||
|
||||
## 快速验证
|
||||
|
||||
```bash
|
||||
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.json`
|
||||
- `MOCK_TASK_10852_MEMBER_EBONUS`:Task 10852 会员资料接口返回的 eBonus 数值(默认 `188`)
|
||||
- `MOCK_TOKEN_GET_FIXTURE_FILE`:`/edip/v1/token/get` JSON 模板文件路径(默认 `./fixtures/token.get.json`)
|
||||
- `MOCK_MEMBER_PROFILE_FIXTURE_FILE`:`/ewl/edip/v1/member/profile` JSON 模板文件路径(默认 `./fixtures/member.profile.json`)
|
||||
- `MOCK_MEMBER_PROFILE_FORCE_STATUS_CODE`:`/ewl/edip/v1/member/profile` 强制返回指定 HTTP 状态码,例如 `503`
|
||||
- `MOCK_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 的 `loginId`
|
||||
- `MOCK_PROMOTION_REDEMPTION_BRIDGE_TIMEOUT_MS`:桥接调用超时毫秒数(默认 `30000`);本地完整链路联调建议至少保留 `30000`
|
||||
- `MOCK_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,且会限制在 Backend `int` 可解析范围内,避免 Mock_Gateway 重启后重复复用旧 `redemptionId`
|
||||
- `MOCK_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`,加入或覆盖以下配置:
|
||||
|
||||
```bash
|
||||
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
|
||||
```
|
||||
|
||||
复现方式:
|
||||
|
||||
1. 启动 `Mock_Gateway`
|
||||
2. 前后端联调继续指向本地 mock 网关
|
||||
3. 在 `Wallet` 页面搜索会员 `80010766`
|
||||
4. 切到 `Promotion`
|
||||
5. 搜索 `cny`
|
||||
6. 选择 `CNY Gift Set Earn & Get-2026 / GS-8pts-LCH Gift Set Abalone + Scallop`
|
||||
7. 点击 `Redeem` 并完成确认
|
||||
|
||||
预期:
|
||||
|
||||
- 会员资料接口返回 `eBonus=8888`
|
||||
|
||||
- promotion 列表固定返回 Task 10766 专用 fixture
|
||||
- `POST /ewl/promotion/v1/playerpromotion/redeem` 固定返回 `Prize definition not found` 场景
|
||||
- 可稳定复现 10766 对应的 promotion redeem 失败明细展示问题
|
||||
|
||||
## Task 10852 复现场景
|
||||
|
||||
打开 `.env`,加入或覆盖以下配置:
|
||||
|
||||
```bash
|
||||
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
|
||||
```
|
||||
|
||||
复现方式:
|
||||
|
||||
1. 启动 `Mock_Gateway`
|
||||
2. 前后端联调继续指向本地 mock 网关
|
||||
3. 在 `Wallet` 页面搜索会员 `80010852`
|
||||
4. 切到 `Promotion`
|
||||
5. 搜索 `cny`
|
||||
6. 选择 `CNY Gift Set Earn & Get-2026`
|
||||
7. 勾选两个 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.json`
|
||||
- `fixtures/promotions.capture.80010852.json`
|
||||
- `fixtures/promotions.backdate.800038008.json`
|
||||
|
||||
适用场景:
|
||||
|
||||
- 需要保留某个会员的真实采样 promotion 规则
|
||||
- 想快速补充新的 `minOutcome / maxOutcome / outcomeList / prize` 组合
|
||||
- 不希望影响默认共享 mock 数据
|
||||
|
||||
|
||||
|
||||
## 使用本地测试开发网关的时候可以使用以下会员号
|
||||
按 `Mock_Gateway` 当前代码中的“定向逻辑 / 定向 fixture / 固定路由”统计,特别会员号共有 `5` 个(不含默认模板/示例号):
|
||||
|
||||
1. `800038008` - backdate 固定会员号。
|
||||
`/ewl/promotion/v1/promotion/entitledBackDate` 和 `/ewl/promotion/v1/promotion/entitledBackDate/all` 会固定返回这个会员号的 backdate promotion;仓库里也有它的普通 promotion fixture 和 backdate fixture。
|
||||
2. `80010766` - Task 10766 专用复现号。
|
||||
开启 `MOCK_TASK_10766_ENABLED=true` 后,会员资料固定返回 `eBonus=8888`,promotion 列表走专用 fixture,`playerpromotion/redeem` 固定复现 `Prize definition not found` 失败场景。
|
||||
3. `80010852` - Task 10852 专用复现号。
|
||||
开启 `MOCK_TASK_10852_ENABLED=true` 后,会员资料固定返回 `eBonus=188`,promotion 列表走专用 fixture,并强制提供可点击的 entitled 双 outcome 场景,用于验证多 outcome redeem。
|
||||
4. `80010991` - 完整链路 / 同 outcome 切换场景号。
|
||||
命中专用 `promotions.capture.80010991.json`,内含单 outcome reprint chain 和 3-outcome `USER_CHOICE` promotion;也用于 runtime fulfillment override,方便在 UI 上反复验证同一个 outcome 的 `Open Item / Auto Settle` 切换。
|
||||
5. `100000059` - redeemed promotion detail 专用号。
|
||||
命中 `award.promotions.100000059.json`,用于 `redeemedpromotion/detail` 返回账户级已兑 promotion 明细。
|
||||
|
||||
以下号码也出现在 `Mock_Gateway` 中,但更适合视为默认模板 / 示例数据,不计入上面的“特别会员号”:
|
||||
|
||||
1. `800048718` - 默认 promotion 抓包模板来源。
|
||||
没有专属定向逻辑,未命中其他专用场景时,普通账号会回落到这份默认 promotion fixture。
|
||||
2. `800049052` - 默认 redeemed promotions 示例号。
|
||||
只在 `redeemedpromotion/detail` 没传账号且没有账户级记录时,作为默认示例数据中的 `customerId` 出现。
|
||||
|
||||
800048718 老会员----换新账号----910700001
|
||||
Reference in New Issue
Block a user