Płatności cykliczne

Płatności cykliczne to po prostu ponowne obciążenia karty (resale) wykonywane w określonych odstępach czasowych. Możesz wykonywać je według schematu określanego przez Twój model biznesowy.

Resale nie wymaga kompletu informacji o karcie i kliencie. Dlatego właśnie potrzebna jest najpierw przynajmniej jedna płatność lub autoryzacja karty.

Oznacza to, że możemy wyróżnić dwa rodzaje płatności cyklicznych:

Płatności cykliczne bazujące na wcześniejszych transakcjach

Zacznij od przygotowania informacji potrzebnych do zrealizowania ponownego obciążenia karty. W tym celu musisz najpierw pozyskać numer ID wcześniejszej transakcji, który jednoznacznie określa daną płatność w systemie PayLane. Możesz łatwo odczytać ten numer podczas przeprowadzania transakcji, na przykład:

1
2
$status = $client->cardSale($card_params);
$id_first_sale = $status['id_sale'];
1
2
status = client.card_sale(card_params)
id_first_sale = status['id_sale']
1
2
status = client.card_sale(card_params)
id_first_sale = status['id_sale']
1
2
3
4
5
6
api.cardSale(sale, customer, card, new Callback<CardSaleResult>() {
    @Override
    public void onFinish(CardSaleResult result) {
        long idFirstSale = result.getIdSale();
    }
});
Na stronie Pojedyncza transakcja znajdziesz więcej informacji na temat dokonywania pojedynczej płatności.

Wprawdzie możesz odwołać się do dowolnej wcześniejszej transakcji dokonanej daną kartą, to jednak zalecamy odnoszenie się do ostatniej płatności. Takie podejście ma wiele zalet, pozwala m.in. na łatwe śledzenie przepływu płatności.

Zazwyczaj sprzedawcy przechowują takie numery ID w swoich bazach danych. W ten sposób nie muszą przechowywać żadnych wrażliwych danych, a jednocześnie mają możliwość bezpośredniego odwołania się do wybranej transakcji.

Gdy posiadasz już numer ID (np. pobrany z bazy danych), możesz przygotować dane potrzebne do obciążenia karty i wywołać metodę resaleBySale.

Możesz sprawdzić czy płatność została wykonana prawidłowo wywołując metodę isSuccess. Pozyskanie numeru ID transakcji (lub danych o błędzie, jeśli operacja się nie powiodła) jest również bardzo proste i może wyglądać jak na poniższym przykładzie.

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
$resale_params = array(
    'id_sale'     => $id_first_sale,
    'amount'      => 99.99,
    'currency'    => 'EUR',
    'description' => 'Recurring billing product #1',
);

// perform the resale:
try {
    $status = $client->resaleBySale($resale_params);
} catch (Exception $e) {
    // handle exceptions here
}

// checking transaction status example (optional):
if ($client->isSuccess()) {
    echo "Success, second id_sale: {$status['id_sale']} \n";
} else {
    die("Error ID: {$status['error']['id_error']}, \n".
        "Error number: {$status['error']['error_number']}, \n".
        "Error description: {$status['error']['error_description']}");
}
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
resale_params = {
    'id_sale'     => id_first_sale,
    'amount'      => 99.99,
    'currency'    => 'EUR',
    'description' => 'Recurring billing product #1'
}

# perform the resale:
begin
    status = client.resale_by_sale(resale_params)
rescue PayLane::ClientError => e
    # handle exceptions here
end

# checking transaction status example (optional):
if client.success?
    puts "Success, id_second_sale: #{status["id_sale"]}"
else
    puts "Error ID: #{status["error"]["id_error"]}, \n"\
         "Error number: #{status["error"]["error_number"]}, \n"\
         "Error description: #{status["error"]["error_description"]}"
    exit
end
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
resale_params = {
  'id_sale'     : id_first_sale,
  'amount'      : 99.99,
  'currency'    : 'EUR',
  'description' : 'Recurring billing product #1'
}

# perform the resale:
try:
    status = client.resale_by_sale(resale_params)
except Exception, e:
    # handle exceptions here

# checking transaction status example (optional):
if client.is_success():
    print 'Success, second id_sale: %s' % status['id_sale']
else:
    sys.exit('Error ID: ' + str(status["error"]["id_error"]) + '\n' \
             'Error number: ' + str(status["error"]["error_number"]) + '\n' \
             'Error description: ' + str(status["error"]["error_description"]))
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
api.resaleSale(
    idFirstSale,
    99.99,
    "EUR",
    "Recurring billing product #1",
    new Callback<FraudSaleResult>() {
        @Override
        public void onFinish(FraudSaleResult result) {
            // success
        }

        @HandleException
        public void onProtocolError(ProtocolException e) {
            // invoke if not success
            // e.getCode() - error code
            // e.getMessage() - error message
        }

        @Override
        public void onError(Exception e) {
            // connection error etc.
        }
    }
);

Płatności cykliczne są po prostu ponownymi obciążeniami karty. Od Ciebie zależy, czy będą to odstępy tygodniowe, miesięczne, roczne czy inne; podobnie możesz obciążyć kartę np. dopiero, gdy klient osiągnie określoną kwotę do spłaty.

Płatności cykliczne bazujące na autoryzacji karty

Jeśli klient nie dokonał jeszcze żadnego zakupu (a więc nie było ani jednej płatności), nadal możesz rozpocząć płatności cykliczne. Klient musi tylko podać potrzebne dane karty.

Możesz zebrać wymagane informacje w różnych sytuacjach, np.:

  • kiedy klient zakłada konto w Twoim e-sklepie,
  • gdy klient zapisuje się na bezpłatny okres testowy Twojej usługi.

Gdy zbierzesz te dane, wykonaj autoryzację karty i zapisz jej numer ID.

Wróćmy do płatności cyklicznych. Zakładając, że dysponujesz już numerem ID autoryzacji karty klienta, możesz przygotować dane potrzebne do pobrania środków, czyli wykonania resale’a (a więc wywołania metody resaleByAuthorization).

Podobnie jak w przypadku płatności bazujących na wcześniejszych transakcjach, tak i tu możesz sprawdzić, czy płatność cykliczna się powiodła, wywołując metodę isSuccess. Możesz także odczytać numer ID transakcji lub dane o błędzie, w razie niepowodzenia operacji.

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
$resale_params = array(
    'id_authorization' => $id_authorization,
    'amount'           => 99.99,
    'currency'         => 'EUR',
    'description'      => 'Recurring billing for product #1',
);

// perform the resale:
try {
    $status = $client->resaleByAuthorization($resale_params);
} catch (Exception $e) {
    // handle exceptions here
}

// checking transaction status example (optional):
if ($client->isSuccess()) {
    echo "Success, id_sale: {$status['id_sale']} \n";
} else {
    die("Error ID: {$status['error']['id_error']}, \n".
        "Error number: {$status['error']['error_number']}, \n".
        "Error description: {$status['error']['error_description']}");
}
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
resale_params = {
    'id_authorization' => id_authorization,
    'amount'           => 99.99,
    'currency'         => 'EUR',
    'description'      => 'Recurring billing for product #1'
}

# perform the resale:
begin
    status = client.resale_by_authorization(resale_params)
rescue PayLane::ClientError => e
    # handle exceptions here
end

# checking transaction status example (optional):
if client.success?
    puts "Success, id_sale: #{status["id_sale"]}"
else
    puts "Error ID: #{status["error"]["id_error"]}, \n"\
         "Error number: #{status["error"]["error_number"]}, \n"\
         "Error description: #{status["error"]["error_description"]}"
    exit
end
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
resale_params = {
  'id_authorization' : id_authorization,
  'amount'           : 99.99,
  'currency'         : 'EUR',
  'description'      : 'Recurring billing product #1'
}

# perform the resale:
try:
    status = client.resale_by_authorization(resale_params)
except Exception, e:
    # handle exceptions here

# checking transaction status example (optional):
if client.is_success():
    print 'Success, id_sale: %s' % status['id_sale']
else:
    sys.exit('Error ID: ' + str(status["error"]["id_error"]) + '\n' \
             'Error number: ' + str(status["error"]["error_number"]) + '\n' \
             'Error description: ' + str(status["error"]["error_description"]))
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
api.resaleAuthorization(
    idFirstSale,
    99.99,
    "EUR",
    "Recurring billing product #1",
    new Callback<FraudSaleResult>() {

        @Override
        public void onFinish(FraudSaleResult result) {
            // success
        }

        @HandleException
        public void onProtocolError(ProtocolException e) {
            // invoke if not success
            // e.getCode() - error code
            // e.getMessage() - error message
        }

        @Override
        public void onError(Exception e) {
            // connection error etc.
        }
    }
);