Customer credit check
In case of a positive customer credit check with status “Accept”, the process for the customer is finished and a "Thank you for your purchase" message can be shown. If the payment is with status “Rejected” an alternative payment method should be proposed. The Twisto credit check is real-time and runs completely on Twisto’s server side.
The evaluation process is powered by the Twisto.js - JS library, that should be added to the purchase process and a back-end e-shop library designed to prepare data (payload) for the JS library. If you are using different programming language, it is also possible to prepare the data manually according to the specification.
For detailed evaluation, it is necessary to provide full customer data, including previous transaction history.
At the time of clicking on "Confirm order" the credit check is started by calling the method in the JS Library Twisto.check(data, success, error). This process may take several seconds. The result of the credit check is then forwarded to the callback success, in both cases, even if the request was rejected.
In case of an error that may be caused by technical problems, error callback is called. We recommend showing an error to inform the customer and offer an alternative payment method. An order with error status cannot be shipped because it is not stored in the Twisto system. This means that the e-shop will not receive payment for it.
Implementation
The following example includes a full-featured code that performs customer credit check. The jQuery library is used to simplify code writing.
Customer data and previous orders are prepared on the server side and then passed to the Javascript library (as payload
) for the Twisto.check()
call. You can use the back-end library to prepare your payload or manually prepare the data according to the specifications. Then JS library will send prepared payload to the server.
When selecting the Twisto payment method and clicking on the order confirmation, the customer’s check is performed instead of submitting the form. This is done by replacing the normal action of submitting the form by clicking on the confirmation (submit
) for the Twisto.check
call. The "Confirm order" button should be changed to loader during the check process to indicate the ongoing credit check. Because this process may take several seconds, we recommend that this information is presented to the customer in a similar way.
When a payment is approved, a transaction ID is inserted into the hidden form field. Please save this ID to server, you will need it to create and update the order through our API.
A unique string for the random_nonce
should be generated for each request. In case of Twisto.check
will be called multiple times with the same random_nonce
, the same result will always be returned. This way, you can avoid problems with sending same form repeatedly by customer. Twisto libraries generate random*nonce automatically, but if you’re manually creating the payload, please ensure that this string will always be unique. For example, you can use uuid4.
Note: Payload can’t be generated on the client side because it is encrypted and signed with a secret key that can not be disclosed.
Note: You can choose from two encryption options. You can change the encryption method in the eshop settings a detailed description can be found in the Reference Guide (data encryption).
Warning: If you perform the evaluation within WebView in a mobile application, you need to store and maintain cookies for further evaluation on the same device.
<?php
define('TWISTO_PUBLIC_KEY', ''); // You can find your public key in administration
define('TWISTO_SECRET_KEY', ''); // You can find your secret key in administration
$reject_test_order = false;
require 'vendor/autoload.php';
date_default_timezone_set('Europe/Prague');
$twisto = new Twisto\Twisto();
$twisto->setPublicKey(TWISTO_PUBLIC_KEY);
$twisto->setSecretKey(TWISTO_SECRET_KEY);
$customer = new Twisto\Customer('novak@example.cz', 'Jan Novák', '1146217671', '01615165', 'CZ01615165');
if($reject_test_order)
$customer->email = 'karel.zlodej@example.cz';
$order_items = array(
new Twisto\Item(
Twisto\Item::TYPE_DEFAULT, // type
'Coca Cola 1 litr', // name
530, // product_id (Product ID has to be unique per order)
6, // quantity
156, // price_vat (total price of all items of order item)
15, // vat
'5449000017888', // ean_code (product barcode)
null, // isbn_code
null, // issn_code
3808 // heureka_category (ID of Heureka.cz category)
),
new Twisto\Item(
Twisto\Item::TYPE_DEFAULT, // type
'Agatha Christie: The Secret Adversary', // name
942, // product_id
1, // quantity
285.31, // price_vat
15, // vat
null, // ean_code
'9781609421052', // isbn_code
null, // issn_code
1469 // heureka_category
),
new Twisto\Item(
Twisto\Item::TYPE_SHIPMENT, // type
'Doprava DPD', // name
'shipment', // product_id
1, // quantity
119, // price_vat
21 // vat
),
/*
* Payment item (Twisto) is also required to be listed among order items
*
* You can lower the price of payment in order items below at your own expense.
*/
new Twisto\Item(
Twisto\Item::TYPE_PAYMENT, // type
'Twisto – Zboží inhed, platím za 14 dní', // name
'payment', // product_id
1, // quantity
0, // price_vat
21 // vat
),
new Twisto\Item(
Twisto\Item::TYPE_ROUND, // type
'Zaokrouhlení', // name
'round', // product_id
1, // quantity
-0.31, // price_vat
0 // vat
),
);
// Instance of class NewOrder will contain all information about order
$order = new Twisto\Order(
new DateTime(), // date_created
new Twisto\Address('Jan Novák', 'Milady Horákové 116/109', 'Praha 6', '16000', 'CZ', '+420603604605'), // billing_address
new Twisto\Address('Jan Novák, Twisto payments a.s.', 'Sokolovská 47/73', 'Praha 8', '18600', 'CZ', '+420603604605'), // delivery_address
560, // total_price_vat
$order_items // items
);
$previous_orders = array(
new Twisto\Order(
new DateTime("2012-07-08 11:14:15.638276"),
$order->billing_address,
$order->delivery_address,
$order->total_price_vat,
$order_items
)
);
// create data to be sent to Twisto server via javascript
$payload = $twisto->getCheckPayload($customer, $order, $previous_orders);
?>
<!DOCTYPE html>
<html>
<head>
<meta charset="utf-8">
<link rel="stylesheet" href="//maxcdn.bootstrapcdn.com/bootstrap/3.2.0/css/bootstrap.min.css">
<script src="//ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>
<link rel="stylesheet" href="https://static.twistopay.com/base/css/doc-examples.css">
<script type="text/javascript">
var _twisto_config = {
public_key: '<?php echo TWISTO_PUBLIC_KEY; ?>',
script: 'https://api.twisto.cz/v2/lib/twisto.js'
};
(function(e,g,a){function h(a){return function(){b._.push([a,arguments])}}var f=["check"],b=e||{},c=document.createElement(a);a=document.getElementsByTagName(a)[0];b._=[];for(var d=0;d<f.length;d++)b[f[d]]=h(f[d]);this[g]=b;c.type="text/javascript";c.async=!0;c.src=e.script;a.parentNode.insertBefore(c,a);delete e.script}).call(window,_twisto_config,"Twisto","script");
</script>
<script type="text/javascript">
$(function() {
DemoCheckout = {
$terms_notice: $('#terms-notice'),
$checkout_form: $('#checkout-form'),
$form_submit_button: $('.btn-submit'),
$btn_check: $('.btn-check'),
$error_alert: $('#error-alert'),
init: function () {
DemoCheckout.$checkout_form.on('submit', function(e) {
e.preventDefault();
// Twisto payment method was selected
if($('input[name=payment_method]:checked').val() == 'twisto') {
if($('#terms-checkbox').is(':not(:checked)')) {
DemoCheckout.$terms_notice.show();
} else {
DemoCheckout.reset();
// show button with an animation signaling order evaluation
DemoCheckout.$form_submit_button.hide();
DemoCheckout.$btn_check.css('display', 'inline-block');
DemoCheckout.twisto_check('<?php echo $payload; ?>');
}
}
});
},
twisto_check: function (payload) {
Twisto.check(payload, function(response) {
if (response.status == 'accepted') {
// payment accepted
DemoCheckout.order_complete();
// save transaction id to hidden form field
$('#twisto-transaction-id').val(response.transaction_id);
} else {
// payment declined
DemoCheckout.reset();
DemoCheckout.error(response.reason);
}
}, function() {
// an error occurred due to invalid request or connection failure
DemoCheckout.reset();
DemoCheckout.error();
});
},
reset: function () {
DemoCheckout.$terms_notice.hide();
DemoCheckout.$form_submit_button.show();
DemoCheckout.$btn_check.hide();
DemoCheckout.$error_alert.hide();
},
error: function (reason) {
if(typeof(reason) == 'undefined')
reason = 'Došlo k chybě při odesílání objednávky na platební bránu Twisto. Zkuste to prosím znovu, případně si vyberte jinou platební metodu.';
DemoCheckout.$error_alert.html(reason);
DemoCheckout.$error_alert.show();
},
order_complete: function() {
DemoCheckout.reset();
$('.panel-body.form').hide();
$('.panel-body.thank-you').show();
}
};
DemoCheckout.init();
});
</script>
</head>
<body>
<div class="container" role="main">
<div class="panel panel-default">
<div class="panel-body form">
<form action="" method="post" id="checkout-form">
<input type="hidden" name="twisto-transaction-id" id="twisto-transaction-id" value="">
<div class="alert alert-danger" id="error-alert"></div>
<div class="radio">
<label>
<input type="radio" name="payment_method" value="twisto" checked>
<span>Zboží ihned, platím za 14 dní</span>
</label>
<div id="terms-notice">
<small>Pro použití platební metody Twisto je potřeba souhlasit s podmínkami služby.</small>
</div>
<div class="twisto-terms">
<label>
<input type="checkbox" id="terms-checkbox">
Souhlasím s <a href="https://www.twisto.cz/podminky/">všeobecnými obchodními podmínkami</a>
služby Twisto.cz (platba první objednávky do 14 dní od doručení zboží) a se zpracováním
osobních údajů pro účely této služby. Podmínkou služby je věk 18+ a převzetí zboží
zákazníkem.
</label>
</div>
</div>
<div class="radio">
<label>
<input type="radio" name="payment_method" value="cash">
<span>Dobírka</span>
</label>
</div>
<div class="radio">
<label>
<input type="radio" name="payment_method" value="online_card">
<span>Platební kartou online</span>
</label>
</div>
<div id="twisto-checkout"></div>
<input type="hidden" name="transaction_id">
<div class="submit">
<input type="submit" class="btn btn-success btn-submit" value="Dokončit objednávku">
<a class="btn btn-success btn-check disabled">Probíhá vyhodnocení objednávky <img
src="https://upx.cz/9ii0u5ydmfi7u1zx3mxr9xqp628ra2eoljoyqrhy"></a>
</div>
</form>
</div>
<div class="panel-body thank-you">
<h3>Děkujeme za Vaši objednávku!</h3>
<p>Po obdržení zboží budete mít 14 dní na zaplacení bankovním převodem, kartou online nebo hotově
společnosti Twisto.cz.</p>
</div>
</div>
</div>
</body>
</html>
?>
Data format
API requires valid phone numbers in international format, e.g. "+420732629228". In case of missing the country-specific prefix it will be automatically added (field country
in billing address). For new orders, customer’s phone number is mandatory, and if the phone is not filled, the order will be declined. Phone number validation in the shopping cart is on a particular e-shop implementation, we recommend using the libphonenumber, library, which is also used by the Twisto API.
Warning: An incorrect phone number in the order will cause an API error and the order will not be created.
In the field for previous orders should be all customer orders that have already been paid, are not canceled and were not made with Twisto. If the customer is not registered, please search previous orders by email.
Request
Name | Required | Data type | Maximum length | Value |
---|---|---|---|---|
random_nonce | ✓ | String | 64 | Text string unique for each check |
customer | ✓ | Customer | Detailed information about the customer | |
order | ✓ | Order | Current customer order | |
previous_orders | ✓ | Order[] | All already paid orders except for orders via Twisto |
It’s possible to set callback using Twisto.js which will be called after the scoring process successfully started, i.e. at the moment when the data has been already sent to the server and the library waits for scoring result.
This can be set up using processingStarted
option, see reference manual.
Response
The result of the credit check has two possible states. The response always has transaction ID (transaction_id
) and status
, if rejected - (reason
). The answer is forwarded to the success callback.
accepted
= approval- The order is successfully completed. "Thank you for your payment" message is shown to the customer.
- When the purchase is completed, use transaction_id to create an invoice.
accepted-verification-required
= verification required- Order is approved, but needs additional verification. The customer would have to enter verification code before finishing the order.
- When the purchase is completed, use
transaction_id
to create an invoice. - Before invoice create user verification via API is required.
- This response is only for eshops with enabled verification api.
rejected
= rejection- The rejected
reason
will be shown to the customer. - If the rejection is final, allow customer to choose another payment method and display rejected reason.
- If you have multilingual e-shop or you are not able to use
reason
, usereason_params
andreason_id
. Some reasons has inreason_params
parametrlimit
.reason_id
is positive number or0
- The rejected
{
"status": "accepted",
"transaction_id": "hisnmy6enxhq07rx69hniwwd"
}
{
"status": "accepted-verification-required",
"transaction_id": "hisnmy6enxhq07rx69hniwwd"
}
{
"status": "rejected",
"transaction_id": "hisnmy6enxhq07rx69hniwwd",
"reason_id": 2,
"reason_params": {},
"reason": "The payment was not approved as we were unable to process the format of your address. Please try entering the address again as it is written in your personal ID or the Land Register."
}
{
"status": "rejected",
"transaction_id": "hisnmy6enxhq07rx69hniwwd",
"reason_id": 0,
"reason_params": {},
"reason": "Sorry, unfortunately this order was not accepted by the Twisto payment gateway verification process. Please use an alternative payment method."
}
{
"status": "rejected",
"transaction_id": "hisnmy6enxhq07rx69hniwwd",
"reason_id": 3,
"reason_params": {
"limit": "1,000 Kč"
},
"reason": "Your purchase is too big for Twisto. We’ll be happy to serve you if the total price of the order will be lower than 1,000 Kč."
}
Rejection reason
reason_id | Short description | Message | reason_params |
---|---|---|---|
0 | Default | We’re sorry, but we have to ask you to use another payment method. | {} |
1 | Invalid address | As much as we tried, we couldn’t find this address. However, when you enter it in the same format that is on your identity card, it should go through. | {} |
2 | Unpaid invoices | Your purchase is a little bit too big for Twisto. We’ll be happy to allow you this payment after you settle your previous purchases. | {} |
3 | Over limit | Your purchase is too big for Twisto. We’ll be happy to serve you if the total price of the order will be lower than 1,000 Kč. | {"limit": "1,000 Kč"} |
4 | Over annual limit | You've reached maximum annual limit for Twisto Pay purchases.We will be happy to allow you to make a further purchase if you register a Twisto account. We have sent you more information by e-mail. | {} |
5 | Invalid name | Please enter your first name and surname in your billing address. | {} |
6 | No account | At this time, we only allow the purchase of customers who have a Twisto account. You can find information on how to register a Twisto account at www.twisto.cz | {} |
7 | Sms verification required | You have closed the window with SMS verification dialog. For security reasons, we require SMS verification. | {} |
100 | Account over limit | Your purchase exceeds the current limit of your Twisto account. We will be happy to allow you this payment if your purchase is within 1,000 Kč. | {"limit": "1,000 Kč"} |
101 | Unpaid invoices | Your purchase exceeds the current limit of your Twisto account. We’ll be happy to allow you this payment after you settle your previous purchases. | {} |
102 | Account login required | You have closed the window with Twisto account login dialog. For security reasons, we require a login before continuing. | {} |
Customer verification
In some cases additional identity verification is required. It’s either SMS code or login to customer account. In these cases modal is displayed to customer right on eshop page. Our JS library is responsible for displaying this modal. Our library can detect that third party cookies are disabled in the browser and allow the customer to display verification form in a new window instead of modal. To test this use email test@twisto.cz
, in other word set email
field of Customer object to this value. Modal is displayed and any password is accepted.
For payment gateway there is verification API. It’s not intended for eshops so It’s not needed in this case.
Testing
If you’d like to test rejection of the order (property status
will be set to rejected
in the response), please use testing email address karel.zlodej@example.cz
. Object Customer should have the property email
set to this value. The scoring will always accept all other email addresses in the testing API (property status
will be set to accepted
).