Customer Payment Methods
The payment methods system allows customers to store and manage their payment cards for use with Levy Fleets services. This guide covers how administrators can manage payment methods on behalf of customers through the dashboard, as well as how the system handles cards behind the scenes.
How Payment Methods Work
Storage Architecture
Payment methods are stored in two locations for security and efficiency:
- Stripe - The actual payment method data (card number, expiry, CVC) is securely stored by Stripe
- Levy Database - Only non-sensitive metadata is stored locally:
- Stripe payment method ID
- Card brand (Visa, Mastercard, etc.)
- Last 4 digits
- Card type
- Default status
This architecture ensures PCI compliance while enabling efficient local queries.
PCI Compliance
Levy Fleets never handles or stores raw card data. All card collection uses Stripe Elements or the Stripe mobile SDK, ensuring the highest level of payment security.
Payment Method Flow
When a customer adds a card:
Customer Initiates
Customer adds card in the mobile app or an admin adds it through the dashboard
SetupIntent Created
Stripe SetupIntent is created to securely collect card details
Card Details Collected
Card details are collected by Stripe Elements (never touches our servers)
Stripe Validates
Stripe validates and tokenizes the card
SetupIntent Completes
SetupIntent completes successfully
Payment Method Attached
Payment method is attached to the Stripe customer
Metadata Saved
Card metadata (brand, last4, etc.) is saved to the payment_methods table
Database Schema
Payment Methods Table
| Column | Type | Description |
|---|---|---|
id | uuid | Primary key |
customer_uuid | uuid | Reference to customers table |
stripe_payment_method_id | text | Stripe's payment method ID (pm_xxx) |
type | text | Payment method type (usually "card") |
brand | text | Card brand (visa, mastercard, amex, etc.) |
last4 | text | Last 4 digits of card number |
is_default | boolean | Whether this is the default payment method |
created_at | timestamptz | When the card was added |
updated_at | timestamptz | Last modification time |
Managing Payment Methods in the Dashboard
Accessing Payment Methods
- Navigate to Dashboard > Customers
- Click on a customer to view their profile
- Find the Payment Methods section
Viewing Cards
The payment methods section displays:
- Card brand and last 4 digits (e.g., "VISA **** 4242")
- Date the card was added
- Default badge for the primary card
- Delete button for each card
Adding a Card
Click Add Card
Click the + Add Card button in the Payment Methods section
Stripe Form Opens
A modal opens with the Stripe Elements form for secure card entry
Enter Card Details
Enter card details directly into the secure Stripe form
Save Card
Click Save Card to validate and save the payment method
Card Added
The modal closes and the card list refreshes to show the new card
Test Mode Indicator
When adding cards for test accounts:
- A yellow banner shows "Test Mode Active"
- Use Stripe test card numbers (see below)
- No real charges will occur
Deleting a Card
- Click the trash icon next to the card
- Confirm the deletion in the dialog
- Card is removed from both Stripe and the database
Deletion Behavior
When you delete a payment method, it's removed from both Stripe and the local database. If the deleted card was the default, the oldest remaining card automatically becomes the new default.
Test Mode
When Test Mode is Active
Test mode is automatically enabled when:
- Super Admin Users - Any user with
super_adminrole - Internal Test Emails - Customers with
@levyelectric.comemail
Test Mode Behavior
In test mode:
- Uses test Stripe API keys
- Cards are stored in Stripe's test environment
- No real charges occur
- Setup intents use test endpoints
- Dashboard shows "Test Mode Active" indicator
Test Card Numbers
| Card Number | Description |
|---|---|
4242 4242 4242 4242 | Success |
4000 0000 0000 0002 | Card declined |
4000 0000 0000 9995 | Insufficient funds |
4000 0027 6000 3184 | Requires authentication |
5555 5555 5555 4444 | Mastercard |
3782 822463 10005 | American Express |
Use any valid future expiry date and any 3-digit CVC (4 digits for Amex).
Default Payment Method
Automatic Default Selection
When a customer adds their first payment method, it automatically becomes the default. This ensures there's always a usable payment method for:
- Wallet top-ups
- Auto top-up charges
- Payment retries
How Default is Determined
- First card added is default
- If default card is deleted, oldest remaining card becomes default
How Default is Used
The default payment method is used for:
- Auto Top-Up - Automatic wallet replenishment
- Payment Retries - Recovering negative wallet balances
- Off-Session Charges - Any charge initiated without customer presence
Integration with Payment Retry System
Payment methods play a critical role in the automatic payment retry system for recovering negative wallet balances.
How Payment Methods Are Used for Retries
When a customer's wallet goes negative, the system creates a payment retry job that:
- Tries the default payment method first
- Cycles through other cards ordered by creation date (oldest first)
- Tracks which methods have been tried to avoid duplicate attempts within the same scheduling window
- Resets the cycle when moving to a new day or week
Payment Method Cycling Order
1. Default payment method (is_default = true)
2. Oldest non-default card
3. Second oldest non-default card
4. ... continues through all cards
Importance of Multiple Cards
Customers with multiple payment methods have higher payment recovery rates because:
- If one card is declined, others are tried automatically
- Different cards may have different credit limits
- Bank-specific issues (temporary holds, fraud alerts) won't block payment entirely
Encourage Backup Cards
Encourage customers to add backup payment methods. Display prompts in the mobile app after a declined transaction, or offer small wallet bonuses for adding a second card.
Webhook Integration
Payment methods can also be created via Stripe webhooks when customers add cards through the mobile app:
setup_intent.succeeded
When a SetupIntent completes from the mobile app:
- System looks up the customer by Stripe ID
- Retrieves payment method details from Stripe
- Saves card metadata to the database
- Sets as default if it's the first card
payment_intent.succeeded
When a payment completes with a new payment method:
- System checks if payment method already exists
- If not, saves the new payment method
- Updates customer's default if needed
Mobile App Integration
Adding Cards from Mobile
The mobile app uses Stripe's native SDK:
- App requests ephemeral key from the server
- Stripe CustomerSheet or PaymentSheet is presented
- Customer enters card details in native Stripe UI
- On success,
setup_intent.succeededwebhook fires - Payment method is saved to database
Mobile Payment Actions
| Action | Description |
|---|---|
add-funds | Manually top up wallet with selected amount |
redeem-promo | Apply promotional code for wallet credits |
toggle-auto-topup | Enable/disable automatic wallet top-up |
update-auto-topup-amount | Change the auto top-up amount |
Security Considerations
PCI Compliance
The payment methods system maintains PCI compliance by:
- Never handling raw card data - All card collection uses Stripe Elements/SDK
- Storing only tokens - Only Stripe payment method IDs are stored
- Masking card numbers - Only last 4 digits are saved
- Secure transmission - All API calls use HTTPS
- Webhook verification - All Stripe webhooks are signature-verified
Access Control
Payment method operations require authenticated users with appropriate roles:
| Operation | Required Roles |
|---|---|
| List | All admin roles |
| Add | All admin roles |
| Delete | All admin roles |
Deletion Behavior
When deleting a payment method:
- Stripe Detachment - Card is detached from Stripe customer
- Local Deletion - Record removed from database
- Default Reassignment - If default was deleted, next oldest becomes default
- Both Environments Tried - System tries both live and test Stripe to ensure cleanup
Troubleshooting
Common Issues
"Failed to initialize Stripe form"
Cause: Setup intent creation failed
Solutions:
- Check Stripe API keys are correct
- Verify customer has a Stripe customer ID
- Check Stripe dashboard for rate limits
Card not appearing after adding
Cause: Registration failed after SetupIntent
Solutions:
- Check browser console for errors
- Verify webhook is receiving
setup_intent.succeeded - Check database for orphaned payment methods
"No payment method on file" during auto top-up
Cause: Customer has no payment methods or no default
Solutions:
- Check
payment_methodstable for customer - Verify at least one card has
is_default = true - Add a payment method if none exist
Test mode not working
Cause: Test keys not configured
Solutions:
- Verify
STRIPE_TEST_SECRET_KEYis set - Verify
STRIPE_TEST_PUBLISHABLE_KEYis set - Ensure user is super_admin or customer has @levyelectric.com email
Diagnostic Queries
List customer's payment methods
SELECT
pm.id,
pm.brand,
pm.last4,
pm.is_default,
pm.created_at,
c.email
FROM payment_methods pm
JOIN customers c ON c.id = pm.customer_uuid
WHERE c.id = 'customer-uuid-here'
ORDER BY pm.created_at;
Find customers without payment methods
SELECT
c.id,
c.email,
c.full_name,
c.stripe_customer_id
FROM customers c
LEFT JOIN payment_methods pm ON pm.customer_uuid = c.id
WHERE pm.id IS NULL
AND c.stripe_customer_id IS NOT NULL
ORDER BY c.created_at DESC
LIMIT 50;
Check for duplicate payment methods
SELECT
stripe_payment_method_id,
COUNT(*) as count
FROM payment_methods
GROUP BY stripe_payment_method_id
HAVING COUNT(*) > 1;
Best Practices
For Operators
- Encourage multiple cards - Customers with backup cards have fewer payment failures
- Monitor declined cards - Follow up with customers whose cards are failing
- Use test mode - Always test card flows with test cards before production
For Customer Support
- Verify before adding - Confirm customer identity before adding payment methods
- Explain the process - Help customers understand why cards are needed
- Document issues - Record any card-related problems for troubleshooting
What's Next?
- Stripe Setup - Configure Stripe integration
- Automatic Refunds - How automatic refunds work
- Damage Charges - Charging customers for damage
Payment Methods Ready
With payment methods properly configured, customers can seamlessly pay for rides and top up their wallets. Monitor your payment success rates and follow up with customers who have payment issues to maintain a healthy revenue stream.