Your Guide to SADAD Payment Gateway
Tags: react, sadad, paymen, javascript
Published: 2023-09-16 17:40:15

## Why Sadad

1. Simple Integration: Easily add our payment gateway to your setup.
2. 
3. Strong Security: Trust in our robust security features.
4. 
5. Qatar's Top Payment Solution: Choose the leading payment gateway in Qatar.

## How it works

## At the Frontend

- Prepare and collect order details, including information such as the order amount, customer email, and phone number.
- Generate a signature using the signature generation method described in the document at developer.sadad.qa/all_plugins/sadad_signat... Note that signature generation serves as an alternative method to the checksumhash field, so do not send both the signature and checksumhash together. You can find a sample HTML form with values in the provided PDF guide.
- Utilize the fields used to generate the signature to create an HTML form. Include the signature field within the form. Submit this form as a standard HTML form to sadadqa.com/webpurchase.
- When the user accesses the Sadad payment page, they can make payments using methods such as credit cards or debit cards. After completing the transaction, the user will be redirected back to the callback URL page specified in step 3.
- Upon redirection, you will receive the order_id and transaction status fields, along with the checksumhash.
- To verify the checksumhash, apply the same signature generation method as described in step 2. Ensure that when creating the plain string (before hashing), you exclude the checksumhash parameter and consider only the incoming POST parameters
.

## AT the callback url

- Upon receiving a callback URL, you will find the following POST parameters:

"MID" => "1234567"

"ORDERID" => "123"

"RESPCODE" => "1"

"RESPMSG" => "Txn Success"

"STATUS" => "TXN_SUCCESS"

"TXNAMOUNT" => "38"

"issandboxmode" => "1"

"transaction_number" => "SD1234567899"

"transaction_status" => "3"

"website_ref_no" => "123"

"checksumhash" => "f76ad853c3f28f69791da1be43660a668068534c51a2a10d73f5fd29a9023558"

- Notably, the "checksumhash" field functions as a signature.

- Both "website_ref_no" and "ORDERID" fields contain the same value, representing the ORDER_ID used in the original request to Sadad.
- The "transaction_status" field with a value of 3 indicates a successful transaction; otherwise, it signifies a failed transaction.
- To ensure data integrity, verify the "checksumhash" field by creating a signature string using all incoming fields, excluding the "checksumhash" field. The signature generation process should mirror that used during the initial request creation. Finally, compare the generated signature with the "checksumhash" field value.


![Image description](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/py3ox9gi2rcilatd0lqf.png)

- You have to **_add frontend domain as well as callback_** domain in sadad in Api section

## Code

## Code at Frontend
`
import { SHA256 } from "crypto-js";
import React, { useEffect, useState } from "react";


// function to generate checksum
const generateSignature = (
	data,
	secretKey
): string => {
    // data has to be forted which generating checksum
	const sortedKeys = Object.keys(data)
		.filter((key) => key !== "productdetail")
		.sort();

	let queryString = "";
	for (const key of sortedKeys) {
		queryString += data[key];
	}
	const signatureString = secretKey + queryString;
	const hashedSignature = SHA256(signatureString).toString();
	return hashedSignature;
};
function ShadadEventPayment() {
	const [signature, setSignature] = useState<string>("");
	const data = {
        // callback url is the url of the backend
		CALLBACK_URL: `${process.env.NEXT_PUBLIC_CALL_BACK_URL}/events/payment`,
		MOBILE_NO: userInfo.MOBILE_NO,
		ORDER_ID: "7885845",
		SADAD_WEBCHECKOUT_PAGE_LANGUAGE: lng == "ar" ? "Arb" : "ENG",
		TXN_AMOUNT: amount,
		merchant_id: "merchent_id",
		txnDate: dateAndTime,
		productdetail: [
			{
				order_id: "",
				amount: "18.00", // here the amout will be from frontend and in the form amount will be from backend if both are not same shadad will not work automaticly
				quantity:"1",
			},
		],
		WEBSITE: "www.aiqatar.qa",
	};

	useEffect(() => {
            // you have this secret key from your shadad account
            const SecretKey = process.env.NEXT_PUBLIC_SHADAD_SECRET_KEY_EVENT!; // I am using test mode secret key
				//getsignature
				setSignature(generateSignature(data, SecretKey));
				const form = document.getElementById(
				"sadad_payment_form"
			) as HTMLFormElement;
			form.submit();
	}, []);

	return (
		<form
			action="https://sadadqa.com/webpurchase"
			method="post"
			id="sadad_payment_form"
			name="gosadad"
			data-link="https://sadadqa.com/webpurchase"
		>
			{/* Hidden input fields */}
			<input type="hidden" name="CALLBACK_URL" value={data.CALLBACK_URL} />
			<input type="hidden" name="MOBILE_NO" value={userInfo.MOBILE_NO} />
			<input type="hidden" name="ORDER_ID" value={7885845} />
			<input
				type="hidden"
				name="SADAD_WEBCHECKOUT_PAGE_LANGUAGE"
				value={lng == "ar" ? "Arb" : "ENG"}
			/>
			<input type="hidden" name="TXN_AMOUNT" value={amoutFromBck} />
			<input type="hidden" name="WEBSITE" value="www.aiqatar.qa" />
			<input type="hidden" name="merchant_id" value={data.merchant_id} />
			<input type="hidden" name="txnDate" value={dateAndTime} />

			<input type="hidden" name="signature" value={signature} />

			<input
				type="hidden"
				name="productdetail[0][order_id]"
				value={7885845}
			/>
			<input
				type="hidden"
				name="productdetail[0][amount]"
				value={18.00}
			/>
			<input type="hidden" name="productdetail[0][quantity]" value="1" />
			{/* <input type="submit" /> */}
			<p className="text-center">{t("Redirecting")}</p>
		</form>
	);
}

export default ShadadEventPayment;`

## Code at Backend

`// function to generate the checksumhash
export function generateSignature(paymentData: PaymentData) {
	// sort the keys of the object
	const sortedKeys = Object.keys(paymentData).sort();

	let queryString = "";

	for (const key of sortedKeys) {
		queryString += paymentData[key as keyof PaymentData];
	}
    // you can get secret key from shadad after login
	const SecretKey = process.env.SHADAD_SECRET_KEY_EVENT!;
	const signatureString = SecretKey + queryString;

	// hash signature with hash256
	const hash = crypto.createHash("sha256");
	hash.update(signatureString);
	const signature = hash.digest("hex"); // Capture the hash value as a hexadecimal string
	return signature;
}

// 
// @DESC this route will be called by sadad after payment
// @Route POST /events/payments
// @Access Public
export const make_payment = asyncRequestHandler(
	// define the schema of the request body
    // if you are not using Zod you can ignore bellow code 
    /*
	z.object({
		MID: z.string().optional(),
		ORDERID: z.string().optional(),
		RESPCODE: z.string().optional(),
		RESPMSG: z.string().optional(),
		STATUS: z.string().optional(),
		TXNAMOUNT: z.string(),
		issandboxmode: z.string().optional(),
		transaction_number: z.string().optional(),
		transaction_status: z.string().optional(),
		website_ref_no: z.string().optional(),
		checksumhash: z.string().optional(),
	}),
*/

	async (req, res) => {
		// extract the fields from the request body
		const { checksumhash: signatureFromShadad, ...pymentData } = req.body;
		// console.log(req.body);
		// if RESPCODE 1 – Transaction Success 400 – Transaction Pending 402 – Transaction pending confirmation from bank 810 – Transaction failed
		// check the status

		const generateHashSignature = generateSignature(pymentData);
		if (generateHashSignature !== signatureFromShadad) {
			// signature didn't match return error
			return res.status(400).send(
				`<body style="margin: 0; display: flex; justify-content: center; align-items: center; height: 100vh; background-color: #f5f5f5;">
        		    <div style="background-color: #fff; padding: 20px; border-radius: 8px; box-shadow: 0 0 8px rgba(0, 0, 0, 0.1); max-width: 400px; text-align: center;">
        			    <h1 style="color: #dc3545; font-size: 24px;">Payment failed!</h1>
        			    <p style="font-size: 16px;">Signature didn't match</p>
        			</div>
        		</body>
        			`
			);
		}
});`

All done

You can also refer SADAD's official [Documentation](https://developer.sadad.qa/)