Verify Payments
After a customer completes a checkout, always verify the transaction on your server before fulfilling an order or granting access. Client-side callbacks can be tampered with — server-side verification is the source of truth.
Never fulfill an order based solely on a client-side callback. Always verify via the server before processing.
Using the SDK
import { Pay100 } from "@100pay-hq/100pay.js";
const client = new Pay100({
publicKey: "your_public_key",
secretKey: "your_secret_key",
});
const result = await client.verify("transaction_id");
if (result.status === "success") {
// Payment confirmed — fulfill order
console.log("Transaction data:", result.data);
} else {
// Payment not confirmed
console.error("Verification failed:", result.message);
}Typical Verification Flow
Receive the Transaction ID
After checkout, the callback handler in the Checkout SDK receives a reference string — this is the transaction ID to verify.
// In your checkout setup (client-side)
shop100Pay.setup({
// ...
callback: (reference) => {
// Send reference to your server for verification
fetch("/api/verify-payment", {
method: "POST",
body: JSON.stringify({ reference }),
});
},
});Verify on the Server
// /api/verify-payment (server-side — e.g. Next.js API route)
import { Pay100 } from "@100pay-hq/100pay.js";
const client = new Pay100({
publicKey: process.env.NEXT_PUBLIC_100PAY_PUBLIC_KEY!,
secretKey: process.env.PAY100_SECRET_KEY!,
});
export async function POST(req: Request) {
const { reference } = await req.json();
const result = await client.verify(reference);
if (result.status === "success") {
// Fulfill order, update DB, etc.
return Response.json({ success: true });
}
return Response.json({ success: false, message: result.message }, { status: 400 });
}Fulfill the Order
Only proceed with order fulfillment (e.g. grant access, ship product, update database) once result.status === "success".
Parameters
| Parameter | Type | Required | Description |
|---|---|---|---|
transactionId | string | ✅ | The unique transaction reference returned by the Checkout SDK |
Response
interface IVerifyResponse {
status: "success" | "error";
data?: ITransactionData | null;
message?: string;
}| Field | Type | Description |
|---|---|---|
status | "success" | "error" | Verification outcome |
data | object | null | Full transaction object on success (amount, currency, status, etc.) |
message | string | Error message if status is "error" |
Error Handling
import { Pay100, PaymentVerificationError } from "@100pay-hq/100pay.js";
try {
const result = await client.verify(transactionId);
if (result.status === "success") {
// Payment is valid — process order
} else {
// The API returned an error status
console.error(result.message);
}
} catch (error) {
if (error instanceof PaymentVerificationError) {
// Network failure or invalid response
console.error("Verification error:", error.message);
}
}Common error messages:
| Message | Cause |
|---|---|
"Access Denied, Invalid KEY supplied" | Wrong or missing public key |
"invalid payment id supplied" | Transaction ID doesn’t exist |
"Something went wrong..." | Empty or unparseable response |
The verify endpoint uses your Public API Key — no secret key is required just for verification. However, including the secret key enables signed requests for extra security.
Next Steps
- Checkout — set up the client-side payment modal
- Asset Transfers — transfer funds between wallets
- Webhooks — receive real-time payment event notifications