{
  "info": {
    "_postman_id": "suqna-tap-payment-flow",
    "name": "Suqna - Tap (PayTap) Payment Flow",
    "description": "Endpoints involved in online (Tap / PayTap), wallet, and COD payment flows.\n\n## Setup\n1. Run: `php artisan db:seed --class=PaymentFlowSeeder`\n2. Set collection variables (defaults match the seeder)\n3. Run **Auth → Login Client** first (saves `client_token`)\n4. Follow Order Online or Package Online folders\n\n## Seeded credentials\n- Client phone: `511111111` / code `966` / password `123456789`\n- Wallet balance: `500`\n- Product SKU: `PAY-TEST-SIMPLE-001` (price 100)\n- Package: Premium (40 SAR)\n\n## Required headers\n- `user-type: client`\n- `Agent-Token: {{agent_token}}`\n- `Accept-Language: en`\n- `Authorization: Bearer {{client_token}}` (auth routes)\n\nWebhook + redirect are public (no auth / user-type).",
    "schema": "https://schema.getpostman.com/json/collection/v2.1.0/collection.json"
  },
  "variable": [
    { "key": "base_url", "value": "http://localhost:8000" },
    { "key": "agent_token", "value": "postman-agent" },
    { "key": "client_token", "value": "" },
    { "key": "client_phone", "value": "511111111" },
    { "key": "client_phone_code", "value": "966" },
    { "key": "client_password", "value": "123456789" },
    { "key": "location_id", "value": "1" },
    { "key": "product_id", "value": "1" },
    { "key": "package_id", "value": "1" },
    { "key": "order_group_id", "value": "" },
    { "key": "tran_ref", "value": "" },
    { "key": "payment_url", "value": "" },
    { "key": "return_url", "value": "http://localhost:3000/payment-status" },
    { "key": "brand", "value": "card" }
  ],
  "item": [
    {
      "name": "0. Auth",
      "item": [
        {
          "name": "Login Client",
          "event": [
            {
              "listen": "test",
              "script": {
                "exec": [
                  "const res = pm.response.json();",
                  "if (pm.response.code === 200 && res.data && res.data.token) {",
                  "  pm.collectionVariables.set('client_token', res.data.token);",
                  "  console.log('client_token saved');",
                  "}"
                ],
                "type": "text/javascript"
              }
            }
          ],
          "request": {
            "method": "POST",
            "header": [
              { "key": "user-type", "value": "client" },
              { "key": "Agent-Token", "value": "{{agent_token}}" },
              { "key": "Accept-Language", "value": "en" },
              { "key": "Accept", "value": "application/json" },
              { "key": "Content-Type", "value": "application/json" }
            ],
            "body": {
              "mode": "raw",
              "raw": "{\n  \"auth\": \"{{client_phone}}\",\n  \"phone_code\": \"{{client_phone_code}}\",\n  \"password\": \"{{client_password}}\",\n  \"device_type\": \"web\",\n  \"device_token\": \"postman-device\"\n}"
            },
            "url": "{{base_url}}/api/app/client/auth/login",
            "description": "Login seeded payment client. Saves `client_token`."
          }
        },
        {
          "name": "Show Profile",
          "request": {
            "method": "GET",
            "header": [
              { "key": "user-type", "value": "client" },
              { "key": "Agent-Token", "value": "{{agent_token}}" },
              { "key": "Accept-Language", "value": "en" },
              { "key": "Accept", "value": "application/json" },
              { "key": "Authorization", "value": "Bearer {{client_token}}" }
            ],
            "url": "{{base_url}}/api/app/client/profile",
            "description": "Confirm wallet balance and verified client."
          }
        }
      ]
    },
    {
      "name": "1. Setup (Location / Product / Cart)",
      "item": [
        {
          "name": "List Locations",
          "event": [
            {
              "listen": "test",
              "script": {
                "exec": [
                  "const res = pm.response.json();",
                  "const list = res.data?.locations || res.data?.data || res.data;",
                  "if (Array.isArray(list) && list.length) {",
                  "  pm.collectionVariables.set('location_id', String(list[0].id));",
                  "} else if (list?.data?.length) {",
                  "  pm.collectionVariables.set('location_id', String(list.data[0].id));",
                  "}"
                ],
                "type": "text/javascript"
              }
            }
          ],
          "request": {
            "method": "GET",
            "header": [
              { "key": "user-type", "value": "client" },
              { "key": "Agent-Token", "value": "{{agent_token}}" },
              { "key": "Accept-Language", "value": "en" },
              { "key": "Accept", "value": "application/json" },
              { "key": "Authorization", "value": "Bearer {{client_token}}" }
            ],
            "url": "{{base_url}}/api/app/client/locations",
            "description": "Use seeded location or capture `location_id`."
          }
        },
        {
          "name": "Create Location (optional)",
          "event": [
            {
              "listen": "test",
              "script": {
                "exec": [
                  "const res = pm.response.json();",
                  "if (res.data?.id) pm.collectionVariables.set('location_id', String(res.data.id));"
                ],
                "type": "text/javascript"
              }
            }
          ],
          "request": {
            "method": "POST",
            "header": [
              { "key": "user-type", "value": "client" },
              { "key": "Agent-Token", "value": "{{agent_token}}" },
              { "key": "Accept-Language", "value": "en" },
              { "key": "Accept", "value": "application/json" },
              { "key": "Content-Type", "value": "application/json" },
              { "key": "Authorization", "value": "Bearer {{client_token}}" }
            ],
            "body": {
              "mode": "raw",
              "raw": "{\n  \"country_id\": 1,\n  \"city_id\": 1,\n  \"lat\": 24.7136,\n  \"lng\": 46.6753,\n  \"name\": \"Postman Home\",\n  \"property_number\": \"99\",\n  \"details\": \"Riyadh Street Test Address\",\n  \"url\": \"https://maps.google.com/?q=24.7136,46.6753\",\n  \"is_default\": 1\n}"
            },
            "url": "{{base_url}}/api/app/client/locations"
          }
        },
        {
          "name": "List Products",
          "event": [
            {
              "listen": "test",
              "script": {
                "exec": [
                  "const res = pm.response.json();",
                  "const products = res.data?.products || res.data?.data || res.data;",
                  "const first = Array.isArray(products) ? products[0] : (products?.data?.[0]);",
                  "if (first?.id) pm.collectionVariables.set('product_id', String(first.id));"
                ],
                "type": "text/javascript"
              }
            }
          ],
          "request": {
            "method": "GET",
            "header": [
              { "key": "user-type", "value": "client" },
              { "key": "Agent-Token", "value": "{{agent_token}}" },
              { "key": "Accept-Language", "value": "en" },
              { "key": "Accept", "value": "application/json" }
            ],
            "url": "{{base_url}}/api/app/client/products",
            "description": "Find seeded Tap Test Product and save `product_id`."
          }
        },
        {
          "name": "Add to Cart",
          "request": {
            "method": "POST",
            "header": [
              { "key": "user-type", "value": "client" },
              { "key": "Agent-Token", "value": "{{agent_token}}" },
              { "key": "Accept-Language", "value": "en" },
              { "key": "Accept", "value": "application/json" },
              { "key": "Content-Type", "value": "application/json" },
              { "key": "Authorization", "value": "Bearer {{client_token}}" }
            ],
            "body": {
              "mode": "raw",
              "raw": "{\n  \"product_id\": {{product_id}},\n  \"quantity\": 1,\n  \"action\": \"increment\"\n}"
            },
            "url": "{{base_url}}/api/app/client/cart",
            "description": "Add simple product to cart (no variant_id)."
          }
        },
        {
          "name": "Get Cart",
          "request": {
            "method": "GET",
            "header": [
              { "key": "user-type", "value": "client" },
              { "key": "Agent-Token", "value": "{{agent_token}}" },
              { "key": "Accept-Language", "value": "en" },
              { "key": "Accept", "value": "application/json" },
              { "key": "Authorization", "value": "Bearer {{client_token}}" }
            ],
            "url": {
              "raw": "{{base_url}}/api/app/client/cart?location_id={{location_id}}",
              "host": ["{{base_url}}"],
              "path": ["api", "app", "client", "cart"],
              "query": [{ "key": "location_id", "value": "{{location_id}}" }]
            }
          }
        }
      ]
    },
    {
      "name": "2. Order Payments",
      "item": [
        {
          "name": "Create Order - Online (Tap)",
          "event": [
            {
              "listen": "test",
              "script": {
                "exec": [
                  "const res = pm.response.json();",
                  "const data = res.data || {};",
                  "if (data.order_group_id) pm.collectionVariables.set('order_group_id', String(data.order_group_id));",
                  "if (data.payment?.tran_ref) pm.collectionVariables.set('tran_ref', data.payment.tran_ref);",
                  "if (data.payment?.payment_url) pm.collectionVariables.set('payment_url', data.payment.payment_url);",
                  "console.log('tran_ref=', data.payment?.tran_ref);",
                  "console.log('payment_url=', data.payment?.payment_url);"
                ],
                "type": "text/javascript"
              }
            }
          ],
          "request": {
            "method": "POST",
            "header": [
              { "key": "user-type", "value": "client" },
              { "key": "Agent-Token", "value": "{{agent_token}}" },
              { "key": "Accept-Language", "value": "en" },
              { "key": "Accept", "value": "application/json" },
              { "key": "Content-Type", "value": "application/json" },
              { "key": "Authorization", "value": "Bearer {{client_token}}" }
            ],
            "body": {
              "mode": "raw",
              "raw": "{\n  \"location_id\": {{location_id}},\n  \"payment_method\": \"online\",\n  \"brand\": \"{{brand}}\",\n  \"return_url\": \"{{return_url}}\",\n  \"phone_code\": \"{{client_phone_code}}\",\n  \"phone\": \"{{client_phone}}\"\n}"
            },
            "url": "{{base_url}}/api/app/client/orders",
            "description": "Creates pending payment and returns Tap `payment_url` + charge id (`tran_ref` / `tap_id`).\nOpen payment_url in browser, then call Verify Payment with tap charge id."
          }
        },
        {
          "name": "Create Order - Wallet",
          "request": {
            "method": "POST",
            "header": [
              { "key": "user-type", "value": "client" },
              { "key": "Agent-Token", "value": "{{agent_token}}" },
              { "key": "Accept-Language", "value": "en" },
              { "key": "Accept", "value": "application/json" },
              { "key": "Content-Type", "value": "application/json" },
              { "key": "Authorization", "value": "Bearer {{client_token}}" }
            ],
            "body": {
              "mode": "raw",
              "raw": "{\n  \"location_id\": {{location_id}},\n  \"payment_method\": \"wallet\"\n}"
            },
            "url": "{{base_url}}/api/app/client/orders",
            "description": "Instant wallet debit (seeded balance 500)."
          }
        },
        {
          "name": "Create Order - COD",
          "request": {
            "method": "POST",
            "header": [
              { "key": "user-type", "value": "client" },
              { "key": "Agent-Token", "value": "{{agent_token}}" },
              { "key": "Accept-Language", "value": "en" },
              { "key": "Accept", "value": "application/json" },
              { "key": "Content-Type", "value": "application/json" },
              { "key": "Authorization", "value": "Bearer {{client_token}}" }
            ],
            "body": {
              "mode": "raw",
              "raw": "{\n  \"location_id\": {{location_id}},\n  \"payment_method\": \"cod\"\n}"
            },
            "url": "{{base_url}}/api/app/client/orders"
          }
        },
        {
          "name": "Show Order Group",
          "request": {
            "method": "GET",
            "header": [
              { "key": "user-type", "value": "client" },
              { "key": "Agent-Token", "value": "{{agent_token}}" },
              { "key": "Accept-Language", "value": "en" },
              { "key": "Accept", "value": "application/json" },
              { "key": "Authorization", "value": "Bearer {{client_token}}" }
            ],
            "url": "{{base_url}}/api/app/client/orders/{{order_group_id}}",
            "description": "Includes payment_status, tran_ref, payment_url."
          }
        },
        {
          "name": "List Orders",
          "request": {
            "method": "GET",
            "header": [
              { "key": "user-type", "value": "client" },
              { "key": "Agent-Token", "value": "{{agent_token}}" },
              { "key": "Accept-Language", "value": "en" },
              { "key": "Accept", "value": "application/json" },
              { "key": "Authorization", "value": "Bearer {{client_token}}" }
            ],
            "url": "{{base_url}}/api/app/client/orders"
          }
        }
      ]
    },
    {
      "name": "3. Package Subscription Payments",
      "item": [
        {
          "name": "Show Package",
          "event": [
            {
              "listen": "test",
              "script": {
                "exec": [
                  "const res = pm.response.json();",
                  "if (res.data?.id) pm.collectionVariables.set('package_id', String(res.data.id));"
                ],
                "type": "text/javascript"
              }
            }
          ],
          "request": {
            "method": "GET",
            "header": [
              { "key": "user-type", "value": "client" },
              { "key": "Agent-Token", "value": "{{agent_token}}" },
              { "key": "Accept-Language", "value": "en" },
              { "key": "Accept", "value": "application/json" }
            ],
            "url": "{{base_url}}/api/app/client/package"
          }
        },
        {
          "name": "Subscribe - Online (Tap)",
          "event": [
            {
              "listen": "test",
              "script": {
                "exec": [
                  "const res = pm.response.json();",
                  "const data = res.data || {};",
                  "if (data.payment?.tran_ref) pm.collectionVariables.set('tran_ref', data.payment.tran_ref);",
                  "if (data.payment?.payment_url) pm.collectionVariables.set('payment_url', data.payment.payment_url);"
                ],
                "type": "text/javascript"
              }
            }
          ],
          "request": {
            "method": "POST",
            "header": [
              { "key": "user-type", "value": "client" },
              { "key": "Agent-Token", "value": "{{agent_token}}" },
              { "key": "Accept-Language", "value": "en" },
              { "key": "Accept", "value": "application/json" },
              { "key": "Content-Type", "value": "application/json" },
              { "key": "Authorization", "value": "Bearer {{client_token}}" }
            ],
            "body": {
              "mode": "raw",
              "raw": "{\n  \"package_id\": {{package_id}},\n  \"payment_method\": \"online\",\n  \"brand\": \"{{brand}}\",\n  \"return_url\": \"{{return_url}}\"\n}"
            },
            "url": "{{base_url}}/api/app/client/package/subscribe"
          }
        },
        {
          "name": "Subscribe - Wallet",
          "request": {
            "method": "POST",
            "header": [
              { "key": "user-type", "value": "client" },
              { "key": "Agent-Token", "value": "{{agent_token}}" },
              { "key": "Accept-Language", "value": "en" },
              { "key": "Accept", "value": "application/json" },
              { "key": "Content-Type", "value": "application/json" },
              { "key": "Authorization", "value": "Bearer {{client_token}}" }
            ],
            "body": {
              "mode": "raw",
              "raw": "{\n  \"package_id\": {{package_id}},\n  \"payment_method\": \"wallet\"\n}"
            },
            "url": "{{base_url}}/api/app/client/package/subscribe"
          }
        }
      ]
    },
    {
      "name": "4. Tap Callbacks",
      "item": [
        {
          "name": "Verify Payment (after Tap)",
          "request": {
            "method": "POST",
            "header": [
              { "key": "user-type", "value": "client" },
              { "key": "Agent-Token", "value": "{{agent_token}}" },
              { "key": "Accept-Language", "value": "en" },
              { "key": "Accept", "value": "application/json" },
              { "key": "Content-Type", "value": "application/json" },
              { "key": "Authorization", "value": "Bearer {{client_token}}" }
            ],
            "body": {
              "mode": "raw",
              "raw": "{\n  \"payment_reference\": \"{{tran_ref}}\"\n}"
            },
            "url": "{{base_url}}/api/app/client/payment/verify",
            "description": "Call after returning from Tap with charge id (`tap_id` / `tran_ref`) as payment_reference."
          }
        },
        {
          "name": "Webhook (Tap server)",
          "request": {
            "method": "POST",
            "header": [
              { "key": "Accept", "value": "application/json" },
              { "key": "Content-Type", "value": "application/json" }
            ],
            "body": {
              "mode": "raw",
              "raw": "{\n  \"id\": \"{{tran_ref}}\",\n  \"metadata\": { \"cart_id\": \"og-1-000000\" }\n}"
            },
            "url": "{{base_url}}/api/app/client/payment/webhook",
            "description": "Public. Simulated Tap post/callback. No user-type / auth required. Body uses Tap charge `id`."
          }
        },
        {
          "name": "Redirect Relay",
          "request": {
            "method": "GET",
            "header": [],
            "url": {
              "raw": "{{base_url}}/api/app/client/payment/redirect?cart_id=og-1-000000&return_url={{return_url_b64}}&tran_ref={{tran_ref}}",
              "host": ["{{base_url}}"],
              "path": ["api", "app", "client", "payment", "redirect"],
              "query": [
                { "key": "cart_id", "value": "og-1-000000" },
                { "key": "return_url", "value": "{{return_url_b64}}", "description": "base64 of frontend URL (optional if env TAP_FRONTEND_RETURN_URL set)" },
                { "key": "tran_ref", "value": "{{tran_ref}}" }
              ]
            },
            "description": "Public relay. Tap hits this; app redirects to frontend with tap_id/tran_ref."
          }
        }
      ]
    },
    {
      "name": "5. Wallet",
      "item": [
        {
          "name": "Get Wallet",
          "request": {
            "method": "GET",
            "header": [
              { "key": "user-type", "value": "client" },
              { "key": "Agent-Token", "value": "{{agent_token}}" },
              { "key": "Accept-Language", "value": "en" },
              { "key": "Accept", "value": "application/json" },
              { "key": "Authorization", "value": "Bearer {{client_token}}" }
            ],
            "url": "{{base_url}}/api/app/client/wallet"
          }
        }
      ]
    }
  ]
}
