diff --git a/src/com/telesign/util/TeleSignRequest.java b/src/com/telesign/util/TeleSignRequest.java index ba690b3..9c4e6b8 100644 --- a/src/com/telesign/util/TeleSignRequest.java +++ b/src/com/telesign/util/TeleSignRequest.java @@ -17,6 +17,9 @@ import java.net.HttpURLConnection; import java.net.URL; import java.net.URLEncoder; +import java.security.KeyManagementException; +import java.security.NoSuchAlgorithmException; +import java.security.SecureRandom; import java.security.SignatureException; import java.text.SimpleDateFormat; import java.util.Date; @@ -27,6 +30,8 @@ import java.util.TreeMap; import javax.crypto.Mac; import javax.crypto.spec.SecretKeySpec; +import javax.net.ssl.HttpsURLConnection; +import javax.net.ssl.SSLContext; import org.apache.commons.codec.binary.Base64; @@ -320,7 +325,8 @@ public String executeRequest() throws IOException { connection.setConnectTimeout(connectTimeout); connection.setReadTimeout(readTimeout); connection.setRequestProperty("Authorization", auth_header); - + setTLSProtocol(); + if (post) { connection.setRequestProperty("Content-Length", Integer.toString(body.length())); @@ -365,7 +371,6 @@ public String executeRequest() throws IOException { in.close(); } catch (IOException e) { - System.err.println("IOException while reading from input stream " + e.getMessage()); } @@ -497,4 +502,26 @@ private String encode(String data, String key) throws java.security.SignatureEx return result; } + + /** + * Set the TLS protocol to TLSv1.2 + */ + private void setTLSProtocol() { + SSLContext sslContext; + try { + // setting ssl instance to TLSv1.2 + sslContext = SSLContext.getInstance("TLSv1.2"); + + // sslContext initialize + sslContext.init(null,null,new SecureRandom()); + + // typecasting ssl with HttpsUrlConnection and setting sslcontext + ((HttpsURLConnection)connection).setSSLSocketFactory(sslContext.getSocketFactory()); + } catch (NoSuchAlgorithmException e1) { + System.err.println("Error signing request " + e1.getMessage()); + } + catch (KeyManagementException e) { + System.err.println("Error signing request " + e.getMessage()); + } + } } diff --git a/src/com/telesign/verify/Verify.java b/src/com/telesign/verify/Verify.java index 3d680b2..5ad533d 100644 --- a/src/com/telesign/verify/Verify.java +++ b/src/com/telesign/verify/Verify.java @@ -15,6 +15,8 @@ import com.telesign.verify.response.VerifyResponse; import java.io.IOException; import java.net.URLEncoder; +import java.util.regex.Matcher; +import java.util.regex.Pattern; /** * The Verify class abstracts your interactions with the TeleSign Verify web service. @@ -27,6 +29,8 @@ public class Verify { private int connectTimeout = 30000; private int readTimeout = 30000; + private final Gson gson = new Gson(); + /** * The Verify class constructor. * Once you instantiate a Verify object, you can use it to make instance calls to Verify SMS and Verify Call. @@ -157,10 +161,9 @@ public VerifyResponse sms(String phone_number, String language, String verify_co } catch (IOException e) { - System.err.println("IOException while executing phoneid API: " + e.getMessage()); + System.err.println("IOException while executing Verify SMS API: " + e.getMessage()); } - Gson gson = new Gson(); VerifyResponse response = gson.fromJson(result, VerifyResponse.class); return response; @@ -174,7 +177,7 @@ public VerifyResponse sms(String phone_number, String language, String verify_co */ public VerifyResponse call(String phone_number) { - return call(phone_number, null, null, null, 0, null, true, null, null); + return call(phone_number, null, null, null, 0, null, true, null, null, null); } /** @@ -186,9 +189,9 @@ public VerifyResponse call(String phone_number) { */ public VerifyResponse call(String phone_number, String language) { - return call(phone_number, language, null, null, 0, null, true, null, null); + return call(phone_number, language, null, null, 0, null, true, null, null, null); } - + /** * Delivers a verification code to the end user with a phone call. When the user answers their phone, the TeleSign server plays an automated voice message that contains the code. * Use this overload when the user's native spoken language is not the default language (English). You specify the user's language in the language parameter. @@ -202,7 +205,24 @@ public VerifyResponse call(String phone_number, String language) { */ public VerifyResponse call(String phone_number, String language, String originating_ip, String session_id) { - return call(phone_number, language, null, null, 0, null, true, originating_ip, session_id); + return call(phone_number, language, null, null, 0, null, true, originating_ip, session_id, null); + } + + /** + * Delivers a verification code to the end user with a phone call. When the user answers their phone, the TeleSign server plays an automated voice message that contains the code. + * Use this overload when the user's native spoken language is not the default language (English). You specify the user's language in the language parameter. + * @param phone_number [Required] A string containing the user�s phone number. + * @param language [Optional] A string containing the IETF language tag. For example, "fr-CA". Set this value to "null" to use English (the default). + * @param originating_ip [Optional] Your end users IP Address. This value must be in the format defined by IETF in the + * Internet-Draft document titled Textual Representation of IPv4 and IPv6 Addresses. Ex: originating_ip=192.168.123.456. + * Set it to null if not sending originating ip. + * @param session_id [Optional] Your end users session id. Set it to "null" if not sending session id. + * @param call_forward_action [Optional] A string containing call forward action + * @return A {@link com.telesign.verify.response.VerifyResponse} object, which contains the JSON-formatted response body from the TeleSign server. + */ + public VerifyResponse call(String phone_number, String language, String originating_ip, String session_id, String call_forward_action) { + + return call(phone_number, language, null, null, 0, null, true, originating_ip, session_id, call_forward_action); } /** @@ -221,13 +241,15 @@ public VerifyResponse call(String phone_number, String language, String originat * @param extension_type [Optional] An Integer value representing the type of response to use when dialing into a Private Branch Exchange (PBX). Use a value of 1 to have TeleSign use Dual-Tone Multi-Frequency (DTMF) tones to dail the user's extension. Use a value of 2 to have TeleSign use voice automation to request the user's extension. Use a value of 0 (the default) when the user isn't behind a PBX. * @param extension_template [Optional] A numerical string specifying the user's PBX extension number. Since this value is used in the call string, you can include one second pauses by adding commas before the extension number. Set this value to null (the default) if not used. * @param redial [Optional] A boolean value that enables/disables redialing. Set this value to "true" (the default) when you want TeleSign to re-attempt the call after a failed attempt. Set this value to "false" when you don't. - * @param originating_ip [Optional] Your end users IP Address. This value must be in the format defined by IETF in the - * Internet-Draft document titled Textual Representation of IPv4 and IPv6 Addresses. Ex: originating_ip=192.168.123.456. - * Set it to null if not sending originating ip. - * @param session_id [Optional] Your end users session id. Set it to "null" if not sending session id. + * @param originating_ip [Optional] Your end users IP Address. This value must be in the format defined by IETF in the + * Internet-Draft document titled Textual Representation of IPv4 and IPv6 Addresses. Ex: originating_ip=192.168.123.456. + * Set it to null if not sending originating ip. + * @param session_id [Optional] Your end users session id. Set it to "null" if not sending session id. + * @param call_forward_action [Optional] A string containing call forward action * @return A {@link com.telesign.verify.response.VerifyResponse} object, which contains the JSON-formatted response body from the TeleSign server. */ - public VerifyResponse call(String phone_number , String language, String verify_code, String verify_method, int extension_type, String extension_template, boolean redial, String originating_ip, String session_id) { + public VerifyResponse call(String phone_number , String language, String verify_code, String verify_method, int extension_type, String extension_template, boolean redial, + String originating_ip, String session_id, String call_forward_action) { String result = null; @@ -272,15 +294,24 @@ public VerifyResponse call(String phone_number , String language, String verify_ body += "&redial=" + URLEncoder.encode(Boolean.toString(redial), "UTF-8"); } + if(null != call_forward_action && "block".equalsIgnoreCase(call_forward_action)) { + + body += "&call_forward_action=" + URLEncoder.encode("Block", "UTF-8"); + + } else if(null != call_forward_action && "flag".equalsIgnoreCase(call_forward_action) ) { + + body += "&call_forward_action=" + URLEncoder.encode("Flag", "UTF-8"); + + } + tr.setPostBody(body); result = tr.executeRequest(); } catch (IOException e) { - System.err.println("IOException while executing phoneid API: " + e.getMessage()); + System.err.println("IOException while executing verify call API: " + e.getMessage()); } - Gson gson = new Gson(); VerifyResponse response = gson.fromJson(result, VerifyResponse.class); return response; @@ -297,7 +328,7 @@ public VerifyResponse status(String resource_id) { return status(resource_id, null); } - + /** * Requests the verification result from TeleSign. * After sending an end user a verification code, wait a minute or two to allow them to receive it and then respond, and then call this method to find out if the end user passed the code challenge. @@ -307,6 +338,22 @@ public VerifyResponse status(String resource_id) { * @return A {@link com.telesign.verify.response.VerifyResponse} object, which contains the JSON-formatted response body from the TeleSign server. */ public VerifyResponse status(String resource_id, String verify_code) { + return status(resource_id, verify_code, null, null); + } + + /** + * Requests the verification result from TeleSign. + * After sending an end user a verification code, wait a minute or two to allow them to receive it and then respond, and then call this method to find out if the end user passed the code challenge. + * This method takes only one parameter�the ID of this particular web service transaction. + * @param resource_id [Required] The string returned in the Response Message that TeleSign sends upon receipt of your HTTP 1.1 Request Message - for either {@link com.telesign.verify#sms()} or {@link com.telesign.verify#call()}. + * @param verify_code [Required] The verification code received from the user. + * @param originating_ip [Optional] Your end users IP Address. This value must be in the format defined by IETF in the + * Internet-Draft document titled Textual Representation of IPv4 and IPv6 Addresses. Ex: originating_ip=192.168.123.456. + * Set it to null if not sending originating ip. + * @param session_id [Optional] Your end users session id. Set it to "null" if not sending session id. + * @return A {@link com.telesign.verify.response.VerifyResponse} object, which contains the JSON-formatted response body from the TeleSign server. + */ + public VerifyResponse status(String resource_id, String verify_code, String originating_ip, String session_id) { String result = null; @@ -316,59 +363,58 @@ public VerifyResponse status(String resource_id, String verify_code) { if (verify_code != null) tr.addParam("verify_code", verify_code); + + if(originating_ip != null && !originating_ip.isEmpty() && IpValidator.isValidIpAddress(originating_ip)) { + + tr.addParam("originating_ip", originating_ip); + } + + if(session_id != null && !session_id.isEmpty()) { + + tr.addParam("session_id", session_id); + } result = tr.executeRequest(); } catch (IOException e) { - System.err.println("IOException while executing phoneid API: " + e.getMessage()); + System.err.println("IOException while executing Verify status API: " + e.getMessage()); } - Gson gson = new Gson(); VerifyResponse response = gson.fromJson(result, VerifyResponse.class); return response; - } - + } + /** - * Requests the verification result from TeleSign. - * After sending an end user a verification code, wait a minute or two to allow them to receive it and then respond, and then call this method to find out if the end user passed the code challenge. - * This method takes only one parameter�the ID of this particular web service transaction. - * @param resource_id [Required] The string returned in the Response Message that TeleSign sends upon receipt of your HTTP 1.1 Request Message - for either {@link com.telesign.verify#sms()} or {@link com.telesign.verify#call()}. - * @param originating_ip [Optional] Your end users IP Address. This value must be in the format defined by IETF in the - * Internet-Draft document titled Textual Representation of IPv4 and IPv6 Addresses. Ex: originating_ip=192.168.123.456. - * Set it to null if not sending originating ip. - * @param session_id [Optional] Your end users session id. Set it to "null" if not sending session id. - * @return A {@link com.telesign.verify.response.VerifyResponse} object, which contains the JSON-formatted response body from the TeleSign server. + * @param phone_number [Required] Your end user’s phone number, including the country code. + * @param bundle_id [Required] + * @return A {@link com.telesign.verify.response.VerifyResponse} object, which contains the JSON-formatted response body from the TeleSign server. */ - public VerifyResponse status(String resource_id, String originating_ip, String session_id) { - - return status(resource_id, null, originating_ip, session_id); + public VerifyResponse registration(String phone_number, String bundle_id){ + return registration(phone_number, bundle_id, null, null); } /** - * Requests the verification result from TeleSign. - * After sending an end user a verification code, wait a minute or two to allow them to receive it and then respond, and then call this method to find out if the end user passed the code challenge. - * This method takes only one parameter�the ID of this particular web service transaction. - * @param resource_id [Required] The string returned in the Response Message that TeleSign sends upon receipt of your HTTP 1.1 Request Message - for either {@link com.telesign.verify#sms()} or {@link com.telesign.verify#call()}. - * @param verify_code [Required] The verification code received from the user. - * @param originating_ip [Optional] Your end users IP Address. This value must be in the format defined by IETF in the - * Internet-Draft document titled Textual Representation of IPv4 and IPv6 Addresses. Ex: originating_ip=192.168.123.456. - * Set it to null if not sending originating ip. - * @param session_id [Optional] Your end users session id. Set it to "null" if not sending session id. - * @return A {@link com.telesign.verify.response.VerifyResponse} object, which contains the JSON-formatted response body from the TeleSign server. + * @param phone_number [Required] Your end user’s phone number, including the country code. + * @param bundle_id [optional] The identifier associated with your whitelabel app (your customized/branded version of the AuthID application). + * @param originating_ip [Optional] Your end users IP Address. This value must be in the format defined by IETF in the + * Internet-Draft document titled Textual Representation of IPv4 and IPv6 Addresses. Ex: originating_ip=192.168.123.456. + * Set it to null if not sending originating ip. + * @param session_id [Optional] Your end users session id. Set it to "null" if not sending session id. + * @return A {@link com.telesign.verify.response.VerifyResponse} object, which contains the JSON-formatted response body from the TeleSign server. */ - public VerifyResponse status(String resource_id, String verify_code, String originating_ip, String session_id) { - + public VerifyResponse registration(String phone_number, String bundle_id, String originating_ip, String session_id){ String result = null; - + try { + TeleSignRequest tr = new TeleSignRequest("https://rest-mobile.telesign.com", "/v2/verify/registration/" + phone_number, "GET", customer_id, secret_key, connectTimeout, readTimeout); + + if(null != bundle_id && !bundle_id.isEmpty()) { - TeleSignRequest tr = new TeleSignRequest("https://rest.telesign.com", "/v1/verify/" + resource_id, "GET", customer_id, secret_key, connectTimeout, readTimeout); + tr.addParam("bundle_id", bundle_id); + } - if (verify_code != null) - tr.addParam("verify_code", verify_code); - if(originating_ip != null && !originating_ip.isEmpty() && IpValidator.isValidIpAddress(originating_ip)) { tr.addParam("originating_ip", originating_ip); @@ -378,17 +424,265 @@ public VerifyResponse status(String resource_id, String verify_code, String orig tr.addParam("session_id", session_id); } + + result = tr.executeRequest(); + } + catch (IOException e) { + + System.err.println("IOException while executing verify registration API: " + e.getMessage()); + } + + VerifyResponse response = gson.fromJson(result, VerifyResponse.class); + + return response; + } + + /** + * @param phone_number [Required] Your end user’s phone number, including the country code. + * @param ucid [Required] A string the specifies one of the Use Case Codes. + * @return A {@link com.telesign.verify.response.VerifyResponse} object, which contains the JSON-formatted response body from the TeleSign server. + */ + public VerifyResponse smartVerify(String phone_number, String ucid, String caller_id, String language, String verify_code, String preference, String ignore_risk){ + return smartVerify(phone_number, ucid, caller_id, language, verify_code, preference, ignore_risk, null, null); + } + + /** + * @param phone_number [Required] Your end user’s phone number, including the country code. + * @param ucid [Required] A string the specifies one of the Use Case Codes. + * @param caller_id [Optional] End user’s caller ID if available. Used for Verify SMS and Verify Call transations, but is ignored for Verify Push transactions. + * @param language [Optional] Determines the message for Verify SMS and Verify Push. IETF language tag is used in mapping languages codes to predefined templates. + * For Verify Voice, the language determines the set of audio files to play for the call.
For a complete list of language tags, see Supported Languages. + * @param verify_code [Optional] The verification code used for the code challenge. By default, TeleSign automatically generates a six-digit value for you. + *
If you prefer to use your own verification code, you can override the default behavior by including this parameter and giving it an all-digit string value (0-9 in Latin-1), with the length as specified by your selected TeleSign settings. + *
Leading zeros are recognized, and therefore should be used accordingly. + * @param preference [Optional] Allows customers to override the Smart Verify method selection. Customers can specify either “call”, “sms” or “push” to be the recommended method to attempt. + *
Since not all methods are supported on all devices, TeleSign may ignore the selected override method, in order to provide the method that is most appropriate, in which case Telesign selects the method in the order of “push”, “sms”, and “call”. + * @param ignore_risk [Optional] If set to “true”, allows customers to bypass blocking the request if the score is above the threshold value configured in the customer account. + * @param originating_ip [Optional] Your end users IP Address. This value must be in the format defined by IETF in the Internet-Draft document titled Textual Representation of IPv4 and IPv6 Addresses. + *
Ex: originating_ip=192.168.123.456.
Set it to null if not sending originating ip. + * @param session_id [Optional] Your end users session id. Set it to "null" if not sending session id. + * @return A {@link com.telesign.verify.response.VerifyResponse} object, which contains the JSON-formatted response body from the TeleSign server. + */ + public VerifyResponse smartVerify(String phone_number, String ucid, String caller_id, String language, String verify_code, String preference, String ignore_risk, String originating_ip, String session_id){ + String result = null; + + try { + + TeleSignRequest tr = new TeleSignRequest("https://rest.telesign.com", "/v1/verify/smart", "POST", customer_id, secret_key, connectTimeout, readTimeout); + String body = "phone_number=" + URLEncoder.encode(phone_number, "UTF-8"); + + if(null != ucid) { + + body += "&ucid=" + URLEncoder.encode(ucid, "UTF-8"); + } + + if(null != caller_id) { + + body += "&caller_id=" + URLEncoder.encode(caller_id, "UTF-8"); + } + + if(null != language) { + + body += "&language=" + URLEncoder.encode(language, "UTF-8"); + } + + if(null != verify_code) { + + body += "&verify_code=" + URLEncoder.encode(verify_code, "UTF-8"); + } + + if(null != preference) { + + body += "&preference=" + URLEncoder.encode(preference, "UTF-8"); + } + + if(null != ignore_risk) { + + body += "&ignore_risk=" + URLEncoder.encode(ignore_risk, "UTF-8"); + } + + if(null != originating_ip && !originating_ip.isEmpty() && IpValidator.isValidIpAddress(originating_ip)) { + + body += "&originating_ip=" + URLEncoder.encode(originating_ip, "UTF-8"); + } + if(null != session_id && !session_id.isEmpty()) { + + body += "&session_id=" + URLEncoder.encode(session_id, "UTF-8"); + } + tr.setPostBody(body); result = tr.executeRequest(); } catch (IOException e) { - System.err.println("IOException while executing phoneid API: " + e.getMessage()); + System.err.println("IOException while executing smart verify API: " + e.getMessage()); + } + + VerifyResponse response = gson.fromJson(result, VerifyResponse.class); + + return response; + } + + /** + * @param phone_number [Required] The phone number of the mobile device that you want to send push notifications to. + * The phone number must include its associated country code (1 for North America). + * For example, phone_number=13105551212. + * @param bundle_id [Required] Specifies a custom banner and icon for the TeleSign AuthID application to use for this notification. + * This allows you to brand your notifications with your corporate logo and/or your service-specific branding. + * [Examples] template=mobile_2fa, or template=Outlook-2FA + * @return A {@link com.telesign.verify.response.VerifyResponse} object, which contains the JSON-formatted response body from the TeleSign server. + */ + public VerifyResponse push(String phone_number, String bundle_id){ + return push(phone_number, null, null, bundle_id, null, null, null); + } + + /** + * @param phone_number [Required] The phone number of the mobile device that you want to send push notifications to. + * The phone number must include its associated country code (1 for North America). + * For example, phone_number=13105551212. + * @param notification_type [Optional] Indicates the security measure to use for transaction authorization. Valid values are SIMPLE and CODE. + * The default value is SIMPLE. + * @param notification_value [Optional] Applies when notification_type=CODE.You normally leave this parameter empty, + * and accept the default behavior in which TeleSign automatically generates a six-digit value for you, + * and sends it to you in our response message. If you’d prefer to use your own verification code, + * you can override the default behavior by setting a numeric value for this parameter. + * Values must be between six and eight digits long. [Default] is null. + * @param bundle_id [Required] Specifies a custom banner and icon for the TeleSign AuthID application to use for this notification. + * This allows you to brand your notifications with your corporate logo and/or your service-specific branding. + * [Examples] template=mobile_2fa, or template=Outlook-2FA + * @param message [Optional] The message to display to the end user, in the body of the notification. + * If you don’t include this parameter, then TeleSign automatically supplies the default message. + * [Example] message=Enter the code displayed on our web site.[Default] is null. + * @param originating_ip [Optional] Your end users IP Address. This value must be in the format defined by IETF in the + * Internet-Draft document titled Textual Representation of IPv4 and IPv6 Addresses. Ex: originating_ip=192.168.123.456. + * Set it to null if not sending originating ip. + * @param session_id [Optional] Your end users session id. Set it to "null" if not sending session id. + * @return A {@link com.telesign.verify.response.VerifyResponse} object, which contains the JSON-formatted response body from the TeleSign server. + */ + public VerifyResponse push(String phone_number, String notification_type, String notification_value, String bundle_id, String message, + String originating_ip, String session_id){ + String result = null; + + try { + TeleSignRequest tr = new TeleSignRequest("https://rest-mobile.telesign.com", "/v2/verify/push", "POST", customer_id, secret_key, connectTimeout, readTimeout); + String body = "phone_number=" + URLEncoder.encode(phone_number, "UTF-8"); + + if(null == notification_type || notification_type.isEmpty()){ + + notification_type = "SIMPLE"; + body += "¬ification_type=" + URLEncoder.encode(notification_type, "UTF-8"); + + } else if("CODE".equalsIgnoreCase(notification_type)) { + + body += "¬ification_type=" + URLEncoder.encode(notification_type.toUpperCase(), "UTF-8"); + body += "¬ification_value=" + URLEncoder.encode(isValidNotificationValue(notification_value)?notification_value:null, "UTF-8"); + } + + if(null != bundle_id) { + + body += "&bundle_id=" + URLEncoder.encode(bundle_id, "UTF-8"); + } + + if(null != message) { + + body += "&message=" + URLEncoder.encode(message, "UTF-8"); + } + + if(null != originating_ip && !originating_ip.isEmpty() && IpValidator.isValidIpAddress(originating_ip)) { + + body += "&originating_ip=" + URLEncoder.encode(originating_ip, "UTF-8"); + } + if(null != session_id && !session_id.isEmpty()) { + + body += "&session_id=" + URLEncoder.encode(session_id, "UTF-8"); + } + + tr.setPostBody(body); + result = tr.executeRequest(); } + catch (IOException e) { + + System.err.println("IOException while executing Verify push API: " + e.getMessage()); + } - Gson gson = new Gson(); VerifyResponse response = gson.fromJson(result, VerifyResponse.class); return response; - } + } + + /** + * @param phone_number [Required] The phone number for the Verify Soft Token request, including country code. For example, phone_number=13105551212. + * @param verify_code [Required] The verification code received from the end user. + * @return A {@link com.telesign.verify.response.VerifyResponse} object, which contains the JSON-formatted response body from the TeleSign server. + */ + public VerifyResponse softToken(String phone_number, String soft_token_id, String verify_code, String bundle_id){ + return softToken( phone_number, soft_token_id, verify_code, bundle_id, null, null); + } + + /** + * @param phone_number [Required] The phone number for the Verify Soft Token request, including country code. For example, phone_number=13105551212. + * @param soft_token_id [Optional] The alphanumeric string that uniquely identifies your TeleSign soft token subscription. + * @param verify_code [Required] The verification code received from the end user. + * @param bundle_id [Optional] + * @param originating_ip [Optional] Your end users IP Address. This value must be in the format defined by IETF in the + * Internet-Draft document titled Textual Representation of IPv4 and IPv6 Addresses. Ex: originating_ip=192.168.123.456. + * Set it to null if not sending originating ip. + * @param session_id [Optional] Your end users session id. Set it to "null" if not sending session id. + * @return A {@link com.telesign.verify.response.VerifyResponse} object, which contains the JSON-formatted response body from the TeleSign server. + */ + public VerifyResponse softToken(String phone_number, String soft_token_id, String verify_code, String bundle_id, String originating_ip, String session_id){ + String result = null; + + try { + TeleSignRequest tr = new TeleSignRequest("https://rest-mobile.telesign.com", "/v2/verify/soft_token", "POST", customer_id, secret_key, connectTimeout, readTimeout); + String body = "phone_number=" + URLEncoder.encode(phone_number, "UTF-8"); + + if(null != soft_token_id) { + + body += "&soft_token_id=" + URLEncoder.encode(soft_token_id, "UTF-8"); + } + + if(null != verify_code) { + + body += "&verify_code=" + URLEncoder.encode(verify_code, "UTF-8"); + } + + if(null != bundle_id) { + + body += "&bundle_id=" + URLEncoder.encode(bundle_id, "UTF-8"); + } + + if(null != originating_ip && !originating_ip.isEmpty() && IpValidator.isValidIpAddress(originating_ip)) { + + body += "&originating_ip=" + URLEncoder.encode(originating_ip, "UTF-8"); + } + + if(null != session_id && !session_id.isEmpty()) { + + body += "&session_id=" + URLEncoder.encode(session_id, "UTF-8"); + } + + tr.setPostBody(body); + result = tr.executeRequest(); + } + catch (IOException e) { + System.err.println("IOException while executing Verify soft token API: " + e.getMessage()); + } + + VerifyResponse response = gson.fromJson(result, VerifyResponse.class); + + return response; + } + /** + * Matches the notification_value for a string having 6-8 digits + * @param notification_value + * @return boolean value checking validity for notification_value + */ + private boolean isValidNotificationValue(String notification_value){ + if(null != notification_value){ + final Matcher m = Pattern.compile("\\d{6,8}").matcher(notification_value); + return m.matches(); + } else + return false; + } } diff --git a/src/com/telesign/verify/response/VerifyResponse.java b/src/com/telesign/verify/response/VerifyResponse.java index 7ca830c..b32f4b6 100644 --- a/src/com/telesign/verify/response/VerifyResponse.java +++ b/src/com/telesign/verify/response/VerifyResponse.java @@ -27,10 +27,22 @@ public class VerifyResponse { /** An object containing details about the request status. */ public Status status; + + /** An object that describes aspects of the user’s phone. */ + public Device device; + + /** An object that identifies your whitelabel app (customized/branded version of our AuthID application). */ + public App app; + /** An object that describes the call forwarding status. */ + public Call_forwarding call_forwarding; + /** An object that describes the verification status. */ public Verify verify; + /** An object that describes the user’s verification response. */ + public UserResponse user_response; + /** An array of property-value pairs, that contain information on error conditions that might have resulted from the Request. */ public static class Error { @@ -40,7 +52,7 @@ public static class Error /** A string that describes the type of error that occurred. If no error occurs, this parameter is empty. */ public String description; } - + /** An object containing details about the request status. */ public static class Status { @@ -50,10 +62,46 @@ public static class Status { /** One of the Transaction Status Codes. */ public int code; - /** A descriptionm of the transaction status. */ + /** A description of the transaction status. */ public String description; } + /** An object that describes aspects of the user’s phone. */ + public static class Device { + + /** The user’s phone number, prefixed with the Country Dialing Code. */ + public String phone_number; + + /** The name of the mobile operating system running on the phone. */ + public String operating_system; + + /** The IETF Language Tag corresponding to the user’s written language, as they have configured it on their phone (in Language Setting). */ + public String language; + } + + /** An object that describes aspects of the user’s phone. */ + public static class App { + + /** The TeleSign-assigned ID associated with your whitelabel app. */ + public String signature; + + /** A timestamp value indicating when your whitelabel app was activated by TeleSign. */ + public String created_on_utc; + + } + + /** + * An object that describes the Call_forwarding status. + */ + public static class Call_forwarding { + + /** A string value that indicates FLAG or BLOCK */ + public String action; + + /** Returns the following values: FORWARDED, NOT FORWARDED, UNAVAILABLE and UNSUPPORTED.. */ + public String call_forward; + } + /** An object that describes the verification status. */ public static class Verify { @@ -62,8 +110,22 @@ public static class Verify { /** Always set to an empty string. */ public String code_entered; + + /** In case of code challenge, contains the verification code presented to the user otherwise contains null if Simple push verification. */ + public String code_expected; } - + + /** An object that describes the user’s verification response. */ + public static class UserResponse{ + /** A timestamp marking the time when TeleSign received the user’s verification response. */ + public String received; + /** The pass code returned from the user. */ + public String verification_code; + /** Indicates the user’s intention, as selected from three choices. Possible values are ALLOWED, DENIED, and REPORTED_FRAUD. */ + public String selection; + + } + /** * Converts a VerifyResponse object to its equivalent JSON format. * @see java.lang.Object#toString() diff --git a/test/com/telesign/VerifyTest.java b/test/com/telesign/VerifyTest.java index 3c55a61..7d41d2e 100644 --- a/test/com/telesign/VerifyTest.java +++ b/test/com/telesign/VerifyTest.java @@ -26,6 +26,7 @@ public class VerifyTest { public static String CUSTOMER_ID; public static String SECRET_KEY; public static String PHONE_NUMBER; + public static String CALLER_ID; public static String CONNECT_TIMEOUT; public static String READ_TIMEOUT; public static int readTimeout; @@ -33,6 +34,13 @@ public class VerifyTest { public static boolean timeouts = false; public static String ORIGINATING_IP; public static String SESSION_ID; + public static String SMART_VERIFY_PREFERENCE; + public static String SMART_VERIFY_IGNORE_RISK; + public static String PUSH_NOTIFICATION_TYPE; + public static String PUSH_NOTIFICATION_VALUE; + public static String SOFT_TOKEN_ID; + public static String CALL_FORWARD_ACTION; + public static String BUNDLE_ID; @BeforeClass public static void setUp() throws IOException { @@ -52,6 +60,14 @@ public static void setUp() throws IOException { READ_TIMEOUT = props.getProperty("test.readtimeout"); ORIGINATING_IP = props.getProperty("test.originating_ip"); SESSION_ID = props.getProperty("test.session_id"); + SMART_VERIFY_PREFERENCE=props.getProperty("test.smart_verify_preference"); + SMART_VERIFY_IGNORE_RISK=props.getProperty("test.smart_verify_ignore_risk"); + PUSH_NOTIFICATION_TYPE=props.getProperty("test.push_notification_type"); + PUSH_NOTIFICATION_VALUE=props.getProperty("test.push_notification_value"); + SOFT_TOKEN_ID = props.getProperty("test.soft_token_id"); + CALL_FORWARD_ACTION = props.getProperty("test.call_forward_action"); + CALLER_ID = props.getProperty("test.caller_id"); + BUNDLE_ID = props.getProperty("test.bundle_id"); boolean pass = true; @@ -90,6 +106,51 @@ public static void setUp() throws IOException { pass = true; } + if(null == SMART_VERIFY_PREFERENCE || SMART_VERIFY_PREFERENCE.isEmpty()) { + System.out.println("SMART_VERIFY_PREFERENCE not set. Please set the \"test.smart_verify_preference\" property in the properties file"); + pass = true; + } + + if(null == SMART_VERIFY_IGNORE_RISK || SESSION_ID.isEmpty()) { + System.out.println("SMART_VERIFY_IGNORE_RISK not set. Please set the \"test.smart_verify_ignore_risk\" property in the properties file"); + pass = true; + } + + if(null == CALL_FORWARD_ACTION || CALL_FORWARD_ACTION.isEmpty()) { + System.out.println("CALL_FORWARD_ACTION not set. Please set the \"test.call_forward_action\" property in the properties file"); + pass = true; + } + + if(null == CALLER_ID || CALLER_ID.isEmpty()) { + System.out.println("CALLER_ID not set. Please set the \"test.caller_id\" property in the properties file"); + pass = true; + } + + if(null == PUSH_NOTIFICATION_TYPE || PUSH_NOTIFICATION_TYPE.isEmpty()) { + System.out.println("PUSH_NOTIFICATION_TYPE not set. Please set the \"test.push_notification_type\" property in the properties file"); + pass = true; + } + + if(null == PUSH_NOTIFICATION_VALUE || PUSH_NOTIFICATION_VALUE.isEmpty()) { + System.out.println("PUSH_NOTIFICATION_VALUE not set. Please set the \"test.push_notification_value\" property in the properties file"); + pass = true; + } + + if(null == SOFT_TOKEN_ID || SOFT_TOKEN_ID.isEmpty()) { + System.out.println("SOFT_TOKEN_ID not set. Please set the \"test.soft_token_id\" property in the properties file"); + pass = true; + } + + if(null == CALL_FORWARD_ACTION || CALL_FORWARD_ACTION.isEmpty()) { + System.out.println("CALL_FORWARD_ACTION not set. Please set the \"test.call_forward_action\" property in the properties file"); + pass = true; + } + + if(null == BUNDLE_ID || BUNDLE_ID.isEmpty()) { + System.out.println("BUNDLE_ID not set. Please set the \"test.bundle_id\" property in the properties file"); + pass = true; + } + if(!pass) { fail("Configuration file not setup correctly!"); } @@ -141,6 +202,22 @@ public void verifyRequestCallWithLanguage() { assertTrue(ret.errors.length == 0); } + @Test + public void verifyRequestCallWithCallForwardAction() { + if(CUSTOMER_ID.isEmpty() || SECRET_KEY.isEmpty() || PHONE_NUMBER.isEmpty()) { + fail("CUSTOMER_ID, SECRET_KEY and PHONE_NUMBER must be set to pass this test"); + } + Verify ver; + if(!timeouts) + ver = new Verify(CUSTOMER_ID, SECRET_KEY); + else + ver = new Verify(CUSTOMER_ID, SECRET_KEY, connectTimeout, readTimeout); + + VerifyResponse ret = ver.call(PHONE_NUMBER, "en-US", ORIGINATING_IP, SESSION_ID, CALL_FORWARD_ACTION); + assertNotNull(ret); + assertTrue(ret.errors.length == 0); + } + @Test public void verifyRequestCallWithAllParams() { if(CUSTOMER_ID.isEmpty() || SECRET_KEY.isEmpty() || PHONE_NUMBER.isEmpty()) { @@ -152,7 +229,7 @@ public void verifyRequestCallWithAllParams() { else ver = new Verify(CUSTOMER_ID, SECRET_KEY, connectTimeout, readTimeout); - VerifyResponse ret = ver.call(PHONE_NUMBER, "en-US", "12345", "keypress", 1, "1234", true, ORIGINATING_IP, SESSION_ID); + VerifyResponse ret = ver.call(PHONE_NUMBER, "en-US", "12345", "keypress", 1, "1234", true, ORIGINATING_IP, SESSION_ID, CALL_FORWARD_ACTION); assertNotNull(ret); assertTrue(ret.errors.length == 0); } @@ -276,4 +353,140 @@ public void verifyRequestSMSwithVerifyCode() { assertTrue(ret2.errors.length == 0); assertTrue(ret2.verify.code_state.equals("VALID")); } + + @Test + public void verifyRequestPush(){ + if(CUSTOMER_ID.isEmpty() || SECRET_KEY.isEmpty() || PHONE_NUMBER.isEmpty()) { + fail("CUSTOMER_ID, SECRET_KEY and PHONE_NUMBER must be set to pass this test"); + } + + Verify ver; + if(!timeouts) + ver = new Verify(CUSTOMER_ID, SECRET_KEY); + else + ver = new Verify(CUSTOMER_ID, SECRET_KEY, connectTimeout, readTimeout); + + VerifyResponse ret = ver.push(PHONE_NUMBER,BUNDLE_ID); + assertNotNull(ret); + assertTrue(ret.errors.length == 0); + } + + @Test + public void verifyRequestPushWithAllParams(){ + if(CUSTOMER_ID.isEmpty() || SECRET_KEY.isEmpty() || PHONE_NUMBER.isEmpty()) { + fail("CUSTOMER_ID, SECRET_KEY and PHONE_NUMBER must be set to pass this test"); + } + + Verify ver; + if(!timeouts) + ver = new Verify(CUSTOMER_ID, SECRET_KEY); + else + ver = new Verify(CUSTOMER_ID, SECRET_KEY, connectTimeout, readTimeout); + + VerifyResponse ret = ver.push(PHONE_NUMBER, PUSH_NOTIFICATION_TYPE, PUSH_NOTIFICATION_VALUE, BUNDLE_ID, "Verify request push", ORIGINATING_IP, SESSION_ID); + assertNotNull(ret); + assertTrue(ret.errors.length == 0); + } + + @Test + public void verifyRequestSoftToken(){ + if(CUSTOMER_ID.isEmpty() || SECRET_KEY.isEmpty() || PHONE_NUMBER.isEmpty()) { + fail("CUSTOMER_ID, SECRET_KEY and PHONE_NUMBER must be set to pass this test"); + } + + Verify ver; + if(!timeouts) + ver = new Verify(CUSTOMER_ID, SECRET_KEY); + else + ver = new Verify(CUSTOMER_ID, SECRET_KEY, connectTimeout, readTimeout); + + VerifyResponse ret = ver.softToken(PHONE_NUMBER, SOFT_TOKEN_ID, "571591", BUNDLE_ID); + assertNotNull(ret); + assertTrue(ret.errors.length == 0); + } + + @Test + public void verifyRequestSoftTokenWithAllParams(){ + if(CUSTOMER_ID.isEmpty() || SECRET_KEY.isEmpty() || PHONE_NUMBER.isEmpty()) { + fail("CUSTOMER_ID, SECRET_KEY and PHONE_NUMBER must be set to pass this test"); + } + + Verify ver; + if(!timeouts) + ver = new Verify(CUSTOMER_ID, SECRET_KEY); + else + ver = new Verify(CUSTOMER_ID, SECRET_KEY, connectTimeout, readTimeout); + VerifyResponse ret = ver.softToken(PHONE_NUMBER, SOFT_TOKEN_ID, "928417", BUNDLE_ID, ORIGINATING_IP, SESSION_ID); + System.out.println("verifyRequestSoftTokenWithAllParams response: " + ret.toString()); // To Be removed + assertNotNull(ret); + assertTrue(ret.errors.length == 0); + } + + @Test + public void vertifyRequestRegistration(){ + if(CUSTOMER_ID.isEmpty() || SECRET_KEY.isEmpty() || PHONE_NUMBER.isEmpty()) { + fail("CUSTOMER_ID, SECRET_KEY and PHONE_NUMBER must be set to pass this test"); + } + + Verify ver; + if(!timeouts) + ver = new Verify(CUSTOMER_ID, SECRET_KEY); + else + ver = new Verify(CUSTOMER_ID, SECRET_KEY, connectTimeout, readTimeout); + + VerifyResponse ret = ver.registration(PHONE_NUMBER, BUNDLE_ID); + assertNotNull(ret); + assertTrue(ret.errors.length == 0); + } + + @Test + public void verifyRequestRegistrationWithAllParams(){ + if(CUSTOMER_ID.isEmpty() || SECRET_KEY.isEmpty() || PHONE_NUMBER.isEmpty()) { + fail("CUSTOMER_ID, SECRET_KEY and PHONE_NUMBER must be set to pass this test"); + } + + Verify ver; + if(!timeouts) + ver = new Verify(CUSTOMER_ID, SECRET_KEY); + else + ver = new Verify(CUSTOMER_ID, SECRET_KEY, connectTimeout, readTimeout); + + VerifyResponse ret = ver.registration(PHONE_NUMBER, BUNDLE_ID, ORIGINATING_IP, SESSION_ID); + assertNotNull(ret); + assertTrue(ret.errors.length == 0); + } + + @Test + public void smartVerify(){ + if(CUSTOMER_ID.isEmpty() || SECRET_KEY.isEmpty() || PHONE_NUMBER.isEmpty()) { + fail("CUSTOMER_ID, SECRET_KEY and PHONE_NUMBER must be set to pass this test"); + } + + Verify ver; + if(!timeouts) + ver = new Verify(CUSTOMER_ID, SECRET_KEY); + else + ver = new Verify(CUSTOMER_ID, SECRET_KEY, connectTimeout, readTimeout); + + VerifyResponse ret = ver.smartVerify(PHONE_NUMBER,"BACS", CALLER_ID, "en-US", null, SMART_VERIFY_PREFERENCE, SMART_VERIFY_IGNORE_RISK); + assertNotNull(ret); + assertTrue(ret.errors.length == 0); + } + + @Test + public void smartVerifyWithAllParams(){ + if(CUSTOMER_ID.isEmpty() || SECRET_KEY.isEmpty() || PHONE_NUMBER.isEmpty()) { + fail("CUSTOMER_ID, SECRET_KEY and PHONE_NUMBER must be set to pass this test"); + } + + Verify ver; + if(!timeouts) + ver = new Verify(CUSTOMER_ID, SECRET_KEY); + else + ver = new Verify(CUSTOMER_ID, SECRET_KEY, connectTimeout, readTimeout); + + VerifyResponse ret = ver.smartVerify(PHONE_NUMBER,"BACS", CALLER_ID, "en-US", null, SMART_VERIFY_PREFERENCE, SMART_VERIFY_IGNORE_RISK , ORIGINATING_IP, SESSION_ID); + assertNotNull(ret); + assertTrue(ret.errors.length == 0); + } }