Skip to content
MrIvoryMrIvory
Connect processor Merchant panel

JSON sale

Server-to-server payment

Two steps. Step 1 is JSON on your server (you handle PAN — this sandbox is not PCI Level 1). Step 2 is a browser form only when the card needs the sandbox 3DS page.

1. Initiate

POST /pgui/services/paymentServices/initiate/payment with Content-Type: application/json.

Required: every hosted field plus CUST_NAME, PAYMENT_TYPE (CC or DC), CARD_NUMBER, CARD_EXP_DT, CVV, and HASH over the JSON you send.

TXNTYPE must be SALE. Other payment types return 113. Duplicate ORDER_ID returns 018.

JSON
{
  "APP_ID": "1000221129001154",
  "ORDER_ID": "S2S-001",
  "TXNTYPE": "SALE",
  "CUST_NAME": "Sara Khan",
  "CUST_FIRST_NAME": "Sara",
  "CUST_LAST_NAME": "Khan",
  "CUST_CITY": "Dubai",
  "CUST_STATE": "DU",
  "CUST_COUNTRY": "AE",
  "CUST_ZIP": "00000",
  "CUST_PHONE": "0501234567",
  "CUST_EMAIL": "buyer@example.test",
  "AMOUNT": "1000",
  "CURRENCY_CODE": "784",
  "PAYMENT_TYPE": "CC",
  "CARD_NUMBER": "5100000000000511",
  "CARD_EXP_DT": "112029",
  "CVV": "456",
  "RETURN_URL": "https://merchant.example/return",
  "HASH": "<128 hex>"
}

Captured (Mastercard test card)

JSON
{
  "RESPONSE_CODE": "000",
  "STATUS": "Captured",
  "IS_CHALANGE_REQUIRED": "No",
  "TXN_ID": "16-digit id",
  "MOP_TYPE": "MC",
  "PG_DESCRIPTOR": "Test_PG_Display",
  "HASH": "<signed>"
}

Spelling of IS_CHALANGE_REQUIRED is as implemented (one A).

3DS pending (Visa test card)

JSON
{
  "RESPONSE_CODE": "000",
  "STATUS": "Enrolled",
  "IS_CHALANGE_REQUIRED": "Yes",
  "PG_TXN_MESSAGE": "ThreeD Authentication Pending",
  "TXN_ID": "16-digit id"
}

That is not success. Continue to capture.

Declined

RESPONSE_CODE=004, STATUS=Declined. Wrong CVV/expiry on a known PAN also declines.

2. Capture (3DS)

POST /pgui/jsp/capturePayment as a browser form — not JSON.

FieldNotes
APP_IDSame merchant
TXN_IDFrom initiate
HASHHash of the fields you post (usually those three plus any extras you include)

If the sale is Enrolled or IS_CHALANGE_REQUIRED=Yes, the sandbox marks it Captured. The browser is then auto-POSTed to RETURN_URL (or shown the result table if no return URL). This is a fake challenge — there is no issuer OTP.

Which processor runs the sale

Same assignment as hosted: routeForMerchantplugin.sale. The JSON body does not include a processor id — it comes from the merchant record. See Processors.