commerce_square.module in Commerce Square Connect 7
Same filename and directory in other branches
Module file for Commerce Square.
File
commerce_square.moduleView source
<?php
/**
* @file
* Module file for Commerce Square.
*/
use SquareConnect\Api\LocationsApi;
use SquareConnect\Api\OAuthApi;
use SquareConnect\Api\OrdersApi;
use SquareConnect\Api\TransactionsApi;
use SquareConnect\ApiException;
use SquareConnect\Model\ChargeRequest;
use SquareConnect\Model\CreateOrderRequest;
use SquareConnect\Model\Money;
use SquareConnect\Model\ObtainTokenRequest;
use SquareConnect\Model\OrderLineItem;
/**
* Implements hook_libraries_info().
*/
function commerce_square_libraries_info() {
$libraries['square'] = array(
'name' => 'Square connect SDK library',
'vendor url' => 'https://squareup.com',
'download url' => 'https://github.com/square/connect-php-sdk',
'version arguments' => array(
'file' => 'composer.json',
'pattern' => '/"version": "(\\d+\\.\\d+\\.\\d+)"/',
),
'files' => array(
'php' => array(
'autoload.php',
),
),
);
return $libraries;
}
/**
* Implements hook_permission().
*/
function commerce_square_permission() {
return array(
'administer commerce_square' => array(
'title' => t('Administer Commerce Square'),
'description' => t('Allows configuring Commerce Square.'),
),
);
}
/**
* Implements hook_commerce_payment_method_info().
*/
function commerce_square_commerce_payment_method_info() {
$payment_methods['commerce_square'] = array(
'base' => 'commerce_square_payment_method',
'title' => t('Square Connect'),
'short_title' => t('Square'),
'description' => t('Square Connect Payment Method'),
'terminal' => TRUE,
'cardonfile' => array(
'create callback' => 'commerce_square_cardonfile_create',
'charge callback' => 'commerce_square_cardonfile_charge',
'update callback' => 'commerce_square_cardonfile_update',
'delete callback' => 'commerce_square_cardonfile_delete',
),
);
return $payment_methods;
}
/**
* Returns the default settings for the Square module.
*/
function commerce_square_default_settings() {
return array(
'app_name' => '',
'app_secret' => '',
'test_app_id' => '',
'test_access_token' => '',
'live_app_id' => '',
'live_access_token' => '',
'live_access_token_expiry' => '',
'live_access_refresh_token' => '',
);
}
/**
* Returns the default settings for the Square payment method.
*/
function commerce_square_payment_method_default_settings() {
return array(
'mode' => 'test',
'type' => COMMERCE_CREDIT_AUTH_CAPTURE,
'cardonfile' => FALSE,
'test_location_id' => '',
'live_location_id' => '',
);
}
/**
* Payment method form callback.
*/
function commerce_square_payment_method_settings_form($settings) {
$square_settings = variable_get('commerce_square_settings', commerce_square_default_settings()) + commerce_square_default_settings();
$settings = $settings + commerce_square_payment_method_default_settings();
libraries_load('square');
$form['mode'] = array(
'#type' => 'radios',
'#title' => t('Mode'),
'#options' => _commerce_square_get_supported_modes(),
'#default_value' => empty($settings['mode']) ? 'test' : $settings['mode'],
'#required' => TRUE,
);
$form['type'] = array(
'#type' => 'radios',
'#title' => t('Default credit card transaction type'),
'#description' => t('The default will be used to process transactions during checkout.'),
'#options' => array(
COMMERCE_CREDIT_AUTH_CAPTURE => t('Authorization and capture'),
COMMERCE_CREDIT_AUTH_ONLY => t('Authorization only (requires manual or automated capture after checkout)'),
),
'#default_value' => $settings['type'],
);
foreach (_commerce_square_get_supported_modes() as $mode => $name) {
$form[$mode . '_location_id'] = array(
'#type' => 'select',
'#title' => t('@mode Location', array(
'@mode' => $name,
)),
'#description' => t('The location for the transactions.'),
'#default_value' => $settings[$mode . '_location_id'],
'#required' => TRUE,
);
$access_token = $square_settings[$mode . '_access_token'];
if (!empty($access_token)) {
$square_api = new SquareApi($access_token, $mode);
$location_api = new LocationsApi($square_api
->getClient());
try {
$locations = $location_api
->listLocations();
$location_options = $locations
->getLocations();
$options = array();
foreach ($location_options as $location_option) {
$options[$location_option
->getId()] = $location_option
->getName();
}
$form[$mode . '_location_id']['#options'] = $options;
} catch (\Exception $e) {
drupal_set_message($e
->getMessage(), 'error');
}
}
else {
$form[$mode][$mode . '_location_id']['#disabled'] = TRUE;
$form[$mode][$mode . '_location_id']['#options'] = array(
'_none' => 'Not configured',
);
}
}
if (module_exists('commerce_cardonfile')) {
$form['cardonfile'] = array(
'#type' => 'checkbox',
'#title' => t('Enable Card on File functionality with this payment method.'),
'#default_value' => $settings['cardonfile'],
);
}
return $form;
}
/**
* Returns the payment method modes.
*/
function _commerce_square_get_supported_modes() {
return array(
'test' => t('Sandbox'),
'live' => t('Production'),
);
}
/**
* Renew access token.
*
* Triggered by cron via commerce_square_cron().
*/
function commerce_square_renew_access_token() {
$settings = variable_get('commerce_square_settings', commerce_square_default_settings()) + commerce_square_default_settings();
libraries_load('square');
// If site has not yet had Square app configured, do nothing.
if (empty($settings['live_app_id']) || empty($settings['live_access_token'])) {
return FALSE;
}
// OAuth access tokens expire after 30 days. renew a token before it expires.
// Begin attempting to renew on the 29th day.
// https://developer.squareup.com/docs/oauth-api/cookbook/renew-oauth-tokens.
if (!empty($settings['live_access_token_expiry']) && $settings['live_access_token_expiry'] - 86400 < time()) {
// Use OAuth API and ObtainToken endpoint if SDK version accommodates.
if (class_exists('SquareConnect\\Api\\OAuthApi') && method_exists('SquareConnect\\Model\\ObtainTokenRequest', 'setRefreshToken')) {
$oauth_api = new OAuthApi();
$request_body = new ObtainTokenRequest();
// Use refresh token, if present, and make request via OAuth API.
if (!empty($settings['live_access_refresh_token'])) {
$request_body
->setClientId($settings['live_app_id']);
$request_body
->setClientSecret($settings['app_secret']);
$request_body
->setGrantType('refresh_token');
$request_body
->setRefreshToken($settings['live_access_refresh_token']);
try {
$result = $oauth_api
->obtainToken($request_body);
} catch (Exception $e) {
watchdog('commerce_square', 'Square token refresh failed. Message: @message', array(
'@message' => $e
->getMessage(),
), WATCHDOG_ERROR);
return FALSE;
}
$access_token = !empty($result) ? $result
->getAccessToken() : FALSE;
if (!empty($access_token)) {
$settings['live_access_token'] = $access_token;
$settings['live_access_token_expiry'] = strtotime($result
->getExpiresAt());
$settings['live_access_refresh_token'] = $result
->getRefreshToken();
variable_set('commerce_square_settings', $settings);
watchdog('commerce_square', 'Square token refresh successful.', array(), WATCHDOG_INFO);
}
else {
watchdog('commerce_square', 'Square token refresh failed: no access token returned by ObtainToken endpoint when using refresh_token.', array(), WATCHDOG_ERROR);
}
}
else {
$request_body
->setClientId($settings['live_app_id']);
$request_body
->setClientSecret($settings['app_secret']);
$request_body
->setGrantType('migration_token');
$request_body
->setMigrationToken($settings['live_access_token']);
try {
$result = $oauth_api
->obtainToken($request_body);
} catch (Exception $e) {
watchdog('commerce_square', 'Square token refresh via migration_token failed. Message: @message', array(
'@message' => $e
->getMessage(),
), WATCHDOG_ERROR);
return FALSE;
}
$access_token = !empty($result) ? $result
->getAccessToken() : FALSE;
if (!empty($access_token)) {
$settings['live_access_token'] = $access_token;
$settings['live_access_token_expiry'] = strtotime($result
->getExpiresAt());
$settings['live_access_refresh_token'] = $result
->getRefreshToken();
variable_set('commerce_square_settings', $settings);
watchdog('commerce_square', 'Square token refresh via migration_token successful.', array(), WATCHDOG_INFO);
}
else {
watchdog('commerce_square', 'Square token migration failed: no access token returned by ObtainToken endpoint when using migration_token.', array(), WATCHDOG_ERROR);
}
}
}
else {
$data = array(
'access_token' => $settings['live_access_token'],
);
$data_string = json_encode($data);
$ch = curl_init('https://connect.squareup.com/oauth2/clients/' . $settings['live_app_id'] . '/access-token/renew');
curl_setopt($ch, CURLOPT_CUSTOMREQUEST, "POST");
curl_setopt($ch, CURLOPT_POSTFIELDS, $data_string);
curl_setopt($ch, CURLOPT_RETURNTRANSFER, TRUE);
curl_setopt($ch, CURLOPT_HTTPHEADER, array(
'Content-Type: application/json',
'Content-Length: ' . strlen($data_string),
'Authorization: Client ' . $settings['app_secret'],
));
$response = curl_exec($ch);
$response_body = drupal_json_decode($response);
if (!empty($response_body['access_token'])) {
$settings['live_access_token'] = $response_body['access_token'];
$settings['live_access_token_expiry'] = strtotime($response_body['expires_at']);
variable_set('commerce_square_settings', $settings);
watchdog('commerce_square', 'Square token refresh via deprecated RenewToken endpoint successful. Please consider upgrading the Square SDK.', array(), WATCHDOG_INFO);
}
else {
watchdog('commerce_square', 'Square token refresh via deprecated RenewToken endpoint failed. Please consider upgrading the Square SDK.', array(), WATCHDOG_ERROR);
}
}
}
}
/**
* Implements hook_menu().
*/
function commerce_square_menu() {
$items = array();
$items['admin/commerce/config/square'] = array(
'title' => 'Square settings',
'description' => 'Configure Square.',
'page callback' => 'drupal_get_form',
'page arguments' => array(
'commerce_square_settings_form',
),
'access arguments' => array(
'administer commerce_square',
),
'file' => 'includes/commerce_square.admin.inc',
);
$items['admin/commerce_square/oauth/obtain'] = array(
'title' => 'Obtain Square Merchant Token',
'page callback' => 'commerce_square_obtain_token',
'access callback' => 'commerce_square_obtain_token_access',
'type' => MENU_CALLBACK,
);
$items['admin/commerce/orders/%commerce_order/payment/%commerce_payment_transaction/square-capture'] = array(
'title' => 'Capture',
'page callback' => 'drupal_get_form',
'page arguments' => array(
'commerce_square_capture_form',
3,
5,
),
'access callback' => 'commerce_square_payment_transaction_access',
'access arguments' => array(
3,
5,
'capture',
),
'type' => MENU_DEFAULT_LOCAL_TASK,
'context' => MENU_CONTEXT_INLINE,
'file' => 'includes/commerce_square.admin.inc',
'weight' => 10,
);
$items['admin/commerce/orders/%commerce_order/payment/%commerce_payment_transaction/square-void'] = array(
'title' => 'Void',
'page callback' => 'drupal_get_form',
'page arguments' => array(
'commerce_square_void_form',
3,
5,
),
'access callback' => 'commerce_square_payment_transaction_access',
'access arguments' => array(
3,
5,
'void',
),
'type' => MENU_DEFAULT_LOCAL_TASK,
'context' => MENU_CONTEXT_INLINE,
'file' => 'includes/commerce_square.admin.inc',
'weight' => 10,
);
$items['admin/commerce/orders/%commerce_order/payment/%commerce_payment_transaction/square-refund'] = array(
'title' => 'Refund',
'page callback' => 'drupal_get_form',
'page arguments' => array(
'commerce_square_refund_form',
3,
5,
),
'access callback' => 'commerce_square_payment_transaction_access',
'access arguments' => array(
3,
5,
'refund',
),
'type' => MENU_DEFAULT_LOCAL_TASK,
'context' => MENU_CONTEXT_INLINE,
'file' => 'includes/commerce_square.admin.inc',
'weight' => 10,
);
return $items;
}
/**
* Square OAuth flow menu callback to redirect back to the payment method form.
*/
function commerce_square_obtain_token() {
$options = array(
'query' => array(
'code' => $_GET['code'],
),
);
drupal_goto('admin/commerce/config/square', $options);
}
/**
* Square OAuth flow menu access callback.
*/
function commerce_square_obtain_token_access() {
if (empty($_GET['state'])) {
return FALSE;
}
if (drupal_valid_token(check_plain($_GET['state']))) {
return TRUE;
}
return FALSE;
}
/**
* Square payment checkout pane form callback.
*/
function commerce_square_payment_method_submit_form($payment_method, $pane_values, $checkout_pane, $order) {
$settings = variable_get('commerce_square_settings', commerce_square_default_settings()) + commerce_square_default_settings();
$order_wrapper = entity_metadata_wrapper('commerce_order', $order);
$postal_code = NULL;
if (!empty($order->commerce_customer_billing) && !empty($order_wrapper->commerce_customer_billing
->value()->commerce_customer_address)) {
$address_value = $order_wrapper->commerce_customer_billing->commerce_customer_address
->value();
if (!empty($address_value['postal_code'])) {
$postal_code = $address_value['postal_code'];
}
}
$mode = $payment_method['settings']['mode'];
$element['#attached'] = array(
'js' => array(
array(
'data' => array(
'commerceSquare' => array(
'applicationId' => $settings[$mode . '_app_id'],
'postalCode' => $postal_code,
),
),
'type' => 'setting',
),
),
);
_commerce_square_ensure_assets_attached($element, $mode);
$element['#type'] = 'container';
$element['#attributes']['class'][] = 'square-form';
// Populated by the JS library.
$element['payment_method_nonce'] = array(
'#type' => 'hidden',
'#attributes' => array(
'class' => array(
'square-nonce',
),
),
);
$element['card_type'] = array(
'#type' => 'hidden',
'#attributes' => array(
'class' => array(
'square-card-type',
),
),
);
$element['last4'] = array(
'#type' => 'hidden',
'#attributes' => array(
'class' => array(
'square-last4',
),
),
);
$element['exp_month'] = array(
'#type' => 'hidden',
'#attributes' => array(
'class' => array(
'square-exp-month',
),
),
);
$element['exp_year'] = array(
'#type' => 'hidden',
'#attributes' => array(
'class' => array(
'square-exp-year',
),
),
);
$element['number'] = array(
'#type' => 'item',
'#title' => t('Card number'),
'#markup' => '<div id="square-card-number"></div>',
);
$element['details'] = array(
'#type' => 'container',
'#attributes' => array(
'class' => array(
'credit-card-form__expiration',
),
),
);
$element['details']['expiration'] = array(
'#type' => 'item',
'#title' => t('Expiration'),
'#markup' => '<div id="square-expiration-date"></div>',
);
$element['details']['cvv'] = array(
'#type' => 'item',
'#title' => t('CVV'),
'#markup' => '<div id="square-cvv"></div>',
);
$element['details']['postal-code'] = array(
'#type' => 'item',
'#title' => t('Postal code'),
'#markup' => '<div id="square-postal-code"></div>',
);
return $element;
}
/**
* Square payment checkout pane validate callback.
*/
function commerce_square_payment_method_submit_form_validate($payment_method, $pane_form, $pane_values, $order) {
if (empty($pane_values['payment_method_nonce'])) {
drupal_set_message('There was an error collecting the payment information.', 'error');
return FALSE;
}
libraries_load('square');
$mode = $payment_method['settings']['mode'];
$location_id = $payment_method['settings'][$mode . '_location_id'];
$charge = commerce_payment_order_balance($order);
$square_total_amount = $charge['amount'];
$square_order_currency = $charge['currency_code'];
$order_wrapper = entity_metadata_wrapper('commerce_order', $order);
$square_api = SquareApi::createFromInstanceId($payment_method['instance_id']);
$api_client = $square_api
->getClient();
$order_api_instance = new OrdersApi($api_client);
$charge_api_instance = new TransactionsApi($api_client);
// Containers for accumulating line item data
$line_items = array();
$square_line_item_total = 0;
// Iterate through Drupal Commerce standard line items
foreach ($order_wrapper->commerce_line_items as $line_item_wrapper) {
$line_item = new OrderLineItem();
$base_price_money = new Money();
$base_price_money
->setAmount((int) $line_item_wrapper->commerce_unit_price->amount
->value());
$base_price_money
->setCurrency($line_item_wrapper->commerce_unit_price->currency_code
->value());
$line_item
->setBasePriceMoney($base_price_money);
$line_item_label = $line_item_wrapper->line_item_label
->value();
// Convert line item label to product title + (SKU).
if (isset($line_item_wrapper->commerce_product)) {
$line_item_label = $line_item_wrapper->commerce_product->title
->value() . ' (' . $line_item_wrapper->commerce_product->sku
->value() . ')';
}
$line_item
->setName($line_item_label);
// Quantity needs to be a string integer, it cannot be a float.
$line_item
->setQuantity((string) (int) $line_item_wrapper->quantity
->value());
// Handling DISCOUNTS and VAT:
// If either are included in line item price, include details in Note field.
// Note that we are NOT adding them as Square discount/tax elements because of
// limitations in Square's discount/tax calculation flexibility and to avoid any
// discrepancies in totals between Drupal and Square.
$line_item_price_data_array = $line_item_wrapper->commerce_unit_price->data
->value();
$line_item_price_components = $line_item_price_data_array['components'];
if (count($line_item_price_components) > 1) {
$price_component_notes = array();
foreach ($line_item_price_components as $price) {
// Skip base_price component and components that are not included as
// part of the price (ie, VAT.)
if ($price['name'] === 'base_price' || $price['included'] === FALSE) {
continue;
}
$formatted_component_price = commerce_currency_format($price['price']['amount'], $price['price']['currency_code']);
$component_label = $price['name'];
// If the price component is from the commerce_discount module and
// provides a component title, use that.
if (isset($price['price']['data']['discount_component_title'])) {
$component_label = $price['price']['data']['discount_component_title'];
}
elseif ($price['name'] === 'discount') {
$component_label = t('Sale');
}
elseif (isset($price['price']['data']['tax_rate']['display_title'])) {
$component_label = $price['price']['data']['tax_rate']['display_title'];
}
$price_component_notes[] = $component_label . ' ' . $formatted_component_price;
}
// Format Note if there was at least one component to be displayed.
if (count($price_component_notes) > 0) {
$adjust_text = format_plural(count($price_component_notes), 'Adjustment', 'Adjustments');
$include_text = t('included in price (per item):');
$notes_text = implode('; ', $price_component_notes);
$line_item
->setNote($adjust_text . ' ' . $include_text . ' ' . $notes_text);
}
}
$line_items[] = $line_item;
$square_line_item_total += $line_item_wrapper->commerce_total->amount
->value();
}
// ONLY IF commerce_tax is installed & enabled:
// Add order-level taxes (EXCLUDED from line item price) as generic line items,
// ignoring Square's tax functionality to avoid discrepancies in calculations and rounding.
// Note: if any other tax module is being used, it will NOT be added as a line item here,
// but will be handled with the catch-all final "adjustments"
if (module_exists('commerce_tax')) {
$order_total_data_array = $order_wrapper->commerce_order_total->data
->value();
$order_taxes = commerce_tax_components($order_total_data_array['components']);
foreach ($order_taxes as $tax) {
if ($tax['included'] === TRUE) {
continue;
}
$tax_money = new Money();
$tax_money
->setAmount((int) $tax['price']['amount']);
$tax_money
->setCurrency($tax['price']['currency_code']);
$line_item = new OrderLineItem();
$line_item
->setBasePriceMoney($tax_money);
$line_item
->setName($tax['price']['data']['tax_rate']['display_title']);
$line_item
->setQuantity('1');
// Done building line item. Add it to line items array.
$line_items[] = $line_item;
// Add line item total to running order total
$square_line_item_total += $tax['price']['amount'];
}
}
// Square requires the order total to match the payment amount, the following
// logic accommodates for rounding error or other omitted calculations.
if ($square_line_item_total != $square_total_amount) {
$diff = $square_total_amount - $square_line_item_total;
$total_money = new Money();
$total_money
->setAmount($diff);
$total_money
->setCurrency($square_order_currency);
$line_item = new OrderLineItem();
$line_item
->setBasePriceMoney($total_money);
$line_item
->setName(t('Adjustment'));
$line_item
->setQuantity('1');
$line_items[] = $line_item;
}
// Start building the Square Order.
$order_request = new CreateOrderRequest();
$order_request
->setIdempotencyKey(uniqid($order->order_id . '-', TRUE));
$order_request
->setReferenceId($order->order_id);
$order_request
->setLineItems($line_items);
// Make the Order API call
try {
$order_result = $order_api_instance
->createOrder($location_id, $order_request);
} catch (ApiException $e) {
$response = $e
->getResponseBody();
$error = $response->errors[0];
drupal_set_message($error->detail, 'error');
$vars = array(
'@category' => $error->category,
'@code' => $error->code,
'@detail' => $error->detail,
);
watchdog('commerce_square', 'Square order error. category: @category code: @code detail: @detail', $vars);
return FALSE;
}
//// Above is all processing needed to prepare Order & get Square Order ID
//// Below we process the ChargeRequest
$charge_amount = new Money();
$charge_amount
->setAmount((int) $charge['amount']);
$charge_amount
->setCurrency($charge['currency_code']);
$charge_request = new IntegrationChargeRequest();
// Link the transaction to this order.
$charge_request
->setOrderId($order_result
->getOrder()
->getId());
$charge_request
->setAmountMoney($charge_amount);
$charge_request
->setDelayCapture($payment_method['settings']['type'] == COMMERCE_CREDIT_AUTH_ONLY);
$charge_request
->setCardNonce($pane_values['payment_method_nonce']);
$charge_request
->setIdempotencyKey(uniqid('', TRUE));
$charge_request
->setBuyerEmailAddress($order->mail);
// The Square note field identifies transactions in the Square dashboard.
// TODO: make site-configurable using tokens
$charge_label = t('Order #@order_number, @store', array(
'@order_number' => $order->order_id,
'@store' => variable_get('site_name'),
));
// Trim to max 60 characters (Square limit on field).
$charge_label = substr($charge_label, 0, 60);
$charge_request
->setNote($charge_label);
// The `integration_id` is only valid when live.
if ($mode === 'live') {
$charge_request
->setIntegrationId('sqi_b6ff0cd7acc14f7ab24200041d066ba6');
}
try {
$result = $charge_api_instance
->charge($location_id, $charge_request);
$order->square_result = $result;
} catch (ApiException $e) {
$response = $e
->getResponseBody();
$error = $response->errors[0];
drupal_set_message($error->detail, 'error');
$vars = array(
'@category' => $error->category,
'@code' => $error->code,
'@detail' => $error->detail,
);
watchdog('commerce_square', 'Square transaction error. category: @category code: @code detail: @detail', $vars);
return FALSE;
}
return TRUE;
}
/**
* Square payment checkout pane submit callback.
*/
function commerce_square_payment_method_submit_form_submit($payment_method, $pane_form, $pane_values, $order, $charge) {
/** @var \SquareConnect\Model\ChargeResponse $result */
$result = $order->square_result;
$transaction = commerce_payment_transaction_new('commerce_square', $order->order_id);
$transaction->instance_id = $payment_method['instance_id'];
$transaction->amount = $charge['amount'];
$transaction->currency_code = $charge['currency_code'];
$transaction->status = $payment_method['settings']['type'] == COMMERCE_CREDIT_AUTH_ONLY ? COMMERCE_PAYMENT_STATUS_PENDING : COMMERCE_PAYMENT_STATUS_SUCCESS;
$remote_transaction = $result
->getTransaction();
$tender = $remote_transaction
->getTenders();
$tender = $tender[0];
$transaction->remote_id = $remote_transaction
->getId() . '|' . $tender
->getId();
$transaction->message = $tender
->getNote();
commerce_payment_transaction_save($transaction);
}
/**
* Implements hook_form_alter().
*
* Workaround https://www.drupal.org/node/1988968#comment-12032406. We need to
* add the js files to the payment method selection since drupal AJAX cannot
* ensure the proper loading of new js files.
*/
function commerce_square_form_alter(&$form, $form_state) {
$square_payment_method = FALSE;
if (isset($form['commerce_payment']['payment_methods']['#value']) && is_array($form['commerce_payment']['payment_methods']['#value'])) {
foreach ($form['commerce_payment']['payment_methods']['#value'] as $key => $method) {
if ($method['method_id'] === 'commerce_square') {
$square_payment_method = TRUE;
break;
}
}
if ($square_payment_method) {
_commerce_square_ensure_assets_attached($form, $method['settings']['mode']);
}
}
}
/**
* Ensures the JavaScript assets are attached to the Square payment form.
*
* @param array $element
* The element.
* @param string $mode
* The API mode.
*/
function _commerce_square_ensure_assets_attached(&$element, $mode) {
if ($mode === 'test') {
$element['#attached']['js']['https://js.squareupsandbox.com/v2/paymentform'] = array(
'type' => 'external',
);
}
else {
$element['#attached']['js']['https://js.squareup.com/v2/paymentform'] = array(
'type' => 'external',
);
}
$element['#attached']['js'][] = drupal_get_path('module', 'commerce_square') . '/js/commerce_square.form.js';
}
/**
* Access callback for transaction forms.
*
* @param object $order
* The order.
* @param object $transaction
* The transaction.
* @param string $type
* The operation type.
*
* @return bool
* The access.
*/
function commerce_square_payment_transaction_access($order, $transaction, $type) {
if ($transaction->payment_method != 'commerce_square') {
return FALSE;
}
if (!entity_access('update', 'commerce_payment_transaction', $transaction)) {
return FALSE;
}
if ($transaction->amount <= 0) {
return FALSE;
}
switch ($type) {
case 'void':
return $transaction->status == COMMERCE_PAYMENT_STATUS_PENDING;
case 'capture':
return $transaction->status == COMMERCE_PAYMENT_STATUS_PENDING;
case 'refund':
return $transaction->status == COMMERCE_PAYMENT_STATUS_SUCCESS;
default:
return FALSE;
}
}
/**
* Implements hook_cron().
*/
function commerce_square_cron() {
commerce_square_renew_access_token();
}