{
    "info": {
        "name": "Merchant Webhook API (EN)",
        "description": "Simulating Paynance's outbound merchant webhook.\n\nThis collection does not call the Paynance API: it sends the very same payloads, with the very same signature, to YOUR OWN endpoint that you will receive in production — so you can exercise your integration end to end without a real payment.\n\nSetup:\n1. `merchant_endpoint_url` — your receiving URL.\n2. `webhook_secret` — readable in the Paynance interface with the `Reveal secret` button.\n\nThe `Paynance-Signature` header is calculated by the collection's pre-request script (HMAC-SHA256 over the raw body, hex, no timestamp).\n\nThe tests assert the response CLASS (2xx / 4xx), because that is the contract. Recommended concrete codes: `202 Accepted` once you have accepted the event, `401 Unauthorized` on a signature failure.\n\nDetails: https://paynance.hu/api-doc/merchant-webhook-guide?lang=en — machine-readable schema: https://paynance.hu/api-doc/merchant-webhook?lang=en (OpenAPI 3.0.3). Magyar változat: https://paynance.hu/merchant-webhook/Merchant_Webhook_API.hu.postman_collection.json.",
        "schema": "https://schema.getpostman.com/json/collection/v2.1.0/collection.json"
    },
    "event": [
        {
            "listen": "prerequest",
            "script": {
                "type": "text/javascript",
                "exec": [
                    "// Paynance calculates HMAC-SHA256 over the RAW body, hex encoded, with no timestamp.",
                    "// This script does the same, so your endpoint receives the request with a real signature.",
                    "const secret = pm.collectionVariables.get('webhook_secret');",
                    "const body = pm.request.body.raw;",
                    "const signature = CryptoJS.HmacSHA256(body, secret).toString(CryptoJS.enc.Hex);",
                    "",
                    "pm.request.headers.upsert({ key: 'Paynance-Signature', value: signature });"
                ]
            }
        }
    ],
    "variable": [
        {
            "key": "merchant_endpoint_url",
            "value": "https://example.com/webhooks/paynance",
            "description": "Your receiving URL (https only, on a publicly reachable address)."
        },
        {
            "key": "webhook_secret",
            "value": "whsec_...",
            "description": "The signing secret from the Paynance Webshop settings page."
        }
    ],
    "item": [
        {
            "name": "payment.authorised",
            "event": [
                {
                    "listen": "test",
                    "script": {
                        "type": "text/javascript",
                        "exec": [
                            "pm.test('The endpoint returns 2xx', function () {",
                            "    pm.expect(pm.response.code).to.be.within(200, 299);",
                            "});",
                            "",
                            "pm.test('The response arrived within 5 seconds', function () {",
                            "    pm.expect(pm.response.responseTime).to.be.below(5000);",
                            "});"
                        ]
                    }
                }
            ],
            "request": {
                "method": "POST",
                "header": [
                    {
                        "key": "Content-Type",
                        "value": "application/json"
                    }
                ],
                "body": {
                    "mode": "raw",
                    "raw": "{\n    \"version\": 1,\n    \"event_id\": \"0192f1a2-3b4c-7d5e-8f60-1a2b3c4d5e6f\",\n    \"event_type\": \"payment.authorised\",\n    \"created_at\": \"2026-09-09T12:04:12+00:00\",\n    \"data\": {\n        \"psp_reference\": \"NC6HT9CRT65ZGN82\",\n        \"original_psp_reference\": null,\n        \"merchant_reference\": \"ORDER-10231\",\n        \"transaction_type\": \"payment\",\n        \"success\": true,\n        \"amount\": {\n            \"value\": 249900,\n            \"currency\": \"HUF\"\n        },\n        \"payment_method\": \"visa\",\n        \"reason\": null,\n        \"event_date\": \"2026-09-09T12:04:11+02:00\",\n        \"shopper_email\": \"vevo@example.com\",\n        \"store\": \"ST322LJ223223K5FQ4NM3JWLK\"\n    }\n}",
                    "options": {
                        "raw": {
                            "language": "json"
                        }
                    }
                },
                "url": {
                    "raw": "{{merchant_endpoint_url}}",
                    "host": [
                        "{{merchant_endpoint_url}}"
                    ]
                },
                "description": "Paynance sends this on a `payment.authorised` event. The signature is calculated by the collection's pre-request script."
            },
            "response": []
        },
        {
            "name": "payment.failed",
            "event": [
                {
                    "listen": "test",
                    "script": {
                        "type": "text/javascript",
                        "exec": [
                            "pm.test('The endpoint returns 2xx', function () {",
                            "    pm.expect(pm.response.code).to.be.within(200, 299);",
                            "});",
                            "",
                            "pm.test('The response arrived within 5 seconds', function () {",
                            "    pm.expect(pm.response.responseTime).to.be.below(5000);",
                            "});"
                        ]
                    }
                }
            ],
            "request": {
                "method": "POST",
                "header": [
                    {
                        "key": "Content-Type",
                        "value": "application/json"
                    }
                ],
                "body": {
                    "mode": "raw",
                    "raw": "{\n    \"version\": 1,\n    \"event_id\": \"0192f1a3-77bd-7c11-9a04-8f3d5b21c9aa\",\n    \"event_type\": \"payment.failed\",\n    \"created_at\": \"2026-09-09T12:07:45+00:00\",\n    \"data\": {\n        \"psp_reference\": \"LK2P9WQ4RT88ZZ01\",\n        \"original_psp_reference\": null,\n        \"merchant_reference\": \"ORDER-10232\",\n        \"transaction_type\": \"payment\",\n        \"success\": false,\n        \"amount\": {\n            \"value\": 249900,\n            \"currency\": \"HUF\"\n        },\n        \"payment_method\": \"mc\",\n        \"reason\": \"Refused\",\n        \"event_date\": \"2026-09-09T12:07:44+02:00\",\n        \"shopper_email\": \"vevo@example.com\",\n        \"store\": \"ST322LJ223223K5FQ4NM3JWLK\"\n    }\n}",
                    "options": {
                        "raw": {
                            "language": "json"
                        }
                    }
                },
                "url": {
                    "raw": "{{merchant_endpoint_url}}",
                    "host": [
                        "{{merchant_endpoint_url}}"
                    ]
                },
                "description": "Paynance sends this on a `payment.failed` event. The signature is calculated by the collection's pre-request script."
            },
            "response": []
        },
        {
            "name": "payment.captured",
            "event": [
                {
                    "listen": "test",
                    "script": {
                        "type": "text/javascript",
                        "exec": [
                            "pm.test('The endpoint returns 2xx', function () {",
                            "    pm.expect(pm.response.code).to.be.within(200, 299);",
                            "});",
                            "",
                            "pm.test('The response arrived within 5 seconds', function () {",
                            "    pm.expect(pm.response.responseTime).to.be.below(5000);",
                            "});"
                        ]
                    }
                }
            ],
            "request": {
                "method": "POST",
                "header": [
                    {
                        "key": "Content-Type",
                        "value": "application/json"
                    }
                ],
                "body": {
                    "mode": "raw",
                    "raw": "{\n    \"version\": 1,\n    \"event_id\": \"0192f1b0-04ce-7a52-b7d1-6e0c9f4471d3\",\n    \"event_type\": \"payment.captured\",\n    \"created_at\": \"2026-09-09T14:31:02+00:00\",\n    \"data\": {\n        \"psp_reference\": \"QT4M8ZC2XX10PP77\",\n        \"original_psp_reference\": \"NC6HT9CRT65ZGN82\",\n        \"merchant_reference\": \"ORDER-10231\",\n        \"transaction_type\": \"capture\",\n        \"success\": true,\n        \"amount\": {\n            \"value\": 249900,\n            \"currency\": \"HUF\"\n        },\n        \"payment_method\": \"visa\",\n        \"reason\": null,\n        \"event_date\": \"2026-09-09T14:31:01+02:00\",\n        \"shopper_email\": \"vevo@example.com\",\n        \"store\": \"ST322LJ223223K5FQ4NM3JWLK\"\n    }\n}",
                    "options": {
                        "raw": {
                            "language": "json"
                        }
                    }
                },
                "url": {
                    "raw": "{{merchant_endpoint_url}}",
                    "host": [
                        "{{merchant_endpoint_url}}"
                    ]
                },
                "description": "Paynance sends this on a `payment.captured` event. The signature is calculated by the collection's pre-request script."
            },
            "response": []
        },
        {
            "name": "payment.cancelled",
            "event": [
                {
                    "listen": "test",
                    "script": {
                        "type": "text/javascript",
                        "exec": [
                            "pm.test('The endpoint returns 2xx', function () {",
                            "    pm.expect(pm.response.code).to.be.within(200, 299);",
                            "});",
                            "",
                            "pm.test('The response arrived within 5 seconds', function () {",
                            "    pm.expect(pm.response.responseTime).to.be.below(5000);",
                            "});"
                        ]
                    }
                }
            ],
            "request": {
                "method": "POST",
                "header": [
                    {
                        "key": "Content-Type",
                        "value": "application/json"
                    }
                ],
                "body": {
                    "mode": "raw",
                    "raw": "{\n    \"version\": 1,\n    \"event_id\": \"0192f1b4-9a20-7f08-8c33-2d5a7e91b402\",\n    \"event_type\": \"payment.cancelled\",\n    \"created_at\": \"2026-09-09T15:02:20+00:00\",\n    \"data\": {\n        \"psp_reference\": \"WW90KL22ZZ41MM08\",\n        \"original_psp_reference\": \"NC6HT9CRT65ZGN82\",\n        \"merchant_reference\": \"ORDER-10231\",\n        \"transaction_type\": \"cancellation\",\n        \"success\": true,\n        \"amount\": {\n            \"value\": 249900,\n            \"currency\": \"HUF\"\n        },\n        \"payment_method\": \"visa\",\n        \"reason\": null,\n        \"event_date\": \"2026-09-09T15:02:19+02:00\",\n        \"shopper_email\": \"vevo@example.com\",\n        \"store\": \"ST322LJ223223K5FQ4NM3JWLK\"\n    }\n}",
                    "options": {
                        "raw": {
                            "language": "json"
                        }
                    }
                },
                "url": {
                    "raw": "{{merchant_endpoint_url}}",
                    "host": [
                        "{{merchant_endpoint_url}}"
                    ]
                },
                "description": "Paynance sends this on a `payment.cancelled` event. The signature is calculated by the collection's pre-request script."
            },
            "response": []
        },
        {
            "name": "payment.refunded",
            "event": [
                {
                    "listen": "test",
                    "script": {
                        "type": "text/javascript",
                        "exec": [
                            "pm.test('The endpoint returns 2xx', function () {",
                            "    pm.expect(pm.response.code).to.be.within(200, 299);",
                            "});",
                            "",
                            "pm.test('The response arrived within 5 seconds', function () {",
                            "    pm.expect(pm.response.responseTime).to.be.below(5000);",
                            "});"
                        ]
                    }
                }
            ],
            "request": {
                "method": "POST",
                "header": [
                    {
                        "key": "Content-Type",
                        "value": "application/json"
                    }
                ],
                "body": {
                    "mode": "raw",
                    "raw": "{\n    \"version\": 1,\n    \"event_id\": \"0192f2c1-51ab-7d90-9e77-4b8c0a2f6611\",\n    \"event_type\": \"payment.refunded\",\n    \"created_at\": \"2026-09-10T09:18:40+00:00\",\n    \"data\": {\n        \"psp_reference\": \"RF77TT01YY93QQ12\",\n        \"original_psp_reference\": \"NC6HT9CRT65ZGN82\",\n        \"merchant_reference\": \"ORDER-10231\",\n        \"transaction_type\": \"refund\",\n        \"success\": true,\n        \"amount\": {\n            \"value\": 100000,\n            \"currency\": \"HUF\"\n        },\n        \"payment_method\": \"visa\",\n        \"reason\": null,\n        \"event_date\": \"2026-09-10T09:18:39+02:00\",\n        \"shopper_email\": \"vevo@example.com\",\n        \"store\": \"ST322LJ223223K5FQ4NM3JWLK\"\n    }\n}",
                    "options": {
                        "raw": {
                            "language": "json"
                        }
                    }
                },
                "url": {
                    "raw": "{{merchant_endpoint_url}}",
                    "host": [
                        "{{merchant_endpoint_url}}"
                    ]
                },
                "description": "Paynance sends this on a `payment.refunded` event. The signature is calculated by the collection's pre-request script."
            },
            "response": []
        },
        {
            "name": "payment.chargeback",
            "event": [
                {
                    "listen": "test",
                    "script": {
                        "type": "text/javascript",
                        "exec": [
                            "pm.test('The endpoint returns 2xx', function () {",
                            "    pm.expect(pm.response.code).to.be.within(200, 299);",
                            "});",
                            "",
                            "pm.test('The response arrived within 5 seconds', function () {",
                            "    pm.expect(pm.response.responseTime).to.be.below(5000);",
                            "});"
                        ]
                    }
                }
            ],
            "request": {
                "method": "POST",
                "header": [
                    {
                        "key": "Content-Type",
                        "value": "application/json"
                    }
                ],
                "body": {
                    "mode": "raw",
                    "raw": "{\n    \"version\": 1,\n    \"event_id\": \"0192f9d4-c8e1-7b33-a5f2-90ab13cd4477\",\n    \"event_type\": \"payment.chargeback\",\n    \"created_at\": \"2026-09-21T06:45:03+00:00\",\n    \"data\": {\n        \"psp_reference\": \"CB55QQ88WW22EE31\",\n        \"original_psp_reference\": \"NC6HT9CRT65ZGN82\",\n        \"merchant_reference\": \"ORDER-10231\",\n        \"transaction_type\": \"chargeback\",\n        \"success\": true,\n        \"amount\": {\n            \"value\": 249900,\n            \"currency\": \"HUF\"\n        },\n        \"payment_method\": \"visa\",\n        \"reason\": \"Fraud\",\n        \"event_date\": \"2026-09-21T06:45:02+02:00\",\n        \"shopper_email\": \"vevo@example.com\",\n        \"store\": \"ST322LJ223223K5FQ4NM3JWLK\"\n    }\n}",
                    "options": {
                        "raw": {
                            "language": "json"
                        }
                    }
                },
                "url": {
                    "raw": "{{merchant_endpoint_url}}",
                    "host": [
                        "{{merchant_endpoint_url}}"
                    ]
                },
                "description": "Paynance sends this on a `payment.chargeback` event. The signature is calculated by the collection's pre-request script."
            },
            "response": []
        },
        {
            "name": "test",
            "event": [
                {
                    "listen": "test",
                    "script": {
                        "type": "text/javascript",
                        "exec": [
                            "pm.test('The endpoint returns 2xx', function () {",
                            "    pm.expect(pm.response.code).to.be.within(200, 299);",
                            "});",
                            "",
                            "pm.test('The response arrived within 5 seconds', function () {",
                            "    pm.expect(pm.response.responseTime).to.be.below(5000);",
                            "});"
                        ]
                    }
                }
            ],
            "request": {
                "method": "POST",
                "header": [
                    {
                        "key": "Content-Type",
                        "value": "application/json"
                    }
                ],
                "body": {
                    "mode": "raw",
                    "raw": "{\n    \"version\": 1,\n    \"event_id\": \"0192f1a0-1111-7222-8333-444455556666\",\n    \"event_type\": \"test\",\n    \"created_at\": \"2026-09-09T11:59:00+00:00\",\n    \"data\": {\n        \"transaction_type\": \"test\",\n        \"store\": \"ST322LJ223223K5FQ4NM3JWLK\",\n        \"message\": \"This is a test event from Paynance. No payment is associated with it.\"\n    }\n}",
                    "options": {
                        "raw": {
                            "language": "json"
                        }
                    }
                },
                "url": {
                    "raw": "{{merchant_endpoint_url}}",
                    "host": [
                        "{{merchant_endpoint_url}}"
                    ]
                },
                "description": "Paynance sends this on a `test` event. The signature is calculated by the collection's pre-request script."
            },
            "response": []
        },
        {
            "name": "invalid signature → 4xx expected",
            "event": [
                {
                    "listen": "prerequest",
                    "script": {
                        "type": "text/javascript",
                        "exec": [
                            "// Deliberately wrong signature: the correct answer is 4xx.",
                            "pm.request.headers.upsert({ key: 'Paynance-Signature', value: 'deadbeef' });"
                        ]
                    }
                },
                {
                    "listen": "test",
                    "script": {
                        "type": "text/javascript",
                        "exec": [
                            "pm.test('A signature failure answers 4xx, not 2xx', function () {",
                            "    pm.expect(pm.response.code).to.be.within(400, 499);",
                            "});",
                            "",
                            "// On 2xx the delivery would be lost for good: on our side it would look successful.",
                            "pm.test('Not 2xx', function () {",
                            "    pm.expect(pm.response.code).to.not.be.within(200, 299);",
                            "});"
                        ]
                    }
                }
            ],
            "request": {
                "method": "POST",
                "header": [
                    {
                        "key": "Content-Type",
                        "value": "application/json"
                    }
                ],
                "body": {
                    "mode": "raw",
                    "raw": "{\n    \"version\": 1,\n    \"event_id\": \"0192f1a2-3b4c-7d5e-8f60-1a2b3c4d5e6f\",\n    \"event_type\": \"payment.authorised\",\n    \"created_at\": \"2026-09-09T12:04:12+00:00\",\n    \"data\": {\n        \"psp_reference\": \"NC6HT9CRT65ZGN82\",\n        \"original_psp_reference\": null,\n        \"merchant_reference\": \"ORDER-10231\",\n        \"transaction_type\": \"payment\",\n        \"success\": true,\n        \"amount\": {\n            \"value\": 249900,\n            \"currency\": \"HUF\"\n        },\n        \"payment_method\": \"visa\",\n        \"reason\": null,\n        \"event_date\": \"2026-09-09T12:04:11+02:00\",\n        \"shopper_email\": \"vevo@example.com\",\n        \"store\": \"ST322LJ223223K5FQ4NM3JWLK\"\n    }\n}",
                    "options": {
                        "raw": {
                            "language": "json"
                        }
                    }
                },
                "url": {
                    "raw": "{{merchant_endpoint_url}}",
                    "host": [
                        "{{merchant_endpoint_url}}"
                    ]
                },
                "description": "The negative case of signature verification. We retry on 4xx and not on 2xx — so with a 2xx the event is lost for good."
            },
            "response": []
        }
    ]
}
