Дубликат метода оплаты Cash on delivery (COD)
Создал плагин с копией метода оплаты COD, но в выполненных ордерах приходит как товар оплаченный онлайн. Как сделать ордер без оплаты (точно как COD). Мне надо сделать оплата картой при доставке товара, что бы курьер мог взять с собой терминал для оплаты картой.
Вот таким макаром создал копию метода оплаты. https://stackoverflow.com/questions/63787049/extending-woocommerce-cod-payment-gateway-in-a-plugin
Здесь cкопировал код COD и сделал COD2 https://github.com/woocommerce/woocommerce/blob/4.4.1/includes/gateways/cod/class-wc-gateway-cod.php
Плагины для создания дополнительных методов оплаты пробовал, так же выводят что продукт был оплачен онлайн.
Разницав в заказах
Вот мой код.
<?php /* Plugin Name: Woo card payment on delivery Plugin URI: https://woocommerce.com/ Description: Your shipping method plugin Version: 1.0.0 Author: Aleksei Author URI: https://woocommerce.com/ */ defined( 'ABSPATH' ) or exit; // Make sure WooCommerce is active if ( ! in_array( 'woocommerce/woocommerce.php', apply_filters( 'active_plugins', get_option( 'active_plugins' ) ) ) ) { return; } add_filter( 'woocommerce_payment_gateways', 'wc_custom_add_to_gateways' ); function wc_custom_add_to_gateways( $gateways ) { $gateways[] = 'WC_Gateway_COD2'; return $gateways; } add_filter( 'plugin_action_links_' . plugin_basename( __FILE__ ), 'wc_gateway_custom_plugin_links' ); function wc_gateway_custom_plugin_links( $links ) { $plugin_links = array( '<a href="' . admin_url( 'admin.php?page=wc-settings&tab=checkout§ion=cod2' ) . '">' . __( 'Configure', 'payment_cod2' ) . '</a>' ); return array_merge( $plugin_links, $links ); } add_action( 'plugins_loaded', 'wc_gateway_cod2_init', 11 ); function wc_gateway_cod2_init() { class WC_Gateway_COD2 extends WC_Payment_Gateway { public $domain; // The text domain (optional) /** * Constructor for the gateway. */ public function __construct() { $this->domain = 'payment_cod2'; // text domain name (for translations) // Setup general properties. $this->setup_properties(); // Load the settings. $this->init_form_fields(); $this->init_settings(); // Get settings. $this->title = $this->get_option( 'title' ); $this->description = $this->get_option( 'description' ); $this->instructions = $this->get_option( 'instructions' ); $this->enable_for_methods = $this->get_option( 'enable_for_methods', array() ); $this->enable_for_virtual = $this->get_option( 'enable_for_virtual', 'yes' ) === 'yes'; add_action( 'woocommerce_update_options_payment_gateways_' . $this->id, array( $this, 'process_admin_options' ) ); add_action( 'woocommerce_thankyou_' . $this->id, array( $this, 'thankyou_page' ) ); add_filter( 'woocommerce_payment_complete_order_status', array( $this, 'change_payment_complete_order_status' ), 10, 3 ); // Customer Emails. add_action( 'woocommerce_email_before_order_table', array( $this, 'email_instructions' ), 10, 3 ); } /** * Setup general properties for the gateway. */ protected function setup_properties() { $this->id = 'cod2'; $this->icon = apply_filters( 'woocommerce_cod2_icon', '' ); $this->method_title = __( 'Card Payment on Delivery', 'woocommerce' ); $this->method_description = __( 'Have your customers pay with card upon delivery.', 'woocommerce' ); $this->has_fields = false; } /** * Initialise Gateway Settings Form Fields. */ public function init_form_fields() { $this->form_fields = array( 'enabled' => array( 'title' => __( 'Enable/Disable', 'woocommerce' ), 'label' => __( 'Enable Card Payment on Delivery', 'woocommerce' ), 'type' => 'checkbox', 'description' => '', 'default' => 'no', ), 'title' => array( 'title' => __( 'Title', 'woocommerce' ), 'type' => 'text', 'description' => __( 'Payment method description that the customer will see on your checkout.', 'woocommerce' ), 'default' => __( 'Card Payment on Delivery', 'woocommerce' ), 'desc_tip' => true, ), 'description' => array( 'title' => __( 'Description', 'woocommerce' ), 'type' => 'textarea', 'description' => __( 'Payment method description that the customer will see on your website.', 'woocommerce' ), 'default' => __( 'Pay with card upon delivery.', 'woocommerce' ), 'desc_tip' => true, ), 'instructions' => array( 'title' => __( 'Instructions', 'woocommerce' ), 'type' => 'textarea', 'description' => __( 'Instructions that will be added to the thank you page.', 'woocommerce' ), 'default' => __( 'Pay with card upon delivery.', 'woocommerce' ), 'desc_tip' => true, ), ); } /** * Check If The Gateway Is Available For Use. * * @return bool */ public function is_available() { $order = null; $needs_shipping = false; // Test if shipping is needed first. if ( WC()->cart && WC()->cart->needs_shipping() ) { $needs_shipping = true; } elseif ( is_page( wc_get_page_id( 'checkout' ) ) && 0 < get_query_var( 'order-pay' ) ) { $order_id = absint( get_query_var( 'order-pay' ) ); $order = wc_get_order( $order_id ); // Test if order needs shipping. if ( 0 < count( $order->get_items() ) ) { foreach ( $order->get_items() as $item ) { $_product = $item->get_product(); if ( $_product && $_product->needs_shipping() ) { $needs_shipping = true; break; } } } } $needs_shipping = apply_filters( 'woocommerce_cart_needs_shipping', $needs_shipping ); // Virtual order, with virtual disabled. if ( ! $this->enable_for_virtual && ! $needs_shipping ) { return false; } // Only apply if all packages are being shipped via chosen method, or order is virtual. if ( ! empty( $this->enable_for_methods ) && $needs_shipping ) { $order_shipping_items = is_object( $order ) ? $order->get_shipping_methods() : false; $chosen_shipping_methods_session = WC()->session->get( 'chosen_shipping_methods' ); if ( $order_shipping_items ) { $canonical_rate_ids = $this->get_canonical_order_shipping_item_rate_ids( $order_shipping_items ); } else { $canonical_rate_ids = $this->get_canonical_package_rate_ids( $chosen_shipping_methods_session ); } if ( ! count( $this->get_matching_rates( $canonical_rate_ids ) ) ) { return false; } } return parent::is_available(); } /** * Checks to see whether or not the admin settings are being accessed by the current request. * * @return bool */ private function is_accessing_settings() { if ( is_admin() ) { // phpcs:disable WordPress.Security.NonceVerification if ( ! isset( $_REQUEST['page'] ) || 'wc-settings' !== $_REQUEST['page'] ) { return false; } if ( ! isset( $_REQUEST['tab'] ) || 'checkout' !== $_REQUEST['tab'] ) { return false; } if ( ! isset( $_REQUEST['section'] ) || 'cod' !== $_REQUEST['section'] ) { return false; } // phpcs:enable WordPress.Security.NonceVerification return true; } if ( Constants::is_true( 'REST_REQUEST' ) ) { global $wp; if ( isset( $wp->query_vars['rest_route'] ) && false !== strpos( $wp->query_vars['rest_route'], '/payment_gateways' ) ) { return true; } } return false; } /** * Loads all of the shipping method options for the enable_for_methods field. * * @return array */ private function load_shipping_method_options() { // Since this is expensive, we only want to do it if we're actually on the settings page. if ( ! $this->is_accessing_settings() ) { return array(); } $data_store = WC_Data_Store::load( 'shipping-zone' ); $raw_zones = $data_store->get_zones(); foreach ( $raw_zones as $raw_zone ) { $zones[] = new WC_Shipping_Zone( $raw_zone ); } $zones[] = new WC_Shipping_Zone( 0 ); $options = array(); foreach ( WC()->shipping()->load_shipping_methods() as $method ) { $options[ $method->get_method_title() ] = array(); // Translators: %1$s shipping method name. $options[ $method->get_method_title() ][ $method->id ] = sprintf( __( 'Any "%1$s" method', 'woocommerce' ), $method->get_method_title() ); foreach ( $zones as $zone ) { $shipping_method_instances = $zone->get_shipping_methods(); foreach ( $shipping_method_instances as $shipping_method_instance_id => $shipping_method_instance ) { if ( $shipping_method_instance->id !== $method->id ) { continue; } $option_id = $shipping_method_instance->get_rate_id(); // Translators: %1$s shipping method title, %2$s shipping method id. $option_instance_title = sprintf( __( '%1$s (#%2$s)', 'woocommerce' ), $shipping_method_instance->get_title(), $shipping_method_instance_id ); // Translators: %1$s zone name, %2$s shipping method instance name. $option_title = sprintf( __( '%1$s – %2$s', 'woocommerce' ), $zone->get_id() ? $zone->get_zone_name() : __( 'Other locations', 'woocommerce' ), $option_instance_title ); $options[ $method->get_method_title() ][ $option_id ] = $option_title; } } } return $options; } /** * Converts the chosen rate IDs generated by Shipping Methods to a canonical 'method_id:instance_id' format. * * @since 3.4.0 * * @param array $order_shipping_items Array of WC_Order_Item_Shipping objects. * @return array $canonical_rate_ids Rate IDs in a canonical format. */ private function get_canonical_order_shipping_item_rate_ids( $order_shipping_items ) { $canonical_rate_ids = array(); foreach ( $order_shipping_items as $order_shipping_item ) { $canonical_rate_ids[] = $order_shipping_item->get_method_id() . ':' . $order_shipping_item->get_instance_id(); } return $canonical_rate_ids; } /** * Converts the chosen rate IDs generated by Shipping Methods to a canonical 'method_id:instance_id' format. * * @since 3.4.0 * * @param array $chosen_package_rate_ids Rate IDs as generated by shipping methods. Can be anything if a shipping method doesn't honor WC conventions. * @return array $canonical_rate_ids Rate IDs in a canonical format. */ private function get_canonical_package_rate_ids( $chosen_package_rate_ids ) { $shipping_packages = WC()->shipping()->get_packages(); $canonical_rate_ids = array(); if ( ! empty( $chosen_package_rate_ids ) && is_array( $chosen_package_rate_ids ) ) { foreach ( $chosen_package_rate_ids as $package_key => $chosen_package_rate_id ) { if ( ! empty( $shipping_packages[ $package_key ]['rates'][ $chosen_package_rate_id ] ) ) { $chosen_rate = $shipping_packages[ $package_key ]['rates'][ $chosen_package_rate_id ]; $canonical_rate_ids[] = $chosen_rate->get_method_id() . ':' . $chosen_rate->get_instance_id(); } } } return $canonical_rate_ids; } /** * Indicates whether a rate exists in an array of canonically-formatted rate IDs that activates this gateway. * * @since 3.4.0 * * @param array $rate_ids Rate ids to check. * @return boolean */ private function get_matching_rates( $rate_ids ) { // First, match entries in 'method_id:instance_id' format. Then, match entries in 'method_id' format by stripping off the instance ID from the candidates. return array_unique( array_merge( array_intersect( $this->enable_for_methods, $rate_ids ), array_intersect( $this->enable_for_methods, array_unique( array_map( 'wc_get_string_before_colon', $rate_ids ) ) ) ) ); } /** * Process the payment and return the result. * * @param int $order_id Order ID. * @return array */ public function process_payment( $order_id ) { $order = wc_get_order( $order_id ); if ( $order->get_total() > 0 ) { // Mark as processing or on-hold (payment won't be taken until delivery). $order->update_status( apply_filters( 'woocommerce_cod_process_payment_order_status', $order->has_downloadable_item() ? 'on-hold' : 'processing', $order ), __( 'Payment to be made upon delivery.', 'woocommerce' ) ); } else { $order->payment_complete(); } // Remove cart. WC()->cart->empty_cart(); // Return thankyou redirect. return array( 'result' => 'success', 'redirect' => $this->get_return_url( $order ), ); } /** * Output for the order received page. */ public function thankyou_page() { if ( $this->instructions ) { echo wp_kses_post( wpautop( wptexturize( $this->instructions ) ) ); } } /** * Change payment complete order status to completed for COD orders. * * @since 3.1.0 * @param string $status Current order status. * @param int $order_id Order ID. * @param WC_Order|false $order Order object. * @return string */ public function change_payment_complete_order_status( $status, $order_id = 0, $order = false ) { if ( $order && 'cod' === $order->get_payment_method() ) { $status = 'completed'; } return $status; } /** * Add content to the WC emails. * * @param WC_Order $order Order object. * @param bool $sent_to_admin Sent to admin. * @param bool $plain_text Email format: plain text or HTML. */ public function email_instructions( $order, $sent_to_admin, $plain_text = false ) { if ( $this->instructions && ! $sent_to_admin && $this->id === $order->get_payment_method() ) { echo wp_kses_post( wpautop( wptexturize( $this->instructions ) ) . PHP_EOL ); } } } }
Я не совсем понимаю вашу задачу, НО если вам нужно выводить СВОЙ статус для заказа, который оплатили вашим методом, что выше
то вот здесь
вы ставите статус заказу.
Предлагаю добавить кастомный order status
cod2_completed
И ставить его, когда оплата прошла способом cod2
Там пример, как добавить кастомный статус в order
Мне надо что бы метод оплаты был такой же как и наличными при доставке. Он не должен быть оплачен онлайн, а оплачивается картой при доставке.
Сейчас ордер приходит в админку как и COD, но он почему то со статусом оплачен онлайн приходит в POS систему (кассу)
Решение выше.
Еще раз - в Woo НЕТ понятия статус "Оплачен онлайн"
есть статус "Выполнен" или в "Обработка"
Замените у себя этот участок кода, и какой статус будет приходить тогда:
Вот такой статус должен быть в админке.
И тогда он никак не может передаваться, как "оплачен онлайн" - ХОТЯ еще раз - WOO нет понятия статус как "оплачен онлайн".
Статус сейчас возвращает в процессе. Спасибо вам!