Section one
Connection
Register this browser as a PayWibe device, then test it before real money moves through it. PayWibe decides what settles — this extension only reports what the bank reference on your dashboard says.
chrome://extensions.
Your API URL, device secret and settings are kept — they live in Chrome, not in the folder.
POST /v1/device/register using your dashboard
login. Shown once, never recoverable — an admin can disable the device to revoke it.The test signs a heartbeat, not a payment — it proves the URL, secret and signature work without any chance of settling a real order.
Payments
What was read off the dashboard, next to what PayWibe did with it.
| Time | Payer | UTR | Amount | PayWibe |
|---|
Activity
Section two
Setup
This extension authenticates as a PayWibe device, exactly like the merchant Android app. Four steps, once per browser.
Steps
| # | Do this |
|---|---|
1 | In the PayWibe dashboard open Devices → Register device. Name it something you will recognise, e.g. "Counter PC — Chrome". |
2 | Copy the device_secret it shows. It starts with dvc_ and is displayed once — PayWibe stores only its hash and can never show it again. |
3 | On the Connection tab paste your API origin and that secret, then press Save connection and accept Chrome's permission prompt. |
4 | Press Test this device. A green reply means the signature chain works. Then open your PhonePe or Paytm dashboard on its transaction list and leave the tab open. |
What gets sent
One POST per captured credit to /v1/device/confirm, carrying only
what PayWibe needs to identify the payment:
| Field | Type | Notes |
|---|---|---|
amount | string | Rupees with exactly two decimals, e.g. "2499.50". A JSON number is rejected by the server. |
utr | string | Bank reference, 6–40 alphanumerics, upper-cased. |
payer | string | Who paid, from a dedicated cell or a labelled "Paid by …" on the row. Evidence for reconciliation only — never a match key. |
vpa | string | The payer's UPI handle, e.g. ravi.k@okhdfcbank. More reliable than a name, since handles rarely repeat. |
package | string | Always chrome-extension, so you can tell these apart from APK confirmations. |
No merchant id, no store name, no page text. Your account is derived server-side from the device secret, so a scraped identity would be an unverified claim with no purpose.
Headers
| Header | Value |
|---|---|
Authorization | Bearer <device_secret> |
X-Timestamp | Unix seconds, stamped at send time (5-minute skew window) |
X-Nonce | UUID, stable across retries of the same payment |
X-Signature | HMAC-SHA256 of <ts>.<nonce>.<raw body> |
duplicate instead of settling a second time.
What PayWibe replies
| Reply | Meaning |
|---|---|
200 success | The order was matched and settled. |
200 duplicate | That bank reference already settled an order. Nothing credited twice. |
202 review_required | Real money, but more than one open order fits. Waiting for you in the dashboard. |
202 pending | No open order matches. Recorded for reconciliation, not settled. |
All four are final answers and are not retried. Only network errors, timeouts and 5xx are retried — five times, backing off 15s, 1m, 5m, 15m, 1h. Every reply is written to the Payments table on the Connection tab, with the order it settled.
Staying connected
Once a minute this browser signs a heartbeat to /v1/device/heartbeat. Two
things come of that:
- It appears as an online device in the PayWibe admin device list, alongside the merchant phones — same view, same two-minute online window.
- It picks up admin commands.
disableandmaintenancestop it reading;logoutalso wipes the stored secret. Both are already enforced server-side the moment they are issued, so a revoked device cannot keep confirming payments even if this browser never polls again.
Section three
Troubleshooting
Start with the Activity feed on the Connection tab — it names the failure. Then find it below.
"Network error" or the request never reaches my server
This is almost never CORS. The POST goes out from the extension's service
worker, which is exempt from CORS once Chrome has granted host permission — so
your server does not need Access-Control-Allow-Origin for this
traffic, and there is no preflight to answer.
What it usually is, in order:
- Permission not granted. Press Save connection and accept Chrome's prompt. Changing the API host requires granting the new one.
- Bad certificate. Self-signed TLS is rejected outright. Use a real
certificate, or test against
http://localhost. - Not reachable from this machine. A private-network address only resolves from inside that network.
- Server closed the connection before responding — check your reverse proxy timeouts.
HTTP 401 invalid_signature on every delivery
- Wrong or revoked secret. Re-check that it starts with
dvc_and that the device is still active in the dashboard. A device an admin has disabled fails here, by design. - Secret pasted with a trailing space or newline. The field trims on save; re-paste and save again if in doubt.
- Clock drift. The server allows five minutes either way. If this PC's clock is wrong, every request is stale. Fix the system time.
- API URL points at the wrong environment — a secret issued on one PayWibe instance is meaningless on another.
HTTP 404 on every delivery
- The API URL has a path on it. Save the origin only —
https://api.example.com, nothttps://api.example.com/v1/…. The extension appends the path itself. - Your proxy strips or adds a prefix in front of
/v1. - A trailing-slash redirect is in play; redirects on a POST commonly land as 404.
HTTP 400 invalid_amount or invalid_json
The request was authenticated but the body was refused. The Activity feed shows the first 200 characters of the server's reply.
- invalid_amount — the amount read off the row was zero, negative, or had more precision than paise. Check what the row actually renders.
- invalid_json — you are running a mismatched build. The amount
must be a rupee string with two decimals; an older build sent a number.
Reload the extension from
chrome://extensions.
Nothing is captured — the tape says "no transaction rows on screen"
Portals rewrite their markup without notice, which breaks selectors. The extension already falls back to a heuristic that looks for any on-screen block containing both a reference and a ₹ amount, so first check the simple causes:
- The dashboard is on a summary view, not the transaction list.
- Rows are collapsed, or the list is empty for today's filter.
- The UTR is hidden behind a "view details" expander — the extension reads only what is rendered on screen, by design.
- The portal shows status as a coloured icon with no text. Only a row the portal calls successful in words is sent; that is deliberate, and the fix is a selector, not a looser rule.
To repair a selector, edit the adapter's rowSelectors and
fieldSelectors arrays in adapters.js. Right-click a row →
Inspect, find a stable attribute (prefer data-* over generated class
names), add it to the front of the array, and reload the extension. Entries are
tried in order and the first one that matches wins, so old entries can stay as
fallbacks.
The refresh button is never pressed
- Eight seconds of no scrolling, typing, or clicking are required before the extension will touch the UI.
- The tab is in the background. It still runs, but Chrome throttles background timers to roughly once a minute, so presses are far apart.
- The control moved. Update
refreshSelectorsin the adapter — PhonePe's default is[data-id="transaction-refresh-button"].
The extension never reloads or navigates the page. If the portal needs a full reload to show new rows, refresh it yourself and leave the tab open.
The same payment was sent twice
The duplicate index is keyed on utr + amount and lives in this browser
profile only. It resets when you reinstall, clear duplicate history, or move to
another machine.
That is not a money risk: PayWibe refuses a bank reference that has already
settled an order and answers duplicate. The second send is noise in the
activity feed, not a second credit.
A payment shows as "Needs review" instead of settling
The credit reached PayWibe and was recorded — it just could not be tied to exactly one order. Usual reasons:
- The customer never entered that reference at checkout, and two or more open orders share the amount. PayWibe will not guess which customer paid.
- The order already expired before the credit was read.
- The reference on the dashboard is the portal's own transaction id, not the bank UTR the customer sees.
Resolve it from Devices → Unmatched payments in the dashboard. Nothing is lost; it is waiting for a human decision on purpose.
Deliveries sit in "Waiting" and never clear
- No API URL or device secret is saved yet — payments queue until both are.
- The queue drains on a one-minute alarm plus on every new capture, so a fresh retry can take up to a minute. Retry waiting deliveries forces it.
- An item on its fifth backoff is an hour out. The feed shows the attempt count and the last error.