# idcard-2fa **Repository Path**: ghink/idcard-2fa ## Basic Information - **Project Name**: idcard-2fa - **Description**: 2FA Tools for CN IDCard - **Primary Language**: Unknown - **License**: Apache-2.0 - **Default Branch**: main - **Homepage**: None - **GVP Project**: No ## Statistics - **Stars**: 0 - **Forks**: 0 - **Created**: 2026-10-11 - **Last Updated**: 2026-10-11 ## Categories & Tags **Categories**: Uncategorized **Tags**: None ## README # idcard-2fa A desktop tool for checking a name against a Chinese mainland ID number through the Ghink OpenAPI platform. ## Build and run ```sh go build -o idcard-2fa . ./idcard-2fa ``` Built and run on macOS/arm64. The fyne desktop driver needs cgo and OpenGL; other platforms are untested. ## Configuration The first file that exists is loaded, in this order: 1. the file named by `IDCARD_2FA_CONFIG` (it must exist when the variable is set) 2. `config.yaml` in the working directory 3. `config.yaml` next to the executable 4. `idcard-2fa/config.yaml` under the user config dir, which on macOS is `~/Library/Application Support/idcard-2fa/config.yaml` A `config_debug.yaml` in the same directory overrides it and drops the log level to debug. That file is in `.gitignore`, so real credentials go there rather than into the repository. Relative paths in the config resolve against the config file's directory. `ghinkOpenAPI` holds one `secretID`/`secretKey` pair per space. The picker in the window header lists those keys, and picking one fetches a token; the header shows the connection state. | `verify` key | Meaning | | --- | --- | | `workers` | Clients a batch run builds, one request at a time each | | `timeoutSeconds` | Bound on one attempt | | `maxRetries` | Attempts, the first one included | | `retryDelaySeconds` | Wait between attempts. Exponential backoff is off | ## Use **Single**: type a name and an ID number, press Enter or click 核验. **Batch**: load a list from a file or paste one. Each line is `姓名,身份证号`, comma or tab separated; extra columns are ignored. An exported result file loads back unchanged. Results land in a four column table and export to the same four columns. 停止 marks every unsent row as cancelled. A row already on the wire is reported when it comes back; the SDK call takes no context, so it cannot be interrupted. ## Statuses | Status | Meaning | | --- | --- | | 一致 | The platform matched the name and the number | | 不一致 | The platform did not match them | | 格式错误 | Rejected locally: not 18 digits, bad checksum, or a missing field. No request is sent | | 请求失败 | Sent, no answer. The detail column carries the platform message, the API code and the request ID | | 已取消 | Stopped before it was sent | Names and numbers are checked and normalized before anything is sent, so a malformed or pasted-with-separators number is reported as 格式错误 instead of going out to the platform. ## Privacy The log runs at info level and does not write names or ID numbers. At debug level the SDK logs request and response bodies, which do carry them: turn it off and delete `logs/` when you are done. ## Dependencies - `go.gh.ink/openapi/sdk/20260512/v3` v3.2.1 - `fyne.io/fyne/v2` v2.8.1 - `go.gh.ink/json`, `go.uber.org/zap` with lumberjack, `github.com/spf13/viper` ## Tests ```sh go test -race ./... ``` `internal/verify` runs against an `httptest` stand-in of the platform through the real SDK client; `internal/ui` taps buttons through fyne's test driver. Neither needs credentials or network egress.