Каждый способ оплаты в Drupal Commerce это отдельный модуль.
Способы оплаты делятся на два вида:
On-site — когда для завершения оплаты не нужно покидать пределы сайта.
Off-site — когда для завершения оплаты нужно сделать редирект на сторонний сайт или отправить туда форму.
Процесс создания своего способа оплаты состоит из реализации хука hook_commerce_payment_method_info() и необходимых функций обратного вызова:
1. Реализуем хук hook_commerce_payment_method_info(), в котором возвращаем базовую информацию о способе оплаты:
/**
* Implements hook_commerce_payment_method_info().
*/
function mypaymentmethod_commerce_payment_method_info() {
return array(
// Системное название способа оплаты.
'mypaymentmethod' => array(
// Название способа оплаты для отображения в админке.
'title' => t('My Payment Method'),
// Название способа оплаты для отображения в форме чекаута. Может содержать html.
// Опционально.
'display_title' => t('My Payment Method'),
// Описание способа оплаты. Опционально.
'description' => t('Example of Payment Method'),
// Состояние способа оплаты при включении модуля: TRUE — включён, FALSE — выключен
// (по умолчанию). Опционально.
'active' => TRUE,
// Сможет ли администратор самостоятельно добавить этот способ оплаты для
// завершённого заказа. Опционально. По умолчанию TRUE.
'terminal' => TRUE,
// Нужно ли покупателю покидать пределы сайта при оплате заказа этим способом.
// Опционально. По умолчанию FALSE.
'offsite' => TRUE,
// Автоматический редирект на сторонний сайт при оплате заказа этим способом.
// Опционально. По умолчанию FALSE.
'offsite_autoredirect' => TRUE,
),
);
}
2. Если способ оплаты имеет настройки, то реализуем callback PAYMENTNAME_settings_form():
/**
* Payment method callback: settings form.
*/
function mypaymentmethod_settings_form($settings = NULL) {
$form = array();
$settings = (array)$settings + array('information' => '');
// Пример настройки — информация о способе оплаты
$form['information'] = array(
'#type' => 'textarea',
'#title' => t('Information'),
'#description' => t('Information you would like to be shown to users when they select this payment method.'),
'#default_value' => $settings['information'],
);
return $form;
}
3. Если при выборе способа оплаты нужно показывать какую-нибудь информацию или для оплаты от покупателя требуются дополнительные данные, то реализуем callback PAYMENTNAME_submit_form():
/**
* Payment method callback: submit form.
*/
function mypaymentmethod_submit_form($payment_method, $pane_values, $checkout_pane, $order) {
$form = array();
$pane_values += array('name' => '');
// Выводим информацию о способе оплаты
if (!empty($payment_method['settings']['information'])) {
$form['mypaymentmethod_information'] = array(
'#markup' => $payment_method['settings']['information']
);
}
// Дополнительные данные — поле для ввода имени
$form['name'] = array(
'#type' => 'textfield',
'#title' => t('Name'),
'#description' => t('Your full name.'),
'#default_value' => $pane_values['name'],
'#required' => TRUE,
);
return $form;
}
4. Если в прошлом пункте возвращается форма и нужно её проверять, то делаем это в PAYMENTNAME_submit_form_validate():
/**
* Payment method callback: submit form validation.
*/
function mypaymentmethod_submit_form_validate($payment_method, $pane_form, $pane_values, $order, $form_parents = array()) {
// Делаем проверку на длину имени
if (drupal_strlen($pane_values['name']) < 2) {
form_set_error(implode('][', array_merge($form_parents, array('name'))), t('You must enter a name two or more characters long.'));
return FALSE;
}
}
5. Если пользователя не нужно отсылать на сайт платёжной системы, то завершаем оплату в PAYMENTNAME_submit_form_submit():
/**
* Payment method callback: submit form submission.
*/
function mypamentmethod_submit_form_submit($payment_method, $pane_form, $pane_values, $order, $charge) {
$order->data['mypaymentmethod'] = $pane_values;
// Создаём транзакцию
$transaction = commerce_payment_transaction_new('mypamentmethod', $order->order_id);
$transaction->instance_id = $payment_method['instance_id'];
$transaction->amount = $charge['amount'];
$transaction->currency_code = $charge['currency_code'];
$transaction->status = COMMERCE_PAYMENT_STATUS_SUCCESS;
$transaction->message = t('The payment has completed.');
commerce_payment_transaction_save($transaction);
}
Иначе в PAYMENTNAME_redirect_form() формируем форму с данными, которые будут отправлены на сайт платёжной системы:
/**
* Payment method callback: payment redirect form.
*/
function mypaymentmethod_redirect_form($form, &$form_state, $order, $payment_method) {
$order_wrapper = entity_metadata_wrapper('commerce_order', $order);
// Адрес платёжного шлюза
$form['#action'] = 'https://example.com/payment';
// Пример данных — сумма заказа
$form['amount'] = array(
'#type' => 'hidden',
'#value' => $order_wrapper->commerce_order_total->amount->value(),
);
// Пример данных — адрес для редиректа после успешной оплаты
$form['redirect_uri'] = array(
'#type' => 'hidden',
'#value' => url('checkout/' . $order->order_id . '/payment/return/' . $order->data['payment_redirect_key'], array('absolute' => TRUE)),
);
// Пример данных — адрес для редиректа в случаем если оплата не состоялась
$form['error_uri'] = array(
'#type' => 'hidden',
'#value' => url('checkout/' . $order->order_id . '/payment/back/' . $order->data['payment_redirect_key'], array('absolute' => TRUE)),
);
$form['submit'] = array(
'#type' => 'submit',
'#value' => t('Pay'),
);
return $form;
}
После того как покупатель оплатит заказ на сайте платёжной системы и возвратится на страницу checkout/[order_id]/payment/return/[key], сначала будет вызван callback PAYMENTNAME_redirect_form_validate(), в котором можно проверить факт оплаты, а потом PAYMENTNAME_redirect_form_submit(), в котором нужно завершить оплату:
/**
* Payment method callback: redirect form return validation.
*/
function mypaymentmethod_redirect_form_validate($order, $payment_method) {
if (/* ... */) {
return TRUE; // будет вызван callback PAYMENTNAME_redirect_form_submit()
}
else {
return FALSE; // покупатель возвратится на шаг назад в форме чекаута
}
}
/**
* Payment method callback: redirect form submission.
*/
function mypaymentmethod_redirect_form_submit($order, $payment_method) {
$order_wrapper = entity_metadata_wrapper('commerce_order', $order);
// Создаём транзакцию
$transaction = commerce_payment_transaction_new('mypamentmethod', $order->order_id);
$transaction->instance_id = $payment_method['instance_id'];
$transaction->amount = $order_wrapper->commerce_order_total->amount->value();
$transaction->currency_code = $order_wrapper->commerce_order_total->currency_code->value();
$transaction->status = COMMERCE_PAYMENT_STATUS_SUCCESS;
$transaction->message = t('The payment has completed.');
commerce_payment_transaction_save($transaction);
}
Написанное актуально для
Drupal Commerce 1.x