Newer
Older
Ryan Szrama
committed
<?php
/**
* @file
* Defines the payment system and checkout integration.
*/
Ryan Szrama
committed
Ryan Szrama
committed
// Local payment transaction status definitions:
// Pending is used when a transaction has been initialized but is still awaiting
// resolution; e.g. a CC authorization awaiting capture or an e-check payment
// pending at the payment provider.
define('COMMERCE_PAYMENT_STATUS_PENDING', 'pending');
// Success is used when a transaction has completed resulting in money being
// transferred from the customer to the store or vice versa.
define('COMMERCE_PAYMENT_STATUS_SUCCESS', 'success');
// Failure is used when a transaction cannot be completed or is rejected.
define('COMMERCE_PAYMENT_STATUS_FAILURE', 'failure');
Ryan Szrama
committed
// Credit card transaction types definitions:
// Used to just authorize an amount on a credit card account.
define('COMMERCE_CREDIT_AUTH_ONLY', 'authorize');
// User to just capture an amount on a credit card account.
define('COMMERCE_CREDIT_CAPTURE_ONLY', 'capture');
Ryan Szrama
committed
// Used to capture funds from a prior authorization.
define('COMMERCE_CREDIT_PRIOR_AUTH_CAPTURE', 'prior_auth_capture');
// Used to authorize and capture money all at once.
define('COMMERCE_CREDIT_AUTH_CAPTURE', 'auth_capture');
// Used to set up a credit card reference through the payment gateway.
define('COMMERCE_CREDIT_REFERENCE_SET', 'reference_set');
// Used to capture funds using a credit card reference.
define('COMMERCE_CREDIT_REFERENCE_TXN', 'reference_txn');
// Used to remove a reference from the payment gateway.
define('COMMERCE_CREDIT_REFERENCE_REMOVE', 'reference_remove');
// Used to credit funds to a reference at the payment gateway.
define('COMMERCE_CREDIT_REFERENCE_CREDIT', 'reference_credit');
// Used to credit funds to a credit card account.
define('COMMERCE_CREDIT_CREDIT', 'credit');
// Used to void a transaction before the transaction clears.
define('COMMERCE_CREDIT_VOID', 'void');
/**
* Implements of hook_entity_info().
*/
function commerce_payment_entity_info() {
$return = array(
'commerce_payment_transaction' => array(
'label' => t('Commerce Payment transaction'),
'controller class' => 'CommercePaymentTransactionEntityController',
'base table' => 'commerce_payment_transaction',
'revision table' => 'commerce_payment_transaction_revision',
'fieldable' => FALSE,
'entity keys' => array(
'id' => 'transaction_id',
'revision' => 'revision_id',
'bundle' => 'payment_method',
Ryan Szrama
committed
'label' => 'transaction_id', // TODO: Update to use a custom callback.
),
'bundle keys' => array(
'bundle' => 'payment_method',
),
'bundles' => array(),
'load hook' => 'commerce_payment_transaction_load',
'view modes' => array(
Ryan Szrama
committed
'administrator' => array(
'label' => t('Administrator'),
'custom settings' => FALSE,
),
),
Ryan Szrama
committed
'uri callback' => 'commerce_payment_transaction_uri',
'access callback' => 'commerce_payment_transaction_access',
'access arguments' => array(
'user key' => 'uid',
'access tag' => 'commerce_payment_transaction_access',
),
'token type' => 'commerce-payment-transaction',
'metadata controller class' => '',
Ryan Szrama
committed
'permission labels' => array(
'singular' => t('payment transaction'),
'plural' => t('payment transactions'),
),
// Prevent Redirect alteration of the payment transaction form.
'redirect' => FALSE,
),
);
foreach (commerce_payment_methods() as $method_id => $payment_method) {
$return['commerce_payment_transaction']['bundles'][$method_id] = array(
'label' => $payment_method['title'],
);
}
return $return;
}
Ryan Szrama
committed
/**
* Entity uri callback: gives modules a chance to specify a path for a payment
* transaction.
*/
function commerce_payment_transaction_uri($transaction) {
// Allow modules to specify a path, returning the first one found.
foreach (module_implements('commerce_payment_transaction_uri') as $module) {
$uri = module_invoke($module, 'commerce_payment_transaction_uri', $transaction);
// If the implementation returned data, use that now.
if (!empty($uri)) {
return $uri;
}
}
return NULL;
}
Ryan Szrama
committed
/**
* Implements hook_hook_info().
*/
function commerce_payment_hook_info() {
$hooks = array(
Ryan Szrama
committed
'commerce_payment_totals_row_info' => array(
'group' => 'commerce',
),
'commerce_payment_totals_row_info_alter' => array(
'group' => 'commerce',
),
Ryan Szrama
committed
'commerce_payment_method_info' => array(
'group' => 'commerce',
),
'commerce_payment_method_info_alter' => array(
'group' => 'commerce',
),
Ryan Szrama
committed
'commerce_payment_methods' => array(
'group' => 'commerce',
),
Ryan Szrama
committed
'commerce_payment_transaction_status_info' => array(
'group' => 'commerce',
),
Ryan Szrama
committed
'commerce_payment_transaction_uri' => array(
'group' => 'commerce'
),
Ryan Szrama
committed
'commerce_transaction_view' => array(
'group' => 'commerce',
),
'commerce_payment_transaction_access' => array(
'group' => 'commerce',
),
'commerce_payment_transaction_insert' => array(
'group' => 'commerce',
),
'commerce_payment_transaction_update' => array(
'group' => 'commerce',
),
'commerce_payment_transaction_delete' => array(
'group' => 'commerce',
),
'commerce_payment_order_paid_in_full' => array(
'group' => 'commerce',
),
);
return $hooks;
}
/**
* Implements hook_permission().
*/
function commerce_payment_permission() {
return array(
'administer payment methods' => array(
'title' => t('Administer payment methods'),
'description' => t('Allows users to configure enabled payment methods.'),
'restrict access' => TRUE,
),
'administer payments' => array(
'title' => t('Administer payments'),
'description' => t('Allows users to perform any payment action for any order and view transaction payloads.'),
'restrict access' => TRUE,
),
'view payments' => array(
'title' => t('View payments'),
'description' => t('Allows users to view the payments made to an order.'),
'restrict access' => TRUE,
),
'create payments' => array(
'title' => t('Create payments'),
'description' => t('Allows users to create new payments for orders.'),
'restrict access' => TRUE,
),
'update payments' => array(
'title' => t('Update payments'),
'description' => t('Allows users to update payments via payment method specific operations links.'),
'restrict access' => TRUE,
),
'delete payments' => array(
'title' => t('Delete payments'),
'description' => t('Allows users to delete payments on orders they can access.'),
'restrict access' => TRUE,
),
);
}
/**
* Implements hook_theme().
*/
function commerce_payment_theme() {
return array(
Ryan Szrama
committed
'commerce_payment_transaction' => array(
'variables' => array('order' => NULL, 'transaction' => NULL, 'view_mode' => NULL),
),
Ryan Szrama
committed
'commerce_payment_transaction_status_text' => array(
Ryan Szrama
committed
'variables' => array('text' => NULL, 'transaction_status' => NULL),
Ryan Szrama
committed
),
'commerce_payment_transaction_status_icon' => array(
Ryan Szrama
committed
'variables' => array('transaction_status' => NULL),
Ryan Szrama
committed
),
'commerce_payment_totals' => array(
'variables' => array('rows' => array(), 'form' => NULL, 'totals' => array(), 'view' => NULL),
'path' => drupal_get_path('module', 'commerce_payment') . '/theme',
'template' => 'commerce-payment-totals',
),
);
}
/**
* Adds the necessary CSS for the line item summary template.
*/
function template_preprocess_commerce_payment_totals(&$variables) {
drupal_add_css(drupal_get_path('module', 'commerce_payment') . '/theme/commerce_payment.admin.css');
}
/**
* Implements hook_modules_enabled().
*/
function commerce_payment_modules_enabled($modules) {
Bojan Živanović
committed
commerce_payment_methods_reset();
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
_commerce_payment_default_rules_reset($modules);
}
/**
* Resets default Rules if necessary when modules are enabled or disabled.
*
* @param $modules
* An array of module names that have been enabled or disabled.
*/
function _commerce_payment_default_rules_reset($modules) {
$reset_default_rules = FALSE;
// Look for any module defining a new payment method.
foreach ($modules as $module) {
if (function_exists($module . '_commerce_payment_method_info')) {
$reset_default_rules = TRUE;
}
}
// If we found a module defining a new payment method, we need to rebuild the
// default Rules especially for this module so the default payment method Rule
// will appear properly for this module.
if ($reset_default_rules) {
entity_defaults_rebuild();
rules_clear_cache(TRUE);
}
}
Ryan Szrama
committed
/**
* Implements hook_commerce_checkout_page_info().
*/
function commerce_payment_commerce_checkout_page_info() {
$checkout_pages = array();
Ryan Szrama
committed
$checkout_pages['payment'] = array(
Ryan Szrama
committed
'title' => t('Payment'),
'help' => t('Use the button below to proceed to the payment server.'),
Ryan Szrama
committed
'status_cart' => FALSE,
Ryan Szrama
committed
'locked' => TRUE,
'buttons' => FALSE,
Ryan Szrama
committed
'weight' => 20,
);
Ryan Szrama
committed
return $checkout_pages;
Ryan Szrama
committed
}
/**
* Implements hook_commerce_checkout_pane_info().
*/
function commerce_payment_commerce_checkout_pane_info() {
$checkout_panes = array();
Ryan Szrama
committed
$checkout_panes['commerce_payment'] = array(
Ryan Szrama
committed
'title' => t('Payment'),
Ryan Szrama
committed
'page' => 'review',
Ryan Szrama
committed
'file' => 'includes/commerce_payment.checkout_pane.inc',
'base' => 'commerce_payment_pane',
Ryan Szrama
committed
'weight' => 10,
);
Ryan Szrama
committed
$checkout_panes['commerce_payment_redirect'] = array(
Ryan Szrama
committed
'title' => t('Off-site payment redirect'),
'page' => 'payment',
'locked' => TRUE,
'file' => 'includes/commerce_payment.checkout_pane.inc',
'base' => 'commerce_payment_redirect_pane',
Ryan Szrama
committed
);
Ryan Szrama
committed
return $checkout_panes;
Ryan Szrama
committed
}
Damien Tournoud
committed
/**
* Moves an order ahead to the next page via an order update and redirect.
*
* Redirected payment methods are responsible for calling this method when
* receiving external notifications of successful payment.
*
* @param $order
* An order object.
* @param $log
* Optional log message to use when updating the order status in conjunction
* with the redirect to the next checkout page.
Damien Tournoud
committed
*/
function commerce_payment_redirect_pane_next_page($order, $log = '') {
Damien Tournoud
committed
// Load the order status object for the current order.
$order_status = commerce_order_status_load($order->status);
if ($order_status['state'] == 'checkout' && $order_status['checkout_page'] == 'payment') {
$payment_page = commerce_checkout_page_load($order_status['checkout_page']);
$next_page = $payment_page['next_page'];
$order = commerce_order_status_update($order, 'checkout_' . $next_page, FALSE, NULL, $log);
Damien Tournoud
committed
// Inform modules of checkout completion if the next page is Completed.
if ($next_page == 'complete') {
commerce_checkout_complete($order);
}
}
}
/**
* Moves an order back to the previous page via an order update and redirect.
*
* Redirected payment methods are responsible for calling this method when
* receiving external notifications of failed payment.
*
* @param $order
* An order object.
* @param $log
* Optional log message to use when updating the order status in conjunction
* with the redirect to the previous checkout page.
Damien Tournoud
committed
*/
function commerce_payment_redirect_pane_previous_page($order, $log = '') {
Damien Tournoud
committed
// Load the order status object for the current order.
$order_status = commerce_order_status_load($order->status);
if ($order_status['state'] == 'checkout' && $order_status['checkout_page'] == 'payment') {
$payment_page = commerce_checkout_page_load($order_status['checkout_page']);
$prev_page = $payment_page['prev_page'];
$order = commerce_order_status_update($order, 'checkout_' . $prev_page, FALSE, NULL, $log);
Damien Tournoud
committed
}
}
Ryan Szrama
committed
/**
* Implements hook_commerce_payment_totals_row_info().
*/
function commerce_payment_commerce_payment_totals_row_info($totals, $order) {
$rows = array();
if (count($totals) == 0) {
// Add a row for the remaining balance on the order.
if ($order) {
$balance = commerce_payment_order_balance($order, $totals);
$rows[] = array(
'data' => array(
array('data' => t('Order balance'), 'class' => array('label')),
array('data' => commerce_currency_format($balance['amount'], $balance['currency_code']), 'class' => array('balance')),
),
'class' => array('order-balance'),
'weight' => 10,
);
}
}
elseif (count($totals) == 1) {
// Otherwise if there's only a single currency total...
Ryan Szrama
committed
$currency_code = key($totals);
Ryan Szrama
committed
// Add a row for the total amount paid.
$rows[] = array(
'data' => array(
array('data' => t('Total paid'), 'class' => array('label')),
array('data' => commerce_currency_format($totals[$currency_code], $currency_code), 'class' => array('total')),
),
'class' => array('total-paid'),
'weight' => 0,
);
// Add a row for the remaining balance on the order.
if ($order) {
$balance = commerce_payment_order_balance($order, $totals);
Roman Khimin
committed
// Fix false balances.
if (empty($balance)) {
$formatted_amount = commerce_currency_format(0, NULL);
}
else {
$formatted_amount = commerce_currency_format($balance['amount'], $balance['currency_code']);
}
Ryan Szrama
committed
$rows[] = array(
'data' => array(
array('data' => t('Order balance'), 'class' => array('label')),
Roman Khimin
committed
array('data' => $formatted_amount, 'class' => array('balance')),
Ryan Szrama
committed
),
'class' => array('order-balance'),
'weight' => 10,
);
}
}
else {
$weight = 0;
foreach ($totals as $currency_code => $amount) {
$rows[] = array(
'data' => array(
array('data' => t('Total paid (@currency_code)', array('@currency_code' => $currency_code)), 'class' => array('label')),
array('data' => commerce_currency_format($amount, $currency_code), 'class' => array('total')),
),
'class' => array('total-paid', 'total-' . $currency_code),
'weight' => $weight++,
);
}
}
return $rows;
}
Ryan Szrama
committed
/**
* Implements hook_commerce_payment_transaction_insert().
*
* When a new payment transaction is inserted that is already completed, check
* the order balance and invoke a Rules event if the order is paid in full.
*/
Ryan Szrama
committed
function commerce_payment_commerce_payment_transaction_insert($transaction) {
Ryan Szrama
committed
// If the inserted transaction was marked as a success and placed against a
// valid order...
Simon Morvan
committed
$transaction_statuses = commerce_payment_transaction_statuses();
if (!empty($transaction_statuses[$transaction->status]['total']) &&
Ryan Szrama
committed
$order = commerce_order_load($transaction->order_id)) {
// Then check to make sure the event hasn't been invoked for this order.
if (empty($order->data['commerce_payment_order_paid_in_full_invoked'])) {
// Check the order balance and invoke the event.
$balance = commerce_payment_order_balance($order);
if (!empty($balance) && $balance['amount'] <= 0) {
// If automatic order revisions are enabled site-wide, create a new
// revision now with a log message identifying the payment event.
if (variable_get('commerce_order_auto_revision', TRUE)) {
$order->revision = TRUE;
$order->log = t('Order updated to reflect the order has just been paid in full.');
}
Ryan Szrama
committed
// Invoke the event including a hook of the same name.
rules_invoke_all('commerce_payment_order_paid_in_full', $order, $transaction);
// Update the order's data array to indicate this just happened.
Ryan Szrama
committed
$order->data['commerce_payment_order_paid_in_full_invoked'] = REQUEST_TIME;
Ryan Szrama
committed
// Save the updated order.
commerce_order_save($order);
}
}
}
}
/**
* Implements hook_commerce_payment_transaction_update().
*
* When an existing transaction is updated from an incomplete status to
* completed, check the order balance and invoke a Rules event if the order is
* paid in full.
*/
Ryan Szrama
committed
function commerce_payment_commerce_payment_transaction_update($transaction) {
commerce_payment_commerce_payment_transaction_insert($transaction);
Ryan Szrama
committed
}
/**
* Implements hook_commerce_order_delete().
*
* Make sure all payment transactions are deleted whenever the
* order they are associated with is deleted.
*/
function commerce_payment_commerce_order_delete($order) {
foreach (commerce_payment_transaction_load_multiple(array(), array('order_id' => $order->order_id)) as $transaction) {
commerce_payment_transaction_delete($transaction->transaction_id);
}
}
Ryan Szrama
committed
/**
* Implements hook_views_api().
*/
function commerce_payment_views_api() {
return array(
Ryan Szrama
committed
'path' => drupal_get_path('module', 'commerce_payment') . '/includes/views',
);
}
/**
* Returns an array of payment methods defined by enabled modules.
*
* @return
* An associative array of payment method objects keyed by the method_id.
Ryan Szrama
committed
*/
function commerce_payment_methods() {
$payment_methods = &drupal_static(__FUNCTION__);
Ryan Szrama
committed
// If the payment methods haven't been defined yet, do so now.
if (!isset($payment_methods)) {
$payment_methods = array();
// Build the payment methods array, including module names for the purpose
// of including files if necessary.
foreach (module_implements('commerce_payment_method_info') as $module) {
foreach (module_invoke($module, 'commerce_payment_method_info') as $method_id => $payment_method) {
$payment_method['method_id'] = $method_id;
$payment_method['module'] = $module;
$payment_methods[$method_id] = $payment_method;
}
}
drupal_alter('commerce_payment_method_info', $payment_methods);
Ryan Szrama
committed
foreach ($payment_methods as $method_id => &$payment_method) {
$defaults = array(
'method_id' => $method_id,
'base' => $method_id,
Ryan Szrama
committed
'title' => '',
'description' => '',
Ryan Szrama
committed
'active' => FALSE,
'checkout' => TRUE,
'terminal' => TRUE,
'offsite' => FALSE,
Ryan Szrama
committed
'offsite_autoredirect' => FALSE,
Ryan Szrama
committed
'callbacks' => array(),
'file' => '',
Ryan Szrama
committed
);
$payment_method += $defaults;
Ryan Szrama
committed
// Default the display title to the title if necessary. The display title
// is used in instances where the payment method has an official name used
// as the title (i.e. PayPal WPS) but a different method of display on
// selection forms (like some text and a set of images).
if (empty($payment_method['display_title'])) {
$payment_method['display_title'] = $payment_method['title'];
Ryan Szrama
committed
}
// Default the short title to the title if necessary. Like the display
// title, the short title is an alternate way of displaying the title to
// the user consisting of plain text but with unnecessary information
// stripped off. The payment method title might be PayPal WPS as it
// distinguishes itself from other PayPal payment services, but you would
// only want to display PayPal to the customer as their means of payment.
if (empty($payment_methods[$method_id]['short_title'])) {
$payment_method['short_title'] = $payment_method['title'];
Ryan Szrama
committed
}
Ryan Szrama
committed
// Merge in default callbacks.
Christophe Van Gysel
committed
foreach (array('settings_form', 'submit_form', 'submit_form_validate', 'submit_form_submit', 'redirect_form', 'redirect_form_back', 'redirect_form_validate', 'redirect_form_submit') as $callback) {
if (!isset($payment_method['callbacks'][$callback])) {
$payment_method['callbacks'][$callback] = $payment_method['base'] . '_' . $callback;
Ryan Szrama
committed
}
}
}
}
return $payment_methods;
Ryan Szrama
committed
}
Bojan Živanović
committed
/**
* Resets the cached list of payment methods.
*/
function commerce_payment_methods_reset() {
$payment_methods = &drupal_static('commerce_payment_methods');
$payment_methods = NULL;
entity_info_cache_clear();
}
Ryan Szrama
committed
/**
* Returns a payment method array.
*
* @param $method_id
* The ID of the payment method to return.
*
* @return
* The fully loaded payment method object or FALSE if not found.
Ryan Szrama
committed
*/
function commerce_payment_method_load($method_id) {
Ryan Szrama
committed
$payment_methods = commerce_payment_methods();
return isset($payment_methods[$method_id]) ? $payment_methods[$method_id] : FALSE;
Ryan Szrama
committed
}
/**
* Returns the title of any or all payment methods.
*
* @param $title
* String indicating which title to return, either 'title', 'display_title',
* or 'short_title'.
* @param $method
* Optional parameter specifying the payment method whose title to return.
*
* @return
* Either an array of all payment method titles keyed by the machine name or a
* string containing the title for the specified type. If a type is specified
* that does not exist, this function returns FALSE.
*/
function commerce_payment_method_get_title($title = 'title', $method = NULL) {
$payment_methods = commerce_payment_methods();
// Return a method title if specified and it exists.
if (!empty($method)) {
if (isset($payment_methods[$method])) {
return $payment_methods[$method][$title];
}
else {
// Return FALSE if it does not exist.
return FALSE;
}
}
// Otherwise create an array of all payment method titles.
$titles = array();
foreach ($payment_methods as $key => $value) {
$titles[$key] = $value[$title];
return $titles;
}
/**
* Wraps commerce_payment_method_get_title() for the Entity module.
*/
function commerce_payment_method_options_list() {
return commerce_payment_method_get_title();
}
Ryan Szrama
committed
/**
* Returns the specified callback for the given payment method if it exists.
*
* @param $payment_method
* The payment method object.
* @param $callback
* The callback function to return, one of:
* - settings_form
* - submit_form
* - submit_form_validate
* - submit_form_submit
* - redirect_form
Christophe Van Gysel
committed
* - redirect_form_back
Ryan Szrama
committed
* - redirect_form_validate
* - redirect_form_submit
*
* @return
* A string containing the name of the callback function or FALSE if it could
* not be found.
*/
function commerce_payment_method_callback($payment_method, $callback) {
// Include the payment method file if specified.
if (!empty($payment_method['file'])) {
$parts = explode('.', $payment_method['file']);
module_load_include(array_pop($parts), $payment_method['module'], implode('.', $parts));
}
Ryan Szrama
committed
// If the specified callback function exists, return it.
if (!empty($payment_method['callbacks'][$callback]) &&
is_callable($payment_method['callbacks'][$callback])) {
return $payment_method['callbacks'][$callback];
Ryan Szrama
committed
}
// Otherwise return FALSE.
return FALSE;
}
/**
* Returns a payment method instance ID given a payment method ID and the Rule
* containing an enabling action with settings.
*
* @param $method_id
* The ID of the payment method.
* @param $rule
* The Rules configuration object used to provide settings for the method.
*
* @return
* A string used as the payment method instance ID.
*/
function commerce_payment_method_instance_id($method_id, $rule) {
$parts = array($method_id, $rule->name);
return implode('|', $parts);
}
/**
Sven Decabooter
committed
* Returns a payment method instance array which includes the settings specific
* to the context of the instance.
*
* @param $instance_id
* A payment method instance ID in the form of a pipe delimited string
* containing the method_id and the enabling Rule's name.
*
* @return
* The payment method instance object which is identical to the payment method
* object with the addition of the settings array.
*/
function commerce_payment_method_instance_load($instance_id) {
Ryan Szrama
committed
// Return FALSE if there is no pipe delimeter in the instance ID.
Ryan Szrama
committed
if (strpos($instance_id, '|') === FALSE) {
Ryan Szrama
committed
return FALSE;
}
// Explode the method key into its component parts.
list($method_id, $rule_name) = explode('|', $instance_id);
Ryan Szrama
committed
// Return FALSE if we didn't receive a proper instance ID.
if (empty($method_id) || empty($rule_name)) {
return FALSE;
}
// First load the payment method and add the instance ID.
$payment_method = commerce_payment_method_load($method_id);
$payment_method['instance_id'] = $instance_id;
// Then load the Rule configuration that enables the method.
$rule = rules_config_load($rule_name);
// Return FALSE if it couldn't be loaded.
if (empty($rule)) {
return FALSE;
}
// Iterate over its actions to find one with the matching element ID and pull
// its settings into the payment method object.
$payment_method['settings'] = array();
foreach ($rule->actions() as $action) {
Lucas Hedding
committed
if (is_callable(array($action, 'getElementName')) && $action->getElementName() == 'commerce_payment_enable_' . $method_id) {
if (is_array($action->settings['payment_method']) && !empty($action->settings['payment_method']['settings'])) {
$payment_method['settings'] = $action->settings['payment_method']['settings'];
}
}
}
return $payment_method;
}
Ryan Szrama
committed
/**
* Returns an array of transaction payment status objects for the defined
* payment statuses.
*
* This function invokes hook_commerce_payment_transaction_status_info() so
* other payment modules can define statuses if necessary. However, it doesn't
* allow for altering so that existing payment methods cannot be unset. It still
* does perform an array merge in such a way that the properties for the three
* core statuses defined by this module may be overridden if the same keys are
* used in another module's implementation of the info hook.
*/
function commerce_payment_transaction_statuses() {
Ryan Szrama
committed
$transaction_statuses = &drupal_static(__FUNCTION__);
Ryan Szrama
committed
// If the statuses haven't been defined yet, do so now.
Ryan Szrama
committed
if (!isset($transaction_statuses)) {
$transaction_statuses = module_invoke_all('commerce_payment_transaction_status_info');
Ryan Szrama
committed
Ryan Szrama
committed
$transaction_statuses += array(
COMMERCE_PAYMENT_STATUS_PENDING => array(
Ryan Szrama
committed
'status' => COMMERCE_PAYMENT_STATUS_PENDING,
'title' => t('Pending'),
Ryan Szrama
committed
'icon' => drupal_get_path('module', 'commerce_payment') . '/theme/icon-pending.png',
Ryan Szrama
committed
'total' => FALSE,
),
COMMERCE_PAYMENT_STATUS_SUCCESS => array(
Ryan Szrama
committed
'status' => COMMERCE_PAYMENT_STATUS_SUCCESS,
'title' => t('Success'),
'icon' => drupal_get_path('module', 'commerce_payment') . '/theme/icon-success.png',
'total' => TRUE,
),
COMMERCE_PAYMENT_STATUS_FAILURE => array(
Ryan Szrama
committed
'status' => COMMERCE_PAYMENT_STATUS_FAILURE,
'title' => t('Failure'),
'icon' => drupal_get_path('module', 'commerce_payment') . '/theme/icon-failure.png',
'total' => FALSE,
),
);
}
Ryan Szrama
committed
return $transaction_statuses;
Ryan Szrama
committed
}
foopang
committed
/**
* Returns an options list of payment transaction statuses.
*/
function commerce_payment_transaction_status_options_list() {
// Build an array of payment transaction status options.
$options = array();
foreach(commerce_payment_transaction_statuses() as $payment_transaction_status) {
$options[$payment_transaction_status['status']] = $payment_transaction_status['title'];
}
return $options;
}
Matt Glaman
committed
/**
* Themes the payment transaction entity.
*/
function theme_commerce_payment_transaction($variables) {
return render($variables['content']);
}
Ryan Szrama
committed
/**
* Themes the icon representing a payment transaction status.
*/
function theme_commerce_payment_transaction_status_icon($variables) {
Ryan Szrama
committed
$transaction_status = $variables['transaction_status'];
Mark Halliwell
committed
return theme('image', array('path' => $transaction_status['icon'], 'alt' => $transaction_status['title'], 'title' => $transaction_status['title'], 'attributes' => array('class' => array(drupal_html_class($transaction_status['status'])))));
Ryan Szrama
committed
}
/**
* Themes a text value related to a payment transaction status.
*/
function theme_commerce_payment_transaction_status_text($variables) {
Ryan Szrama
committed
$transaction_status = $variables['transaction_status'];
Ryan Szrama
committed
return '<span class="' . drupal_html_class($transaction_status['status']) . '">' . $variables['text'] . '</span>';
Ryan Szrama
committed
}
/**
* Returns the payment transaction status object for the specified status.
*
* @param $status
* The transaction status string.
*
* @return
* An object containing the transaction status information or FALSE if the
* requested status is not found.
*/
function commerce_payment_transaction_status_load($status) {
Ryan Szrama
committed
$transaction_statuses = commerce_payment_transaction_statuses();
return !empty($transaction_statuses[$status]) ? $transaction_statuses[$status] : FALSE;
Ryan Szrama
committed
}
/**
* Returns an initialized payment transaction object.
*
* @param $method_id
* The method_id of the payment method for the transaction.
*
* @return
* A transaction object with all default fields initialized.
*/
Ryan Szrama
committed
function commerce_payment_transaction_new($method_id = '', $order_id = 0) {
return entity_get_controller('commerce_payment_transaction')->create(array(
Ryan Szrama
committed
'payment_method' => $method_id,
'order_id' => $order_id,
));
}
/**
* Saves a payment transaction.
*
* @param $transaction
* The full transaction object to save.
*
* @return
Ryan Szrama
committed
* SAVED_NEW or SAVED_UPDATED depending on the operation performed.
*/
function commerce_payment_transaction_save($transaction) {
Ryan Szrama
committed
return entity_get_controller('commerce_payment_transaction')->save($transaction);
890
891
892
893
894
895
896
897
898
899
900
901
902
903
904
905
906
907
908
909
910
911
912
913
914
915
916
}
/**
* Loads a payment transaction by ID.
*/
function commerce_payment_transaction_load($transaction_id) {
$transactions = commerce_payment_transaction_load_multiple(array($transaction_id), array());
return $transactions ? reset($transactions) : FALSE;
}
/**
* Loads multiple payment transaction by ID or based on a set of matching conditions.
*
* @see entity_load()
*
* @param $transaction_ids
* An array of transaction IDs.
* @param $conditions
* An array of conditions on the {commerce_payment_transaction} table in the
* form 'field' => $value.
* @param $reset
* Whether to reset the internal transaction loading cache.
*
* @return
* An array of transaction objects indexed by transaction_id.
*/
function commerce_payment_transaction_load_multiple($transaction_ids = array(), $conditions = array(), $reset = FALSE) {
Ryan Szrama
committed
return entity_load('commerce_payment_transaction', $transaction_ids, $conditions, $reset);
918
919
920
921
922
923
924
925
926
927
928
929
930
931
932
933
934
935
936
937
938
939
940
941
942
943
944
945
}
/**
* Deletes a payment transaction by ID.
*
* @param $transaction_id
* The ID of the transaction to delete.
*
* @return
* TRUE on success, FALSE otherwise.
*/
function commerce_payment_transaction_delete($transaction_id) {
return commerce_payment_transaction_delete_multiple(array($transaction_id));
}
/**
* Deletes multiple payment transactions by ID.
*
* @param $transaction_ids
* An array of transaction IDs to delete.
*
* @return
* TRUE on success, FALSE otherwise.
*/
function commerce_payment_transaction_delete_multiple($transaction_ids) {
return entity_get_controller('commerce_payment_transaction')->delete($transaction_ids);
}
/**
* Determines access for a variety of operations on payment transactions.
*
* @param $op
* The operation being performed, one of view, update, create, or delete.
* @param $transaction
* The payment transaction to check.
* @param $account
* The user account attempting the operation; defaults to the current user.
*
* @return
* TRUE or FALSE indicating access for the operation.
*/
959
960
961
962
963
964
965
966
967
968
969
970
971
972
973
974
975
976
977
978
979
980
981
982
983
984
985
986
function commerce_payment_transaction_access($op, $transaction, $account = NULL) {
if (isset($transaction->order_id)) {
$order = commerce_order_load($transaction->order_id);
if (!$order) {
return FALSE;
}
}
else {
$order = NULL;
}
return commerce_payment_transaction_order_access($op, $order, $account);
}
/**
* Determines access for a variety of operations for payment transactions on a given order.
*
* @param $op
* The payment transaction operation being performed, one of view, update, create, or delete.
* @param $order
* The order to check against (optional if $op == 'create').
* @param $account
* The user account attempting the operation; defaults to the current user.
*
* @return
* TRUE or FALSE indicating access for the operation.
*/
function commerce_payment_transaction_order_access($op, $order, $account = NULL) {
global $user;
if (empty($account)) {
$account = clone($user);
}
// Grant administrators access to do anything.
if (user_access('administer payments', $account)) {
return TRUE;
}
switch ($op) {
// Creating new payment transactions.
case 'create':