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
This commit is contained in:
@@ -0,0 +1,214 @@
|
||||
# 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.
|
||||
Reference in New Issue
Block a user