# Mingqian v3 integration ## Scope and deployment This is a third-party platform adapter, not a shared-token adapter. Use `temp_key=sim_mingqian_v3` and `temp_model=direct`. Deploy BOTH the gateway and proxy builds containing this key, then save/refresh the channel in both services. A configuration refresh cannot load a template into an old binary. Worktrees for this feature: - Gateway: `F:\Work\iotlcm-upstream-chan` - Proxy: `F:\Work\iotlcm-upstream-proxy` - Branch in each repository: `feat/mingqian-api-integration` The LCM response model update lives in `F:\Work\lcm-mingqian`, branch `feat/mingqian-flow-mapping`, based on `origin/master`. Deploy this LCM build as well to preserve package flow fields in the channel test page. The page already renders the returned JSON; no frontend changes are required. Without the LCM model update, its typed response parser discards the new fields. Do not deploy the old checkout by mistake. This feature does not edit the existing runtime service address, production database, or operator settings. Point the proxy's `gateway.address` at the actual gateway HTTP listener. Do not configure the proxy to call Mingqian directly. ## Admin configuration Create a template named Mingqian third-party v3: - Template key: `sim_mingqian_v3` - Model: `direct` - Status: Enabled (select the UI option; do not assume the numeric enum) - Template JSON: copy `docs/config/mingqian_v3.json` Create a channel: - Channel key: a unique value such as `mingqian_001` - Template: select the template above - AppKey: the upstream **appId** - AppSecret: the upstream signing **APPKEY** (NOT a shared token) - Channel JSON: `{}` (`docs/config/mingqian_channel.json`) - Status: Enabled - Carrier: select the actual carrier of the cards/account; this document covers three carriers and does not establish which one your account uses. Credentials are read from channel AppKey/AppSecret only. Channel JSON does not override template configuration. Never commit real credentials. ## Supported standard gateway capabilities | Capability | Upstream relative path | Behavior | | --- | --- | --- | | Basic information | `/simlist/get-state-by-number` | ICCID, MSISDN, raw state and description only | | Card lifecycle status | `/simlist/get-state-by-number` | Convert upstream states to gateway enums | | Current-month usage | `/simlist/get-flow-use-by-number` | `use` KB / 1024 -> `dataUsage` MB | | Package flow | `/use/get-card-use-by-number` | `totalpackage` and `targetpackageusage` MB -> separate `packageFlow` in the same real-time flow response | | Stop | `/simlist/get-sim-switchoff-by-number` | Disabled unless `api.enableOperations=true` | | Resume | Confirmed `api.resumePath` | Disabled by default; no guessed endpoint | Queries split into at most 50 identifiers. Status changes split into at most 20 identifiers. Responses are matched by the requested ICCID or MSISDN, not by array position. Missing/duplicate cards, missing/negative usage, missing status and per-card operation failures are returned as failures, never as successful zero usage. IMSI-only requests are rejected before network access. Basic information is partial: no fake IMSI, activation date, or opening date. The upstream `activedate` is a PACKAGE effective date, not card activation. Use the admin test's direct-single-identifier mode. Three-code completion cannot succeed unless all three codes are available from another source. State mapping: 1 -> pending(1), 2 -> active(2), 3 -> stopped(4), 4 -> test(6), 5 -> stock(7), 6 -> cancelled(9). States 4 and 5 appear in the inventory example; the global table omits them. State 7 (expired) and other unmapped states return an explicit error rather than treating expiry as permanent cancellation. Raw state remains available in basic information. Not implemented as standard gateway capabilities: account-wide inventory sync, IMEI lookup, APN/session/device/binding/stop-reason diagnostics, historical daily/monthly usage, real-name status, voice-number whitelists, SMS, account balance, recharge and order operations. Unsupported standard methods return explicit errors without contacting upstream. An IMEI field in the account inventory must not imply that binding is enabled. The inventory endpoint is account-wide and paginated; this adapter deliberately does not scan all pages on every single-card query. ## Flow mapping and partial failures Select the admin test's real-time flow item (`simDataUsage`), or POST to the gateway/proxy `/sim/query/sim-datausage` with the normal `simKeys` and empty `reqData`. For each batch of at most 50 identifiers the adapter calls both read-only flow endpoints, sharing the same account rate limiter. Results from each endpoint are matched independently by ICCID/MSISDN, not by response order. For 51 cards this makes four upstream calls, not two. Example `resData`, all units MB: ```json { "dataUsage": 1, "packageFlow": { "totalFlow": 10240, "dataUsage": 8192, "remainingFlow": 2048 } } ``` - `dataUsage`: current-month usage, from `use / 1024`. Existing monthly synchronization continues using this field only. - `packageFlow.totalFlow`: upstream `totalpackage`, already MB. - `packageFlow.dataUsage`: upstream `targetpackageusage`, already MB and cumulative over the package period, not necessarily the current month. - `packageFlow.remainingFlow`: derived as `max(totalpackage - targetpackageusage, 0)`. Overage is retained in cumulative usage, but remaining flow never becomes negative. - The legacy top-level `totalFlow` remains absent for Mingqian. Do not subtract current-month usage from a cross-month package total. Missing/null/negative/non-numeric amounts are failures, not successful zeroes. Actual zero values are valid. When monthly usage succeeds but package flow fails, the card retains its successful monthly reading, omits `packageFlow`, and includes `packageFlowError` plus a warning in the per-card `message`. If monthly usage fails, the per-card code remains failure even if a package snapshot is present; never write the package cumulative amount as monthly usage. The channel test's monthly and daily items request historical periods. The current Mingqian documentation provides neither historical endpoint, so these remain explicitly unsupported rather than returning current-period numbers. Real-time sessions, online status, APN and IP likewise remain unsupported; neither lifecycle state nor nonzero usage proves a currently active session. This update exposes package flow in API/channel-test results. It does not persist package snapshots, change card-list balance calculations, or change charging, quotas, or monthly synchronization semantics. ## Wire contract and safety JSON POST envelope: ```json { "body": { "appId": "YOUR_APP_ID", "reqtime": "2026-09-17", "timestamp": "CURRENT_UNIX_MILLISECONDS_PLUS_60000", "transid": "yyyyMMddHHmmssfff_PLUS_SIX_RANDOM_HEX_CHARACTERS", "version": "3.0", "sign": "COMPUTED_SIGNATURE" }, "data": "{\"numberArray\":[\"YOUR_TEST_ICCID\"]}" } ``` The `data` value is a serialized JSON STRING. Dates use UTC+8. The timestamp is current time plus one minute, in milliseconds. Sign excludes `sign` itself: sort common parameter keys, concatenate `key_value` for each without additional separators, prepend/append APPKEY, and produce lowercase MD5. This is the literal interpretation of the signing prose and example casing; no official complete credential/sign test vector was supplied. Local tests verify this interpretation, not acceptance by the upstream server. Confirm against one official sample or a permitted read-only query before release. Successful business code is 200 (not zero). HTTP errors, non-200 business codes, malformed envelopes and absent data fail closed. No automatic retries or HTTP redirects, especially for state-changing requests. Raw response bodies and secrets are not logged. Client response size is bounded at 4 MiB. An in-process limiter shared by base URL + appId spaces calls at least 60ms apart (~166/10s, below the documented 200/10s). It does NOT coordinate separate gateway replicas or other applications using the same account. Use a shared egress limit or allocate a per-replica budget before scaling those accounts. ## Documentation contradictions requiring upstream confirmation 1. Stop and resume pages both list `/simlist/get-sim-switchoff-by-number`. Never enable resume using that path. Obtain the real resume path, configure `api.resumePath`, then explicitly enable operations when authorized. 2. The state page example says `state=1` with an active description; the global table says 1=pending, 2=active. Mapping follows the table, not that example. 3. Confirm signature concatenation/casing with an official sample. ## Verification Use only a sandbox or local `httptest` for stop/resume. No real stop, resume, SMS, purchase or recharge request was sent during implementation. Gateway targeted tests: ```text go test ./internal/service/mingqian go test ./internal/logic/upstreamimpl -run TestMingqianRegistration go build ./... ``` Proxy targeted tests: ```text go test ./internal/logic/upstreamimpl -run TestMingqianProxyTemplate go test ./internal/logic/upstreamimpl -run TestMingqianProxyPreservesFlowFields go build ./... ``` LCM response-model tests (run in `F:\Work\lcm-mingqian\server`): ```text go test ./internal/model -run SimDataUsage go build ./... ``` Initial live verification should select ONLY basic info, card status and current-month usage using a permitted ICCID/MSISDN. Do not use real operations to validate connectivity. A successful mock test is not proof of live access.