OCPP 1.6 Payment Flow - How Charging Sessions Actually Get Billed
The full payment lifecycle in OCPP 1.6: from RFID tap to invoice. Covers authorization, metering, tariffs, CDRs, roaming via OCPI, and backend billing logic.
OCPP 1.6 Payment Flow. How Charging Sessions Actually Get Billed
This is the question everyone eventually asks: "How does the money part work?" The short answer: OCPP handles authorization and metering. It doesn't handle billing, tariffs, or payment processing. Those live entirely in your backend. Let's trace the whole flow from card tap to invoice.
The big picture
Rendering diagram...
Authorization
When a user identifies themselves, the charger sends Authorize. The backend checks: Is this user registered? Account active? Valid payment method on file? Within their prepaid balance?
Rendering diagram...
The idTag is just a string. Could be an RFID UID, a QR code reference, an app-generated token. OCPP doesn't care what it represents. your backend maps it to a real user and a real payment method.
Metering during the session
StartTransaction gives you a transactionId. MeterValues stream in during the session. Your backend records everything:
| Timestamp | Energy (Wh) | Power (kW) | Current (A) |
|---|---|---|---|
| 14:30 | 0 | 0 | 0 |
| 14:31 | 180 | 11.0 | 16.1 |
| 14:35 | 1,100 | 11.2 | 16.3 |
| 14:45 | 3,000 | 10.8 | 15.9 |
| 15:30 | 9,500 | 6.2 | 9.0 |
| 16:00 | 12,000 | 0 | 0 |
StopTransaction arrives with the final meter reading and a reason code.
Tariff calculation
This is where OCPP steps back entirely. The protocol doesn't define tariffs. Your backend applies them based on whatever pricing model you've set up.
Rendering diagram...
Example: session delivers 12 kWh over 90 minutes. Tariff = 0.02/min idle after 60 minutes.
| Component | Calculation | Cost |
|---|---|---|
| Energy | 12 kWh x $0.30 | $3.60 |
| Idle fee | 30 min x $0.02 | $0.60 |
| Total | $4.20 |
The idle fee exists to push drivers to move their car once charging is done. It's a real problem at busy stations. someone charges for 45 minutes and then leaves their car parked for six hours. Without an idle penalty, other users can't charge.
CDR. the formal record
After calculating cost, the backend creates a Charge Detail Record:
{
"cdrId": "CDR-20260107-001",
"userId": "user-456",
"chargerId": "CP-001",
"connectorId": 1,
"startTime": "2026-01-07T14:30:00Z",
"endTime": "2026-01-07T16:00:00Z",
"energyDelivered_kWh": 12.0,
"totalCost": 4.20,
"currency": "USD",
"tariffApplied": "standard-2026"
}
The CDR is your source of truth for invoicing, roaming settlement, regulatory reporting, and dispute resolution.
Payment processing
The CDR goes to your payment processor. Stripe, Adyen, PayPal. standard tools, nothing EV-specific.
Rendering diagram...
Many operators use pre-authorization: hold $25 on the card before the session starts, capture only the actual amount after, release the rest. This protects against non-payment but confuses users who see a large hold on their statement. Good UX means showing the hold amount and explaining what it is.
Roaming. charging on someone else's network
When a user from Network A charges on Network B's charger, the authorization and billing pass through a roaming hub. The protocol for this is OCPI (Open Charge Point Interface). separate from OCPP.
Rendering diagram...
OCPP handles charger-to-backend. OCPI handles backend-to-backend. They compose well but they're completely separate specs.
The transactionId ties it all together
From Authorize to StopTransaction to CDR to invoice. the transactionId assigned by StartTransaction is the key that links every piece. If you lose it, billing breaks. If you duplicate it, you double-bill. Get the transaction lifecycle right and the payment flow follows.
That's the full money path in OCPP 1.6. The protocol gives you authorization and raw energy data. Everything else. pricing, billing, payment, roaming. is your backend's job.