Skip to main content

Prepaid Reservations

Reservations enable real-time balance control by holding funds before consumption.

Reservation Flow

Reservation Status Lifecycle

OPEN → CONFIRMED (service consumed)
→ CANCELLED (user cancellation)
→ EXPIRED (auto-timeout)

API Endpoints

Reserve via CDR

POST /api/rest/billing/mediation/reserveCdr
Content-Type: text/plain

2024-01-15T10:30:00;SUB_001;5000;API_TOKENS;GPT-4

Response:

{
"reservationId": 12345,
"availableQuantity": 5000,
"amountWithTax": 10.00
}

Confirm Reservation

POST /api/rest/billing/mediation/confirmReservation
Content-Type: application/json

{
"reservationId": 12345
}

Response:

{
"status": "SUCCESS",
"message": "Reservation confirmed"
}

Cancel Reservation

POST /api/rest/billing/mediation/cancelReservation
Content-Type: application/json

{
"reservationId": 12345
}

Response:

{
"status": "SUCCESS",
"message": "Reservation cancelled, balance restored"
}

Auto-Expiration

Reservations automatically expire after a configurable timeout.

Configuration

Set at Provider level:

Provider.prepaidReservationExpirationDelayinMillisec = 300000  // 5 minutes

Timer Mechanism

// On reservation creation, a timer is scheduled
Timer timer = timerService.createSingleActionTimer(
provider.getPrepaidReservationExpirationDelayinMillisec(),
timerConfig);

// When timer fires
@Timeout
void reservationExpired(Timer timer) {
Reservation reservation = findById(reservationId);
if (reservation.getStatus() != CONFIRMED) {
cancelPrepaidReservation(reservation); // Auto-cancel
}
}

Counter Integration

Counter Deduction on Reserve

When a reservation is created:

  1. Counter is immediately decremented
  2. Deducted value stored in reservation.counterPeriodValues
  3. If reservation is cancelled, counter is restored
// Store counter values for later restoration
if (reservation != null) {
reservation.getCounterPeriodValues().put(
counterPeriodId,
deltaValue);
}

Counter Restoration on Cancel

// Restore all counter values
for (Entry<Long, BigDecimal> periodInfo :
reservation.getCounterPeriodValues().entrySet()) {
counterInstanceService.incrementCounterValue(
periodInfo.getKey(),
periodInfo.getValue());
}

Wallet Reservation API

For offer-based reservations (not CDR-based):

Create Reservation

POST /api/rest/billing/wallet/reservation
Content-Type: application/json

{
"sellerCode": "MAIN_SELLER",
"offerCode": "BASIC_OFFER",
"userAccountCode": "UA_001",
"subscriptionDate": "2024-01-15",
"creditLimit": 100.00
}

Update Reservation

PUT /api/rest/billing/wallet/reservation
Content-Type: application/json

{
"reservationId": 12345,
"creditLimit": 150.00
}

Cancel Reservation

DELETE /api/rest/billing/wallet/reservation/12345

Confirm Reservation

POST /api/rest/billing/wallet/reservation/confirm
Content-Type: application/json

{
"reservationId": 12345
}

Error Handling

Insufficient Balance

{
"status": "FAIL",
"errorCode": "INSUFFICIENT_BALANCE",
"message": "Insufficient balance: required $15.00, available $10.50"
}

Reservation Not Found

{
"status": "FAIL",
"errorCode": "ENTITY_NOT_FOUND",
"message": "Reservation 12345 not found"
}

Reservation Already Confirmed

{
"status": "FAIL",
"errorCode": "INVALID_STATE",
"message": "Reservation 12345 is already confirmed"
}