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:
MiFaZhan
2026-10-22 15:42:29 +08:00
commit 96b1edff45
191 changed files with 30805 additions and 0 deletions
+214
View File
@@ -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.