Skip to main content
purchase() decides the shape of your checkout. There are three workable flows, and the right one depends on what your provider offers.

Flow 1: Hosted redirect

The provider hosts the payment page. This is the simplest flow and the safest, since card data never touches the installation.
Returning a UriInterface makes the browser follow it. When the user comes back, completePurchase() verifies the payment.

Flow 2: Your own checkout page

Use this when the provider needs a client-side SDK, or when you must collect something extra, such as a bank choice. Return a relative URI, which resolves against the site root:
Then serve that page from your plugin, extending the billing view base class:
src/CheckoutView.php
BillingView puts the route under /app/billing and requires an authenticated user, so the page sits inside the app with the normal chrome. The page loads the provider’s script and, on success, sends the user to the callback URL:
templates/checkout.twig
If you need a server-side step before redirecting, such as creating a mandate from a form, add a POST endpoint under the same base class and redirect from there.

Flow 3: Offline or token-based

Methods that settle outside Aikeedo, such as a bank transfer, return a PurchaseToken. The user goes to the receipt page, which shows your instructions, and an administrator marks the order paid later.
Implement OfflinePaymentGatewayInterface so the method is listed with the manual options rather than as a branded button.
The generic checkout buttons don’t do anything special with the token beyond sending the user to the receipt. Only the built-in card form consumes a token client-side.

Flow 4: Charge immediately

If the payment is already complete when purchase() runs, for example because you charged a saved payment method, return the provider reference as a plain string. Aikeedo pays and fulfils the order right away, without a callback.
Only do this when the charge is genuinely settled. Returning a reference for a pending payment grants credits that may never be paid for.

Where the reference lives

completePurchase() must return the provider reference, because it becomes the order’s external ID and, for recurring plans, the subscription’s. There are two ways to get it: Either way, verify against the provider before returning.
Compare the amount too when the provider lets the payer change it. An unchecked callback is an invitation to pay 1 unit for a 99 unit plan.

Callback URLs

The callback accepts both GET and POST, and completePurchase() receives the query parameters merged with the parsed body, so a provider that posts its result works the same as one that redirects.