Skip to main content

EIOTCLUB Web Staging Verification Checklist

Scope: web-side staging verification for the AOVIS / NEXA direct store Goal: confirm EIOTCLUB connectivity, fulfillment, webhook, refund, and user-visible status updates from the browser

0. Prerequisites

  • Staging site is deployed and healthy
  • VM .env.production contains EIOTCLUB env vars
  • EIOTCLUB outbound IP whitelist includes 8.229.42.246
  • EIOTCLUB webhook URL is configured to https://aovis.app/api/webhooks/eiotclub
  • A test ICCID is available
  • Admin account can sign in
  • Stripe test mode is available for checkout verification

1. Read-only EIOTCLUB connectivity checks

1.1 Admin SIM card sync

Target page:

  • /admin/sim-cards
  • /admin/sim-cards/[iccid]

Checklist:

  • Open /admin/sim-cards
  • Run Dry run for Sync all from EIOTCLUB
  • Confirm the result shows scanned, updated, and skipped
  • Confirm no data is written during dry run
  • Open a known test ICCID detail page
  • Run Sync from EIOTCLUB
  • Confirm the SIM record fills with real EIOTCLUB fields
    • imsi
    • packageCode
    • packageName
    • packageType
    • network
    • planExpiry
    • flow / usage numbers

Expected:

  • The page shows real card data rather than placeholder values
  • No raw EIOTCLUB errors are shown to the user

1.2 Admin data plan refresh

Target page:

  • /admin/data-plans

Checklist:

  • Open /admin/data-plans
  • For a row with packageCode, click Refresh from EIOTCLUB
  • Confirm the row updates without changing local priceUsd
  • Confirm success / failure feedback is shown in the page

Expected:

  • EIOTCLUB-linked plan metadata refreshes locally
  • Local pricing remains the source of truth

2. Purchase and fulfillment checks

2.1 Create a test data plan purchase

Target pages:

  • /services/cellular-data
  • /data-plans
  • Stripe checkout success return path

Checklist:

  • Start a Stripe test purchase for a data plan
  • Complete checkout with a test card
  • Confirm DataPlanPurchase is created in the admin backend
  • Confirm the purchase has the expected dataPlanId
  • Confirm the purchase starts in pending / ordering flow

Expected:

  • Stripe webhook writes the purchase record
  • EIOTCLUB fulfillment can proceed from the purchase record

2.2 Fulfillment status progression

Target page:

  • /admin/data-plan-purchases/[id]

Checklist:

  • Open the new purchase detail page
  • Confirm eiotclubOrderId appears after fulfillment starts
  • Confirm status moves from pending to ordering
  • Wait for reconcile or webhook processing
  • Confirm status moves to active
  • Confirm activatedAt is set
  • Confirm eiotclubPackageEndDate is set

Expected:

  • Fulfillment status changes are visible in the admin detail page
  • Audit timeline reflects the transition

3. Webhook checks

Target page / script:

  • /api/webhooks/eiotclub
  • scripts/eiotclub-webhook-replay.ts

Checklist:

  • Replay a PkgEffective sample payload
  • Confirm webhook returns SUCCESS
  • Confirm the related purchase stays active
  • Replay the same payload again
  • Confirm the second delivery is treated as duplicate
  • Replay a Refund sample payload
  • Confirm the purchase becomes refunded
  • Replay a CardIMEILocked sample payload
  • Confirm the SIM status becomes locked

Expected:

  • Webhook processing is idempotent
  • Duplicate payloads do not double-apply state changes
  • Webhook success response is { "status": "SUCCESS" }

4. Refund checks

Target page:

  • /admin/data-plan-purchases/[id]

Checklist:

  • Click Preview refund
  • Confirm an amount is returned
  • Enter an optional refund reason
  • Click Refund via EIOTCLUB
  • Confirm the purchase becomes refunded
  • Confirm Stripe refund was not triggered automatically

Expected:

  • EIOTCLUB refund and Stripe refund remain separate operations
  • The page shows friendly success / error feedback

5. User-visible status checks

Target pages:

  • /account/services
  • /account/devices

Checklist:

  • Open /account/services
  • Confirm the purchase shows a human-readable fulfillment badge
    • Processing
    • Activating
    • Active
    • Expired
    • Refunded
    • Action needed - contact support
  • Confirm Active rows show an expiry date
  • If pending_assignment, confirm the UI shows the SIM assignment placeholder
  • Open /account/devices
  • Confirm SIM rows show usage, carrier, and Expires {date}
  • Confirm offline and locked states are visibly flagged

Expected:

  • Users can see the fulfillment state change without using the admin backend

6. Failure-path checks

6.1 Invalid signature

Checklist:

  • Send a webhook replay with a bad signature
  • Confirm the endpoint returns 401
  • Confirm the response body says Invalid signature

6.2 Stale timestamp

Checklist:

  • Send a webhook replay with an expired timestamp
  • Confirm the endpoint returns 401

6.3 Missing local record

Checklist:

  • Replay a webhook for a card / order that does not exist locally
  • Confirm the webhook returns 200
  • Confirm the handler reports not_local or equivalent

Expected:

  • The app fails closed on auth problems and fails open on unknown but valid callbacks

7. Operational sanity checks

  • npm run eiotclub:connection-test prints the signature self-check and real card JSON
  • npm run eiotclub:smoke -- account-balance returns a real balance response
  • npm run eiotclub:smoke -- cards --size 5 returns a list
  • The admin pages do not show raw stack traces
  • The staging site still serves the homepage and main product pages normally

8. Notes for staging operators

  • Use test ICCIDs only
  • Do not expect every EIOTCLUB cardStatus value to map neatly to the same local label on day one
  • If the browser flow passes but a webhook replay fails, trust the webhook result first
  • Keep EIOTCLUB refunds separate from Stripe refunds
  • If a purchase is pending_assignment, treat it as an operations task, not a user self-service flow yet