SMS Verify API - Implement PSD2 compliance for payments

This page walks you step-by-step through how to implement payment verification with Telesign SMS Verify API that complies with the European Union's Revised Payment Services Directive (PSD2). This includes the directive's Strong Customer Authentication (SCA) requirement; SMS Verify API helps you comply with the "Possession" part of this requirement.

Keep the reference pages POST /v1/verify/sms and GET /v1/verify/{reference_id} open in another window while you work on these steps.

📘

NOTE:

This guide assumes that Telesign is generating the verification code for you. If you prefer to generate your own code, take a look also at SMS Verify API - Verify with your own code and adapt these steps accordingly.

Before you begin

  • Upgrade your account: Upgrade to a paid account if you are using a trial account.
  • "From" phone number: You must buy a “from” phone number from Telesign before sending OTPs to any number other than the one you registered your account with.
  • (Optional) Contact our Customer Support Team to configure any of these optional features:
    • Validity period: The time duration in minutes after which a verification code expires.
    • Max attempts: The number of times an end user can submit potential matches for a specific verification code. If this number is five, for example, an end user's sixth submission is rejected, even if it matches the original code.

Step 1: Send the SMS

  1. Send a POST /verify/sms request to the SMS Verify API. Include the following param values:
ParameterValueDescriptionRequired?
phone_numberDigits without spaces or special characters.The end user’s phone number you want to send a message to, beginning with the country/dialing code.yes
transaction_amountA currency and amount.

Example: $95
Replaces the $$AMOUNT$$ variable in the message template. Specifies the currency and amount for the payment that the end user is approving.yes
transaction_payeeTextReplaces the $$PAYEE$$ variable in the message template. Specifies the entity that the end user is approving a payment to.yes
templateText with variables.Text that overrides the contents of the predefined message templates. Include the $$CODE$$ variable to have the verification code automatically inserted. Include the $$AMOUNT$$ and $$PAYEE$$ variables to have those payment details from your other params automatically inserted.no

📘

NOTE:

You can use one of Telesign's non-English (US) message templates by including the optional language parameter. To see a full list of languages for which we have PSD2/SCA templates, see Supported languages.

SMS Verify API request

POST /v1/verify/sms HTTP/1.1
Authorization: Basic 12345678-9ABC-DEF0-1234-56789ABCDEF0:Uak4fcLTTH/Tv8c/Q6QMwl5t4ck=
Content-Type: application/x-www-form-urlencoded; charset=utf-8
Host: rest-ww.telesign.com
phone_number=15558675309
&transaction_amount=$95
&transaction_payee=Viatu
&template=To confirm your payment to $$PAYEE$$ in the amount of $$AMOUNT$$ your code is $$CODE$$. Thank you for shopping with us.

📘

NOTE:

We used €95 as the example value here because PSD2’s threshold for using SCA is €30. You can choose either to perform SCA for all transactions or check whether the amount is greater than €30 first.

  1. The service then sends an SMS message, replacing the $$CODE$$ variable in the message template with a verification code, and the $$PAYEE$$ and $$AMOUNT$$ variables with your provided payment details. You include the payee and amount to comply with PSD2's requirement for dynamic linking.

A screenshot of a SMS message containing a one time passcode displayed on a phone.

  1. Save the value of the property reference_id from the response. You will need it to complete the verification flow.
  2. The status.code and status.description properties in the response indicate the preliminary delivery status of the SMS.

SMS Verify API response

HTTP/1.1 200 OK
Content-Type: application/json

{
  "reference_id": "0123456789ABCDEF0123456789ABCDEF",
  "sub_resource": "sms",
  "errors": [],
  "status": {
    "updated_on": "2015-10-03T14:51:28.709526Z",
    "code": 290,
    "description": "Message in progress"
  },
  "verify": {
    "code_state": "UNKNOWN",
    "code_entered": ""
  },
  "additional_info": {
    "message_parts_count": 1
  }
}

📘

NOTE:

The status.code property gives you status of delivery to the destination carrier, not necessarily all the way to the end-user.

Step 2: Complete verification and get delivery status

Once your end-user has submitted a potential code through your application, complete the verification flow with a second API call.

  1. Send a GET /verify/{reference_id} request.
    • Include the end-user's potential code in the verify_code query parameter.
    • Include the reference_id for the transaction in the reference_id path parameter.

Get Status request

GET /v1/verify/0123456789ABCDEF0123456789ABCDEF?verify_code=57244 HTTP/1.1
Authorization: Basic 12345678-9ABC-DEF0-1234-56789ABCDEF0:Uak4fcLTTH/Tv8c/Q6QMwl5t4ck=
Host: rest-ww.telesign.com
  1. In the response, if the value of the verify.code_state property is VALID, the verification completed successfully.
  2. The status.code and status.description properties in the payload of that response indicate the delivery status all the way to the end-user.

Get Status response

HTTP/1.1 200 OK
Content-Type: application/json

{
  "reference_id": "ABCDEF0123456789ABCDEF0123456789",
  "sub_resource": "sms",
  "errors": [],
  "status": {
    "updated_on": "2015-04-17T22:26:43.784963Z",
    "code": 201,
    "description": "Message is read"
  },
  "verify": {
    "code_state": "VALID",
    "code_entered": ""
  },
  "additional_info": {
    "code_entered": null,
    "message_parts_count": 1
  }
}
  1. If the value of the verify.code_state property is EXPIRED or MAX_ATTEMPTS_EXCEEDED, the verification code is no longer matchable by your end user. If you still want to give them the opportunity to verify, make a new SMS Verify request to send them a new verification code.

The complete Python sample code for this how-to guide can be found on GitHub.