View source
<?php
require "Mollie/API/Autoloader.php";
function commerce_mollie_init() {
if (strtolower(commerce_default_currency()) != 'eur') {
drupal_set_message(t('The Commerce Mollie payment module only supports the Euro as the default currency'), 'error');
}
}
function commerce_mollie_menu() {
$items = array();
$items['commerce_mollie/webhook'] = array(
'page callback' => 'commerce_mollie_webhook',
'access arguments' => array(
'access content',
),
'type' => MENU_CALLBACK,
);
$items['checkout/%commerce_order/payment/response/%'] = array(
'title' => 'Commerce Mollie Payment',
'page callback' => 'commerce_mollie_return',
'page arguments' => array(
1,
4,
),
'access arguments' => array(
'access content',
),
'type' => MENU_CALLBACK,
);
$items['admin/commerce/orders/%commerce_order/payment/%commerce_payment_transaction/mollie-status-request'] = array(
'title' => 'Request payment status',
'page callback' => 'drupal_get_form',
'page arguments' => array(
'commerce_mollie_request_payment_status_form',
3,
5,
),
'access callback' => 'commerce_mollie_transfer_transaction_confirm_access',
'access arguments' => array(
3,
5,
),
'type' => MENU_DEFAULT_LOCAL_TASK,
'context' => MENU_CONTEXT_INLINE,
'weight' => 2,
);
return $items;
}
function commerce_mollie_permission() {
$perms = array();
$perms['mollie payment status request'] = array(
'title' => t('Request payment status'),
'description' => t('Perform a request with Mollie about the status of a Payment.'),
);
return $perms;
}
function commerce_mollie_transfer_transaction_confirm_access($order, $transaction = NULL, $account = NULL) {
if (user_access('mollie payment status request')) {
$access = commerce_payment_transaction_access('update', $transaction, $account);
if ($access && $transaction) {
if ($transaction->payment_method != 'commerce_mollie') {
$access = FALSE;
}
}
return $access;
}
return FALSE;
}
function commerce_mollie_commerce_payment_method_info() {
$payment_methods = array();
$payment_methods['commerce_mollie'] = array(
'title' => t('Mollie'),
'description' => t('Integrates Mollie payment services support.'),
'active' => TRUE,
'offsite' => TRUE,
'offsite_autoredirect' => FALSE,
);
return $payment_methods;
}
function commerce_mollie_settings_form($settings = NULL) {
$form = array();
$settings = (array) $settings + array(
'commerce_mollie_api_key_live' => '',
'commerce_mollie_api_key_test' => '',
'commerce_mollie_test_mode' => 0,
'commerce_mollie_redirect_page_button_text' => 'Pay via Mollie',
'commerce_mollie_redirect_page_text' => 'Continue with checkout to complete payment via Mollie.',
);
$form['commerce_mollie_api_key_live'] = array(
'#type' => 'textfield',
'#title' => t('Mollie live API key'),
'#description' => t('Your Mollie live API key.'),
'#default_value' => $settings['commerce_mollie_api_key_live'],
'#required' => TRUE,
'#element_validate' => array(
'_commerce_mollie_api_key_element_validate',
),
);
$form['commerce_mollie_api_key_test'] = array(
'#type' => 'textfield',
'#title' => t('Mollie test API key'),
'#description' => t('Your Mollie test API key.'),
'#default_value' => $settings['commerce_mollie_api_key_test'],
'#required' => TRUE,
'#element_validate' => array(
'_commerce_mollie_api_key_element_validate',
),
);
$form['commerce_mollie_test_mode'] = array(
'#type' => 'checkbox',
'#title' => t('Enable test mode'),
'#description' => t('Check this option to enable test mode.'),
'#default_value' => $settings['commerce_mollie_test_mode'],
);
$form['commerce_mollie_redirect_page_button_text'] = array(
'#type' => 'textfield',
'#title' => t('Payment button text'),
'#description' => t('The text of the payment button that redirects the user to the Mollie website.'),
'#default_value' => $settings['commerce_mollie_redirect_page_button_text'],
'#required' => TRUE,
);
$form['commerce_mollie_redirect_page_text'] = array(
'#type' => 'textarea',
'#title' => t('Payment page text'),
'#description' => t('The text displayed above the payment button that redirects the user to the Mollie website.'),
'#default_value' => $settings['commerce_mollie_redirect_page_text'],
'#required' => FALSE,
);
return $form;
}
function commerce_mollie_redirect_form($form, &$form_state, $order, $payment_method) {
$wrapper = entity_metadata_wrapper('commerce_order', $order);
$amount = $wrapper->commerce_order_total->amount
->value();
$currency_code = $wrapper->commerce_order_total->currency_code
->value();
$payment_description = t("Order @order_id - @site_name", array(
'@order_id' => $order->order_number,
'@site_name' => variable_get('site_name', ''),
));
$transaction = commerce_payment_transaction_new('commerce_mollie', $order->order_id);
$transaction->instance_id = $payment_method['instance_id'];
$transaction->amount = $amount;
$transaction->status = COMMERCE_PAYMENT_STATUS_PENDING;
$transaction->currency_code = $currency_code;
commerce_payment_transaction_save($transaction);
$redirect_url = url('checkout/' . $order->order_id . '/payment/response/' . $order->data['payment_redirect_key'], array(
'absolute' => TRUE,
));
$webhook_url = url('commerce_mollie/webhook', array(
'absolute' => TRUE,
));
try {
$mollie = new Mollie_API_Client();
$mollie
->setApiKey($payment_method['settings']['commerce_mollie_test_mode'] ? $payment_method['settings']['commerce_mollie_api_key_test'] : $payment_method['settings']['commerce_mollie_api_key_live']);
$payment = $mollie->payments
->create(array(
"amount" => commerce_currency_amount_to_decimal($amount, $currency_code),
"description" => $payment_description,
"redirectUrl" => $redirect_url,
"webhookUrl" => $webhook_url,
"metadata" => array(
"order_id" => $order->order_id,
"transaction_id" => $transaction->transaction_id,
"currency_code" => $currency_code,
),
));
$transaction->remote_id = $payment->id;
commerce_payment_transaction_save($transaction);
$form['#action'] = $payment
->getPaymentUrl();
$form['mollie_information'] = array(
'#markup' => '<p class="commerce-mollie-info">' . t($payment_method['settings']['commerce_mollie_redirect_page_text']) . '</p>',
);
$form['submit'] = array(
'#type' => 'submit',
'#value' => t($payment_method['settings']['commerce_mollie_redirect_page_button_text']),
);
} catch (Mollie_API_Exception $e) {
watchdog('commerce_mollie', 'Could not create a Mollie payment. Error: %error', array(
'%error' => htmlspecialchars($e
->getMessage()),
), WATCHDOG_ERROR);
drupal_set_message(t('An error occured while preparing your Mollie payment. Please try again or contact the webmaster.'), 'error');
drupal_goto('cart/checkout');
}
return $form;
}
function commerce_mollie_return($order, $payment_redirect_key) {
if ($payment_redirect_key == $order->data['payment_redirect_key']) {
$transaction_query = new EntityFieldQuery();
$transaction_query
->entityCondition('entity_type', 'commerce_payment_transaction')
->propertyCondition('status', 'failure', '!=')
->propertyCondition('order_id', $order->order_id);
$transaction = $transaction_query
->execute();
if (!empty($transaction['commerce_payment_transaction'])) {
$transaction = entity_load('commerce_payment_transaction', array_keys($transaction['commerce_payment_transaction']));
$transaction = reset($transaction);
}
else {
$transaction = NULL;
}
if (!empty($transaction)) {
$transaction = commerce_mollie_request_status($order, $transaction);
commerce_payment_transaction_save($transaction);
if ($transaction->status == COMMERCE_PAYMENT_STATUS_FAILURE) {
drupal_set_message(t('You cancelled your payment. Please proceed again or choose a different payment option.'));
commerce_payment_redirect_pane_previous_page($order);
drupal_goto('checkout/' . $order->order_id . '/payment/back/' . $order->data['payment_redirect_key']);
}
else {
commerce_payment_redirect_pane_next_page($order);
drupal_goto('checkout/' . $order->order_id . '/payment/return/' . $order->data['payment_redirect_key']);
}
}
else {
commerce_payment_redirect_pane_previous_page($order);
drupal_goto('checkout/' . $order->order_id . '/payment/back/' . $order->data['payment_redirect_key']);
}
}
else {
watchdog('commerce_mollie', 'Return payment url used with incorrect redirect key.', array(), WATCHDOG_WARNING);
drupal_not_found();
}
}
function commerce_mollie_webhook() {
$payment_method = _commerce_mollie_get_payment_method_instance();
try {
$mollie = new Mollie_API_Client();
$mollie
->setApiKey($payment_method['settings']['commerce_mollie_test_mode'] ? $payment_method['settings']['commerce_mollie_api_key_test'] : $payment_method['settings']['commerce_mollie_api_key_live']);
$payment = $mollie->payments
->get($_POST["id"]);
$transaction = commerce_payment_transaction_load($payment->metadata->transaction_id);
$order = commerce_order_load($payment->metadata->order_id);
if ($payment
->isPaid() == TRUE) {
$transaction->status = COMMERCE_PAYMENT_STATUS_SUCCESS;
$transaction->message = t('Successful Mollie payment with transaction ID: %transaction_id for order ID: %order_id', array(
'%transaction_id' => $payment->metadata->transaction_id,
'%order_id' => $payment->metadata->order_id,
));
commerce_payment_redirect_pane_next_page($order);
}
else {
if ($payment
->isOpen() == FALSE) {
$transaction->status = COMMERCE_PAYMENT_STATUS_FAILURE;
$transaction->message = t('Mollie payment with transaction ID: %transaction_id for order ID: %order_id failed', array(
'%transaction_id' => $payment->metadata->transaction_id,
'%order_id' => $payment->metadata->order_id,
));
commerce_payment_redirect_pane_previous_page($order);
}
}
watchdog('commerce_mollie', $transaction->message, array(), WATCHDOG_NOTICE);
commerce_payment_transaction_save($transaction);
} catch (Mollie_API_Exception $e) {
watchdog('commerce_mollie', 'Could not load Mollie payment from webhook call. Error: %error', array(
'%error' => htmlspecialchars($e
->getMessage()),
), WATCHDOG_ERROR);
}
}
function commerce_mollie_request_payment_status_form($form, &$form_state, $order, $transaction) {
$transaction = commerce_mollie_request_status($order, $transaction);
commerce_payment_transaction_save($transaction);
drupal_goto('admin/commerce/orders/' . $order->order_id . '/payment');
return $form;
}
function commerce_mollie_request_status($order, $transaction) {
$payment_method = _commerce_mollie_get_payment_method_instance();
try {
$mollie = new Mollie_API_Client();
$mollie
->setApiKey($payment_method['settings']['commerce_mollie_test_mode'] ? $payment_method['settings']['commerce_mollie_api_key_test'] : $payment_method['settings']['commerce_mollie_api_key_live']);
$payment = $mollie->payments
->get($transaction->remote_id);
if (!empty($payment)) {
switch ($payment->status) {
case 'open':
case 'pending':
$transaction->status = COMMERCE_PAYMENT_STATUS_PENDING;
$transaction->remote_status = $payment->status;
$transaction->message = commerce_mollie_status_explained($payment->status);
break;
case 'cancelled':
case 'expired':
$transaction->status = COMMERCE_PAYMENT_STATUS_FAILURE;
$transaction->remote_status = $payment->status;
$transaction->message = commerce_mollie_status_explained($payment->status);
break;
case 'paid':
case 'paidout':
$transaction->status = COMMERCE_PAYMENT_STATUS_SUCCESS;
$transaction->remote_status = $payment->status;
$transaction->message = commerce_mollie_status_explained($payment->status);
break;
default:
break;
}
return $transaction;
}
} catch (Mollie_API_Exception $e) {
watchdog('commerce_mollie', 'Could not retrieve payment information. Error: %error', array(
'%error' => htmlspecialchars($e
->getMessage()),
), WATCHDOG_ERROR);
drupal_set_message(t('An error occured while retrieving payment status information from Mollie. Please try again later or contact your webmaster.'), 'error');
}
return $transaction;
}
function _commerce_mollie_get_payment_method_instance() {
$payment_method = FALSE;
$event = rules_get_cache('event_commerce_payment_methods');
foreach ($event
->getIterator() as $rule) {
foreach ($rule
->actions() as $action) {
if ($action
->getElementName() == 'commerce_payment_enable_commerce_mollie') {
$instance_id = commerce_payment_method_instance_id('commerce_mollie', $rule);
$payment_method = commerce_payment_method_instance_load($instance_id);
}
}
}
return $payment_method;
}
function _commerce_mollie_api_key_element_validate($element, &$form_state, $form) {
if ($element['#title'] == 'Mollie live API key' && strpos($element['#value'], 'live') !== 0) {
form_error($element, t('Your Mollie live API key should start with <em>live</em>.'));
}
else {
if ($element['#title'] == 'Mollie test API key' && strpos($element['#value'], 'test') !== 0) {
form_error($element, t('Your Mollie test API key should start with <em>test</em>.'));
}
}
}
function commerce_mollie_status_explained($status) {
$status_messages = array(
'open' => t('The payment is created but nothing happened yet.'),
'cancelled' => t('The payment has been cancelled by the customer.'),
'pending' => t('The payment is in transit.'),
'expired' => t('The payment has expired.'),
'paid' => t('The payment has been paid.'),
'paidout' => t('The payment has been paid to your bank account.'),
'refunded' => t('The payment has had a refund to the customer.'),
);
if (array_key_exists($status, $status_messages)) {
return $status_messages[$status];
}
return '';
}