POS card terminal — CodePay (ECR Hub)
Nội dung này hiện chưa có sẵn bằng ngôn ngữ của bạn.
Executive summary
Section titled “Executive summary”CodePay integration in LionPOS uses the same POS bridge WebSocket and activation flow as other terminal tooling: clients pair via pos-bridge/activate, then exchange JSON messages whose shape follows CodePay’s ECR Hub contract (ecrhub.* topics). The monorepo implements this in @indochina/ecr-hub — package path packages/ecr-hub — via CodepayAdapter, encoder/parser helpers under manufacturers/codepay/, and shared constants (also re-exported from @indochina/shared for backwards compatibility).
Official reference (Kotlin samples, topic names, demo app_id): codepay-us/codepay-regsiter-same-terminal-integration-demo.
For platform-wide behaviour (payment intent, polling, terminal-webhook, bridge pairing), see POS card terminals & ECR Hub (PAX focus).
Transport and activation
Section titled “Transport and activation”| Concern | Detail |
|---|---|
| Channel | WebSocket — same wsUrl from POST /api/v1/pos-bridge/activate (or vendor dashboard activate) as the generic POS bridge; path /api/v1/pos-bridge/ws with terminalId + token query params. |
| Heartbeat | Clients may send bridge_heartbeat so the server keeps store_devices.is_connected accurate; the CodePay lab does this while testing. |
| Outcome to SaaS | Production bridges still turn terminal success/failure into POST /api/v1/pos/payments/terminal-webhook with x-pos-terminal-key — see POS and payment webhooks. |
Server ECR relay (ecr_relay_request / ecr_relay_response): when the SaaS backend dispatches through EcrHubService with createBridgeRelayTransport, the POS bridge carries opaque hub payloads to vendor-desktop, which opens the CodePay service WebSocket (relayTransportKind: "ws"). Those socket JSON bodies are still ecrhub.* envelopes as below; they are not re-wrapped except for the outer bridge message type and correlationId. Manufacturer is ECR_MFR.CODEPAY in application code. See the bridge-relay matrix and sequence in POS card terminals & ECR Hub (PAX focus) (section Bridge relay).
Message envelope
Section titled “Message envelope”Each outbound request is a JSON object with (at minimum):
| Field | Role |
|---|---|
version | Protocol version — constants CODEPAY_ECR_HUB_VERSION_1_1 ("1.1") or CODEPAY_ECR_HUB_VERSION_2_0 ("2.0"). |
app_id | Merchant / integration id from CodePay (device settings in vendor dashboard). The demo repo uses a sample id also exposed as CODEPAY_ECR_HUB_DEMO_APP_ID in code — replace in production. |
topic | ECR Hub topic (see table below). |
request_id | Correlates request/response; the hub uses the command’s correlationId. |
biz_data | Topic-specific payload (e.g. trans_type, amounts, merchant_order_no). |
Encoder implementation: packages/ecr-hub/src/manufacturers/codepay/codepay-encoder.ts.
Topics (ecrhub.*)
Section titled “Topics (ecrhub.*)”| Constant (code) | topic value | Typical use |
|---|---|---|
CODEPAY_ECR_HUB_TOPIC_PAY | ecrhub.pay.order | Sale, refund, void (via trans_type in biz_data). |
CODEPAY_ECR_HUB_TOPIC_TIP_ADJUSTMENT | ecrhub.pay.tip.adjustment | Post-auth tip adjustment. |
CODEPAY_ECR_HUB_TOPIC_BATCH_CLOSE | ecrhub.pay.batch.close | Batch close / settlement housekeeping. |
CODEPAY_ECR_HUB_TOPIC_QUERY | ecrhub.pay.query | Query / report-style lookup (REPORT in the adapter maps here). |
CODEPAY_ECR_HUB_TOPIC_REPRINT | ecrhub.pay.reprint | Reprint last receipt (PRINTER in the adapter). |
trans_type (pay order)
Section titled “trans_type (pay order)”String codes align with the official demo’s invoke constants:
| Constant | Value | Meaning |
|---|---|---|
CODEPAY_TRANS_TYPE_PURCHASE | 1 | Purchase / sale. |
CODEPAY_TRANS_TYPE_VOID | 2 | Void. |
CODEPAY_TRANS_TYPE_REFUND | 3 | Refund / return. |
CODEPAY_TRANS_TYPE_PRE_AUTH | 4 | Pre-authorization (constants exist; CodepayAdapter does not expose PRE_AUTH today — lab samples may build raw envelopes). |
CODEPAY_TRANS_TYPE_PRE_AUTH_COMPLETE | 6 | Complete pre-auth. |
CODEPAY_TRANS_TYPE_QUERY | 21 | Query. |
CODEPAY_TRANS_TYPE_REPRINT | 22 | Reprint. |
CODEPAY_TRANS_TYPE_BATCH_CLOSE | 23 | Batch close. |
CODEPAY_TRANS_TYPE_TIP_ADJUSTMENT | 24 | Tip adjustment. |
pay_scenario
Section titled “pay_scenario”Default in encoders: CODEPAY_PAY_SCENARIO_SWIPE_CARD (SWIPE_CARD). Other supported scenario constants include SCANQR_PAY, BSCANQR_PAY, CASH_PAY — pass via encoder payScenario options when wiring a custom transport.
Response parsing and trans_status
Section titled “Response parsing and trans_status”packages/ecr-hub/src/manufacturers/codepay/codepay-parser.ts normalizes terminal JSON into EcrNormalizedPayment fields used across the hub (auth code, trace/reference, card hints, tip cents, etc.). CodePay returns two common envelope shapes:
- Legacy ECR Hub — top-level
{ version, app_id, topic, request_id, biz_data }with no top-levelresponse_code/response_msg. Approval followsbiz_data.trans_status === "1"only (see constants below). - App-mode (e.g.
callAppMode) — top-levelresponse_code,response_msg(orresponse_message), plusbiz_data. Live terminals often returnresponse_code: "0"andresponse_msg: "SUCCESS"together withbiz_data.trans_status: "2"for a completed sale. The parser treats approval as zero host response code, no explicit decline phrase in the host message, and either a success-likeresponse_msg(SUCCESS/APPROVED/OK) or terminal-completetrans_statusof"1"or"2".trans_status3/4still mean cancelled / pending and are never approved.
| Value | Constant | Legacy biz_data-only envelope | App-mode + host fields |
|---|---|---|---|
1 | CODEPAY_TRANS_STATUS_SUCCESS | Approved | Completed / success |
2 | CODEPAY_TRANS_STATUS_FAIL | Declined / failed (legacy) | Often completed sale when paired with response_code: "0" and response_msg: "SUCCESS" |
3 | CODEPAY_TRANS_STATUS_CANCEL | Cancelled | Cancelled |
4 | CODEPAY_TRANS_STATUS_PENDING | Pending | Pending |
CodepayAdapter — supported canonical actions
Section titled “CodepayAdapter — supported canonical actions”CodepayAdapter requires options.appId. Default timeouts: 90s for payment flows, 30s for housekeeping (BATCH_CLOSE, REPORT, PRINTER).
EcrHubCommand.action | Maps to |
|---|---|
SALE | ecrhub.pay.order + purchase trans_type; optional metadata onScreenTip, onScreenSignature, description. |
RETURN | ecrhub.pay.order + refund; requires reference as original merchant_order_no; optional tipAmountCents. |
VOID_SALE / VOID_RETURN | ecrhub.pay.order + void; requires reference as orig_merchant_order_no. |
TIP_ADJUSTMENT | ecrhub.pay.tip.adjustment. |
BATCH_CLOSE | ecrhub.pay.batch.close. |
REPORT | ecrhub.pay.query (uses merchant_order_no from reference / correlationId). |
PRINTER | ecrhub.pay.reprint. |
Not implemented on the adapter today: SIGN, ABORT, and PRE_AUTH / pre-auth complete — use PAX or raw envelope construction only if the device contract requires it.
Import: @indochina/ecr-hub/codepay or @indochina/ecr-hub.
Vendor dashboard and web lab
Section titled “Vendor dashboard and web lab”| Area | Location |
|---|---|
| Device record | Vendor → Settings → Devices — set manufacturer to CodePay and configure app id (and LAN fields if applicable). |
| WebSocket lab | /dashboard/settings/codepay-ws — connect with wsUrl, send envelopes, inspect responses (developer tooling). |
| Sample payloads | apps/vendor-web/src/lib/codepay-ws-lab-samples.ts — includes pre-auth style samples for manual testing (may not match CodepayAdapter surface). |
Architecture (high level)
Section titled “Architecture (high level)”flowchart LR
subgraph browser["Vendor web"]
Lab["CodePay WS lab\n/settings/codepay-ws"]
Future["Future POS / bridge"]
end
subgraph bridge["POS bridge WebSocket"]
WS["/api/v1/pos-bridge/ws"]
end
subgraph device["CodePay terminal / app"]
ECR["ECR Hub runtime"]
end
Lab -->|"JSON ecrhub.*"| WS
Future -->|"JSON ecrhub.*"| WS
WS <--> ECR
Implementation checklist (CodePay-specific)
Section titled “Implementation checklist (CodePay-specific)”- Obtain production
app_idfrom CodePay; do not ship the demo id outside dev/test. - Wire
CodepayAdapter+ anEcrTransportthat sendsencode()payloads on the bridge socket and returns raw JSON strings todecode(). - Map
EcrHubResult.normalized+ command context intoTerminalPaymentWebhookDtoand POST toterminal-webhookwithx-pos-terminal-key. - Align
pay_scenariowith store payment methods (card vs QR). - If
PRE_AUTHis required, extendCodepayAdapteror document a dedicated path — constants already exist incodepay-constants.ts. - Add/extend
*.spec.tsfor any new adapter branches per project rules.
Related
Section titled “Related”- POS card terminals & ECR Hub (PAX focus) — bridge pairing, webhook, ECR Hub overview
- POS and payment webhooks
- Frontend applications
Document history
Section titled “Document history”| Version | Date | Notes |
|---|---|---|
| 1.0 | 2026-04-26 | Initial CodePay ECR Hub reference: envelope, topics, adapter, parser, vendor-web lab |