PayOrc
Checkout

Post Final Response

Understand and verify the callback data PayOrc sends after a payment is completed. Covers all response fields, signature verification, status handling, and error codes.

Post Final Response

Version: 3.0.0

What is the Post Final Response? After a payment is completed (successful, failed, or cancelled), PayOrc sends a server-to-server POST callback to your configured endpoint with the full transaction details. This is your source of truth for order fulfillment — never rely solely on the client-side redirect URL.

Why This Matters

The client-side redirect (to your success/failure/cancel URL) can be:

  • Spoofed — A malicious user could craft a fake redirect URL with fake parameters.
  • Lost — Network issues, browser crashes, or popup blockers can prevent the redirect from reaching your customer's browser.

The server-side callback is tamper-proof (when verified) and reliable (sent directly from PayOrc to your server). Always use the callback for:

  • Updating order status in your database
  • Fulfilling the purchase (shipping, provisioning access, etc.)
  • Recording transaction details for reconciliation

How the Callback Works

Step 1: PayOrc processes the transaction (authorization, capture, or decline).

Step 2: PayOrc sends an HTTP POST request to your configured callback URL with the transaction payload as JSON.

Step 3: Your server receives the payload, verifies the signature (recommended), updates the order status, and returns a 200 OK response.

Step 4: PayOrc considers the callback delivered if it receives a 200 OK within 30 seconds. If not, it retries with exponential backoff (up to 5 attempts over 24 hours).

Important: Your callback endpoint must respond with HTTP 200 within 30 seconds. If your processing takes longer, acknowledge immediately with 200 and process the payload asynchronously.


Callback Endpoint Configuration

You configure your callback URL in the PayOrc dashboard:

  1. Navigate to Developers → Webhooks → Add Endpoint
  2. Enter your callback URL (must be HTTPS)
  3. Select the events to subscribe to (payment completed, failed, etc.)
  4. Save and note the signing secret for signature verification

Response Fields

The callback payload contains the following fields:

Core Transaction Fields

FieldTypeDescription
m_order_idStringYour merchant order ID from the original request
p_order_idIntegerPayOrc's unique order ID
p_request_idIntegerPayOrc's unique request ID
transaction_idIntegerUnique transaction identifier for this payment attempt
transaction_dateStringTimestamp of the transaction (format varies)
statusStringTransaction status (see Status Values below)
amountFloatTransaction amount in the smallest currency unit
currencyStringThree-letter ISO currency code (e.g., AED, USD)
modeStringlive for production, test for sandbox

Payment Details Fields

FieldTypeDescription
pspStringPayment Service Provider that processed the transaction
psp_ref_idStringReference ID returned by the PSP
psp_txn_idIntegerTransaction ID assigned by the PSP
payment_methodStringPayment method used (e.g., VISA, MASTERCARD, APPLEPAY)
payment_method_dataObjectAdditional payment method details (see below)
apm_nameStringAlternative Payment Method name (if applicable, e.g., Apple Pay, Google Pay)
m_payment_tokenStringToken for recurring/one-click payments (if tokenization was requested)

Customer and Metadata Fields

FieldTypeDescription
m_customer_idStringYour customer ID from the original request
parametersObjectCustom key-value pairs you passed in the order request
custom_dataObjectAdditional data from PayOrc (e.g., 3DS result, fraud score)

Payment Method Data Object

The payment_method_data field contains details about the payment instrument used:

FieldTypeDescription
schemeStringCard network: VISA, MASTERCARD, AMEX, DISCOVER, etc.
card_countryStringISO country code of the card issuer
card_typeStringCREDIT, DEBIT, or PREPAID
masked_panStringMasked card number (e.g., 411111******1111)

Status Values

StatusMeaningAction Required
APPROVEDPayment was successfully authorized and/or capturedFulfill the order
DECLINEDPayment was declined by the issuerNotify customer, suggest retry
PENDINGPayment is awaiting processing (e.g., bank transfer)Poll for status updates or wait for callback
CANCELLEDCustomer cancelled the paymentLog the attempt, no fulfillment needed
ERRORAn error occurred during processingLog the error, check transaction details
REFUNDEDPayment was fully refundedUpdate order status
PARTIALLY_REFUNDEDPayment was partially refundedUpdate order with refund amount

Full Callback Example

# Simulate receiving the callback (for testing your endpoint)
curl --location 'https://your-site.com/api/payment-callback' \
--header 'Content-Type: application/json' \
--header 'X-PayOrc-Signature: sha256=abc123def456...' \
--data-raw '{
    "m_order_id": "CUST-10042",
    "p_order_id": 1000010240,
    "p_request_id": 1000010200,
    "transaction_id": 5000123456,
    "transaction_date": "2024-01-15T14:30:00Z",
    "status": "APPROVED",
    "amount": 150.00,
    "currency": "AED",
    "mode": "live",
    "psp": "Adyen",
    "psp_ref_id": "adyen-ref-789012",
    "psp_txn_id": 9876543,
    "payment_method": "VISA",
    "payment_method_data": {
        "scheme": "VISA",
        "card_country": "AE",
        "card_type": "CREDIT",
        "masked_pan": "411111******1111"
    },
    "apm_name": null,
    "m_customer_id": "CUST-10042",
    "m_payment_token": "tok_abc123xyz",
    "parameters": {},
    "custom_data": {
        "three_ds_result": "Y",
        "fraud_score": 12
    }
}'

Error Handling and Retries

PayOrc uses automatic retries for failed callback deliveries:

AttemptDelayCondition
1stImmediateFirst delivery attempt
2nd1 minuteIf no 200 response received
3rd10 minutesStill no 200 response
4th1 hourStill no 200 response
5th24 hoursFinal attempt

Your callback endpoint must:

  • Return HTTP 200 within 30 seconds
  • Handle duplicate callbacks gracefully (idempotency)
  • Verify the signature before processing
  • Process asynchronously if business logic takes longer than 30 seconds

Idempotency Pattern

Always check if you have already processed a callback before acting on it:

# Test idempotency by sending the same callback twice
BODY='{"m_order_id":"CUST-10042","p_order_id":1000010240,"status":"APPROVED"}'
curl -X POST 'https://your-site.com/api/payment-callback' \
--header 'Content-Type: application/json' \
--data "$BODY"
# First: processes the order
# Second: returns "Already processed" with 200

On this page