Payvol Verify
Never ask a payer to trust a green tick.
Verify answers seven separate questions about a payment request and shows every answer, including the ones it cannot reach. That last part is the whole point.
Add Verify to a wallet Read the docs
@payvol/coreruns offlinefails closed Available
The package is published, so you can install this today.
Why seven
One checkmark hides the question that matters.
A request can have perfect bytes and a perfect signature and still come from the wrong company. It can name a real account that belongs to somebody else. Collapse all of that into a single green state and the payer cannot tell which part was actually established.
Unknown is a rejection, not a shrug
Fails closed
An unrecognised profile, an unlisted signature suite, a mismatched identifier. Each one stops the request before a pay button can render. There is no path where the wallet guesses.
A valid signature is not a verified merchant
Honest about identity
Cryptography proves the bytes were not altered by someone without the key. It does not prove whose key it is. Verify keeps those two facts apart and refuses to let the second borrow confidence from the first.
The request declares, the wallet checks
Checked at pay time
A request states what the receiving side needs. It never carries a claim that those conditions are met, because a request created on Monday cannot know what is true on Thursday.
Two implementations, one verdict
Same answer everywhere
The conformance vectors decide what is correct, not our code. Build your own reader and prove it agrees with every other one, in your own browser.
// same request, two independent readers
reader A -> 9f2c...41a7
reader B -> 9f2c...41a7
// a disagreement is a failing test, not a bug report How it works
Decode, check, decide.
01
Decode
- Read the artifact from a QR, a link or a pointer
- Verify fetched bytes against the identifier in the URI
- Reject an unknown profile before parsing further
- Reproduce the canonical bytes locally
02
Check
- Recompute the identifier and compare
- Open the envelope against an allowed suite
- Resolve the payee, or record that you could not
- Bind the destination account to the payee
- Ask the registry whether the receiving side can accept
03
Decide
- Apply your own thresholds and trusted origins
- Render every answer, including the unanswered one
- Allow, warn, hold for review, or reject
- Hand a prepared transfer to the signing flow
Three ways to show a request
The middle one is what most software does.
01
Raw
no checks at all
The wallet renders whatever the request says. The payer reads a name and an amount and decides on instinct.
The payer carries all of the risk
02
One green tick
checks collapsed into a state
Several checks run and their results are merged into a single indicator. When identity could not be established, the tick appears anyway, because the bytes were fine.
Confidence the evidence does not support
03
Seven answers
Payvol Verify
Each question is answered on its own evidence and shown on its own line. The one that could not be answered is labelled rather than hidden, and your policy decides what to do about it.
The payer sees exactly what was established
Boundaries
What Verify deliberately does not do.
A module that pretends to cover more than it does is worse than one with a narrow edge, because you find the edge later, in production.
For wallet teams
Four calls, and your users stop guessing.
Verify runs entirely inside the wallet. No network calls of ours, no keys held, no account. Pass it the artifact, read the answers, decide with your own policy.
The conformance vectors ship with it, so you can prove your integration reads a request the same way every other implementation does.
import { decode, validate } from '@payvol/core'
// decode the artifact, then check it against the profile
const request = decode(scanned)
const result = validate(request)
// a refusal names its rule; it is never a bare false
result.valid // false
result.code // 'EXPIRED'
result.signatureVerified // 'absent' | 'not-checked'
// your policy, not ours
if (result.valid) wallet.present(result.payvol) Where it is used
4 of the six situations reach Verify.
See it answer a real request.
Paste any Payvol request into the app and watch all 7 answers resolve. 1 of them will say it could not be reached, and that is the honest result rather than a gap. No wallet needed.