Troubleshooting
Use the database and the provider dashboard together. The success page in the browser is not evidence that a payment or an approval happened.
The customer paid and the booking is still pending payment
The redirect arrived and the webhook did not, or the signature check failed.
- Read
orders.statusandpayments.status. - Look for a
payment_webhook_eventsrow for that provider event id. - If the event is absent, inspect API logs for a signature failure.
- Run reconcile so the API reads the provider payment and applies the normal transaction.
- Confirm the webhook URL is the public Express route and the signing secret matches the endpoint.
The booking is pending approval and the customer expects a confirmed date
That is the intended state after a verified payment. The photographer still has to approve or reject it. Check bookings.status and the photographer notification. Do not update the status with a manual SQL statement. Use the decision endpoint so the audit row and any reward credit are written together.
A refund did not appear
- Confirm the booking is
REJECTEDorCANCELLEDand the order isREFUND_PENDINGorREFUNDED. - Read the
payment.refundjob.FAILEDjobs keeplast_error. - Match
payments.provider_payment_idto the provider refund. - A duplicate refund call should be refused by the provider idempotency key stored with the payment. Do not create a second full refund by hand unless the provider shows that no refund exists.
The customer cannot download a published gallery
Publication is not access. Check publication_status, access_status, and photos.status.
| Observed | Result |
|---|---|
| Published, access pending | No signed URL. Approve access. |
Approved, photo still PROCESSING | No signed URL until the thumbnail job sets READY. |
| Access revoked | No new URL. An older URL works only until its five-minute expiry. |
| Another customer's access token | Not found. |
A referral discount is missing
- Confirm the reward is
AVAILABLEand a positiveCREDITexists.PENDINGis not spendable. - Sum
reward_ledger.amount_centsfor the referrer. That sum is the balance. - A self-referral or a second referrer never creates a second row.
referrals.referred_user_idis unique. - If the qualifying booking was rejected, the reward should be
REVERSEDor stillPENDINGwith no credit.
A ledger row looks wrong
Do not update it. Insert a REVERSAL through the refund or an audited administrative reversal that uses the same sign rules. The database rejects UPDATE and DELETE on reward_ledger.
Jobs are stuck
Claimed jobs have locked_at set and status RUNNING. A worker that died leaves that lock. The worker releases locks older than its heartbeat before claiming again. Inspect attempt_count and last_error. Email and thumbnail failures do not roll back the booking or the original file.