Skip to main content

Top-Up and Recharge System

The OmniCRM Top-Up system provides a self-service prepaid recharge portal for customers to add credit or extend service validity via the Self-Care Portal . This feature is commonly used for:

  • Mobile data services - Prepaid SIM cards and data-only services
  • Hotspot services - WiFi hotspot dongles and portable internet devices
  • Fixed wireless services - Prepaid internet access

Overview

The top-up system allows customers to purchase additional days of service through a streamlined, multi-step checkout process with integrated Stripe payment processing.

Key Features:

  • Self-service customer portal (no staff intervention required)
  • Flexible duration selection (1-30 days)
  • Real-time usage display before purchase
  • Stripe-powered secure payment processing
  • Automatic refunds if top-up fails
  • Invoice and transaction generation
  • Provisioning system integration for service activation

Access the Top-Up Portal

The top-up portal is accessed via a public URL that customers can visit without logging into the CRM:

How Customers Access It:

  • Direct link sent via SMS when balance is low
  • QR code on printed materials
  • Link on self-care portal
  • Shared via customer support

The portal automatically detects the customer's service based on their requesting IP address or IMSI.

Top-Up Process

The top-up flow consists of 4 steps:

Step 1: Data Selection

Customers select how many days of service they want to purchase.

Interface:

  • Slider control - Select 1 to 30 days
  • Live price calculation - Shows total cost based on selection
  • Expiry date display - Calculates and shows when service will expire
  • Current usage display - Shows remaining balance/expiry before top-up

Example Display:

Pricing Configuration:

  • Price per day is configured via environment variable REACT_APP_TOPUP_PRICE_PER_DAY
  • Default: $10 USD per day
  • Currency is set via REACT_APP_CURRENCY_CODE

Step 2: Billing Information

Customers provide their contact details for the transaction:

  • First Name
  • Last Name
  • Email Address

This information is used for:

  • Invoice generation
  • Payment receipt email
  • Transaction records
  • Refund processing (if needed)

Step 3: Payment

Secure payment processing via Stripe Elements.

Payment Methods Supported:

  • Credit cards (Visa, Mastercard, Amex)
  • Debit cards
  • Digital wallets (Apple Pay, Google Pay) if enabled in Stripe

Security Features:

  • PCI-compliant Stripe integration
  • No card details stored in OmniCRM
  • 3D Secure authentication support
  • Encrypted payment transmission

Payment Flow:

  1. Stripe Elements form displayed with card input
  2. Customer enters payment details
  3. Payment Intent created for the exact amount
  4. Card charged immediately
  5. Payment success/failure handled

::: note ::: title Note :::

If the payment succeeds but the top-up provisioning fails (e.g., network error, OCS unreachable), the system automatically initiates a full refund to the customer's payment method. :::

Step 4: Completion

Success Screen:

Your service has been extended. New expiry date: 17 Jan 2025

Receipt sent to: <customer@example.com> Transaction ID: TXN-123456

Failure Screen:

If top-up fails, the system displays an error and automatically processes a refund:

We were unable to complete your top-up. Your payment has been refunded.

Error: Unable to connect to billing system

Please try again or contact support.

Backend Processing

When a customer completes payment, the following happens automatically:

1. Payment Validation

The system validates:

  • Payment Intent status is succeeded
  • Payment amount matches selected days (days × price_per_day)
  • Payment Intent hasn't been processed before (prevents double top-up)

2. Top-Up Operation

- API endpoint: POST /oam/topup_dongle
- Validates service_uuid and IMSI
- Calls OCS/CGRateS to add balance
- Creates provisioning job (play_topup_hotspot)

3. Record Creation

The system creates multiple database records:

  • HotspotTopup record - Tracks the top-up transaction
    • payment_intent_id
    • service_uuid
    • imsi
    • days purchased
    • topup_amount
    • status (Success/Failed/Refunded)
  • Transaction record - Financial transaction
    • Title: "Hotspot Topup - 7 Days"
    • Amount: topup_amount (positive)
    • Linked to service_id and customer_id
  • Invoice record - Payment invoice
    • Contains the top-up transaction
    • Marked as paid immediately
    • Payment reference: Stripe payment_intent_id
  • Payment transaction - Offsetting credit transaction
    • Title: "Payment for [Invoice Title]"
    • Amount: topup_amount (negative - credit)
    • Links invoice payment to customer account

4. Provisioning Job

A provisioning job is created with playbook play_topup_hotspot which:

  • Connects to OCS/CGRateS API
  • Adds balance to the account
  • Extends expiry date
  • Creates activity log entry
  • Sends confirmation notification (if configured)

The API waits for provisioning to complete (polling with 0.2s intervals, max 25 iterations) before returning success to the customer.

5. Automatic Refund on Failure

If any step fails after payment:

if topup_provisioning_failed:
refund = stripe.Refund.create(
payment_intent=payment_intent_id,
reason='requested_by_customer' # Automatic system refund
)
status_message = "Topup Failed. Refunding payment..."

The refund is processed automatically and the customer is notified on-screen.

API Endpoints

Top-Up Endpoint

POST /oam/topup_dongle
Content-Type: application/json

{
"service_uuid": "123e4567-e89b-12d3-a456-426614174000",
"imsi": "310120123456789",
"days": 7,
"payment_intent_id": "pi_1234567890abcdef",
"topup_amount": 70.00
}

Response (Success):

{
"result": "OK",
"status": 200,
"provision_id": 456,
"payment_intent_id": "pi_1234567890abcdef",
"service_uuid": "123e4567-e89b-12d3-a456-426614174000",
"invoice_id": 789
}

Response (Failure):

{
"result": "Failed",
"Reason": "OCS connection timeout",
"status": 500
}

Validation Checks:

  • All required fields present (service_uuid, imsi, days, payment_intent_id, topup_amount)
  • topup_amount matches days: topup_amount × 100 == days × 1000 (in cents)
  • Payment Intent exists in Stripe
  • Payment Intent amount matches: payment_intent.amount == topup_amount × 100
  • Payment Intent status is succeeded
  • Payment Intent not already processed (checks HotspotTopup table)

Usage Endpoint

Retrieves current usage and service information for the customer:

GET /oam/usage

Response:

{
"imsi": "310120123456789",
"service": {
"service_uuid": "123e4567-e89b-12d3-a456-426614174000",
"service_name": "Mobile Data - 0412345678",
"service_status": "Active"
},
"balance": {
"expiry": "2025-01-10T23:59:59Z",
"unlimited": true
},
"requestingIp": "203.0.113.45"
}

This endpoint uses the requesting IP address to identify the customer's service automatically.

Configuration

Environment Variables

Configure these in the OmniCRM-UI .env file:

# Top-Up Portal Configuration
REACT_APP_TOPUP_PRICE_PER_DAY=10
REACT_APP_CURRENCY_CODE=AUD
REACT_APP_SELF_CARE_NAME="YourCompany"

# Stripe Configuration
REACT_APP_STRIPE_PUBLISHABLE_KEY=pk_live_...

Stripe Configuration

The top-up system uses Stripe Payment Intents:

  1. Enable Payment Intents in your Stripe Dashboard
  2. Configure Webhook to receive payment status updates (optional but recommended)
  3. Set up payment methods (cards, wallets, etc.)
  4. Test mode - Use test keys for development
# Development
REACT_APP_STRIPE_PUBLISHABLE_KEY=pk_test_...

# Production
REACT_APP_STRIPE_PUBLISHABLE_KEY=pk_live_...

Playbook Configuration

The provisioning playbook play_topup_hotspot.yaml must be configured to:

  • Accept days variable
  • Connect to OCS/CGRateS API
  • Add balance to account
  • Update service expiry date

Example playbook structure:

- name: Top up hotspot service
hosts: localhost
tasks:
- name: Add balance to OCS
uri:
url: "{{ ocs_api_url }}/add_balance"
method: POST
body:
imsi: "{{ imsi }}"
days: "{{ days }}"
service_uuid: "{{ service_uuid }}"

Low Balance Notifications

The system can send automatic notifications when customer balance is low:

SMS Notifications:

When triggered by OCS events (Action_Balance_Low, Action_Balance_Out, Action_Balance_Expired):

Email Notifications:

Configured in the OCS/CGRateS action plans to send balance alerts.

Notification Triggers:

  • Action_Balance_Low - Balance below threshold (e.g., 2 days remaining)
  • Action_Balance_Out - Balance exhausted
  • Action_Balance_Expired - Service expired

Each notification includes the top-up portal link for easy customer access.

Troubleshooting

Common Issues

"Payment system unavailable"

  • Cause: Stripe library failed to load or invalid publishable key
  • Fix:
    • Check REACT_APP_STRIPE_PUBLISHABLE_KEY is set correctly
    • Verify Stripe account is active
    • Check browser console for JavaScript errors

"Top-up failed. Refunding payment..."

  • Cause: Provisioning job failed (OCS unreachable, playbook error, etc.)
  • Fix:
    • Check provisioning logs: GET /crm/provision/provision_id/<id>
    • Verify OCS/CGRateS API is accessible
    • Review playbook play_topup_hotspot.yaml for errors
    • Check Ansible logs

"Payment intent already processed"

  • Cause: Customer attempting to reuse same payment (e.g., refresh after success)
  • Fix: This is working as designed to prevent double billing. Customer should start a new top-up if needed.

"Payment intent amount does not match"

  • Cause: Mismatch between UI calculation and backend validation
  • Fix:
    • Verify REACT_APP_TOPUP_PRICE_PER_DAY matches backend expectation (default $10)
    • Check currency configuration is consistent
    • Clear browser cache and retry

Monitoring Top-Ups

View Top-Up Records:

Query the HotspotTopup table to see all top-up attempts:

SELECT
hotspot_topup_id,
service_uuid,
days,
topup_amount,
status,
payment_intent_id,
created
FROM hotspot_topup
WHERE status = 'Failed'
ORDER BY created DESC;

Check Provisioning Status:

GET /crm/provision/provision_id/<provision_id>

Shows the detailed status of the top-up provisioning job.

Stripe Dashboard:

Monitor payments, refunds, and failed transactions in your Stripe Dashboard at <https://dashboard.stripe.com>

Security Considerations

Payment Security:

  • All card data handled by Stripe (PCI Level 1 compliant)
  • No sensitive payment data stored in OmniCRM database
  • Payment Intents prevent unauthorized charges
  • Amount validation on both client and server side

Fraud Prevention:

  • Duplicate payment Intent detection prevents double billing
  • IP address tracking for usage correlation
  • IMSI validation ensures top-up goes to correct service
  • Automatic refunds limit financial exposure

Access Control:

  • Top-up portal is public (by design - customers need access)
  • Usage endpoint requires valid service identification (IP or IMSI)
  • Backend validation prevents arbitrary service top-ups
  • Admin can view all top-up records via CRM interface

Best Practices

For Operators:

  1. Test refund flow - Regularly test failure scenarios to ensure refunds work
  2. Monitor failed top-ups - Set up alerts for high failure rates
  3. Keep playbooks simple - Top-up playbooks should be fast and reliable
  4. Verify OCS connectivity - Ensure OCS API is always accessible
  5. Review pricing - Update REACT_APP_TOPUP_PRICE_PER_DAY as needed

For Customers:

  1. Bookmark the top-up URL - Quick access when needed
  2. Save low balance notifications - SMS contains direct link
  3. Keep email updated - Receipts sent to email on file
  4. Check expiry before travel - Top up before leaving coverage area

For Developers:

  1. Handle Stripe webhooks - Implement webhook handlers for payment status updates
  2. Implement idempotency - Always check payment_intent_id before processing
  3. Log extensively - Top-up failures need detailed troubleshooting info
  4. Test error paths - Verify refund automation works correctly
  5. Monitor performance - Provisioning polling should complete in &lt;5 seconds
  • payments_process - General payment processing
  • concepts_provisioning - Provisioning system overview
  • integrations_stripe - Stripe integration details
  • payments_transaction - Transaction management
  • payments_invoices - Invoice handling