001/*
002 *   Copyright 2024 Vonage
003 *
004 *   Licensed under the Apache License, Version 2.0 (the "License");
005 *   you may not use this file except in compliance with the License.
006 *   You may obtain a copy of the License at
007 *
008 *        http://www.apache.org/licenses/LICENSE-2.0
009 *
010 *   Unless required by applicable law or agreed to in writing, software
011 *   distributed under the License is distributed on an "AS IS" BASIS,
012 *   WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
013 *   See the License for the specific language governing permissions and
014 *   limitations under the License.
015 */
016package com.vonage.client.verify;
017
018import com.vonage.client.*;
019import com.vonage.client.auth.ApiKeyQueryParamsAuthMethod;
020import com.vonage.client.common.HttpMethod;
021import java.util.Locale;
022
023/**
024 * A client for talking to the Vonage Verify API. The standard way to obtain an instance of this class is to use {@link
025 * VonageClient#getVerifyClient()}.
026 * <p>
027 * Send a verification request with a call to {@link #verify}, confirm the code entered by the user with {@link #check},
028 * and search in-progress or completed verification requests with {@link #search}
029 * <p>
030 * More information on method parameters can be found on the
031 * <a href="https://developer.vonage.com/verify/overview">Vonage developer portal</a>.
032 */
033public class VerifyClient {
034    final RestEndpoint<CheckRequest, CheckResponse> check;
035    final RestEndpoint<VerifyRequest, VerifyResponse> verify;
036    final RestEndpoint<SearchRequest, SearchVerifyResponse> search;
037    final RestEndpoint<ControlRequest, ControlResponse> control;
038    final RestEndpoint<Psd2Request, VerifyResponse> psd2;
039
040    /**
041     * Constructor.
042     *
043     * @param wrapper (required) shared HTTP wrapper object used for making REST calls.
044     */
045    public VerifyClient(HttpWrapper wrapper) {
046        @SuppressWarnings("unchecked")
047        class Endpoint<T, R> extends DynamicEndpoint<T, R> {
048            Endpoint(String path, boolean formEncoded, R... type) {
049                super(DynamicEndpoint.<T, R> builder(type)
050                        .wrapper(wrapper).requestMethod(HttpMethod.POST)
051                        .authMethod(ApiKeyQueryParamsAuthMethod.class)
052                        .urlFormEncodedContentType(formEncoded)
053                        .pathGetter((de, req) -> de.getHttpWrapper().getHttpConfig()
054                                .getApiBaseUri() + "/verify" + path + "/json"
055                        )
056                );
057            }
058        }
059
060        verify = new Endpoint<>("", true);
061        check = new Endpoint<>("/check", true);
062        search = new Endpoint<>("/search", false);
063        psd2 = new Endpoint<>("/psd2", true);
064        control = new Endpoint<ControlRequest, ControlResponse>("/control", true) {
065            @Override
066            public ControlResponse postProcessParsedResponse(ControlResponse parsed) {
067                if (parsed.getStatus().equals("0")) {
068                    return parsed;
069                }
070                else {
071                    throw new VerifyException(parsed.getStatus(), parsed.getErrorText());
072                }
073            }
074        };
075    }
076
077    /**
078     * Send a verification request to a phone number.
079     *
080     * @param number (required) The recipient's phone number in <a href="https://en.wikipedia.org/wiki/E.164">E.164</a>
081     *               format.
082     * @param brand  (required) The name of the company or app to be verified for. Must not be longer than 18
083     *               characters.
084     *
085     * @return a VerifyResponse representing the response received from the Verify API call.
086     *
087     * @throws VonageClientException        if there was a problem with the Vonage request or response objects.
088     * @throws VonageResponseParseException if the response from the API could not be parsed.
089     */
090    public VerifyResponse verify(final String number, final String brand) throws VonageResponseParseException, VonageClientException {
091        return verify(new VerifyRequest.Builder(number, brand).build());
092    }
093
094    /**
095     * Send a verification request to a phone number with a pin verification workflow
096     *
097     * @param number (required) The recipient's phone number in <a href="https://en.wikipedia.org/wiki/E.164">E.164</a>
098     *               format.
099     * @param brand  (required) The name of the company or app to be verified for. Must not be longer than 18
100     *               characters.
101     * @param workflow <a href="https://developer.vonage.com/verify/guides/workflows-and-events">workflow</a>
102     *                 to use for sending verification pin
103     *
104     * @return a VerifyResponse representing the response received from the Verify API call.
105     *
106     * @throws VonageClientException        if there was a problem with the Vonage request or response objects.
107     * @throws VonageResponseParseException if the response from the API could not be parsed.
108     * @since 5.5.0
109     */
110    public VerifyResponse verify(final String number, final String brand, VerifyRequest.Workflow workflow)
111            throws VonageResponseParseException, VonageClientException {
112        return verify(new VerifyRequest.Builder(number, brand).workflow(workflow).build());
113    }
114
115    /**
116     * Send a verification request to a phone number.
117     *
118     * @param number (required) The recipient's phone number in <a href="https://en.wikipedia.org/wiki/E.164">E.164</a>
119     *               format.
120     * @param brand  (required) The name of the company or app to be verified for. Must not be longer than 18
121     *               characters.
122     * @param from   (optional The Vonage number to use as the sender for the verification SMS message and calls, in
123     *               <a href="https://en.wikipedia.org/wiki/E.164">E.164</a> format.
124     *
125     * @return a VerifyResponse representing the response received from the Verify API call.
126     *
127     * @throws VonageClientException        if there was a problem with the Vonage request or response objects.
128     * @throws VonageResponseParseException if the response from the API could not be parsed.
129     */
130    public VerifyResponse verify(final String number,
131                                 final String brand,
132                                 final String from) throws VonageClientException, VonageResponseParseException {
133        return verify(new VerifyRequest.Builder(number, brand)
134                .senderId(from)
135                .build()
136        );
137    }
138
139    /**
140     * Send a verification request to a phone number.
141     *
142     * @param number (required) The recipient's phone number in <a href="https://en.wikipedia.org/wiki/E.164">E.164</a>
143     *               format.
144     * @param brand  (required) The name of the company or app to be verified for. Must not be longer than 18
145     *               characters.
146     * @param from   (optional The Vonage number to use as the sender for the verification SMS message and calls, in
147     *               <a href="https://en.wikipedia.org/wiki/E.164">E.164</a> format.
148     * @param length (optional) The length of the verification code to be sent to the user. Must be either 4 or 6. Use
149     *               -1 to use the default value.
150     * @param locale (optional) Override the default locale used for verification. By default the locale is determined
151     *               from the country code included in {@code number}
152     *
153     * @return a VerifyResponse representing the response received from the Verify API call.
154     *
155     * @throws VonageClientException        if there was a problem with the Vonage request or response objects.
156     * @throws VonageResponseParseException if the response from the API could not be parsed.
157     */
158    public VerifyResponse verify(final String number,
159                                 final String brand,
160                                 final String from,
161                                 final int length,
162                                 final Locale locale) throws VonageClientException, VonageResponseParseException {
163        return verify(VerifyRequest.builder(number, brand).length(length).senderId(from).locale(locale).build());
164    }
165
166    /**
167     * Send a verification request to a phone number.
168     *
169     * @param request validation request for the 2FA verification.
170     * @return a VerifyResponse representing the response received from the Verify API call.
171     *
172     * @throws VonageClientException if there was a problem with the Vonage request or response objects.
173     * @throws VonageResponseParseException if the response from the API could not be parsed.
174     *
175     */
176    public VerifyResponse verify(VerifyRequest request) throws VonageClientException, VonageResponseParseException {
177        return verify.execute(request);
178    }
179
180    /**
181     * Validate a code provided by a user in response to a call from {@link #verify}.
182     *
183     * @param request The request to send for validation.
184     * @return a CheckResponse representing the response received from the API call.
185     *
186     * @throws VonageClientException        if there was a problem with the Vonage request or response objects.
187     * @throws VonageResponseParseException if the response from the API could not be parsed.
188     * @deprecated Use {@link #check(String, String)}.
189     */
190    @Deprecated
191    public CheckResponse check(CheckRequest request) throws VonageClientException, VonageResponseParseException {
192        return check.execute(request);
193    }
194
195    /**
196     * Validate a code provided by a user in response to a call from {@link #verify}.
197     *
198     * @param requestId (required) The requestId returned by the {@code verify} call.
199     * @param code      (required) The code entered by the user.
200     *
201     * @return a CheckResponse representing the response received from the API call.
202     *
203     * @throws VonageClientException        if there was a problem with the Vonage request or response objects.
204     * @throws VonageResponseParseException if the response from the API could not be parsed.
205     */
206    public CheckResponse check(final String requestId, final String code) throws VonageClientException, VonageResponseParseException {
207        return check(new CheckRequest(requestId, code));
208    }
209
210    /**
211     * Search for a previous verification request.
212     *
213     * @param requestId The requestId of a single Verify request to be looked up.
214     *
215     * @return A SearchVerifyResponse containing the details of the Verify request that was looked up, or {@code null}
216     * if no record was found.
217     *
218     * @throws VonageClientException        if there was a problem with the Vonage request or response objects.
219     * @throws VonageResponseParseException if the response from the API could not be parsed.
220     */
221    public SearchVerifyResponse search(String requestId) throws VonageClientException, VonageResponseParseException {
222        return search.execute(new SearchRequest(requestId));
223    }
224
225    /**
226     * Search for a previous verification request.
227     *
228     * @param requestIds The requestIds of Verify requests to be looked up.
229     *
230     * @return An array SearchVerifyResponse for each record that was found.
231     *
232     * @throws VonageClientException        if there was a problem with the Vonage request or response objects.
233     * @throws VonageResponseParseException if the response from the API could not be parsed.
234     */
235    public SearchVerifyResponse search(String... requestIds) throws VonageClientException, VonageResponseParseException {
236        return search.execute(new SearchRequest(requestIds));
237    }
238
239    /**
240     * Advance a current verification request to the next stage in the process.
241     *
242     * @param requestId The requestId of the ongoing verification request.
243     *
244     * @return A {@link ControlResponse} representing the response from the API.
245     *
246     * @throws VonageClientException        if there was a problem with the Vonage request or response objects.
247     * @throws VonageResponseParseException if the response from the API could not be parsed.
248     */
249    public ControlResponse advanceVerification(String requestId) throws VonageClientException, VonageResponseParseException {
250        return control.execute(new ControlRequest(requestId, VerifyControlCommand.TRIGGER_NEXT_EVENT));
251    }
252
253    /**
254     * Cancel a current verification request.
255     *
256     * @param requestId The requestId of the ongoing verification request.
257     *
258     * @return A {@link ControlResponse} representing the response from the API.
259     *
260     * @throws VonageClientException        if there was a problem with the Vonage request or response objects.
261     * @throws VonageResponseParseException if the response from the API could not be parsed.
262     */
263    public ControlResponse cancelVerification(String requestId) throws VonageClientException, VonageResponseParseException {
264        return control.execute(new ControlRequest(requestId, VerifyControlCommand.CANCEL));
265    }
266
267    /**
268     * Send a PSD2 compliant payment token to a user for payment authorization
269     *
270     * @param number Telephone number to verify, in <a href="https://en.wikipedia.org/wiki/E.164">E.164</a> format
271     * @param amount payment amount
272     * @param payee name of the person the payment is for. Name will be included in the message
273     *
274     * @return A {@link VerifyResponse} representing the response from the API.
275     *
276     * @throws VonageClientException          if there was a problem with the Vonage request or response objects.
277     * @throws VonageResponseParseException   if the response from the API could not be parsed.
278     *
279     * @since 5.5.0
280     */
281    public VerifyResponse psd2Verify(String number, Double amount, String payee) throws VonageClientException, VonageResponseParseException {
282        return psd2Verify(new Psd2Request.Builder(number, amount, payee).build());
283    }
284
285    /**
286     * Send a PSD2 compliant payment token to a user for payment authorization with a pin verification workflow
287     *
288     * @param number   telephone number to verify, in <a href="https://en.wikipedia.org/wiki/E.164">E.164</a> format
289     * @param amount   payment amount
290     * @param payee    name of the person the payment is for. Name will be included in the message
291     * @param workflow <a href="https://developer.vonage.com/verify/guides/workflows-and-events">workflow</a>
292     *                 to use for sending verification pin
293     *
294     * @return A {@link VerifyResponse} representing the response from the API.
295     *
296     * @throws VonageClientException          if there was a problem with the Vonage request or response objects.
297     * @throws VonageResponseParseException   if the response from the API could not be parsed.
298     *
299     * @since 5.5.0
300     */
301    public VerifyResponse psd2Verify(String number, Double amount, String payee, Psd2Request.Workflow workflow)
302            throws VonageClientException, VonageResponseParseException {
303        return psd2Verify(new Psd2Request.Builder(number, amount, payee).workflow(workflow).build());
304    }
305
306    /**
307     * Send a PSD2 verification request to a phone number with optional parameters
308     *
309     * @param psd2Request request to send PSD2 verification to a phone.
310     *
311     * @return A VerifyResponse representing the response from the API.
312     *
313     * @throws VonageClientException          if there was a problem with the Vonage request or response objects.
314     * @throws VonageResponseParseException   if the response from the API could not be parsed.
315     *
316     * @since 5.5.0
317     */
318    public VerifyResponse psd2Verify(Psd2Request psd2Request) throws VonageClientException, VonageResponseParseException {
319        return psd2.execute(psd2Request);
320    }
321}