Rekurencyjne obciążanie kart płatniczych jest wygodnym rozwiązaniem dla klienta i sprzedawcy

Ten tutorial pozwoli zarówno zrozumieć mechanizm działania tego rodzaju płatności jak i pomoże w poprawnym wdrożeniu ich na własnej stronie. Płatności rekurencyjne mogą być wykorzystywane do opłat subskrypcyjnych lub na żądanie, bez potrzeby ponownego wprowadzania danych karty.

Wymagania

  1. Konto sprzedawcy w systemie Tpay.com - zarejestruj
  2. Włączona obsługa kart kredytowych (za pośrednictwem Elavon oraz Banku Pekao S.A.)

Mechanizm płatności zapamiętaną kartą

Umożliwienie rozpoczęcia pobierania opłat bez konieczności wprowadzania danych, wymaga uprzedniego zapisania karty, poprzez wykonanie jednorazowej płatności na dowolną kwotę. W artykule "wdrożenie bramki płatności kartami na stronie sklepu" opisaliśmy sposób implementacji bramki kartowej, służącej do procesowania pierwszego obciążenia karty.

Posiadając zapisany token karty płatniczej, można wykonać próbę jej kolejnego obciążenia w wielu sytuacjach np:

  • Udostępniając możliwość płatności zapisaną kartą (sklepy internetowe)
  • Przed lub po wykonaniu usługi
  • Przed udostępnieniem treści multimedialnych
  • Po upływie okresu opłaconej subskrypcji

Mechanizm działania jest bardzo prosty i nie wymaga większego nakładu pracy.

  1. Za każdym razem gdy pojawia się potrzeba obciążenia karty klienta, wystarczy wygenerować transakcję w określonej walucie i kwocie, a następnie spróbować ją wyegzekwować.
  2. Jeżeli klient posiada wystarczającą ilość środków finansowych oraz ograniczenia transakcji online pozwalają na poprawne przeprowadzenie obciążenia, to cały proces przebiega w ciągu sekund.
  3. W przypadku niepowodzenia, nasz system zwraca odpowiednią informację, którą można przekazać do klienta i/lub ponowić próbę opłacenia transakcji w późniejszym terminie.
  4. Informacje o udanym obciążeniu zwracane przez system Tpay są wiążące i można na ich podstawie uznać, że środki zostaną poprawnie przekazane na konto sprzedawcy.
  5. W chwili obecnej nie ma możliwości preautoryzacji środków na karcie. Można jedynie pobrać oczekiwaną kwotę, a następnie zwrócić ewentualną różnicę.

Techniczne wyjaśnienie płatności rekurencyjnych

  1. Wykonanie transakcji zapisaną kartą wymaga wcześniejszego wykonania metody secure sale, której implementacja została opisana w artykule "wdrożenie bramki płatności kartami na stronie sklepu" lub metody register sale.
  2. Posiadając token (parametr "cli_auth"), będący losowym ciągiem znaków reprezentującym powiązanie karty płatniczej z kontem sprzedawcy w systemie Tpay, należy przygotować transakcję.
  3. Nieopłaconą transakcję należy wygenerować korzystając z metody presale. W przypadku późniejszego niepowodzenia płatności, nie ma potrzeby generowania kolejnych jeśli dane zamówienia nie ulegną zmianie.
    Przykład parametrów presale:
    {
      "desc": "payment for order xyz",
      "cli_auth": "t59c2810d59285e3e0ee9d1f1eda1c2f4c554e24",
      "amount": 10.99,
      "api_password": "XtCns9OAue8zSFJ",
      "sign": "1355b3d2584af8a1fa44573171d25b316ef16b4f",
      "currency": 985,
      "order_id": 32145,
      "language": "pl"
    }​
  4. Wygenerowany tą metodą identyfikator transakcji (parametr "sale_auth" w odpowiedzi) należy przekazać do metody sale, którą wykonywana jest próba egzekucji obciążenia:
    {
      "cli_auth": "t59c2810d59285e3e0ee9d1f1eda1c2f4c554e24",
      "sale_auth": "t59c28295aeb071b0cf6471b24f727f6456998de",
      "api_password": "XtCns9OAue8zSFJ",
      "sign": "231f533d91cf3ec6ce5d02d672beb4b127e1e987"
    }​
  5. Informacje zwrócone w odpowiedzi są jednoznaczne z udanym pobraniem środków lub niepowodzeniem. W przypadku niepowodzenia zwrócony zostanie parametr "reason", zawierający kod odrzucenia, który można porównać z danymi tej tabeli i przekazać klientowi (na przykład gdy limit kwoty płatności jest zbyt niski).
  6. Można wykonywać kolejne próby obciążenia w późniejszych terminach ponawiając metodę sale dla tego samego identyfikatora transakcji.
  7. Tpay.com udostępnia gotowe biblioteki PHP, w których wykonanie płatności za pomocą tokenu jest banalnie proste! Sprawdź przykład płatności rekurencyjnej w serwisie github.com.

Przykład wdrożenia w oparciu o biblioteki PHP Tpay

W tutorialu Przykład wdrożenia bramki kartowej w oparciu o biblioteki PHP Tpay opisaliśmy stworzenie dwóch klas, które odpowiadają za wykonanie pierwszej płatności kartą oraz odebranie powiadomienia o takiej transakcji. Rozpoczynając integrację płatności rekurencyjnych zakładamy, że w bazie danych sklepu dany użytkownik ma już przypisany minimum jeden token karty płatniczej, którą się posługuje.

  1. Pobierz biblioteki Tpay z serwisu Github.com
  2. Stwórz plik RecurrentPayment.php (np. w folderze examples) rozszerzający klasę PaymentCard, w którego konstruktorze podaj swoje dane dostępowe do API kart płatniczych:
    <?php
    
    namespace tpayLibs\examples;
    
    use tpayLibs\src\_class_tpay\PaymentCard;
    
    include_once 'config.php';
    include_once 'loader.php';
    
    class RecurrentPayment extends PaymentCard
    {
        private $transactionId = null;
    
        public function __construct()
        {
            $this->cardApiKey = 'bda5eda723bf1ae71a82e90a249803d3f852248d';
            $this->cardApiPass = 'IhZVgraNcZoWPLgA';
            $this->cardKeyRSA = 'LS0tLS1CRUdJTiBQVUJMSUMgS0VZLS0tLS0NCk1JR2ZNQTBHQ1NxR1NJYjNEUUVCQVFVQUE0R05BRENCaVFLQmdRQ2NLRTVZNU1Wemd5a1Z5ODNMS1NTTFlEMEVrU2xadTRVZm1STS8NCmM5L0NtMENuVDM2ekU0L2dMRzBSYzQwODRHNmIzU3l5NVpvZ1kwQXFOVU5vUEptUUZGVyswdXJacU8yNFRCQkxCcU10TTVYSllDaVQNCmVpNkx3RUIyNnpPOFZocW9SK0tiRS92K1l1YlFhNGQ0cWtHU0IzeHBhSUJncllrT2o0aFJDOXk0WXdJREFRQUINCi0tLS0tRU5EIFBVQkxJQyBLRVktLS0tLQ';
            $this->cardVerificationCode = '6680181602d396e640cb091ea5418171';
            $this->cardHashAlg = 'sha1';
            parent::__construct();
        }
    
    }​
  3. Utwórz funkcję sterującą, która wprowadzi podstawowe dane transakcji oraz przygotuje nieopłaconą transakcję metodą presale. W tym miejscu zakładamy, że przekazywany będzie Token klienta pobrany z bazy danych klienta: 
    public function init(
            $saleDescription,
            $clientToken,
            $amount,
            $orderId = null,
            $currency = 985,
            $language = 'pl'
        ) {
            $this
                ->setAmount($amount)
                ->setCurrency($currency)
                ->setOrderID($orderId)
                ->setLanguage($language)
                ->setClientToken($clientToken);
            //Przygotuj nieopłaconą transakcję
            $transaction = $this->presaleMethod($saleDescription);
            $this->transactionId = $transaction['sale_auth'];
    
            return $this;
    }
  4. Utwórz funkcję, która będzie próbowała wyegzekwować obciążenie oraz własną funkcję setOrderAsConfirmed, która zaktualizuje status transakcji w Twojej bazie danych:
    public function payBySavedCreditCard()
    {
        //Spróbuj wykonać obciążenie
        //W trybie testowym ta metoda ma 50% szans powodzenia
        $result = $this->saleMethod($this->transactionId);
        if (isset($result['status']) && $result['status'] === 'correct') {
            //Obciążenie się udało, oznacz zamówienie jako opłacone
            return $this->setOrderAsConfirmed();
        } else {
            //Płatność tą kartą została odrzucona, warto zalogować przyczynę odrzucenia
            return $result['reason'];
        }
    }​
  5. Na końcu pliku, poza klasą wystarczy dodać wywołanie z parametrami wejściowymi, np. żeby pobrać 12,50 PLN z zapamiętanej karty klienta wystarczy wywołać:
    (new RecurrentPayment())
        ->init('payment for order xyz', 't5a96d292cd0a5c63a14c30adeae55cb200df087', 12.50, 'order_123456', 985, 'pl')
        ->payBySavedCreditCard();​
  6. Ten mechanizm wystarczy teraz wywoływać w momencie, kiedy należy obciążyć konto płatnika, np. abonamentem lub inną opłatą, ponieważ kwota może być różna od kwoty pierwotnej transakcji.
    • W najprostszym (niezalecanym) modelu można posłużyć się mechanizmem CRON, który wywoła nasz plik obudowany w dodatkowe potrzebne w Twoim systemie warunki (jak weryfikacja, czy konto klienta nadal jest aktywne) np. raz w miesiącu.
    • Oczywiście dla każdego obciążenia dane wejściowe funkcji init() powinny przyjąć takie wartości jakimi chcemy obciążyć konto płatnika, w tym wypadku posłużyliśmy się przykładowymi danymi.
    • Po każdym obciążeniu klient otrzymuje w powiadomieniu email od Tpay.com linka, w którym może wyrejestrować swoją kartę, uniemożliwiając pobranie kolejnej opłaty.
    • Jeżeli Twój system pobierze błędnie opłatę klientowi, a nie powinien, to po prostu zleć zwrot w Panelu Odbiorcy Płatności.