rbkmoney-cms-drupal-commerce/commerce_rbkmoney.module
2018-09-20 17:19:17 +03:00

498 lines
17 KiB
Plaintext
Raw Permalink Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

<?php
module_load_include('inc', 'commerce_rbkmoney', 'includes/commerce_rbkmoney_settings');
/**
* Implements hook_permission().
*/
function commerce_rbkmoney_permission()
{
return [
'administer commerce_rbkmoney' => [
'title' => t('Administer Commerce ' . COMPANY_NAME),
'description' => t('Access the Commerce ' . COMPANY_NAME . ' settings page'),
],
];
}
/**
* Implements hook_menu().
*/
function commerce_rbkmoney_menu()
{
$items['admin/commerce/config/rbkmoney'] = [
'title' => 'RBKmoney configuration',
'page callback' => 'drupal_get_form',
'page arguments' => ['commerce_rbkmoney_config'],
'access arguments' => ['administer commerce_rbkmoney'],
'type' => MENU_NORMAL_ITEM,
];
$items['commerce/rbkmoney/callback/result'] = [
'title' => 'Status',
'page callback' => 'commerce_rbkmoney_callback_result',
'access arguments' => ['access content'],
'type' => MENU_CALLBACK,
'file' => 'includes/commerce_rbkmoney_callback.pages.inc',
];
$items['commerce/rbkmoney/success'] = [
'title' => 'Internal Data',
'page callback' => 'commerce_rbkmoney_payment_end',
'page arguments' => ['success'],
'access arguments' => ['access content'],
'type' => MENU_CALLBACK,
];
$items['commerce/rbkmoney/fail'] = [
'title' => 'Internal Data',
'page callback' => 'commerce_rbkmoney_payment_end',
'page arguments' => ['fail'],
'access arguments' => ['access content'],
'type' => MENU_CALLBACK,
];
return $items;
}
/**
* Implements hook_commerce_payment_method_info().
*/
function commerce_rbkmoney_commerce_payment_method_info()
{
$payment_methods = [];
// The system name of the payment method.
$payment_methods[MODULE_NAME] = [
// Name of payment method to display in the admin area.
'title' => t(COMPANY_NAME),
// The description of the payment method. Optional.
'description' => t('Payment via ' . COMPANY_NAME . ' payment system'),
// TRUE or FALSE indicating whether or not payments can be processed
// via this payment method through the administrative payment
// terminal on an orders Payment tab Optional. Defaults to TRUE.
'terminal' => FALSE,
// Whether the buyer to leave the website for payment by this method.
// Optional. Defaults to FALSE.
'offsite' => TRUE,
// As a payment method when you enable the module: TRUE — enabled, FALSE — disabled
// (the default). Optional.
'active' => TRUE,
// Automatically redirect to third party website for payment in this way.
// Optional. Defaults to FALSE.
'offsite_autoredirect' => FALSE,
];
return $payment_methods;
}
/**
* Payment method settings form.
*/
function commerce_rbkmoney_config()
{
$form['commerce_rbkmoney_help'] = [
'#markup' => t('Настройки платежного модуля RBKmoney'),
];
$form['vertical_tabs'] = array(
'#type' => 'vertical_tabs',
'#default_tab' => 'edit-tab1',
);
$form['tab1'] = array(
'#type' => 'fieldset',
'#title' => t('Обязательные настройки'),
'#collapsible' => TRUE,
'#group' => 'vertical_tabs',
);
$form['tab1']['commerce_rbkmoney_shop_id'] = [
'#type' => 'textfield',
'#title' => t('ID магазина'),
'#default_value' => variable_get('commerce_rbkmoney_shop_id', 'Shop_ID'),
'#description' => t(''),
'#required' => TRUE,
];
$form['tab1']['commerce_rbkmoney_merchant_callback_public_key'] = [
'#type' => 'textarea',
'#title' => t('Ключ подписи получаемых на Webhook уведомлений из <a href=\'!dblog\'>https://dashboard.rbk.money/api/webhooks</a>',
['!dblog' => "https://dashboard.rbk.money/api/webhooks"]),
'#default_value' => MERCHANT_CALLBACK_PUBLIC_KEY,
'#description' => t(''),
'#rows' => 10,
'#cols' => 10,
'#resizable' => FALSE,
'#weight' => 10,
'#required' => TRUE,
];
$form['tab1']['commerce_rbkmoney_merchant_private_key'] = [
'#type' => 'textarea',
'#title' => t('Ваш ключ для доступа к API из <a href=\'!dblog\'>https://dashboard.rbk.money/api/key</a>',
['!dblog' => "https://dashboard.rbk.money/api/key"]),
'#default_value' => MERCHANT_PRIVATE_KEY,
'#description' => t(''),
'#rows' => 10,
'#cols' => 10,
'#resizable' => FALSE,
'#weight' => 10,
'#required' => TRUE,
];
$form['tab2'] = array(
'#type' => 'fieldset',
'#title' => t('Кастомизация формы оплаты'),
'#collapsible' => TRUE,
'#group' => 'vertical_tabs',
);
$form['tab2']['commerce_rbkmoney_payform_button_label'] = [
'#type' => 'textfield',
'#title' => t('Текст кнопки открытия формы оплаты'),
'#default_value' => variable_get('commerce_rbkmoney_payform_button_label', ''),
'#description' => t(''),
'#required' => FALSE,
];
$form['tab2']['commerce_rbkmoney_payform_description'] = [
'#type' => 'textfield',
'#title' => t('Описание в форме оплаты'),
'#default_value' => variable_get('commerce_rbkmoney_payform_description', ''),
'#description' => t(''),
'#required' => FALSE,
];
$form['tab2']['commerce_rbkmoney_payform_company_name'] = [
'#type' => 'textfield',
'#title' => t('Название магазина для отображения на форме оплаты'),
'#default_value' => variable_get('commerce_rbkmoney_payform_company_name', ''),
'#description' => t(''),
'#required' => FALSE,
];
$form['tab2']['commerce_rbkmoney_payform_css_button'] = [
'#type' => 'textarea',
'#title' => t('Стилизация кнопки открытия формы оплаты'),
'#default_value' => variable_get('commerce_rbkmoney_payform_css_button', PAYMENT_FORM_DEFAULT_CSS_BUTTON),
'#description' => t(''),
'#rows' => 10,
'#cols' => 10,
'#resizable' => FALSE,
'#weight' => 10,
'#required' => FALSE,
];
$form['tab3'] = array(
'#type' => 'fieldset',
'#title' => t('Дополнительные настройки'),
'#collapsible' => TRUE,
'#group' => 'vertical_tabs',
);
$form['tab3']['common_settings']['commerce_rbkmoney_log'] = [
'#type' => 'radios',
'#title' => t('Сохранять лог RBKmoney API в <a href=\'!dblog\'>system log</a>',
['!dblog' => url(BASE_URL . '/#overlay=admin/reports/dblog')]),
'#options' => [1 => t('Yes'), 0 => t('No')],
'#default_value' => variable_get('commerce_rbkmoney_log', 1),
];
$form['tab4'] = array(
'#type' => 'fieldset',
'#title' => t('Документация'),
'#collapsible' => TRUE,
'#group' => 'vertical_tabs',
);
$form['tab4']['docs_integrations'] = array(
'#type' => 'item',
'#markup' => t(l('Документация по интеграции', 'https://developer.rbk.money/',
['attributes' =>
['target' => '_blank']
])),
);
$form['tab4']['docs_webhooks'] = array(
'#type' => 'item',
'#markup' => t(l('Документация для работы с вебхуками', 'https://rbkmoney.github.io/webhooks-events-api/',
['attributes' =>
['target' => '_blank']
])),
);
$form['tab4']['docs_checkout'] = array(
'#type' => 'item',
'#markup' => t(l('Документация по кастомизации платежной формы', 'https://developer.rbk.money/docs/payments/checkout/#html-api',
['attributes' =>
['target' => '_blank']
])),
);
return system_settings_form($form);
}
/*
* Payment method callback
*/
function commerce_rbkmoney_redirect_form($form, &$form_state, $order, $payment_method)
{
if ($order->order_id > 0 && $payment_method['method_id'] == MODULE_NAME) {
if (empty($_SESSION[API_INVOICE_ID])) {
$response = _commerce_rbkmoney_create_invoice($order);
$response_decode = drupal_json_decode($response['body']);
$invoice_id = !empty($response_decode['invoice']['id']) ? $response_decode['invoice']['id'] : '';
$access_token = !empty($response_decode['invoiceAccessToken']['payload']) ? $response_decode['invoiceAccessToken']['payload'] : '';
$_SESSION[API_INVOICE_ID] = $invoice_id;
} else {
$invoice_id = $_SESSION[API_INVOICE_ID];
}
$company_name = (!empty(variable_get('commerce_rbkmoney_payform_company_name'))) ? 'data-name="' . variable_get('commerce_rbkmoney_payform_company_name') . '"' : '';
$button_label = (!empty(variable_get('commerce_rbkmoney_payform_button_label'))) ? 'data-label="' . variable_get('commerce_rbkmoney_payform_button_label') . '"' : '';
$description = (!empty(variable_get('commerce_rbkmoney_payform_description'))) ? 'data-description="' . variable_get('commerce_rbkmoney_payform_description') . '"' : '';
$action = BASE_URL . '/commerce/rbkmoney/success?order_id=' . $order->order_id;
$payframe = '<script src="' . PAYMENT_FORM_URL . '" class="rbkmoney-checkout"
data-invoice-id="' . $invoice_id . '"
data-invoice-access-token="' . $access_token . '"
' . $company_name . '
' . $button_label . '
' . $description . '
>
</script>';
$css_button = '<style>' . strip_tags(variable_get('commerce_rbkmoney_payform_css_button', PAYMENT_FORM_DEFAULT_CSS_BUTTON)) . '</style>';
$form['#action'] = $action;
$text = $css_button . '<form></form>';
$form['info'] = ['#markup' => $text];
$form['order_id'] = ['#type' => 'hidden', '#value' => $order->order_id];
$form['payment_details']['#prefix'] = '<div id="payment-details"><form action="' . $action . '" method="' . HTTP_METHOD_POST . '">' . $payframe;
$form['payment_details']['#suffix'] = '</form></div>';
}
return $form;
}
/**
* Payment method callback: submit form.
*/
function commerce_rbkmoney_submit_form($payment_method, $pane_values, $checkout_pane, $order)
{
$form = [];
$text = theme('image',
[
'path' => PAYMENT_METHOD_PATH_IMG_LOGO,
'alt' => t(COMPANY_NAME),
'title' => t(COMPANY_NAME),
'attributes' => ['class' => 'rbkmoney-logo']
]
);
$text .= '<div class="rbkmoney">' . t('Pay with credit card') . '<br /></div>';
$form['info'] = ['#markup' => $text];
return $form;
}
function _commerce_rbkmoney_update_status_order($order_id, $status)
{
$order = commerce_order_load($order_id);
$order_wrapper = entity_metadata_wrapper('commerce_order', $order);
$amount = _commerce_rbkmoney_prepare_amount($order_wrapper);
$currency_code = _commerce_rbkmoney_prepare_currency($order_wrapper);
switch ($status) {
case RBKMONEY_STATUS_FAILED:
$transaction = commerce_payment_transaction_new(MODULE_NAME, $order->order_id);
$transaction->instance_id = $order->data['payment_method'];
$transaction->amount = $amount;
$transaction->currency_code = $currency_code;
$transaction->status = COMMERCE_PAYMENT_STATUS_FAILURE;
$transaction->message = t('Response from RBK Money: failure');
commerce_payment_transaction_save($transaction);
_commerce_rbkmoney_logger(MODULE_NAME, "status: {" . RBKMONEY_STATUS_FAILED . "}; data: <pre>%log</pre>", ['%log' => var_export(['order_id' => $order_id, 'status' => $status], TRUE)]);
break;
case RBKMONEY_STATUS_SUCCESS:
$transaction = commerce_payment_transaction_new(MODULE_NAME, $order->order_id);
$transaction->instance_id = $order->data['payment_method'];
$transaction->amount = $amount;
$transaction->currency_code = $currency_code;
$transaction->status = COMMERCE_PAYMENT_STATUS_SUCCESS;
$transaction->message = t('Response from RBK Money: successful');
commerce_payment_transaction_save($transaction);
_commerce_rbkmoney_logger(MODULE_NAME, "status: {" . RBKMONEY_STATUS_SUCCESS . "}; data: <pre>%log</pre>", ['%log' => var_export(['order_id' => $order_id, 'status' => $status], TRUE)]);
break;
default:
_commerce_rbkmoney_logger(MODULE_NAME, "Fail update status; data: <pre>%log</pre>", ['%log' => var_export(['order_id' => $order_id, 'status' => $status], TRUE)]);
}
}
/**
* Callback redirect from RBKmoney site.
*/
function commerce_rbkmoney_payment_end($arg)
{
if (!empty($_SESSION[API_INVOICE_ID])) unset($_SESSION[API_INVOICE_ID]);
if (empty($_GET['order_id'])) $arg = 'fail';
switch ($arg) {
case "success":
drupal_set_message(t("Your payment processed."));
drupal_goto('cart');
break;
case "fail":
drupal_set_message(t("Your payment has been declined."), 'error');
drupal_goto('cart');
break;
}
return;
}
function _commerce_rbkmoney_create_invoice($order)
{
$order_wrapper = entity_metadata_wrapper('commerce_order', $order);
$data = [
'shopID' => variable_get('commerce_rbkmoney_shop_id'),
'amount' => _commerce_rbkmoney_prepare_amount($order_wrapper),
'metadata' => _commerce_rbkmoney_prepare_metadata($order),
'dueDate' => _commerce_rbkmoney_prepare_due_date(),
'currency' => _commerce_rbkmoney_prepare_currency($order_wrapper),
'product' => $order->order_id,
'description' => "",
];
$url = _commerce_rbkmoney_prepare_api_url('processing/invoices');
$headers = _commerce_rbkmoney_prepare_headers();
$response = _commerce_rbkmoney_send($url, $headers, drupal_json_encode($data), 'init_invoice');
if ($response['http_code'] != HTTP_CODE_CREATED) {
drupal_set_message(t('An error occurred while creating invoice'), 'error');
drupal_goto('cart');
}
return $response;
}
function _commerce_rbkmoney_prepare_headers()
{
$headers = [];
$headers[] = 'X-Request-ID: ' . uniqid();
$headers[] = 'Authorization: Bearer ' . MERCHANT_PRIVATE_KEY;
$headers[] = 'Content-type: application/json; charset=utf-8';
$headers[] = 'Accept: application/json';
return $headers;
}
/**
* Prepare due date
* @return string
*/
function _commerce_rbkmoney_prepare_due_date()
{
date_default_timezone_set('UTC');
return date(CREATE_INVOICE_TEMPLATE_DUE_DATE, strtotime(CREATE_INVOICE_DUE_DATE));
}
/**
* Prepare metadata
*
* @param $order Object
* @return array
*/
function _commerce_rbkmoney_prepare_metadata($order)
{
return [
'cms' => 'drupal',
'cms_version' => VERSION,
'module' => MODULE_NAME,
'order_id' => $order->order_id,
];
}
/**
* Prepare amount
*
* @param $amount int
* @return int
*/
function _commerce_rbkmoney_prepare_amount($order_wrapper)
{
$amount = $order_wrapper->commerce_order_total->amount->value();
if ($amount < 0) {
drupal_set_message(t('Requested amount less than allowed'), 'error');
drupal_goto('cart');
}
return $amount;
}
function _commerce_rbkmoney_prepare_currency($order_wrapper)
{
return $order_wrapper->commerce_order_total->currency_code->value();
}
function _commerce_rbkmoney_send($url = '', $headers = [], $data = '', $type = '')
{
$request = [
'url' => $url,
'method' => HTTP_METHOD_POST,
'body' => $data,
'headers' => $headers,
];
$curl = curl_init($url);
curl_setopt($curl, CURLOPT_POST, TRUE);
curl_setopt($curl, CURLOPT_POSTFIELDS, $data);
curl_setopt($curl, CURLOPT_SSL_VERIFYHOST, FALSE);
curl_setopt($curl, CURLOPT_SSL_VERIFYPEER, FALSE);
curl_setopt($curl, CURLOPT_RETURNTRANSFER, TRUE);
curl_setopt($curl, CURLOPT_HTTPHEADER, $headers);
$body = curl_exec($curl);
$info = curl_getinfo($curl);
$curl_errno = curl_errno($curl);
$response['http_code'] = $info['http_code'];
$response['body'] = $body;
$response['error'] = $curl_errno;
$logs = [
'request' => $request,
'response' => $response,
];
_commerce_rbkmoney_logger($type, "<pre>%logs</pre>", ['%logs' => var_export($logs, TRUE)]);
curl_close($curl);
return $response;
}
function _commerce_rbkmoney_prepare_api_url($path = '', $query_params = [])
{
$url = rtrim(API_URL, '/') . '/' . $path;
if (!empty($query_params)) {
$url .= '?' . http_build_query($query_params);
}
return $url;
}
function _commerce_rbkmoney_logger($type, $message, $variables = [])
{
if (variable_get('commerce_rbkmoney_log', 1)) {
watchdog(MODULE_NAME . '_' . $type, $message, $variables);
}
}