Payments
This guide covers the complete payment flow in ToffeePay, from creating payment sessions to handling confirmations.
Payment Flow
Available Payment Methods
ToffeePay supports the following payment methods:
- card: Traditional credit/debit card payments
- tokenized_card: Saved card tokens for returning customers
- apple_pay: Apple Pay for iOS and Safari users
- google_pay: Google Pay for Android and Chrome users
- paypal: PayPal wallet payments
- paylater: PayPal's buy now, pay later options
- venmo: Venmo wallet payments
The available payment methods are automatically displayed to users on the payment page based on their device, browser, and configured options for your game.
Create a Payment Session
Send a server-side request to create a payment session.
POST /pay.v1.PaymentService/CreateSession
Authorization: Bearer <your_api_key>
Content-Type: application/json
{
"game_id": "space_shooter",
"user_id": "player_42",
"item": {
"title": "50 Gold Coins",
"price": 499,
"currency": "USD",
"image": "data:image/png;base64,..."
},
"return_url": "mygame://payment-complete",
"wallet_enabled": true // if Toffee Wallet configured and enabled
}
Parameters:
game_id: Your unique game identifieruser_id: Unique identifier for the playeritem: The item being purchasedtitle: Display name of the itemprice: Price in cents (e.g., 499 = $4.99)currency: Three-letter currency code (USD, EUR, etc.)image: Base64-encoded image or URL
return_url: Deep link to return to after paymentwallet_enabled: Boolean flag that specifies whether Toffee Wallet should be enabled or disabled for the session
Response
{
"id": "sess_abc123",
"url": "https://pay.toffeepay.com/sess_abc123"
}
Payment Statuses
Session Statuses
Payment sessions can have the following statuses:
pending: Payment session created but not yet paidpaid: Payment successfully completedfailed: Payment attempt failedcancelled: Payment session was cancelledexpired: Payment session has expired
Payment Statuses
Individual payment objects (created when processing a session) have these statuses:
processing: Payment is being processed by the payment providerauthorized: Payment has been authorized but not yet capturedsucceeded: Payment completed successfullycancelled: Authorized payment was cancelled before capturefailed: Payment processing failed
Status Flow:
-
Session starts as
pending -
When payment begins, a Payment object is created with status
processing -
Payment can transition to:
authorized: Payment authorized but not capturedsucceeded: Payment completed successfully (either automatically or via CompletePayment)cancelled: Authorized payment was cancelled via CancelPaymentfailed: Payment processing failed
Note: Whether payments automatically proceed from
authorizedtosucceededor require manual completion via CompletePayment is configured during game setup. -
Session status updates based on final payment status:
paid(if payment succeeded)cancelled(if session was cancelled manually via CancelSession or after 3 cancelled payment attempts)failed(after 3 failed payment attempts)
Timestamp Fields
Both sessions and payments include relevant timestamp fields:
Session timestamps:
created_at: When the session was createdpaid_at: When the session was successfully paid (if applicable)failed_at: When the session failed (if applicable)expired_at: When the session expired (if applicable)cancelled_at: When the session was cancelled (if applicable)
Payment timestamps:
created_at: When payment processing beganauthorized_at: When payment was authorized (if applicable)succeeded_at: When payment completed successfully (if applicable)cancelled_at: When payment was cancelled (if applicable)failed_at: When payment failed (if applicable)
Webhook Events
ToffeePay sends webhooks for the following payment-related events:
Session Events
session.created: When a payment session is createdsession.paid: When a session is successfully paidsession.failed: When payment attempt related to this session failssession.expired: When a session expires without paymentsession.cancelled: When session is cancelled by user
Payment Events
payment.created: When a payment is created and processing beginspayment.authorized: When payment is authorized but not yet capturedpayment.succeeded: When payment completes successfullypayment.cancelled: When an authorized payment is cancelledpayment.failed: When payment attempt fails
See the Webhooks page for implementation details and signature verification.
Open the Payment Page
Open the returned payment url in the browser or webview.
The user will:
- View the item details and total price
- Pay using Apple Pay, Google Pay, or other supported methods
- Be redirected back to your game via the
return_url
Internationalization
You can customize the payment page language by adding a locale query parameter to the payment URL:
https://pay.toffeepay.com/sess_abc123?locale=es
The payment page will display all text (buttons, labels, error messages) in the specified language.
Handle Payment Notifications
ToffeePay notifies you of payment events through two methods:
1. Webhooks
When a payment is completed, ToffeePay sends a signed webhook to your backend. See the Webhooks page for detailed implementation.
Sample Payload:
{
"id": "550e8400-e29b-41d4-a716-446655440000",
"event": "payment.succeeded",
"timestamp": "2023-06-01T12:05:00Z",
"data": {
"payment_id": "pay_xyz789"
}
}
2. Return URL
After payment, the user is redirected to your specified return_url. This is typically a custom deep link that your game handles.
Example:
"return_url": "mygame://payment-complete"
Cancel a Payment Session
You can cancel a payment session that is still in pending status:
POST /pay.v1.PaymentService/CancelSession
Authorization: Bearer <your_api_key>
Content-Type: application/json
{
"id": "sess_abc123"
}
Response:
{}
When a session is cancelled:
- The session status changes to
cancelled - The
cancelled_attimestamp is set - A
session.cancelledwebhook event is sent - The session cannot be paid and the payment URL becomes invalid
Check Session Status
To confirm session status (especially when handling return URLs), you can use either endpoint:
GetSession (Full Details)
POST /pay.v1.PaymentService/GetSession
Authorization: Bearer <your_api_key>
Content-Type: application/json
{
"id": "sess_abc123"
}
Response:
{
"id": "sess_abc123",
"status": "paid",
"payment_id": "pay_xyz789",
"user_id": "player_42",
"game_id": "space_shooter",
"item": {
"title": "50 Gold Coins",
"price": 499,
"currency": "USD"
},
"tax": {
"amount": 50
},
"created_at": "2023-06-01T12:00:00Z",
"paid_at": "2023-06-01T12:05:00Z"
}
GetSessionStatus (Status Only)
POST /pay.v1.PaymentService/GetSessionStatus
Authorization: Bearer <your_api_key>
Content-Type: application/json
{
"id": "sess_abc123"
}
Response:
{
"id": "sess_abc123",
"status": "paid"
}
Status handling:
- If
statusispaid, grant the items and show success - If
statusispending, show a waiting screen - If
statusisfailed,cancelledorexpired, inform the user and offer to retry
Complete Payment
When your game wants to control when an authorized payment is captured, use CompletePayment. This is useful for scenarios where you want to authorize payment but only capture it after fulfilling the order (e.g., confirming item availability).
POST /pay.v1.PaymentService/CompletePayment
Authorization: Bearer <your_api_key>
Content-Type: application/json
{
"id": "pay_xyz789"
}
Parameters:
id: The payment ID to complete
Response:
{}
Cancel Payment
Cancel an authorized payment before it's captured. This releases the hold on the customer's payment method.
POST /pay.v1.PaymentService/CancelPayment
Authorization: Bearer <your_api_key>
Content-Type: application/json
{
"id": "pay_xyz789"
}
Parameters:
id: The payment ID to cancel
Response:
{}
Get Payment Details
Retrieve details of a payment:
POST /pay.v1.PaymentService/GetPayment
Authorization: Bearer <your_api_key>
Content-Type: application/json
{
"id": "pay_xyz789"
}
Response:
{
"id": "pay_xyz789",
"session_id": "sess_abc123",
"status": "succeeded",
"amount": 499,
"currency": "USD",
"method": "apple_pay",
"details": "50 Gold Coins",
"created_at": "2023-06-01T12:05:00Z",
"succeeded_at": "2023-06-01T12:05:30Z"
}
List Sessions
Retrieve historical sessions for audit and analytics:
POST /pay.v1.PaymentService/ListSessions
Authorization: Bearer <your_api_key>
Content-Type: application/json
{
"game_id": "space_shooter",
"user_id": "player_42",
"status": "paid",
"limit": 50,
"offset": 0
}
Response:
{
"sessions": [
{
"id": "sess_abc123",
"status": "paid",
"payment_id": "pay_xyz789",
"user_id": "player_42",
"game_id": "space_shooter",
"item": {
"title": "50 Gold Coins",
"price": 499,
"currency": "USD"
},
"tax": {
"amount": 50
},
"created_at": "2023-06-01T12:00:00Z",
"paid_at": "2023-06-01T12:05:00Z"
}
],
"total": 1,
"has_more": false
}
List Payments
Retrieve historical payments (successful transactions only):
POST /pay.v1.PaymentService/ListPayments
Authorization: Bearer <your_api_key>
Content-Type: application/json
{
"game_id": "space_shooter",
"user_id": "player_42",
"limit": 50,
"offset": 0
}
Response:
{
"payments": [
{
"id": "pay_xyz789",
"session_id": "sess_abc123",
"status": "succeeded",
"amount": 499,
"currency": "USD",
"method": "apple_pay",
"details": "50 Gold Coins",
"created_at": "2023-06-01T12:05:00Z",
"succeeded_at": "2023-06-01T12:05:30Z"
}
],
"total": 1,
"has_more": false
}
Tax Handling
ToffeePay automatically calculates and applies taxes based on the customer's location. Tax information is included in session responses when the session is completed.
Tax Structure
The tax object in session responses contains:
amount: Tax amount in cents (same currency as the item price)
Example
For a $4.99 item with $0.50 tax:
{
"item": {
"price": 499,
"currency": "USD"
},
"tax": {
"amount": 50
}
}
The customer will be charged the total amount (item price + tax = $5.49 in this example).
Note: Tax calculations are handled automatically during payment processing. The tax amount is determined at the time of payment based on the customer's billing address.
Image Requirements
Item images must meet these requirements:
- Format: PNG, JPG, WebP
- Size: ≤ 300 KB recommended
- Encoding: Base64 with MIME prefix or direct URL
Base64 format:
data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAA...
URL format:
https://yourgame.com/images/gold-coins.png
Best Practices
- Authentication: See Authentication for API key management
- Idempotency: Use Idempotency-Key header to prevent duplicate operations
- Webhook verification: Always verify webhook signatures (see Webhooks)
- Error handling: Implement proper error handling for all payment statuses
- User experience: Show loading states and clear success/failure messages
- Security: Use HTTPS for all webhook endpoints and return URLs
- Testing: Use sandbox mode for development and testing
Error Handling
Common payment errors and how to handle them:
invalid_game_id: Check your game registration and API key (see Authentication)invalid_currency: Ensure currency code is supported (USD, EUR, etc.)invalid_price: Price must be a positive integer in centsinvalid_image: Check image format and size requirementssession_expired: Payment session has expired, create a new oneinsufficient_funds: User's payment method was declined
Testing
Use ToffeePay's sandbox environment for testing:
- Use sandbox API keys (different from production)
- Test with various payment methods and failure scenarios
- Verify webhook delivery and signature verification
- Test return URL handling in your game client
Test Cards
Use these test card numbers in sandbox mode for testing payments:
Mastercard
- Number:
5100 0600 0000 0002 - Expiry:
12/2029 - CVC:
737
Visa
- Number:
4400 0000 0000 0008 - Expiry:
03/2030 - CVC:
737