Step 1: Include the SDK
Add our JavaScript SDK to your website. The SDK handles all Pay Later interactions, UI components, and API communications:
<!-- Include the Appfinity Pay Later SDK -->
<script src="https://appfinitystore.com/js/appfinity-sdk.js"></script>
<!-- Optional: Include CSS for default styling -->
<link rel="stylesheet" href="https://appfinitystore.com/css/paylater-ui.css">
Step 2: Initialize the SDK
Initialize the SDK with your platform credentials:
Appfinity.init({
platformId: "SLOTGAME",
baseUrl: "appfinitystore.com",
apiKey: "SLOT_eueue_your_key"
});
const startFlow = () => {
Appfinity.startFlow({
email: "user@example.com",
deductAmount: 50,
callbackFunction: (res) => {
console.log("PayLater callback", res);
if(res.success) {
// redirect to success page
} else {
// redirect to failure page
}
}
});
}
Note: The deductAmount parameter is optional and is used when you want to immediately purchase coins from the Appfinity wallet. When provided, the system will attempt to deduct the specified amount from the user's wallet during Step 1 of the flow. The response of this deduction operation will be received in the callbackFunction, allowing you to handle success or failure scenarios accordingly.
Expected Response Format
The callbackFunction(res) will receive a response object with the following structure:
// Success Response (Top Up - Step 3)
{
type: 'top-up',
step: 3,
success: true,
message: 'TopUp successful',
data: {
success: true,
message: "Wallet balance deducted successfully",
data: {
wallet: {
amountDeducted: 50,
currency: "USD",
description: "SDK deduction",
email: "user@example.com",
eventId: 98,
newBalance: 250,
platformId: "your_platform_id",
previousBalance: 300,
transactionAt: "2025-09-23T11:32:58.947Z",
userId: "your_user_id"
}
}
}
}
// Error Response
{
success: false,
message: "Insufficient wallet balance",
error: {
code: "INSUFFICIENT_FUNDS",
details: "Current balance: $25.50, Required: $50.00"
}
}
// Other possible error codes:
// "INVALID_AMOUNT" - Amount is invalid or negative
// "USER_NOT_FOUND" - User account not found
// "WALLET_LOCKED" - User wallet is temporarily locked
// "NETWORK_ERROR" - Connection or server error
Step 3: Add Pay Later Button
Add the Pay Later button to your checkout page:
<button onclick="startFlow()" id="pay-later-btn" class="paylater-button">
<span>Pay Later</span>
<small>Get instant approval</small>
</button>
Callback Types
The type field in the callback can be "step", "deduction", or "top-up".
To get a callback for Step 3 (card save), check response.type == "step" and response.step == 3.
For deductions, response.type == "deduction". For top up, response.type == "top-up".
// Examples of handling callback types
Appfinity.startFlow({
email: "user@example.com",
callbackFunction: (response) => {
// Step 3: card save completed
if (response.type === 'step' && response.step === 3) {
console.log('Card saved / Step 3 completed');
// Handle post-card-save logic
}
// Deduction event (wallet deduction during Step 1)
else if (response.type === 'deduction') {
console.log('Wallet deduction event:', response);
// Handle deduction success/failure
}
// Top Up flow completed
else if (response.type === 'top-up') {
console.log('Top Up successful:', response);
// Handle top-up success
}
}
});
// Note: If your integration wraps callback payload under `data`,
// you can equivalently check:
// response.data && response.data.type === 'step' && response.data.step === 3
// response.data && response.data.type === 'deduction'
// response.data && response.data.type === 'top-up'
Top-Up Flow Function
The startTopupThenFlow function is designed specifically for displaying the top-up interface to users.
This function opens the top-up modal where users can add funds to their wallet, and provides a callback mechanism
to handle the top-up completion events.
Appfinity.startTopupThenFlow({
email: config.email,
deductAmount: 50,
callbackFunction: (res) => {
console.log("PayLater TopUp callback", res);
if(res.success) {
// redirect to success page
fetchDueBalance(); // Refresh balance
} else {
// redirect to failure page
}
setButtonLoading('pay-later-btn', false);
}
});
How it works:
- Display Top-Up UI: Opens the top-up interface in a modal overlay
- User Interaction: User selects top-up amount and completes payment
- Callback Execution: Upon completion, the callback function receives the result
- Balance Update: Successful top-ups automatically update the user's wallet balance
- Flow Continuation: Optionally continues the subscription flow if user category requirements are met
Demo Button Implementation
Here's a complete example of how to create a button that triggers the top-up flow:
<!-- HTML Button -->
<button onclick="handleTopupClick()" id="topup-btn" class="topup-button">
Top Up Wallet
</button>
<script>
function handleTopupClick() {
const button = document.getElementById('topup-btn');
const originalText = button.innerHTML;
// Show loading state
button.innerHTML = 'Loading...';
button.disabled = true;
// Trigger the top-up flow
Appfinity.startTopupThenFlow({
email: config.email,
deductAmount: 50,
callbackFunction: (res) => {
console.log("TopUp callback", res);
// Reset button state
button.innerHTML = originalText;
button.disabled = false;
if(res.success) {
// Handle success - redirect or update UI
alert('Top-up successful!');
fetchDueBalance(); // Refresh balance
} else {
// Handle failure - show error message
alert('Top-up failed: ' + res.message);
}
}
});
}
</script>
<!-- Optional CSS for styling -->
<style>
.topup-button {
background: linear-gradient(135deg, #667eea 0%, #764ba2 100%);
color: white;
border: none;
padding: 12px 24px;
border-radius: 6px;
cursor: pointer;
font-size: 16px;
font-weight: 500;
transition: all 0.3s;
}
.topup-button:hover {
transform: translateY(-2px);
box-shadow: 0 4px 12px rgba(102, 126, 234, 0.4);
}
.topup-button:disabled {
opacity: 0.6;
cursor: not-allowed;
transform: none;
}
</style>
Step 4: Optional Parameters
The startFlow function can contain additional user parameters for better user experience:
// The startFlow can contain other parameters like first_name, last_name, date_of_birth, address, city, zip, country
Appfinity.startFlow({
email: "user@example.com",
first_name: "John",
last_name: "Doe"
}); // etc
Step 5: Wallet API Endpoints
Use these wallet API endpoints to manage user balances and transactions:
// Get wallet balance
fetch('/v1/wallet?email=user@example.com', {
method: 'GET',
headers: {
'Content-Type': 'application/json',
'x-api-key': 'your_api_key',
'x-platform-id': 'your_platform_id'
}
})
.then(response => response.json())
.then(data => console.log('Balance:', data.balance));
// Deduct from wallet
fetch('/v1/wallet/deduct', {
method: 'POST',
headers: {
'Content-Type': 'application/json',
'x-api-key': 'your_api_key',
'Idempotency-Key': `deduct-${Date.now()}-${Math.random()}`
},
body: JSON.stringify({
email: "user@example.com",
amount: 50.00,
description: 'Game purchase',
metadata: {
orderId: 'order_123',
productId: 'game_coins'
}
})
})
.then(response => response.json())
.then(data => {
if (data.success) {
console.log('Deduction successful:', data.newBalance);
} else {
console.error('Deduction failed:', data.message);
}
});
// Expected Response:
{
"success": true,
"message": "Wallet deduction successful",
"data": {
"transaction_id": "txn_abc123def456",
"amount_deducted": 50.00,
"previous_balance": 200.00,
"new_balance": 150.00,
"currency": "USD",
"description": "Game purchase",
"timestamp": "2024-01-15T10:30:00Z"
}
}
Step 6: Get Transaction History
Retrieve wallet transaction history for user account management:
// Get wallet transaction history
fetch('/v1/wallet/transactions', {
method: 'GET',
headers: {
'Content-Type': 'application/json',
'x-api-key': 'your_api_key',
'x-platform-id': 'your_platform_id'
}
})
.then(response => response.json())
.then(data => {
if (data.success) {
console.log('Transaction history:', data.transactions);
// Display transactions in UI
data.transactions.forEach(transaction => {
console.log(`${transaction.type}: ${transaction.amount} - ${transaction.description}`);
});
} else {
console.error('Failed to get transactions:', data.message);
}
});
// Expected Response:
{
"success": true,
"data": {
"transactions": [
{
"id": "txn_abc123def456",
"type": "debit",
"amount": -50.00,
"balance_after": 150.00,
"description": "Game purchase",
"metadata": {
"orderId": "order_123",
"productId": "game_coins"
},
"timestamp": "2024-01-15T10:30:00Z",
"status": "completed"
},
{
"id": "txn_def456ghi789",
"type": "credit",
"amount": 100.00,
"balance_after": 200.00,
"description": "Wallet top-up",
"timestamp": "2024-01-14T15:20:00Z",
"status": "completed"
}
],
"pagination": {
"current_page": 1,
"total_pages": 3,
"total_transactions": 25,
"per_page": 10
}
}
}
// Required headers for all wallet API requests:
// - Content-Type: application/json
// - x-api-key: Your platform API key
// - x-platform-id: Your platform ID
// - Idempotency-Key: Unique key for POST requests (prevents duplicate transactions)