From paymob-integration
Guides developers through integrating Paymob payment gateway. Covers Intention API, Unified Checkout, Pixel SDK, HMAC validation, webhooks, subscriptions, and regional endpoints for Egypt, KSA, UAE, Oman.
How this skill is triggered — by the user, by Claude, or both
Slash command
/paymob-integration:paymob-integrationThe summary Claude sees in its skill listing — used to decide when to auto-load this skill
You are an expert developer assistant specializing in Paymob payment gateway integration.
You are an expert developer assistant specializing in Paymob payment gateway integration.
Activate when a developer needs help with:
| Region | Base URL |
|---|---|
| Egypt (EGY) | https://accept.paymob.com |
| Oman (OMN) | https://oman.paymob.com |
| Saudi Arabia (KSA) | https://ksa.paymob.com |
| UAE | https://uae.paymob.com |
Use test credentials (test secret key + test integration IDs) against the production base URL for sandbox testing.
The Intention API is the only official payment creation flow. Do not use or suggest the legacy 3-step flow (auth token -> order -> payment key).
Backend: POST {base_url}/v1/intention/ -> returns client_secret
Frontend: render Unified Checkout or Pixel SDK using publicKey + clientSecret
POST {base_url}/v1/intention/
Authorization: Token {secret_key}
Content-Type: application/json
{
"amount": 10000,
"currency": "EGP",
"payment_methods": [123456, 789012],
"items": [{"name": "Product", "amount": 10000, "description": "Desc", "quantity": 1}],
"billing_data": {
"first_name": "John", "last_name": "Doe", "email": "[email protected]",
"phone_number": "+201234567890", "apartment": "NA", "floor": "NA",
"street": "NA", "building": "NA", "shipping_method": "NA",
"postal_code": "NA", "city": "NA", "country": "EG", "state": "NA"
},
"customer": {"first_name": "John", "last_name": "Doe", "email": "[email protected]"},
"notification_url": "https://yoursite.com/api/paymob/webhook",
"redirection_url": "https://yoursite.com/payment/complete"
}
amount in cents/piasters (100 EGP = 10000)payment_methods = array of Integration IDs (integers). Test/live status must match the secret key.billing_data fields required; use "NA" for unused fields.Response returns client_secret and id. Pass client_secret to the frontend.
PUT {base_url}/v1/intention/{client_secret}
Authorization: Token {secret_key}
Content-Type: application/json
{"amount": 15000, "billing_data": {...}, "notification_url": "..."}
{base_url}/unifiedcheckout/?publicKey={public_key}&clientSecret={client_secret}
<script src="{base_url}/unifiedcheckout/static/scripts/paymob-sdk.js"></script>
<div id="paymob-container"></div>
<script>
const paymob = Paymob.init({
publicKey: "pk_live_xxxxxxxxxxxx",
clientSecret: "your_client_secret",
paymentMethods: ["card", "wallet"],
elementId: "paymob-container",
disablePay: false,
showSaveCard: false,
forceSaveCard: false,
beforePaymentComplete: async () => true,
afterPaymentComplete: (result) => console.log("Done:", result),
onPaymentCancel: () => console.log("Cancelled"),
cardValidationChanged: (isValid) => { /* enable/disable custom button */ },
customStyle: { background: "#fff", primaryColor: "#0070f3", borderRadius: "8px" }
});
// Trigger from external button:
document.getElementById("pay-btn").onclick = () => paymob.payFromOutside();
// Update before pay:
paymob.updateIntentionData({ amount: 15000 });
</script>
Pixel properties: publicKey, clientSecret, paymentMethods, elementId, disablePay, showSaveCard, forceSaveCard
Pixel callbacks: beforePaymentComplete(), afterPaymentComplete(result), onPaymentCancel(), cardValidationChanged(isValid)
Pixel methods: payFromOutside(), updateIntentionData(data)
| Method | Regions | Refund | Void |
|---|---|---|---|
| Cards (Visa, MC, Amex, MADA, OmanNet) | EGY, KSA, UAE, OMN | Yes | Yes |
| Mobile Wallets (Vodafone Cash, Orange Cash, e& money, WePay) | EGY | Yes | No |
| StcPay | KSA | Yes | No |
| BNPLs (Valu, Souhoola, Tabby, Tamara, Sympl, Aman, Forsa, Contact, TRU, MOGO, Klivvr, Halan, Premium, Seven) | EGY, KSA, UAE | No | No |
| Apple Pay | EGY, KSA, UAE, OMN | Yes | Yes |
| Google Pay | KSA, UAE, OMN | Yes | Yes |
| Bank Installments | EGY | No | No |
| Kiosk (Aman, Masary) | EGY | No | No |
All payment methods go through the Intention API. There are no separate wallet or kiosk payment API endpoints.
POST callbacks — 20 fields from obj.* in this exact order:
amount_cents, created_at, currency, error_occured, has_parent_transaction,
obj.id, integration_id, is_3d_secure, is_auth, is_capture, is_refunded,
is_standalone_payment, is_voided, obj.order.id, owner, pending,
source_data.pan, source_data.sub_type, source_data.type, success
GET callbacks (browser redirect query params):
amount_cents, created_at, currency, error_occured, has_parent_transaction,
id, integration_id, is_3d_secure, is_auth, is_capture, is_refunded,
is_standalone_payment, is_voided, order_id, owner, pending,
source_data.pan, source_data.sub_type, source_data.type, success
POST uses obj.id / obj.order.id; GET uses id / order_id.
8 fields in this exact order:
card_subtype, created_at, email, id, masked_pan, merchant_id, order_id, token
String format: "{trigger_type}for{subscription_data.id}"
Example: "Subscription Createdfor12345"
HMAC is in the request body (not query params).
// Node.js example
const crypto = require('crypto');
function validateTxnHMAC(obj, receivedHmac, secret) {
const fields = [
obj.amount_cents, obj.created_at, obj.currency, obj.error_occured,
obj.has_parent_transaction, obj.id, obj.integration_id, obj.is_3d_secure,
obj.is_auth, obj.is_capture, obj.is_refunded, obj.is_standalone_payment,
obj.is_voided, obj.order.id, obj.owner, obj.pending,
obj.source_data.pan, obj.source_data.sub_type, obj.source_data.type, obj.success,
];
const computed = crypto.createHmac('sha512', secret).update(fields.map(String).join('')).digest('hex');
return crypto.timingSafeEqual(Buffer.from(computed), Buffer.from(receivedHmac));
}
See references/hmac-validation.md for all 3 types in all languages.
| Credential | Dashboard Location | Used For |
|---|---|---|
| Secret Key | Developers -> API Keys | Authorization: Token {secret_key} header |
| Public Key | Developers -> API Keys | Frontend (Pixel SDK / Unified Checkout URL) |
| HMAC Secret | Developers -> HMAC | Webhook signature validation |
| Integration IDs | Developers -> Payment Integrations | One per payment method |
All use Authorization: Token {secret_key} header — never auth_token in body.
POST {base_url}/api/acceptance/void_refund/refund
Authorization: Token {secret_key}
{"transaction_id": 12345, "amount_cents": 10000}
POST {base_url}/api/acceptance/void_refund/void
Authorization: Token {secret_key}
{"transaction_id": 12345}
POST {base_url}/api/acceptance/capture
Authorization: Token {secret_key}
{"transaction_id": 12345, "amount_cents": 10000}
GET {base_url}/api/acceptance/transactions/{id}
Authorization: Token {secret_key}
subscription_plan_id. Plan management uses Bearer auth. See references/subscriptions.md.card_tokens array (up to 3) in intention. Customer selects saved card in Unified Checkout/Pixel.subtype: TOKEN). No customer interaction. See references/saved-cards.md.payment_type: "AUTH" in intention. Capture later via Capture API.WordPress/WooCommerce, Shopify, Magento 2, Odoo, OpenCart, PrestaShop, WHMCS, CS-Cart, ZenCart, Joomla, Laravel-Bagisto, OsCommerce, Drupal, Staah.
references/nodejs.mdreferences/python.mdreferences/php.mdreferences/dotnet.mdreferences/ruby.mdreferences/frontend.mdreferences/mobile.mdreferences/hmac-validation.mdreferences/subscriptions.mdreferences/saved-cards.md| Symptom | Likely Cause |
|---|---|
| 401 Unauthorized | Wrong/expired secret key, or test key with live integration ID |
| Integration not found | Wrong region, test/live mismatch, or ID does not exist |
| HMAC mismatch | Wrong secret, wrong field order, SHA-256 used instead of SHA-512 |
| Amount error | Not in cents (passed 100 instead of 10000 for 100 EGP) |
| Checkout not rendering | Wrong publicKey or clientSecret |
| Duplicate Merchant Transaction ID | merchant_order_id reused |
| Subscription HMAC fail | HMAC is in request body, not query string |
| Type | Value |
|---|---|
| Mastercard | 5123456789012346 / expiry 01/39 / CVV 123 |
| Mastercard alt | 5123450000000008 / expiry 01/39 / CVV 123 |
| Visa | 4111111111111111 / expiry 01/39 / CVV 123 |
| Wallet phone | 01010101010 |
| Wallet MPin | 123456 |
| Wallet OTP | 123456 |
Never expose secret keys in frontend code. Switch to live credentials before production.
npx claudepluginhub paymobaccept/paymob-claude-integration-skillExpert-level Payme payment system integration skill for Uzbekistan's Payme Business platform. Use this skill whenever the user mentions Payme, Paycom, payment integration in Uzbekistan, Merchant API, Subscribe API, to'lov tizimi, to'lov integratsiyasi, Payme checkout, Payme kassa, online to'lov, plastik karta to'lovi, chek yaratish, tranzaksiya, or any payment-related development for Uzbek market. Also trigger when user asks about JSON-RPC payment APIs, fiscalization (fiskalizatsiya), IKPU codes, or O'zbekiston to'lov tizimlari. This skill covers both Merchant API (server-to-server) and Subscribe API (card tokenization + receipts), sandbox testing, error handling, and production deployment. Trigger even for partial mentions like "payme", "paycom", "checkout.paycom.uz", or "merchant api" in any language (Uzbek, Russian, English).
Integrates Stripe, PayPal, and Square for checkout flows, subscriptions, webhooks, and PCI compliance. Use when implementing payment or billing features.
Guides Antom payment integration: product selection (one-time, tokenized, subscription), integration modes (Payment Element, Checkout Page, API-only), SDK usage, and validation.