| Time | Status | User Agent | |
|---|---|---|---|
Retrieving recent requests… | |||
Introduction
This guide explains how to perform a SALE transaction while saving the customer’s card for future use.
This flow is identical to a standard SALE transaction, with the addition of tokenization using the save_token parameter.
Endpoint
POST https://api.edfapay.com/payment/post
Content-Type: multipart/form-data
Request Parameters
| Field | Type | Required | Description |
|---|---|---|---|
| action | String | Yes | Transaction type. Use "SALE" for standard sale transactions. |
| client_key | String | Yes | Your unique merchant identifier issued by Edfapay. |
| order_id | String | Yes | Unique identifier for the transaction/order. |
| order_amount | Decimal | Yes | Amount to be charged (e.g., 0.11). |
| order_currency | String | Yes | Currency code in ISO 4217 format (e.g., SAR). |
| order_description | String | Yes | Description of the order. |
| req_token | String | Optional | "Y" to request a tokenized transaction; "N" otherwise. |
| payer_first_name | String | Yes | First name of the customer. |
| payer_last_name | String | Yes | Last name of the customer. |
| payer_address | String | Yes | The email or address of the customer. |
| payer_country | String | Yes | Country code (e.g., SA, UAE). |
| payer_city | String | Yes | City of the payer. |
| payer_zip | String | Yes | ZIP or postal code of the payer. |
| payer_email | String | Yes | The email address of the customer. |
| payer_phone | String | Yes | The customer’s phone number with country code. |
| payer_ip | String | Yes | IP address of the Customer |
| term_url_3ds | String | Yes | URL that the customer is redirected to after completing 3D Secure authentication |
| auth | String | Optional | "Y" to authorize only, "N" for authorize+ capture (default). |
| recurring_init | String | Optional | "Y"If this transaction is a recurring initiation |
| hash | String | Yes | Secure hash for request authentication. |
| card_number | String | Yes | Customer's card number (PAN) |
| card_exp_month | String | Yes | Expiry month in MM format |
| card_exp_year | String | Yes | Expiry year in YYYY format |
| card_cvv2 | String | Yes | CVV/CVC of the card |
| save_token | String | Yes | Must be "Y" to save card |
Critical Requirement
The save_token parameter must be set to "Y".
If not provided, no card token will be generated and the card cannot be reused.
Hash Generation
var password = "YOUR_SECRET_KEY";
var cardNumber = "5123450000000008";
var email = "[email protected]";
const ReverseString = str => [...str].reverse().join('');
var final = (
ReverseString(email) +
password +
ReverseString(cardNumber.substr(0,6) + cardNumber.substr(-4))
).toUpperCase();
var finalHash = CryptoJS.MD5(final).toString();
Common MistakesMake sure to reverse the email and card segments correctly. Any mismatch between hash calculation on your side and our validation will cause the request to fail.
Notes:
- password → Your secret hash key from EdfaPay.
- cardNumber → The full card number entered by the customer.
- email → The customer’s email used in hash generation.
Example cURL Request
curl --location 'https://apidev.edfapay.com/payment/post' \
--form 'client_key="XXXXXXXX"' \
--form 'order_id="Saved_Card_0000"' \
--form 'hash="HASH_VALUE"' \
--form 'order_amount="100"' \
--form 'card_number="5123450000000008"' \
--form 'card_exp_month="01"' \
--form 'card_exp_year="2039"' \
--form 'card_cvv2="100"' \
--form 'payer_phone="+966556644333"' \
--form 'payer_country="SA"' \
--form 'payer_address="[email protected]"' \
--form 'action="SALE"' \
--form 'payer_zip="623524"' \
--form 'payer_ip="176.44.76.100"' \
--form 'order_currency="SAR"' \
--form 'payer_first_name="Test"' \
--form 'payer_city="Riyadh"' \
--form 'auth="N"' \
--form 'payer_last_name="User"' \
--form 'order_description="Test Order"' \
--form 'payer_email="[email protected]"' \
--form 'term_url_3ds="https://your-webhook.com"' \
--form 'recurring_init="N"' \
--form 'req_token="N"' \
--form 'save_token="Y"'Important Note — Hash Generation
The hash parameter included in the request body is dynamically generated for each request and must not be hardcoded.
The hash value is calculated using specific request parameters combined with your merchant secret key. Any change in the request data requires regenerating the hash before sending the request.
🔗 For detailed steps and the exact formula used to generate the hash, refer to the Hash Generation Section.
Response Example
{
"action": "SALE",
"result": "REDIRECT",
"status": "REDIRECT",
"order_id": "Saved_Card_0000",
"trans_id": "XXXXXXXXXXXXXXXX",
"trans_date": "22-04-2026 15:44:05",
"amount": "100.00",
"currency": "SAR",
"redirect_url": "https://api.edfapay.com/payment/Collector",
"redirect_params": {
"body": "EDFPAY_REF_f27ec0fd-1234-5678-9d56-9d9f22608beb"
},
"redirect_method": "POST"
}action: The type of transaction performed (always SALE).result: Tells you what to do next (REDIRECT means further action is needed).status: Current transaction status (also REDIRECT here).order_id: The order ID you sent in the original request.trans_id: Unique transaction ID generated by EdfaPay (also used at the end of the redirect_url).trans_date: The date and time of the transaction.amount: The transaction amount.currency: The currency used (e.g., SAR).redirect_url: The URL to which you should send the next POST request.redirect_params.body: Base64-encoded data to include in the POST request body.redirect_method: HTTP method to use for the redirect (always POST).merchant_id: Merchant Name.
Redirect to Collector
POST https://api.edfapay.com/payment/Collector
Content-Type: application/json
{
"body": "BASE64_ENCODED_JSON_STRING"
}
Important NoteThe body must be sent exactly as received from redirect_params.body. It is Base64-encoded JSON that the collector uses to complete the transaction.
Response
This request will return an HTML page (3DS challenge, OTP, etc.) which must be rendered to the user. You can open this in:
- A browser (web integration)
- A WebView (mobile apps)
Next Step
Use the card_token to perform future payments without card details.
200