asciisd/cybersource-hosted-checkout-laravel
Laravel integration for CyberSource Secure Acceptance Hosted Checkout. Includes a Blade component (and optional Vue component) to render the hosted payment form, plus configurable credentials via config/env for a fluent checkout setup.
Installation
composer require asciisd/cybersource-hosted-checkout-laravel
Publish the config file:
php artisan vendor:publish --provider="Asciisd\CybersourceHostedCheckout\CybersourceHostedCheckoutServiceProvider" --tag="config"
Configuration
Update .env with your CyberSource credentials:
CYBERSOURCE_MERCHANT_ID=your_merchant_id
CYBERSOURCE_KEY=your_key
CYBERSOURCE_SECRET=your_secret
CYBERSOURCE_ENV=test # or 'live'
First Use Case: Redirect to Hosted Checkout
use Asciisd\CybersourceHostedCheckout\Facades\CybersourceHostedCheckout;
$checkoutUrl = CybersourceHostedCheckout::createCheckout([
'amount' => 100.00,
'currency' => 'USD',
'orderId' => 'order_123',
'returnUrl' => route('checkout.return'),
'cancelUrl' => route('checkout.cancel'),
'customer' => [
'id' => 'customer_456',
'name' => 'John Doe',
'email' => 'john@example.com',
],
]);
return redirect()->to($checkoutUrl);
Handling Return
Add routes for returnUrl and cancelUrl:
Route::get('/checkout/return', [CheckoutController::class, 'handleReturn']);
Route::get('/checkout/cancel', [CheckoutController::class, 'handleCancel']);
Pre-Checkout
orderId for tracking.Post-Return
public function handleReturn(Request $request)
{
$response = CybersourceHostedCheckout::verifyCheckout($request->all());
if ($response->isSuccessful()) {
// Mark order as paid, update inventory, etc.
Order::find($response->orderId)->paid();
} else {
// Handle failure (e.g., refund, notify customer)
}
}
Webhook Handling (Advanced) Use CyberSource’s transaction notifications to sync payments in real-time:
Route::post('/cybersource/webhook', [WebhookController::class, 'handle']);
public function handle(Request $request)
{
$payload = $request->validate([
'notification' => 'required|string',
'signature' => 'required|string',
]);
$isValid = CybersourceHostedCheckout::verifyWebhook($payload['notification'], $payload['signature']);
if ($isValid) {
// Process the transaction (e.g., update order status)
}
}
Laravel Cashier Sync: Attach CyberSource transactions to Laravel Cashier subscriptions:
$user->newSubscription('premium', $plan)
->create($token)
->syncPayment($response->transactionId);
Local Testing:
Use the test environment and CyberSource’s sandbox for mock transactions.
Dynamic Fields: Extend the checkout with custom fields (e.g., shipping options):
$checkoutUrl = CybersourceHostedCheckout::createCheckout([
// ... default fields ...
'customData' => [
'shippingOption' => 'express',
'giftMessage' => 'Happy Birthday!',
],
]);
Signature Mismatch in Webhooks
CYBERSOURCE_SECRET in .env and ensure the payload is unaltered. Use dd($payload) to debug.Redirect URI Mismatch
returnUrl that doesn’t match your app’s routes.https://yourdomain.com/checkout/return) and verify the cancelUrl is accessible.Currency/Amount Formatting
100.0 vs. 100.00).'amount' => (float) $cartTotal,
Idempotency
orderId is reused.orderId for each checkout or implement idempotency keys in your backend.Enable Logging
Add to config/cybersource.php:
'debug' => env('CYBERSOURCE_DEBUG', false),
Check storage/logs/laravel.log for raw API responses.
Test Mode Quirks
transactionIds (e.g., 1234567890123456).CYBERSOURCE_ENV=test for development; switch to live only after thorough testing.Custom Templates
Override CyberSource’s hosted page by extending the createCheckout payload:
'template' => [
'name' => 'custom_template',
'data' => ['logoUrl' => asset('images/logo.png')],
],
Pre/Post-Processing Hooks
Bind events in AppServiceProvider:
public function boot()
{
CybersourceHostedCheckout::extend(function ($checkout) {
$checkout->onBeforeRedirect(function ($payload) {
// Modify payload (e.g., add tracking)
$payload['customData']['trackingId'] = Str::uuid()->toString();
});
});
}
Multi-Currency Support
Dynamically set currency based on user locale:
'currency' => app()->getLocale() === 'fr' ? 'EUR' : 'USD',
Pro Tip: Bookmark the CyberSource API Reference for field definitions and error codes (e.g., 104 = invalid merchant ID).
How can I help you explore Laravel packages today?