yoomoney_api-2.5.2/yoo_commerce/yoo_commerce_api.module

yoo_commerce/yoo_commerce_api.module
<?php

use YooKassa\Common\Exceptions\ApiException;
use YooKassa\Model\Payment;
use YooKassa\Model\PaymentStatus;
use YooKassa\Request\Payments\CreatePaymentRequest;
use YooKassa\Request\Payments\CreatePaymentRequestBuilder;
use YooKassa\Request\Payments\CreatePaymentRequestSerializer;
use YooKassa\Request\Payments\Payment\CreateCaptureRequest;
use YooKassa\Request\Payments\Payment\CreateCaptureRequestBuilder;

require_once MODULE_PATH.DIRECTORY_SEPARATOR.'vendor'.DIRECTORY_SEPARATOR.'autoload.php';
require_once MODULE_PATH.DIRECTORY_SEPARATOR.'YooMoneyLogger.php';
require_once MODULE_PATH.DIRECTORY_SEPARATOR.'YooMoneyKassaLogger.php';

/**
 * Implements hook_commerce_order_presave().
 */
function yoo_commerce_api_commerce_order_presave($order)
{
    if (empty($order->original)) {
        return;
    }

    if ($order->status == $order->original->status) {
        return;
    }

    if (!yoomoney_api_is_need_second_receipt($order->status)) {
        return;
    }

    $orderInfo = array(
        'order_id'   => $order->order_id,
        'user_email' => empty($order->mail) ? null : $order->mail,
        'user_phone' => empty($order->phone) ? null : $order->phone,
    );

    $result = yoomoney_api_send_second_receipt($orderInfo);

    if (!$result->is_send) {
        return;
    }

    $order->log = $result->message;
}


/**
 * Implements hook_commerce_payment_method_info().
 */
function yoo_commerce_api_commerce_payment_method_info()
{
    $payment_methods = array();
    $icon_name       = 'yookassa-logo';
    $icon            = theme(
        'image',
        array(
            'path'       => drupal_get_path('module', 'yoo_commerce_api').'/images/'.$icon_name.'.png',
            'attributes' => array('class' => array('yoo-commerce-logo')),
        )
    );

    $display_title = t('YooKassa (bank card, e-money, etc.)');

    $display_title                      .= '<br/>'.$icon;
    $payment_methods['yoo_commerce_api'] = array(
        'base'                 => 'yoo_commerce_api',
        'title'                => t('YooMoney'),
        'short_title'          => t('YooMoney'),
        'display_title'        => $display_title,
        'description'          => t('Integration with YooMoney.'),
        'terminal'             => false,
        'offsite'              => true,
        'offsite_autoredirect' => true,
        'active'               => true,
    );

    return $payment_methods;
}

/**
 * Payment method callback: checkout form submission.
 *
 * @param $payment_method
 * @param $pane_form
 * @param $pane_values
 * @param $order
 * @param $charge
 * @throws \YooKassa\Common\Exceptions\ExtensionNotFoundException
 */
function yoo_commerce_api_submit_form_submit($payment_method, $pane_form, $pane_values, $order, $charge)
{
    global $user;
    $kassaLogger = getKassaLog();
    $kassaLogger->sendHeka(array('payment.create.init'));

    $apiClient = yoomoney_api__common__get_api_client();

    $order_wrapper = entity_metadata_wrapper('commerce_order', $order);
    $currency_code = $order_wrapper->commerce_order_total->currency_code->value();
    $amount        = $order_wrapper->commerce_order_total->amount->value();
    $amount        = round(commerce_currency_amount_to_decimal($amount, $currency_code), 2);

    $builder        = yoo_commerce_api_get_create_payment_request_builder($order, $amount,
        $order_wrapper);
    $paymentRequest = $builder->build();

    if ($paymentRequest->getReceipt() !== null) {
        $paymentRequest->getReceipt()->normalize($paymentRequest->getAmount());
    }

    $serializer     = new CreatePaymentRequestSerializer();
    $serializedData = $serializer->serialize($paymentRequest);
    YooMoneyLogger::info('Create payment request: '.json_encode($serializedData));
    try {
        $kassaLogger->sendHeka(array('payment.request.init'));
        $response = $apiClient->createPayment($paymentRequest);
        if ($response && $response->status !== PaymentStatus::CANCELED) {
            $transaction                = commerce_payment_transaction_new($payment_method['method_id'],
                $order->order_id);
            $transaction->instance_id   = $payment_method['instance_id'];
            $transaction->remote_id     = $response->id;
            $transaction->amount        = intval($amount) * 100;
            $transaction->currency_code = $currency_code;
            $transaction->status        = COMMERCE_PAYMENT_STATUS_PENDING;
            $transaction->remote_status = $response->getStatus();
            commerce_order_status_update($order, YOOMONEY_API_ORDER_STATUS_PENDING);
            $ymTransaction             = new YooMoneyApiTransaction();
            $ymTransaction->uid        = isset($user->uid) ? $user->uid : 0;
            $ymTransaction->amount     = $amount;
            $ymTransaction->mail       = isset($user->mail) ? $user->mail : $order->mail;
            $ymTransaction->order_id   = $order->order_id;
            $ymTransaction->payment_id = $response->getId();
            $ymTransaction->status     = $response->getStatus();
            if (commerce_payment_transaction_save($transaction) && commerce_order_save($order)
                && yoomoney_api_transaction_save($ymTransaction)
            ) {
                $confirmationUrl = $response->confirmation->confirmationUrl;
                $kassaLogger->sendHeka(array(
                    'payment.create.success',
                    'payment.request.success',
                    'payment.redirect.init')
                );
                drupal_goto($confirmationUrl);
            }
        } else {
            YooMoneyLogger::error('Payment not created. Order id: '.$order->order_number);
            drupal_set_message(t('Unable to create payment.'), 'error');
        }

    } catch (ApiException $e) {
        getKassaLog()->sendAlertLog('Failed to create payment', array(
            'methodid' => 'POST/createPayment',
            'exception' => $e,
        ), array('payment.request.fail', 'payment.create.fail'));
        YooMoneyLogger::error('Api error: '.$e->getMessage());
        drupal_set_message(t('Unable to pay with this method.'), 'error');
        drupal_goto(request_uri());
    }

    $kassaLogger->sendHeka(array('payment.create.fail', 'payment.request.fail'));
    $order->data['yoo_commerce_api'] = $pane_values;
}

/**
 * Запрос на создание платежа
 *
 * @param $order
 * @param $amount
 * @param string $paymentMethod
 * @param EntityMetadataWrapper $order_wrapper
 *
 * @return \YooKassa\Request\Payments\CreatePaymentRequestBuilder
 */
function yoo_commerce_api_get_create_payment_request_builder($order, $amount, $order_wrapper)
{
    $confirmationType = \YooKassa\Model\ConfirmationType::REDIRECT;
    YooMoneyLogger::info('Return url: '.yoo_commerce_api_get_return_url($order));
    $builder = CreatePaymentRequest::builder()
        ->setAmount($amount)
        ->setCapture(!yoomoney_api__common__is_enable_hold_mode())
        ->setDescription(yoo_commerce_api_create_description($order))
        ->setConfirmation(
            array(
                'type' => $confirmationType,
                'returnUrl' => yoo_commerce_api_get_return_url($order),
            )
        )
        ->setMetadata(array(
            'cms_name' => CMS_NAME_COMMERCE,
            'module_version' => YOOMONEY_MODULE_VERSION,
        ));

    yoo_commerce_api_set_receipt_if_needed($builder, $order, $order_wrapper);

    return $builder;
}

/**
 * @param CreatePaymentRequestBuilder|CreateCaptureRequestBuilder $builder
 * @param $order
 * @param EntityMetadataWrapper $order_wrapper
 */
function yoo_commerce_api_set_receipt_if_needed($builder, $order, $order_wrapper)
{
    if (!variable_get('yoomoney_api_send_check', false)) {
        return;
    }

    $kassaLogger = getKassaLog();
    $kassaLogger->sendHeka(array('receipt.create.init'));

    $builder->setReceiptEmail($order->mail);
    foreach ($order_wrapper->commerce_line_items as $delta => $line_item_wrapper) {
        if ($line_item_wrapper->value()->type == 'product') {
            $product    = $line_item_wrapper->commerce_product->value();
            $components = $product->commerce_price['und'][0]['data']['components'];
            $tax_id     = false;
            foreach ($components as $component) {
                $info = explode('|', $component['name']);
                if (count($info) && $info[0] == 'tax') {
                    $tax_id = $info[1];
                    break;
                }
            }

            $quantity = $line_item_wrapper->quantity->value();
            $tax      = $tax_id && variable_get('yoomoney_api_kassa_tax_'.$tax_id)
                ? variable_get('yoomoney_api_kassa_tax_'.$tax_id)
                : variable_get('yoomoney_api_kassa_tax_default', YOOMONEY_API_DEFAULT_TAX_RATE_ID);
            $amount   = commerce_currency_amount_to_decimal(
                $product->commerce_price['und'][0]['amount'],
                $product->commerce_price['und'][0]['currency_code']
            );

            $builder->addReceiptItem($product->title, $amount, $quantity, $tax,
                variable_get('yoomoney_kassa_payment_mode'),
                variable_get('yoomoney_kassa_payment_subject'));
        }

        if ($line_item_wrapper->value()->type == 'shipping') {
            $shipping = $line_item_wrapper->value();
            $amount   = commerce_currency_amount_to_decimal(
                $shipping->commerce_total['und'][0]['amount'],
                $shipping->commerce_total['und'][0]['currency_code']
            );
            $builder->addReceiptShipping('Доставка', $amount, YOOMONEY_API_DEFAULT_TAX_RATE_ID,
                variable_get('yoomoney_kassa_delivery_payment_mode'),
                variable_get('yoomoney_kassa_delivery_payment_subject'));
        }
    }
    $kassaLogger->sendHeka(array('receipt.create.success'));
}

/**
 * Payment method callback: redirect form.
 *
 * A wrapper around the module's general use function for building a submit form.
 */
function yoo_commerce_api_redirect_form($form, &$form_state, $order, $payment_method)
{
    global $user;

    $order_wrapper = entity_metadata_wrapper('commerce_order', $order);
    $currency_code = $order_wrapper->commerce_order_total->currency_code->value();
    $amount        = $order_wrapper->commerce_order_total->amount->value();
    $amount        = round(commerce_currency_amount_to_decimal($amount, $currency_code), 2);

    $transaction           = new YooMoneyApiTransaction();
    $transaction->uid      = isset($user->uid) ? $user->uid : 0;
    $transaction->amount   = $amount;
    $transaction->mail     = isset($user->mail) ? $user->mail : '';
    $transaction->order_id = $order->order_id;

    if (!yoomoney_api_transaction_save($transaction)) {
        $error_message = t('Can not save transaction.');

        // create failure commerce transaction
        yoo_commerce_create_commerce_transaction($transaction, COMMERCE_PAYMENT_STATUS_FAILURE, '');

        // show message to the user
        drupal_set_message(t('Payment failed: %message', array('%message' => $error_message)), 'error');

        // log error to watchdog
        watchdog('yoo_commerce_api', 'Payment failed: %message', array('%message' => $error_message), WATCHDOG_WARNING);

        // redirect back to checkout
        $cancel_url = yoo_commerce_api_get_checkout_url($order, false);
        drupal_goto($cancel_url);
    }

    $target_url = yoomoney_api_get_order_submission_url();
    $params     = yoomoney_api_get_order_submission_params($transaction);

    $form['#action'] = $target_url;
    foreach ($params as $key => $value) {
        if ($key == 'fio') {
            $form[$key] = array(
                '#type'  => 'hidden',
                '#value' => $order->data['yoo_commerce_api']['customer_name'],
            );
        } else {
            $form[$key] = array(
                '#type'  => 'hidden',
                '#value' => $value,
            );
        }
    }
    $form['actions']           = array('#type' => 'actions');
    $form['actions']['submit'] = array(
        '#type'  => 'submit',
        '#value' => t('Submit order'),
    );
    $form['cms_name']          = array(
        '#type'  => 'hidden',
        '#value' => "drupal-commerce",
    );


    return $form;
}

/**
 * Payment method callback: redirect form return validation.
 */
function yoo_commerce_api_redirect_form_validate($order, $payment_method)
{
    return true;
}

/**
 * Implements hook_yoomoney_api_shop_params_alter().
 *
 * @param $params
 */
function yoo_commerce_api_yoomoney_api_shop_params_alter(&$params)
{
    $order = commerce_order_load($params['order_id']);

    if ($order) {
        // Return to the payment redirect page for processing successful payments
        $params['shopSuccessURL'] = yoo_commerce_api_get_checkout_url($order, true);

        // Return to the previous page when payment is canceled
        $params['shopFailURL'] = yoo_commerce_api_get_checkout_url($order, false);
    }
}

/**
 * Implements hook_yoomoney_quick_params_alter().
 *
 * @param $params
 */
function yoo_commerce_api_yoomoney_api_quick_params_alter(&$params)
{
    $order = commerce_order_load($params['order_id']);

    // Selected payment method
    $params['paymentType'] = $order->data['yoo_commerce_api']['payment_method'];
}

/**
 * Process successful payment to update Commerce entities.
 * Implements hook_yoomoney_api_process_payment_alter().
 *
 * @param array $payment
 */
function yoo_commerce_api_yoomoney_api_process_payment_alter(&$payment)
{
    /** @var YooMoneyApiTransaction $transaction */
    $transaction = $payment['transaction'];
    $order       = commerce_order_load($transaction->order_id);

    if ($order) {
        $paymentId = $transaction->ymid;
        yoomoney_api_update_transaction_payment_id($transaction->ymid, $paymentId);
        $transaction->status = yoomoney_api_update_transaction_status($transaction->ymid, YooMoneyApiTransaction::STATUS_COMPLETED);
        yoo_commerce_create_commerce_transaction(
            $transaction,
            COMMERCE_PAYMENT_STATUS_SUCCESS,
            '',
            array(),
            $payment['request']
        );
        commerce_order_status_update($order, YooMoneyApiTransaction::STATUS_COMPLETED);

        $payment['success'] = true;
    } else {
        $payment['success'] = false;
        $payment['error']   = t('Can not find order with id ').$transaction->order_id;
    }
}

/**
 * @param stdClass $order
 * @param bool $success
 *
 * @return string
 */
function yoo_commerce_api_get_checkout_url($order, $success = true)
{
    return url(
        'checkout/'.$order->order_id.'/payment/'.($success ? 'return' : 'back').'/'.$order->data['payment_redirect_key'],
        array('absolute' => true)
    );
}

/**
 * @param YooMoneyApiTransaction $transaction
 * @param string $status
 * @param string $message
 * @param array $message_params
 * @param null $request
 *
 * @return bool
 */
function yoo_commerce_create_commerce_transaction(
    YooMoneyApiTransaction $transaction,
    $status,
    $message = '',
    $message_params = array(),
    $request = null
) {
    $order = commerce_order_load($transaction->order_id);

    $order_wrapper              = entity_metadata_wrapper('commerce_order', $order);
    $currency_code              = $order_wrapper->commerce_order_total->currency_code->value();
    $payment_method_instance_id = 'yoo_commerce|commerce_payment_yoo_commerce';

    // Prepare a transaction object to log the API response.
    $commerce_transaction                    = commerce_payment_transaction_new($payment_method_instance_id, $order->order_id);
    $commerce_transaction->instance_id       = $payment_method_instance_id;
    $commerce_transaction->uid               = $transaction->uid;
    $commerce_transaction->remote_id         = $transaction->ymid;
    $commerce_transaction->message           = $message;
    $commerce_transaction->message_variables = $message_params;
    $commerce_transaction->amount            = $transaction->amount * 100;
    $commerce_transaction->currency_code     = $currency_code;
    $commerce_transaction->status            = $status;
    $commerce_transaction->remote_status     = $transaction->status;

    if ($request) {
        $commerce_transaction->payload[REQUEST_TIME] = $request;
    }

    // Save the transaction information.
    return !commerce_payment_transaction_save($commerce_transaction);
}

function yoo_commerce_api_get_return_url($order)
{
    return url(
        'yoomoney_api/commerce/return',
        array(
            'absolute' => true,
            'query'    => array('orderId' => $order->order_id),
        )
    );
}


/**
 * Implements hook_yoomoney_api_complete();
 */
function yoo_commerce_yoomoney_api_complete()
{
    if (isset($_GET['shopSuccessURL'])) {
        drupal_goto($_GET['shopSuccessURL']);
    }
}

/**
 * Implements hook_yoomoney_api_fail();
 */
function yoo_commerce_api_yoomoney_api_fail()
{
    if (isset($_GET['shopFailURL'])) {
        drupal_goto($_GET['shopFailURL']);
    }
}

/**
 * @param $orderInfo
 *
 * @return bool|string
 */
function yoo_commerce_api_create_description($orderInfo)
{
    $descriptionTemplate = variable_get('yoomoney_api_description_template', t('Payment for order No. %order_number%'));

    $replace = array();
    foreach ($orderInfo as $key => $value) {
        if (is_scalar($value)) {
            $replace['%'.$key.'%'] = $value;
        }
    }

    $description = strtr($descriptionTemplate, $replace);

    return mb_substr($description, 0, Payment::MAX_LENGTH_DESCRIPTION);
}

/**
 * @param $paymentId
 *
 * @return mixed|null
 */
function yooCommerceApiPaymentTransactioLoad($paymentId)
{
    $transactions = commerce_payment_transaction_load_multiple(
        array(),
        array('remote_id' => $paymentId)
    );

    return !empty($transactions) ? array_shift($transactions) : null;
}

/**
 * @param \YooKassa\Model\PaymentInterface $payment
 * @param $order
 * @throws Exception
 */
function yoo_commerce_api_capture_payment($payment, $order)
{
    $kassaLogger = getKassaLog();
    $kassaLogger->sendHeka(array('capture.create.init'));
    $apiClient = yoomoney_api__common__get_api_client();
    try {
        $builder = CreateCaptureRequest::builder();

        $order_wrapper = entity_metadata_wrapper('commerce_order', $order);
        $currency_code = $order_wrapper->commerce_order_total->currency_code->value();
        $amount        = $order_wrapper->commerce_order_total->amount->value();
        $amount        = round(commerce_currency_amount_to_decimal($amount, $currency_code), 2);

        $builder->setAmount($amount);
        yoo_commerce_api_set_receipt_if_needed($builder, $order, $order_wrapper);

        $request  = $builder->build();

        if ($request->getReceipt() !== null) {
            $request->getReceipt()->normalize($request->getAmount());
        }

        $response = $apiClient->capturePayment($request, $payment->getId());
    } catch (\Exception $e) {
        $this->getKassaLog()->sendAlertLog('Failed to capture payment', array(
            'methodid' => 'POST/capturePayment',
            'exception' => $e,
        ), array('capture.create.fail'));
        YooMoneyLogger::error('Capture error: ' . $e->getMessage());
        $response = $payment;
    }
    yoomoney_api_common_check_value_is_not_empty($response, '400 Bad Request', 'Empty payment info');
    if ($response->getStatus() !== \YooKassa\Model\PaymentStatus::SUCCEEDED) {
        YooMoneyLogger::error('Capture payment error: capture failed');
        $kassaLogger->sendHeka(array('capture.create.fail'));
        return;
    }

    yoomoney_api_update_transaction_status($response->getId(), $response->getStatus());

    $transaction = yooCommerceApiPaymentTransactioLoad($response->getId());
    if ($transaction) {
        $transaction->message = t('Вы подтвердили платёж в ЮKassa.');
        commerce_payment_transaction_save($transaction);
    }

    $kassaLogger->sendHeka(array('capture.create.success', 'shop.'.$kassaLogger->getShopId().'.payment.succeeded'));
    echo "OK";
    exit();
}

/**
 * @param string $paymentId
 * @param $order
 */
function yoo_commerce_api_cancel_payment($paymentId, $order)
{
    $kassaLogger = getKassaLog();
    $kassaLogger->sendHeka(array('cancel.create.init'));;
    $apiClient = yoomoney_api__common__get_api_client();

    try {
        $response  = $apiClient->cancelPayment($paymentId);
    } catch (Exception $e) {
        $this->getKassaLog()->sendAlertLog('Failed to cancel payment', array(
            'methodid' => 'POST/cancelPayment',
            'exception' => $e,
        ), array('cancel.create.fail'));
        YooMoneyLogger::error('Cancel payment error: ' . $e->getMessage());
    }

    if (!$response || $response->getStatus() !== PaymentStatus::CANCELED) {
        YooMoneyLogger::error('Cancel payment error: cancel failed');
        $kassaLogger->sendHeka(array('cancel.create.fail'));
        return;
    }

    commerce_order_status_update($order, YOOMONEY_API_ORDER_STATUS_CANCELED);
    yoomoney_api_update_transaction_status($paymentId, PaymentStatus::CANCELED);

    $transaction = yooCommerceApiPaymentTransactioLoad($paymentId);
    if ($transaction) {
        $transaction->status        = COMMERCE_PAYMENT_STATUS_FAILURE;
        $transaction->remote_status = $response->getStatus();
        $transaction->message       = t('Вы отменили платёж в ЮKassa. Деньги вернутся клиенту.');
        commerce_payment_transaction_save($transaction);
    }

    $kassaLogger->sendHeka(array('cancel.create.success', 'shop.'.$kassaLogger->getShopId().'.payment.canceled'));
    echo "OK";
    exit();
}

Главная | Обратная связь

drupal hosting | друпал хостинг | it patrol .inc