Merchant Payments API

Drop-in South African payments. Create a charge on your server, open our popup, get a webhook when it clears.

Integration kit

GitHub-style pack: OpenAPI spec, Postman collection, PHP, Node, Python, WooCommerce starter, checkout HTML.

How it works

  1. Your server creates a payment with sk_live_… (never in the browser).
  2. The browser opens SmgPay.open — a Social Media Guru popup. PayFast runs only on our domain.
  3. We POST payment.paid to your webhook. That is the source of truth.
  4. You request an EFT payout from the merchant dashboard when you want to withdraw.

Fees

  • Cards (Visa, Mastercard, debit, Apple/Samsung/Google Pay): 6% + R2.00 excl. VAT, then 15% VAT on the fee. R100 → R9.20 fee → R90.80 net.
  • Capitec Pay, Instant EFT, SnapScan, Zapper, other: 6% + 15% VAT, minimum R2.00 + VAT (R2.30). R100 → R6.90 fee → R93.10 net. R30 → R2.30 fee → R27.70 net.
  • Create responses include both quotes in fees.card and fees.other. We settle from PayFast's payment_method. If the method is missing or unknown, the card rate (6% + R2 + VAT) applies.
  • Minimum R10.00. Same amount cannot be charged again within 15 minutes.

Create a payment

curl -X POST https://www.socialmediaguru.co.za/api/v1/payments \
  -H "Authorization: Bearer sk_live_YOUR_SECRET" \
  -H "Content-Type: application/json" \
  -d '{
    "amount": 199.00,
    "merchant_ref": "ORD-1001",
    "customer": {
      "name": "Jane Doe",
      "email": "jane@example.com",
      "phone": "0713743360"
    },
    "return_url": "https://yourstore.co.za/order/1001/thanks",
    "cancel_url": "https://yourstore.co.za/order/1001/cancel"
  }'

Open the PayFast popup

Do not load PayFast engine.js on the merchant site and do not iframe our pay page.

<script src="https://www.socialmediaguru.co.za/js/smg-pay.js"></script>
<script>
  SmgPay.open({
    payment_url: data.payment_url,
    onSuccess: function () { window.location = "/thanks"; },
    onCancel: function () {}
  });
</script>

Webhook

Header X-SMG-Signature = HMAC-SHA256 of the raw JSON body with the webhook secret. Event: payment.paid.

$raw = file_get_contents('php://input');
$sig = $_SERVER['HTTP_X_SMG_SIGNATURE'] ?? '';
if (!hash_equals(hash_hmac('sha256', $raw, $webhookSecret), $sig)) {
  http_response_code(401);
  exit;
}

Endpoints

MethodPathNotes
POST/api/v1/paymentsCreate (idempotent on merchant_ref)
GET/api/v1/paymentsList ?status=&limit=
GET/api/v1/payments/{id}id, SMG-P- number, or merchant_ref
POST/api/v1/payments/{id}{ "action": "cancel" }
GET/api/v1/balanceAvailable balance