Categories » =) Home Work

#30. WC: Extending

Использование пользовательских атрибутов в меню и архивах таксономии

Зарегистрировать таксономию для меню

Создать шаблон

Настройка полей checkout с помощью действий и фильтров

Как поля Checkout загружаются в WooCommerce?

Переопределение core полей

Priority

Добавление custom полей для доставки и оплаты

Добавление custom специального поля

Добавление custom полей в сообщения электронной почты

Classes в WooCommerce

Список классов в WooCommerce

Common Classes

Woocommerce

WC_Product

WC_Customer

WC_Cart

Полезные функции ядра

wc_mail

wc_get_page_id( $pagename )

wc_price( $price, $args )

wc_clean( $var )

wc_get_dimension( $dim, $to_unit )

wc_get_weight( $weight, $to_unit )

Payment Gateway API

Типы платежных шлюзов

Создание базового платежного шлюза

Необходимые методы

Обновление статуса заказа и добавление заметок

Лучшая практика статуса заказа

Примечания по прямым шлюзам

Работа с обратными вызовами платежного шлюза (например, PayPal IPN)

Hooks в шлюзах

Дополнительные примеры

Создание WooCommerce Payment Extension

Различные варианты платежных шлюзов WooCommerce

Зачем использовать прямой метод

Получение учетной записи разработчика Authorize.Net

Планирование нашего WooCommerce Payment Extension Plugin

Создание нашего плагина

Настройка Class Constructor

Активируйте свой плагин

Создание страницы администрирования

Заполните параметры администрирования

Обработка платежей

Проверка отправленных полей

Используете ли вы Checkout Pages SSL?

Код плагина

Удаление / product /, / product-category /, или / shop / из URL-адресов

В сумме

Лучше избегать

WC_API – The WooCommerce API Callback

Callback URL

Hooking into the callback

Добавление Section на Settings Tab

Когда создавать раздел

Как создать раздел

Как добавить параметры в раздел

Использование новых параметров

Вывод

Реализация класса интеграции WC

Создание настроек

Типы настроек

Создание собственных настроек

Validating & Sanitizing Data

Использование пользовательских атрибутов в меню и архивах таксономии

Атрибуты, которые могут использоваться для многоуровневого навигатора, являются custom taxonomy, что означает, что вы можете отображать их в меню или отображать продукты по атрибутам. Это требует некоторой работы с вашей стороны, и архивы должны быть включены.

Зарегистрировать таксономию для меню

При регистрации таксономий для пользовательских атрибутов WooCommerce вызывает следующий hook:

$show_in_nav_menus = apply_filters(‘woocommerce_attribute_show_in_nav_menus’, false, $name);

Так, например, если ваш slug атрибута был «size», вы бы сделали следующее, чтобы зарегистрировать его для меню:

add_filter(‘woocommerce_attribute_show_in_nav_menus’, ‘wc_reg_for_menus’, 1, 2);

function wc_reg_for_menus( $register, $name = » ) {

    if ( $name == ‘pa_size’ ) $register = true;

    return $register;

}

Custom attribute slugs префикс ‘pa_’, поэтому атрибут, называемый ‘size’, будет ‘pa_size’

Теперь используйте свой атрибут в «Внешний вид»> «Меню». Однако вы заметите, что он имеет стиль блога по умолчанию, когда вы нажимаете ссылку на свой таксономический термин.

Создать шаблон

Вам нужно указать свой атрибут, чтобы он отображал товары по своему усмотрению. Сделать это:

  1. Скопируйте woocommerce/templates/taxonomy-product_cat.php в свою папку темы
  2. Переименуйте шаблон, чтобы отразить ваш атрибут — в нашем примере мы будем использовать taxonomy-pa_size.php

Теперь вы должны увидеть этот шаблон при просмотре терминов таксономии для своего настраиваемого атрибута.

Настройка полей checkout с помощью действий и фильтров

Настройка полей checkout с помощью действий и фильтров должна быть удобной.

Если вы не знакомы с кодом и разрешаете потенциальные конфликты, у нас есть расширение, которое может помочь: WooCommerce Checkout Field Editor. Установка и активация этого расширения отменяет любой код ниже того, который вы пытаетесь реализовать; И вы не можете иметь custom код поля checkout в вашем файле functions.php, когда расширение активировано.

Как поля Checkout загружаются в WooCommerce?

Поля billing и shipping для checkout вытягивания из стран (class-wc-countries.php) и функции get_address_fields. Это позволяет WooCommerce включать / отключать поля в зависимости от местоположения пользователя.

Перед возвратом этих полей WooCommerce помещает поля через фильтр. Это позволяет редактировать их сторонними плагинами, темами и собственным custom кодом.

Billing:

$address_fields = apply_filters(‘woocommerce_billing_fields’, $address_fields);

Shipping:

$address_fields = apply_filters(‘woocommerce_shipping_fields’, $address_fields);

Класс checkout добавляет загруженные поля в массив «checkout fields», а также добавляет несколько других полей, например «примечания к заказу».

$this->checkout_fields[‘billing’]    = $woocommerce->countries->get_address_fields( $this->get_value(‘billing_country’), ‘billing_’ );

$this->checkout_fields[‘shipping’]   = $woocommerce->countries->get_address_fields( $this->get_value(‘shipping_country’), ‘shipping_’ );

$this->checkout_fields[‘account’]    = array(

   ‘account_username’ => array(

       ‘type’ => ‘text’,

       ‘label’ => __(‘Account username’, ‘woocommerce’),

       ‘placeholder’ => _x(‘Username’, ‘placeholder’, ‘woocommerce’)

       ),

   ‘account_password’ => array(

       ‘type’ => ‘password’,

       ‘label’ => __(‘Account password’, ‘woocommerce’),

       ‘placeholder’ => _x(‘Password’, ‘placeholder’, ‘woocommerce’),

       ‘class’ => array(‘form-row-first’)

       ),

   ‘account_password-2’ => array(

       ‘type’ => ‘password’,

       ‘label’ => __(‘Account password’, ‘woocommerce’),

       ‘placeholder’ => _x(‘Password’, ‘placeholder’, ‘woocommerce’),

       ‘class’ => array(‘form-row-last’),

       ‘label_class’ => array(‘hidden’)

       ) );

$this->checkout_fields[‘order’]  = array(

   ‘order_comments’ => array(

       ‘type’ => ‘textarea’,

       ‘class’ => array(‘notes’),

       ‘label’ => __(‘Order Notes’, ‘woocommerce’),

       ‘placeholder’ => _x(‘Notes about your order, e.g. special notes for delivery.’, ‘placeholder’, ‘woocommerce’)

       ) );

Этот массив также пропускается через фильтр:

$this->checkout_fields = apply_filters(‘woocommerce_checkout_fields’, $this->checkout_fields);

Это означает, что у вас есть полный контроль над полями checkout — вам нужно только знать, как получить к ним доступ.

Переопределение core полей

Присоединение к фильтру woocommerce_checkout_fields позволяет переопределить любое поле. В качестве примера изменим placeholder в полях order_comments. В настоящее время установлено:

_x(‘Notes about your order, e.g. special notes for delivery.’, ‘placeholder’, ‘woocommerce’)

Мы можем изменить это, добавив функцию в наш файл functions.php темы:

// Hook in

add_filter( ‘woocommerce_checkout_fields’ , ‘custom_override_checkout_fields’ );

// Our hooked in function — $fields is passed via the filter!

function custom_override_checkout_fields( $fields ) {

    $fields[‘order’][‘order_comments’][‘placeholder’] = ‘My new placeholder’;

    return $fields;

}

Вы можете переопределить другие части, такие как labels:

// Hook in

add_filter( ‘woocommerce_checkout_fields’ , ‘custom_override_checkout_fields’ );

// Our hooked in function — $fields is passed via the filter!

function custom_override_checkout_fields( $fields ) {

    $fields[‘order’][‘order_comments’][‘placeholder’] = ‘My new placeholder’;

    $fields[‘order’][‘order_comments’][‘label’] = ‘My new label’;

    return $fields;

}

Или удалите поля:

// Hook in

add_filter( ‘woocommerce_checkout_fields’ , ‘custom_override_checkout_fields’ );

// Our hooked in function — $fields is passed via the filter!

function custom_override_checkout_fields( $fields ) {

    unset($fields[‘order’][‘order_comments’]);

    return $fields;

}

Вот полный список полей в массиве, переданном woocommerce_checkout_fields:

  • Billing
    • billing_first_name
    • billing_last_name
    • billing_company
    • billing_address_1
    • billing_address_2
    • billing_city
    • billing_postcode
    • billing_country
    • billing_state
    • billing_email
    • billing_phone
  • Shipping
    • shipping_first_name
    • shipping_last_name
    • shipping_company
    • shipping_address_1
    • shipping_address_2
    • shipping_city
    • shipping_postcode
    • shipping_country
    • shipping_state
  • Account
    • account_username
    • account_password
    • account_password-2
  • Order
    • order_comments

Каждое поле содержит массив свойств:

  • type – тип поля (text, textarea, password, select)
  • label – label для поля ввода
  • placeholder – placeholder для поля ввода
  • class – class для поля ввода
  • required – true or false, независимо от того, требуется или нет поле
  • clear – true or false, applies a clear fix to the field/label
  • label_class – class для элемента label
  • options – for select boxes, array of options (key => value pairs)

В определенных случаях вам нужно использовать фильтр woocommerce_default_address_fields. Этот фильтр применяется ко всем полям по умолчанию для оплаты и доставки:

  • country
  • first_name
  • last_name
  • company
  • address_1
  • address_2
  • city
  • state
  • postcode

Например, чтобы поле address_1 было необязательным:

// Hook in

add_filter( ‘woocommerce_default_address_fields’ , ‘custom_override_default_address_fields’ );

// Our hooked in function — $address_fields is passed via the filter!

function custom_override_default_address_fields( $address_fields ) {

    $address_fields[‘address_1’][‘required’] = false;

    return $address_fields;

}

Определение вариантов выбора

Если вы добавляете поле с типом select, как указано выше, вы определяете пары ключ / значение. Например:

$fields[‘billing’][‘your_field’][‘options’] = array(

 ‘option_1’ => ‘Option 1 text’,

 ‘option_2’ => ‘Option 2 text’

);

Priority

Приоритет в отношении кода PHP помогает установить, когда бит кода, называемый функцией, выполняется в зависимости от загрузки страницы. Он устанавливается внутри каждой функции и полезен при переопределении существующего кода для пользовательского отображения.

Код с большим номером, установленным в качестве приоритета, будет запускаться после кода с меньшим числом, то есть код с приоритетом 20 будет запускаться после кода с 10 приоритетами.

Аргумент приоритета устанавливается во время функции add_action, после того, как вы установили, с каким hook вы подключаетесь, и именем вашей настраиваемой функции.

В приведенном ниже примере синий текст — это имя изменяемого hook, зеленый текст — это имя нашей настраиваемой функции, а красный — это тот приоритет, который мы установили.

Примеры

В этом примере код настроен так, чтобы перенаправлять кнопку «Возврат в магазин», найденную в корзине, в категорию, которая перечисляет продукты для продажи по адресу http://example.com/category/specials/.

<?php

/**

* Changes the redirect URL for the Return To Shop button in the cart.

*/

function wc_empty_cart_redirect_url() {

 return ‘http://example.com/category/specials/’;

}

add_filter( ‘woocommerce_return_to_shop_redirect’, ‘wc_empty_cart_redirect_url’, 10 );

Там мы видим, что приоритет установлен на 10. Это типичное значение по умолчанию для функций и скриптов WooCommerce, поэтому этого может быть недостаточно для переопределения функциональности этой кнопки.

Вместо этого мы можем изменить приоритет на любое число больше 10. В то время как 11 будет работать, наилучшая практика подсказывает, что мы используем приращения в десять, поэтому 20, 30 и так далее.

<?php

/**

* Changes the redirect URL for the Return To Shop button in the cart.

*/

function wc_empty_cart_redirect_url() {

 return ‘http://example.com/category/specials/’;

}

add_filter( ‘woocommerce_return_to_shop_redirect’, ‘wc_empty_cart_redirect_url’, 20 );

С приоритетом мы можем иметь две функции, которые действуют на одном hook. Обычно это может вызвать множество проблем, но поскольку мы установили один из них имеет более высокий приоритет, чем другой, наш сайт будет загружать только соответствующую функцию, и мы перейдем на страницу Specials, как и было указано ниже.

<?php

/**

* Changes the redirect URL for the Return To Shop button in the cart.

* BECAUSE THIS FUNCTION HAS THE PRIORITY OF 20, IT WILL RUN AFTER THE FUNCTION BELOW (HIGHER NUMBERS RUN LATER)

*/

function wc_empty_cart_redirect_url() {

 return ‘http://example.com/category/specials/’;

}

add_filter( ‘woocommerce_return_to_shop_redirect’, ‘wc_empty_cart_redirect_url’, 20 );

/**

* Changes the redirect URL for the Return To Shop button in the cart.

* EVEN THOUGH THIS FUNCTION WOULD NORMALLY RUN LATER BECAUSE IT’S CODED AFTERWARDS, THE 10 PRIORITY IS LOWER THAN 20 ABOVE

*/

function wc_empty_cart_redirect_url() {

 return ‘http://example.com/shop/’;

}

add_filter( ‘woocommerce_return_to_shop_redirect’, ‘wc_empty_cart_redirect_url’, 10 );

?>

Добавление custom полей для доставки и оплаты

Добавление полей выполняется аналогично переопределению полей. Например, добавим новое поле в поля для доставки — shipping_phone:

// Hook in

add_filter( ‘woocommerce_checkout_fields’ , ‘custom_override_checkout_fields’ );

// Our hooked in function — $fields is passed via the filter!

function custom_override_checkout_fields( $fields ) {

    $fields[‘shipping’][‘shipping_phone’] = array(

       ‘label’     => __(‘Phone’, ‘woocommerce’),

   ‘placeholder’   => _x(‘Phone’, ‘placeholder’, ‘woocommerce’),

   ‘required’  => false,

   ‘class’     => array(‘form-row-wide’),

   ‘clear’     => true

    );

    return $fields;

}

/**

* Display field value on the order edit page

*/

add_action( ‘woocommerce_admin_order_data_after_shipping_address’, ‘my_custom_checkout_field_display_admin_order_meta’, 10, 1 );

function my_custom_checkout_field_display_admin_order_meta($order){

   echo ‘<p><strong>’.__(‘Phone From Checkout Form’).’:</strong> ‘ . get_post_meta( $order->id, ‘_shipping_phone’, true ) . ‘</p>’;

}

 

Что нам делать с новой областью? Ничего. Поскольку мы определили поле в массиве checkout_fields, это поле автоматически обрабатывается и сохраняется в метаданной заказа (в данном случае _shipping_phone). Если вы хотите добавить правила проверки, см. Класс checkout, в котором есть дополнительные hooks, которые вы можете использовать.

Добавление custom специального поля

Аналогично добавляется custom поле. Давайте добавим новое поле для checkout, после заметок заказа, подключившись к следующему:

/**

* Add the field to the checkout

*/

add_action( ‘woocommerce_after_order_notes’, ‘my_custom_checkout_field’ );

function my_custom_checkout_field( $checkout ) {

   echo ‘<div id=»my_custom_checkout_field»><h2>’ . __(‘My Field’) . ‘</h2>’;

   woocommerce_form_field( ‘my_field_name’, array(

       ‘type’          => ‘text’,

       ‘class’         => array(‘my-field-class form-row-wide’),

       ‘label’         => __(‘Fill in this field’),

       ‘placeholder’   => __(‘Enter something’),

       ), $checkout->get_value( ‘my_field_name’ ));

   echo ‘</div>’;

}

Затем нам нужно проверить поле, когда выведет форму заказа. Для этого примера поле является обязательным, а не обязательным:

/**

* Process the checkout

*/

add_action(‘woocommerce_checkout_process’, ‘my_custom_checkout_field_process’);

function my_custom_checkout_field_process() {

   // Check if set, if its not set add an error.

   if ( ! $_POST[‘my_field_name’] )

       wc_add_notice( __( ‘Please enter something into this new shiny field.’ ), ‘error’ );

}

Если поле пустое, отображается ошибка проверки:

Наконец, давайте сохранить новое поле для заказа пользовательские поля, используя следующий код:

/**

* Update the order meta with field value

*/

add_action( ‘woocommerce_checkout_update_order_meta’, ‘my_custom_checkout_field_update_order_meta’ );

function my_custom_checkout_field_update_order_meta( $order_id ) {

   if ( ! empty( $_POST[‘my_field_name’] ) ) {

       update_post_meta( $order_id, ‘My Field’, sanitize_text_field( $_POST[‘my_field_name’] ) );

   } }

Поле теперь сохраняется в заказе.

Если вы хотите отобразить значение настраиваемого поля на странице редактирования заказа администратора, вы можете добавить этот код:

/**

* Display field value on the order edit page

*/

add_action( ‘woocommerce_admin_order_data_after_billing_address’, ‘my_custom_checkout_field_display_admin_order_meta’, 10, 1 );

function my_custom_checkout_field_display_admin_order_meta($order){

   echo ‘<p><strong>’.__(‘My Field’).’:</strong> ‘ . get_post_meta( $order->id, ‘My Field’, true ) . ‘</p>’;

}

Это результат:

Пример: Сделать номер телефона не обязательным

<?php

add_filter( ‘woocommerce_billing_fields’, ‘wc_npr_filter_phone’, 10, 1 );

function wc_npr_filter_phone( $address_fields ) {

$address_fields[‘billing_phone’][‘required’] = false;

return $address_fields;

?>

Добавление custom полей в сообщения электронной почты

Чтобы добавить custom field value  в сообщения электронной почты WooCommerce — например, заполненный электронный адрес заказа, — используйте следующий фрагмент:

/*

Использовать:

  1. Добавьте этот фрагмент в файл functions.php вашей темы
  2. Измените имена мета ключей в фрагменте кода.
  3. Создайте настраиваемое поле в записи заказа — например. Key = «Код отслеживания» value = abcdefg
  4. При следующем обновлении статуса или во время любого другого события, которое отправляет электронное письмо пользователю, они будут видеть это поле в своем электронном письме

*/

add_filter(‘woocommerce_email_order_meta_keys’, ‘my_custom_order_meta_keys’);

function my_custom_order_meta_keys( $keys ) {

    $keys[] = ‘Tracking Code’; // This will look for a custom field called ‘Tracking Code’ and add it to emails

    return $keys;

}

Classes в WooCommerce

Список классов в WooCommerce

Список классов в WooCommerce приведен в API DOCS.

Common Classes

Woocommerce

Основной класс — класс Woocommerce, доступный в глобальном масштабе через переменную $woocommerce. Он обрабатывает основные функции WooCommerce, другие классы init, сохраняет переменные сайта и обрабатывает сообщения об ошибках / успехах.

Класс woocommerce инициализирует следующие классы при построении:

  • WC_Query – Хранится в $woocommerce->query
  • WC_Customer – Хранится в $woocommerce->customer
  • WC_Shipping – Хранится в $woocommerce->shipping
  • WC_Payment_Gateways – Хранится в $woocommerce->payment_gateways
  • WC_Countries – Хранится в $woocommerce->countries

Другие классы автоматически загружаются по требованию.

WC_Product

WooCommerce имеет несколько классов продуктов, ответственных за загрузку и вывод данных продукта. Это можно загрузить через PHP, используя:

$product = wc_get_product( $post->ID );

В цикле это не всегда необходимо, так как вызов функции the_post () автоматически заполняет глобальную переменную $product, если post является продуктом.

WC_Customer

Класс customer позволяет вам получать данные о текущем клиенте, например:

global $woocommerce;

$customer_country = $woocommerce->customer->get_country();

Просмотр API документации для полного списка методов, содержащихся в этом классе.

WC_Cart

Класс корзины загружает и сохраняет данные корзины пользователей в сеансе. Например, чтобы получить промежуточный итог по карте, вы можете использовать:

global $woocommerce;

$cart_subtotal = $woocommerce->cart->get_cart_subtotal();

Просмотр API документации для полного списка методов, содержащихся в этом классе.

Полезные функции ядра

Следующие полезные функции находятся в include / wc-core-functions.php и могут использоваться темами и плагинами.

wc_mail

Используется для отправки электронной почты с использованием шаблонов электронной почты WooCommerce.

wc_mail( $to, $subject, $message, $headers = «Content-Type: text/htmlrn», $attachments = «» )

wc_get_page_id( $pagename )

Получает ID страницы WooCommerce по имени, например. thankyou

wc_get_page_id( $page )

wc_price( $price, $args )

Форматирует пройденную цену с правильным количеством десятичных знаков и символом валюты.

wc_price( $price, $args = array() )

Массив $ args имеет опцию под названием ex tax label — если true, то будет добавлено сообщение «excluding tax».

wc_clean( $var )

Обрезает и извлекает теги из строки ($ var).

wc_clean( $var )

wc_get_dimension( $dim, $to_unit )

Измерение измеряется в модуле измерения WooCommerce и преобразует его в целевой модуль ($to_unit).

wc_get_dimension( 10, ‘lbs’ )

wc_get_weight( $weight, $to_unit )

Принимает weight ($ weight), взвешенный в единицах weight WooCommerce, и преобразует его в целевую единицу weight ($to_unit).

wc_get_weight( 10, ‘lbs’ )

Payment Gateway API

Платежные шлюзы в WooCommerce основаны на классах и могут быть добавлены через традиционные плагины. Это руководство содержит введение в разработку шлюза.

Типы платежных шлюзов

Платежные шлюзы бывают нескольких видов:

  • Form based — здесь пользователь должен нажать кнопку в форме, которая затем перенаправляет их в процессор платежей на собственном веб-сайте шлюза. Пример: стандарт PayPal, Authorize.net DPM
  • iFrame based — это когда загрузочная платежная система загружается внутри iframe в вашем магазине. Пример: форма SagePay, PayPal Advanced
  • Direct — это когда поля платежа отображаются непосредственно на странице оформления заказа и оплата производится при нажатии «заказ места». Пример: PayPal Pro, Authorize.net AIM
  • Offline  — оплата не производится онлайн. Пример:  Cheque, Bank Transfer

Шлюзы на основе форм и iFrame отправляют данные вне offsite, что означает, что для вас меньше проблем с безопасностью. Однако для прямых шлюзов требуется обеспечить безопасность сервера (SSL-сертификаты и т. Д.), А также может потребоваться уровень соответствия PCI.

Создание базового платежного шлюза

Платежные шлюзы должны быть созданы как дополнительные плагины, которые подключаются к WooCommerce. Внутри плагина вам нужно создать класс после загрузки плагинов. Пример:

add_action( ‘plugins_loaded’, ‘init_your_gateway_class’ );

Также важно, чтобы ваш класс шлюза расширил базовый класс шлюза WooCommerce, поэтому у вас есть доступ к важным методам и API настроек:

function init_your_gateway_class() {

class WC_Gateway_Your_Gateway extends WC_Payment_Gateway {}

}

Вы можете просмотреть класс WC_Payment_Gateway в Документах API.

Помимо определения вашего класса, вам также необходимо сообщить WooCommerce (WC), что он существует. Сделайте это, фильтр woocommerce_payment_gateways:

function add_your_gateway_class( $methods ) {

$methods[] = ‘WC_Gateway_Your_Gateway’;

return $methods;

}

add_filter( ‘woocommerce_payment_gateways’, ‘add_your_gateway_class’ );

Необходимые методы

Большинство методов наследуются от класса WC_Payment_Gateway, но некоторые из них требуются в пользовательском шлюзе.

__construct()

Внутри вашего конструктора вы должны определить следующие переменные:

  • $this->id — Уникальный идентификатор вашего шлюза, например, «your_gateway»
  • $this->icon — Если вы хотите, чтобы изображение отображалось рядом с именем шлюза в интерфейсе, введите URL-адрес изображения.
  • $this->has_fields — Bool. Может быть установлено значение true, если вы хотите, чтобы поля оплаты отображались на кассе (если выполняется прямая интеграция).
  • $this->method_title — Название способа оплаты, показанного на странице администратора.
  • $this->method_description — Описание для способа оплаты, показанного на странице администратора.

Ваш конструктор должен также определять и загружать поля настроек:

$this->init_form_fields();

$this->init_settings();

Мы рассмотрим init_form_fields () позже, но это в основном определяет ваши настройки, которые затем загружаются с помощью init_settings ().

После вызова init_settings () вы можете получить настройки и загрузить их в переменные, что означает:

$this->title = $this->get_option( ‘title’ );

Наконец, вам нужно добавить hook для ваших настроек:

add_action( ‘woocommerce_update_options_payment_gateways_’ . $this->id, array( $this, ‘process_admin_options’ ) );

init_form_fields()

Используйте этот метод для установки $this->form_fields — это параметры, которые вы покажете в админке на странице настроек шлюза и используете API настроек WC.

Базовый набор настроек для вашего шлюза будет состоять из включенного, заголовка и описания:

$this->form_fields = array(

‘enabled’ => array(

‘title’ => __( ‘Enable/Disable’, ‘woocommerce’ ),

‘type’ => ‘checkbox’,

‘label’ => __( ‘Enable Cheque Payment’, ‘woocommerce’ ),

‘default’ => ‘yes’

),

‘title’ => array(

‘title’ => __( ‘Title’, ‘woocommerce’ ),

‘type’ => ‘text’,

‘description’ => __( ‘This controls the title which the user sees during checkout.’, ‘woocommerce’ ),

‘default’ => __( ‘Cheque Payment’, ‘woocommerce’ ),

‘desc_tip’      => true,

),

‘description’ => array(

‘title’ => __( ‘Customer Message’, ‘woocommerce’ ),

‘type’ => ‘textarea’,

‘default’ => »

);

process_payment( $order_id )

Теперь о самой важной части шлюза — обработке платежа и обработке заказа. Process_payment также сообщает WC, куда перенаправить пользователя, и это делается с возвращенным массивом.

Вот пример функции process_payment с Check Gateway:

function process_payment( $order_id ) {

global $woocommerce;

$order = new WC_Order( $order_id );

// Mark as on-hold (we’re awaiting the cheque)

$order->update_status(‘on-hold’, __( ‘Awaiting cheque payment’, ‘woocommerce’ ));

// Reduce stock levels

$order->reduce_order_stock();

// Remove cart

$woocommerce->cart->empty_cart();

// Return thankyou redirect

return array(

‘result’ => ‘success’,

‘redirect’ => $this->get_return_url( $order )

); }

Как вы можете видеть, его работа состоит в том, чтобы:

  • Получение и обновление обрабатываемого ордера
  • Уменьшите запас и очистите корзину
  • Успех возврата и URL переадресации (в этом случае страница благодарности)

Проверка дает статус On-Hold Order, так как платеж не может быть проверен автоматически. Если, однако, вы создаете прямой шлюз, то вместо этого вы можете выполнить заказ здесь. Вместо того, чтобы использовать update_status, когда заказ оплачен, вы должны нам payment_complete:

$order->payment_complete();

Это обеспечивает сокращение запасов, и состояние изменяется на правильное значение.

Если платеж не удался, вы должны выдать ошибку и вернуть значение null:

wc_add_notice( __(‘Payment error:’, ‘woothemes’) . $error_message, ‘error’ );

return;

WooCommerce поймает эту ошибку и покажет ее на странице оформления заказа.

Обновление статуса заказа и добавление заметок

Обновление статуса заказа может выполняться с использованием функций в классе заказа. Это нужно делать только в том случае, если статус заказа не обрабатывается (в этом случае вы должны использовать payment_complete ()). Примером обновления пользовательского статуса будет:

$order = new WC_Order( $order_id );

$order->update_status(‘on-hold’, __(‘Awaiting cheque payment’, ‘woothemes’));

В приведенном выше примере состояние обновляется до On-Hold и добавляется примечание, сообщающее владельцу, что он ожидает проверки. Вы можете добавлять заметки без обновления статуса заказа; Это используется для добавления отладочного сообщения:

$order->add_order_note( __(‘IPN payment completed’, ‘woothemes’) );

Лучшая практика статуса заказа

  • Если заказ завершен, но администратору необходимо вручную проверить оплату, используйте On-Hold
  • Если заказ неудачен и уже создан, установите значение Failed
  • Если платеж завершен, пусть WooCommerce обрабатывает статус и использует $ order-> payment_complete (). WooCommerce будет использовать статус Completed или Processing и обрабатывать акции.

Примечания по прямым шлюзам

Если вы создаете расширенный, прямой шлюз (то есть тот, который принимает оплату на странице фактического оформления), есть дополнительные шаги. Во-первых, вам нужно установить has_fields в true в конструкторе gateway:

$this->has_fields = true;

Это сообщает кассе для вывода «payment_box», содержащего вашу форму прямого платежа, которую вы определяете затем.

Создайте метод с названием payment_fields () — он содержит вашу форму, которая, скорее всего, будет содержать данные кредитной карты.

Следующий, но необязательный метод для добавления — validate_fields (). Возвращает true, если форма проходит проверку или false, если она не выполняется. Вы можете использовать функцию wc_add_notice (), если хотите добавить ошибку и отобразить ее пользователю.

Наконец, вам нужно добавить код платежа внутри метода process_payment ($ order_id). Это берет данные отправленной формы и пытается осуществить платеж напрямую через поставщика платежей.

Если платеж не удался, выведите ошибку и ничего не возвращайте:

wc_add_notice( __(‘Payment error:’, ‘woothemes’) . $error_message, ‘error’ );

return;

Если платеж прошел успешно, вы должны установить заказ как оплаченный и вернуть success array

// Payment complete

$order->payment_complete();

// Return thank you page redirect

return array(

‘result’ => ‘success’,

‘redirect’ => $this->get_return_url( $order )

);

Работа с обратными вызовами платежного шлюза (например, PayPal IPN)

Если вы создаете шлюз, который делает обратный вызов в ваш магазин, чтобы рассказать вам о статусе заказа, вам нужно добавить код для обработки этого внутри вашего шлюза.

Лучший способ добавить обработчик обратного вызова и обратного вызова — использовать hooks WC-API. Примером может служить стандарт PayPal. Он устанавливает URL-адрес обратного вызова / IPN как:

str_replace( ‘https:’, ‘http:’, add_query_arg( ‘wc-api’, ‘WC_Gateway_Paypal’, home_url( ‘/’ ) ) );

Затем hooks в свой обработчик hook:

add_action( ‘woocommerce_api_wc_gateway_paypal’, array( $this, ‘check_ipn_response’ ) );

WooCommerce будет вызывать ваш шлюз и запускать действие при вызове URL.

Для получения дополнительной информации см. WC_API — Обратный вызов API WooCommerce.

Hooks в шлюзах

Важно отметить, что добавление hooks внутри классов шлюза может не запускаться. Шлюзы загружаются только при необходимости, например, во время проверки и на странице настроек в админке.

Вы должны держать hooks за пределами класса или использовать WC-API, если вам нужно подключиться к событиям WordPress из вашего класса.

Дополнительные примеры

Еще несколько примеров платежных шлюзов, перейдите на основные шлюзы WooCommerce или шлюзы премиум-класса WooCommerce.

Создание WooCommerce Payment Extension

Разработка расширения payment WooCommerce — это, по большей части, простой процесс. Самая сложная проблема, с которой вам придется столкнуться, — это научиться взаимодействовать с API-интерфейсом payment, чтобы отправить платеж и проанализировать ответ. В этой статье мы собираемся создать реальную вещь: рабочее расширение оплаты WooCommerce. Тогда мы даже подключим его к реальному процессу платежей, который мы собираемся отправлять и анализировать.

Различные варианты платежных шлюзов WooCommerce

Существует четыре различных типа платежных шлюзов WooCommerce, которые мы можем построить для обработки платежей в вашем магазине. Давайте начнем с рассмотрения того, что мы будем использовать в этой статье;

  • Direct
  • Form Based
  • iFrame Based
  • Offline

Зачем использовать прямой метод

Прямой метод позволяет повысить уровень настройки, поскольку поля оплаты обрабатываются вами, и, что наиболее важно, клиент никогда не покидает ваш сайт. Заказчику очень понравится этот опыт по остальным трем вариантам.

Получение учетной записи разработчика Authorize.Net

Если у вас еще нет учетной записи разработчика / теста от Authorize.net, вам понадобится один, чтобы полностью завершить и протестировать этот плагин. Чтобы получить авторизационную / тестовую или тестовую учетную запись Authorize.net (как они ее описывают), просто зайдите в их Центр разработчиков и заполните форму.

Песочница разработчика — полностью функционирующий платежный шлюз Authorize.Net, поддерживающий текущие методы API. Песочница функционирует подобно нашей производственной среде. Однако есть два основных отличия:

  1. Обработка реальной карты не выполняется. Песочница только имитирует соединения с сетями карточек, но фактические платежи по карте не обрабатываются.
  2. Разработчики могут инициировать особые условия ошибок и реакции транзакций, чтобы помочь в тестировании.

Планирование нашего WooCommerce Payment Extension Plugin

Чтобы облегчить чтение и сопровождение, мы собираемся разделить наш плагин на два разных файла. В одном из файлов будет зарегистрирован наш платежный шлюз и пользовательская ссылка на действие. Другим будет простой класс, который будет содержать методы, которые будут отвечать за создание полей администрирования, обработку обработки платежей и проверку полей, а также отображение сообщения об ошибке, если вы не принудительно применяете SSL на странице оформления. Посмотрите ниже на нашу файловую структуру:

woocommerce-authorizenet-aim-gateway (folder)

— woocommerce-authorizenet-aim-gateway.php

— woocommerce-authorizenet-aim.php

Создание нашего плагина

Теперь, когда у нас есть четкое представление о том, как наш плагин будет настроен и какие файлы будут делать, мы можем начать с написания всего нашего плагина; Базовый код, который мы будем расширять до тех пор, пока плагин не будет завершен.

<?php
/*
Plugin Name: Authorize.net AIM — WooCommerce Gateway
Plugin URI: http://www.sitepoint.com/
Description: Extends WooCommerce by Adding the Authorize.net AIM Gateway.
Version: 1
Author: Yojance Rabelo, SitePoint
Author URI: http://www.sitepoint.com/
*/

// 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
/*
Plugin Name: Authorize.net AIM — WooCommerce Gateway
Plugin URI: http://www.sitepoint.com/
Description: Extends WooCommerce by Adding the Authorize.net AIM Gateway.
Version: 1.0
Author: Yojance Rabelo, SitePoint
Author URI: http://www.sitepoint.com/
*/

// 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 );
}

Обратите внимание, что ссылки действия, в этом случае ссылка «Настройки», покажет только, когда плагин был активирован. Это приведет клиента к странице администрирования checkout WooCommerce. Давайте продолжим, чтобы мы были на один шаг ближе к активации плагина и просмотрели по крайней мере некоторые поля по умолчанию.

Настройка Class Constructor

Теперь, когда мы собираемся начать работу над нашим фактическим классом оплаты, мы должны начать с установки некоторых значений по умолчанию для этого Платежного шлюза. Некоторые настройки мы определим:

 

  • id — Глобальный ID для этого способа оплаты.
  • method_title — Заголовок отображается в верхней части страницы платежных шлюзов рядом со всеми другими платежными шлюзами.
  • method_description — Описание для этого платежного шлюза, показанное на фактической странице вариантов оплаты на внутреннем интерфейсе.
  • title — Заголовок, который будет использоваться для вертикальных вкладок, которые можно упорядочить сверху вниз.
  • icon — Если вы хотите показать изображение рядом с именем шлюза на front-end.. URL-адрес изображения.
  • has_fields — Bool Может быть установлено значение «true», если вы хотите, чтобы поля оплаты отображались в checkout при выполнении прямой интеграции, что мы и делаем в этом случае.
  • supports — Поддерживает форму кредитной карты по умолчанию. Подробнее об этом позже. На этом этапе вам просто нужно знать, что это супер круто.

 

Выражение этого в нашем конструкторе является следующим, наряду с некоторыми другими полезными функциями, которые нам нужны, чтобы все работало в гармонии. Комментарии помогут вам понять цель и почему она там.

// 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, e.g:
// $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 API-интерфейса оплаты. В нашем случае, так как мы используем AIM AIM Authorize.net, нам просто нужен логин Authorize.net API и ключ транзакции.

Поскольку мы используем нашу тестовую учетную запись для создания плагина, также неплохо было бы включить опцию для установки шлюза в тестовом режиме. Независимо от того, что вы делаете, предоставление способа легко превратить Gateway в тестовый режим очень полезно, и вы должны подумать о том, чтобы сделать это необходимым при создании шлюза. Большинство шлюзов предоставляют вам две разные ссылки, с которыми вы можете отправлять транзакции: одна для целей тестирования, а другая для производственной среды.

После некоторого мозгового штурма, это то, что я придумал для полей, которые мы собираемся включить в нашу страницу администрирования:

 

  • enabled — Enable/Disable этого payment gateway.
  • title — Название платежа, которое клиент увидит во время процесса checkout.
  • description — писание платежа, которое клиент увидит в процессе оформления заказа.
  • api_login — Вход в API, предоставляемый Authorize.net при регистрации в учетной записи.
  • trans_key — Ключ транзакции, предоставленный Authorize.net при регистрации в учетной записи.
  • environment — Поместите платежный шлюз в тестовом режиме или на production.

 

Давайте превратим их в код, который понимает 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.

Многие плагины шлюза, в том числе и наши, используют подобный интерфейс для полей оплаты картой в форме checkout, поэтому WooCommerce добавила нам форму, которую мы можем использовать при необходимости. Эта форма по умолчанию имеет автоматическое форматирование номеров кредитных карт, срок действия и даже автоматически отображает тип используемой карты, как только клиент вводит первые несколько цифр номера своей кредитной карты. Чтобы использовать эту форму, убедитесь, что ваш сайт работает, по крайней мере, с версией 2.1 WooCommerce.

По умолчанию форма создаст следующие поля формы, которые можно получить из $ _POST:

  • GATEWAYID-card-number
  • GATEWAYID-card-cvc
  • GATEWAYID-card-expiry

Вот пример того, как форма по умолчанию выглядит без каких-либо специальных 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’] );
}

Давайте разберем код еще больше, чтобы его было легче понять.

Lines 5-15

Мы назначаем $customer_order новый WC_Order, содержащий всю информацию из заказа, для которого мы собираемся обработать платеж. Затем мы решаем, находимся ли мы в тестовом режиме, и, наконец, выбрали правильный URL для транзакции.

Lines 18-66

Это произвольные поля, которые мы можем отправить Authorize.net, чтобы они могли записать эту информацию. Мы создаем его в виде массива, чтобы позже мы могли построить правильный запрос, используя http_build_query().

Lines 69-74

Поскольку мы используем WordPress, мы можем использовать весь HTTP API для взаимодействия с другими сайтами и, в этом случае, POST нашей полезной нагрузки для обработки на Authorize.net. Перейдите по этой ссылке, чтобы узнать больше о HTTP API и wp_remote_post().

Lines 76-80

Здесь происходят две важные проверки. Сначала мы убеждаемся, что WordPress не столкнулся с какими-либо ошибками при загрузке нашей полезной нагрузки, а во-вторых; Мы убеждаемся что мы получили ответ назад. В любой момент мы генерируем ошибку исключения, позволяющую клиенту узнать, есть ли что-то неладное в транзакции. Ниже приведен пример одной из этих ошибок:

Lines 83-94

Если мы дошли до этого без ошибок, мы можем извлечь тело ответа и разобрать его во что-то, что мы можем прочитать. Первые четыре значения в ответе являются единственными, которые нам нужны. Мы добавляем эти четыре значения в массив для упрощения тестирования, а также для упрощения его чтения.

Lines 98-112

Проверьте значение параметра response_code. Коды 1 или 4 означают, что транзакция одобрена. Если транзакция одобрена, мы добавляем дружественную записку для заказа, отмечаем заказ как оплаченный, очищаем содержимое корзины и, наконец, перенаправляем клиента на страницу «Спасибо». Если вам интересно узнать, как выглядят примечания к заказу после выполнения этих четырех шагов, взгляните ниже:

Lines 114-118

В случае, если транзакция не прошла успешно, мы выводим уведомление об ошибке клиенту и обновляем заказ с ошибкой, полученной от Authorize.net. Ниже приведен пример заметок заказа в фоновом режиме после того, как клиент попытался несколько раз выполнить транзакцию без успеха.

Вот и все для обработки платежей.

Проверка отправленных полей

Мы не выполняем проверку полей, поскольку мы полагаемся на форму кредитной карты по умолчанию. Попытайтесь ввести буквы или символы в любом поле, и вы увидите, что это просто невозможно. В некоторых случаях я могу видеть, как это было бы чрезвычайно полезно, например; Для проверки сроков годности, которые должны быть в определенном формате, отличном от стандарта, который мы в основном привыкли видеть.

Ради простоты в этой статье мы просто вернем значение «true» и обойдем проверку поля.

// Validate fields
public function validate_fields() {
return true;
}

Используете ли вы Checkout Pages SSL?

Часть того, что вы можете предоставить заказчику для бесшовной проверки, и разрешать им оформление покупки на вашем собственном сайте, требует использования SSL-сертификата. WooCommerce позволяет вам быстро применять SSL только на страницах проверки, установив флажок «Принудительная безопасная проверка» в разделе WooCommerce -> Settings -> Checkout.

Мы просто проверим, проверено это или нет. Если он не был отмечен, тогда мы увидим ошибку на сервере, предупреждающую о необходимости 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 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, e.g:
// $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 Gateway

<?php
/*
Plugin Name: Authorize.net AIM — WooCommerce Gateway
Plugin URI: http://www.sitepoint.com/
Description: Extends WooCommerce by Adding the Authorize.net AIM Gateway.
Version: 1.0
Author: Yojance Rabelo, SitePoint
Author URI: http://www.sitepoint.com/
*/

// 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 );
}

Удаление / product /, / product-category /, или / shop / из URL-адресов

В сумме

Удаление / product /, / category-category / или / shop / из URL-адресов нецелесообразно из-за того, как WordPress решает свои URL-адреса. Он использует категорию продукта (или любой другой текст на этот счет) базы URL-адреса, чтобы определить, что это URL-адрес, ведущий к категории продукта.

Существуют плагины SEO, которые позволяют удалить эту базу, но это может привести к ряду проблем с производительностью и дублированием URL-адресов.

Лучше избегать

Вам будет труднее, если WordPress обнаружит, на какую страницу вы пытаетесь попасть, когда вводите URL-адрес категории товаров.

Кроме того, понимайте, что стандартная «Страница» в WordPress всегда не имеет базового текста в URL. Например:

  • http://yoursite.com/about-page/ (это URL стандартной страницы)
  • http://yoursite.com/about-page/product-category/category-x/ (это URL ведет к категории продукта)

Что произойдет, если мы удалим часть ‘product-category’?

  • http://yoursite.com/about-page/about-page/
  • http://yoursite.com/about-page/category-x/

WordPress должен будет сделать гораздо больше работы, чтобы определить, какую страницу вы ищете, когда вводите один из указанных выше URL-адресов. Именно поэтому мы не рекомендуем использовать любой плагин SEO для достижения этой цели.

WC_API – The WooCommerce API Callback

API WooCommerce позволяет плагинам выполнять обратный вызов специального URL-адреса, который затем загружает указанный класс (если он существует) и запускает действие. Это также полезно для шлюзов, которые не инициализированы.

Вы можете просмотреть класс WC_API в наших документах.

Callback URL

Для запуска API WooCommerce вам нужно использовать специальный URL-адрес. Перед WooCommerce 2.0 вы можете использовать:

http://yoursite.com/?wc-api=CALLBACK

В WooCommerce 2.0+ вы можете использовать это или использовать нашу конечную точку:

http://yoursite.com/wc-api/CALLBACK/

Когда этот URL-адрес вызывается, WooCommerce:

  1. Инициализирует класс CALLBACK, если он существует
  2. Запускает действие, основанное на обратном вызове: woocommerce api callback. Примечание: CALLBACK будет sanitized и строчными буквами.
  3. Выйдите из WordPress.

Hooking into the callback

Добавьте действие, чтобы зацепить hook обратного вызова. Например:

add_action( ‘woocommerce_api_callback’, ‘callback_handler’ );

WooCommerce выйдет после этого действия, но вы можете перенаправить пользователя в другом месте от вашего обработчика, если хотите.

Добавление Section на Settings Tab

Когда вы добавляете расширения для WooCommerce, для которого требуются какие-то настройки, важно спросить себя: где они будут находиться?

Если у вашего расширения всего несколько простых настроек, вам действительно нужно создать новую вкладку специально для нее? Скорее всего, ответ будет отрицательным.

Когда создавать раздел

Допустим, у нас есть расширение, которое добавляет слайдер к одной странице продукта. Это расширение не имеет много вариантов, всего пара:

  • Автоматическая вставка в одну страницу продукта (checkbox)
  • Заголовок слайдера (text field)

Это только два варианта, специально связанных с продуктами. Мы могли бы просто добавить их в основные настройки WooCommerce Products (WooCommerce > Settings > Products), но это было бы не очень удобно. Пользователи не знают, где искать, поэтому им нужно будет просканировать все варианты продуктов, и было бы трудно / невозможно напрямую связать эти параметры.

К счастью, начиная с WooCommerce 2.2.2, появился новый фильтр, который позволяет вам добавить новый раздел под вкладками основных настроек.

Как создать раздел

Мы займемся этим с помощью отдельных функций, но вам, вероятно, следует создать класс, в котором хранятся все ваши методы настроек.

Первое, что вам нужно, — это добавить раздел, который можно сделать та

к, подключившись к фильтру woocommerce_get_sections_products:

<?php

/**

* Create the section beneath the products tab

**/

add_filter( ‘woocommerce_get_sections_products’, ‘wcslider_add_section’ );

function wcslider_add_section( $sections ) {

$sections[‘wcslider’] = __( ‘WC Slider’, ‘text-domain’ );

return $sections;

}

Убедитесь, что вы изменили части wcslider, чтобы они соответствовали name / text-domain. вашего расширения.

Важная информация о фильтре woocommerce_get_sections_products заключается в том, что в последней части продуктов есть вкладка, на которую вы хотите добавить раздел. Поэтому, если вы хотите добавить новую вкладку в раздел учетных записей, вы должны подключиться к фильтру woocommerce_get_sections_accounts.

Как добавить параметры в раздел

Теперь, когда у вас есть вкладка, вам нужно фильтровать выходные данные woocommerce_get_sections_products (или аналогичных). Вы хотели бы добавить настройки, как обычно, используя WooCommerce Settings API, но проверьте текущий раздел перед добавлением настроек в массив настроек вкладки.

Например, добавим приведенные выше примеры настроек в новый раздел wcslider, который мы только что создали:

<?php

/**

* Add settings to the specific section we created before

*/

add_filter( ‘woocommerce_get_settings_products’, ‘wcslider_all_settings’, 10, 2 );

function wcslider_all_settings( $settings, $current_section ) {

/**

* Check the current section is what we want

**/

if ( $current_section == ‘wcslider’ ) {

$settings_slider = array();

// Add Title to the Settings

$settings_slider[] = array( ‘name’ => __( ‘WC Slider Settings’, ‘text-domain’ ), ‘type’ => ‘title’, ‘desc’ => __( ‘The following options are used to configure WC Slider’, ‘text-domain’ ), ‘id’ => ‘wcslider’ );

// Add first checkbox option

$settings_slider[] = array(

‘name’     => __( ‘Auto-insert into single product page’, ‘text-domain’ ),

‘desc_tip’ => __( ‘This will automatically insert your slider into the single product page’, ‘text-domain’ ),

‘id’       => ‘wcslider_auto_insert’,

‘type’     => ‘checkbox’,

‘css’      => ‘min-width:300px;’,

‘desc’     => __( ‘Enable Auto-Insert’, ‘text-domain’ ),

);

// Add second text field option

$settings_slider[] = array(

‘name’     => __( ‘Slider Title’, ‘text-domain’ ),

‘desc_tip’ => __( ‘This will add a title to your slider’, ‘text-domain’ ),

‘id’       => ‘wcslider_title’,

‘type’     => ‘text’,

‘desc’     => __( ‘Any title you want can be added to your slider with this option!’, ‘text-domain’ ),

);

$settings_slider[] = array( ‘type’ => ‘sectionend’, ‘id’ => ‘wcslider’ );

return $settings_slider;

/**

* If not, return the standard settings

**/

} else {

return $settings;

}

Мы подключаемся к тому же фильтру woocommerce_get_sections_products, но на этот раз делаем проверку, что $current_section соответствует нашему ранее определенному настраиваемому разделу (wcslider), прежде чем добавлять новые настройки.

Использование новых параметров

Теперь вы просто используете свои вновь созданные настройки, как и любой другой параметр WordPress / WooCommerce, с помощью функции get_option и определенного идентификатора настройки.

Например, чтобы использовать ранее созданную опцию wcslider_auto_insert, просто используйте следующий код:

get_option( ‘wcslider_auto_insert’ )

Вывод

При создании расширения для WooCommerce, подумайте, где ваши настройки принадлежат, прежде чем создавать их. Ключом к созданию полезного продукта является его простота в использовании для конечного пользователя, поэтому правильное размещение настроек имеет решающее значение.

Более подробную информацию о добавлении настроек в WooCommerce см. В документации по настройкам API.

Реализация класса интеграции WC

Если вы настраиваете WooCommerce или добавляете свои собственные функции, вам, вероятно, понадобится какая-то страница настроек. Одним из самых простых способов создания страницы настроек является использование класса WC_Integration. Использование класса Integration автоматически создаст новую страницу настроек в WooCommerce > Settings > Integrations, и она автоматически сохранит и обезопасит ваши данные для вас.

Мы создали этот урок, чтобы вы могли увидеть, как создать новую интеграцию.

Настройка интеграции

Для создания интеграции вам понадобится как минимум два файла, поэтому вам нужно создать каталог.

Создание основного файла плагина

Создайте свой основной файл подключаемого модуля, чтобы подключиться к hooks plugins_loaded и проверьте, существует ли класс WC_Integration. Если это не так, то, скорее всего, пользователь не активирует WooCommerce.

После этого вам необходимо зарегистрировать интеграцию. Загрузите файл интеграции (мы перейдем к этому файлу через минуту). Используйте фильтр woocommerce_integrations, чтобы добавить новую интеграцию в массив.

Создание класса интеграции

Теперь, когда у нас есть базовая установка, давайте фактически реализуем этот класс Integration. Уже есть класс WC_Integration, поэтому мы хотим создать дочерний класс. Таким образом, он наследует все существующие методы и данные.

Вам нужно будет установить идентификатор, описание и заголовок для вашей интеграции. Они появятся на странице интеграции.

Вам также нужно будет загрузить настройки, вызывая:

$this->init_form_fields(); & $this->init_settings();

Вам также нужно будет сохранить параметры, вызвав hook woocommerce_update_options_integration_{your method id}.

Наконец, вы должны ввести некоторые настройки для сохранения! Я включил в него два фиктивных поля, но в следующем разделе мы углубимся в поля.

<?php

/**

* Integration Demo Integration.

*

* @package  WC_Integration_Demo_Integration

* @category Integration

* @author   Patrick Rauland

*/

if ( ! class_exists( ‘WC_Integration_Demo_Integration’ ) ) :

class WC_Integration_Demo_Integration extends WC_Integration {

/**

* Init and hook in the integration.

*/

public function __construct() {

global $woocommerce;

$this->id                 = ‘integration-demo’;

$this->method_title       = __( ‘Integration Demo’, ‘woocommerce-integration-demo’ );

$this->method_description = __( ‘An integration demo to show you how easy it is to extend WooCommerce.’, ‘woocommerce-integration-demo’ );

// Load the settings.

$this->init_form_fields();

$this->init_settings();

// Define user set variables.

$this->api_key          = $this->get_option( ‘api_key’ );

$this->debug            = $this->get_option( ‘debug’ );

// Actions.

add_action( ‘woocommerce_update_options_integration_’ .  $this->id, array( $this, ‘process_admin_options’ ) );

}

/**

* Initialize integration settings form fields.

*/

public function init_form_fields() {

$this->form_fields = array(

‘api_key’ => array(

‘title’             => __( ‘API Key’, ‘woocommerce-integration-demo’ ),

‘type’              => ‘text’,

‘description’       => __( ‘Enter with your API Key. You can find this in «User Profile» drop-down (top right corner) > API Keys.’, ‘woocommerce-integration-demo’ ),

‘desc_tip’          => true,

‘default’           => »

),

‘debug’ => array(

‘title’             => __( ‘Debug Log’, ‘woocommerce-integration-demo’ ),

‘type’              => ‘checkbox’,

‘label’             => __( ‘Enable logging’, ‘woocommerce-integration-demo’ ),

‘default’           => ‘no’,

‘description’       => __( ‘Log events such as API requests’, ‘woocommerce-integration-demo’ ),

), ); }

endif;

class-wc-integration-demo-integration.php

<?php

/**

* Plugin Name: WooCommerce Integration Demo

* Plugin URI: https://gist.github.com/BFTrick/091d55feaaef0c5341d8

* Description: A plugin demonstrating how to add a new WooCommerce integration.

* Author: Patrick Rauland

* Author URI: http://speakinginbytes.com/

* Version: 1.0

*

* This program is free software: you can redistribute it and/or modify

* it under the terms of the GNU General Public License as published by

* the Free Software Foundation, either version 3 of the License, or

* (at your option) any later version.

*

* This program is distributed in the hope that it will be useful,

* but WITHOUT ANY WARRANTY; without even the implied warranty of

* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the

* GNU General Public License for more details.

*

* You should have received a copy of the GNU General Public License

* along with this program. If not, see <http://www.gnu.org/licenses/>.

*

*/

if ( ! class_exists( ‘WC_Integration_Demo’ ) ) :

class WC_Integration_Demo {

/**

* Construct the plugin.

*/

public function __construct() {

add_action( ‘plugins_loaded’, array( $this, ‘init’ ) );

}

/**

* Initialize the plugin.

*/

public function init() {

// Checks if WooCommerce is installed.

if ( class_exists( ‘WC_Integration’ ) ) {

// Include our integration class.

include_once ‘class-wc-integration-demo-integration.php’;

// Register the integration.

add_filter( ‘woocommerce_integrations’, array( $this, ‘add_integration’ ) );

} else {

// throw an admin error if you like

}

/**

* Add a new integration to WooCommerce.

*/

public function add_integration( $integrations ) {

$integrations[] = ‘WC_Integration_Demo_Integration’;

return $integrations;

}

$WC_Integration_Demo = new WC_Integration_Demo( __FILE__ );

endif;

woocommerce-integration-demo.php

Создание настроек

Если вы просмотрите последний раздел, вы увидите, что мы добавили две фиктивные настройки, используя метод init_form_fields ().

Типы настроек

WooCommerce поддерживает 8 типов настроек.

  • text
  • price
  • decimal
  • password
  • textarea
  • checkbox
  • select
  • multiselect

И эти параметры имеют атрибуты, которые вы можете использовать. Они влияют на то, как этот параметр выглядит и ведет себя на странице настроек. Это не влияет на настройку. Атрибуты будут проявляться немного по-разному в зависимости от типа настройки. placeholder, например, не работает с checkboxes. Чтобы увидеть, как именно они работают, вы должны просмотреть исходный код. Исх.

  • title
  • class
  • css
  • placeholder
  • description
  • default
  • desc_tip

Создание собственных настроек

Встроенные настройки великолепны, но для создания страницы настроек могут потребоваться дополнительные элементы управления. Вот почему мы включили некоторые методы, чтобы сделать это для вас.

Сначала создайте новую настройку. И под типом введите любой новый элемент управления, который вы хотите.

Затем создайте новый метод для генерации HTML для этого ввода. Вы можете посмотреть исходный код примера кода. В следующем примере создается кнопка, которая переходит на WooThemes.com.

/**

* Initialize integration settings form fields.

*

* @return void

*/

public function init_form_fields() {

$this->form_fields = array(

// don’t forget to put your other settings here

‘customize_button’ => array(

‘title’             => __( ‘Customize!’, ‘woocommerce-integration-demo’ ),

‘type’              => ‘button’,

‘custom_attributes’ => array(

‘onclick’ => «location.href=’http://www.woothemes.com'»,

),

‘description’       => __( ‘Customize your settings by going to the integration site directly.’, ‘woocommerce-integration-demo’ ),

‘desc_tip’          => true,

); }

/**

* Generate Button HTML.

*

* @access public

* @param mixed $key

* @param mixed $data

* @since 1.0.0

* @return string

*/

public function generate_button_html( $key, $data ) {

$field    = $this->plugin_id . $this->id . ‘_’ . $key;

$defaults = array(

‘class’             => ‘button-secondary’,

‘css’               => »,

‘custom_attributes’ => array(),

‘desc_tip’          => false,

‘description’       => »,

‘title’             => »,

);

$data = wp_parse_args( $data, $defaults );

ob_start();

?>

<tr valign=»top»>

<th scope=»row» class=»titledesc»>

<label for=»<?php echo esc_attr( $field ); ?>»><?php echo wp_kses_post( $data[‘title’] ); ?></label>

<?php echo $this->get_tooltip_html( $data ); ?>

</th>

<td class=»forminp»>

<fieldset>

<legend class=»screen-reader-text»><span><?php echo wp_kses_post( $data[‘title’] ); ?></span></legend>

<button class=»<?php echo esc_attr( $data[‘class’] ); ?>» type=»button» name=»<?php echo esc_attr( $field ); ?>» id=»<?php echo esc_attr( $field ); ?>» style=»<?php echo esc_attr( $data[‘css’] ); ?>» <?php echo $this->get_custom_attribute_html( $data ); ?>><?php echo wp_kses_post( $data[‘title’] ); ?></button>

<?php echo $this->get_description_html( $data ); ?>

</fieldset>

</td>

</tr>

<?php

return ob_get_clean();

}

create-custom-setting.php

Validating & Sanitizing Data

Чтобы создать наилучший пользовательский интерфейс, вы, скорее всего, захотите проверить и обезопасить свои данные. Класс интеграции уже выполняет базовую sanitization, поэтому в нем нет вредоносного кода, но вы можете дополнительно очистить его, удалив неиспользуемые данные. Примером sanitization обработки данных может быть интеграция со сторонней службой, в которой все ключи API являются строчными. Вы можете преобразовать ключ API в верхний регистр, что сделает его более понятным для пользователя.

Sanitize

Сначала я расскажу вам, как sanitize данные, потому что это немного легче понять. Но единственное, что вы должны иметь в виду, это то, что sanitize происходит после проверки. Поэтому, если что-то не validated, оно не попадет на стадию sanitize.

/**

* Init and hook in the integration.

*/

public function __construct() {

   // do other constructor stuff first

// Filters.

add_filter( ‘woocommerce_settings_api_sanitized_fields_’ . $this->id, array( $this, ‘sanitize_settings’ ) );

}

/**

* Sanitize our settings

*/

public function sanitize_settings( $settings ) {

// We’re just going to make the api key all upper case characters since that’s how our imaginary API works

if ( isset( $settings ) &&

    isset( $settings[‘api_key’] ) ) {

$settings[‘api_key’] = strtoupper( $settings[‘api_key’] );

}

return $settings;

}

sanitize-settings.php

Validation

Validation не всегда необходима, но это приятно делать. Если ваши ключи API всегда состоят из 10 символов, а кто-то вводит один, который не 10, вы можете распечатать сообщение об ошибке и предупредить пользователя много головной боли, когда они предположили, что они правильно вписали его.

Сначала настройте метод validate_ {set key} _field для каждого поля, которое вы хотите проверить. Например, в поле api_key вам нужен метод validate_api_key_field ().

public function validate_api_key_field( $key, $value ) {

   if ( isset( $value ) && 20 < strlen( $value ) ) {

       WC_Admin_Settings::add_error( esc_html__( ‘Looks like you made a mistake with the API Key field. Make sure it isn&apos;t longer than 20 characters’, ‘woocommerce-integration-demo’ ) );

   }

   return $value;

}

validate-settings.php

Полный пример

Если вы следовали вместе, у вас должен быть полный пример интеграции. Если у вас есть какие-либо проблемы, ознакомьтесь с нашей полной интеграционной демонстрацией.

Generic selectors
Exact matches only
Search in title
Search in content
Search in posts
Search in pages
Filter by Categories
=) Home Work
CSS
JavaScript
Word Press

Интеркасса (API)

Доллар

покупка  $ 1 | 27.53 грн
продажа $ 1 | 24.7 грн

Евро

покупка  € 1 | 30.59 грн
продажа € 1 | 27.33 грн