Custom payment gateway
Connect a payment provider Merx does not ship with.
Use the gateways option to add your own payment gateway.
A gateway is a pair of functions. initializePayment starts the payment when the checkout is submitted, and completePayment finishes it once the provider sends the customer back. Both receive the virtual order page and must return an OrderPage object.
In initializePayment you can set a redirect URL. The customer will be sent there. If you don’t set redirect, they go to /api/shop/success directly, which is what an invoice order does.
Whatever return address you hand your provider has to be Merx::returnUrl(). It carries a one-time nonce that ties the return to the checkout that started it — /api/shop/success completes a payment on a GET, and without that check a link on any page could complete a pending payment of somebody who approved it at the provider but never came back. A return that arrives without the nonce is refused with error.merx.invalidReturn.
<?php
use Kirby\Data\Yaml;
use Wagnerwagner\Merx\OrderPage;
use Wagnerwagner\Merx\PaymentDetails;
return [
'wagnerwagner.merx.gateways' => [
'my-payment-provider' => [
'initializePayment' => function(OrderPage $virtualOrderPage): OrderPage
{
// Ask your provider for a payment URL for the amount of
// $virtualOrderPage->cart()->total()
$redirectUrl = 'https://mypaymentprovider.com/payment/mlDquvqMQK85M1Pw';
$virtualOrderPage->version()->update([
'redirect' => $redirectUrl,
]);
return $virtualOrderPage;
},
'completePayment' => function(OrderPage $virtualOrderPage, array $data): OrderPage
{
$virtualOrderPage->version()->update([
'datePaid' => date('c'),
'paymentDetails' => Yaml::encode(PaymentDetails::create([
'provider' => 'my-payment-provider',
'id' => $data['transaction_id'] ?? null,
])),
]);
return $virtualOrderPage;
}
],
],
];
Be careful. $virtualOrderPage is just virtual and not yet written to the content folder, so you can’t use $page->update() (which would write a content file). Instead you can use $page->version()->update() to update the virtual page’s content.
Build the payment record with PaymentDetails::create() instead of storing your provider’s response as it is. A raw response carries the customer’s name, email and address, and order pages are plain content files.