import { test, expect } from '../fixtures'; test.describe('POST /payments/callback/:provider — Payment webhooks', () => { test.describe('VNPay callback', () => { test('handles VNPay callback with query params', async ({ request }) => { const res = await request.post('payments/callback/vnpay', { params: { vnp_TxnRef: 'TEST_TXN_001', vnp_ResponseCode: '00', vnp_Amount: '50000000', // VNPay uses x100 vnp_TransactionNo: '14000000', vnp_SecureHash: 'invalid_hash_for_test', }, }); // Callback endpoint should not crash — expect a handled response // May return 200 (processed) or 400 (invalid hash) but never 500 expect(res.status()).toBeLessThan(500); }); test('handles VNPay callback with failed transaction code', async ({ request }) => { const res = await request.post('payments/callback/vnpay', { params: { vnp_TxnRef: 'TEST_TXN_002', vnp_ResponseCode: '24', // Customer cancelled vnp_Amount: '50000000', vnp_TransactionNo: '0', vnp_SecureHash: 'invalid_hash_for_test', }, }); expect(res.status()).toBeLessThan(500); }); }); test.describe('MoMo callback', () => { test('handles MoMo callback with body payload', async ({ request }) => { const res = await request.post('payments/callback/momo', { data: { orderId: 'TEST_ORDER_001', resultCode: 0, amount: 500000, transId: 'MOMO_TXN_001', signature: 'invalid_signature_for_test', }, }); expect(res.status()).toBeLessThan(500); }); }); test.describe('ZaloPay callback', () => { test('handles ZaloPay callback with body payload', async ({ request }) => { const res = await request.post('payments/callback/zalopay', { data: { data: '{"app_trans_id":"TEST_001","amount":500000}', mac: 'invalid_mac_for_test', type: 1, }, }); expect(res.status()).toBeLessThan(500); }); }); test.describe('Invalid provider', () => { test('rejects callback for unknown provider', async ({ request }) => { const res = await request.post('payments/callback/unknown_provider', { data: { txn: 'test' }, }); expect(res.ok()).toBeFalsy(); expect([400, 404, 500]).toContain(res.status()); }); }); });