125 lines
8.2 KiB
Markdown
125 lines
8.2 KiB
Markdown
# CreditCall payment streaming
|
|
|
|
Deploy ChipDNAClientCLI, then hardlink, then Operafyne. No database or configuration
|
|
migration is needed. The existing CreditCall provider selection enables the new
|
|
SALE and PREAUTH routes; CreditCall does not implement the generic payment provider interface.
|
|
|
|
## Contracts
|
|
|
|
`POST /api/payment/sale` accepts the existing JSON sale request, for example
|
|
`{"amount":1234,"confirmNo":"BOOKING-123","currency":"GBP"}`. Amount remains in
|
|
minor units. CreditCall uses its existing SDK transaction reference generation.
|
|
|
|
`POST /api/payment/preauth` accepts string fields `amount`, `transactionType`
|
|
and `checkoutDate`. Positive preauth sends the existing `Sale` input and checkout
|
|
string; zero-value verification sends `{"amount":"","transactionType":"AccountVerification","checkoutDate":""}`.
|
|
The returned `ACCOUNT VERIFICATION` type is matched case-insensitively and succeeds
|
|
without persistence. Returned approved `SALE` schedules existing SQL persistence
|
|
using provider-returned `TOTAL_AMOUNT`, never the request amount. PREAUTH does not
|
|
confirm. Checkout remains departure-derived midnight UTC in the existing string
|
|
format; SQL's existing date conversion and 48-hour release calculation are unchanged.
|
|
|
|
For CreditCall, responses contain newline-delimited JSON:
|
|
|
|
```json
|
|
{"type":"status","code":"PAYMENT_PRESENT_CARD"}
|
|
{"type":"result","result":{"outcome":"approved","message":"Payment approved","httpStatus":200,"status":{"code":200,"message":"Approved"},"transactionReference":"native-reference","cardType":"Visa","maskedCardNumber":"************1234","expiryDate":"1228","cardHash":"existing-hash","cardReference":"existing-card-reference"}}
|
|
```
|
|
|
|
`outcome` is `approved`, `declined`, `cancelled`, `timeout`, or `error`. Approval
|
|
is produced only by the shared CreditCall transaction/finalization core, including
|
|
SALE confirmation behavior; PREAUTH uses its existing unconfirmed-result rules. `httpStatus` preserves the equivalent legacy
|
|
operation status even after streaming commits HTTP 200. `status` preserves the
|
|
existing processor `StatusRec`. Failure `message` preserves the plain description
|
|
used by the legacy flow, including its existing interpretation quirks.
|
|
|
|
Card fields are emitted only on success. Unmasked or unexpected card-number data
|
|
is omitted; encoding is not masking. Receipts and raw SDK parameter bags are not
|
|
sent to Operafyne. The new adapter never builds a redirect URL. Dojo and PayBridge
|
|
continue using their existing `{"type":"result","response":...}` contract.
|
|
|
|
Hardlink calls `POST /start-transaction-stream/` on ChipDNAClientCLI with
|
|
`{"amount":"1234","transactionType":"Sale"}`. Its NDJSON consists of allowlisted
|
|
`status` frames (`source`, `value`), a single `result` containing allowlisted SDK
|
|
fields, or a sanitized `error`. `TRANSACTION_TYPE` and optional `TOTAL_AMOUNT`
|
|
are included only when returned by the provider. They are never synthesized and
|
|
are not added to the kiosk-facing result. AccountVerification normally omits
|
|
`TOTAL_AMOUNT`. Receipt XML may be a JSON string field needed by
|
|
hardlink's existing receipt handler; it is never a raw line in the stream.
|
|
SALE confirmation continues through the existing, separate XML endpoint.
|
|
|
|
## Lifetime and compatibility
|
|
|
|
- `/start-transaction/`, `/takepayment`, and `/takepreauth` retain their existing
|
|
external contracts. Both SALE and PREAUTH now stream to Operafyne; existing SQL
|
|
persistence/release behavior remains unchanged.
|
|
- Operafyne uses a private 120-second CreditCall client for SALE and PREAUTH.
|
|
This is only the kiosk wait boundary; Dojo/PayBridge clients are unchanged.
|
|
Timeout/cancellation is technical, not an authoritative decline or automatically
|
|
retryable result. It never triggers a second start or legacy endpoint fallback.
|
|
- Validation uses the inbound request. At financial dispatch handoff, hardlink
|
|
detaches cancellation with `context.WithoutCancel`. Inbound cancellation and
|
|
write failures control only delivery; result processing, SALE confirmation,
|
|
receipts and PREAUTH persistence scheduling continue independently.
|
|
- Start and each SALE confirmation call retain their independent 300-second timeout.
|
|
Confirmation still uses two attempts, retrying transport/read errors with the
|
|
existing two-second delay. The generic whole-operation timeout is not used.
|
|
- Kiosk cancellation or failed/blocked kiosk delivery does not cancel upstream reading,
|
|
confirmation, receipt handling, or PREAUTH persistence scheduling. Progress queues may drop hints when full;
|
|
final results have a separate slot and are delivered at most once.
|
|
- Only the response writer writes frames. Transaction execution never waits
|
|
for progress delivery. No additional delivery timer or whole-operation deadline
|
|
shortens the existing HTTP call bounds.
|
|
- Native SDK 3.17 updates use `UPDATE`; card notifications use `NOTIFICATION`,
|
|
retained as `CARD_STATUS` on the internal wire. Normal progress does not require
|
|
a reference: it is accepted only inside the existing serial transaction's active
|
|
observational window. A supplied nonempty reference must match. The window opens
|
|
immediately before the SDK start call and closes immediately at
|
|
`TransactionFinished`; finalization never waits for card removal.
|
|
- `CardRemovalRequested` and `CardRemovalEnforced` follow the same active-window
|
|
rule as other progress, including when no reference is supplied. Real Miura
|
|
insertion-recovery sequences can repeat present-card and remove-card prompts
|
|
within one transaction; these repeated prompts are not deduplicated. Outside
|
|
the active window they are discarded. `Removed` remains omitted even with a
|
|
reference, and the existing `Inserted` mapping is unchanged.
|
|
- Ownership is best-effort UI observation. SDK 3.17 does not establish that every
|
|
queued reference-less callback, including removal, has drained before another transaction
|
|
starts. Such a callback may briefly display stale progress in a later active
|
|
window. This accepted limitation must never affect success, decline, cancellation,
|
|
timeout outcomes, confirmation, retry, receipts, PMS posting, or business state.
|
|
- After timeout, an ambiguous start error, an asynchronous SDK error during an
|
|
active window, or reference reuse/overlap, progress remains suppressed for that
|
|
`Client` lifetime across SALE and PREAUTH. New transactions, elapsed time, callbacks and automatic
|
|
reconnect do not reset the guard. Payments remain enabled.
|
|
- Only the exact synchronous `ClientNotConnectedToServer` error safely clears an
|
|
unsuppressed window and releases its unused reference: SDK 3.17 `StartCommand`
|
|
returns it before `SendRequest`. Validation errors, mixed errors and all other
|
|
unproven errors suppress observation. Safe pre-dispatch rejection never clears
|
|
an existing suppression latch.
|
|
- Progress cannot approve, decline, confirm, cancel, or retry a transaction.
|
|
`OnlineAuthCompleted` means waiting; `Removed` and unknown events are omitted.
|
|
|
|
## Automated verification
|
|
|
|
In hardlink, use `go test -count=1 -skip '^Test_SendMail$' ./...` to exclude the
|
|
existing test that sends real email. Focused tests cover legacy parity, malformed
|
|
XML/NDJSON, retained confirmation fields and receipts, retries, disconnects,
|
|
backpressure, field filtering, and conservative status mapping. Race checks cover
|
|
the changed handler and mapper packages. No test proves absence of orphan holds.
|
|
|
|
In ChipDNAClientCLI, build `ChipDnaClient.sln` and `Tests/StreamingTests.csproj`
|
|
with MSBuild, then run `Tests/bin/Debug/ChipDNAClient.StreamingTests.exe`. The
|
|
test executable links the production streaming code and needs no terminal.
|
|
|
|
In Operafyne, run `go test -count=1 ./...`; the service tests cover structured
|
|
CreditCall SALE/PREAUTH, unchanged legacy requests, the 120-second UX boundary,
|
|
cancellation after dispatch, failure/retry parity, and existing
|
|
Dojo/PayBridge response handling. Run `go vet ./...`, `go build ./...`, and
|
|
`git diff --check` in both Go repositories.
|
|
|
|
Physical account-verification testing confirmed approved `ACCOUNT VERIFICATION`
|
|
with no `TOTAL_AMOUNT`. A monetary `/takepayment` test confirmed returned minor
|
|
units; positive PREAUTH through the new transport still needs physical Miura
|
|
validation. Automated tests do not replace that check. Receipt fields such as
|
|
`NoChargeDeclaration` retain the existing provider-entry rendering behavior.
|