Guide on setting up a payment gateway for CyberSource in a Laravel
Published: 2023-10-03 19:44:11

Setting up a payment gateway like CyberSource in a Laravel and Vue.js project involves several steps. I'll provide a high-level overview of the process and then provide some code snippets and descriptions for each step.


Step 1: Install the CyberSource PHP SDK
To get started, you'll need to install the CyberSource PHP SDK using Composer. You can do this by running the following command in your Laravel project directory:

```
composer require cybersource/sdk
```

Step 2: Create a CyberSource configuration file
Next, you'll need to create a configuration file to store your CyberSource API credentials and other settings. You can create a new file called `cybersource.php` in your Laravel `config` directory with the following contents:

```php
return [
    'merchant_id' => env('CYBERSOURCE_MERCHANT_ID'),
    'transaction_key' => env('CYBERSOURCE_TRANSACTION_KEY'),
    'api_version' => 'v1',
    'sandbox' => env('CYBERSOURCE_SANDBOX', true),
];
```

In this file, you'll need to replace the `CYBERSOURCE_MERCHANT_ID` and `CYBERSOURCE_TRANSACTION_KEY` values with your own API credentials. You can also set the `CYBERSOURCE_SANDBOX` value to `false` if you're using a production account.

Step 3: Create a CyberSource controller
Next, you'll need to create a new controller in Laravel to handle the payment requests. You can create a new file called `CybersourceController.php` in your Laravel `app/Http/Controllers` directory with the following contents:

```php
<?php

namespace App\Http\Controllers;

use Illuminate\Http\Request;
use Cybersource\Api\Client\Configuration;
use Cybersource\Api\PaymentsApi;
use Cybersource\Model\Address;
use Cybersource\Model\AggregatorInformation;
use Cybersource\Model\AmountDetails;
use Cybersource\Model\BillTo;
use Cybersource\Model\Card;
use Cybersource\Model\CreatePaymentRequest;
use Cybersource\Model\CustomerInformation;
use Cybersource\Model\DeviceInformation;
use Cybersource\Model\MerchantInformation;
use Cybersource\Model\MerchantDescriptor;
use Cybersource\Model\OrderInformation;
use Cybersource\Model\PaymentInformation;
use Cybersource\Model\PointOfSaleInformation;
use Cybersource\Model\Ptsv2paymentsClientReferenceInformation;
use Cybersource\Model\Ptsv2paymentsProcessingInformation;
use Cybersource\Model\Ptsv2paymentsProcessingInformationAuthorizationOptions;
use Cybersource\Model\Ptsv2paymentsShippingInformation;

class CybersourceController extends Controller
{
    public function index()
    {
        return view('cybersource');
    }

    public function submitPayment(Request $request)
    {
        // Set up CyberSource API configuration
        $config = new Configuration();
        $config->setMerchantId(config('cybersource.merchant_id'));
        $config->setTransactionKey(config('cybersource.transaction_key'));
        $config->setDebug(config('cybersource.sandbox'));

        // Set up payment request data
        $request = new CreatePaymentRequest([
            'clientReferenceInformation' => new Ptsv2paymentsClientReferenceInformation([
                'code' => 'test_payment'
            ]),
            'processingInformation' => new Ptsv2paymentsProcessingInformation([
                'commerceIndicator' => 'internet'
            ]),
            'orderInformation' => new OrderInformation([
                'amountDetails' => new AmountDetails([
                    'totalAmount' => $request->input('amount'),
                    'currency' => 'USD'
                ])
            ]),
            'paymentInformation' => new PaymentInformation([
                'card' => new Card([
                    'expirationYear' => $request->input('exp_year'),
                    'expirationMonth' => $request->input('exp_month'),
                    'number' => $request->input('card_number'),
                    'securityCode' => $request->input('cvv')
                ])
            ]),
            'billTo' => new BillTo([
                'firstName' => $request->input('first_name'),
                'lastName' => $request->input('last_name'),
                'address1' => $request->input('address1'),
                'address2' => $request->input('address2') ?: '',
                'postalCode' => $request->input('zip'),
                'locality' => $request->input('city'),
                'administrativeArea' => $request->input('state'),
                'country' => $request->input('country')
            ]),
            'aggregatorInformation' => new AggregatorInformation([
                'subMerchant' => false,
                'name' => 'Acme LLC',
                'aggregatorId' => '123456789'
            ])
        ]);

        // Submit payment request to CyberSource API
        $api_instance = new PaymentsApi($config);
        try {
            $result = $api_instance->createPayment($request);
            return response()->json(['success' => true, 'message' => 'Payment processed successfully']);
        } catch (Exception $e) {
            return response()->json(['success' => false, 'message' => $e->getMessage()]);
        }
    }
}
```

In this controller, we're using the CyberSource PHP SDK to create and submit a payment request to the CyberSource API. The `index()` method returns a view that contains the payment form, and the `submitPayment()` method handles the form submission and sends the payment request to the API.

Step 4: Create a Vue.js component for the payment form
Next, you'll need to create a Vue.js component to handle the payment form. You can create a new file called `Cybersource.vue` in your Laravel `resources/js/components` directory with the following contents:

```html
<template>
  <div>
    <form @submit.prevent="submit">
      <div>
        <label for="first_name">First Name</label>
        <input type="text" id="first_name" v-model="firstName" required>
      </div>
      <div>
        <label for="last_name">Last Name</label>
        <input type="text" id="last_name" v-model="lastName" required>
      </div>
      <div>
        <label for="address1">Address 1</label>
        <input type="text" id="address1" v-model="address1" required>
      </div>
      <div>
        <label for="address2">Address 2</label>
        <input type="text" id="address2" v-model="address2">
      </div>
      <div>
        <label for="city">City</label>
        <input type="text" id="city" v-model="city" required>
      </div>
      <div>
        <label for="state">State</label>
        <input type="text" id="state" v-model="state" required>
      </div>
      <div>
        <label for="zip">Zip Code</label>
        <input type="text" id="zip" v-model="zip" required>
      </div>
      <div>
        <label for="country">Country</label>
        <input type="text" id="country" v-model="country" required>
      </div>
      <div>
        <label for="card_number">Card Number</label>
        <input type="text" id="card_number" v-model="cardNumber" required>
      </div>
      <div>
        <label for="exp_month">Expiration Month</label>
        <input type="text" id="exp_month" v-model="expMonth" required>
      </div>
      <div>
        <label for="exp_year">Expiration Year</label>
        <input type="text" id="exp_year" v-model="expYear" required>
      </div>
      <div>
        <label for="cvv">CVV</label>
        <input type="text" id="cvv" v-model="cvv" required>
      </div>
      <div>
        <label for="amount">Amount</label>
        <input type="text" id="amount" v-model="amount" required>
      </div>
      <button type="submit">Submit Payment</button>
    </form>

    <div v-if="processing">
      Processing payment...
    </div>

    <div v-if="message">
      {{ message }}
    </div>
  </div>
</template>

<script>
export default {
  data() {
    return {
      firstName: '',
      lastName: '',
      address1: '',
      address2: '',
      city: '',
      state: '',
      zip: '',
      country: '',
      cardNumber: '',
      expMonth: '',
      expYear: '',
      cvv: '',
      amount: '',
      processing: false,
      message: ''
    };
  },
  methods: {
    submit() {
      this.processing = true;

      axios.post('/cybersource/submit-payment', {
        first_name: this.firstName,
        last_name: this.lastName,
        address1: this.address1,
        address2: this.address2,
        city: this.city,
        state: this.state,
        zip: this.zip,
        country: this.country,
        card_number: this.cardNumber,
        exp_month: this.expMonth,
        exp_year: this.expYear,
        cvv: this.cvv,
        amount: this.amount
      })
      .then(response => {
        this.processing = false;
        if (response.data.success) {
          this.message = response.data.message;
        } else {
          this.message = response.data.message;
        }
      })
      .catch(error => {
        this.processing = false;
        this.message = error.response.data.message;
      });
    }
  }
};
</script>
```

In this component, we're using Vue.js to render the payment form and handle form submission. When the user submits the form, we're sending an AJAX request to the Laravel controller using Axios.

Step 5: Add routes and views
Finally, you'll need to add routes and views to your Laravel application to display the payment form and handle form submission. You can add a new route to your `web.php` file like so:

```php
Route::get('/cybersource', [CybersourceController::class, 'index']);
Route::post('/cybersource/submit-payment', [CybersourceController::class, 'submitPayment']);
```

And you can create a new view called `cybersource.blade.php` in your Laravel `resources/views` directory with the following contents:

```html
@extends('layouts.app')

@section('content')
  <cybersource></cybersource>

  <script src="{{ mix('js/app.js') }}"></script>
@endsection
```

This view includes the Vue.js component and the necessary JavaScript files.

That's it! With these steps completed, you should now have a working payment gateway for CyberSource in your Laravel and Vue.js project.