mirror of
https://github.com/valitydev/rbkmoney-cms-drupal-ubercart.git
synced 2024-11-06 02:15:23 +00:00
582 lines
18 KiB
Plaintext
582 lines
18 KiB
Plaintext
<?php
|
||
|
||
/**
|
||
* @file
|
||
* Integrates RBKmoney's payment service.
|
||
*/
|
||
|
||
module_load_include('inc', 'rbkmoney_checkout_ubercart', 'includes/rbkmoney_checkout_ubercart_settings');
|
||
|
||
/**
|
||
* Implements hook_permission().
|
||
*/
|
||
function rbkmoney_checkout_ubercart_permission()
|
||
{
|
||
return [
|
||
'administer rbkmoney_checkout_ubercart' => [
|
||
'title' => t('Administer RBKmoney'),
|
||
'description' => t('Access RBKmoney administration page.'),
|
||
],
|
||
];
|
||
}
|
||
|
||
|
||
/**
|
||
* Implements hook_menu().
|
||
*/
|
||
function rbkmoney_checkout_ubercart_menu()
|
||
{
|
||
$items['admin/store/settings/rbkmoney_checkout_ubercart'] = [
|
||
'title' => 'RBKmoney',
|
||
'description' => 'Settings RBKmoney payment gateway',
|
||
'page callback' => 'drupal_get_form',
|
||
'page arguments' => ['rbkmoney_checkout_ubercart_setup'],
|
||
'access arguments' => ['administer rbkmoney_checkout_ubercart'],
|
||
'type' => MENU_NORMAL_ITEM,
|
||
];
|
||
|
||
$items['rbkmoney_checkout_ubercart/success'] = [
|
||
'title' => 'Internal Data',
|
||
'page callback' => 'rbkmoney_checkout_ubercart_payment_end',
|
||
'page arguments' => ['success'],
|
||
'access arguments' => ['access content'],
|
||
'type' => MENU_CALLBACK,
|
||
];
|
||
|
||
$items['rbkmoney_checkout_ubercart/callback/result'] = [
|
||
'title' => 'Callback',
|
||
'page callback' => 'rbkmoney_checkout_ubercart_callback_result',
|
||
'access arguments' => ['access content'],
|
||
'type' => MENU_CALLBACK,
|
||
'file' => 'includes/rbkmoney_checkout_ubercart_callback.pages.inc',
|
||
];
|
||
|
||
return $items;
|
||
}
|
||
|
||
/**
|
||
* Callback for settings page.
|
||
*/
|
||
function rbkmoney_checkout_ubercart_setup()
|
||
{
|
||
$form['uc_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']['uc_rbkmoney_shop_id'] = [
|
||
'#type' => 'textfield',
|
||
'#title' => t('Shop ID'),
|
||
'#default_value' => variable_get('uc_rbkmoney_shop_id', 'TEST'),
|
||
'#description' => t('Идентификатор магазина из RBKmoney. Скопируйте его в Личном кабинете RBKmoney в разделе Детали магазина, поле Идентификатор'),
|
||
'#required' => TRUE,
|
||
];
|
||
|
||
$form['tab1']['uc_rbkmoney_merchant_callback_public_key'] = [
|
||
'#type' => 'textarea',
|
||
'#title' => t('Публичный ключ из <a href=\'!dblog\'>https://dashboard.rbk.money</a>',
|
||
['!dblog' => "https://dashboard.rbk.money"]),
|
||
'#default_value' => MERCHANT_CALLBACK_PUBLIC_KEY,
|
||
'#description' => t('Ключ для обработки уведомлений о смене статуса'),
|
||
'#rows' => 10,
|
||
'#cols' => 10,
|
||
'#resizable' => FALSE,
|
||
'#weight' => 10,
|
||
'#required' => TRUE,
|
||
];
|
||
|
||
$form['tab1']['uc_rbkmoney_merchant_private_key'] = [
|
||
'#type' => 'textarea',
|
||
'#title' => t('Приватный ключ из <a href=\'!dblog\'>https://dashboard.rbk.money</a>',
|
||
['!dblog' => "https://dashboard.rbk.money"]),
|
||
'#default_value' => MERCHANT_PRIVATE_KEY,
|
||
'#description' => t('Ключ для доступа к API. Скопируйте его в Личном кабинете RBKmoney в разделе API Ключ'),
|
||
'#rows' => 10,
|
||
'#cols' => 10,
|
||
'#resizable' => FALSE,
|
||
'#weight' => 10,
|
||
'#required' => TRUE,
|
||
];
|
||
|
||
$form['tab2'] = array(
|
||
'#type' => 'fieldset',
|
||
'#title' => t('Кастомизация формы оплаты'),
|
||
'#collapsible' => TRUE,
|
||
'#group' => 'vertical_tabs',
|
||
);
|
||
|
||
$form['tab2']['uc_rbkmoney_payform_button_label'] = [
|
||
'#type' => 'textfield',
|
||
'#title' => t('Текст кнопки открытия формы оплаты'),
|
||
'#default_value' => variable_get('uc_rbkmoney_payform_button_label', ''),
|
||
'#description' => t(''),
|
||
'#required' => FALSE,
|
||
];
|
||
|
||
$form['tab2']['uc_rbkmoney_payform_description'] = [
|
||
'#type' => 'textfield',
|
||
'#title' => t('Описание в форме оплаты'),
|
||
'#default_value' => variable_get('uc_rbkmoney_payform_description', ''),
|
||
'#description' => t(''),
|
||
'#required' => FALSE,
|
||
];
|
||
|
||
$form['tab2']['uc_rbkmoney_payform_company_name'] = [
|
||
'#type' => 'textfield',
|
||
'#title' => t('Название магазина для отображения на форме оплаты'),
|
||
'#default_value' => variable_get('uc_rbkmoney_payform_company_name', ''),
|
||
'#description' => t(''),
|
||
'#required' => FALSE,
|
||
];
|
||
|
||
$form['tab2']['uc_rbkmoney_payform_css_button'] = [
|
||
'#type' => 'textarea',
|
||
'#title' => t('Стилизация кнопки открытия формы оплаты'),
|
||
'#default_value' => variable_get('uc_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']['uc_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('uc_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://webhooks.developer.rbk.money',
|
||
['attributes' =>
|
||
['target' => '_blank']
|
||
])),
|
||
);
|
||
|
||
$form['tab4']['docs_checkout'] = array(
|
||
'#type' => 'item',
|
||
'#markup' => t(l('Документация по кастомизации платежной формы', 'https://developer.rbk.money/integrations/checkout/#html-api',
|
||
['attributes' =>
|
||
['target' => '_blank']
|
||
])),
|
||
);
|
||
|
||
return system_settings_form($form);
|
||
}
|
||
|
||
/**
|
||
* Implements hook_uc_payment_method().
|
||
*/
|
||
function rbkmoney_checkout_ubercart_uc_payment_method()
|
||
{
|
||
$img = theme('image', [
|
||
'path' => PAYMENT_METHOD_PATH_IMG_LOGO,
|
||
'alt' => 'RBKmoney',
|
||
'attributes' => [
|
||
'class' => 'system_logo'
|
||
]
|
||
]
|
||
);
|
||
$title = t('RBKmoney') . '<br />' . $img;
|
||
$methods[] = [
|
||
'id' => 'rbkmoney',
|
||
'name' => t('RBKmoney'),
|
||
'title' => $title,
|
||
'desc' => t('RBKmoney'),
|
||
'weight' => 1,
|
||
'callback' => 'uc_payment_method_rbkmoney',
|
||
'checkout' => TRUE,
|
||
//'no_gateway' => TRUE,
|
||
];
|
||
|
||
return $methods;
|
||
}
|
||
|
||
/**
|
||
* Implements hook_payment_method
|
||
*/
|
||
function uc_payment_method_rbkmoney()
|
||
{
|
||
return;
|
||
}
|
||
|
||
/**
|
||
* Implements hook_form_alter() for uc_cart_checkout_review_form().
|
||
*/
|
||
function rbkmoney_checkout_ubercart_form_alter(&$form, &$form_state, $form_id)
|
||
{
|
||
$order_id = isset($_SESSION['cart_order']) ? intval($_SESSION['cart_order']) : 0;
|
||
|
||
if ($form_id == 'uc_cart_checkout_review_form' && $order_id > 0) {
|
||
$order = uc_order_load($order_id);
|
||
|
||
if ($order->payment_method == 'rbkmoney') {
|
||
unset($form['actions']['submit']);
|
||
|
||
if (empty($_SESSION[API_INVOICE_ID]) || empty($_SESSION[API_INVOICE_ACCESS_TOKEN])) {
|
||
$response = _rbkmoney_checkout_ubercart_create_invoice($order);
|
||
|
||
$invoice_id = $response["invoice"]["id"];
|
||
$access_token = $response["invoiceAccessToken"]["payload"];
|
||
|
||
$_SESSION[API_INVOICE_ID] = $invoice_id;
|
||
$_SESSION[API_INVOICE_ACCESS_TOKEN] = $access_token;
|
||
} else {
|
||
$invoice_id = $_SESSION[API_INVOICE_ID];
|
||
$access_token = $_SESSION[API_INVOICE_ACCESS_TOKEN];
|
||
}
|
||
|
||
$form_company_name = variable_get('uc_rbkmoney_payform_company_name');
|
||
$company_name = !empty($form_company_name) ? 'data-name="' . $form_company_name . '"' : '';
|
||
|
||
$form_button_label = variable_get('uc_rbkmoney_payform_button_label');
|
||
$button_label = !empty($form_button_label) ? 'data-label="' . $form_button_label . '"' : '';
|
||
|
||
$form_description = variable_get('uc_rbkmoney_payform_description');
|
||
$description = !empty($form_description) ? 'data-description="' . $form_description . '"' : '';
|
||
|
||
|
||
$payframe = '<form action="' . PAYMENT_FORM_SUCCESS_URL . '" method="' . HTTP_METHOD_GET . '">
|
||
<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>
|
||
</form>';
|
||
|
||
$payform_css_button = variable_get('uc_rbkmoney_payform_css_button', PAYMENT_FORM_DEFAULT_CSS_BUTTON);
|
||
$css_button = '<style>' . strip_tags($payform_css_button) . '</style>';
|
||
|
||
$form['#prefix'] = '<table><tr><td>';
|
||
$form['#suffix'] = '</td><td>' . $css_button . $payframe . '</td></tr></table>';
|
||
}
|
||
|
||
}
|
||
|
||
}
|
||
|
||
/**
|
||
* Returns the description and subtotal of the products on an order.
|
||
*/
|
||
function _rbkmoney_checkout_ubercart_product_details($items)
|
||
{
|
||
$desc = '';
|
||
if (!empty($items)) {
|
||
foreach ($items as $item) {
|
||
if (!empty($desc)) {
|
||
$desc .= ', ';
|
||
}
|
||
$desc .= $item->qty . 'x ' . check_plain($item->title);
|
||
}
|
||
}
|
||
|
||
return $desc;
|
||
}
|
||
|
||
function rbkmoney_checkout_ubercart_hook_form($form, &$form_state, $order)
|
||
{
|
||
$order = uc_order_load($_SESSION['cart_order']);
|
||
|
||
$form['shopId'] = [
|
||
'#type' => 'hidden',
|
||
'#value' => variable_get('uc_rbkmoney_shop_id'),
|
||
];
|
||
|
||
$form['orderId'] = [
|
||
'#type' => 'hidden',
|
||
'#value' => $order->order_id,
|
||
];
|
||
|
||
$form['amount'] = [
|
||
'#type' => 'hidden',
|
||
'#value' => $order->order_total,
|
||
];
|
||
|
||
$form['user_email'] = [
|
||
'#type' => 'hidden',
|
||
'#value' => $order->primary_email,
|
||
];
|
||
|
||
$form['#action'] = '#';
|
||
$form['submit'] = [
|
||
'#type' => 'button',
|
||
'#value' => t('Place your order'),
|
||
'#attributes' => ['class' => ['ctools-use-modal']],
|
||
'#id' => 'go'
|
||
];
|
||
|
||
return $form;
|
||
}
|
||
|
||
/**
|
||
* Payment request.
|
||
*/
|
||
function rbkmoney_checkout_ubercart_submit_form($form, &$form_state, $order)
|
||
{
|
||
$order = uc_order_load($_SESSION['cart_order']);
|
||
|
||
$form['shopId'] = [
|
||
'#type' => 'hidden',
|
||
'#value' => variable_get('uc_rbkmoney_shop_id'),
|
||
];
|
||
|
||
$form['orderId'] = [
|
||
'#type' => 'hidden',
|
||
'#value' => $order->order_id,
|
||
];
|
||
|
||
$form['amount'] = [
|
||
'#type' => 'hidden',
|
||
'#value' => $order->order_total,
|
||
];
|
||
|
||
$form['user_email'] = [
|
||
'#type' => 'hidden',
|
||
'#value' => $order->primary_email,
|
||
];
|
||
|
||
$form['#action'] = '#';
|
||
$form['submit'] = [
|
||
'#type' => 'button',
|
||
'#value' => t('Place your order'),
|
||
'#attributes' => ['class' => ['ctools-use-modal']],
|
||
'#id' => 'go'
|
||
];
|
||
|
||
return $form;
|
||
}
|
||
|
||
/**
|
||
* Callback redirect from RBKmoney site.
|
||
*/
|
||
function rbkmoney_checkout_ubercart_payment_end($arg)
|
||
{
|
||
switch ($arg) {
|
||
case 'success':
|
||
if (isset($_SESSION['cart_order'])) {
|
||
$_SESSION['uc_checkout'][$_SESSION['cart_order']]['do_complete'] = TRUE;
|
||
if (!empty($_SESSION[API_INVOICE_ID])) unset($_SESSION[API_INVOICE_ID]);
|
||
if (!empty($_SESSION[API_INVOICE_ACCESS_TOKEN])) unset($_SESSION[API_INVOICE_ACCESS_TOKEN]);
|
||
drupal_goto('cart/checkout/complete');
|
||
}
|
||
break;
|
||
|
||
case 'fail':
|
||
if (isset($_SESSION['cart_order'])) {
|
||
unset($_SESSION['cart_order']);
|
||
if (!empty($_SESSION[API_INVOICE_ID])) unset($_SESSION[API_INVOICE_ID]);
|
||
if (!empty($_SESSION[API_INVOICE_ACCESS_TOKEN])) unset($_SESSION[API_INVOICE_ACCESS_TOKEN]);
|
||
drupal_set_message(t('Ваш платеж отклонен.'), 'error');
|
||
drupal_goto('cart');
|
||
}
|
||
break;
|
||
}
|
||
|
||
return;
|
||
}
|
||
|
||
function _rbkmoney_checkout_ubercart_create_invoice($order)
|
||
{
|
||
$shopId = variable_get('uc_rbkmoney_shop_id');
|
||
$data = [
|
||
'shopID' => $shopId,
|
||
'amount' => _rbkmoney_checkout_ubercart_prepare_amount($order->order_total),
|
||
'metadata' => _rbkmoney_checkout_ubercart_prepare_metadata($order),
|
||
'dueDate' => _rbkmoney_checkout_ubercart_prepare_due_date(),
|
||
'currency' => $order->currency,
|
||
'product' => $order->order_id,
|
||
'description' => _rbkmoney_checkout_ubercart_product_details($order->products),
|
||
];
|
||
|
||
$url = _rbkmoney_checkout_ubercart_prepare_api_url('processing/invoices');
|
||
$headers = _rbkmoney_checkout_ubercart_prepare_headers();
|
||
$response = _rbkmoney_checkout_ubercart_send($url, $headers, drupal_json_encode($data), 'init_invoice');
|
||
if ($response['http_code'] != HTTP_CODE_CREATED) {
|
||
drupal_set_message(t('Что-то пошло не так! Мы уже знаем и работаем над этим!'), 'error');
|
||
drupal_goto('cart');
|
||
}
|
||
|
||
return json_decode($response['body'], true);
|
||
}
|
||
|
||
function _rbkmoney_checkout_ubercart_prepare_headers()
|
||
{
|
||
$headers = array();
|
||
$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 _rbkmoney_checkout_ubercart_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 _rbkmoney_checkout_ubercart_prepare_metadata($order)
|
||
{
|
||
return [
|
||
'cms' => 'drupal',
|
||
'cms_version' => VERSION,
|
||
'module' => MODULE_NAME,
|
||
'order_id' => $order->order_id,
|
||
];
|
||
}
|
||
|
||
/**
|
||
* Prepare amount (e.g. 124.24 -> 12424)
|
||
*
|
||
* @param $amount int
|
||
* @return int
|
||
*/
|
||
function _rbkmoney_checkout_ubercart_prepare_amount($amount)
|
||
{
|
||
if ($amount < 0) {
|
||
drupal_set_message(t('Сумма заказа меньше допустимой'), 'error');
|
||
drupal_goto('cart');
|
||
}
|
||
return $amount * 100;
|
||
}
|
||
|
||
function _rbkmoney_checkout_ubercart_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,
|
||
];
|
||
|
||
_rbkmoney_checkout_ubercart_logger($type, "<pre>%logs</pre>",
|
||
[
|
||
'%logs' => var_export($logs, TRUE)
|
||
]
|
||
);
|
||
curl_close($curl);
|
||
|
||
return $response;
|
||
}
|
||
|
||
/**
|
||
* Update status order
|
||
*
|
||
* @param string $order_id
|
||
* @param string $invoice_status
|
||
*/
|
||
function _rbkmoney_checkout_ubercart_update_status_order($order_id = '', $invoice_status = '')
|
||
{
|
||
_rbkmoney_checkout_ubercart_logger('update_status_order_req', 'order_id: ' . $order_id . '; invoice status: ' . $invoice_status);
|
||
$order = uc_order_load($order_id);
|
||
// if the user is anonymous - always equals zero
|
||
$uid = isset($order->uid) ? $order->uid : ANONYMOUS_USER_ID;
|
||
|
||
switch ($invoice_status) {
|
||
case UC_RBKMONEY_STATUS_FAILED:
|
||
uc_order_update_status($order_id, 'canceled');
|
||
uc_order_comment_save($order_id, $uid, t('Order canceled'), $type = 'admin', $status = 1, $notify = FALSE);
|
||
$status = UC_RBKMONEY_STATUS_FAILED;
|
||
break;
|
||
case UC_RBKMONEY_STATUS_SUCCESS:
|
||
uc_payment_enter($order_id, 'RBKmoney', $order->order_total, $uid, NULL, NULL);
|
||
uc_order_update_status($order_id, 'completed');
|
||
uc_cart_complete_sale($order);
|
||
uc_order_comment_save($order_id, $uid, t('RBKmoney: payment successful'), $type = 'admin', $status = 1, $notify = FALSE);
|
||
$status = UC_RBKMONEY_STATUS_SUCCESS;
|
||
break;
|
||
default:
|
||
$status = $invoice_status;
|
||
break;
|
||
}
|
||
_rbkmoney_checkout_ubercart_logger('update_status_order_res', 'order status: ' . $status . '; order_id: ' . $order_id);
|
||
}
|
||
|
||
function _rbkmoney_checkout_ubercart_prepare_api_url($path = '', $query_params = [])
|
||
{
|
||
$url = rtrim(API_URL, '/') . '/' . $path;
|
||
if (!empty($query_params)) {
|
||
$url .= '?' . http_build_query($query_params);
|
||
}
|
||
|
||
return $url;
|
||
}
|
||
|
||
function _rbkmoney_checkout_ubercart_logger($type, $message, $variables = [])
|
||
{
|
||
if (variable_get('uc_rbkmoney_log', 1)) {
|
||
watchdog(MODULE_NAME . '_' . $type, $message, $variables);
|
||
}
|
||
}
|