Customer credit check

Customer risk assessment, which determines whether the invoice will be approved or not, occurs when the customer chooses Twisto as the payment method and clicks the "Complete Order" button. This ensures that only data about users who have chosen our payment method and consented to the provision of personal information is sent to our server.

In case of a positive evaluation, the process is completed for the customer, and a thank you message for the order can be displayed. Otherwise, the customer's payment is rejected, and an alternative payment method is suggested. The entire process takes place in real-time on the Twisto server.

The Twisto.js JavaScript library, designed to be added to the shopping process, and the Twisto.php PHP library are used for the evaluation process. The description of customer evaluation integration is divided into Webhook and JavaScript, precisely based on these libraries.

Check Image

Webhook

Implementation Method

The webhook is used to send information about the customer and their orders. The customer is identified using their email, which is used to retrieve relevant information as mentioned in the Data Format section. Setting up the webhook to receive requests on your server is described in detail in the previous chapter.

Note: Data about the current order and the customer are already sent during the shopping process via the JavaScript library directly from the customer's browser. However, these data cannot be considered trustworthy, as users can intentionally modify them in the browser's source code (this does not apply to normal users). Therefore, the data is sent again in the invoice creation step.

The webhook request is a JSON document that specifies the action being performed and the customer's email:

{ "action": "check", "email": "test@example.com" }

Example of usage

<?php require_once 'twistophp/Twisto.php'; $dbh = new PDO('mysql:host=xxx;port=xxx;dbname=xxx', 'username', 'password'); $request = json_decode(file_get_contents('php://input')); if (is_object($request) && $request->action == 'check') { // získání informací o požadovaném zákazníkovi $sth = $dbh->prepare('SELECT * FROM customers WHERE email = :email'); $sth->execute(array(':email' => $request->email)); $customer = $sth->fetch(); // informace o zákazníkovi předáme třídě Customer $customer_output = new Twisto\Customer(array( 'name' => $customer['name'], 'email' => $customer['email'], 'customer_id' => $customer['id'] )); // získání dat o objednávkách zákazníka $sth = $dbh->prepare(' SELECT O.id, O.date_add, O.carrier_id, OS.paid, OS.delivered, OS.shipped, OS.returned, B.name billing_name, B.street billing_street, B.phone billing_phone, B.city billing_city, B.zipcode billing_zipcode, D.name delivery_name, D.street delivery_street, D.phone delivery_phone, D.city delivery_city, D.zipcode delivery_zipcode FROM orders O JOIN address B ON B.id = O.billing_address_id JOIN address D ON D.id = O.delivery_address_id JOIN order_states OS ON O.id = OS.orders_id WHERE customer_id = :customer_id '); $sth->execute(array(':customer_id' => $customer['id'])); $orders = $sth->fetchAll(); $orders_output = array(); foreach ($orders as $order) { $sth = $dbh->prepare('SELECT * FROM order_items I WHERE I.order_id = :order_id'); $sth->execute(array(':order_id' => $order['id'])); $items = $sth->fetchAll(); $order_items = array(); // jednotlivé položky objednávky jsou instance třídy OrderItem foreach ($items as $item) { $order_items[] = new Twisto\OrderItem(array( 'price_vat' => $item['price_vat'], // celková cena všech kusů dané položky 'vat' => $item['tax'], 'quantity' => $item['quantity'], 'name' => $item['name'], // v názvu dopravy prosím zasílejte i jméno dopravce 'is_shipment' => $item['is_shipment'], 'is_payment' => $item['is_payment'], 'ean_code' => $item['ean_code'] // čárový kód produktu, nepovinný )); } // celá objednávka je instance třídy Order $order_data = new Twisto\Order(array( 'order_id' => $order['id'], 'created' => date('c', strtotime($order['date_add'])), /* * total_price_vat = cena s DPH všech položek včetně dopravy a platby, * stejná cena musí být zobrazena zákazníkovi */ 'total_price_vat' => $order['total_price_tax_incl'], 'billing_address' => new Twisto\Address(array( 'name' => $order['billing_name'], 'street' => $order['billing_street'], 'city' => $order['billing_city'], 'zipcode' => $order['billing_zipcode'], 'phones' => array($order['billing_phone']) )), 'delivery_address' => new Twisto\Address(array( 'name' => $order['delivery_name'], 'street' => $order['delivery_street'], 'city' => $order['delivery_city'], 'zipcode' => $order['delivery_zipcode'], 'phones' => array($order['delivery_phone'], $order['delivery_mobile_phone']) )), 'is_paid' => $order['paid'], 'is_delivered' => $order['delivered'], 'is_shipped' => $order['shipped'], 'is_returned' => $order['returned'], 'items' => $order_items )); // pole objednávek (pole instancí třídy Order) $orders_output[] = $order_data; } // odeslání řešíme přes třídu CheckResponse, která zajistí, že data budou ve správném formátu $response = new Twisto\CheckResponse(); $response->add($customer_output, $orders_output); } else { header("HTTP/1.1 400 Bad Request"); echo json_encode(array('error' => 'Unknown action')); } ?>

Data Format

Information about historical transactions is obtained upon request from your server via the webhook. Its setup is described in detail in the previous chapter.

Note: Our servers expect valid JSON, which should be taken care of by the PHP library itself. The fact that the string inside is escaped is not a problem; it is still valid JSON. Examples in our documentation may contain unescaped JSON, but your PHP version can escape the data, and both variants are valid.

Warning: Phone numbers are required in international format with the prefix "+420732629228". For new orders, the customer's phone number is mandatory, and if not provided, the order will be rejected.

Your response should be in JSON format:

{ "customer": { "name": "Jan Novák", "email": "novak@example.cz", "date_registered": "2013-08-14T12:40:39+02:00", "customer_id": "1" }, "orders": [ { "order_id": "9259802", "created": "2013-08-14T12:45:46+02:00", "total_price_vat": 23239.0, "billing_address": { "name": "Jan Novák", "street": "Karlova 2", "city": "Praha 5", "zipcode": "10010", "phones": ["+420732629228"], "country": "CZ" }, "delivery_address": { "name": "Jan Novák", "street": "Karlova 2", "city": "Praha 5", "zipcode": "10010", "phones": ["+420732629228"], "country": "CZ" }, "is_paid": true, "is_delivered": true, "is_shipped": true, "is_returned": false, "items": [ { "quantity": "1", "name": "MacBook", "price_vat": 23000.0, "vat": 21, "is_shipment": false, "is_payment": false, "categories": ["Laptops", "Apple"], "ean_code": "8859094127591" }, { "quantity": 1, "name": "DHL", "price_vat": 200.0, "vat": 21, "is_shipment": true, "is_payment": false }, { "quantity": 1, "name": "Platba Twisto (na fakturu)", "price_vat": 39.0, "vat": 21, "is_shipment": false, "is_payment": true } ] } ] }
NameRequiredData TypeValue
customerCustomerDetailed information about the customer
ordersArray<Order>Previous orders of the customer. Please do not send unfinished or canceled orders.

JavaScript

Implementation Method

For detailed evaluation, it is necessary to provide complete user data, including their previous transactions.

After clicking the "Complete Order" button (just before displaying the thank you message for the completed order), detailed evaluation is triggered in the JavaScript library by calling the Twisto.check(data, success, error) method. This entire process can take several seconds. The result of the evaluation is then passed to the success callback, in both cases, even if the request was rejected.

There are two possible outcomes:

  • accepted = approval The response includes the transaction identifier transaction_id. The order is completed normally. The user sees a thank you message, and the entire process is completed for the customer. After completing the order, the transaction_id is used to create an invoice.

  • rejected = rejection The user sees a reason for the rejection. In this case, it is advisable to offer the user an alternative payment method. The response also includes the transaction identifier transaction_id.

{ "status": "accepted" }

In case of an error, which can be caused by technical issues, the error callback is invoked. We recommend taking the same action as in the case of rejection.

Example Usage

The following example shows a code snippet with an order form, specifically the payment selection part. It utilizes the jQuery library. Instead of submitting the form when clicking the confirmation button, a detailed customer check is performed by replacing the normal form submission action with a call to Twisto.check. The confirmation button is disabled during the request processing to prevent multiple submissions. Since the processing can take several seconds, it is recommended to provide some visual indication to the user, such as an AJAX loader. If the payment is approved, the transaction ID is stored in a hidden form field and submitted.

<?php require_once 'twistophp/Twisto.php'; $twisto = new Twisto\Twisto(); $twisto->setPublicKey(''); $twisto->setSecretKey(''); // zákazník je uložen v session z předchozích kroků nákupního procesu $customer_data = $_SESSION['customer_data']; $customer = new Twisto\Customer(array( 'name' => $customer_data['name'], 'email' => $customer_data['email'], 'date_registered' => $customer_data['date_registered'], 'customer_id' => $customer_data['id'] )); // info o objednávce $order_data = $_SESSION['order_data']; $oredered_items = array(); // každá položka objednávky bude instance třídy OrderItem foreach($order_data['items'] as $item) { $ordered_items[] = new Twisto\OrderItem(array( 'price_vat' => $item['price_tax_incl'], // celková cena všech kusů dané položky 'vat' => $item['tax_rate'], 'quantity' => $item['quantity'], 'name' => $item['name'], 'is_shipment' => false, 'is_payment' => false, 'categories' => $item['categories'], 'ean_code' => $item['ean_code'] // čárový kód produktu, nepovinný )); } // doprava musí být také součástí objednávky $ordered_items[] = new Twisto\OrderItem(array( 'price_vat' => $order_data['carrier_price'], 'vat' => 21, 'quantity' => 1, 'name' => $order_data['carrier_name'], // v názvu dopravy prosím zasílejte i jméno dopravce 'is_shipment' => true, 'is_payment' => false )); // a nakonec položka platby $ordered_items[] = new Twisto\OrderItem(array( 'price_vat' => $order_data['payment_price'], // cena se může lišit např. v případě promo akce 'vat' => 21, 'quantity' => 1, 'name' => 'Platba Twisto (na fakturu)', 'is_shipment' => false, 'is_payment' => true )); // Instance třídy NewOrder bude obsahovat všechny informace o objednávce $order = new Twisto\NewOrder(array( 'created' => date('c', strtotime($order_data['date_add'])), /* * total_price_vat = cena s DPH všech položek včetně dopravy a platby, * stejná cena musí být zobrazena zákazníkovi */ 'total_price_vat' => $order_data['total_price_tax_incl'], 'billing_address' => new Twisto\Address(array( 'name' => $order_data['billing_name'], 'street' => $order_data['billing_street'], 'city' => $order_data['billing_city'], 'zipcode' => $order_data['billing_zipcode'], 'phones' => array($order_data['billing_phone']), 'city' => $order_data['billing_city'], 'country' => $order_data['billing_country'], )), 'delivery_address' => new Twisto\Address(array( 'name' => $order_data['delivery_name'], 'street' => $order_data['delivery_street'], 'city' => $order_data['delivery_city'], 'zipcode' => $order_data['delivery_zipcode'], 'phones' => array($order_data['delivery_phone']), 'city' => $order_data['delivery_city'], 'country' => $order_data['delivery_country'], )), 'items' => $ordered_items )); // připravíme si data pro odeslání na Twisto server přes javascript $payload = $twisto->getCheckPayload($customer, $order); ?> <form action="" method="post"> ... <h2>Platba</h2> <input type="radio" name="payment_method" id="cash" value="cash"> <label for="cash">Dobírka</label> <input type="radio" name="payment_method" id="online_card" value="online_card"> <label for="online_card">Platební kartou online</label> <input type="radio" name="payment_method" id="twisto" value="twisto"> <label for="twisto">Twisto</label> <div id="twisto-checkout"></div> ... <input type="hidden" name="transaction_id"> <input type="submit" value="Potvrdit"> </form> <script type="text/javascript" src="https://static.twisto.cz/api/v1/twisto.js"></script> <script type="text/javascript"> Twisto.setPublicKey(''); $('input[type=submit]').click(function(e) { if ($('#twisto').is(':checked')) { e.preventDefault(); $('input[type=submit]').prop('disabled', true); // zakážeme vícenásobné odeslání formuláře Twisto.check(<?php echo $payload ?>, function(response) { if (response.status == 'accepted') { // platba byla schválena // uložíme ID transakce pro následné vytvoření faktury po úspěšném dokončení objednávky $('input[name=transaction_id]').val(response.transaction_id); $('form').off('submit').submit(); // odešleme původní formulář } else { // platba byla zamítnuta $('input[type=submit]').prop('disabled', false); } }, function() { // nastala chyba ve formuláři $('input[type=submit]').prop('disabled', false); }); } }); </script>

JavaScript Data Format

If the ordering process is divided into multiple steps, it is possible to prepare the data on the server using a PHP library, as shown in the example above. If the ordering process is on a single page, the data can be prepared directly from JavaScript.

Your request should be in JSON format:

{ "customer": { "name": "Jan Novák", "email": "novak@example.cz", "date_registered": "2013-07-11T11:31:21+02:00", "customer_id": "1" }, "order": { "total_price_vat": 23239.0, "delivery_address": { "name": "Jan Novák", "street": "Karlova 2", "phones": ["+420732629228"], "city": "Praha 5", "zipcode": "10010", "country": "CZ" }, "billing_address": { "name": "Jan Novák", "street": "Karlova 2", "phones": ["+420732629228"], "city": "Praha 5", "zipcode": "10010", "country": "CZ" }, "items": [ { "product_id": "c81e728d9d4c2f636f067f89cc14862c", "quantity": "1", "name": "MacBook", "price_vat": 23000.0, "vat": 21, "is_shipment": false, "is_payment": false, "categories": ["Laptops", "Apple"], "ean_code": "8859094127591" }, { "product_id": "a87ff679a2f3e71d9181a67b7542122c", "quantity": 1, "name": "DHL", "price_vat": 200.0, "vat": 21, "is_shipment": true, "is_payment": false }, { "quantity": 1, "name": "Platba Twisto (na fakturu)", "price_vat": 39.0, "vat": 21, "is_shipment": false, "is_payment": true } ] } }
NameRequiredData TypeValue
customerCustomerDetailed information about the customer
ordersNewOrderCurrent order of customer

Testing

In the testing API, you can use the following email karel.zlodej@example.cz for testing the rejection of a customer order (the response will have the status set to rejected). Therefore, you need to set the email property of the Customer object to this value. For all customers with a different email, the order will be allowed in the testing API (the response will have the status set to accepted).

The next step is invoice creation.