Skip to main content

Writing a payment gateway

4 min readApplies to every PremiumPress theme · 12.x

Writing a payment gateway

Connect a payment provider that PremiumPress does not ship a plugin for.

Gateways are separate plugins, not part of the theme, so a gateway can be updated on its own. Before writing one, check the ready-made gateways at premiumpress.com/plugins.

How a payment flows​

  1. The buyer chooses your gateway at checkout. The theme creates an order and asks your gateway where to send the buyer (ppt_gateway_start).
  2. You create the payment at your provider and return the address of its payment page.
  3. The buyer pays there and the provider sends them back to the return address the theme gave you.
  4. The theme asks your gateway whether the payment really went through (ppt_gateway_verify). The order completes only when you answer true.

The same flow serves every kind of purchase: listing plans, memberships, credits and bookings.

1. Register the gateway​

Your gateway appears on the Payments screen, with its settings, as soon as you add it to ppt_payment_gateways. Only id is required.

<?php
/*
Plugin Name: MyPay for PremiumPress
*/

add_filter('ppt_payment_gateways', function (array $gateways) {
$gateways[] = array(
'id' => 'mypay',
'name' => 'MyPay',
'desc' => 'Accept card payments with MyPay.',
'logo' => plugins_url('logo.svg', __FILE__), // optional
'fields' => array(
array('id' => 'mode', 'label' => 'Mode', 'type' => 'select',
'options' => array('test' => 'Test', 'live' => 'Live'), 'default' => 'test'),
array('id' => 'api_key', 'label' => 'API key', 'type' => 'password',
'hint' => 'In your MyPay dashboard under Developers.'),
),
'notes' => 'Create your API key in the MyPay dashboard first.',
);
return $gateways;
});
KeyWhat it is
idA short unique name, used everywhere below. Required.
name, desc, logo, notesWhat the site owner sees on the Payments screen.
fieldsSettings for the owner to fill in. Each has id, label, type (text, password, select, textarea or checkbox), and optionally options, default and hint.
recurringtrue if your gateway can take repeat payments for subscriptions.
trialtrue if it supports free-trial subscriptions.
can_testtrue to show a Test connection button (answer it with ppt_gateway_test).

Read the owner's settings with:

$key = \Ppt\Admin\Payments::value('mypay', 'api_key');
$live = \Ppt\Admin\Payments::value('mypay', 'mode', 'test') === 'live';
$on = \Ppt\Admin\Payments::isEnabled('mypay');

2. Send the buyer to pay​

add_filter('ppt_gateway_start', function ($url, $gatewayId, $order, $returnUrl) {
if ($gatewayId !== 'mypay') {
return $url; // another gateway's order: leave it alone
}

// Create the payment at your provider. Use the order ID as your reference
// and the theme's return address as the provider's success address.
$payment = mypay_create_payment(array(
'amount' => $order['total'],
'currency' => $order['currency'] ?? 'USD',
'reference' => $order['id'],
'return_url' => $returnUrl,
));

return $payment ? $payment['checkout_url'] : ''; // '' cancels the order
}, 10, 4);

$order includes id, total, currency, name and description, plus recurring, duration and trial_days for subscriptions. Return an empty value if you cannot start the payment: the buyer goes back to checkout with a "payment unavailable" message and the order is cancelled.

3. Confirm the payment​

When the buyer comes back, the theme asks you to confirm. Only a strict true completes the order. Anything else leaves it pending; if you return a sentence, the buyer sees it.

add_filter('ppt_gateway_verify', function ($result, $gatewayId, $order) {
if ($gatewayId !== 'mypay') {
return $result;
}
// Ask the provider's server. Never decide from what the browser sent back.
$paid = mypay_payment_is_paid($order['id']);
return $paid ? true : __('We are still waiting for MyPay to confirm your payment.', 'mypay');
}, 10, 3);

$order here has id, ref, total, currency, listing and plan. Bookings pass only id and ref.

4. Webhooks​

If your provider confirms payments by webhook, for example when a buyer closes the tab before returning, complete the order from your webhook handler once you have verified the webhook's signature:

\Ppt\Payments\CheckoutFlow::markPaid($orderId); // safe to call twice

For subscription renewals, record each new payment with \Ppt\Payments\CheckoutFlow::renewOrder($orderId, $providerEventId).

Optional extras​

HookUse it to
ppt_gateway_can_refund / ppt_gateway_refundOffer refunds from the admin. The refund receives the order ID, amount, currency, reason and a key to stop a refund being sent twice; return array('ok' => true, 'id' => '…', 'message' => '…').
ppt_gateway_cancelCancel a subscription at the provider; return true when done.
ppt_gateway_can_manage / ppt_gateway_manage_urlGive members a link to manage their subscription at the provider.
ppt_gateway_testAnswer the Test connection button.
ppt_gateway_card_afterPrint extra help under your gateway's card on the Payments screen.

Testing​

Turn on your provider's test mode, enable the gateway on Payments, and buy something on the site: a listing plan is quickest. Check the order shows as complete on the Orders screen, and that a declined test card leaves it pending. The theme's built-in test gateway is a complete small example of every hook on this page.