uc_authorizenet.module in Ubercart 8.4
Same filename and directory in other branches
Processes payments using Authorize.net. Supports AIM and ARB.
File
payment/uc_authorizenet/uc_authorizenet.moduleView source
<?php
/**
* @file
* Processes payments using Authorize.net. Supports AIM and ARB.
*/
use Drupal\uc_order\OrderInterface;
define('UC_AUTHORIZENET_TEST_GATEWAY_URL', 'https://test.authorize.net/gateway/transact.dll');
define('UC_AUTHORIZENET_LIVE_GATEWAY_URL', 'https://secure.authorize.net/gateway/transact.dll');
/**
* Implements hook_uc_payment_gateway().
*/
function uc_authorizenet_uc_payment_gateway() {
$gateways['authorizenet'] = [
'title' => t('Authorize.net'),
'description' => t('Process credit card payments using the AIM service of Authorize.net.'),
'settings' => 'uc_authorizenet_settings_form',
'credit' => 'uc_authorizenet_charge',
'credit_txn_types' => [
UC_CREDIT_AUTH_ONLY,
UC_CREDIT_PRIOR_AUTH_CAPTURE,
UC_CREDIT_AUTH_CAPTURE,
UC_CREDIT_REFERENCE_SET,
UC_CREDIT_REFERENCE_TXN,
],
];
return $gateways;
}
/**
* Creates a CIM profile using an order's data.
*/
function _uc_authorizenet_cim_profile_create(OrderInterface $order) {
$server = variable_get('uc_authnet_cim_mode', 'disabled');
// Help build the request.
$request = _uc_authorizenet_cim_profile_create_request($order);
// Request a profile from auth.net.
$xml = _uc_authorizenet_xml_api_wrapper('createCustomerProfileRequest', _uc_authorizenet_array_to_xml($request));
// Parse the response.
$response = _uc_authorizenet_cim_parse_response(uc_authorizenet_xml_api($server, $xml));
if ($response['resultCode'] == 'Error') {
uc_order_comment_save($order
->id(), 0, t('Authorize.Net: Creating CIM profile failed.<br />@error - @text', [
'@error' => $response['code'],
'@text' => $response['text'],
]), 'admin');
return $response['text'];
}
else {
uc_order_comment_save($order
->id(), 0, t('Authorize.Net: CIM profile created - @id', [
'@id' => $response['customerProfileId'],
]));
}
// Save the new credit reference to the db.
$order->data = uc_credit_log_reference($order
->id(), $response['customerProfileId'], $order->payment_details['cc_number']);
return '';
}
/**
* Helper to create the CIM profile creation request.
*/
function _uc_authorizenet_cim_profile_create_request(OrderInterface $order) {
return [
'refId' => substr($order
->id() . '-' . \Drupal::time()
->getRequestTime(), 0, 20),
'profile' => [
'merchantCustomerId' => substr($order
->getOwnerId(), 0, 20),
'description' => substr(t('Order @order taking place at @date', [
'@order' => $order
->id(),
'@date' => \Drupal::service('date.formatter')
->format(\Drupal::time()
->getRequestTime()),
]), 0, 255),
'email' => substr($order
->getEmail(), 0, 255),
'paymentProfiles' => [
'billTo' => _uc_authorize_cim_xml_billto($order),
'payment' => [
'creditCard' => [
'cardNumber' => $order->payment_details['cc_number'],
'expirationDate' => $order->payment_details['cc_exp_year'] . '-' . str_pad($order->payment_details['cc_exp_month'], 2, '0', STR_PAD_LEFT),
],
],
],
'shipToList' => _uc_authorize_cim_xml_shipto($order),
],
];
}
/**
* Uses a reference to charge to a CIM profile.
*/
function _uc_authorizenet_cim_profile_charge(OrderInterface $order, $amount, $data) {
global $user;
$server = variable_get('uc_authnet_cim_mode', 'disabled');
// Help build the request.
$request = _uc_authorizenet_cim_profile_charge_request($order, $amount, $data);
// Check error state.
if (array_key_exists('errorCode', $request)) {
$comment[] = $request['text'];
$result = [
'success' => FALSE,
];
}
else {
// Request a profile from auth.net.
$xml = _uc_authorizenet_xml_api_wrapper('createCustomerProfileTransactionRequest', _uc_authorizenet_array_to_xml($request));
// Parse the response.
$response = _uc_authorizenet_cim_parse_response(uc_authorizenet_xml_api($server, $xml));
// Error state.
if ($response['resultCode'] == 'Error') {
$result = [
'success' => FALSE,
];
$comment[] = '(' . $response['resultCode'] . ': ' . $response['text'] . ')';
}
else {
$result = [
'success' => TRUE,
];
// Build info message.
$types = uc_credit_transaction_types();
$comment[] = t('<b>@type:</b> @amount', [
'@type' => $types[$data['txn_type']],
'@amount' => uc_currency_format($amount),
]);
}
// Save a comment to the order.
uc_order_comment_save($order
->id(), $user
->id(), implode('<br />', $comment), 'admin');
}
// Build the response to the payment gateway API.
return $result + [
'comment' => implode(', ', $comment),
'message' => implode('<br />', $comment),
'uid' => $user
->id(),
];
}
/**
* Helper for building the request for a CIM profile charge.
*/
function _uc_authorizenet_cim_profile_charge_request(OrderInterface $order, $amount, $data) {
$profile = _uc_authorizenet_cim_profile_get($order, $data['ref_id']);
if ($profile['resultCode'] == 'Error') {
return $profile;
}
else {
return [
'refId' => substr($order
->id() . '-' . \Drupal::time()
->getRequestTime(), 0, 20),
'transaction' => [
'profileTransAuthCapture' => [
'amount' => uc_currency_format($amount, FALSE, FALSE, '.'),
'customerProfileId' => $profile['customerProfileId'],
'customerPaymentProfileId' => $profile['customerPaymentProfileId'],
'customerShippingAddressId' => $profile['customerAddressId'],
'order' => [
'invoiceNumber' => $order
->id(),
],
],
],
];
}
}
/**
* Gets a CIM profile stored at Authorize.Net.
*/
function _uc_authorizenet_cim_profile_get(OrderInterface $order, $profile_id) {
$server = variable_get('uc_authnet_cim_mode', 'disabled');
$request = [
'customerProfileId' => $profile_id,
];
// Request a profile from auth.net.
$xml = _uc_authorizenet_xml_api_wrapper('getCustomerProfileRequest', _uc_authorizenet_array_to_xml($request));
// Parse the response.
$response = _uc_authorizenet_cim_parse_response(uc_authorizenet_xml_api($server, $xml));
return $response;
}
/**
* Gets a CIM payment profile stored at auth.net.
*/
function _uc_authorizenet_cim_payment_profile_get(OrderInterface $order, $profile_id, $payment_profile_id) {
$server = variable_get('uc_authnet_cim_mode', 'disabled');
$request = [
'customerProfileId' => $profile_id,
];
// Request a profile from auth.net.
$xml = _uc_authorizenet_xml_api_wrapper('getCustomerPaymentProfileRequest', _uc_authorizenet_array_to_xml($request));
// Parse the response.
$response = _uc_authorizenet_cim_parse_response(uc_authorizenet_xml_api($server, $xml));
return $response['resultCode'] == 'Error' ? FALSE : $response;
}
/**
* Helper function for XML API requests.
*
* Wraps XML API request child elements in the request element and includes
* the merchant authentication information.
*/
function _uc_authorizenet_xml_api_wrapper($request, $xml) {
return '<?xml version="1.0" encoding="utf-8"?><' . $request . ' xmlns="AnetApi/xml/v1/schema/AnetApiSchema.xsd"><merchantAuthentication>' . '<name>' . trim(variable_get('uc_authnet_api_login_id', '')) . '</name>' . '<transactionKey>' . trim(variable_get('uc_authnet_api_transaction_key', '')) . '</transactionKey></merchantAuthentication>' . $xml . '</' . $request . '>';
}
/**
* Converts a hierarchical array of elements into an XML string.
*/
function _uc_authorizenet_array_to_xml($data) {
$xml = '';
// Loop through the elements in the data array.
foreach ($data as $element => $contents) {
if (is_array($contents)) {
// Render the element with its child elements.
$xml .= '<' . $element . '>' . _uc_authorizenet_array_to_xml($contents) . '</' . $element . '>';
}
else {
// Render the element with its contents.
$xml .= '<' . $element . '>' . htmlspecialchars($contents) . '</' . $element . '>';
}
}
return $xml;
}
/**
* Maps an order's billing information to an array for later XML conversion.
*/
function _uc_authorize_cim_xml_billto(OrderInterface $order) {
return [
'firstName' => substr($order->billing_first_name, 0, 50),
'lastName' => substr($order->billing_last_name, 0, 50),
'company' => substr($order->billing_company, 0, 50),
'address' => substr($order->billing_street1, 0, 60),
'city' => substr($order->billing_city, 0, 40),
'state' => substr($order->billing_zone, 0, 2),
'zip' => substr($order->billing_postal_code, 0, 20),
'country' => $order->billing_country,
'phoneNumber' => substr($order->billing_phone, 0, 25),
];
}
/**
* Maps an order's shipping information to an array for later XML conversion.
*/
function _uc_authorize_cim_xml_shipto(OrderInterface $order) {
return [
'firstName' => substr($order->delivery_first_name, 0, 50),
'lastName' => substr($order->delivery_last_name, 0, 50),
'company' => substr($order->delivery_company, 0, 50),
'address' => substr($order->delivery_street1, 0, 60),
'city' => substr($order->delivery_city, 0, 40),
'state' => substr($order->delivery_zone, 0, 2),
'zip' => substr($order->delivery_postal_code, 0, 20),
'country' => $order->delivery_country,
];
}
/**
* Parses an Authorize.Net XML CIM API response.
*/
function _uc_authorizenet_cim_parse_response($content) {
// Find the elements in the XML and build the return array.
$data = [
'refId' => _uc_authorizenet_substr_between($content, 'refId'),
'resultCode' => _uc_authorizenet_substr_between($content, 'resultCode'),
'code' => _uc_authorizenet_substr_between($content, 'code'),
'text' => _uc_authorizenet_substr_between($content, 'text'),
'customerProfileId' => _uc_authorizenet_substr_between($content, 'customerProfileId'),
'directResponse' => _uc_authorizenet_substr_between($content, 'directResponse'),
'customerPaymentProfileId' => _uc_authorizenet_substr_between($content, 'customerPaymentProfileId'),
'customerAddressId' => _uc_authorizenet_substr_between($content, 'customerAddressId'),
];
return $data;
}
/**
* Parses an Authorize.Net XML API response; from sample PHP for ARB.
*/
function _uc_authorizenet_arb_parse_response($content) {
// Find the elements in the XML and build the return array.
$data = [
'refId' => _uc_authorizenet_substr_between($content, 'refId'),
'resultCode' => _uc_authorizenet_substr_between($content, 'resultCode'),
'code' => _uc_authorizenet_substr_between($content, 'code'),
'text' => _uc_authorizenet_substr_between($content, 'text'),
'subscriptionId' => _uc_authorizenet_substr_between($content, 'subscriptionId'),
];
return $data;
}
/**
* Helper function for parsing responses; adapted from sample PHP for ARB.
*/
function _uc_authorizenet_substr_between($string, $element) {
$open = '<' . $element . '>';
$close = '</' . $element . '>';
// Fail if we can't find the open or close tag for the element.
if (strpos($string, $open) === FALSE || strpos($string, $close) === FALSE) {
return FALSE;
}
$start = strpos($string, $open) + strlen($open);
$end = strpos($string, $close);
return substr($string, $start, $end - $start);
}
/*
* @todo Remove!
*/
if (!function_exists('variable_get')) {
/**
* Temporary shim for removed variable_get().
*/
function variable_get($name, $default = NULL) {
return $default;
}
}
Functions
Name | Description |
---|---|
uc_authorizenet_uc_payment_gateway | Implements hook_uc_payment_gateway(). |
_uc_authorizenet_arb_parse_response | Parses an Authorize.Net XML API response; from sample PHP for ARB. |
_uc_authorizenet_array_to_xml | Converts a hierarchical array of elements into an XML string. |
_uc_authorizenet_cim_parse_response | Parses an Authorize.Net XML CIM API response. |
_uc_authorizenet_cim_payment_profile_get | Gets a CIM payment profile stored at auth.net. |
_uc_authorizenet_cim_profile_charge | Uses a reference to charge to a CIM profile. |
_uc_authorizenet_cim_profile_charge_request | Helper for building the request for a CIM profile charge. |
_uc_authorizenet_cim_profile_create | Creates a CIM profile using an order's data. |
_uc_authorizenet_cim_profile_create_request | Helper to create the CIM profile creation request. |
_uc_authorizenet_cim_profile_get | Gets a CIM profile stored at Authorize.Net. |
_uc_authorizenet_substr_between | Helper function for parsing responses; adapted from sample PHP for ARB. |
_uc_authorizenet_xml_api_wrapper | Helper function for XML API requests. |
_uc_authorize_cim_xml_billto | Maps an order's billing information to an array for later XML conversion. |
_uc_authorize_cim_xml_shipto | Maps an order's shipping information to an array for later XML conversion. |