This guide will walk you through the process of integrating Chiron Payments into your application. The integration involves both backend and frontend components working together to process payments securely.
The Chiron payment flow consists of two main parts:
The first step is to generate a transaction token from your backend server. This token authorizes a payment of a specific amount.
// Using Node.js with Express
const express = require('express');
const axios = require('axios');
const app = express();
app.use(express.json());
app.post('/create-payment-token', async (req, res) => {
try {
// Get the amount from the request
const { amount } = req.body;
// Generate a unique ID for this transaction
// Call Chiron API to get a token
const response = await axios.post('https://api.chironapp.io/api/transactions/token/generate', {
amount: amount,
}, {
headers: {
'Content-Type': 'application/json',
'Authorization': 'Bearer YOUR_API_KEY'
}
});
// Return the token to your frontend
res.json({
token: response.data.id,
amount: amount
});
} catch (error) {
console.error('Error generating token:', error);
res.status(500).json({ error: 'Failed to generate payment token' });
}
});
app.listen(3000, () => {
console.log('Server running on port 3000');
});
# Using Python with Flask
from flask import Flask, request, jsonify
import requests
import time
app = Flask(__name__)
@app.route('/create-payment-token', methods=['POST'])
def create_payment_token():
try:
// Get the amount from the request
data = request.get_json()
amount = data.get('amount')
// Generate a unique ID for this transaction
transaction_id = str(int(time.time()))
// Call Chiron API to get a token
response = requests.post(
'https://api.chironapp.io/api/transactions/token/generate',
json={
'amount': amount
},
headers={
'Content-Type': 'application/json',
'Authorization': 'Bearer YOUR_API_KEY'
}
)
response_data = response.json()
// Return the token to your frontend
return jsonify({
'token': response_data['id'],
'amount': amount
})
except Exception as e:
print(f'Error generating token: {str(e)}')
return jsonify({'error': 'Failed to generate payment token'}), 500
if __name__ == '__main__':
app.run(debug=True, port=3000)
<?php
// Using PHP
header('Content-Type: application/json');
$data = json_decode(file_get_contents('php://input'), true);
$amount = $data['amount'] ?? null;
if (!$amount) {
http_response_code(400);
echo json_encode(['error' => 'Amount is required']);
exit;
}
// Generate a unique ID for this transaction
// Call Chiron API to get a token
$ch = curl_init('https://api.chironapp.io/api/transactions/token/generate');
curl_setopt($ch, CURLOPT_RETURNTRANSFER, true);
curl_setopt($ch, CURLOPT_POST, true);
curl_setopt($ch, CURLOPT_POSTFIELDS, json_encode([
'amount' => $amount
]));
curl_setopt($ch, CURLOPT_HTTPHEADER, [
'Content-Type: application/json',
'Authorization: Bearer YOUR_API_KEY'
]);
$response = curl_exec($ch);
$httpCode = curl_getinfo($ch, CURLINFO_HTTP_CODE);
curl_close($ch);
if ($httpCode !== 200) {
http_response_code(500);
echo json_encode(['error' => 'Failed to generate payment token']);
exit;
}
$responseData = json_decode($response, true);
// Return the token to your frontend
echo json_encode([
'token' => $responseData['id'],
'amount' => $amount
]);
?>
Once you have the token from your backend, you can use it in your frontend to process the payment.
<!-- Add this to your HTML head section -->
<script src="https://payment.chironapp.io/chiron-checkout.js"></script>
<form id="payment-form">
<div class="form-group">
<label for="card-name">Cardholder Name</label>
<input type="text" id="card-name" placeholder="John Smith" required>
</div>
<div class="form-group">
<label for="card-number">Card Number</label>
<input type="text" id="card-number" placeholder="4242 4242 4242 4242" required>
</div>
<div class="row">
<div class="col">
<div class="form-group">
<label for="expiry">Expiration Date</label>
<input type="text" id="expiry" placeholder="MM/YY" required>
</div>
</div>
<div class="col">
<div class="form-group">
<label for="cvc">CVC</label>
<input type="text" id="cvc" placeholder="123" required maxlength="4">
</div>
</div>
</div>
<!-- Billing Address Fields -->
<div class="form-group">
<label for="address">Street Address</label>
<input type="text" id="address" placeholder="123 Main St" required>
</div>
<div class="row">
<div class="col">
<div class="form-group">
<label for="city">City</label>
<input type="text" id="city" placeholder="San Francisco" required>
</div>
</div>
<div class="col">
<div class="form-group">
<label for="state">State</label>
<input type="text" id="state" placeholder="CA" required>
</div>
</div>
</div>
<div class="form-group">
<label for="zip">ZIP Code</label>
<input type="text" id="zip" placeholder="94103" required>
</div>
<button type="submit">Pay Now</button>
<div id="payment-message" class="error" style="display: none;"></div>
<div id="success-message" class="success" style="display: none;"></div>
</form>
document.addEventListener('DOMContentLoaded', function() {
const form = document.getElementById('payment-form');
const paymentMessage = document.getElementById('payment-message');
const successMessage = document.getElementById('success-message');
// Format card number with spaces
const cardNumberInput = document.getElementById('card-number');
cardNumberInput.addEventListener('input', function(e) {
let value = e.target.value.replace(/\s+/g, '');
if (value.length > 0) {
value = value.match(new RegExp('.{1,4}', 'g')).join(' ');
}
e.target.value = value;
});
// Format expiry date
const expiryInput = document.getElementById('expiry');
expiryInput.addEventListener('input', function(e) {
let value = e.target.value.replace(/\D/g, '');
if (value.length > 2) {
value = value.substring(0, 2) + '/' + value.substring(2, 4);
}
e.target.value = value;
});
form.addEventListener('submit', async function(e) {
e.preventDefault();
// Hide any previous messages
paymentMessage.style.display = 'none';
successMessage.style.display = 'none';
// Get form values
const name = document.getElementById('card-name').value;
const cardNumber = document.getElementById('card-number').value.replace(/\s+/g, '');
const expiry = document.getElementById('expiry').value.replace('/', '');
const cvc = document.getElementById('cvc').value;
const address = document.getElementById('address').value;
const city = document.getElementById('city').value;
const state = document.getElementById('state').value;
const zip = document.getElementById('zip').value;
// Validate form
if (!validateForm()) {
return;
}
try {
// First, get a payment token from your backend
const tokenResponse = await fetch('/create-payment-token', {
method: 'POST',
headers: {
'Content-Type': 'application/json'
},
body: JSON.stringify({
amount: 1.00 // Replace with your actual amount
})
});
const tokenData = await tokenResponse.json();
if (!tokenData.token) {
throw new Error('Failed to generate payment token');
}
// Define callback
const callback = {
onError: (error) => {
paymentMessage.textContent = error.ssl_result_message || 'An error occurred during payment processing.';
paymentMessage.style.display = 'block';
},
onDeclined: async (error) => {
console.error(error);
paymentMessage.textContent = error.errorMessage || 'Payment was declined.';
paymentMessage.style.display = 'block';
},
onApproval: async (response) => {
try {
successMessage.textContent = 'Payment succeeded.';
successMessage.style.display = 'block';
form.reset();
} catch (err) {
paymentMessage.textContent = err.error || 'An error occurred after approval.';
paymentMessage.style.display = 'block';
}
}
};
// Process payment using ChironPayment.pay() - see detailed explanation below
window.ChironPayment.pay(
{
ssl_amount: tokenData.amount.toString(),
ssl_transaction_type: 'ccsale',
ssl_txn_auth_token: tokenData.token,
ssl_exp_date: expiry,
ssl_cvv2cvc2: cvc,
ssl_card_number: cardNumber,
ssl_get_token: 'Y',
ssl_add_token: 'Y',
ssl_first_name: name.split(' ')[0],
ssl_last_name: name.split(' ')[1] || '',
ssl_avs_zip: zip,
ssl_city: city,
ssl_state: state,
ssl_avs_address: address,
},
callback
);
} catch (error) {
paymentMessage.textContent = 'Failed to initialize payment: ' + (error.message || 'Unknown error');
paymentMessage.style.display = 'block';
}
});
function validateForm() {
// Basic validation
const cardNumber = document.getElementById('card-number').value.replace(/\s+/g, '');
if (cardNumber.length < 13 || cardNumber.length > 19) {
paymentMessage.textContent = 'Please enter a valid card number.';
paymentMessage.style.display = 'block';
return false;
}
const expiry = document.getElementById('expiry').value;
if (!expiry.match(/^\d{2}\/\d{2}$/)) {
paymentMessage.textContent = 'Please enter a valid expiration date (MM/YY).';
paymentMessage.style.display = 'block';
return false;
}
const cvc = document.getElementById('cvc').value;
if (cvc.length < 3 || cvc.length > 4) {
paymentMessage.textContent = 'Please enter a valid CVC code.';
paymentMessage.style.display = 'block';
return false;
}
return true;
}
});
The core of the payment processing is handled by the ChironPayment.pay() method. This method takes two parameters: a payment configuration object and a callback object.
The payment configuration object contains all the necessary details for processing the payment:
window.ChironPayment.pay(
{
// Payment amount from the token response
ssl_amount: tokenData.amount.toString(),
// Transaction type - 'ccsale' for credit card sale
ssl_transaction_type: 'ccsale',
// The token received from your backend
ssl_txn_auth_token: tokenData.token,
// Card details
ssl_exp_date: expiry, // Format: MMYY (no slash)
ssl_cvv2cvc2: cvc, // Security code
ssl_card_number: cardNumber, // Card number (no spaces)
// Token options
ssl_get_token: 'Y', // Get a token for this card
ssl_add_token: 'Y', // Add the token to the customer's saved cards
// Cardholder information
ssl_first_name: name.split(' ')[0],
ssl_last_name: name.split(' ')[1] || '',
// Billing address for AVS verification
ssl_avs_zip: zip,
ssl_city: city,
ssl_state: state,
ssl_avs_address: address,
},
callback
);
ssl_amount: The payment amount as a string (e.g., "10.99")ssl_transaction_type: Type of transaction, usually "ccsale" for credit card salesssl_txn_auth_token: The token generated by your backendssl_exp_date: Card expiration date in MMYY format (no slash)ssl_cvv2cvc2: Card verification code (CVC/CVV)ssl_card_number: Credit card number with no spacesssl_get_token: Set to "Y" to tokenize the card for future usessl_add_token: Set to "Y" to save the token to the customer's profilessl_first_name & ssl_last_name: Cardholder's namessl_avs_zip, ssl_city, ssl_state, ssl_avs_address: Billing address for AVS (Address Verification System) checksThe callback object defines how your application will handle different payment outcomes:
const callback = {
// Called when a system error occurs
onError: (error) => {
paymentMessage.textContent = error.ssl_result_message || 'An error occurred during payment processing.';
paymentMessage.style.display = 'block';
},
// Called when the payment is declined
onDeclined: async (error) => {
console.error(error);
paymentMessage.textContent = error.errorMessage || 'Payment was declined.';
paymentMessage.style.display = 'block';
},
// Called when the payment is approved
onApproval: async (response) => {
try {
successMessage.textContent = 'Payment succeeded.';
successMessage.style.display = 'block';
form.reset();
// You might want to redirect to a success page or perform other actions
// such as updating order status in your database
} catch (err) {
paymentMessage.textContent = err.error || 'An error occurred after approval.';
paymentMessage.style.display = 'block';
}
}
};
The payment configuration object supports additional parameters for more advanced use cases:
ssl_invoice_number: Your internal invoice numberssl_description: Description of the transactionssl_customer_code: Your internal customer identifierssl_email: Customer's email addressssl_phone: Customer's phone numberssl_country: Customer's countryYou can test your integration using the following test card details:
onApproval callback will be triggered.
Before going live with your integration, make sure to: