SMS z WooCommerce o statusie zamówienia: gotowy kod PHP
Sprawdzone z dokumentacją:
W WooCommerce podpinasz funkcję pod hook woocommerce_order_status_processing lub woocommerce_order_status_completed i wysyłasz wp_remote_post na https://smsportal.app/api/v1/gateway/send-sms z nagłówkiem x-api-key. Kod bierze numer z danych rozliczeniowych, dopisuje +48, zapisuje wynik w notatce zamówienia i nie wysyła tego samego SMS-a dwa razy.
Czego potrzebujesz
- WooCommerce na WordPressie z dostępem do
wp-config.php(FTP, panel hostingu). - Miejsce na kod: wtyczka Code Snippets albo
functions.phpmotywu potomnego. - Konto smsportal z podłączonym telefonem z Androidem i kartą SIM.
- Klucz API z panelu smsportal (Klucze API → Wygeneruj klucz API).
Jak wysyłać SMS o zamówieniu z WooCommerce
Zapisz klucz w wp-config.php
Dodaj nad linią
/* That's all, stop editing! */wierszdefine( 'SMSPORTAL_API_KEY', 'twoj_klucz_api' );. Klucz nie trafi do bazy, eksportu fragmentów ani repozytorium motywu.Wklej kod
W Code Snippets dodaj nowy fragment PHP i ustaw uruchamianie wszędzie. Bez wtyczki wklej kod na końcu
functions.phpmotywu potomnego (plik ma już na początku<?php). Treści szablonów są bez polskich liter, żeby zmieścić się w 160 znakach jednej części.Fragment PHP: SMS przy statusach processing i completed// SMS o zmianie statusu zamówienia przez smsportal. // Klucz API trzymaj w wp-config.php, nie tutaj: // define( 'SMSPORTAL_API_KEY', 'twoj_klucz_api' ); add_action( 'woocommerce_order_status_processing', function ( $order_id, $order ) { smsportal_order_sms( $order, 'processing', 'Zamowienie #{number} przyjete. Dziekujemy, {name}! Sklep Kowalski' ); }, 10, 2 ); add_action( 'woocommerce_order_status_completed', function ( $order_id, $order ) { smsportal_order_sms( $order, 'completed', 'Zamowienie #{number} wyslane. Sklep Kowalski' ); }, 10, 2 ); function smsportal_order_sms( $order, $status, $template ) { if ( ! defined( 'SMSPORTAL_API_KEY' ) ) { return; } $flag = '_smsportal_sms_' . $status; if ( $order->get_meta( $flag ) ) { return; // ten SMS już wyszedł, nie wysyłaj drugi raz } $phone = smsportal_normalize_phone( $order->get_billing_phone(), '48' ); if ( '' === $phone ) { $order->add_order_note( 'SMS nie wysłany: brak poprawnego numeru telefonu.' ); return; } $message = strtr( $template, array( '{number}' => $order->get_order_number(), '{name}' => $order->get_billing_first_name(), ) ); $response = wp_remote_post( 'https://smsportal.app/api/v1/gateway/send-sms', array( 'timeout' => 5, 'headers' => array( 'x-api-key' => SMSPORTAL_API_KEY, 'Content-Type' => 'application/json', ), 'body' => wp_json_encode( array( 'recipients' => array( $phone ), 'message' => $message, ) ), ) ); if ( is_wp_error( $response ) ) { $order->add_order_note( 'SMS nie wysłany: ' . $response->get_error_message() ); return; } $code = (int) wp_remote_retrieve_response_code( $response ); $body = wp_remote_retrieve_body( $response ); if ( $code < 200 || $code >= 300 ) { $order->add_order_note( sprintf( 'SMS odrzucony (HTTP %d): %s', $code, substr( $body, 0, 200 ) ) ); return; } $order->update_meta_data( $flag, current_time( 'mysql' ) ); $order->save_meta_data(); $json = json_decode( $body, true ); $batch = isset( $json['data']['smsBatchId'] ) ? ' (partia ' . $json['data']['smsBatchId'] . ')' : ''; $order->add_order_note( 'SMS w kolejce do ' . $phone . $batch . ': ' . $message ); } // 600 100 200 -> +48600100200. Numery z + albo 00 zostają bez zmian. function smsportal_normalize_phone( $raw, $country_code ) { $raw = trim( (string) $raw ); $digits = preg_replace( '/\D+/', '', $raw ); if ( '' === $digits ) { return ''; } if ( 0 === strpos( $raw, '+' ) ) { // już w formacie międzynarodowym } elseif ( 0 === strpos( $digits, '00' ) ) { $digits = substr( $digits, 2 ); } elseif ( ! ( 0 === strpos( $digits, $country_code ) && strlen( $digits ) > 9 ) ) { $digits = $country_code . ltrim( $digits, '0' ); } $length = strlen( $digits ); return ( $length >= 8 && $length <= 15 ) ? '+' . $digits : ''; }Dopasuj statusy i treści
Każdy status to osobny hook
woocommerce_order_status_<status>(nazwa bez prefiksuwc-). Dostępne zmienne:{number}i{name}. Sklep spoza Polski zmienia'48'w wywołaniusmsportal_normalize_phonena swój kierunkowy.Przetestuj na własnym numerze
Złóż zamówienie z własnym telefonem wpisanym bez
+48i zmień status w panelu. W notatkach zamówienia zobaczysz „SMS w kolejce” albo powód błędu. Ponowna zmiana na ten sam status nie wyśle drugiego SMS-a.
Gotowe scenariusze
Paczka nadana, z numerem przesyłki
Hook
woocommerce_order_status_completedwysyła „Zamówienie wysłane”. Numer przesyłki nie jest polem WooCommerce: odczytaj go przez$order->get_meta()z pola, które zapisuje Twoja wtyczka do śledzenia, i dopisz dostrtrjako{tracking}.Nieudana płatność
Dodaj trzeci hook
woocommerce_order_status_failedz treścią typu „Płatność za #{number} nie przeszła, dokończ ją w sklepie”. Link z$order->get_checkout_payment_url()jest długi, więc SMS zajmie kilka części.Zamówienie gotowe do odbioru
Status „Gotowe do odbioru” dodany wtyczką ma własny slug, np.
ready-pickup. Hook to wtedywoocommerce_order_status_ready-pickup, a treść podaje godziny otwarcia punktu.
Błędy i rozwiązania
- Notatka „SMS odrzucony (HTTP 401)”
- Przyczyna: Zły klucz albo nagłówek
Authorizationzamiastx-api-key. - Co zrobić: Sprawdź stałą
SMSPORTAL_API_KEYwwp-config.phpi wygeneruj nowy klucz, jeśli stary usunięto. - Notatka „SMS odrzucony (HTTP 400)”
- Przyczyna: Brak włączonego telefonu na koncie albo niezweryfikowany e-mail.
- Co zrobić: W panelu sprawdź, czy telefon jest podłączony i włączony, oraz potwierdź adres e-mail.
- Notatka „SMS odrzucony (HTTP 429)”
- Przyczyna: Wyczerpany limit SMS-ów w pakiecie.
- Co zrobić: Treść odpowiedzi w notatce mówi, który limit się skończył. Zmień pakiet albo poczekaj na odnowienie.
- Brak jakiejkolwiek notatki o SMS-ie
- Przyczyna: Brak stałej
SMSPORTAL_API_KEY, nieaktywny fragment kodu albo status, który nie ma hooka. - Co zrobić: Sprawdź, czy fragment jest włączony i czy stała jest zdefiniowana przed
require_once ABSPATH . 'wp-settings.php'. - Notatka „SMS w kolejce”, ale SMS nie dociera
- Przyczyna: Telefon jest offline albo Android usypia aplikację.
- Co zrobić: Sprawdź zasięg, internet i stan telefonu w panelu. Wiadomość czeka do 72 godzin, potem wygasa.
Najczęstsze pytania
Czy ten kod działa z HPOS (nowym magazynem zamówień)?
Tak. Hooki statusu odpala sam obiekt zamówienia niezależnie od magazynu, a znacznik wysyłki zapisuje `update_meta_data` i `save_meta_data`, czyli metody, które WooCommerce zaleca dla HPOS zamiast `update_post_meta`.
Czy wysyłka spowalnia składanie zamówienia?
Żądanie czeka na odpowiedź najwyżej 5 sekund, zwykle znacznie krócej. Opcja `'blocking' => false` skraca to do zera, ale wtedy kod nie zna wyniku, więc nie zapisze notatki ani znacznika przeciw duplikatom.
Czy mogę użyć webhooków WooCommerce zamiast kodu?
Tak, ale webhook z WooCommerce → Ustawienia → Zaawansowane → Webhooki wysyła własny format zamówienia, którego smsportal nie przyjmie. Potrzebny jest krok pośredni, np. n8n albo Make, który wyciągnie telefon i zbuduje treść SMS-a.
Co z odpowiedziami klientów na SMS?
Trafiają do panelu smsportal, bo klient odpisuje na Twój numer. Żeby przekazać je dalej, np. na Slacka, ustaw webhook ze zdarzeniem `MESSAGE_RECEIVED` w n8n lub Make.
Czy na SMS o zamówieniu potrzebuję zgody klienta?
Wiadomość o realizacji konkretnego zamówienia jest transakcyjna. Reklama, kupon czy promocja w SMS-ie wymaga osobnej zgody marketingowej zgodnie z Prawem komunikacji elektronicznej. Do kampanii lepszy jest dostawca z nazwą nadawcy.
Źródła
- WooCommerce: kod klasy WC_Order (hooki statusów)
- WooCommerce: HPOS recipe book (metadane zamówień)
- WooCommerce: Webhooks
- WordPress: WP_Http::request (timeout, blocking)
- Code Snippets w katalogu wtyczek WordPress
- smsportal: dokumentacja API
Więcej w poradnikach
Wyślij pierwszego SMS-a jeszcze dziś
Załóż darmowe konto, podłącz telefon i sprawdź, jak klienci reagują na wiadomości z Twojego numeru.