{
  "info": {
    "_postman_id": "745ad2fe-26c5-4bff-b6f1-5d6531b531ea",
    "name": "Developer Pay2S",
    "description": "Configure the supplied blank Environment before use. Credentials are read from Environment. Run individual requests; Cancel and Publish change state. HĐĐT samples enforce sandbox. Documentation: https://docs.pay2s.vn/others/postman.html",
    "schema": "https://schema.getpostman.com/json/collection/v2.1.0/collection.json"
  },
  "item": [
    {
      "name": "Order API",
      "item": [
        {
          "name": "Collection Link Create Order",
          "item": [
            {
              "name": "Create",
              "event": [
                {
                  "listen": "prerequest",
                  "script": {
                    "type": "text/javascript",
                    "exec": [
                      "const get = name => pm.environment.get(name);",
                      "const need = name => { const v = get(name); if (v === undefined || v === null || v === '') throw new Error('Set Environment: ' + name); return v; };",
                      "const CryptoJS = pm.require(\"npm:crypto-js@4.2.0\");\r",
                      "\r",
                      "const accessKey = need('accessKey');\r",
                      "const partnerCode = need('partnerCode');\r",
                      "const secretKey = need('secretKey');\r",
                      "\r",
                      "if (!accessKey || !partnerCode || !secretKey) {\r",
                      "    throw new Error(\r",
                      "        \"Cần cấu hình accessKey, partnerCode và secretKey trong Environment\"\r",
                      "    );\r",
                      "}\r",
                      "\r",
                      "const partnerName = \"DEMO\";\r",
                      "const requestId = Date.now().toString();\r",
                      "const orderId = `ORDER-${requestId}`;\r",
                      "const amount = String(need('amount'));\r",
                      "const orderInfo = requestId;\r",
                      "const requestType = \"pay2s\";\r",
                      "\r",
                      "const redirectUrl = need('redirectUrl');\r",
                      "const ipnUrl = need('ipnUrl');\r",
                      "\r",
                      "// Thay bằng tài khoản đã liên kết khi chạy thử thực tế.\r",
                      "const bankAccounts = [\r",
                      "    {\r",
                      "        account_number: String(need('account_number')).replace(/\\s/g, ''),\r",
                      "        bank_id: need('bankCode')\r",
                      "    }\r",
                      "];\r",
                      "\r",
                      "const metadata = {\r",
                      "    invoiceType: \"vat\",\r",
                      "\r",
                      "    customerInfo: {\r",
                      "        buyerContactName: \"NGUYỄN VĂN A\",\r",
                      "        buyerCompanyName: \"CÔNG TY DEMO\",\r",
                      "        taxCode: \"\",\r",
                      "        citizenId: \"\",\r",
                      "        address: \"Địa chỉ khách hàng mẫu\",\r",
                      "        email: \"customer@example.com\",\r",
                      "        phone: \"\"\r",
                      "    },\r",
                      "\r",
                      "    items: [\r",
                      "        {\r",
                      "            itemCode: \"DV001\",\r",
                      "            itemName: \"Dịch vụ mẫu 1\",\r",
                      "            unit: \"Tháng\",\r",
                      "            quantity: 1,\r",
                      "            unitPrice: 1000,\r",
                      "            taxRate: 10\r",
                      "        },\r",
                      "        {\r",
                      "            itemCode: \"DV002\",\r",
                      "            itemName: \"Dịch vụ mẫu 2\",\r",
                      "            unit: \"Tháng\",\r",
                      "            quantity: 1,\r",
                      "            unitPrice: 1000,\r",
                      "            taxRate: 10\r",
                      "        }\r",
                      "    ],\r",
                      "\r",
                      "    invoiceOptions: {\r",
                      "        requested: true,\r",
                      "        buyerNotTakingInvoice: false,\r",
                      "        paymentMethod: \"Chuyển khoản\",\r",
                      "        note: \"\"\r",
                      "    }\r",
                      "};\r",
                      "\r",
                      "const extraData = CryptoJS.enc.Base64.stringify(\r",
                      "    CryptoJS.enc.Utf8.parse(JSON.stringify(metadata))\r",
                      ");\r",
                      "\r",
                      "const rawSignature =\r",
                      "    `accessKey=${accessKey}` +\r",
                      "    `&amount=${amount}` +\r",
                      "    `&bankAccounts=Array` +\r",
                      "    `&extraData=${extraData}` +\r",
                      "    `&ipnUrl=${ipnUrl}` +\r",
                      "    `&orderId=${orderId}` +\r",
                      "    `&orderInfo=${orderInfo}` +\r",
                      "    `&partnerCode=${partnerCode}` +\r",
                      "    `&redirectUrl=${redirectUrl}` +\r",
                      "    `&requestId=${requestId}` +\r",
                      "    `&requestType=${requestType}` +\r",
                      "    `&signatureVersion=2`;\r",
                      "\r",
                      "const signature = CryptoJS\r",
                      "    .HmacSHA256(rawSignature, secretKey)\r",
                      "    .toString(CryptoJS.enc.Hex);\r",
                      "\r",
                      "const payload = {\r",
                      "    accessKey,\r",
                      "    partnerCode,\r",
                      "    partnerName,\r",
                      "    requestId,\r",
                      "    amount,\r",
                      "    orderId,\r",
                      "    orderInfo,\r",
                      "    orderType: requestType,\r",
                      "    bankAccounts,\r",
                      "    redirectUrl,\r",
                      "    ipnUrl,\r",
                      "    requestType,\r",
                      "    signatureVersion: \"2\",\r",
                      "    extraData,\r",
                      "    signature\r",
                      "};\r",
                      "\r",
                      "pm.request.body.update(JSON.stringify(payload));\r",
                      "\r",
                      "console.log(\"Đã tạo request:\", { requestId, orderId, amount });",
                      "pm.request.headers.upsert({key:\"Content-Type\",value:\"application/json\"});",
                      "for (const key of [\"orderId\",\"requestId\",\"amount\",\"orderInfo\",\"extraData\"]) pm.environment.set(key, payload[key]);"
                    ]
                  }
                },
                {
                  "listen": "test",
                  "script": {
                    "type": "text/javascript",
                    "exec": [
                      "if (pm.response.code >= 200 && pm.response.code < 300) {",
                      " const r = pm.response.json();",
                      " if (r.orderInfo) pm.environment.set('orderInfo', r.orderInfo);",
                      " if (r.payUrl) pm.environment.set('payUrl', r.payUrl);",
                      "}"
                    ]
                  }
                }
              ],
              "request": {
                "method": "POST",
                "header": [
                  {
                    "key": "Content-Type",
                    "value": "application/json"
                  }
                ],
                "body": {
                  "mode": "raw",
                  "raw": "{}",
                  "options": {
                    "raw": {
                      "language": "json"
                    }
                  }
                },
                "url": "https://payment.pay2s.vn/v1/gateway/api/create",
                "description": "Collection Link V2. Configure Environment and edit metadata/items in Pre-request before sending. Saves orderId for Cancel; each Send creates a new order."
              },
              "response": []
            }
          ]
        },
        {
          "name": "Simulate Demo Payment",
          "item": [
            {
              "name": "Simulate Payment",
              "request": {
                "method": "POST",
                "url": "https://payment.pay2s.vn/v1/gateway/api/simulate-payment",
                "header": [
                  {
                    "key": "Content-Type",
                    "value": "application/json"
                  }
                ],
                "body": {
                  "mode": "raw",
                  "raw": "{}",
                  "options": {
                    "raw": {
                      "language": "json"
                    }
                  }
                },
                "description": "Bearer Secret Key of demo account; no request HMAC. No real transfer. Simulate once; regular retry does not requeue IPN.",
                "auth": {
                  "type": "noauth"
                }
              },
              "event": [
                {
                  "listen": "prerequest",
                  "script": {
                    "type": "text/javascript",
                    "exec": [
                      "const secretKey = pm.environment.get('secretKey');",
                      "const orderId = pm.environment.get('orderId');",
                      "if (!secretKey || !orderId) throw new Error('Set Environment: secretKey and orderId');",
                      "pm.request.headers.upsert({key:'Authorization',value:'Bearer '+secretKey});",
                      "pm.request.headers.upsert({key:'Content-Type',value:'application/json'});",
                      "pm.request.body.update(JSON.stringify({orderId:String(orderId),resendIpn:false}));"
                    ]
                  }
                }
              ]
            },
            {
              "name": "Resend Demo IPN",
              "request": {
                "method": "POST",
                "url": "https://payment.pay2s.vn/v1/gateway/api/simulate-payment",
                "header": [
                  {
                    "key": "Content-Type",
                    "value": "application/json"
                  }
                ],
                "body": {
                  "mode": "raw",
                  "raw": "{}",
                  "options": {
                    "raw": {
                      "language": "json"
                    }
                  }
                },
                "description": "Bearer Secret Key of demo account; no request HMAC. No real transfer. Explicitly requeue demo IPN without another transaction.",
                "auth": {
                  "type": "noauth"
                }
              },
              "event": [
                {
                  "listen": "prerequest",
                  "script": {
                    "type": "text/javascript",
                    "exec": [
                      "const secretKey = pm.environment.get('secretKey');",
                      "const orderId = pm.environment.get('orderId');",
                      "if (!secretKey || !orderId) throw new Error('Set Environment: secretKey and orderId');",
                      "pm.request.headers.upsert({key:'Authorization',value:'Bearer '+secretKey});",
                      "pm.request.headers.upsert({key:'Content-Type',value:'application/json'});",
                      "pm.request.body.update(JSON.stringify({orderId:String(orderId),resendIpn:true}));"
                    ]
                  }
                }
              ]
            }
          ]
        },
        {
          "name": "Cancel Order",
          "item": [
            {
              "name": "Cancel",
              "event": [
                {
                  "listen": "prerequest",
                  "script": {
                    "type": "text/javascript",
                    "exec": [
                      "const CryptoJS = pm.require('npm:crypto-js@4.2.0');",
                      "const get = name => pm.environment.get(name);",
                      "const need = name => { const v = get(name); if (v === undefined || v === null || v === '') throw new Error('Set Environment: ' + name); return v; };",
                      "",
                      "const accessKey=need('accessKey'), partnerCode=need('partnerCode'), secretKey=need('secretKey'), orderId=String(need('orderId'));",
                      "const requestId='CANCEL-'+Date.now(), requestType='cancel';",
                      "const raw='accessKey='+accessKey+'&orderId='+orderId+'&partnerCode='+partnerCode+'&requestId='+requestId+'&requestType=cancel';",
                      "const signature=CryptoJS.HmacSHA256(raw,secretKey).toString(CryptoJS.enc.Hex);",
                      "pm.request.body.update(JSON.stringify({accessKey,partnerCode,orderId,requestId,requestType,signature}));",
                      "pm.request.headers.upsert({key:'Content-Type',value:'application/json'});"
                    ]
                  }
                },
                {
                  "listen": "test",
                  "script": {
                    "exec": [
                      ""
                    ],
                    "type": "text/javascript",
                    "packages": {},
                    "requests": {}
                  }
                }
              ],
              "request": {
                "method": "POST",
                "header": [
                  {
                    "key": "Content-Type",
                    "value": "application/json"
                  }
                ],
                "body": {
                  "mode": "raw",
                  "raw": "{}",
                  "options": {
                    "raw": {
                      "language": "json"
                    }
                  }
                },
                "url": "https://payment.pay2s.vn/v1/gateway/api/cancel"
              },
              "response": []
            }
          ]
        },
        {
          "name": "Payment Notification (Return URL)",
          "item": [
            {
              "name": "Payment Notification",
              "event": [
                {
                  "listen": "prerequest",
                  "script": {
                    "type": "text/javascript",
                    "exec": [
                      "const CryptoJS = pm.require('npm:crypto-js@4.2.0');",
                      "const get = name => pm.environment.get(name);",
                      "const need = name => { const v = get(name); if (v === undefined || v === null || v === '') throw new Error('Set Environment: ' + name); return v; };",
                      "",
                      "const accessKey=need('accessKey'), secretKey=need('secretKey');",
                      "const payload={};",
                      "for(const key of ['partnerCode','orderId','requestId','amount','orderInfo','orderType','transId','resultCode','message','payType']) payload[key]=String(need(key));",
                      "payload.extraData=String(get('extraData') || '');",
                      "payload.responseTime=String(Date.now());",
                      "const fields=['amount','extraData','message','orderId','orderInfo','orderType','partnerCode','payType','requestId','responseTime','resultCode','transId'];",
                      "const raw='accessKey='+accessKey+fields.map(k=>'&'+k+'='+payload[k]).join('');",
                      "payload.m2signature=CryptoJS.HmacSHA256(raw,secretKey).toString(CryptoJS.enc.Hex);",
                      "const target=need('redirectUrl');",
                      "const query=Object.entries(payload).map(([k,v])=>encodeURIComponent(k)+'='+encodeURIComponent(v)).join('&');",
                      "pm.request.url.update(target+(target.includes('?')?'&':'?')+query);"
                    ]
                  }
                }
              ],
              "protocolProfileBehavior": {
                "disableBodyPruning": true
              },
              "request": {
                "method": "GET",
                "header": [],
                "url": "{{redirectUrl}}",
                "description": "Simulation sent to your own endpoint. Does not confirm a real bank payment. Verify against the current IPN contract."
              },
              "response": []
            }
          ]
        },
        {
          "name": "Instant Payment Notification (IPN)",
          "item": [
            {
              "name": "Instant Payment Notification",
              "event": [
                {
                  "listen": "prerequest",
                  "script": {
                    "type": "text/javascript",
                    "exec": [
                      "const CryptoJS = pm.require('npm:crypto-js@4.2.0');",
                      "const get = name => pm.environment.get(name);",
                      "const need = name => { const v = get(name); if (v === undefined || v === null || v === '') throw new Error('Set Environment: ' + name); return v; };",
                      "",
                      "const accessKey=need('accessKey'), secretKey=need('secretKey');",
                      "const payload={};",
                      "for(const key of ['partnerCode','orderId','requestId','amount','orderInfo','orderType','transId','resultCode','message','payType']) payload[key]=String(need(key));",
                      "payload.extraData=String(get('extraData') || '');",
                      "payload.responseTime=String(Date.now());",
                      "const fields=['amount','extraData','message','orderId','orderInfo','orderType','partnerCode','payType','requestId','responseTime','resultCode','transId'];",
                      "const raw='accessKey='+accessKey+fields.map(k=>'&'+k+'='+payload[k]).join('');",
                      "payload.m2signature=CryptoJS.HmacSHA256(raw,secretKey).toString(CryptoJS.enc.Hex);",
                      "pm.request.body.update(JSON.stringify(payload));",
                      "pm.request.headers.upsert({key:'Content-Type',value:'application/json'});"
                    ]
                  }
                }
              ],
              "request": {
                "method": "POST",
                "header": [
                  {
                    "key": "Content-Type",
                    "value": "application/json"
                  }
                ],
                "body": {
                  "mode": "raw",
                  "raw": "{}",
                  "options": {
                    "raw": {
                      "language": "json"
                    }
                  }
                },
                "url": "{{ipnUrl}}",
                "description": "Simulation sent to your own endpoint. Does not confirm a real bank payment. Verify against the current IPN contract."
              },
              "response": []
            }
          ]
        }
      ]
    },
    {
      "name": "Transactions",
      "item": [
        {
          "name": "Transactions",
          "event": [
            {
              "listen": "prerequest",
              "script": {
                "type": "text/javascript",
                "exec": [
                  "const CryptoJS = pm.require('npm:crypto-js@4.2.0');",
                  "const get = name => pm.environment.get(name);",
                  "const need = name => { const v = get(name); if (v === undefined || v === null || v === '') throw new Error('Set Environment: ' + name); return v; };",
                  "const secretKey=need('secretKey');",
                  "pm.variables.set('pay2sToken',CryptoJS.enc.Base64.stringify(CryptoJS.enc.Utf8.parse(secretKey)));"
                ]
              }
            }
          ],
          "request": {
            "method": "POST",
            "header": [
              {
                "key": "pay2s-token",
                "value": "{{pay2sToken}}",
                "type": "text"
              },
              {
                "key": "Content-Type",
                "value": "application/json"
              }
            ],
            "body": {
              "mode": "raw",
              "raw": "{\r\n  \"bankAccounts\": \"{{account_number}}\",\r\n  \"begin\": \"{{begin}}\",\r\n  \"end\": \"{{end}}\"\r\n}",
              "options": {
                "raw": {
                  "language": "json"
                }
              }
            },
            "url": "https://api.pay2s.vn/userapi/transactions"
          },
          "response": []
        }
      ]
    },
    {
      "name": "Recipient Name",
      "item": [
        {
          "name": "Recipient Name Lookup",
          "event": [
            {
              "listen": "prerequest",
              "script": {
                "type": "text/javascript",
                "exec": [
                  "const CryptoJS = pm.require('npm:crypto-js@4.2.0');",
                  "const get = name => pm.environment.get(name);",
                  "const need = name => { const v = get(name); if (v === undefined || v === null || v === '') throw new Error('Set Environment: ' + name); return v; };",
                  "const secretKey=need('secretKey');",
                  "pm.variables.set('pay2sToken',CryptoJS.enc.Base64.stringify(CryptoJS.enc.Utf8.parse(secretKey)));"
                ]
              }
            }
          ],
          "request": {
            "method": "POST",
            "header": [
              {
                "key": "pay2s-token",
                "value": "{{pay2sToken}}",
                "type": "text"
              },
              {
                "key": "Content-Type",
                "value": "application/json"
              }
            ],
            "body": {
              "mode": "raw",
              "raw": "{\r\n  \"accountNumber\": \"{{account_number}}\",\r\n  \"bankCode\": \"{{bankCode}}\"\r\n}",
              "options": {
                "raw": {
                  "language": "json"
                }
              }
            },
            "url": "https://api.pay2s.vn/userapi/get-recipient-name"
          },
          "response": []
        }
      ]
    },
    {
      "name": "Tax Lookup",
      "item": [
        {
          "name": "Tax Code Lookup",
          "event": [
            {
              "listen": "prerequest",
              "script": {
                "type": "text/javascript",
                "exec": [
                  "const CryptoJS = pm.require('npm:crypto-js@4.2.0');",
                  "const get = name => pm.environment.get(name);",
                  "const need = name => { const v = get(name); if (v === undefined || v === null || v === '') throw new Error('Set Environment: ' + name); return v; };",
                  "const secretKey=need('secretKey');",
                  "pm.variables.set('pay2sToken',CryptoJS.enc.Base64.stringify(CryptoJS.enc.Utf8.parse(secretKey)));"
                ]
              }
            }
          ],
          "request": {
            "method": "GET",
            "header": [
              {
                "key": "pay2s-token",
                "value": "{{pay2sToken}}",
                "type": "text"
              }
            ],
            "url": "https://api.pay2s.vn/userapi/tax-lookup?mst={{taxCode}}"
          },
          "response": []
        }
      ]
    },
    {
      "name": "Webhooks",
      "item": [
        {
          "name": "webhook",
          "request": {
            "auth": {
              "type": "bearer",
              "bearer": [
                {
                  "key": "token",
                  "value": "{{token}}",
                  "type": "string"
                }
              ]
            },
            "method": "POST",
            "header": [
              {
                "key": "Content-Type",
                "value": "application/json"
              }
            ],
            "body": {
              "mode": "raw",
              "raw": "{\r\n  \"transactions\": [\r\n    {\r\n      \"id\": \"1788052\",\r\n      \"gateway\": \"ACB\",\r\n      \"transactionDate\": \"2025-04-01 00:02:18\",\r\n      \"transactionNumber\": \"10418\",\r\n      \"accountNumber\": \"12805521\",\r\n      \"content\": \"SHOPVPS12537 GD 789604-040125 00:05:38\",\r\n      \"transferType\": \"IN\",\r\n      \"transferAmount\": 50000,\r\n      \"checksum\": \"7e2b3bbc03d1083017e3d2a96d3b8e01\"\r\n    }\r\n  ]\r\n}",
              "options": {
                "raw": {
                  "language": "json"
                }
              }
            },
            "url": "{{endpoint}}",
            "description": "Example payload only. Target your own endpoint and adapt checksum validation to your webhook configuration."
          },
          "response": []
        }
      ]
    },
    {
      "name": "QR Payment",
      "item": [
        {
          "name": "OneQR (Dynamic QR)",
          "item": [
            {
              "name": "Authentication",
              "item": [
                {
                  "name": "Authentication",
                  "event": [
                    {
                      "listen": "test",
                      "script": {
                        "type": "text/javascript",
                        "exec": [
                          "if(pm.response.code===200){const r=pm.response.json();if(r.data && r.data.access_token) pm.environment.set('oneqrToken',r.data.access_token);}"
                        ]
                      }
                    }
                  ],
                  "request": {
                    "auth": {
                      "type": "basic",
                      "basic": [
                        {
                          "key": "password",
                          "value": "{{secretKey}}",
                          "type": "string"
                        },
                        {
                          "key": "username",
                          "value": "{{accessKey}}",
                          "type": "string"
                        }
                      ]
                    },
                    "method": "POST",
                    "header": [
                      {
                        "key": "Content-Type",
                        "value": "application/json"
                      }
                    ],
                    "url": "https://api.pay2s.vn/api/auth/token",
                    "description": "Get OneQR access token using the same accessKey/secretKey."
                  },
                  "response": []
                }
              ]
            },
            {
              "name": "02 - QR flow",
              "item": [
                {
                  "name": "Create OneQR",
                  "event": [
                    {
                      "listen": "test",
                      "script": {
                        "type": "text/javascript",
                        "exec": [
                          "if(pm.response.code>=200 && pm.response.code<300){const r=pm.response.json();const d=r.data||{};for(const key of ['traceNumber','transactionId'])if(d[key])pm.environment.set(key,d[key]);}"
                        ]
                      }
                    }
                  ],
                  "request": {
                    "method": "POST",
                    "header": [
                      {
                        "key": "Content-Type",
                        "value": "application/json"
                      }
                    ],
                    "body": {
                      "mode": "raw",
                      "raw": "{\r\n    \"orderId\": \"{{orderId}}\",\r\n    \"amount\": {{amount}},\r\n    \"merchantName\" : \"{{merchantName}}\",\r\n    \"merchantId\": \"{{MID}}\",\r\n    \"terminalId\": \"{{TID}}\",\r\n    \"description\": \"{{description}}\",\r\n    \"template\": \"frame\",\r\n    \"maskAccount\" : true,\r\n    \"frameId\": 1\r\n}",
                      "options": {
                        "raw": {
                          "language": "json"
                        }
                      }
                    },
                    "url": "https://api.pay2s.vn/api/{{bankShortName}}/v1/qr/create",
                    "description": "Creates a QR payment request and stores the traceNumber and virtualAccount in the environment."
                  },
                  "response": []
                },
                {
                  "name": "Cancel QR",
                  "event": [
                    {
                      "listen": "test",
                      "script": {
                        "exec": [
                          ""
                        ],
                        "type": "text/javascript",
                        "packages": {},
                        "requests": {}
                      }
                    }
                  ],
                  "request": {
                    "method": "POST",
                    "header": [
                      {
                        "key": "Content-Type",
                        "value": "application/json"
                      }
                    ],
                    "body": {
                      "mode": "raw",
                      "raw": "{\r\n    \"orderId\": \"{{orderId}}\",\r\n    \"traceNumber\": \"{{traceNumber}}\"\r\n  }",
                      "options": {
                        "raw": {
                          "language": "json"
                        }
                      }
                    },
                    "url": "https://api.pay2s.vn/api/vcb/v1/qr/cancel",
                    "description": "Cancel OneQR using orderId and traceNumber from its create response."
                  },
                  "response": []
                },
                {
                  "name": "List QR",
                  "event": [
                    {
                      "listen": "test",
                      "script": {
                        "exec": [
                          ""
                        ],
                        "type": "text/javascript",
                        "packages": {},
                        "requests": {}
                      }
                    }
                  ],
                  "request": {
                    "method": "GET",
                    "header": [
                      {
                        "key": "Content-Type",
                        "value": "application/json"
                      }
                    ],
                    "url": "https://api.pay2s.vn/api/vcb/v1/qr/list?limit={{limit}}&offset={{offset}}",
                    "description": "List OneQR requests."
                  },
                  "response": []
                },
                {
                  "name": "Retrieve QR transactions",
                  "event": [
                    {
                      "listen": "prerequest",
                      "script": {
                        "exec": [
                          ""
                        ],
                        "type": "text/javascript",
                        "packages": {},
                        "requests": {}
                      }
                    }
                  ],
                  "request": {
                    "method": "GET",
                    "header": [],
                    "url": "https://api.pay2s.vn/api/{{bankShortName}}/v1/qr/transactions/{{transactionId}}",
                    "description": "Queries QR transactions through the backend. If from_date/to_date are empty, a 7-day window is set automatically."
                  },
                  "response": []
                }
              ],
              "auth": {
                "type": "bearer",
                "bearer": [
                  {
                    "key": "token",
                    "value": "{{oneqrToken}}",
                    "type": "string"
                  }
                ]
              },
              "event": [
                {
                  "listen": "prerequest",
                  "script": {
                    "type": "text/javascript",
                    "packages": {},
                    "requests": {},
                    "exec": [
                      ""
                    ]
                  }
                },
                {
                  "listen": "test",
                  "script": {
                    "type": "text/javascript",
                    "packages": {},
                    "requests": {},
                    "exec": [
                      ""
                    ]
                  }
                }
              ]
            }
          ]
        },
        {
          "name": "VietQR (Static QR)",
          "item": [
            {
              "name": "VietQR",
              "request": {
                "method": "POST",
                "header": [
                  {
                    "key": "Content-Type",
                    "value": "application/json"
                  }
                ],
                "body": {
                  "mode": "raw",
                  "raw": "{\r\n    \"accountNo\": \"{{account_number}}\",\r\n    \"accountName\": \"{{account_name}}\",\r\n    \"bankCode\": \"{{bankShortName}}\",\r\n    \"addInfo\": \"{{content}}\",\r\n    \"amount\": {{amount}},\r\n    \"template\": \"modern\",\r\n    \"maskAccount\": true\r\n}",
                  "options": {
                    "raw": {
                      "language": "json"
                    }
                  }
                },
                "url": "https://api.pay2s.vn/vietqr/generate"
              },
              "response": []
            }
          ]
        }
      ]
    },
    {
      "name": "API HDDT",
      "item": [
        {
          "name": "01 - Sandbox connections",
          "request": {
            "method": "POST",
            "header": [
              {
                "key": "Content-Type",
                "value": "application/json"
              }
            ],
            "body": {
              "mode": "raw",
              "raw": "{\n  \"action\": \"connections\"\n}",
              "options": {
                "raw": {
                  "language": "json"
                }
              }
            },
            "url": "https://api.pay2s.vn/api/v1/einvoices"
          },
          "response": []
        },
        {
          "name": "02 - Create draft",
          "request": {
            "method": "POST",
            "header": [
              {
                "key": "Content-Type",
                "value": "application/json"
              }
            ],
            "body": {
              "mode": "raw",
              "raw": "{\n  \"action\": \"create_draft\",\n  \"connection_id\": {{connection_id}},\n  \"environment\": \"sandbox\",\n  \"external_ref\": \"{{external_ref}}\",\n  \"buyer_contact_name\": \"Khách lẻ\",\n  \"payment_method\": \"TM/CK\",\n  \"items\": [\n    {\n      \"name\": \"Kẹo mút\",\n      \"unit\": \"Cái\",\n      \"quantity\": 1,\n      \"unit_price\": 2000,\n      \"tax_rate\": 10\n    }\n  ],\n  \"auto_submit\": false\n}",
              "options": {
                "raw": {
                  "language": "json"
                }
              }
            },
            "url": "https://api.pay2s.vn/api/v1/einvoices",
            "description": "Manual sample flow: create_draft, then submit_draft. Set auto_submit:true to send immediately and skip step 03."
          },
          "response": []
        },
        {
          "name": "03 - submit_draft",
          "request": {
            "method": "POST",
            "header": [
              {
                "key": "Content-Type",
                "value": "application/json"
              }
            ],
            "body": {
              "mode": "raw",
              "raw": "{\n  \"action\": \"submit_draft\",\n  \"connection_id\": {{connection_id}},\n  \"environment\": \"sandbox\",\n  \"invoice_id\": {{invoice_id}}\n}",
              "options": {
                "raw": {
                  "language": "json"
                }
              }
            },
            "url": "https://api.pay2s.vn/api/v1/einvoices"
          },
          "response": []
        },
        {
          "name": "04 - publish",
          "request": {
            "method": "POST",
            "header": [
              {
                "key": "Content-Type",
                "value": "application/json"
              }
            ],
            "body": {
              "mode": "raw",
              "raw": "{\n  \"action\": \"publish\",\n  \"connection_id\": {{connection_id}},\n  \"environment\": \"sandbox\",\n  \"invoice_id\": {{invoice_id}}\n}",
              "options": {
                "raw": {
                  "language": "json"
                }
              }
            },
            "url": "https://api.pay2s.vn/api/v1/einvoices"
          },
          "response": []
        },
        {
          "name": "05 - detail",
          "request": {
            "method": "POST",
            "header": [
              {
                "key": "Content-Type",
                "value": "application/json"
              }
            ],
            "body": {
              "mode": "raw",
              "raw": "{\n  \"action\": \"detail\",\n  \"connection_id\": {{connection_id}},\n  \"environment\": \"sandbox\",\n  \"invoice_id\": {{invoice_id}}\n}",
              "options": {
                "raw": {
                  "language": "json"
                }
              }
            },
            "url": "https://api.pay2s.vn/api/v1/einvoices"
          },
          "response": []
        },
        {
          "name": "06 - sync",
          "request": {
            "method": "POST",
            "header": [
              {
                "key": "Content-Type",
                "value": "application/json"
              }
            ],
            "body": {
              "mode": "raw",
              "raw": "{\n  \"action\": \"sync\",\n  \"connection_id\": {{connection_id}},\n  \"environment\": \"sandbox\",\n  \"invoice_id\": {{invoice_id}}\n}",
              "options": {
                "raw": {
                  "language": "json"
                }
              }
            },
            "url": "https://api.pay2s.vn/api/v1/einvoices"
          },
          "response": []
        },
        {
          "name": "07 - files",
          "request": {
            "method": "POST",
            "header": [
              {
                "key": "Content-Type",
                "value": "application/json"
              }
            ],
            "body": {
              "mode": "raw",
              "raw": "{\n  \"action\": \"files\",\n  \"connection_id\": {{connection_id}},\n  \"environment\": \"sandbox\",\n  \"invoice_id\": {{invoice_id}},\n  \"file_type\": \"pdf\"\n}",
              "options": {
                "raw": {
                  "language": "json"
                }
              }
            },
            "url": "https://api.pay2s.vn/api/v1/einvoices"
          },
          "response": []
        }
      ],
      "event": [
        {
          "listen": "prerequest",
          "script": {
            "type": "text/javascript",
            "exec": [
              "const CryptoJS = pm.require('npm:crypto-js@4.2.0');",
              "const get = name => pm.environment.get(name);",
              "const need = name => { const v = get(name); if (v === undefined || v === null || v === '') throw new Error('Set Environment: ' + name); return v; };",
              "",
              "for(const key of ['partnerCode','accessKey','secretKey']) need(key);",
              "const raw=pm.variables.replaceIn(pm.request.body.raw);",
              "const payload=JSON.parse(raw);",
              "if(payload.action!=='connections' && payload.environment!=='sandbox') throw new Error('Use sandbox in this sample collection.');",
              "if(payload.action==='create_draft' && !payload.external_ref) throw new Error('Set Environment: external_ref');",
              "pm.request.body.update(raw);",
              "const timestamp=String(Math.floor(Date.now()/1000));",
              "const hash=CryptoJS.SHA256(raw).toString(CryptoJS.enc.Hex);",
              "const canonical=[timestamp,'POST','/api/v1/einvoices',hash].join('\\n');",
              "const signature=CryptoJS.HmacSHA256(canonical,need('secretKey')).toString(CryptoJS.enc.Hex);",
              "for(const [key,value] of Object.entries({'Content-Type':'application/json','X-Partner-Code':need('partnerCode'),'X-Access-Key':need('accessKey'),'X-Timestamp':timestamp,'X-Signature':signature})) pm.request.headers.upsert({key,value});"
            ]
          }
        },
        {
          "listen": "test",
          "script": {
            "type": "text/javascript",
            "packages": {},
            "requests": {},
            "exec": [
              "const result = pm.response.json();\r",
              "pm.test('API succeeded', () => pm.expect(result.status, result.message).to.eql(true));\r",
              "if (result.status === true) {\r",
              "  const action = JSON.parse(pm.request.body.raw).action;\r",
              "  if (action === 'create_draft' && result.data.id) pm.environment.set('invoice_id', result.data.id);\r",
              "  if (action === 'connections') {\r",
              "    const connections = result.data.connections.filter(c => c.environment === 'sandbox');\r",
              "    if (connections.length === 1) pm.environment.set('connection_id', connections[0].id);\r",
              "  }\r",
              "}"
            ]
          }
        }
      ]
    }
  ],
  "event": [
    {
      "listen": "prerequest",
      "script": {
        "type": "text/javascript",
        "packages": {},
        "requests": {},
        "exec": [
          ""
        ]
      }
    },
    {
      "listen": "test",
      "script": {
        "type": "text/javascript",
        "packages": {},
        "requests": {},
        "exec": [
          ""
        ]
      }
    }
  ],
  "variable": [
    {
      "key": "accessKey",
      "value": "",
      "type": "string"
    },
    {
      "key": "partnerCode",
      "value": "",
      "type": "string"
    },
    {
      "key": "secretKey",
      "value": "",
      "type": "string"
    },
    {
      "key": "amount",
      "value": "",
      "type": "string"
    },
    {
      "key": "account_number",
      "value": "",
      "type": "string"
    },
    {
      "key": "account_name",
      "value": "",
      "type": "string"
    },
    {
      "key": "bankCode",
      "value": "",
      "type": "string"
    },
    {
      "key": "bankShortName",
      "value": "",
      "type": "string"
    },
    {
      "key": "redirectUrl",
      "value": "",
      "type": "string"
    },
    {
      "key": "ipnUrl",
      "value": "",
      "type": "string"
    },
    {
      "key": "orderId",
      "value": "",
      "type": "string"
    },
    {
      "key": "requestId",
      "value": "",
      "type": "string"
    },
    {
      "key": "orderInfo",
      "value": "",
      "type": "string"
    },
    {
      "key": "extraData",
      "value": "",
      "type": "string"
    },
    {
      "key": "orderType",
      "value": "",
      "type": "string"
    },
    {
      "key": "payType",
      "value": "",
      "type": "string"
    },
    {
      "key": "transId",
      "value": "",
      "type": "string"
    },
    {
      "key": "resultCode",
      "value": "",
      "type": "string"
    },
    {
      "key": "message",
      "value": "",
      "type": "string"
    },
    {
      "key": "connection_id",
      "value": "",
      "type": "string"
    },
    {
      "key": "invoice_id",
      "value": "",
      "type": "string"
    },
    {
      "key": "external_ref",
      "value": "",
      "type": "string"
    },
    {
      "key": "taxCode",
      "value": "",
      "type": "string"
    },
    {
      "key": "begin",
      "value": "",
      "type": "string"
    },
    {
      "key": "end",
      "value": "",
      "type": "string"
    },
    {
      "key": "endpoint",
      "value": "",
      "type": "string"
    },
    {
      "key": "token",
      "value": "",
      "type": "string"
    },
    {
      "key": "oneqrToken",
      "value": "",
      "type": "string"
    },
    {
      "key": "MID",
      "value": "",
      "type": "string"
    },
    {
      "key": "TID",
      "value": "",
      "type": "string"
    },
    {
      "key": "merchantName",
      "value": "",
      "type": "string"
    },
    {
      "key": "description",
      "value": "",
      "type": "string"
    },
    {
      "key": "traceNumber",
      "value": "",
      "type": "string"
    },
    {
      "key": "transactionId",
      "value": "",
      "type": "string"
    },
    {
      "key": "limit",
      "value": "",
      "type": "string"
    },
    {
      "key": "offset",
      "value": "",
      "type": "string"
    },
    {
      "key": "content",
      "value": "",
      "type": "string"
    }
  ]
}
