For a step-by-step tutorial, see the Quickstart. For the full API reference, see API Overview.
Creating a payment
Create a payment intent by callingPOST /api/v1/payments. The response includes a checkout_url - redirect your customer there to complete payment.
curl -X POST https://pay.yourbrand.com/api/v1/payments \\
-H "Authorization: Bearer op_live_abc123.def456" \\
-H "Content-Type: application/json" \\
-d '{
"amount": "500.00",
"currency": "USD",
"redirect_url": "https://my-store.com/success",
"cancel_url": "https://my-store.com/cancel",
"customer_email": "[email protected]",
"customer_name": "Jane Doe",
"reference": "ORDER-10024"
}'
<?php
use OwnPay\Client;
$client = new Client('https://pay.yourbrand.com/api/v1', 'op_live_abc123.def456');
$payment = $client->payments->create([
'amount' => '500.00',
'currency' => 'USD',
'redirect_url' => 'https://my-store.com/success',
'cancel_url' => 'https://my-store.com/cancel',
'customer_email' => '[email protected]',
'customer_name' => 'Jane Doe',
'reference' => 'ORDER-10024',
]);
// Redirect the customer to the checkout page
header('Location: ' . $payment->checkout_url);
exit;
use OwnPay\Laravel\Facades\OwnPay;
$payment = OwnPay::createPayment([
'amount' => '500.00',
'currency' => 'USD',
'redirect_url' => 'https://my-store.com/success',
'cancel_url' => 'https://my-store.com/cancel',
'customer_email' => '[email protected]',
'customer_name' => 'Jane Doe',
'reference' => 'ORDER-10024',
]);
return redirect($payment->checkout_url);
import OwnPay from 'ownpay';
const client = new OwnPay('https://pay.yourbrand.com/api/v1', 'op_live_abc123.def456');
const payment = await client.payments.create({
amount: '500.00',
currency: 'USD',
redirect_url: 'https://my-store.com/success',
cancel_url: 'https://my-store.com/cancel',
customer_email: '[email protected]',
customer_name: 'Jane Doe',
reference: 'ORDER-10024',
});
console.log('Redirect to:', payment.checkout_url);
import ownpay
client = ownpay.Client(
base_url="https://pay.yourbrand.com/api/v1",
api_key="op_live_abc123.def456"
)
payment = client.payments.create(
amount="500.00",
currency="USD",
redirect_url="https://my-store.com/success",
cancel_url="https://my-store.com/cancel",
customer_email="[email protected]",
customer_name="Jane Doe",
reference="ORDER-10024",
)
print(f"Redirect to: {payment['checkout_url']}")
package main
import (
"fmt"
"github.com/own-pay/ownpay-go"
)
func main() {
client := ownpay.NewClient("https://pay.yourbrand.com/api/v1", "op_live_abc123.def456")
payment, err := client.Payments.Create(ownpay.PaymentParams{
Amount: "500.00",
Currency: "USD",
RedirectURL: "https://my-store.com/success",
CancelURL: "https://my-store.com/cancel",
CustomerEmail: "[email protected]",
CustomerName: "Jane Doe",
Reference: "ORDER-10024",
})
if err != nil {
panic(err)
}
fmt.Println("Redirect to:", payment.CheckoutURL)
}
import org.ownpay.Client;
import org.ownpay.model.Payment;
import java.util.Map;
public class Main {
public static void main(String[] args) {
Client client = new Client(
"https://pay.yourbrand.com/api/v1",
"op_live_abc123.def456"
);
Payment payment = client.payments().create(Map.of(
"amount", "500.00",
"currency", "USD",
"redirect_url", "https://my-store.com/success",
"cancel_url", "https://my-store.com/cancel",
"customer_email", "[email protected]",
"customer_name", "Jane Doe",
"reference", "ORDER-10024"
));
System.out.println("Redirect to: " + payment.getCheckoutUrl());
}
}
Verifying webhooks
Always verify the HMAC-SHA256 signature before processing a webhook. The signature covers{timestamp}.{raw_body}.
<?php
use OwnPay\Webhook;
$webhook = new Webhook('whsec_your_webhook_secret');
try {
$event = $webhook->constructEvent(
file_get_contents('php://input'),
$_SERVER['HTTP_X_OWNPAY_SIGNATURE'] ?? '',
$_SERVER['HTTP_X_OWNPAY_TIMESTAMP'] ?? ''
);
} catch (\OwnPay\Exception\SignatureVerificationException $e) {
http_response_code(401);
exit('Invalid signature');
}
if ($event->type === 'payment.completed') {
$trx = $event->data;
// Fulfill the order using $trx['reference']
}
http_response_code(200);
echo 'OK';
import OwnPay from 'ownpay';
import crypto from 'crypto';
const webhookSecret = 'whsec_your_webhook_secret';
function verifyWebhook(rawBody, signatureHeader, timestampHeader) {
const hmac = crypto.createHmac('sha256', webhookSecret);
hmac.update(`${timestampHeader}.${rawBody}`);
const expected = `sha256=${hmac.digest('hex')}`;
return crypto.timingSafeEqual(Buffer.from(expected), Buffer.from(signatureHeader));
}
// In your Express handler:
app.post('/webhooks/ownpay', express.raw({ type: 'application/json' }), (req, res) => {
const sig = req.headers['x-ownpay-signature'];
const ts = req.headers['x-ownpay-timestamp'];
if (!verifyWebhook(req.body.toString(), sig, ts)) {
return res.status(401).send('Invalid signature');
}
const event = JSON.parse(req.body.toString());
if (event.type === 'payment.completed') {
console.log('Order fulfilled:', event.data.reference);
}
res.status(200).send('OK');
});
import hmac
import hashlib
import json
from flask import Flask, request, Response
app = Flask(__name__)
WEBHOOK_SECRET = "whsec_your_webhook_secret"
@app.route("/webhooks/ownpay", methods=["POST"])
def handle_webhook():
sig = request.headers.get("x-ownpay-signature", "")
ts = request.headers.get("x-ownpay-timestamp", "")
raw = request.get_data()
expected = "sha256=" + hmac.new(
WEBHOOK_SECRET.encode(), (ts + ".").encode() + raw, hashlib.sha256
).hexdigest()
if not hmac.compare_digest(expected, sig):
return Response("Invalid signature", status=401)
event = json.loads(raw)
if event["type"] == "payment.completed":
print(f"Order fulfilled: {event['data']['reference']}")
return Response("OK", status=200)
Querying transaction status
You can query a payment’s status directly, which is useful when a customer returns to your site after payment.<?php
use OwnPay\Client;
$client = new Client('https://pay.yourbrand.com/api/v1', 'op_live_abc123.def456');
$payment = $client->payments->get('pi_01j0x8kz7m3wd4b9qfhec5rtg6');
if ($payment->status === 'completed') {
// Fulfill the order
} elseif ($payment->status === 'failed') {
// Show payment failure to customer
} else {
// Still processing - poll again or wait for webhook
}
import OwnPay from 'ownpay';
const client = new OwnPay('https://pay.yourbrand.com/api/v1', 'op_live_abc123.def456');
const payment = await client.payments.get('pi_01j0x8kz7m3wd4b9qfhec5rtg6');
switch (payment.status) {
case 'completed':
console.log('Fulfill order:', payment.reference);
break;
case 'failed':
console.log('Show failure message');
break;
default:
console.log('Status:', payment.status, '- poll or wait for webhook');
}
Prefer webhooks over polling for production integrations. Webhooks are near real-time and do not waste API rate limit quota. Use status queries only as a fallback when a webhook was missed.
Related Pages
- Developer Quickstart - Step-by-step integration tutorial
- API Overview - Full endpoint reference
- Ecosystem - SDK installation and community integrations
- Rate Limiting - Understanding 429 responses and headers