Liigu sisu juurde
🛒 Topelt tellimused WooCommerce'is: 3 skripti blokeerimiseks ostukorvi tasandil

🛒 Topelt tellimused WooCommerce'is: 3 skripti blokeerimiseks ostukorvi tasandil

Klient klõpsas nuppu „Esita tellimus" kaks korda ja nüüd on administraatori paneelis kaks identset tellimust, mille vahe on vaid paar sekundit. Raha võeti maha kaks korda, klient on raevunud ja sina tegeled tagasimaksega.

Topelttellimused ei ole hüpoteetiline olukord. Ligikaudu iga kolmas pood platvormil WooCommerce puutub nendega kokku, eriti ebastabiilse majutuse või aeglaste makseväravate puhul. Kuid isegi kiirel serveril saab kasutaja toote URL-i kaudu uuesti ostukorvi lisada või osta tasuta digitaalset toodet kümneid kordi.

Oleme kokku pannud kolm töötavat skripti, mis katavad erinevaid dubleerimise stsenaariume: alates ühe kaupa müügi sundimisest kuni korduva URL-i kaudu lisamise blokeerimiseni. Allpool on täielik ülevaade koos koodiga.

Miks tellimused WooCommerce'is dubleeritakse

💡 Kiirülevaade:

  • Saad teada, miks tellimused dubleeritakse ostukorvi, URL-i ja korduva ostmise tasandil
  • Paigaldad skripti, et sundida ühe kaupa müüki meta-väljade kaudu
  • Väldid tasuta variatsioonide (digitaalsed kaubad, kupongid) korduvat ostmist
  • Kõrvaldad URL-i kaudu dubleerimise add-to-cart parameetriga lehe värskendamisel
  • Testid kaitset ja õpid, mis veel võib serveri tasandil dubleerimist põhjustada

Tellimuste dubleerimine tuleneb kolmest peamisest stsenaariumist.

Esiteks, kasutaja klõpsab mitu korda nuppu „Esita tellimus". See juhtub, kui leht hangub ja inimene ei näe vastust ning klõpsab nuppu uuesti. Aeglase majutuse puhul tavaline lugu.

Teine stsenaarium, tasuta tooted. Kui sul on tasuta digitaalne toode, ei takista miski ühel kasutajal seda kümme korda järjest „ostmast". WooCommerce ei jälgi vaikimisi, kas see klient on sama tasuta toote juba varem võtnud.

Kolmandaks, otselink parameetriga ?add-to-cart=123. Värskendasid ostukorvi lehte, toode lisati uuesti. Järgisid uudiskirja linki kaks korda, ostukorvis on kaks eksemplari.

Kõik kolm stsenaariumi lahendatakse serveri poolel WooCommerce'i konksude abil. Mitte ühtegi pistikprogrammi, ainult kood.

1. Meetod: ühe kaupa müügi sundimine meta-väljade kaudu

Esimene skript sunnib WooCommerce'i käsitlema konkreetset toodet kui „müüakse eraldi", isegi kui see märkeruut pole toote seadetes märgitud. Juhtimine toimub meta-välja kaudu.

Kui meta-välja maximum_allowed_quantity väärtus on 1, tagastab woocommerce_is_sold_individually filter true ja WooCommerce ise blokeerib teise ühiku ostukorvi lisamise. Töötab nii lihtoodete kui ka variatsioonide puhul.

Lisa kood oma alamteema faili functions.php või Code Snippets pistikprogrammi kaudu:

1function sd_woocommerce_is_sold_individually( $return, $product ) {
2 switch ( $product->get_type() ) {
3 case 'variation':
4 if ( $product->get_meta( 'variation_maximum_allowed_quantity' ) == 1 ) {
5 return true;
6 }
7 break;
8 case 'simple':
9 if ( $product->get_meta( 'maximum_allowed_quantity' ) == 1 ) {
10 return true;
11 }
12 break;
13 }
14 return $return;
15}
16add_filter( 'woocommerce_is_sold_individually', 'sd_woocommerce_is_sold_individually', 10, 2 );

Mis siin toimub: woocommerce_is_sold_individually konks käivitub iga kord, kui WooCommerce kontrollib, kas toodet saab ostukorvi lisada rohkem kui ühe korra. Funktsioon vaatab toote meta-väljadesse ja kui näeb maximum_allowed_quantity = 1, lubab sunniviisiliselt režiimi „Müüakse eraldi". Variatsioonide puhul on välja nimi variation_maximum_allowed_quantity.

Kuidas rakendada. Mine ükskõik millise toote või variatsiooni muutmise juurde, lisa kohandatud väli nimega maximum_allowed_quantity (või variatsiooni puhul variation_maximum_allowed_quantity) ja väärtusega 1. Salvesta. Kõik, nüüd ei saa seda toodet kaks korda ostukorvi panna.

2. Meetod: tasuta variatsioonide korduva ostmise vältimine

Tasuta digitaalsed tooted on peamine lünk topelttellimuste kaitses. Kasutaja on sisse logitud, toote hind on null, WooCommerce laseb tellimuse küsimusteta läbi. Kümme sellist tellimust ühelt kliendilt, kümme identset kirjet administraatori paneelis.

Allolev skript kontrollib funktsiooni wc_customer_bought_product() abil, kas see kasutaja on sama toote juba varem ostnud. Kui jah, blokeeritakse ostukorvi lisamine selge teatega.

1function sd_disable_repeat_purchase_for_free_products( $passed, $product_id, $quantity, $variation_id = 0 ) {
2 $current_user = wp_get_current_user();
3 $product = $variation_id > 0 ? wc_get_product( $variation_id ) : wc_get_product( $product_id );
4 $target_id = $variation_id > 0 ? $variation_id : $product_id;
5
6 if ( floatval( $product->get_price() ) == 0 ) {
7 if ( wc_customer_bought_product( $current_user->user_email, $current_user->ID, $target_id ) ) {
8 wc_add_notice(
9 sprintf( __( 'You have already purchased "%s" and cannot purchase it again.', 'sd' ), $product->get_name() ),
10 'error'
11 );
12 return false;
13 }
14 }
15 return $passed;
16}
17add_filter( 'woocommerce_add_to_cart_validation', 'sd_disable_repeat_purchase_for_free_products', 10, 4 );

Pärast paigaldamist näeb kasutaja veateadet, kui ta üritab juba ostetud tasuta toodet ostukorvi lisada. Tellimust ennast ei looda.

Kaks olulist tingimust. Esiteks, klient peab olema sisse logitud. Külaliste puhul tagastab wp_get_current_user() tühja objekti ja kontroll ei tööta. Teiseks, toote hind peab olema täpselt null (floatval välistab vormindusprobleemid). Skript ei puuduta tooteid, mille hind on üle nulli.

3. Meetod: kaitse URL-i kaudu dubleerimise vastu add-to-cart abil

WooCommerce võimaldab toote ostukorvi lisada otselingi kaudu: /cart/?add-to-cart=123. Mugav turunduseks, kuid kui kasutaja värskendab lehte või järgib linki uuesti, lisatakse toode uuesti.

See skript püüab kinni ostukorvi või kassa lehe laadimise ja kui URL-i parameetrist pärit toode on juba ostukorvis, eemaldab vaikselt päringu parameetrid ja suunab ümber puhtale URL-ile.

1function sd_prevent_duplicate_add_to_cart_redirect() {
2 if ( ( is_cart() || is_checkout() ) && isset( $_GET['add-to-cart'] ) ) {
3 $current_url = home_url( add_query_arg( null, null ) );
4 $product_id = intval( $_GET['add-to-cart'] );
5 $variation_id = isset( $_GET['variation_id'] ) ? intval( $_GET['variation_id'] ) : 0;
6
7 foreach ( WC()->cart->get_cart() as $cart_item ) {
8 if ( $cart_item['product_id'] == $product_id
9 && ( $variation_id == 0 || $cart_item['variation_id'] == $variation_id ) ) {
10 wp_redirect( remove_query_arg( array( 'add-to-cart', 'variation_id' ), $current_url ) );
11 exit;
12 }
13 }
14 }
15}
16add_action( 'template_redirect', 'sd_prevent_duplicate_add_to_cart_redirect' );

template_redirect konks käivitub enne, kui WordPress alustab lehe renderdamist. Skript kontrollib, kas add-to-cart parameeter on URL-is, otsib seda toodet ostukorvi sisust (WC()->cart->get_cart()) ja kui see leitakse, teeb wp_redirect samale lehele ilma päringu parameetriteta.

Korduv lisamine URL-i kaudu on kõrvaldatud. Samal ajal töötab esimene lisamine (kui toodet pole veel ostukorvis) nagu tavaliselt.

Kõige kokku panemine

Kõik kolm skripti ei ole vastuolus ja töötavad iseseisvalt:

  • Esimene piirab ühe toote koguse ühele, kaitse mitmekordse lisamise vastu.
  • Teine blokeerib tasuta toodete korduva ostmise, kaitse tasuta toodete „klõpsuspämmimise" vastu.
  • Kolmas kõrvaldab URL-i kaudu dubleerimise, kaitse juhusliku korduva lisamise vastu.

Lisa kood Code Snippets WP.org-is pistikprogrammi kaudu, mitte otse teema functions.php faili. Pistikprogramm võimaldab koodijuppe ükshaaval lubada ja keelata, ilma et sait vea korral katki läheks, ega kaota koodi teema vahetamisel. Loo kolm eraldi koodijuppi, nii on lihtsam siluda.

Mida veel kontrollida, kui dubleerimine jätkub

Ülaltoodud skriptid katavad dubleerimise ostukorvi ja kassa tasandil. Kuid on veel kaks probleemi allikat, mida kood ei paranda.

Ostukorvi ja kassa lehtede vahemällu salvestamine. Vahemälu pistikprogrammid nagu WP Rocket või LiteSpeed Cache välistavad need lehed vaikimisi, kuid pärast seadete uuendamist võib välistus lähtestuda. Kontrolli: ostukorvi, kassa ja minu konto lehti ei tohi vahemällu salvestada ei pistikprogrammi, serveri ega CDN-i tasandil.

Maksevärava korduskatsed. Kui maksevärav (Stripe, PayPal) ei saa serverilt õigeaegselt kinnitust, saadab see teate uuesti ja WooCommerce loob teise tellimuse. Põhjuseks on tavaliselt aeglane majutus või tulemüür, mis blokeerib tagasihelistamise päringuid. Lahendus: kontrolli maksevärava logisid korduvate veebihaagi saatmiste suhtes ja veendu, et tagasihelistamise URL on väljastpoolt ligipääsetav.

Kuidas kaitset testida

Pärast skriptide paigaldamist testi kindlasti iga stsenaariumi testsaidil.

  1. meetod, loo toode meta-väljaga maximum_allowed_quantity = 1 ja proovi lisada kaks ühikut ostukorvi. Lisada peaks saama ainult ühe.

  2. meetod, logi sisse, osta tasuta toode, seejärel proovi seda uuesti osta. Peaksid nägema veateadet.

  3. meetod, lisa toode ostukorvi otselingiga ?add-to-cart=ID, seejärel värskenda lehte. Toodete arv ostukorvis ei tohiks muutuda.

Testi eraldi installatsioonis või staadiumisaidil. Reaalses poes alles pärast täielikku kontrolli.

⁉️🤔 Korduma kippuvad küsimused

Miks tellimused dubleeritakse, kui nuppu „Esita tellimus" klõpsati ühe korra?

Põhjus on peaaegu alati aeglane serveri vastus. Kasutaja klõpsab nuppu, päring läheb välja, kuid leht ei värskendu mitu sekundit. Inimene arvab, et ei klõpsanud, ja klõpsab uuesti. Mõlemad päringud jõuavad WooCommerce'ini ja luuakse kaks tellimust. Selle artikli skriptid seda olukorda ei taba; siin aitab kliendipoolne vahemällu salvestamine (nupu keelamine pärast klõpsu) või serveripoolne tellimuse kordumatuse kontroll nonce-tõendi abil.

Kas maksevärav võib ise dubleerida?

Jah. Kui maksevärav ei saa teie serverilt IPN-i/veebihaagi vastuseks HTTP 200, kordab see saatmist. Igal korduskatsel võib WooCommerce luua uue tellimuse. Probleem lahendatakse majutuse kiirendamisega ja kontrollides, et maksevärava tagasihelistamise URL ei oleks tulemüüriga blokeeritud ega nõuaks HTTP-autentimist.

Kas see kaitse blokeerib kliendi tõelised korduvtellimused?

Ei. Skriptid töötavad ostukorvi lisamise etapis, mitte tellimuse loomise etapis. Kui klient esitas teadlikult ühe tellimuse ja nädal hiljem teise, siis skriptid ei sega. Erand: 2. meetod, mis keelab sama kasutaja poolt tasuta toote korduva ostmise.

Kas Code Snippets'i kasutamine on kohustuslik või võib koodi panna faili functions.php?

Võid kasutada faili functions.php, kuid soovitame Code Snippets'i. Kirjavea korral functions.php koodis saad valge ekraani ja ligipääsu ainult FTP kaudu. Code Snippets'i pistikprogramm püüab saatuslikud vead kinni ja keelab probleemse koodijupi automaatselt, sait jääb püsti.

Kas topelttellimuste vältimise pistikprogrammid aitavad?

Spetsiaalsed pistikprogrammid nagu WooCommerce Duplicate Order Blocker töötavad teisel tasandil; nad jälgivad dublikaate IP, e-posti või brauseri sõrmejälje järgi kassa etapis. See katab topeltklõpsu stsenaariumi, mida meie skriptid ei kata. Kuid pistikprogrammid ei lahenda URL-i add-to-cart kaudu dubleerimise ja tasuta toote korduva ostmise probleemi. Ideaalne variant: selle artikli skriptid pluss blokeerimise pistikprogramm kassas.

Kokkuvõte: kolm topelttellimuste kaitse taset

Kolm skripti katavad kolm konkreetset tellimuste dubleerimise stsenaariumi. Paigalda need kõik korraga; igaüks vastutab oma valdkonna eest ja koos pakuvad nad tugevat kaitset ostukorvi tasandil.

Kui pärast paigaldamist ilmub endiselt dublikaate, vaata majutuse ja maksevärava poole. Topeltklõpsu nupule „Esita tellimus" ei saa ravida koodiga ostukorvi tasandil; siin on vaja kas blokeerimise pistikprogrammi või kohandatud nupu kaitset JavaScripti abil.

Testi kaitset testsaidil, seejärel vii tootmisse. Viisteist minutit kolme koodijupi paigaldamiseks säästab tunde tagasimaksete lahendamisest.