9.2 KiB
PipraPay Payment Gateway Plugins — Developer Guide
Version: v1.0
Author: Fattain Naime
Summary: A well‑detailed payment gateway developer documentation for PipraPay.
Contents
- Architecture Overview
- Database & Settings
- Plugin Anatomy & Files
- Runtime Contracts
- Core Helper APIs
- Payment Flows (Manual vs API)
- Step‑by‑Step: Build a New Gateway
- Boilerplates & Templates
- Hooks & Webhooks
- Security & UX
- Go‑Live Checklist
- Examples
- FAQ
1) Architecture Overview
Every payment method is an isolated plugin located under:
pp-content/plugins/payment-gateway/<gateway-slug>
How PipraPay loads plugins
Active plugins are recorded in thepluginstable. At runtime, PipraPay autoloads each gateway’s PHP class file and calls your_<slug_underscore>_admin_page()and_<slug_underscore>_checkout_page($payment_id)functions when needed.
2) Database & Settings
Gateways are registered in __PREFIX__plugins with core columns:
plugin_name— display nameplugin_slug— unique slug (e.g.,stripe-checkout)plugin_dir— usuallypayment-gatewayplugin_array— JSON of saved settings (credentials, fees, limits, mode)status—active/inactive
The Admin UI writes settings into
plugin_array. Usepp_get_plugin_setting($slug)to read them at checkout time.
3) Plugin Anatomy & Files
<slug>/
├─ meta.json
├─ <slug>-class.php
├─ views/
│ ├─ admin-ui.php # Admin: configure gateway
│ └─ checkout-ui.php # Checkout: pay flow UI + action
├─ assets/
│ └─ icon.png # 128×128 recommended
└─ readme.txt # Description / changelog
meta.json
{
"type": "payment-gateway",
"slug": "your-gateway",
"name": "Your Gateway",
"mrdr": "payment-gateway"
}
<slug>-class.php
<?php
$plugin_meta = [
'Plugin Name' => 'Your Gateway',
'Version' => '1.0.0',
'Author' => 'Your Name'
];
function your_gateway_admin_page() {
$viewFile = __DIR__ . '/views/admin-ui.php';
if (file_exists($viewFile)) { include $viewFile; }
else { echo "<div class='alert'>Admin UI not found.</div>"; }
}
function your_gateway_checkout_page($payment_id) {
$viewFile = __DIR__ . '/views/checkout-ui.php';
if (file_exists($viewFile)) { include $viewFile; }
else { echo "<div class='alert'>Checkout UI not found.</div>"; }
}
views/admin-ui.php
<?php
$plugin_slug = 'your-gateway';
$plugin_info = pp_get_plugin_info($plugin_slug);
$settings = pp_get_plugin_setting($plugin_slug);
?>
<form id="gatewaySettings" method="post" action="">
<input type="hidden" name="action" value="plugin_update-submit">
<input type="hidden" name="plugin_slug" value="your-gateway">
<!-- Display name, limits, fees, credentials, status -->
</form>
views/checkout-ui.php
<?php
$transaction = pp_get_transation($payment_id);
$setting = pp_get_settings();
$plugin_slug = 'your-gateway';
$settings = pp_get_plugin_setting($plugin_slug);
// Amount math (observed convention across gateways)
$base = convertToDefault($transaction['response'][0]['transaction_amount'],
$transaction['response'][0]['transaction_currency'],
$settings['currency']);
$fee = safeNumber($settings['fixed_charge']) + ($base * (safeNumber($settings['percent_charge']) / 100));
$payable = $base + $fee;
?>
4) Runtime Contracts
- Folder name == slug (kebab-case).
- Main file name must be
<slug>-class.php. - Admin function:
<slug_underscore>_admin_page() - Checkout function:
<slug_underscore>_checkout_page($payment_id) - AJAX POST target often appends
?method=<slug>topp_get_paymentlink($payment_id).
Tip: Keep
slugstable. PipraPay uses it to find settings, routes, and function bindings.
5) Core Helper APIs
Frequently used helpers provided by PipraPay core (observed in real plugins):
pp_get_settings()— global site/app settings (branding, currency, etc.)pp_get_plugin_info($slug)pp_get_plugin_setting($slug)pp_get_transation($payment_id)pp_get_faq(),pp_get_support_links()pp_get_paymentlink($payment_id)pp_set_transaction_byslip($payment_id, $slug, $display_name, $_FILES['payment_slip'], $status)- Utilities:
convertToDefault(),safeNumber()
6) Payment Flows
A) Manual / Slip Upload
<?php
if (isset($_POST['your-gateway'])) {
$ok = pp_set_transaction_byslip(
$payment_id, 'your-gateway', 'Your Gateway Name',
$_FILES['payment_slip'] ?? null, 'pending'
);
echo json_encode([
"status" => $ok ? "true" : "false",
"message" => $ok ? "Initialize Payment Slip" : "Failed to upload payment slip"
]);
exit();
}
Use for bank transfers or providers without instant API capture.
B) Redirect / API (e.g., bKash)
<?php
// (Example) Token then create payment and redirect
$base_url = ($settings['bkash_mode'] === 'live')
? 'https://tokenized.pay.bka.sh' : 'https://tokenized.sandbox.bka.sh';
$client = new \GuzzleHttp\Client();
$resp = $client->request('POST', $base_url.'/v1.2.0-beta/tokenized/checkout/token/grant', [
'body' => json_encode(['app_key' => $app_key, 'app_secret' => $app_secret]),
'headers' => [
'accept' => 'application/json',
'content-type' => 'application/json',
'password' => $password,
'username' => $username,
],
]);
$id_token = json_decode($resp->getBody())->id_token;
// then create payment, redirect to PSP URL
7) Step‑by‑Step: Build a New Gateway
- Create folder
pp-content/plugins/payment-gateway/your-gateway - Add
meta.jsonandreadme.txt - Implement
your-gateway-class.php(admin/checkout loaders) - Build
views/admin-ui.php(credentials, fees, limits, status) - Build
views/checkout-ui.php(manual slip OR API/redirect) - (Optional) add
assets/andfunctions.php - Enable plugin in Admin & test sandbox → live
8) Boilerplates & Templates
Folder Layout
your-gateway/
├─ meta.json
├─ your-gateway-class.php
├─ views/
│ ├─ admin-ui.php
│ └─ checkout-ui.php
├─ assets/
│ └─ icon.png
└─ readme.txt
Admin Form (AJAX)
<script>
document.querySelector('#gatewaySettings')?.addEventListener('submit', async (e) => {
e.preventDefault();
const form = e.currentTarget;
const resp = await fetch(form.action || location.href, {
method: 'POST', body: new FormData(form)
});
const data = await resp.json().catch(() => ({}));
alert(data.message || 'Saved');
});
</script>
9) Hooks & Webhooks
Lightweight action system similar to WordPress:
// Register a callback
add_action('pp_transaction_ipn', 'your_gateway_handle_ipn');
function your_gateway_handle_ipn($transaction_id) {
// verify provider webhook, update transaction state, notify customer, etc.
}
Common core hooks:
pp_transaction_ipn— payment notification receivedpp_invoice_ipn— invoice status updated
10) Security & UX
- Never echo secrets; mask inputs and store in settings only
- Validate/escape output (e.g.,
htmlspecialchars(...)) - Use HTTPS; verify PSP signatures and webhook authenticity
- Keep amounts on server as source of truth
- Offer sandbox/live mode toggle where supported
- Clear customer messaging and error handling
- Log key events (avoid storing PCI data)
11) Go‑Live Checklist
- Slug = folder name (kebab‑case) & file names match
meta.jsoncomplete- Admin & checkout functions exported
- Admin form saves & rehydrates values
- Amount + fee computation correct
- Manual flow: slip upload → status
pending - API flow: sandbox tested, credentials validated
- Icon present; readme has changelog
12) Examples
Stripe Checkout
stripe-checkout-class.phpwithstripe_checkout_admin_page()&stripe_checkout_checkout_page()- Admin: secret key + webhook secret
- Checkout: Stripe.js or hosted Checkout Session
PayPal Checkout
paypal-checkout-class.phpwithpaypal_checkout_admin_page()&paypal_checkout_checkout_page()- Admin: client ID + secret
- Checkout: PayPal SDK smart buttons
Also see local “manual/slip” gateways and wallet APIs (e.g., bKash) for real-life patterns.
13) FAQ
What file names are mandatory?
Folder = slug, main PHP = <slug>-class.php, meta.json, and both view files.
Where are settings stored?
In __PREFIX__plugins.plugin_array as JSON. Use pp_get_plugin_setting($slug) to read.
How do I compute total payable amount?
$base = convertToDefault(amount, fromCurrency, $settings['currency']);
$fee = fixed_charge + ($base * percent_charge / 100);
$payable = $base + $fee;
© PipraPay — Payment Gateway Developer Documentation