0% found this document useful (0 votes)
11 views16 pages

Safe For Dummies

Uploaded by

Arturo Castro
Copyright
© © All Rights Reserved
We take content rights seriously. If you suspect this is your content, claim it here.
Available Formats
Download as PDF, TXT or read online on Scribd
0% found this document useful (0 votes)
11 views16 pages

Safe For Dummies

Uploaded by

Arturo Castro
Copyright
© © All Rights Reserved
We take content rights seriously. If you suspect this is your content, claim it here.
Available Formats
Download as PDF, TXT or read online on Scribd
You are on page 1/ 16

API SAFE (v2)

for dummies
By Jeshua N.
– INDEX –

0) SAFE Presentation
1) External services (APIs)
1.1) Telesign
1.2) Maxmind
2) SAFE main files
2.1) Paths summary
2.2) API files
2.3) LIBS files
2.4) XML file
2.4.1) Structure
2.4.2) Difference between “risk score” concepts
2.4.3) XML paths
2.5) JSON files
2.6) Billing files
2.6.1) how to add stores (flashIDs) to SAFE 2
3) Other files
3.1) Where from is sent Paypal and Maxmind info to SAFE
3.2) Phone number prefix
3.3) CCommand for Safe
3.4) BackOffice view
3.5) Safe rules specification on Redmin Wiki
4) Other info
4.1) Notes for “Safe step 0”
4.2) Rules nomenclature
4.3) Send email to NicoS when a rule is changed/added directly on prod
4.4) How to perform tests on sandbox forcing different SAFE results
4.5) SAFE logs errors
SAFE Presentation
Global view:
SAFE is the engine we use to detect fraudulent customers and purchases.
We use our own stored info, and external info (Maxmind, Telesign.. we will see them
afterwards) to create and configure the rules which SAFE use to flag an
order/customer as fraudulent or not.
After executing SAFE, the engine returns actually one of the following 4 risk status for
the order (ordered by hierarchy of less to more restrictive):

• OK :
o Order valid. No more check needed.
o The customer will receive a confirmation email of correct purchase,
with serials, etc…
• MOBILE_CHECK :
o Order needs an SMS/Call code verification, to determine if the order will
be valid or not.
o Customer must insert its phone number, and will receive an SMS/CALL
with a verification code.
o He will insert it on a form. If it is correct, SAFE runs again all its rules,
now with new phone info (retrieved by Telesign).
o If no verification code is inserted, or code is inserted incorrectly in 5
attempts, the order will be managed for Customer Support.
• MANUAL :
o Order needs manual verification to determine if the order will be valid
or not.
o Customer Support manage these ones.
• FRAUD :
o Order is set as fraudulent, and the amount will be refunded and similar
orders/customer could be flagged as fraudulent.
o Actually, Customer Support manage these ones.
When do we call to SAFE:
SAFE is called actually in 2 steps (but soon will be called from another one, so let´s see
it too):

• Step 0: NOT INTEGRATED YET! This step will be before payment is done. So if
any of the rules triggered returns challenge, the order will not continue on
payment process.
• Step 1: “post_order”. Just after payment process (when we already got the
money of the customer if is a normal order, or if it is a preorder when we got it
in state “captured but not collected”), SAFE is executed.
• Step 2: “code_verification”. If after Step 1 the order is set as MOBILE_CHECK,
will happen all explained on MOBILE_CHECK.

Where SAFE stores its data:


SAFE doesn´t uses DB for store info (except for the 3-fields table “command_safe”,
which only store the orderID and the phonenumber used (no the verification code)
only in case of a MOBILE_CHECK flagged order ).
SAFE uses its own json files to store by separate, the results of very of the steps in
which has been executed the SAFE rules. Every orderID has its own json file. We will
see this in detail afterwards.

Attachment: Training Safe 2015 05 v1.pptx


With this documentation, is attached the powerpoint file named before, which
explains in detail the real use of SAFE to try capture all the frauders on this world!
1) External services (APIs):
1.1) TELESIGN:

Goal of this API:


Retrieve phone info and its risk info when customer inserts its phonenumber to request its
SMS/CALL verification code (in case of order has been flagged with MOBILE_CHECK status).

Credentials:
Login : [email protected]
Pass : Tqsdo98a
url : https://teleportal.telesign.com/

Contracted products:
https://teleportal.telesign.com/auth/suborg/828/
Verify Voice
Verify SMS
PhoneID Score

Phone types:
http://docs.telesign.com/rest/content/xt/xt-phone-type-codes.html

[Docu name] = [API response value]


Fixed Line = FIXED_LINE
Mobile = MOBILE
PrePaid Mobile = PREPAID
Toll-Free = TOOL_FREE
Non-Fixed VOIP = VOIP
Pager = PAGER
Payphone = PAYPHONE
Invalid = INVALID
Restricted Number = RESTRICTED_PREMIUM
Personal = PERSONAL
Voicemail = VOICEMALL
Other = OTHER

Files:

/pepita_api/app/lib/safe/data

- CPhoneID.php
- CTelesign.php
- CVerify.php
1.2) MAXMIND:

Goal of this API:


Returns risk info about payment used on order. This info is retrieved during payment process
and is given to SAFE as parameters when you call de SAFE API on CSafe.php file.

Documentation:
http://dev.maxmind.com/minfraud/

2) SAFE main files:


2.1) Paths summary:

• API:
- /pepita_api/app/controllers/v10
CRestSafe.php
CRestGraphSafe.php
CRestSafeDefault.php
CRestSafeResponseDefault.php
• LIBS:
- /pepita_api/app/lib/safe/
SafeFunctions.php
SafeRules.php
• XML:
- /pepita_customer/app/storage/client/safe/
• Billing:
- /pepita_billing/workbench/pepita/billing/src/Pepita/Billing/
CSafe.php
CProductBilling
• JSON:
- /pepita_log/app/storage/safe/results
- /pepita_log/app/storage/logs/safe
• Feed rule-functions files:
- /pepita_api/app/lib/safe/data
bl_emails.txt
bl_phonenumbers.txt
bl_regex_emails.txt
bl_regex_weirds.txt
- /pepita_core/workbench/pepita/core/src/config/constants/
phone_countries.php
risk_countries.php
2.2) API files:
CRestSafe:
It has 3 API input public functions:
• set_safe : POST. Here SAFE it´s started. It retrieves all info from Maxmind, DB and
payment type. It creates the json file and save all info on it. And directly, calls
“get_safe” function.
• get_safe : GET. Here is the main SAFE engine. Here all rules are passed, the final results
are setted as SAFE API response. It changes the states and refresh the json file =>
[SAFE 1st step: post_order results].
• mobile_check : PUT. This one is used for the SMS validation required cases. It´s
splitted in 2 sub-methods:
_send_code : SMS validation 1st stp: When user inserts his phonenumber,
country and SMS/CALL. If phone is valid (call to Telesign API), the verification
Code is generated, and it is sent by SMS/CALL to the customer, and saved it on
json file (to check it on next step). On this Telesign call, SAFE retrieve al phone
risk infos too from its response.
_code_verification : SMS validation 2nd step: Customer inserts its received
SMS/CALL verification code, and he must insert it. If it matches (5 attempts
maximum), it calls to “get_safe” function to run again all rules, with different
configuration and new phone info added => [SAFE 2nd step: code_verification
results].

CRestGraphSafe:
Is the one which contains the “_update_order_state” method. CRestSafe extends
CRestGraphSafe, so if in CRestSafe you want to call a “self” method, instead of
“self::xxxx”, use “CRestSafe::xxxx”

CRestSafeDefault & CRestSafeResponseDefault :


Same use as all REST API controllers.

The 3 usual actual flows on SAFE are:


• 1ST step result = OK. No 2nd step needed:
[POST] set_safe
[direct] get_safe
1st step SAFE results => OK
Order validated.
• 1ST step result = SMS. 2nd step needed:
[POST] set_safe
[direct] get_safe
1st SAFE results => SMS
Link and email of “Verification code is required”.
[PUT] mobile_check
[direct] _send_code
[PUT] mobile_check
[direct] _code_verification
[direct] get_safe
2nd step SAFE results:
Order validated.
Verification required
Fraud
• 1ST step result = Bypass Safe. No 2nd step needed:
[POST] set_safe
[direct] get_safe
1st step SAFE results => Bypass Safe
Order validated.

2.3) LIBs files:


SafeFunctions.php:
Contains all functions used to operate all rules, providing each one its own result. If
after operate the rule, its result is “challenge”, will take the “result response value” of
the rule from XML file (it is explained afterwards).
Every function returns an array as below. It´s values are predefined on XML and used
to do some operations on the function:
o Type: status / risk_score (determined on XML)
o Value: (ok, mobile_check, manual…) / INT (depends on Type. Determined on
XML.)
o Note: Text shown on BO which gives info about response of the function.

SafeRules.php:
This file contains arrays with the name of all functions. This one matches the <in code
name> of a function, with its <human name> on XML file.
The array selected is defined on CRestSafe. Actually it uses “get_all” for step 1 and
step 2. There is another one array created called “get_before_payment_rules” for step
0, which is not actually being used (as step 0 is not implemented yet). But it is ready to
be used.
Name used on key ‘title’ here, it´s the same as used on field ‘title’ of XML. SO, if you
change it in one of the files, you should change it in the other, using exactly the same
name (mandatory, to be able to do the match).

2.4) XML file:


2.4.1) Structure:
rules : Values used on SafeFunctions.php
o title: Field used to match SafeFunctions with XML, on SafeRules.
o state: enabled / disabled
o limit (optional): Value for variables used on functions.
o note (optional): Value for functions note response.
o formula (optional): Value for variables used on functions, and in some cases
shown on “note” response field.
o type: status / risk_score
o value: Depends of Type. If type is “risk_score”, the Value will be a number. If
Type is “status” will be one of them (ok, mobile_check, manual, fraud…). This
value is the result given when the functions is operated as “Challenge”.
o exception_type / exception_value : Work the same as type / value. It is used
for example when the function needs a parameter which is not defined, and
we can´t operate the function.
special_products : If any these OIDs are in the cart, SAFE will take the value defined on
XML (Note: They got not a function on “SafeFunctions”. It is directly coded on
CRestSafe::_compare_xml_rules after a conditional).
risk_score_values :
o After have been executed all SAFE functions, if there is setted a risk_score > 0,
this risk_score will be compared on these XML fields. And will take this value
as “risk score status”. And will be used to get_worst_response between this
“$risk_score_status” and “$_status” (better explained below).
o Note: Actually no risk_score is being used on SAFE, but it is ready to configure
and use it when it is needed.

Every of them contains its fields into the different SAFE steps groups, which one will be used
depending on actual SAFE step is being executed:
before_payment (step 0)
post_order (step 1)
code_verification (step 2)

And you can call on SafeFunctions every of the last-child XML fields by only using:
$xml['{field_name}’] (ie: $xml['limit']). Automatically SAFE knows which one of steps must be
read.

2.4.2) Difference between $post[‘maxmind_info’][‘riskScore’] , $_risk_score , $_status , and


$final_status :
$post[‘maxmind_info’][‘riskScore’] :
o This is one of the most important values which Maxmind API return to us. It is
a float between 0 – 99, which reflects the riskScore of a payment. Maxmind
returns a lot of values (proxyScore, ip_latitude, binMatch…) when we do a
request to its API, and riskScore is one of them.
o This “riskScore” value of Maxmind´s API response, it´s the “summarized” and
quickest way we have to see if an order is potentially fraudulent or not (as
higher, risker the order is), as it represents numerically the global results of
all of Maxmind’s rules and the other returned values.
o So the goal of explaining this Maxmind param (riskScore), is to show that it is
absolutely different to the “risk_score” we are going to see below. And when
we talk about “risk_score” on next points, we will not refer to this Maxmind
param anymore.

$_status :
o As we know, every rule/function of SAFE is able to return two types of results:
“status” or “risk_score” (See previously XML file -> Structure -> rules -> type).
When a function returns a value of “status” type, it will try to update this
variable ($_status).
o This variable is set on ‘ok’ at start, and it will be updated ONLY if the status
returned by the function is MORE RESTRICTIVE than the actual setted on it.
Examples:
CASE A:
• $_status == ‘ok’
• Status returned by actual function : ‘mobile_check’
• $_status is updated to => ‘mobile_check’ (as ‘mobile_check’ is
more restrictive than ‘ok’)
CASE B:
• $_status == ‘mobile_check’ (because one function as already
setted it as ‘mobile_check’, as seen in previously example).
• Status returned by actual function : ‘ok’
• $status is NOT updated. It will continue having the
‘mobile_check’ value, as is more restrictive than ‘ok’.
o The rule “set status by hierarchy”, from less to more restrictive status is:
ok < mobile_check < manual < fraud
Note: Of course, $_status will be updated too when the higher state is
not the direct-consecutive one in the previous list (ie, it will work
correctly to update from ‘ok’ to ‘fraud’).

$_risk_score :
o Note: Actually no risk_score is being used on SAFE, but it is ready to configure
and use it when it is needed.
o As we know, every rule/function of SAFE is able to return two types of results:
“status” or “risk_score” (See previously XML file -> Structure -> rules -> Type).
When a function returns a value of “risk_score” type, it will try to update this
variable ($_risk_score).
o This variable is set on 0 at start, and will be updated when a function returns a
risk_score value. Functions returns will be able to add or subtract.
o So now, we would have 2 different things to compare: $_status (an
status_word as ok, mobile_check, manual…) and $_risk_score (a number). And
we need to compare them of any way to choose the more restrictive. There is
no way to compare a “number” with a “word”, so we need to convert the
“number” on a word, and then use the rule of “set status by hierarchy”
previously explained.
o So the goal is, after all SAFE functions have been executed, if there is setted a
risk_score > 0, this risk_score will be compared on the XML fields
risk_score_values (See XML file -> Structure -> risk_score_values).
o Then, if the total accumulated $_risk_score for all functions results is >= than
the higher of XML fields, will take its value. For example:
$_risk_score == 1550
XML < risk_score_values > :
<post_order>
<rule>
<type>fraud</type>
<value>8000</value>
</rule>
<rule>
<type>manual</type>
<value>1000</value>
</rule>
<rule>
<type>mobile_check</type>
<value>500</value>
</rule>
</post_order>
In this case as “1550” is more than 1000 but less than 8000, the value
returned will be “manual”
o Let´s call this last value returned, as “risk score status”.
o So finally, we compare the last returned “risk score status” with the variable
“$_status”, with our rule of “Set status by hierarchy”. And the higher, will be
set as the “$final_result”.
o Note: Of course, if after all SAFE functions have been executed $_risk_score ==
0 OR less than the minor of XML setted values (in the example above, less than
500), nothing of this will be needed to be done, and the “$final_result” will b
always the $_status variable value.
This is what happen nowadays, because no function returns
risk_score; only status words.

$final_result : Is the more restrictive value, after comparing $_status and


$_risk_score (see info above).

2.4.3) XML paths (file used by hierarchy, if exists):


1. /var/www/v4/pepita_customer/app/storage/client/safe/{clientID}/{projID}/safe_level1.xml
2. /var/www/v4/pepita_customer/app/storage/client/safe/{clientID}/safe_level1.xml
3. (*) /var/www/v4/pepita_customer/app/storage/client/safe/generic/safe_level1.xml

Uses:
1. One client has many projects. There is on Project by store. And for each one of them you
can have a different customized XML.
2. If some project has not its own customized XML; or if the client wants an XML common for
all its projects.
3. (*) Generic XML for all clients which has not any customized XML.

(*) Actually on use.


2.5) JSON files:
There are two types of json / logs:
PATHS:
• JSON: /pepita_log/app/storage/safe/results
• LOGS: /pepita_log/app/storage/logs/safe

Normal: (Feeds BackOffice “Risk Assestment” view, and pepita_log-


>MiscSafeController.php) =>
a. {orderID}.json: To register all steps done by SAFE from Store (actually,
post_order & code_verification ). This one is which Feeds BO.
b. {orderID}.log: To register adding new entries from Store (ie: 1st) post_order
2nd) post_order and code_verification). For debug pourposes.
_test: (For debug/tests pourposes. Only is created/modified with scripts from
“MiscSafeController.)
c. {orderID}_test.json: To register OVERWRITING steps done in Safe from
MISCSAFECONTROLLER.
d. {orderID}_test.log: To register ADDING NEW ENTRIES (ordered by date time)
steps done by Safe from MISCSAFECONTROLLER (ie: 1st) post_order 2nd)
post_order y code_verification).

• But the most important is {orderID}.json, because is the one used to feed Back Office:
- /pepita_log/app/storage/safe/results
- On this json, is saved every step by separated: all db/maxmind/phone infos, all
functions results, final results, etc…:
Post_order (step 0)
Code_verification (step 1)

• The URL to execute the MiscSafeController script is:


- http://log.pepitastore.com/misc/safe/get_safe_order_details?orderID={orderI
D}
- This writes and overwrites the {orderID}_test.json explained before.
• For the _test ones, you need to add &test=1 to the URL (this is used to reprocess safe
on order):
- http://log.pepitastore.com/misc/safe/get_safe_order_details?orderID={orderI
D}&test=1

2.6) BILLING files:


CSafe.php:
CSafe.php::check_safe is where SAFE API is called after payment proccess, when a
flashID is setted as allowed to use it (we will see how to allow a flashID bellow).
We use the function “Direct2ApiController” instead of “CRestRequest” to call the API,
because this makes it faster.
CProductBilling.php:
Here we allow flashIDs to use SAFE.

2.6.1) How add stores (flashIDs) to SAFE 2 (and/or disable them on SAFE 1):

NOTE 1: There are two “SAFE”s: SAFE 1 (used on pepita_payment v3), and SAFE 2 (the new
one). There are some stores which actually uses SAFE 1, so if you want to use SAFE 2 on them,
you have to disable them for “SAFE 1” list, and enable (allow) them on SAFE 2.
NOTE 2: ¿How to get all flash_id of a client?:
mysql> select ufm.user_id as 'User ID', ufm.project_id as 'Project ID', up.name as 'Project
Name', group_concat( ufm.flash_id ) as 'Flash ID' from user_flash_min ufm, user_project up
where ufm.user_id = {clientID} and ufm.project_id =up.project_id group by ufm.project_id;

NOTE 3: Check that FlashID you are going to use, belongs to the correct projectID.

Two steps:
DISABLE SAFE 1 FOR THIS STORE (only if already SAFE 1 usage is setted):
Note: To change it on prod: PAYMNT SERVER (anyone, but use tha same for all steps).
• /var/www/v3/pepita_payment/payment/methods/class.payment_method_optimalpa
yments.php
o Search: $array_disabled_check_safe
o Add FLASH ID (not proj_id) to the array.
• /var/www/v3/pepita_payment/payment/methods/class.payment_method_paybox.ph
p
o Search: $array_disabled_check_safe.
o Add FLASH ID (not proj_id) to the array.
• How to see on detail the payment log of an order:
o /var/www/private/{TYPE} /orders/{ORDERID}_logs.txt
o {TYPE}: paypal / optimalpayments
o And note:
entity (ie, pepita) => By default, should be “pepita”. But check in this
file.
userID (ie, 122699)
flashID (ie,233)
• /var/www/v3/pepita_payment/class/db_payment/xmls/{entity}
_{userID}_{flashID}.xml
o Find on XML file, the nodes-tree: <prod> -> <paypal> -> <credentials>
o If not exists <payer_email>disabled</payer_email> , write it (inside
<credentials> node, of course).
o If already exists, but it’s set “enabled”, change it to “disabled”.
o NOTE: You have to do this with every FLASH ID!

To sync these changes on all payment servers:


• /var/www/v3/pepita_payment/
• sudo /usr/sbin/synchro_payment.sh
ENABLE SAFE 2:
Note: To change it on prod: FRONT 3 SERVER (because this one has a good configured EMACS).
• /var/www/v4/pepita_billing/workbench/pepita/billing/src/Pepita/Billing/CProductBilli
ng.php
o Search: // Set-up allowed UID and flash_id:
o Add UID and the FLASH IDs (not proj_id) to the array.
If you write ALL on flash_ids array, code will allow all flash ids related
to his UID.

3) OTHER FILES:
3.1) Where from is sent Paypal and Maxmind info to SAFE:
PAYMNT:
/var/www/v3/pepita_payment/payment/methods/class.payment_method_optimalpayments.
php
PAYMNT:
/var/www/v3/pepita_payment/payment/notification/paypal.nip.php
PAYMNT:
/var/www/v3/pepita_payment/payment/methods/class.payment_method_paybox.php

FRONT 3 (Here is where all info retrieved on these previous files is given to Safe):
/pepita_billing/workbench/pepita/billing/src/Pepita/Billing/CSafe.php:: check_safe

NOTE: Remember, if you add new fields, use [ if (¡isset) = “ “ ], to avoid crashes (because when
doing a “release update to prod”, the payment servers are updated later than normal ones).

3.2) Phone number prefix:


• Telesign list: http://docs.telesign.com/rest/content/xt/xt-country-codes.html
• Countries (COUNTRIES_PREFIX_PHONE):
/var/www/v4/pepita_core/workbench/pepita/core/src/config/constants/countries.ph
p
• CCountries (get_prefix_phone_by_iso):
/var/www/v4/pepita_core/workbench/pepita/core/src/Pepita/Core/libraries/misc/CC
ountries.php

3.3) CCommand for Safe:


• get_safe_infos method retrieves all info needed for Safe.
• set_safe_info method saves phonenumber on table command_safe

3.4) BackOffice view:


• merchant/app/views/bootstrap/pages/orders/order/order_risk.blade.php
3.5) Safe rules specification on Redmin Wiki:
https://support.pepitastore.com/projects/pepita-methods/wiki/SAFE_rules

4) OTHER INFO:
4.1) Notes for “Safe step 0”:
4.1.1) [NOTE: This first note isn´t needed to know for this pourpose, but it´s ok to know it]:
When an API is called, the first line of each class you got a static variable $oems. On it it is set
the “Default” REST class is going to be choosen and the “ResponseDefault” REST one too (for
example, if we want a “Default” REST for Avast, we could create ”CRestSafeAvast”).

4.1.2) [NOTE: From here this is what we need to know for “SAFE STEP 0”]:
On CRestOrderDefault there is a function called “is_order_authorized”, which actually always
returns true. This is the function which we will use to make the call to SAFE 0.

In the moment this function is called, the order has been already created, but in state 0
(initiated), but it has not gone to payment process.

So, if we do in this function “return false” (passing specific SAFE rules), it will not goes to
payment => Safe step 0.

4.2) Rules nomenclature:


All rules are numbered on BackOffice. Some of them are “disabled”, so it´s possible that you
see jumps between numbers.

All rule numbers has same format: {# step}.{# rule}. So for all step 0 rules, you will see “0.1, 0.2,
0.3….”; for step 1 “1.1, 1.2, 1.3”; for step 2 “2.1, 2.2, 2.3”, etc…

4.3) Send email to NicoS when a rule is changed/added directly on prod:


You must send an email to NicoS every time you change or modify a rule directly on prod. No
need to write any on body email. When we update prod with a complete release, you don´t
need to send any email.

EXAMPLE:

Subject: Fixed in prod - [SAFE] #0000: Add Irak to risk countries.

Body: <empty>
4.4) How to perform tests on sandbox forcing different SAFE results:
NOTE: This works only in sandbox.

On “firstname” field you must put the results you want obtain for the different steps,
separated by coma. Examples:

- ok,ok => You will get OK on first step (so, 2nd will not be executed anyway)
- sms,ok => 1st step : SMS. 2nd step: OK
- sms,manual
- fraud,fraud

And for SMS verification, you have 2 options:

- Calling Telesign API (costs money): Choose “Spain” and write a real Spanish
phonenumber. Then, on SMS verification, insert the code you received on your
phone.
- NO calling Telesign API (free): Choose any other country except “Spain”, and write
the numbers you want. On SMS verification, just write the last 5 digits of number
you wrote previously.

Keep in mind, that if you NO call Telesign API, you will not receive any phone info for SAFE
rules.

4.5) SAFE logs errors:


You can see all SAFE errors submitted to RSS on:

http://log.pepitastore.com/rss/safe_error_YYYY-MM-DD.xml

4.5.1) About Telesign timeout warnings:

You can see some errors with this text:


Impossible to comunicate with Telesign API.<br> Step: Send code to
pone ( … ) Retry attempt nb: 1

This is a usual Telesign API bug, which gives us timeouts sometimes. And because of this bug,
SAFE retries 3 attempts (0.025 second between each one). So on safe logs you can see up to 3
errors showing the same error about the same orderID, just changing th text “Retry
attempt nb: {1-3} ”

Then you will see logged next 1 of these error logs too, depending if max retries (3) have been
reached and failed, or if finally it has been able to be sent:

- FAILED : Finally after 3 attempts, was impossible to communicate


with Telesign API.<br>Step: Send code to phone.
- OK : No error! Just logging: after 3 attempts trying
communication with Telesign API, it finally works.<br> Step:
Send code to phone.

So, in the case of OK it has continued normally. And in case of FAILED, customer receives an
error, to him try again.

You might also like