Vendor Adapters
Per-vendor implementation notes — one page per adapter, grouped by product line, documenting each vendor's auth, catalog, order, webhook, delivery, and unique quirks.
This section documents every vendor adapter individually. For the architecture (factory routing, the DirectTopUpVendor/VoucherVendor/EsimVendor interfaces, vendor_attributes config), see Vendors & Integrations. For how the orchestrator drives all of them, see Order Lifecycle.
Each adapter is keyed by a short vendor.code its factory switches on. Credentials live in the vendor_attributes DB table, never env.
Voucher Vendors
| Vendor | Code | Model | Delivery | Headline quirk |
|---|---|---|---|---|
| The Reward Store | TRS | async, poll | code/pin/link | no tests/mock; cancel is a no-op |
| Runa | RUNA | async, link | claim URL | Svix webhook; singular endpoints; decimal strings |
| EpinForce | EPIN | async, poll-only | XLSX/ZIP files | stateful shared cart + per-token mutex |
| iRewardify | IRW | async, poll | card or claim link | custom unsigned webhook; memory-only token |
| NeoCurrency | NEO | sync inline | activation link | 24h JWT; heavy spec drift |
| Wupex | WPX | sync/async | serial code+pin | Cloudflare 429 backoff; currency from name |
| Grasshopper | GH | inverted | code+pin+claim | Octopus mints; only hashes sent to GH |
| Octopus (federated) | OCTO | async + webhook | code/pin/link | consumes another Octopus; self-loop guard |
Top-up Vendors
| Vendor | Code | Model | Headline quirk |
|---|---|---|---|
| SEAGM | SEAGM | async + signed webhook | HMAC in the query string; par_value ≠ money |
| DT One | DTONE | async, poll | reference min/max/discount impl; no default webhook |
| Wupex | WPX | sync | server/zone lookup; webhook unsupported |
| Octopus (federated) | OCTO_TOPUP | async + webhook | composite productID:variantID; mobile lookup |
eSIM Vendors
| Vendor | Code | Model | Headline quirk |
|---|---|---|---|
| DT One eSIM | DTONE_ESIM | async PIN purchase | URL path-token webhook; install/activation poll |
| Octopus (federated) | OCTO_ESIM | async, webhook nudge | delivered=PROCESSING nudge → cron poll completes |
Several codes are declared in types/common.go but not implemented (LC, BNC, RZP, WOGI, NCTV, DIGC, VCHG, AQP, GLT, FLZ, WC, TRF) — reserved/planned, no adapter. Wupex and Octopus each appear on multiple lines as separate adapters sharing one DB row.
Cross-cutting patterns
- Auth ranges from static keys (EPIN, WPX), HTTP Basic (TRS, DT One), HMAC query-signing (SEAGM), lazy OAuth (NEO, IRW), to login-tokens (OCTO family).
- Delivery is code/pin, claim link, file (EPIN), account credit (topup), or activation_code/ICCID (eSIM).
- Webhooks are Svix (Runa), HMAC (OCTO, SEAGM), unsigned (IRW, DT One), path-token (eSIM), or none (NEO, EPIN, WPX).
ErrShouldReCreate(vendor lost the order → clear id, re-CREATE) andErrOrderNotFound/ErrDuplicateMerchantRefare the shared orchestration sentinels — see Order Lifecycle → recreate protocol.- Most adapters have a mocky-balboa route + contract test; the OCTO family instead uses the in-process
test/octopusfake/upstream.
Vendor Configuration
The vendor_attributes credential/config catalog — every attribute key each adapter reads, the shared keys, the vendors-table config columns, the onboarding checklist, and the fact that every vendor secret is stored plaintext.
TRS — The Reward Store
Voucher vendor adapter — HTTP Basic auth, async create + poll delivery, no webhook, and several under-tested rough edges.