Environment Variables
Never commit secrets to version control. Use environment variables for all sensitive configuration:
# .gitignore
.env
.env.local
.env.*.local
// Good — Use environment variables
const saligpay = new SaligPay ({
clientId: process.env. SALIGPAY_CLIENT_ID ,
clientSecret: process.env. SALIGPAY_CLIENT_SECRET ,
});
// Bad — Hardcoded credentials
const saligpay = new SaligPay ({
clientId: "hardcoded-client-id" ,
clientSecret: "hardcoded-secret" ,
});
Webhook Secret
Use webhook signature verification to ensure webhooks are from SaligPay:
const WEBHOOK_SECRET = process.env. SALIGPAY_WEBHOOK_SECRET ;
app. post ( "/webhooks/saligpay" , async ( req , res ) => {
try {
const payload = saligpay.webhooks. constructVerifiedEvent (
req.body,
req.headers[ "x-saligpay-signature" ],
req.headers[ "x-saligpay-timestamp" ]
);
if ( ! payload.externalId || ! payload.status) {
return res. status ( 400 ). send ({ error: "Invalid payload" });
}
await handlePayment (payload);
return res. send ({ received: true });
} catch (error) {
console. error ( "Webhook error:" , error);
return res. status ( 400 ). send ({ error: "Invalid webhook" });
}
});
Token Storage
For server-side applications, tokens are managed automatically by the SDK:
// SDK handles token storage and refresh automatically
await saligpay. ensureAuthenticated ();
// If you need to store tokens manually (e.g., for multi-tenant apps)
const tokens = await saligpay.auth. authenticate (clientId, clientSecret);
// Store tokens securely (encrypted at rest)
// Use the access token for subsequent requests
const checkout = await saligpay.checkout. create (options, tokens.accessToken);
Security Checklist
Practice Implementation Store credentials in environment variables process.env.SALIGPAY_CLIENT_IDUse sandbox for development env: "sandbox"Verify webhook signatures constructVerifiedEvent()Implement rate limiting Use express-rate-limit Use HTTPS in production TLS 1.2+ required Validate webhook payloads Check required fields Handle errors gracefully Never expose internal errors Rotate credentials regularly Update env vars
Validate Webhook Origin
const WEBHOOK_SECRET = process.env. SALIGPAY_WEBHOOK_SECRET ;
app. post ( "/webhooks/saligpay" , async ( req , res ) => {
try {
const payload = saligpay.webhooks. constructEvent (req.body);
if ( ! payload.externalId || ! payload.status) {
return res. status ( 400 ). send ({ error: "Invalid payload" });
}
await handlePayment (payload);
return res. send ({ received: true });
} catch (error) {
console. error ( "Webhook error:" , error);
return res. status ( 400 ). send ({ error: "Invalid webhook" });
}
});
Use Sandbox Environment
// Always use sandbox for development
const saligpay = new SaligPay ({
clientId: process.env. SALIGPAY_CLIENT_ID ,
clientSecret: process.env. SALIGPAY_CLIENT_SECRET ,
env: process.env. NODE_ENV === "production" ? "production" : "sandbox" ,
});
Implement Rate Limiting
import rateLimit from "express-rate-limit" ;
const webhookLimiter = rateLimit ({
windowMs: 15 * 60 * 1000 , // 15 minutes
max: 100 , // Limit each IP to 100 requests per windowMs
});
app. post ( "/webhooks/saligpay" , webhookLimiter, async ( req , res ) => {
await saligpay.webhooks. listen (req, res, handler);
});
Secure Webhook Endpoints
// Use HTTPS in production
const WEBHOOK_SECRET = process.env. WEBHOOK_SECRET ;
app. post ( "/webhooks/saligpay" , async ( req , res ) => {
const signature = req.headers[ "x-webhook-signature" ];
if (signature !== WEBHOOK_SECRET ) {
return res. status ( 401 ). send ({ error: "Unauthorized" });
}
await saligpay.webhooks. listen (req, res, handler);
});
Last modified on May 5, 2026