> ## Documentation Index
> Fetch the complete documentation index at: https://razorpay.com/docs/llms.txt
> Use this file to discover all available pages before exploring further.

# Security

> Protect your keys and verify every callback and webhook signature, with the scenarios and failures to test.

Available in
🇮🇳 India

Protect your keys and verify every callback. Never expose your key secret on the client. Verify the `razorpay_signature` on the payment callback and the `X-Razorpay-Signature` header on every webhook. Reject tampered values.

| Area | Do this |
| - | - |
| API keys | Keep them on your server only. Never send them to a browser or app. Rotate them if they leak. |
| Payment signature | Recompute the HMAC SHA256 of `order_id\|razorpay_payment_id` with your key secret, using the order ID you stored. |
| Webhook signature | Verify `X-Razorpay-Signature` with your webhook secret, on the raw body, before parsing it. |
| Card data | Collect and pass card data only within your PCI-DSS scope. Never store CVV. Never log full card numbers. |
| Amounts | Take the amount from your order, never from the browser. |
| Network | Use TLS 1.2 or later. Optionally, allowlist Razorpay's webhook IPs. |

| Behaviour | Live mode | Test mode |
| - | - | - |
| Signatures | Live key and webhook secrets | Test key and test webhook secret: same algorithm |
| Keys | Live keys | Test keys; never mix them |

## Scenarios to test your integration

| Scenario ID | Area | Scenario | Trigger | Steps to follow | Test mode |
| - | - | - | - | - | - |
| BP-02 | Payment signature | Verify the payment signature | A callback from a success trigger | Recompute HMAC-SHA256 of `order_id\|razorpay_payment_id` with your key secret, using the order ID you stored. Send a tampered value; confirm it is rejected. | Available |
| BP-37 | Webhook signature | Verify the webhook signature on the raw body | A stored webhook | Recompute `X-Razorpay-Signature` with your webhook secret over the raw body, before parsing. Send a changed body; confirm it is rejected. | Available |
| BP-16 | Keys and card data | Keys and card data stay on your server | Code review | API keys never reach a browser or app. No CVV stored; no full card numbers in logs. | Client-side |
| BP-38 | Amounts | Take the amount from your order | Change the amount in the browser | Confirm your server creates the order from its own cart total. See ORD-01. | Available |
| BP-39 | Network | TLS 1.2+ and the webhook IP allowlist | Your infrastructure | Confirm TLS 1.2 or later; optionally allowlist Razorpay's webhook IPs. | Client-side |

## Scenario details

**BP-02 · BP-37 — Verify both signatures**

*Before you start:* a callback and a stored webhook from a success trigger.

*How to test:* compute HMAC-SHA256(`order_id` + `"|"` + `razorpay_payment_id`, key secret) with the order ID you stored; compare to `razorpay_signature`. Compute HMAC-SHA256(raw webhook body, webhook secret); compare to `X-Razorpay-Signature`. Change one character in each and confirm both are rejected.

*Expected result:* genuine values pass; tampered values are rejected.

*Your integration should:* use the stored `order_id`, never one from the callback, and the raw body, never re-serialised JSON.

## Common integration gaps to avoid

| Gap | What goes wrong in production | What to do | Test with |
| - | - | - | - |
| Signature over the callback's order ID | An attacker swaps in a cheaper paid order. | Use the order ID you stored. | BP-02 |
| Webhook verified after parsing | Re-serialised JSON never matches. | Verify the raw body. | BP-37 |
| Keys in the app | Anyone can create orders and refunds on your account. | Keep keys server-side. | BP-16 |

## Simulate failures

**Available in test mode**

| Failure | How to simulate | Expected handling | Scenario |
| - | - | - | - |
| Tampered callback | Change `razorpay_signature` | Rejected | BP-02 |
| Tampered webhook | Change the body | Rejected | BP-37 |
| Amount changed in the browser | Edit the client request | Server uses its own amount | BP-38 |

**Not available in test mode:** none.

### Related Information

* [Best Practices](https://razorpay.com/docs/payments/payment-gateway/s2s-integration/test-s2s/best-practices)
* [Refunds](https://razorpay.com/docs/payments/payment-gateway/s2s-integration/test-s2s/refunds.md)
* [Orders](https://razorpay.com/docs/payments/payment-gateway/s2s-integration/test-s2s/orders.md)
