Payment providers
The registered payment providers, and the operator actions against one.
The payment providers this store offers, and the operator actions against one. Configuration itself stays in each provider plugin's own Grav blueprint.
List payment providers
/api/v1/kahunacart/providers
Every registered payment method with its label, the capabilities it declares, whether it can be connection-checked, whether it can register its own webhook endpoint, whether it syncs products, what automatic sync is configured to do, and which one checkout starts on. Each also carries last_check (the kept answer of its last check_provider, or null), deliveries (its webhook log totals, last arrival and failure streak, or null when none has arrived) and webhook_mode (endpoint, per_payment or none). A store that sells in more than one currency also gets currency_coverage: for each currency it sells in, base first, the payment methods that take it (slug to name), and an empty list means a shopper in that currency cannot check out. Credentials live in each provider plugin's own settings and are never reported here.
Response
Answers {providers: [{slug, label, capabilities, can_check, can_setup_webhook, is_default, can_sync, sync_direction}]}. No credential ever appears in a response.
Check a provider's connection
/api/v1/kahunacart/providers/{slug}/check
Ask a payment provider to prove the credentials already configured for it actually work, and report what it resolved, such as the account and the environment. Where the driver can, it also looks up this store's webhook endpoint at the platform, changing nothing. state is ok, warning or failed: warning is a check that passed with something wrong in the webhook (no endpoint, switched off, missing events, or three failed deliveries in a row), each spelled out in warnings. The answer is kept and shown on the Payments card. A failing check is a successful call: it answers 200 with ok false and the provider's own message. The error statuses are kept for a provider that cannot be asked at all, which is a different thing a merchant needs told apart.
Parameters
| Name | Type | Description |
|---|---|---|
| slug required | string | Provider slug, from list_providers |
Sync the catalog with a provider
/api/v1/kahunacart/providers/{slug}/sync
Push this store's catalog to a payment provider, or pull the provider's into it, and report how many products moved. Push is the default because it only restates what this store already believes; pull rewrites local products from the provider's copy and has to be asked for by name. The provider's configured automatic sync direction is not consulted, so a merchant can sync once without committing to syncing forever. A network or API failure answers 200 with ok false and the provider's message. A pull skips any price the provider reports in a currency other than the store's base currency and says how many in skipped_prices, a key that is only there when something was skipped.
Parameters
| Name | Type | Description |
|---|---|---|
| slug required | string | Provider slug, from list_providers |
| direction optional | string |
pull rewrites local products from the provider's copy
One of:
push, pullDefault:
push |
Set up a provider's webhook
/api/v1/kahunacart/providers/{slug}/webhook
Ask a provider to register this store's webhook endpoint with it, subscribed to exactly the events it handles, and write whatever signing secret comes back into that provider's own plugin settings. The secret goes to disk and is never returned. The response also names endpoints registered against this store's route at a different address, which is the residue a site leaves behind when it moves off a tunnel or out of staging. Send reset true to delete this store's existing endpoints and register afresh, which is also how a signing secret is rotated on a platform that will not disclose one twice.
Parameters
| Name | Type | Description |
|---|---|---|
| slug required | string | Provider slug, from list_providers |
| reset optional | boolean |
Delete this store's existing endpoints on the provider first, then register
Default:
false |
Make a provider the default
/api/v1/kahunacart/providers/{slug}/default
Write checkout.default_provider so checkout starts on this payment method. Stored against the store rather than the provider, because two stores running the same provider disagree about it. A configured slug that is not registered, or one filtered out because the cart holds something shippable, falls back to the first method actually offered.
Parameters
| Name | Type | Description |
|---|---|---|
| slug required | string | Provider slug, from list_providers |
List a provider's card readers
/api/v1/kahunacart/providers/{slug}/readers
The card readers on a payment provider's account, as the provider reports them now: each with its id, the label it was given, its status (online, offline or busy), its model and the provider's location reference, and how the provider pairs readers: pairing device_code (the reader shows a code, send it with pair_provider_reader) or app_code (get a code with begin_reader_pairing and type it into the reader). The store keeps no list of readers of its own. 422 for a provider that cannot take a card on a reader, 404 for one that is not registered.
Parameters
| Name | Type | Description |
|---|---|---|
| slug required | string | Provider slug, from list_providers; it must declare card_present |
Pair a card reader
/api/v1/kahunacart/providers/{slug}/readers
Register a card reader with a payment provider from the code the reader shows on its screen (a Stripe registration code, a SumUp pairing code), and answer the reader. For a provider whose readers take a code instead (pairing app_code on list_provider_readers, like Square) use begin_reader_pairing. A code the provider will not pair answers 422 with the provider's own sentence.
Parameters
| Name | Type | Description |
|---|---|---|
| slug required | string | Provider slug, from list_providers |
| code required | string | The code the reader shows |
| label optional | string | What to call the reader, like Front counter |
| location_ref optional | string | The provider's own location for the reader, when it has such a thing |
Get a code to pair a card reader
/api/v1/kahunacart/providers/{slug}/readers/pairing
For a provider whose readers pair from a code the provider makes (pairing app_code on list_provider_readers, like Square): ask the provider for a code, and answer the pairing with its id, the code to type into the reader, its status (waiting) and when it expires. Then read get_reader_pairing until it says paired. 422 for a provider whose readers show their own code (use pair_provider_reader) or when the provider refuses, with its sentence.
Parameters
| Name | Type | Description |
|---|---|---|
| slug required | string | Provider slug, from list_providers |
| label optional | string | What to call the reader, like Front counter |
| location_ref optional | string | The provider's own location for the reader, when it has such a thing |
Read a card reader pairing
/api/v1/kahunacart/providers/{slug}/readers/pairing/{pairing}
How a pairing from begin_reader_pairing stands: waiting for the code to be typed into a reader, expired (start again), or paired, with the reader that took it. A read: nothing changes. 404 when the provider has no pairing by that id.
Parameters
| Name | Type | Description |
|---|---|---|
| slug required | string | Provider slug, from list_providers |
| pairing required | string | The pairing id begin_reader_pairing answered |
Remove a card reader
/api/v1/kahunacart/providers/{slug}/readers/{reader}
Take a card reader off a payment provider's account. 404 when no reader by that id is on the account.
Parameters
| Name | Type | Description |
|---|---|---|
| slug required | string | Provider slug, from list_providers |
| reader required | string | Reader id, from list_provider_readers |
Take a card payment on a reader
/api/v1/kahunacart/orders/{id}/reader-payments
Put an amount on a card reader for an order and come back at once with the payment pending; the customer then taps, inserts or swipes on the reader. The amount may be less than the order owes, and the order is then part paid and the rest can be paid another way; it may not be more. Send the same idempotency_key on a retry and the payment already started is answered instead of a second one. The status is pending, or checking when the provider's answer never came back (nothing is known yet; it is sent again under the same key by refresh_reader_payment). 409 when the order is already paid or cancelled, owes nothing, already has a card payment waiting on a reader, or has a checkout open online that could still be paid (unless the order is paid in parts); 422 for an amount over what is owed, a provider that cannot take a card on a reader, or a reader that refused the payment, with the reason. Then call refresh_reader_payment every couple of seconds while the status is pending, checking or cancelling.
Parameters
| Name | Type | Description |
|---|---|---|
| id required | integer | Order id |
| provider required | string | Provider slug; it must declare card_present |
| reader required | string | Reader id, from list_provider_readers |
| amount_minor optional | integer | What to take, in minor units of the order currency |
| amount optional | string | What to take as a decimal string, like "12.50", when amount_minor is not sent |
| idempotency_key optional | string | The same string on a retry of the same payment, at most 128 characters |
Read a card reader payment
/api/v1/kahunacart/orders/{id}/reader-payments/{tid}
How a card payment on a reader stands as the store has it: pending, checking, cancelling, succeeded, failed (with the reason in plain words), cancelled or timed_out, with the amount, the reader, the provider's reference and order_settled (false while the money is recorded and the order is still being completed). A read: the provider is not asked and nothing changes; refresh_reader_payment asks it.
Parameters
| Name | Type | Description |
|---|---|---|
| id required | integer | Order id |
| tid required | integer | The transaction_id start_reader_payment answered |
Refresh a card reader payment
/api/v1/kahunacart/orders/{id}/reader-payments/{tid}/refresh
Ask the provider how a card payment on a reader stands and apply the answer exactly as its webhook would, so a store the provider cannot reach still settles; then answer the payment. A start whose answer never came back is sent again under the same idempotency key. A payment whose money is recorded and whose order could not be completed yet is completed again (and a job is booked to keep trying). Safe to call as often as needed and at the same moment as the webhook. What a till calls every couple of seconds while the status is pending, checking or cancelling.
Parameters
| Name | Type | Description |
|---|---|---|
| id required | integer | Order id |
| tid required | integer | The transaction_id start_reader_payment answered |
Cancel a card reader payment
/api/v1/kahunacart/orders/{id}/reader-payments/{tid}/cancel
Clear the reader while the payment is still pending, because the customer changed their mind or the wrong amount was sent. Answers the payment as cancelled when the provider confirmed it, or cancelling when it only took the request (keep calling refresh_reader_payment until it is cancelled or succeeded). A payment that has already finished is answered as it stands. 409 when the provider could not cancel it, which usually means the customer had just paid, or could not be reached: refresh it in a moment.
Parameters
| Name | Type | Description |
|---|---|---|
| id required | integer | Order id |
| tid required | integer | The transaction_id start_reader_payment answered |
Give up on a card reader payment
/api/v1/kahunacart/orders/{id}/reader-payments/{tid}/abandon
Give up on a card payment on a reader that the provider cannot say anything about: a start whose answer never came back (checking), or a payment whose provider cannot be reached. It blocks every other reader payment and pay link on the order until somebody hears back, and this is the way out. The provider is asked once more first. When that settles the payment either way it is answered as it now stands and nothing is given up; when the provider answers that the payment is still on the reader it is 409 (cancel_reader_payment instead). Only when it still cannot say is the payment failed, with a history entry saying who gave up on it, and the order can then be paid another way. The customer may still have been charged: a completion that arrives later is recorded on the order as it would be after a cancel.
Parameters
| Name | Type | Description |
|---|---|---|
| id required | integer | Order id |
| tid required | integer | The transaction_id start_reader_payment answered |
check and sync always answer 200 when the provider answered at all. A failing check is a successful request reporting a failure, and the provider's own words are what a merchant needs. sync answers {slug, direction, ok, count, summary}, and a network failure comes back as ok: false with the exception's message rather than a 500. A provider that cannot be asked at all is a 422; a slug nothing registers is a 404.
webhook takes an optional {reset: true}, which deletes this store's existing endpoints before registering. Whatever signing secret comes back is written to the provider plugin's config file and never returned to the caller. default writes checkout.default_provider on the base plugin. Configured sync direction is not consulted by sync: off means "do not sync automatically", not "refuse an operator who asked".