Files
iotlcm/docs/mingqian-integration.md
T
MiFaZhan 96b1edff45 chore: 初始开源发布
iotlcm-upstream-chan:运营商上游通道适配服务(统一 /sim/* 协议)。

- 内联原私有依赖:yunze-public → internal/pub/(10 包 18 文件),
  yunze-pb/pb → internal/pb/(9 文件);Consul 注册改用官方
  gogf/gf/contrib/registry/consul/v2(API 兼容)
- Go module:yz-svr → git.5iot.com/iotlcm-public/iotlcm-upstream-chan
- 修复 mingqian 包测试:实现重构后 `adapter.operations` 字段已移除,
  测试断言按当前实现语义重写(不改产品行为)
- 凭据与内部标识脱敏:MySQL/Redis/Consul 凭据、私网与生产 IP、
  内网域名、真实手机号、注释里的真实 token/transid
- 移除内部资产:CI 触发器、生产通道种子 SQL、真实凭据测试资源文档
- Dockerfile 改用公共基础镜像,移除写死的 registry 凭据
- 补 Apache-2.0 LICENSE,重写 README,LF 行尾 + .gitattributes
2026-10-22 16:08:06 +08:00

9.5 KiB

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:

{
  "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:

{
  "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:

go test ./internal/service/mingqian
go test ./internal/logic/upstreamimpl -run TestMingqianRegistration
go build ./...

Proxy targeted tests:

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):

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.