Authorize.net credit card payment integration using Laravel

Authorize.net is a very popular payment integration method. Let’s integrate it using Laravel. Authorize.net already provides an SDK for PHP. It is available on GitHub. This blog post example using the same GitHub SDK. Because it is Authorize.net approved library.

1. Create a sandbox account.
The tool is required for this program that is authorize.net account. Before move on live payment setup. Every developer testing on the sandbox account. So you need to create a sandbox account first. Here link of authorize.net sandbox account signup.

2. Get authorize.net API key.
Login on your sandbox accounts to access the API details. After login on the landing page under the security settings tab. Click on API Credentials & Keys.

3. Import the Authorize.Net SDK
Update your Laravel composer.json file and add the following JSON code.
These lines must under the ‘require’ array key.

"ext-curl": "*",
"authorizenet/authorizenet": ">=1.9.3",
See the screenshot.

4. Setup the integration of Laravel environment variables.

Update the Laravel services.php file under the config folder. Add the following code.

'authorize' => [
	'login' => env('MERCHANT_LOGIN_ID'),
	'key' => env('MERCHANT_TRANSACTION_KEY'),
	'env' => env('AUTH_NET_ENV')
],
See the screenshot.

Now add the authorize.net API keys details in Laravel .env file.
The following API details are just for example. So replace with correct API details.

MERCHANT_LOGIN_ID=123456789
MERCHANT_TRANSACTION_KEY=86abcdef12234
AUTH_NET_ENV=SANDBOX

5. Blog post example has divided into two parts.
One is the view that has an HTML form for the user end. PHP code for the Laravel credit card payment page. This code for the Laravel view file. Create a view in resources/views/authorizenetPayment.blade.php.

<div class="container">
			<div class="row align-items-center">
				<div class="col">
					<h1 class="mb-3 text-center">Authorize.Net Credit card payment</h1>
					
					@if (Session::has('success'))
						<div class="alert alert-success">{{ Session::get('success') }}</div>
					@endif

					@if (Session::has('error'))
						<div class="alert alert-danger">{{ Session::get('error') }}</div>
					@endif
					
					@if ($errors->any())
						<div class="alert alert-danger mb-3">
							<ul class="error-list">
								@foreach ($errors->all() as $error)
									<li>{{ $error }}</li>
								@endforeach
							</ul>
						</div>
					@endif
				
					<form method="post" action="{{ url('test-process-authorize-card-payment') }}">
						@csrf
						<div class="form-row">
							<div class="form-group col-md-6">
								<label for="cardMemberName" class="control-label">Payment Amount</label>
								
								<div class="input-group mb-3">
								  <div class="input-group-prepend">
									<span class="input-group-text">$</span>
								  </div>
								  <input type="number" class="form-control" value="100" name="amount">
								  <div class="input-group-append" >
									<span class="input-group-text">.00</span>
								  </div>
								</div>
								
							</div>
							<div class="form-group col-md-6">
								<label for="paymentMethod" class="control-label">Payment Method</label>
								<div class="col-sm-12">
									<div class="form-check form-check-inline">
									  <input class="form-check-input" type="radio" id="paymentMethod_cc" value="CC" checked="checked" name="paymentMethod">
									  <label class="form-check-label" for="paymentMethod_cc">Credit Card</label>
									</div>
									<div class="form-check form-check-inline">
									  <input class="form-check-input" type="radio" id="paymentMethod_cod" value="COD" disabled="disabled" name="paymentMethod">
									  <label class="form-check-label" for="paymentMethod_cod">Cash on delivery</label>
									</div>
								</div>
							</div>
						</div>
						<div class="form-row">
							<div class="form-group col-md-6">
								<label for="cardMemberName" class="control-label">Name on Card</label>
								<input type="text" class="form-control" id="cardMemberName" name="cardMemberName" placeholder="Narinder Singh">
								
							</div>
							<div class="form-group col-md-6">
								<label for="cardNumber" class="control-label">Card Number</label>
								<input type="text" class="form-control" id="cardNumber" name="cardNumber" placeholder="" maxlength="20">
								
							</div>
						</div>
						<div class="form-row">
							<div class="form-group col-md-6">
								<label for="cardExpiry" class="control-label">Card Expiry (YYYY-MM)</label>
								<input type="text" class="form-control" id="cardExpiry" name="cardExpiry" placeholder="2021-12" maxlength="7">
								
							</div>
							<div class="form-group col-md-6">
								<label for="cardCVV" class="control-label">Card CVV</label>
								<input type="password" class="form-control" id="cardCVV" name="cardCVV" placeholder="" maxlength="6">
								
							</div>
						</div>
						<div class="form-group row">
							<div class="col-sm-offset-4 col-sm-8">
								<button type="submit" class="btn btn-primary">Pay Now</button>
							</div>
						</div>
					</form>
				</div>
			</div>
		</div>

The second part is the controller class that will process the authorize.net payment and returns a success or failure message. Create a controller class app/Http/Controllers/AuthorizenetPayment.php

<?php

namespace App\Http\Controllers;

use Illuminate\Http\Request;
use net\authorize\api\contract\v1 as AnetAPI;
use net\authorize\api\controller as AnetController;
use Illuminate\Support\Facades\Validator;
use Illuminate\Support\Facades\Redirect;

class AuthorizenetPayment extends Controller {
    
	public function authorizeCardPayment(){
		return view('authorizenetPayment');
	}
	
	public function processAuthorizeCardPayment(Request $request){
	
		$rules = array(
			'cardMemberName' => 'required|regex:/^[a-zA-Z\s]+$/',
			'cardNumber' => 'required|min:12|max:20',
			'cardExpiry' => 'required',
			'cardCVV' => 'required|min:3|max:6',
			'amount' => 'required',
		);
		
		$validatorMesssages = array(
			'cardMemberName.required' => 'Name on credit card is required.',
			'cardNumber' => 'Credit card number is required',
			'cardExpiry' => 'Credit card expiry is required',
			'cardCVV' => 'Credit card secure code is required',
			'amount' => 'Payment amount is required',
        );
		
		$validator = Validator::make($request->all(), $rules, $validatorMesssages);
		
		if ($validator->fails()) {
		
            return redirect('test-authorize-card-payment')
				->withErrors($validator)
				->withInput();
        } else {
		
			if( $request->paymentMethod == 'CC' ){
			
				/* Create a merchantAuthenticationType object with authentication details
			  retrieved from the constants file */
			  
				$merchantAuthentication = new AnetAPI\MerchantAuthenticationType();
				
				// API and environment details.
				
				$authorize_payment_api_login_id = config('services.authorize.login');
				$authorize_payment_transaction_key = config('services.authorize.key');
				$authorize_payment_env = config('services.authorize.env');
				
				
				$merchantAuthentication->setName($authorize_payment_api_login_id);
				$merchantAuthentication->setTransactionKey($authorize_payment_transaction_key);
				
				// Set the transaction's refId
				$refId = 'ref' . time();
				$cardNumber = preg_replace('/\s+/', '', $request->cardNumber);
				$cardExpDate = $request->cardExpiry;
				$cardCVV = $request->cardCVV;
				$bill_amount = $request->amount;
				
				// Create the payment data for a credit card
				$creditCard = new AnetAPI\CreditCardType();
				$creditCard->setCardNumber($cardNumber);
				$creditCard->setExpirationDate($cardExpDate);
				$creditCard->setCardCode($cardCVV);

				// Add the payment data to a paymentType object
				$paymentOne = new AnetAPI\PaymentType();
				$paymentOne->setCreditCard($creditCard);
				
				// Create a TransactionRequestType object and add the previous objects to it
				$transactionRequestType = new AnetAPI\TransactionRequestType();
				$transactionRequestType->setTransactionType("authCaptureTransaction");
				$transactionRequestType->setAmount($bill_amount);
				$transactionRequestType->setPayment($paymentOne);
				
				// Assemble the complete transaction request
				$requests = new AnetAPI\CreateTransactionRequest();
				$requests->setMerchantAuthentication($merchantAuthentication);
				$requests->setRefId($refId);
				$requests->setTransactionRequest($transactionRequestType);

				// Create the controller and get the response
				$controller = new AnetController\CreateTransactionController($requests);
				
				if( $authorize_payment_env == 'PRODUCTION')
				$response = $controller->executeWithApiResponse(\net\authorize\api\constants\ANetEnvironment::PRODUCTION);
				else
				$response = $controller->executeWithApiResponse(\net\authorize\api\constants\ANetEnvironment::SANDBOX);
				
				if ($response != null) {
					// Check to see if the API request was successfully received and acted upon
					if ($response->getMessages()->getResultCode() == "Ok") {
						// Since the API request was successful, look for a transaction response
						// and parse it to display the results of authorizing the card
						$tresponse = $response->getTransactionResponse();

						if ($tresponse != null && $tresponse->getMessages() != null) {
						
							//echo " Successfully created transaction with Transaction ID: " . $tresponse->getTransId() . "\n";	
							// echo " Transaction Response Code: " . $tresponse->getResponseCode() . "\n";
							// echo " Message Code: " . $tresponse->getMessages()[0]->getCode() . "\n";
							// echo " Auth Code: " . $tresponse->getAuthCode() . "\n";
							// echo " Description: " . $tresponse->getMessages()[0]->getDescription() . "\n";
							
							$message_text = $tresponse->getMessages()[0]->getDescription().", Transaction ID: " . $tresponse->getTransId();
							
							$msg_type = "success_msg";
							
							/* save payment status and other values to database */
							/* send payment success email to user or website admin */
							
							
						} else {
							$message_text = 'There were some issue with the payment. Please try again later.';
							$msg_type = "error_msg";                                    

							if ($tresponse->getErrors() != null) {
								$message_text = $tresponse->getErrors()[0]->getErrorText();
								$msg_type = "error_msg";                                    
							}
							/* send payment failed email to user or website admin */
							
						}
						// Or, print errors if the API request wasn't successful
					} else {
						$message_text = 'There were some issue with the payment. Please try again later.';
						$msg_type = "error_msg";                                    

						$tresponse = $response->getTransactionResponse();

						if ($tresponse != null && $tresponse->getErrors() != null) {
							$message_text = $tresponse->getErrors()[0]->getErrorText();
							$msg_type = "error_msg";                    
						} else {
							$message_text = $response->getMessages()->getMessage()[0]->getText();
							$msg_type = "error_msg";
						}
						/* send payment failed email to user or website admin */
						
					}
				} else {
					$message_text = "No response returned. Please contact site admin.";
					$msg_type = "error_msg";
					
					/* send payment failed email to user or website admin */
				}
				
				if($msg_type == 'success_msg')
				\Session::flash('success', $message_text);
				else
				\Session::flash('error', $message_text);
				
				return Redirect::to('test-authorize-card-payment');
			}
			else{
				\Session::flash('error', "No payment method selected.");
				return Redirect::to('test-authorize-card-payment');
			}
		}
	}
}

6. How to test it?
To test and validate this code. The following code in the web.php file under the routes folder.

Route::get('test-authorize-card-payment', 'AuthorizenetPayment@authorizeCardPayment');
Route::post('test-process-authorize-card-payment', 'AuthorizenetPayment@processAuthorizeCardPayment');

If you are testing on localhost. Run PHP artisan serve command on cmd panel.

If you are testing it on a live server. Simply run the URL on the browser.

http://domainName/test-authorize-card-payment.

Credit card for authorize.net testing.