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
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, fromuse / 1024. Existing monthly synchronization continues using this field only.packageFlow.totalFlow: upstreamtotalpackage, already MB.packageFlow.dataUsage: upstreamtargetpackageusage, already MB and cumulative over the package period, not necessarily the current month.packageFlow.remainingFlow: derived asmax(totalpackage - targetpackageusage, 0). Overage is retained in cumulative usage, but remaining flow never becomes negative.- The legacy top-level
totalFlowremains 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
- Stop and resume pages both list
/simlist/get-sim-switchoff-by-number. Never enable resume using that path. Obtain the real resume path, configureapi.resumePath, then explicitly enable operations when authorized. - The state page example says
state=1with an active description; the global table says 1=pending, 2=active. Mapping follows the table, not that example. - 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.