Payments
Track every payment transaction from initiation to completion.
Overview
The Payments module provides a complete transaction history for all door access and device usage payments. Every payment attempt — whether successful, failed, or refunded — is recorded here.
Payment Data
Each payment record contains:
| Field | Description |
|---|---|
| Payment ID | Unique identifier |
| Amount | Total amount charged |
| Currency | Payment currency (EUR default) |
| Status | PENDING, SUCCEEDED, FAILED, or REFUNDED |
| Module | Door access or Device usage |
| Door/Device | Which door or device was accessed |
| Location | Where the transaction occurred |
| Guest Email | Email provided by the guest (if any) |
| Stripe Reference | Payment Intent ID in Stripe |
| Date | When the payment was processed |
Payment Lifecycle
[1] Guest initiates payment
│
▼
Stripe Payment Intent created
──────────────────────────────
Status: PENDING
│
▼
[2] Guest completes payment
│
▼
Stripe processes card
┌────┴────┐
│ │
SUCCEEDED FAILED
│ │
▼ ▼
Access granted Error returned to guest
│ │
▼ ▼
Webhook received No action taken
│
▼
[3] Post-payment actions
┌──────┴──────┐
│ │
Door access Device session
QR code Relay activated
generated timer starts
Door Payment Flow
- Guest scans QR code → opens payment page
- Guest enters email → creates Stripe Checkout session
- Guest pays → Stripe charges the card
- Stripe webhook fires →
payment_intent.succeeded - Hygate receives webhook → creates Payment record → generates QR access code
- Guest sees access code → scans it at the door
Device Payment Flow
- Guest scans QR code → opens payment page
- Guest selects a usage plan → creates Stripe Checkout session
- Guest pays → Stripe charges the card
- Stripe webhook fires →
payment_intent.succeeded - Hygate receives webhook → creates Payment record → creates DeviceSession
- Grace period begins → relay turns ON → timer starts
Filtering and Searching
Filter payments to find exactly what you need:
| Filter | Options |
|---|---|
| Date range | Today, This Week, This Month, Custom range |
| Module | All, Door, Device |
| Status | All, PENDING, SUCCEEDED, FAILED, REFUNDED |
| Location | Any configured location |
Payment Statuses
| Status | Meaning | Action Required |
|---|---|---|
| PENDING | Payment initiated but not yet confirmed | Wait — resolves automatically |
| SUCCEEDED | Payment complete, access granted | None — normal operation |
| FAILED | Payment declined or error occurred | Investigate if pattern continues |
| REFUNDED | Admin initiated refund from Stripe | None — informational |
Why Payments Fail
Common reasons for FAILED payments:
| Reason | What to Check |
|---|---|
| Card declined | Card insufficient funds, expired, or blocked |
| 3D Secure required | Card needs additional verification |
| Stripe API error | Check Stripe status page |
| Webhook not received | Verify Stripe webhook configuration |
Handling Refunds
Refunds are initiated through the Stripe Dashboard, not Hygate. When a refund is processed:
- Stripe sends a
charge.refundedwebhook to Hygate - Hygate updates the payment status to REFUNDED
- The refund appears in your Payments list with REFUNDED status
Hygate does not currently support initiating refunds from the admin interface. Use Stripe Dashboard for all refund operations.
Exporting Payments
Export your payment data for accounting or reporting purposes:
- Go to Payments
- Apply your desired filters
- Click Export to download a CSV file
CSV export includes all columns visible in the payments table, filtered by your current selection.
Payment Visibility
| Role | Can View Payments |
|---|---|
| Administrator | Yes — all payments |
| Operator | Yes — all payments |
Both roles can view the complete payment history. However, only administrators can configure Stripe settings.
Troubleshooting
Payment Not Appearing
| Check | Action |
|---|---|
| Stripe webhook | Verify webhook is configured at /api/stripe/webhook |
| Webhook events | Confirm events are subscribed: payment_intent.succeeded |
| Stripe logs | Check Stripe Dashboard → Developers → Logs |
| Refresh | Click the refresh button to reload |
Duplicate Payments
Hygate uses idempotency keys to prevent duplicate charges. If you see duplicate Payment records in Hygate, check:
- Whether two webhooks were sent for the same intent
- Whether the guest refreshed the payment page
Failed Payments
If you see a pattern of failed payments:
- Check Stripe System Status
- Verify Stripe API keys in Settings → Stripe
- Check the webhook endpoint configuration
- Review Stripe logs for error details
Payment Amount Incorrect
Check the door's price and duration override settings, or the device's usage plan price. Payment amount is determined at the time of session creation based on the current configuration.