[wooCommerce] Usuwanie metod płatności dla płatności przy odbiorze

Konfi­gu­ra­cja wooCom­mer­ce pozwa­la określić dla jakich metod wysył­ki możemy wybrać opcję za pobra­niem, ale nie ma możli­wo­ści zablo­ko­wa­nia wtedy innych kanałów płatno­ści. Może to wywołać u klien­ta konster­na­cję lub spowo­do­wać błąd, taki że klient wybie­rze droższą opcję za pobra­niem a i tak zapła­ci z góry.

Gotowe wtyczki

Znala­złem wtycz­kę, która w darmo­wej wersji robi różne cuda w koszy­ku. Disable payment method /​ COD fees /​ Advan­ce COD or Partial payment for Order for WooCom­mer­ce potra­fi wyłączyć metody płatno­ści dla wybra­ne­go towaru, dla kodu poczto­we­go, ale mimo iż wpisy­wa­łem nazwę metody płatno­ści na wszyst­kie sposo­by, to tego nie umiał. Nie było też w dokumen­ta­cji opisu tego filtru, więc odpuści­łem sobie…

Własne rozwiązanie

Misha Rudra­styh na swoim blogu pokazał rozwią­za­nie usuwa­ją­ce możli­wość wyboru metody za pobra­niem jeżeli wskaże­my odpowied­ni sposób wysył­ki. Reali­zu­je się to za pomocą filtru 'woocommerce_​available_​payment_​gateways' To odwrot­na logika, do moich potrzeb, więc trzeba ją odwró­cić. Na począ­tek kod autor­stwa Mishy:

add_filter( 'woocommerce_available_payment_gateways', 'rudr_payment_method_by_shipping' );

function rudr_payment_method_by_shipping( $gateways ) {
    
    if( is_admin() ) { // do nothing in /wp-admin
        return $gateways;
    }
    
    if( is_wc_endpoint_url( 'order-pay' ) ) { // "Pay for order" page
        
        $order = wc_get_order( wc_get_order_id_by_order_key( $_GET[ 'key' ] ) );
        if( $order->has_shipping_method( 'local_pickup' ) ) {
            if( isset( $gateways[ 'cod' ] ) ) {
                unset( $gateways[ 'cod' ] ); // unset cash on delivery if exists
            }
        }
        
    } else { // Cart/Checkout page
        
        // get a shipping method selected by a customer
        $chosen_shipping_method = WC()->session->get( 'chosen_shipping_methods' )[0];

        // check the shipping method
        if ( 'local_pickup:4' === $chosen_shipping_method ) {
            if( isset( $gateways[ 'cod' ] ) ) {
                unset( $gateways[ 'cod' ] );
            }
        }
        
    }
    
    return $gateways;

}

Intere­su­je nas opcja else warun­ku od linii 18. Do zmien­nej $chosen_​shipping_​method przypi­sa­ny jest wybór metody wysył­ki. Potem jest spraw­dze­nie, czy to ten dla które­go nie wystę­pu­je pobra­nie. Jeżeli tak, to ta metoda wysył­ki znika w linii 26. Po zmianie parame­trów zamówie­nia wooCom­mer­ce spraw­dza wszyst­ko jeszcze raz, więc jeżeli zmieni­my wysył­kę na inną, to za pobra­niem wróci.

Plusy ujemne

Po pierw­sze mi zależa­ło na tym, by po wyborze metody wysył­ki z opcją za pobra­niem znika­ły inne metody płatno­ści. Tutaj znika za pobra­niem. Po drugie, autor podał nazwę metody na sztyw­no i to w specy­ficz­ny sposób: 'local_pickup:4'. Czyli jest to nazwa z id metody. Skąd to wziąć? Trzeba zajrzeć do konso­li i przeko­pio­wać. Czyli zakła­da­my, że właści­ciel sklepu zna się na kodowa­niu? Nie możemy! Znala­złem rozwią­za­nie bardziej uniwer­sal­ne i intuicyjne.

add_filter('woocommerce_available_payment_gateways', 'wdax_payment_method_by_shipping');

if (!function_exists('wdax_payment_method_by_shipping')) {
    function wdax_payment_method_by_shipping($gateways)
    {

        if (is_admin()) { // do nothing in /wp-admin
            return $gateways;
        }

        if (is_wc_endpoint_url('order-pay')) { // "Pay for order" page

            $order = wc_get_order(wc_get_order_id_by_order_key($_GET['key']));
            if ($order->has_shipping_method('local_pickup')) {
                if (isset($gateways['cod'])) {
                    unset($gateways['cod']); // unset cash on delivery if exists
                }
            }
        } else { // Cart/Checkout page

            // get a shipping method selected by a customer
            $chosen_shipping_method = WC()->session->get('chosen_shipping_methods')[0];

            // get a shipping method for order
            $shipping = WC()->session->get('shipping_for_package_0');

            foreach ($shipping["rates"] as $shipping_id => $shipping_method) {
                // check the shipping method
                if ($shipping_id === $chosen_shipping_method && (stristr($shipping_method->meta_data["_fs_method"]["method_description"], '(cod)') !== false)) {
                    foreach ($gateways as $gateway => $val) {
                        if ($gateway !== 'cod')
                            unset($gateways[$gateway]);
                    }
                }
            }
        }

        return $gateways;
    }
}

Intere­su­je nas kod między linia­mi 22 a 35. Przede wszyst­kim musimy znać metody wysył­ki. Pobie­ra­my je w linii 25 do zmien­nej $shipping. Przypi­sy­wa­na jest tabli­ca, której klucza­mi są poszu­ki­wa­ne wcześniej ręcznie nazwy metod wysył­ki. Teraz należy w pętli spraw­dzić czy mamy do czynie­nia z wybra­nym warian­tem czy nie.

Za pobraniem – Cash on delivery

Woocom­mer­ce nie daje nam możli­wo­ści określe­nie metody wysył­ki jako 'za pobra­niem'. Ja korzy­stam z syste­mu Apacz​ka​.pl, a ich wtycz­ka wymaga insta­la­cji dodat­ku Flexi­ble Shipping. Jest tam pole na opis metody, np. "InPost za pobra­niem". Jeżeli dodamy gdzieś hasło "(cod)", to można w ten sposób oznaczyć metodę i łatwo ją rozpo­znać, tak jak w linii 29. Zasto­so­wa­łem funkcję stristr by nie robić proble­mu z wielko­ścią znaków. Jeżeli listo­wa­na metoda jest metodą wskaza­ną przez klien­ta sklepu i opisa­ną jako 'za pobra­niem' przez właści­cie­la, to nastę­pu­je kolej­na pętla w linii 30. Listo­wa­ne są bramki płatno­ści i jeżeli id bramki nie równa się 'cod', to metoda jest usuwa­na. Na końcu zosta­je tylko opcja za pobra­niem. I tak samo jak poprzed­nio, jakakol­wiek zmiana parame­trów powodu­je reset i ponow­ne spraw­dza­nie wymogów.

Nie jest to może ideal­na metoda, bo wymaga odpowied­niej wtycz­ki, ale Flexi­ble Shipping jest bardzo popular­nym, wręcz powszech­nym rozwią­za­niem. Jeżeli ktoś chciał­by rozbu­do­wać moje rozwią­za­nie o inne warian­ty, to wystar­czy spraw­dzić parame­try zapisa­ne w zmien­nej $shipping i popra­wić warunek z linii 29.

Gdzie to umieścić?

Ja swoje rozwią­za­nie załączy­łem do folde­ru mu-plugins. Można też zrobić sobie osobną wtycz­kę albo wkleić kod do function.php szablo­nu, ale pierw­sze rozwią­za­nie jest chyba strza­łem z armaty do wróbli, a drugie, o ile nie korzy­sta­my z szablo­nu dziec­ka, może zniknąć przy następ­nej aktualizacji.

Dodaj komentarz

This site uses Akismet to reduce spam. Learn how your comment data is processed.