return_url or cancel_url and adds the result as query parameters, signed with the portal’s signing secret.
Paid
When the payer presses Done on the receipt, they go to yourreturn_url with:
amount_cents is 10300.
Cancelled
When the payer cancels on the checkout page, they go to yourcancel_url with intent_id, reference_id, status=cancelled, and sig. The checkout can no longer be paid. If the payer reopens its link, they see an empty checkout with no line items; start a new checkout if they want to pay.
Failed to start
When the request to start a checkout fails, no checkout exists. The payer goes to yourcancel_url with error=validation_error, detail=<code>, and sig, or to the GroGov error page. See Errors for the codes.
What is not reported today
Treat a missing result as unknown, not as unpaid. Do not ask the payer to pay again only because no result arrived. Contact GroGov support to confirm a payment’s status.Verifying the signature
Verifysig before you act on a result. Anyone can type a URL with status=paid in it, but only GroGov has the portal’s signing secret. The signature is a hex HMAC-SHA256, keyed with the portal’s signing secret, of the result’s parameters:
- Take the parameters GroGov added, except
sig. Your own query parameters on the address are not signed. GroGov’s parameters areintent_id,reference_id,transaction_id,status,amount_cents,error, anddetail, whichever are present. Do not use these names in your ownreturn_urlorcancel_url. - Sort them by name.
- Join them as
name=valuepairs with&, using the decoded values. - Compute the HMAC-SHA256 of that text with the signing secret, as lowercase hex.
- Compare it with
sigusing a constant-time comparison.
sig, or with one that does not match, is unverified. Results carry no timestamp yet, so you cannot reject an old result by its age. Record each intent_id you have processed and ignore repeats.
Worked example
With this signing secret (an example, not a real one):https://partner.example.com/checkout/return?order=42, the browser arrives at:
order is yours, so it is left out. The other parameters, sorted and joined, are the text to sign:
26dcd59a32e0af4e1f4b6dbfed67927d29c4f4fc534e54825a7e0fed03763fbe, which matches sig.
reference_id to your record and check amount_cents before you mark it paid.