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.numbers; 017 018import com.vonage.client.*; 019import com.vonage.client.auth.ApiKeyHeaderAuthMethod; 020import com.vonage.client.common.HttpMethod; 021import java.util.UUID; 022 023/** 024 * A client for accessing the Vonage API calls that manage phone numbers. The standard way to obtain an instance of 025 * this class is to use {@link VonageClient#getNumbersClient()}. 026 */ 027public class NumbersClient { 028 final RestEndpoint<ListNumbersFilter, ListNumbersResponse> listNumbers; 029 final RestEndpoint<SearchNumbersFilter, SearchNumbersResponse> searchNumbers; 030 final RestEndpoint<BuyCancelNumberRequest, Void> buyNumber, cancelNumber; 031 final RestEndpoint<UpdateNumberRequest, Void> updateNumber; 032 033 public NumbersClient(HttpWrapper wrapper) { 034 @SuppressWarnings("unchecked") 035 final class Endpoint<T, R> extends DynamicEndpoint<T, R> { 036 Endpoint(final String path, HttpMethod method, R... type) { 037 super(DynamicEndpoint.<T, R> builder(type) 038 .responseExceptionType(NumbersResponseException.class) 039 .wrapper(wrapper).requestMethod(method) 040 .authMethod(ApiKeyHeaderAuthMethod.class) 041 .urlFormEncodedContentType(method == HttpMethod.POST) 042 .pathGetter((de, req) -> de.getHttpWrapper().getHttpConfig().getRestBaseUri()+ "/" + path) 043 ); 044 } 045 } 046 047 listNumbers = new Endpoint<>("account/numbers", HttpMethod.GET); 048 searchNumbers = new Endpoint<>("number/search", HttpMethod.GET); 049 cancelNumber = new Endpoint<>("number/cancel", HttpMethod.POST); 050 buyNumber = new Endpoint<>("number/buy", HttpMethod.POST); 051 updateNumber = new Endpoint<>("number/update", HttpMethod.POST); 052 } 053 054 /** 055 * Get the first page of phone numbers assigned to the authenticated account. 056 * 057 * @return A ListNumbersResponse containing the first 10 phone numbers 058 * 059 * @throws NumbersResponseException If the API call returned an unsuccessful (4xx or 5xx) response. 060 */ 061 public ListNumbersResponse listNumbers() throws NumbersResponseException { 062 return listNumbers(ListNumbersFilter.builder().build()); 063 } 064 065 /** 066 * Get a filtered set of numbers assigned to the authenticated account. 067 * 068 * @param filter A ListNumbersFilter describing the filters to be applied to the request. 069 * 070 * @return A ListNumbersResponse containing phone numbers matching the supplied filter. 071 * 072 * @throws NumbersResponseException If the API call returned an unsuccessful (4xx or 5xx) response. 073 */ 074 public ListNumbersResponse listNumbers(ListNumbersFilter filter) throws NumbersResponseException { 075 return listNumbers.execute(filter); 076 } 077 078 /** 079 * Search for available Vonage Virtual Numbers. 080 * 081 * @param country Country to search available numbers from. 082 * 083 * @return Available Vonage Virtual Numbers. 084 * 085 * @throws NumbersResponseException If the API call returned an unsuccessful (4xx or 5xx) response. 086 */ 087 public SearchNumbersResponse searchNumbers(String country) throws NumbersResponseException { 088 return searchNumbers(SearchNumbersFilter.builder().country(country).build()); 089 } 090 091 /** 092 * Search for available Vonage Virtual Numbers. 093 * 094 * @param filter search for available Vonage Virtual Number with filters 095 * @return The available Vonage Virtual Numbers. 096 * 097 * @throws NumbersResponseException If the API call returned an unsuccessful (4xx or 5xx) response. 098 */ 099 public SearchNumbersResponse searchNumbers(SearchNumbersFilter filter) throws NumbersResponseException { 100 return searchNumbers.execute(filter); 101 } 102 103 /** 104 * Start renting a Vonage Virtual Number. 105 * 106 * @param country The two character country code in ISO 3166-1 alpha-2 format. 107 * @param msisdn The phone number to be bought in E.164 format. 108 * 109 * @throws NumbersResponseException If the API call returned an unsuccessful (4xx or 5xx) response. 110 */ 111 public void buyNumber(String country, String msisdn) throws NumbersResponseException { 112 buyNumber(country, msisdn, null); 113 } 114 115 /** 116 * Start renting a Vonage Virtual Number. 117 * 118 * @param country The two character country code in ISO 3166-1 alpha-2 format. 119 * @param msisdn The phone number to be bought in E.164 format. 120 * @param targetApiKey If you’d like to perform an action on a subaccount, provide the API key of that 121 * account here. If you’d like to perform an action on your own account, 122 * you do not need to provide this field. 123 * 124 * @throws NumbersResponseException If the API call returned an unsuccessful (4xx or 5xx) response. 125 * @see #buyNumber(String, String) 126 * @since 8.10.0 127 */ 128 public void buyNumber(String country, String msisdn, String targetApiKey) throws NumbersResponseException { 129 buyNumber.execute(new BuyCancelNumberRequest(country, msisdn, targetApiKey)); 130 } 131 132 /** 133 * Stop renting a Vonage Virtual Number. 134 * 135 * @param country The two character country code in ISO 3166-1 alpha-2 format. 136 * @param msisdn The phone number to be cancelled in E.164 format. 137 * 138 * @throws NumbersResponseException If the API call returned an unsuccessful (4xx or 5xx) response. 139 */ 140 public void cancelNumber(String country, String msisdn) throws NumbersResponseException { 141 cancelNumber(country, msisdn, null); 142 } 143 144 /** 145 * Stop renting a Vonage Virtual Number. 146 * 147 * @param country The two character country code in ISO 3166-1 alpha-2 format. 148 * @param msisdn The phone number to be cancelled in E.164 format. 149 * @param targetApiKey If you’d like to perform an action on a subaccount, provide the API key of that 150 * account here. If you’d like to perform an action on your own account, 151 * you do not need to provide this field. 152 * 153 * @throws NumbersResponseException If the API call returned an unsuccessful (4xx or 5xx) response. 154 * @see #cancelNumber(String, String) 155 * @since 8.10.0 156 */ 157 public void cancelNumber(String country, String msisdn, String targetApiKey) throws NumbersResponseException { 158 cancelNumber.execute(new BuyCancelNumberRequest(country, msisdn, targetApiKey)); 159 } 160 161 /** 162 * Update the callbacks and/or application associations for a given Vonage Virtual Number. 163 * 164 * @param request Details of the updates to be made to the number association. 165 * 166 * @throws NumbersResponseException If the API call returned an unsuccessful (4xx or 5xx) response. 167 */ 168 public void updateNumber(UpdateNumberRequest request) throws NumbersResponseException { 169 updateNumber.execute(request); 170 } 171 172 /** 173 * Link a given Vonage Virtual Number to a Vonage Application with the given ID. 174 * 175 * @param msisdn The Vonage Virtual Number to be updated. 176 * @param country The country for the given msisdn. 177 * @param appId The UUID for the Vonage Application to be associated with the number. 178 * 179 * @throws NumbersResponseException If the API call returned an unsuccessful (4xx or 5xx) response. 180 */ 181 public void linkNumber(String msisdn, String country, String appId) throws NumbersResponseException { 182 updateNumber(UpdateNumberRequest.builder(msisdn, country) 183 .voiceCallback(UpdateNumberRequest.CallbackType.APP, UUID.fromString(appId).toString()).build()); 184 } 185}