Payment Tokens
Stripe Payment Tokens with Vrio API - Integration Guide
Overview
This guide explains how to use Stripe.js with Elements to generate payment tokens and send them to Vrio's API for payment processing. The Vrio platform supports modern confirmation tokens, traditional payment method tokens, and legacy source tokens.
Supported Token Types
Vrio's Stripe gateway supports the following token types:
1. Confirmation Tokens (Recommended)
- Format:
ctoken_xxxxxxxxxxxx
- Benefits: Enhanced security, better 3D Secure support, future-proof, allows two-step confirmation
2. Payment Method Tokens
- Format:
pm_xxxxxxxxxxxx
- Benefits: Widely supported, established pattern, better UX than legacy tokens
3. Source Tokens (Legacy)
- Format:
src_xxxxxxxxxxxx
ortok_xxxxxxxxxxxx
- Note: Still supported but not recommended for new integrations
Frontend Implementation with Stripe.js
For detailed implementation examples and code samples, please refer to Stripe's official documentation:
Confirmation Tokens (Recommended)
- Documentation: Stripe Payment Element Guide
- Integration: Two-Step Confirmation Flow
- Token Creation: Use
stripe.createConfirmationToken()
to generate confirmation tokens
Payment Method Tokens
- Documentation: Stripe Payment Element Guide
- Integration: Accept a Payment with Payment Element
- Token Creation: Use
stripe.createPaymentMethod()
with Payment Element to generate payment method tokens
Legacy Source Tokens
For backward compatibility, you can still use legacy card tokens:
- Card Tokens API: Create a Card Token
- JavaScript Reference: stripe.createToken()
Implementation Example
Here's a complete working example of how to implement Stripe payment tokens with Vrio:
<!DOCTYPE html>
<html>
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>Stripe Payment Tokens Example</title>
<script src="https://js.stripe.com/v3/"></script>
<style>
body {
font-family: Arial, sans-serif;
max-width: 600px;
margin: 0 auto;
padding: 20px;
}
.form-group {
margin-bottom: 20px;
}
label {
display: block;
margin-bottom: 5px;
font-weight: bold;
}
input, select {
width: 100%;
padding: 10px;
border: 1px solid #ccc;
border-radius: 4px;
box-sizing: border-box;
}
#payment-element, #payment-method-element, #card-element {
padding: 10px;
border: 1px solid #ccc;
border-radius: 4px;
background-color: white;
}
button {
background-color: #007cba;
color: white;
padding: 12px 20px;
border: none;
border-radius: 4px;
cursor: pointer;
font-size: 16px;
margin-bottom: 10px;
}
button:disabled {
background-color: #ccc;
cursor: not-allowed;
}
.error {
color: #e74c3c;
margin-top: 5px;
}
.success {
color: #27ae60;
margin-top: 5px;
}
.info {
background-color: #e8f4fd;
border: 1px solid #bee5eb;
border-radius: 4px;
padding: 10px;
margin-bottom: 20px;
}
.section {
border: 1px solid #ddd;
padding: 20px;
margin-bottom: 20px;
border-radius: 4px;
}
.section h3 {
margin-top: 0;
}
</style>
</head>
<body>
<h1>Stripe Payment Tokens Example</h1>
<div class="info">
<strong>Note:</strong> This example demonstrates creating different types of Stripe payment tokens for use with the Vrio API.
</div>
<div class="section">
<h3>Configuration</h3>
<div class="form-group">
<label for="publishable-key">Stripe Publishable Key:</label>
<input type="text" id="publishable-key" placeholder="pk_test_..." required>
</div>
<div class="form-group">
<label for="token-type">Token Type:</label>
<select id="token-type" onchange="handleTokenTypeChange()">
<option value="confirmation">Confirmation Token (Recommended)</option>
<option value="payment-method">Payment Method Token</option>
<option value="legacy">Legacy Token</option>
</select>
</div>
<button onclick="initializeStripe()">Initialize Stripe</button>
<div id="init-status"></div>
</div>
<div class="section">
<h3>Customer Information</h3>
<div class="form-group">
<label for="cardholder-name">Cardholder Name:</label>
<input type="text" id="cardholder-name" value="John Doe" required>
</div>
<div class="form-group">
<label for="email">Email:</label>
<input type="email" id="email" value="[email protected]" required>
</div>
</div>
<div class="section">
<h3>Payment Information</h3>
<div id="payment-element-container" style="display: none;">
<label>Payment Information (Payment Element):</label>
<div id="payment-element"></div>
<div id="payment-errors" class="error"></div>
</div>
<div id="payment-method-element-container" style="display: none;">
<label>Payment Information (Payment Element):</label>
<div id="payment-method-element"></div>
<div id="payment-method-errors" class="error"></div>
</div>
<div id="card-element-container" style="display: none;">
<label>Card Information (Legacy Card Element):</label>
<div id="card-element"></div>
<div id="card-errors" class="error"></div>
</div>
</div>
<div class="section">
<h3>Create Token</h3>
<button id="create-token-button" onclick="createToken()" disabled>Create Token</button>
<div id="token-result"></div>
</div>
<script>
let stripe;
let elements;
let paymentElement;
let paymentMethodElements;
let paymentMethodElement;
let cardElement;
let isInitialized = false;
function initializeStripe() {
const publishableKey = document.getElementById('publishable-key').value.trim();
const tokenType = document.getElementById('token-type').value;
const statusDiv = document.getElementById('init-status');
if (!publishableKey) {
statusDiv.innerHTML = '<div class="error">Please enter a Stripe publishable key</div>';
return;
}
try {
// Initialize Stripe
stripe = Stripe(publishableKey);
// Clear previous elements
if (paymentElement) paymentElement.unmount();
if (paymentMethodElement) paymentMethodElement.unmount();
if (cardElement) cardElement.unmount();
// Hide all containers
document.getElementById('payment-element-container').style.display = 'none';
document.getElementById('payment-method-element-container').style.display = 'none';
document.getElementById('card-element-container').style.display = 'none';
if (tokenType === 'confirmation') {
// Create Payment Element for confirmation tokens (card only)
elements = stripe.elements({
mode: 'payment',
amount: 2000, // Amount in cents
currency: 'usd',
payment_method_types: ['card'], // Restrict to card only
setup_future_usage: 'off_session', // Match what Vrio expects
capture_method: 'manual', // This might help reduce Link options
});
paymentElement = elements.create('payment', {
layout: 'tabs',
defaultValues: {
billingDetails: {
name: '',
email: '',
}
},
wallets: {
applePay: 'never',
googlePay: 'never'
},
terms: {
card: 'never'
},
style: {
base: {
fontSize: '16px',
color: '#424770',
'::placeholder': {
color: '#aab7c4',
},
},
},
});
paymentElement.mount('#payment-element');
document.getElementById('payment-element-container').style.display = 'block';
} else if (tokenType === 'payment-method') {
// Create Payment Element for payment method tokens
paymentMethodElements = stripe.elements({
mode: 'setup',
currency: 'usd',
payment_method_types: ['card'],
setup_future_usage: 'off_session',
paymentMethodCreation: 'manual',
});
paymentMethodElement = paymentMethodElements.create('payment', {
layout: 'tabs',
defaultValues: {
billingDetails: {
name: '',
email: '',
}
},
wallets: {
applePay: 'never',
googlePay: 'never'
},
terms: {
card: 'never'
},
style: {
base: {
fontSize: '16px',
color: '#424770',
'::placeholder': {
color: '#aab7c4',
},
},
},
});
paymentMethodElement.mount('#payment-method-element');
document.getElementById('payment-method-element-container').style.display = 'block';
} else {
// Create legacy Card Element for true tok_ tokens
elements = stripe.elements();
cardElement = elements.create('card', {
style: {
base: {
fontSize: '16px',
color: '#424770',
'::placeholder': {
color: '#aab7c4',
},
},
invalid: {
color: '#e74c3c',
},
},
});
cardElement.mount('#card-element');
document.getElementById('card-element-container').style.display = 'block';
// Listen for real-time validation errors from the card Element
cardElement.on('change', ({error}) => {
const displayError = document.getElementById('card-errors');
if (error) {
displayError.textContent = error.message;
} else {
displayError.textContent = '';
}
});
}
statusDiv.innerHTML = '<div class="success">Stripe initialized successfully</div>';
document.getElementById('create-token-button').disabled = false;
isInitialized = true;
} catch (error) {
statusDiv.innerHTML = '<div class="error">Error initializing Stripe: ' + error.message + '</div>';
console.error('Stripe initialization error:', error);
isInitialized = false;
}
}
function handleTokenTypeChange() {
// Auto re-initialize when token type changes if Stripe was already initialized
if (isInitialized) {
initializeStripe();
}
}
async function createToken() {
const tokenType = document.getElementById('token-type').value;
const cardholderName = document.getElementById('cardholder-name').value;
const email = document.getElementById('email').value;
const resultDiv = document.getElementById('token-result');
const createButton = document.getElementById('create-token-button');
if (!cardholderName || !email) {
resultDiv.innerHTML = '<div class="error">Please fill in all customer information</div>';
return;
}
// Disable button during processing
createButton.disabled = true;
createButton.textContent = 'Creating Token...';
resultDiv.innerHTML = '';
try {
let token, error;
if (tokenType === 'confirmation') {
// Submit the elements first (required for confirmation tokens)
const submitResult = await elements.submit();
if (submitResult.error) {
error = submitResult.error;
} else {
// Create Confirmation Token
const result = await stripe.createConfirmationToken({
elements,
params: {
payment_method_data: {
billing_details: {
name: cardholderName,
email: email,
phone: '', // Required since we're using setup_future_usage
address: {
line1: '',
line2: '',
city: '',
state: '',
postal_code: '',
country: 'US'
}
}
}
}
});
token = result.confirmationToken;
error = result.error;
}
} else if (tokenType === 'payment-method') {
// Check if paymentMethodElements is properly initialized
if (!paymentMethodElements) {
error = { message: 'Payment Method Elements not initialized. Please click "Initialize Stripe" first.' };
} else {
// Submit the elements first (required for Payment Element)
const submitResult = await paymentMethodElements.submit();
if (submitResult.error) {
error = submitResult.error;
} else {
// Create Payment Method Token
const result = await stripe.createPaymentMethod({
elements: paymentMethodElements,
params: {
billing_details: {
name: cardholderName,
email: email,
}
}
});
token = result.paymentMethod;
error = result.error;
}
}
} else {
// Create legacy token using Card Element
const result = await stripe.createToken(cardElement, {
name: cardholderName,
address_line1: '', // Can be empty for test
address_city: '',
address_state: '',
address_zip: '',
address_country: 'US',
});
token = result.token;
error = result.error;
}
// Re-enable button
createButton.disabled = false;
createButton.textContent = 'Create Token';
if (error) {
console.error('Token creation failed:', error);
resultDiv.innerHTML = `<div class="error">Error: ${error.message}</div>`;
} else {
console.log('Token created:', token);
const tokenTypeLabels = {
'confirmation': 'Confirmation Token',
'payment-method': 'Payment Method Token',
'legacy': 'Legacy Token'
};
resultDiv.innerHTML = `
<div class="success">
<strong>Success!</strong><br>
<strong>Type:</strong> ${tokenTypeLabels[tokenType]}<br>
<strong>Token ID:</strong> <code>${token.id}</code><br>
<small>Use this ID as payment_token in your Vrio API call with payment_method_id = 15</small>
</div>
`;
}
} catch (error) {
console.error('Exception creating token:', error);
createButton.disabled = false;
createButton.textContent = 'Create Token';
resultDiv.innerHTML = `<div class="error">Error: ${error.message}</div>`;
}
}
</script>
</body>
</html>
Sending Tokens to Vrio API
Once you have obtained a payment token from Stripe.js, you can process the payment through Vrio's API.
Step 1: Configure Your Merchant Account
Ensure your Stripe merchant account is properly configured in your Vrio dashboard with the appropriate API keys and has Payment Token as an available payment method.
Step 2: Create an Order
First, create an order using Vrio's order creation endpoint ( NOTE: you can also pass the payment_token in Step 1 if you are using the process=action when creating the order ):
curl -X POST "https://api.vrio.app/orders" \
-H "Content-Type: application/json" \
-H "X-API-KEY: YOUR_API_KEY" \
-d '{
"connection_id": 1,
"campaign_id": 18,
"offers": "[{\"offer_id\":89, \"order_offer_quantity\": 1,\"order_offer_price\":0.50}]",
"email": "[email protected]",
"bill_fname": "John",
"bill_lname": "Doe",
"bill_phone": "+1234567890",
"bill_address1": "123 Main St",
"bill_city": "Anytown",
"bill_state": "NY",
"bill_zipcode": "12345",
"bill_country": "US",
"ship_address1": "123 Main St",
"ship_city": "Anytown",
"ship_state": "NY",
"ship_zipcode": "12345",
"ship_country": "US"
}'
This will return an order object with an order_id
.
Step 3: Process Payment with Token
Use the order processing endpoint with your Stripe payment token:
Confirmation Token (Recommended)
curl -X POST "https://api.vrio.app/orders/{order_id}/process" \
-H "Content-Type: application/json" \
-H "X-API-KEY: YOUR_API_KEY" \
-d '{
"payment_method_id": 15, // pass 3 for Google Pay and 4 for Apple Pay
"payment_token": "ctoken_1Nxxxxxxxxxxxxxx",
"merchant_id": 456
}'
Payment Method Token
curl -X POST "https://api.vrio.app/orders/{order_id}/process" \
-H "Content-Type: application/json" \
-H "X-API-KEY: YOUR_API_KEY" \
-d '{
"payment_method_id": 15, // pass 3 for Google Pay and 4 for Apple Pay
"payment_token": "pm_1Nxxxxxxxxxxxxxx",
"merchant_id": 456
}'
Legacy Token (Alternative)
curl -X POST "https://api.vrio.app/orders/{order_id}/process" \
-H "Content-Type: application/json" \
-H "X-API-KEY: YOUR_API_KEY" \
-d '{
"payment_method_id": 15,
"payment_token": "tok_1Nxxxxxxxxxxxxxx",
"merchant_id": 456
}'
Common Issues
"Invalid token id" Error
- Ensure you're using the correct token format (
ctoken_
,pm_
, ortok_
) - Ensure the token being passed belongs to the correct merchant in Vrio
- Verify your Stripe keys match the token's mode (test vs live)
- Check that the token was created successfully before sending to Vrio
Token Creation Fails
- Verify your Stripe publishable key is correct
- Ensure card information is valid (for Payment Method and Legacy tokens)
- For confirmation tokens, ensure Payment Element is properly configured
- Check browser console for Stripe.js errors
For additional support, consult the Stripe Testing Guide and Stripe.js Reference.
Updated 21 days ago