Создание платежного расширения WooCommerce по большей части является простым процессом. Самая сложная проблема, с которой вы, вероятно, столкнетесь, — это узнать, как взаимодействовать с API продавца, чтобы отправить платеж и проанализировать ответ. В этой статье мы собираемся создать реальную вещь: работающее расширение оплаты WooCommerce. Затем мы даже подключим его к реальному платежному процессору, которому мы собираемся отправлять платежи и анализировать ответ.
Различные варианты платежных шлюзов WooCommerce
Существует четыре различных типа платежных шлюзов WooCommerce, которые мы можем создать для обработки платежей в вашем магазине. Давайте начнем с рассмотрения того, что мы будем использовать в этой статье; Прямой метод.
-
Прямой — этот метод оплаты позволяет отображать поля оплаты непосредственно на странице оформления заказа, и оплата происходит сразу после нажатия кнопки «Разместить заказ». Этот тип шлюза требует установки SSL-сертификата на вашем сайте, а также может потребовать, чтобы вы были совместимы с PCI. Совместимость с PCI — это то, что ваш продавец оценивает для вас. Хорошим примером шлюза такого типа является AIM Authorize.net, который мы будем использовать позже, когда будем создавать расширение для платежей WooCommerce.
-
На основе формы — в этом методе пользователь должен нажать кнопку в форме, а затем перенаправиться на сайт фактического процесса оплаты. Платеж затем фиксируется там; думаю, стандарт PayPal.
-
На основе iFrame — с помощью этого метода вся платежная система шлюза загружается для вас внутри iFrame в вашем магазине, что-то вроде того, как работает PayPal Advanced.
-
Оффлайн — последний, но не менее важный метод, при котором онлайн-платежи вообще не производятся. Чек или банковские переводы являются хорошими примерами этого типа оплаты.
Зачем использовать прямой метод
Прямой метод обеспечивает более высокий уровень настройки, так как поля оплаты обрабатываются вами, и, самое главное, клиент никогда не покидает ваш сайт. Клиенту очень понравится этот опыт по сравнению с другими тремя вариантами.
Методы, используемые в этой статье
Скорее всего, есть несколько способов сделать это, и результаты могут быть идентичными. Любые предложения по выполнению этой задачи или дальнейшие улучшения всегда приветствуются и принимаются хорошо. Просто будьте вежливы и информативны в своем ответе.
Следующий код был протестирован в последних версиях, доступных для WordPress (4.0) и WooCommerce (2.2.2), и использовал фиктивные данные, предоставленные для WooCommerce, при установке плагина.
Получение учетной записи разработчика Authorize.Net
Если у вас еще нет учетной записи разработчика / теста от Authorize.net, вам понадобится учетная запись для полного заполнения и тестирования этого плагина. Чтобы получить аккаунт разработчика / теста или песочницы Authorize.net (как они его описывают), просто зайдите в их Центр разработчиков и заполните форму.
Песочница разработчика — это полнофункциональный платежный шлюз Authorize.Net, поддерживающий текущие методы API. Песочница функционирует как наша производственная среда. Однако есть два ключевых различия:
-
Фактическая обработка карты не выполняется. Песочница имитирует только подключения к карточным сетям, но фактические платежи по карточкам не обрабатываются.
-
Разработчики могут инициировать определенные условия ошибок и реакции транзакций, чтобы помочь в тестировании.
Планирование нашего модуля расширения платежей WooCommerce
Чтобы было проще читать и следить за этим, мы собираемся разделить наш плагин на два разных файла. Один из файлов зарегистрирует наш Платежный шлюз и ссылку для специальных действий. Другой будет простой класс, который будет содержать методы, которые будут отвечать за создание полей администрирования, обработку обработки платежей и проверку полей, а также отображение сообщения об ошибке, если вы не используете SSL на странице оформления заказа. Посмотрите ниже на нашу файловую структуру:
woocommerce-authorizenet-aim-gateway (folder) -- woocommerce-authorizenet-aim-gateway.php -- woocommerce-authorizenet-aim.php
Строим наш плагин
Теперь, когда у нас есть четкое понимание того, как будет настроен наш плагин и какие файлы будут делать, мы можем начать с написания базовых элементов нашего всего плагина; основной код, который мы будем расширять, пока плагин не будет завершен.
<?php // Include our Gateway Class and Register Payment Gateway with WooCommerce add_action( 'plugins_loaded', 'spyr_authorizenet_aim_init', 0 ); function spyr_authorizenet_aim_init() {} // Add custom action links add_filter( 'plugin_action_links_' . plugin_basename( __FILE__ ), 'spyr_authorizenet_aim_action_links' ); function spyr_authorizenet_aim_action_links( $links ) {}
Теперь мы можем увидеть наш плагин на странице плагинов, но он еще ничего не делает. Мы пока не готовы его активировать.
Давайте начнем с первого файла: включите класс PHP, зарегистрируйте этот новый платежный шлюз в WooCommerce и добавьте свои ссылки действий, чтобы клиент мог перейти на страницу настроек, как только он активирует плагин.
<?php // Include our Gateway Class and register Payment Gateway with WooCommerce add_action( 'plugins_loaded', 'spyr_authorizenet_aim_init', 0 ); function spyr_authorizenet_aim_init() { // If the parent WC_Payment_Gateway class doesn't exist // it means WooCommerce is not installed on the site // so do nothing if ( ! class_exists( 'WC_Payment_Gateway' ) ) return; // If we made it this far, then include our Gateway Class include_once( 'woocommerce-authorizenet-aim.php' ); // Now that we have successfully included our class, // Lets add it too WooCommerce add_filter( 'woocommerce_payment_gateways', 'spyr_add_authorizenet_aim_gateway' ); function spyr_add_authorizenet_aim_gateway( $methods ) { $methods[] = 'SPYR_AuthorizeNet_AIM'; return $methods; } } // Add custom action links add_filter( 'plugin_action_links_' . plugin_basename( __FILE__ ), 'spyr_authorizenet_aim_action_links' ); function spyr_authorizenet_aim_action_links( $links ) { $plugin_links = array( '<a href="' . admin_url( 'admin.php?page=wc-settings&tab=checkout' ) . '">' . __( 'Settings', 'spyr-authorizenet-aim' ) . '</a>', ); // Merge our new link with the default ones return array_merge( $plugin_links, $links ); }
Обратите внимание, что ссылки действий, в данном случае ссылка «Настройки», будут отображаться только после активации плагина. Это приведет клиента к странице администрирования кассы WooCommerce. Давайте продолжим, чтобы приблизиться к активации плагина и просмотреть хотя бы некоторые поля по умолчанию.
Настройка нашего конструктора классов
Теперь, когда мы собираемся начать работу с нашим фактическим классом платежей, мы должны начать с установки некоторых значений по умолчанию для этого Платежного шлюза. Некоторые настройки мы определим:
-
id — глобальный идентификатор для этого метода оплаты.
-
method_title — Название, отображаемое в верхней части страницы Платежных шлюзов рядом со всеми другими Платежными шлюзами.
-
method_description — описание для этого Платежного шлюза, отображаемое на странице фактических способов оплаты в бэкэнде.
-
title — заголовок, который будет использоваться для вертикальных вкладок, которые можно упорядочить сверху вниз.
-
значок — если вы хотите показать изображение рядом с именем шлюза на внешнем интерфейсе. URL к изображению.
-
has_fields — Bool. Можно установить значение «true», если вы хотите, чтобы поля оплаты отображались на кассе при прямой интеграции, что мы и делаем в этом случае.
-
Поддерживает — Поддерживает форму кредитной карты по умолчанию. Подробнее об этом позже. На этом этапе вам просто нужно знать, что это супер круто.
Следующее выражение в нашем конструкторе, наряду с некоторыми другими полезными функциями, которые нам нужны, чтобы все работало в гармонии. Комментарии помогут вам понять цель и почему она есть.
// Setup our Gateway's id, description and other values function __construct() { // The global ID for this Payment method $this->id = "spyr_authorizenet_aim"; // The Title shown on the top of the Payment Gateways Page next to all the other Payment Gateways $this->method_title = __( "Authorize.net AIM", 'spyr-authorizenet-aim' ); // The description for this Payment Gateway, shown on the actual Payment options page on the backend $this->method_description = __( "Authorize.net AIM Payment Gateway Plug-in for WooCommerce", 'spyr-authorizenet-aim' ); // The title to be used for the vertical tabs that can be ordered top to bottom $this->title = __( "Authorize.net AIM", 'spyr-authorizenet-aim' ); // If you want to show an image next to the gateway's name on the frontend, enter a URL to an image. $this->icon = null; // Bool. Can be set to true if you want payment fields to show on the checkout // if doing a direct integration, which we are doing in this case $this->has_fields = true; // Supports the default credit card form $this->supports = array( 'default_credit_card_form' ); // This basically defines your settings which are then loaded with init_settings() $this->init_form_fields(); // After init_settings() is called, you can get the settings and load them into variables, eg: // $this->title = $this->get_option( 'title' ); $this->init_settings(); // Turn these settings into variables we can use foreach ( $this->settings as $setting_key => $value ) { $this->$setting_key = $value; } // Lets check for SSL add_action( 'admin_notices', array( $this, 'do_ssl_check' ) ); // Save settings if ( is_admin() ) { // Versions over 2.0 // Save our administration options. Since we are not going to be doing anything special // we have not defined 'process_admin_options' in this class so the method in the parent // class will be used instead add_action( 'woocommerce_update_options_payment_gateways_' . $this->id, array( $this, 'process_admin_options' ) ); } } // End __construct()
Активируйте свой плагин
Идите вперед и активируйте свой плагин. Убедитесь в отсутствии ошибок и нажмите на новую ссылку «Настройки». Это приведет вас к параметрам администрирования Checkout. Теперь вы должны увидеть ваш недавно зарегистрированный платежный отсчет там.
Прокрутите страницу до конца, и вы тоже сможете увидеть ее там.
Создание страницы администрирования
Чтобы построить страницу администрирования, нам нужно знать, какие поля требуются самой WooCommerce, а какие — API-интерфейсом обработчика платежей. В нашем случае, поскольку мы используем AIM Authorize.net, нам просто необходимы логин API Authorize.net и ключ транзакции.
Поскольку мы используем нашу тестовую учетную запись для создания плагина, также неплохо включить опцию для установки шлюза в тестовом режиме. Независимо от того, что вы делаете, очень просто предоставить способ легко перевести шлюз в тестовый режим, и вам следует подумать о том, чтобы сделать это обязательным требованием при создании вашего шлюза. Большинство шлюзов предоставляют вам две разные ссылки, по которым вы можете отправлять транзакции: одну для целей тестирования, а другую для производственной среды.
После некоторого мозгового штурма я придумал поля, которые мы собираемся включить в нашу страницу администрирования:
-
enabled — включить / отключить этот платежный шлюз
-
title — название платежа, которое клиент увидит в процессе оформления заказа.
-
описание — описание платежа, которое клиент увидит в процессе оформления заказа.
-
api_login — API Логин, предоставленный Authorize.net, когда вы зарегистрировали аккаунт.
-
trans_key — ключ транзакции, предоставляемый Authorize.net при регистрации учетной записи.
-
среда — Переведите платежный шлюз в тестовый режим или в производство.
Давайте превратим их в код, который понимает WooCommerce, и разберем варианты, которые будут отображаться на сервере. Это где init_form_fields()
вступает в игру.
// Build the administration fields for this specific Gateway public function init_form_fields() { $this->form_fields = array( 'enabled' => array( 'title' => __( 'Enable / Disable', 'spyr-authorizenet-aim' ), 'label' => __( 'Enable this payment gateway', 'spyr-authorizenet-aim' ), 'type' => 'checkbox', 'default' => 'no', ), 'title' => array( 'title' => __( 'Title', 'spyr-authorizenet-aim' ), 'type' => 'text', 'desc_tip' => __( 'Payment title the customer will see during the checkout process.', 'spyr-authorizenet-aim' ), 'default' => __( 'Credit card', 'spyr-authorizenet-aim' ), ), 'description' => array( 'title' => __( 'Description', 'spyr-authorizenet-aim' ), 'type' => 'textarea', 'desc_tip' => __( 'Payment description the customer will see during the checkout process.', 'spyr-authorizenet-aim' ), 'default' => __( 'Pay securely using your credit card.', 'spyr-authorizenet-aim' ), 'css' => 'max-width:350px;' ), 'api_login' => array( 'title' => __( 'Authorize.net API Login', 'spyr-authorizenet-aim' ), 'type' => 'text', 'desc_tip' => __( 'This is the API Login provided by Authorize.net when you signed up for an account.', 'spyr-authorizenet-aim' ), ), 'trans_key' => array( 'title' => __( 'Authorize.net Transaction Key', 'spyr-authorizenet-aim' ), 'type' => 'password', 'desc_tip' => __( 'This is the Transaction Key provided by Authorize.net when you signed up for an account.', 'spyr-authorizenet-aim' ), ), 'environment' => array( 'title' => __( 'Authorize.net Test Mode', 'spyr-authorizenet-aim' ), 'label' => __( 'Enable Test Mode', 'spyr-authorizenet-aim' ), 'type' => 'checkbox', 'description' => __( 'Place the payment gateway in test mode.', 'spyr-authorizenet-aim' ), 'default' => 'no', ) ); }
Если вы сейчас посетите страницу администрирования Authorize.net AIM, ваши поля будут отображаться с использованием собственной системы шаблонов WooCommerce для параметров администрирования отображения.
Заполните параметры администрирования
Идите вперед и заполните опцию администрирования своими учетными данными. Не забудьте установить шлюз в тестовый режим, чтобы мы могли безопасно работать и тестировать весь наш код по ходу работы. Нажмите эту кнопку «Сохранить изменения», прежде чем продолжить.
Обработка платежей
Обработка платежа осуществляется через process_payment($order_id )
. Важно отметить, что ему передается текущий порядок, чтобы мы могли получить нужные нам значения. Поля кредитной карты можно получить из $ _POST.
Многие плагины шлюзов, в том числе и наши, используют аналогичный интерфейс для полей оплаты карточкой в форме оформления заказа, поэтому WooCommerce добавил форму, которую мы можем использовать при необходимости. Эта форма по умолчанию имеет автоматическое форматирование номеров кредитных карт, даты истечения срока действия и даже автоматически отображает тип используемой карты, как только клиент вводит первые несколько цифр номера своей кредитной карты. Чтобы иметь возможность использовать эту форму, убедитесь, что ваш сайт работает по крайней мере с версией 2.1 WooCommerce.
По умолчанию форма создает следующие поля формы, которые можно получить из $ _POST:
-
GATEWAYID-карты номер
-
GATEWAYID-карты CVC
-
GATEWAYID-карты экспирации
Вот пример того, как выглядит форма по умолчанию без какого-либо пользовательского CSS.
Теперь, когда мы это знаем, мы можем перейти к следующему шагу и построить функцию process_payment()
для обработки транзакции.
// Submit payment and handle response public function process_payment( $order_id ) { global $woocommerce; // Get this Order's information so that we know // who to charge and how much $customer_order = new WC_Order( $order_id ); // Are we testing right now or is it a real transaction $environment = ( $this->environment == "yes" ) ? 'TRUE' : 'FALSE'; // Decide which URL to post to $environment_url = ( "FALSE" == $environment ) ? 'https://secure.authorize.net/gateway/transact.dll' : 'https://test.authorize.net/gateway/transact.dll'; // This is where the fun stuff begins $payload = array( // Authorize.net Credentials and API Info "x_tran_key" => $this->trans_key, "x_login" => $this->api_login, "x_version" => "3.1", // Order total "x_amount" => $customer_order->order_total, // Credit Card Information "x_card_num" => str_replace( array(' ', '-' ), '', $_POST['spyr_authorizenet_aim-card-number'] ), "x_card_code" => ( isset( $_POST['spyr_authorizenet_aim-card-cvc'] ) ) ? $_POST['spyr_authorizenet_aim-card-cvc'] : '', "x_exp_date" => str_replace( array( '/', ' '), '', $_POST['spyr_authorizenet_aim-card-expiry'] ), "x_type" => 'AUTH_CAPTURE', "x_invoice_num" => str_replace( "#", "", $customer_order->get_order_number() ), "x_test_request" => $environment, "x_delim_char" => '|', "x_encap_char" => '', "x_delim_data" => "TRUE", "x_relay_response" => "FALSE", "x_method" => "CC", // Billing Information "x_first_name" => $customer_order->billing_first_name, "x_last_name" => $customer_order->billing_last_name, "x_address" => $customer_order->billing_address_1, "x_city" => $customer_order->billing_city, "x_state" => $customer_order->billing_state, "x_zip" => $customer_order->billing_postcode, "x_country" => $customer_order->billing_country, "x_phone" => $customer_order->billing_phone, "x_email" => $customer_order->billing_email, // Shipping Information "x_ship_to_first_name" => $customer_order->shipping_first_name, "x_ship_to_last_name" => $customer_order->shipping_last_name, "x_ship_to_company" => $customer_order->shipping_company, "x_ship_to_address" => $customer_order->shipping_address_1, "x_ship_to_city" => $customer_order->shipping_city, "x_ship_to_country" => $customer_order->shipping_country, "x_ship_to_state" => $customer_order->shipping_state, "x_ship_to_zip" => $customer_order->shipping_postcode, // Some Customer Information "x_cust_id" => $customer_order->user_id, "x_customer_ip" => $_SERVER['REMOTE_ADDR'], ); // Send this payload to Authorize.net for processing $response = wp_remote_post( $environment_url, array( 'method' => 'POST', 'body' => http_build_query( $payload ), 'timeout' => 90, 'sslverify' => false, ) ); if ( is_wp_error( $response ) ) throw new Exception( __( 'We are currently experiencing problems trying to connect to this payment gateway. Sorry for the inconvenience.', 'spyr-authorizenet-aim' ) ); if ( empty( $response['body'] ) ) throw new Exception( __( 'Authorize.net\'s Response was empty.', 'spyr-authorizenet-aim' ) ); // Retrieve the body's resopnse if no errors found $response_body = wp_remote_retrieve_body( $response ); // Parse the response into something we can read foreach ( preg_split( "/\r?\n/", $response_body ) as $line ) { $resp = explode( "|", $line ); } // Get the values we need $r['response_code'] = $resp[0]; $r['response_sub_code'] = $resp[1]; $r['response_reason_code'] = $resp[2]; $r['response_reason_text'] = $resp[3]; // Test the code to know if the transaction went through or not. // 1 or 4 means the transaction was a success if ( ( $r['response_code'] == 1 ) || ( $r['response_code'] == 4 ) ) { // Payment has been successful $customer_order->add_order_note( __( 'Authorize.net payment completed.', 'spyr-authorizenet-aim' ) ); // Mark order as Paid $customer_order->payment_complete(); // Empty the cart (Very important step) $woocommerce->cart->empty_cart(); // Redirect to thank you page return array( 'result' => 'success', 'redirect' => $this->get_return_url( $customer_order ), ); } else { // Transaction was not succesful // Add notice to the cart wc_add_notice( $r['response_reason_text'], 'error' ); // Add note to the order for your reference $customer_order->add_order_note( 'Error: '. $r['response_reason_text'] ); } }
Давайте разберем код еще больше, чтобы его было легче понять.
Линии 5-15
Мы присваиваем $customer_order
новый WC_Order
содержащий всю информацию из заказа, за который мы собираемся обработать платеж. Затем мы решаем, находимся ли мы в тестовом режиме или нет, и наконец выбираем правильный URL для транзакции.
Линии 18-66
Это произвольные поля, которые мы можем отправить Authorize.net, чтобы они могли записать эту информацию. Мы встраиваем его в массив, чтобы впоследствии можно было создать правильный запрос, используя http_build_query()
.
Линии 69-74
Поскольку мы используем WordPress, мы можем использовать весь HTTP API для взаимодействия с другими сайтами и, в этом случае, POST нашей полезной нагрузки для обработки на Authorize.net. Перейдите по этой ссылке, чтобы wp_remote_post()
больше о HTTP API и wp_remote_post()
.
Линии 76-80
Здесь происходят две важные проверки. Во-первых, мы проверяем, чтобы WordPress не сталкивался с какими-либо ошибками во время размещения нашей полезной нагрузки, а во-вторых; мы уверены, что получили ответ. В любой момент мы выдаем исключительную ошибку, сообщая клиенту, если что-то не так с транзакцией. Посмотрите ниже на пример одной из этих ошибок:
Линии 83-94
Если мы сделали это далеко без каких-либо ошибок, то мы можем извлечь тело ответа и разобрать его во что-то, что мы можем прочитать. Первые четыре значения в ответе — единственные, которые нам нужны. Мы добавляем эти четыре значения в массив для облегчения тестирования, а также для того, чтобы сделать его намного проще для чтения.
Линии 98-112
Проверьте значение кода response_code
. Коды 1 или 4 означают, что сделка была одобрена. Если транзакция будет одобрена, мы добавим дружественную заметку о заказе для вашей справки, отметим заказ как оплаченный, очистим содержимое корзины и, наконец, перенаправим клиента на страницу «Спасибо». Если вам интересно посмотреть, как выглядят записи заказа после выполнения этих четырех шагов, взгляните ниже:
Линии 114-118
Если транзакция не удалась, мы показываем клиенту уведомление об ошибке и обновляем заказ с ошибкой, полученной от Authorize.net. Вот пример примечаний к заказу на сервере после того, как клиент несколько раз пытался завершить транзакцию безуспешно.
Вот и все для обработки платежей.
Проверить отправленные поля
Мы не проводим никакой проверки полей, поскольку полагаемся на форму кредитной карты по умолчанию. Попробуйте ввести буквы или символы в любое поле, и вы увидите, что это просто невозможно. В некоторых случаях я вижу, как это было бы чрезвычайно полезно, например; для проверки сроков годности, которые должны быть в определенном формате, отличном от стандарта, который мы обычно привыкли видеть.
Для простоты в этой статье мы просто собираемся вернуть ‘true’ и обойти проверку поля.
// Validate fields public function validate_fields() { return true; }
Страницы оформления заказа используют SSL?
Для обеспечения возможности бесперебойного оформления покупок и предоставления возможности оформления покупок на вашем собственном сайте требуется использование SSL-сертификата. WooCommerce позволяет быстро навязать использование SSL только на страницах оформления заказа, выбрав «Принудительная безопасная проверка» в разделе WooCommerce -> Настройки -> Оформить заказ.
Мы просто собираемся проверить, проверено ли это. Если это не было проверено, то мы будем отображать ошибку на серверной части, предупреждая вас, что требуется SSL.
// Check if we are forcing SSL on checkout pages // Custom function not required by the Gateway public function do_ssl_check() { if( $this->enabled == "yes" ) { if( get_option( 'woocommerce_force_ssl_checkout' ) == "no" ) { echo "<div class=\"error\"><p>". sprintf( __( "<strong>%s</strong> is enabled and WooCommerce is not forcing the SSL certificate on your checkout page. Please ensure that you have a valid SSL certificate and that you are <a href=\"%s\">forcing the checkout pages to be secured.</a>" ), $this->method_title, admin_url( 'admin.php?page=wc-settings&tab=checkout' ) ) ."</p></div>"; } } }
Предполагая, что мы не навязываем безопасную проверку, это сообщение отображается в серверной части.
Если вы сделали это так далеко, просто похлопайте себя по плечу: вы только что создали платежный шлюз WooCommerce, следуя этому руководству.
Что дальше?
Брось себе вызов. Попробуйте создать еще один платежный шлюз, следуя этой статье и применяя те же методы к своему плагину. Если мне нужно дать рекомендацию, я бы порекомендовал попробовать создать собственное расширение для упрощенной торговли . Теперь это включено в WooCommerce, так что не бойтесь взглянуть на этот код.
Simplify Commerce имеет отличный API, SDK для вашего использования и очень хорошо документирован. Кроме того, регистрация в тестовой учетной записи занимает всего несколько минут, и вы можете приступить к написанию следующего плагина в мгновение ока.
Вывод
Как видите, написание платежного расширения WooCommerce оказалось не таким сложным, как вы думали. Немного потренировавшись, вы можете написать новый за считанные часы, просто не забывайте много тестировать, прежде чем публиковать его, или использовать в любой производственной среде. Разработайте с WP_DEBUG
установленным в true, чтобы вы могли получать дополнительные отзывы при необходимости.
Код плагина
Ниже вы найдете пример кода, использованного в этой статье, в полной форме. Пожалуйста, прокомментируйте ниже, если у вас есть какие-либо вопросы или комментарии.
WooCommerce Authorize.net AIM
<?php /* Authorize.net AIM Payment Gateway Class */ class SPYR_AuthorizeNet_AIM extends WC_Payment_Gateway { // Setup our Gateway's id, description and other values function __construct() { // The global ID for this Payment method $this->id = "spyr_authorizenet_aim"; // The Title shown on the top of the Payment Gateways Page next to all the other Payment Gateways $this->method_title = __( "Authorize.net AIM", 'spyr-authorizenet-aim' ); // The description for this Payment Gateway, shown on the actual Payment options page on the backend $this->method_description = __( "Authorize.net AIM Payment Gateway Plug-in for WooCommerce", 'spyr-authorizenet-aim' ); // The title to be used for the vertical tabs that can be ordered top to bottom $this->title = __( "Authorize.net AIM", 'spyr-authorizenet-aim' ); // If you want to show an image next to the gateway's name on the frontend, enter a URL to an image. $this->icon = null; // Bool. Can be set to true if you want payment fields to show on the checkout // if doing a direct integration, which we are doing in this case $this->has_fields = true; // Supports the default credit card form $this->supports = array( 'default_credit_card_form' ); // This basically defines your settings which are then loaded with init_settings() $this->init_form_fields(); // After init_settings() is called, you can get the settings and load them into variables, eg: // $this->title = $this->get_option( 'title' ); $this->init_settings(); // Turn these settings into variables we can use foreach ( $this->settings as $setting_key => $value ) { $this->$setting_key = $value; } // Lets check for SSL add_action( 'admin_notices', array( $this, 'do_ssl_check' ) ); // Save settings if ( is_admin() ) { // Versions over 2.0 // Save our administration options. Since we are not going to be doing anything special // we have not defined 'process_admin_options' in this class so the method in the parent // class will be used instead add_action( 'woocommerce_update_options_payment_gateways_' . $this->id, array( $this, 'process_admin_options' ) ); } } // End __construct() // Build the administration fields for this specific Gateway public function init_form_fields() { $this->form_fields = array( 'enabled' => array( 'title' => __( 'Enable / Disable', 'spyr-authorizenet-aim' ), 'label' => __( 'Enable this payment gateway', 'spyr-authorizenet-aim' ), 'type' => 'checkbox', 'default' => 'no', ), 'title' => array( 'title' => __( 'Title', 'spyr-authorizenet-aim' ), 'type' => 'text', 'desc_tip' => __( 'Payment title the customer will see during the checkout process.', 'spyr-authorizenet-aim' ), 'default' => __( 'Credit card', 'spyr-authorizenet-aim' ), ), 'description' => array( 'title' => __( 'Description', 'spyr-authorizenet-aim' ), 'type' => 'textarea', 'desc_tip' => __( 'Payment description the customer will see during the checkout process.', 'spyr-authorizenet-aim' ), 'default' => __( 'Pay securely using your credit card.', 'spyr-authorizenet-aim' ), 'css' => 'max-width:350px;' ), 'api_login' => array( 'title' => __( 'Authorize.net API Login', 'spyr-authorizenet-aim' ), 'type' => 'text', 'desc_tip' => __( 'This is the API Login provided by Authorize.net when you signed up for an account.', 'spyr-authorizenet-aim' ), ), 'trans_key' => array( 'title' => __( 'Authorize.net Transaction Key', 'spyr-authorizenet-aim' ), 'type' => 'password', 'desc_tip' => __( 'This is the Transaction Key provided by Authorize.net when you signed up for an account.', 'spyr-authorizenet-aim' ), ), 'environment' => array( 'title' => __( 'Authorize.net Test Mode', 'spyr-authorizenet-aim' ), 'label' => __( 'Enable Test Mode', 'spyr-authorizenet-aim' ), 'type' => 'checkbox', 'description' => __( 'Place the payment gateway in test mode.', 'spyr-authorizenet-aim' ), 'default' => 'no', ) ); } // Submit payment and handle response public function process_payment( $order_id ) { global $woocommerce; // Get this Order's information so that we know // who to charge and how much $customer_order = new WC_Order( $order_id ); // Are we testing right now or is it a real transaction $environment = ( $this->environment == "yes" ) ? 'TRUE' : 'FALSE'; // Decide which URL to post to $environment_url = ( "FALSE" == $environment ) ? 'https://secure.authorize.net/gateway/transact.dll' : 'https://test.authorize.net/gateway/transact.dll'; // This is where the fun stuff begins $payload = array( // Authorize.net Credentials and API Info "x_tran_key" => $this->trans_key, "x_login" => $this->api_login, "x_version" => "3.1", // Order total "x_amount" => $customer_order->order_total, // Credit Card Information "x_card_num" => str_replace( array(' ', '-' ), '', $_POST['spyr_authorizenet_aim-card-number'] ), "x_card_code" => ( isset( $_POST['spyr_authorizenet_aim-card-cvc'] ) ) ? $_POST['spyr_authorizenet_aim-card-cvc'] : '', "x_exp_date" => str_replace( array( '/', ' '), '', $_POST['spyr_authorizenet_aim-card-expiry'] ), "x_type" => 'AUTH_CAPTURE', "x_invoice_num" => str_replace( "#", "", $customer_order->get_order_number() ), "x_test_request" => $environment, "x_delim_char" => '|', "x_encap_char" => '', "x_delim_data" => "TRUE", "x_relay_response" => "FALSE", "x_method" => "CC", // Billing Information "x_first_name" => $customer_order->billing_first_name, "x_last_name" => $customer_order->billing_last_name, "x_address" => $customer_order->billing_address_1, "x_city" => $customer_order->billing_city, "x_state" => $customer_order->billing_state, "x_zip" => $customer_order->billing_postcode, "x_country" => $customer_order->billing_country, "x_phone" => $customer_order->billing_phone, "x_email" => $customer_order->billing_email, // Shipping Information "x_ship_to_first_name" => $customer_order->shipping_first_name, "x_ship_to_last_name" => $customer_order->shipping_last_name, "x_ship_to_company" => $customer_order->shipping_company, "x_ship_to_address" => $customer_order->shipping_address_1, "x_ship_to_city" => $customer_order->shipping_city, "x_ship_to_country" => $customer_order->shipping_country, "x_ship_to_state" => $customer_order->shipping_state, "x_ship_to_zip" => $customer_order->shipping_postcode, // Some Customer Information "x_cust_id" => $customer_order->user_id, "x_customer_ip" => $_SERVER['REMOTE_ADDR'], ); // Send this payload to Authorize.net for processing $response = wp_remote_post( $environment_url, array( 'method' => 'POST', 'body' => http_build_query( $payload ), 'timeout' => 90, 'sslverify' => false, ) ); if ( is_wp_error( $response ) ) throw new Exception( __( 'We are currently experiencing problems trying to connect to this payment gateway. Sorry for the inconvenience.', 'spyr-authorizenet-aim' ) ); if ( empty( $response['body'] ) ) throw new Exception( __( 'Authorize.net\'s Response was empty.', 'spyr-authorizenet-aim' ) ); // Retrieve the body's resopnse if no errors found $response_body = wp_remote_retrieve_body( $response ); // Parse the response into something we can read foreach ( preg_split( "/\r?\n/", $response_body ) as $line ) { $resp = explode( "|", $line ); } // Get the values we need $r['response_code'] = $resp[0]; $r['response_sub_code'] = $resp[1]; $r['response_reason_code'] = $resp[2]; $r['response_reason_text'] = $resp[3]; // Test the code to know if the transaction went through or not. // 1 or 4 means the transaction was a success if ( ( $r['response_code'] == 1 ) || ( $r['response_code'] == 4 ) ) { // Payment has been successful $customer_order->add_order_note( __( 'Authorize.net payment completed.', 'spyr-authorizenet-aim' ) ); // Mark order as Paid $customer_order->payment_complete(); // Empty the cart (Very important step) $woocommerce->cart->empty_cart(); // Redirect to thank you page return array( 'result' => 'success', 'redirect' => $this->get_return_url( $customer_order ), ); } else { // Transaction was not succesful // Add notice to the cart wc_add_notice( $r['response_reason_text'], 'error' ); // Add note to the order for your reference $customer_order->add_order_note( 'Error: '. $r['response_reason_text'] ); } } // Validate fields public function validate_fields() { return true; } // Check if we are forcing SSL on checkout pages // Custom function not required by the Gateway public function do_ssl_check() { if( $this->enabled == "yes" ) { if( get_option( 'woocommerce_force_ssl_checkout' ) == "no" ) { echo "<div class=\"error\"><p>". sprintf( __( "<strong>%s</strong> is enabled and WooCommerce is not forcing the SSL certificate on your checkout page. Please ensure that you have a valid SSL certificate and that you are <a href=\"%s\">forcing the checkout pages to be secured.</a>" ), $this->method_title, admin_url( 'admin.php?page=wc-settings&tab=checkout' ) ) ."</p></div>"; } } } } // End of SPYR_AuthorizeNet_AIM
WooCommerce Authorize.net AIM Шлюз
<?php // Include our Gateway Class and register Payment Gateway with WooCommerce add_action( 'plugins_loaded', 'spyr_authorizenet_aim_init', 0 ); function spyr_authorizenet_aim_init() { // If the parent WC_Payment_Gateway class doesn't exist // it means WooCommerce is not installed on the site // so do nothing if ( ! class_exists( 'WC_Payment_Gateway' ) ) return; // If we made it this far, then include our Gateway Class include_once( 'woocommerce-authorizenet-aim.php' ); // Now that we have successfully included our class, // Lets add it too WooCommerce add_filter( 'woocommerce_payment_gateways', 'spyr_add_authorizenet_aim_gateway' ); function spyr_add_authorizenet_aim_gateway( $methods ) { $methods[] = 'SPYR_AuthorizeNet_AIM'; return $methods; } } // Add custom action links add_filter( 'plugin_action_links_' . plugin_basename( __FILE__ ), 'spyr_authorizenet_aim_action_links' ); function spyr_authorizenet_aim_action_links( $links ) { $plugin_links = array( '<a href="' . admin_url( 'admin.php?page=wc-settings&tab=checkout' ) . '">' . __( 'Settings', 'spyr-authorizenet-aim' ) . '</a>', ); // Merge our new link with the default ones return array_merge( $plugin_links, $links ); }