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; 017 018import com.vonage.client.account.AccountClient; 019import com.vonage.client.application.ApplicationClient; 020import com.vonage.client.auth.*; 021import com.vonage.client.auth.hashutils.HashUtil; 022import com.vonage.client.camara.numberverification.NumberVerificationClient; 023import com.vonage.client.camara.simswap.SimSwapClient; 024import com.vonage.client.conversations.ConversationsClient; 025import com.vonage.client.conversion.ConversionClient; 026import com.vonage.client.insight.InsightClient; 027import com.vonage.client.meetings.MeetingsClient; 028import com.vonage.client.messages.MessagesClient; 029import com.vonage.client.numberinsight2.NumberInsight2Client; 030import com.vonage.client.numbers.NumbersClient; 031import com.vonage.client.proactiveconnect.ProactiveConnectClient; 032import com.vonage.client.redact.RedactClient; 033import com.vonage.client.sms.SmsClient; 034import com.vonage.client.subaccounts.SubaccountsClient; 035import com.vonage.client.users.UsersClient; 036import com.vonage.client.verify.VerifyClient; 037import com.vonage.client.video.VideoClient; 038import com.vonage.client.verify2.Verify2Client; 039import com.vonage.client.voice.VoiceClient; 040import org.apache.http.client.HttpClient; 041import java.io.IOException; 042import java.nio.file.*; 043import java.util.UUID; 044 045/** 046 * Top-level Vonage API client object. 047 * <p> 048 * Construct an instance of this object with one or more {@link AuthMethod}s (providing all the authentication methods 049 * for the APIs you wish to use), and then call {@link #getVoiceClient()} to obtain a client for the Vonage Voice API. 050 * <p>. 051 */ 052public class VonageClient { 053 /** 054 * The HTTP wrapper for this client and its sub-clients. 055 */ 056 final HttpWrapper httpWrapper; 057 058 private final AccountClient account; 059 private final ApplicationClient application; 060 private final InsightClient insight; 061 private final NumbersClient numbers; 062 private final SmsClient sms; 063 private final VoiceClient voice; 064 private final VerifyClient verify; 065 private final ConversionClient conversion; 066 private final RedactClient redact; 067 private final MessagesClient messages; 068 private final Verify2Client verify2; 069 private final SubaccountsClient subaccounts; 070 private final ProactiveConnectClient proactiveConnect; 071 private final MeetingsClient meetings; 072 private final UsersClient users; 073 private final VideoClient video; 074 private final NumberInsight2Client numberInsight2; 075 private final ConversationsClient conversations; 076 private final SimSwapClient simSwap; 077 private final NumberVerificationClient numberVerification; 078 079 /** 080 * Constructor which uses the builder pattern for instantiation. 081 * 082 * @param builder The builder object to use for configuration. 083 */ 084 private VonageClient(Builder builder) { 085 httpWrapper = new HttpWrapper(builder.httpConfig, builder.authCollection); 086 if (builder.httpClient != null) { 087 httpWrapper.setHttpClient(builder.httpClient); 088 } 089 090 account = new AccountClient(httpWrapper); 091 application = new ApplicationClient(httpWrapper); 092 insight = new InsightClient(httpWrapper); 093 numbers = new NumbersClient(httpWrapper); 094 verify = new VerifyClient(httpWrapper); 095 voice = new VoiceClient(httpWrapper); 096 sms = new SmsClient(httpWrapper); 097 conversion = new ConversionClient(httpWrapper); 098 redact = new RedactClient(httpWrapper); 099 messages = new MessagesClient(httpWrapper); 100 verify2 = new Verify2Client(httpWrapper); 101 subaccounts = new SubaccountsClient(httpWrapper); 102 proactiveConnect = new ProactiveConnectClient(httpWrapper); 103 meetings = new MeetingsClient(httpWrapper); 104 users = new UsersClient(httpWrapper); 105 video = new VideoClient(httpWrapper); 106 numberInsight2 = new NumberInsight2Client(httpWrapper); 107 conversations = new ConversationsClient(httpWrapper); 108 simSwap = new SimSwapClient(httpWrapper); 109 numberVerification = new NumberVerificationClient(httpWrapper); 110 } 111 112 /** 113 * Returns the Account API client. 114 * 115 * @return The {@linkplain AccountClient}. 116 */ 117 public AccountClient getAccountClient() { 118 return account; 119 } 120 121 /** 122 * Returns the Application API client. 123 * 124 * @return The {@linkplain ApplicationClient}. 125 */ 126 public ApplicationClient getApplicationClient() { 127 return application; 128 } 129 130 /** 131 * Returns the Number Insight API client. 132 * 133 * @return The {@linkplain InsightClient}. 134 */ 135 public InsightClient getInsightClient() { 136 return insight; 137 } 138 139 /** 140 * Returns the Numbers API client. 141 * 142 * @return The {@linkplain NumbersClient}. 143 */ 144 public NumbersClient getNumbersClient() { 145 return numbers; 146 } 147 148 /** 149 * Returns the SMS API client. 150 * 151 * @return The {@linkplain SmsClient}. 152 */ 153 public SmsClient getSmsClient() { 154 return sms; 155 } 156 157 /** 158 * Returns the Verify v1 API client. 159 * 160 * @return The {@linkplain VerifyClient}. 161 */ 162 public VerifyClient getVerifyClient() { 163 return verify; 164 } 165 166 /** 167 * Returns the Voice API client. 168 * 169 * @return The {@linkplain VoiceClient}. 170 */ 171 public VoiceClient getVoiceClient() { 172 return voice; 173 } 174 175 /** 176 * Returns the Conversion API client. 177 * 178 * @return The {@linkplain ConversionClient}. 179 */ 180 public ConversionClient getConversionClient() { 181 return conversion; 182 } 183 184 /** 185 * Returns the Redact API client. 186 * 187 * @return The {@linkplain RedactClient}. 188 */ 189 public RedactClient getRedactClient() { 190 return redact; 191 } 192 193 /** 194 * Returns the Messages v1 API client. 195 * 196 * @return The {@linkplain MessagesClient}. 197 * @since 6.5.0 198 */ 199 public MessagesClient getMessagesClient() { 200 return messages; 201 } 202 203 /** 204 * Returns the Proactive Connect API client. 205 * 206 * @return The {@linkplain ProactiveConnectClient}. 207 * @since 7.6.0 208 * @deprecated This API is sunset and will be removed in the next major release. 209 */ 210 @Deprecated 211 public ProactiveConnectClient getProactiveConnectClient() { 212 return proactiveConnect; 213 } 214 215 /** 216 * Returns the Meetings API client. 217 * 218 * @return The {@linkplain MeetingsClient}. 219 * @since 7.6.0 220 * @deprecated Support for this API will be removed in the next major release. 221 */ 222 @Deprecated 223 public MeetingsClient getMeetingsClient() { 224 return meetings; 225 } 226 227 /** 228 * Returns the Verify v2 API client. 229 * 230 * @return The {@linkplain Verify2Client}. 231 * @since 7.4.0 232 */ 233 public Verify2Client getVerify2Client() { 234 return verify2; 235 } 236 237 /** 238 * Returns the Subaccounts API client. 239 * 240 * @return The {@linkplain SubaccountsClient}. 241 * @since 7.5.0 242 */ 243 public SubaccountsClient getSubaccountsClient() { 244 return subaccounts; 245 } 246 247 /** 248 * Returns the Users API client. 249 * 250 * @return The {@linkplain UsersClient}. 251 * @since 7.7.0 252 */ 253 public UsersClient getUsersClient() { 254 return users; 255 } 256 257 /** 258 * Returns the Video API client. 259 * 260 * @return The {@linkplain VideoClient}. 261 * @since 8.0.0-beta1 262 */ 263 public VideoClient getVideoClient() { 264 return video; 265 } 266 267 /** 268 * Returns the Fraud Detection API client. 269 * 270 * @return The {@linkplain NumberInsight2Client}. 271 * @since 8.2.0 272 */ 273 public NumberInsight2Client getNumberInsight2Client() { 274 return numberInsight2; 275 } 276 277 /** 278 * Returns the Conversations v1 client. 279 * 280 * @return The Conversation client. 281 * @since 8.4.0 282 */ 283 public ConversationsClient getConversationsClient() { 284 return conversations; 285 } 286 287 /** 288 * Returns the CAMARA SIM Swap API client. 289 * 290 * @return The {@linkplain SimSwapClient}. 291 * @since 8.8.0 292 */ 293 public SimSwapClient getSimSwapClient() { 294 return simSwap; 295 } 296 297 /** 298 * Returns the CAMARA Number Verification API client. 299 * 300 * @return The {@linkplain NumberVerificationClient}. 301 * @since 8.9.0 302 */ 303 public NumberVerificationClient getNumberVerificationClient() { 304 return numberVerification; 305 } 306 307 /** 308 * Generate a JWT for the application the client has been configured with. 309 * 310 * @return A String containing the token data. 311 * 312 * @throws VonageUnacceptableAuthException if no {@link JWTAuthMethod} is available 313 */ 314 public String generateJwt() throws VonageUnacceptableAuthException { 315 return httpWrapper.getAuthCollection().getAuth(JWTAuthMethod.class).generateToken(); 316 } 317 318 /** 319 * Entry point for constructing an instance of this class. 320 * 321 * @return A new Builder with default initial configuration. 322 */ 323 public static Builder builder() { 324 return new Builder(); 325 } 326 327 /** 328 * Builder for specifying the properties of the client. 329 */ 330 public static class Builder { 331 private AuthCollection authCollection; 332 private HttpConfig httpConfig = HttpConfig.defaultConfig(); 333 private HttpClient httpClient; 334 private String apiKey, apiSecret, signatureSecret; 335 private UUID applicationId; 336 private byte[] privateKeyContents; 337 private HashUtil.HashType hashType = HashUtil.HashType.MD5; 338 339 /** 340 * Configure the HTTP client parameters. 341 * 342 * @param httpConfig Configuration options for the {@link HttpWrapper}. 343 * 344 * @return This builder. 345 */ 346 public Builder httpConfig(HttpConfig httpConfig) { 347 this.httpConfig = httpConfig; 348 return this; 349 } 350 351 /** 352 * Set the underlying HTTP client instance. 353 * 354 * @param httpClient Custom implementation of {@link HttpClient}. 355 * 356 * @return This builder. 357 * 358 * @deprecated This method will be removed in the next major release. 359 */ 360 @Deprecated 361 public Builder httpClient(HttpClient httpClient) { 362 this.httpClient = httpClient; 363 return this; 364 } 365 366 /** 367 * Set the application ID for this client. This will be used alongside your private key 368 * (se via {@link #privateKeyContents}) for authenticating requests. 369 * 370 * @param applicationId The application UUID. 371 * 372 * @return This builder. 373 * 374 * @since 7.11.0 375 */ 376 public Builder applicationId(UUID applicationId) { 377 this.applicationId = applicationId; 378 return this; 379 } 380 381 /** 382 * When setting an applicationId, it is also expected that the {@link #privateKeyContents} will also be set. 383 * 384 * @param applicationId Used to identify each application. 385 * 386 * @return This builder. 387 */ 388 public Builder applicationId(String applicationId) { 389 return applicationId(UUID.fromString(applicationId)); 390 } 391 392 /** 393 * When setting an apiKey, it is also expected that {@link #apiSecret(String)} and/or {@link 394 * #signatureSecret(String)} will also be set. 395 * 396 * @param apiKey The API Key found in the dashboard for your account. 397 * 398 * @return This builder. 399 */ 400 public Builder apiKey(String apiKey) { 401 this.apiKey = apiKey; 402 return this; 403 } 404 405 /** 406 * When setting an apiSecret, it is also expected that {@link #apiKey(String)} will also be set. 407 * 408 * @param apiSecret The API Secret found in the dashboard for your account. 409 * 410 * @return This builder. 411 */ 412 public Builder apiSecret(String apiSecret) { 413 this.apiSecret = apiSecret; 414 return this; 415 } 416 417 /** 418 * When setting a signatureSecret, it is also expected that {@link #apiKey(String)} will also be set. 419 * 420 * @param signatureSecret The Signature Secret found in the dashboard for your account. 421 * 422 * @return This builder. 423 */ 424 public Builder signatureSecret(String signatureSecret) { 425 this.signatureSecret = signatureSecret; 426 return this; 427 } 428 429 /** 430 * Sets the hash type to use for signing requests. 431 * 432 * @param hashType The hashing strategy for signature keys as an enum. 433 * 434 * @return This builder. 435 */ 436 public Builder hashType(HashUtil.HashType hashType) { 437 this.hashType = hashType; 438 return this; 439 } 440 441 /** 442 * When setting the contents of your private key, it is also expected that {@link #applicationId(String)} will 443 * also be set. 444 * 445 * @param privateKeyContents The contents of your private key used for JWT generation. 446 * 447 * @return This builder. 448 */ 449 public Builder privateKeyContents(byte[] privateKeyContents) { 450 this.privateKeyContents = privateKeyContents; 451 return this; 452 } 453 454 /** 455 * When setting the contents of your private key, it is also expected that {@link #applicationId(String)} will 456 * also be set. 457 * 458 * @param privateKeyContents The contents of your private key used for JWT generation. 459 * 460 * @return This builder. 461 */ 462 public Builder privateKeyContents(String privateKeyContents) { 463 return privateKeyContents(privateKeyContents.getBytes()); 464 } 465 466 /** 467 * When setting the path of your private key, it is also expected that {@link #applicationId(String)} will also 468 * be set. 469 * 470 * @param privateKeyPath The path to your private key used for JWT generation. 471 * 472 * @return This builder. 473 * 474 * @throws VonageUnableToReadPrivateKeyException if the private key could not be read from the file system. 475 */ 476 public Builder privateKeyPath(Path privateKeyPath) throws VonageUnableToReadPrivateKeyException { 477 try { 478 return privateKeyContents(Files.readAllBytes(privateKeyPath)); 479 } catch (IOException e) { 480 throw new VonageUnableToReadPrivateKeyException("Unable to read private key at " + privateKeyPath, e); 481 } 482 } 483 484 /** 485 * When setting the path of your private key, it is also expected that {@link #applicationId(String)} will also 486 * be set. 487 * 488 * @param privateKeyPath The path to your private key used for JWT generation. 489 * 490 * @return This builder. 491 * 492 * @throws VonageUnableToReadPrivateKeyException if the private key could not be read from the file system. 493 */ 494 public Builder privateKeyPath(String privateKeyPath) throws VonageUnableToReadPrivateKeyException { 495 return privateKeyPath(Paths.get(privateKeyPath)); 496 } 497 498 /** 499 * Builds the client with this builder's parameters. 500 * 501 * @return A new {@link VonageClient} from the stored builder options. 502 * 503 * @throws VonageClientCreationException if credentials aren't provided in a valid pairing or there were issues 504 * generating an {@link JWTAuthMethod} with the provided credentials. 505 */ 506 public VonageClient build() { 507 try { 508 authCollection = new AuthCollection( 509 applicationId, privateKeyContents, 510 apiKey, apiSecret, 511 hashType, signatureSecret 512 ); 513 } 514 catch (IllegalStateException ex) { 515 throw new VonageClientCreationException("Failed to generate authentication methods.", ex); 516 } 517 518 return new VonageClient(this); 519 } 520 } 521}