Skip to main content
Follow these best practices to ensure your payment integration is secure and reliable.

Essential Security Practices

Always verify webhooks

Verify the signature on every webhook to ensure it’s from Payviox and hasn’t been tampered with.

Use HTTPS

Always use HTTPS for your webhook endpoint to ensure data is encrypted in transit.

Handle idempotency

Be prepared to receive the same webhook multiple times. Use order_id and session_id to prevent duplicate processing.

Respond quickly

Return 200 OK within 30 seconds. Process webhooks asynchronously if needed.

Webhook Security

Critical: Never process webhooks without verifying the signature. This protects against malicious actors sending fake payment notifications.

Signature Verification

Always verify webhook signatures using HMAC SHA256:
// PHP example
$payload = file_get_contents('php://input');
$signature = $_SERVER['HTTP_SIGNATURE'];
$webhookToken = 'your_webhook_token';

$computed = hash_hmac('sha256', $payload, $webhookToken);

if (!hash_equals($computed, $signature)) {
    http_response_code(401);
    exit('Invalid signature');
}

Use Timing-Safe Comparison

Always use timing-safe comparison functions:
  • PHP: hash_equals()
  • Node.js: crypto.timingSafeEqual()
  • Python: hmac.compare_digest()
This prevents timing attacks.

Idempotency Handling

Webhooks may be delivered more than once. Implement idempotency checks:
// Check if already processed
$sessionId = $data['metadata']['integration_session_id'];
$orderId = $data['order_id'];

$existingPayment = Payment::where('session_id', $sessionId)
                          ->where('order_id', $orderId)
                          ->first();

if ($existingPayment && $existingPayment->status === 'completed') {
    // Already processed - skip
    return response()->json(['status' => 'already_processed'], 200);
}

// Process the payment
// ...

Asynchronous Processing

For optimal performance, process webhooks asynchronously:
// Laravel example with queued job
public function handleWebhook(Request $request) {
    // Verify signature...
    
    // Dispatch to queue
    ProcessWebhook::dispatch($data);
    
    // Immediately return 200 OK
    return response()->json(['status' => 'queued'], 200);
}
Responding quickly prevents webhook timeout and retry attempts.

API Token Security

Never hardcode API tokens in your code:
// ✅ Good
const payviox = new Payviox(process.env.PAYVIOX_API_TOKEN);

// ❌ Bad
const payviox = new Payviox('pk_live_xxxxxxxxxxxxx');
Use different tokens for different environments:
const PAYVIOX_TOKEN = process.env.NODE_ENV === 'production'
  ? process.env.PAYVIOX_LIVE_TOKEN
  : process.env.PAYVIOX_TEST_TOKEN;
Change your API tokens periodically and immediately if compromised.
For production, use tokens only on your server, never in frontend code.

Error Handling

Implement proper error handling in your integration:
async function initiatePayment() {
  try {
    await payviox.createSession({
      amount: 1000,
      currency: 'USD',
      // ... other params
    }, {
      redirect: true
    });
  } catch (error) {
    // Log error for debugging
    console.error('Payment error:', error);
    
    // Show user-friendly message
    if (error.status === 401) {
      alert('Configuration error. Please contact support.');
    } else if (error.status === 400) {
      alert('Invalid payment details. Please check and try again.');
    } else {
      alert('Payment failed. Please try again later.');
    }
  }
}

Logging and Monitoring

Log all webhooks

Keep detailed logs of all webhook events with timestamps for debugging and audit trails.

Monitor success rates

Track payment success and failure rates to identify issues early.

Set up alerts

Configure alerts for high failure rates or webhook delivery issues.

Review dashboard regularly

Check your Payviox dashboard for payment trends and anomalies.

Testing Checklist

Production Checklist

Common Issues and Solutions

Possible causes:
  • Incorrect webhook URL in dashboard
  • Firewall blocking Payviox IP addresses
  • Server not responding within 30 seconds
Solution:
  • Verify webhook URL in dashboard
  • Check server logs for errors
  • Ensure endpoint returns 200 OK quickly
Possible causes:
  • Using wrong webhook token
  • Modifying request body before verification
  • Incorrect HMAC algorithm
Solution:
  • Verify webhook token from dashboard
  • Always verify against raw request body
  • Use HMAC SHA256 algorithm
Possible causes:
  • Not implementing idempotency checks
  • Slow response times causing retries
Solution:
  • Implement idempotency using session_id and order_id
  • Return 200 OK immediately
  • Process asynchronously if needed
Possible causes:
  • Invalid API token
  • Missing required fields
  • Invalid payment method ID
Solution:
  • Verify API token is correct
  • Check all required fields are provided
  • Ensure payment method exists and is active

Need Help?

Documentation

Browse our complete documentation

Support