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.subaccounts; 017 018import com.vonage.client.DynamicEndpoint; 019import com.vonage.client.RestEndpoint; 020import com.vonage.client.HttpWrapper; 021import com.vonage.client.auth.ApiKeyHeaderAuthMethod; 022import com.vonage.client.common.HttpMethod; 023import java.util.List; 024import java.util.Objects; 025import java.util.function.Function; 026 027public class SubaccountsClient { 028 final RestEndpoint<CreateSubaccountRequest, Account> createSubaccount; 029 final RestEndpoint<UpdateSubaccountRequest, Account> updateSubaccount; 030 final RestEndpoint<Void, ListSubaccountsResponse> listSubaccounts; 031 final RestEndpoint<String, Account> getSubaccount; 032 final RestEndpoint<ListTransfersFilter, ListTransfersResponseWrapper> listBalanceTransfers, listCreditTransfers; 033 final RestEndpoint<MoneyTransfer, MoneyTransfer> transferBalance, transferCredit; 034 final RestEndpoint<NumberTransfer, NumberTransfer> transferNumber; 035 036 /** 037 * Constructor. 038 * 039 * @param wrapper (REQUIRED) shared HTTP wrapper object used for making REST calls. 040 */ 041 public SubaccountsClient(HttpWrapper wrapper) { 042 043 @SuppressWarnings("unchecked") 044 final class Endpoint<T, R> extends DynamicEndpoint<T, R> { 045 Endpoint(Function<T, String> pathGetter, HttpMethod method, R... type) { 046 super(DynamicEndpoint.<T, R> builder(type) 047 .responseExceptionType(SubaccountsResponseException.class) 048 .wrapper(wrapper).requestMethod(method).authMethod(ApiKeyHeaderAuthMethod.class) 049 .pathGetter((de, req) -> { 050 final String apiKey = de.getHttpWrapper().getApiKey(); 051 if (apiKey == null) { 052 throw new IllegalStateException("Primary account API key is unavailable."); 053 } 054 if (req instanceof CreateSubaccountRequest) { 055 CreateSubaccountRequest csr = (CreateSubaccountRequest) req; 056 csr.primaryAccountApiKey = apiKey; 057 } 058 return String.format( 059 de.getHttpWrapper().getHttpConfig().getApiBaseUri() 060 + "/accounts/%s/", apiKey 061 ) + pathGetter.apply(req); 062 }) 063 ); 064 } 065 } 066 067 createSubaccount = new Endpoint<>(req -> "subaccounts", HttpMethod.POST); 068 updateSubaccount = new Endpoint<>(req -> "subaccounts/"+req.subaccountApiKey, HttpMethod.PATCH); 069 listSubaccounts = new Endpoint<>(req -> "subaccounts", HttpMethod.GET); 070 getSubaccount = new Endpoint<>(req -> "subaccounts/"+req, HttpMethod.GET); 071 listBalanceTransfers = new Endpoint<>(req -> "balance-transfers", HttpMethod.GET); 072 listCreditTransfers = new Endpoint<>(req -> "credit-transfers", HttpMethod.GET); 073 transferBalance = new Endpoint<>(req -> "balance-transfers", HttpMethod.POST); 074 transferCredit = new Endpoint<>(req -> "credit-transfers", HttpMethod.POST); 075 transferNumber = new Endpoint<>(req -> "transfer-number", HttpMethod.POST); 076 } 077 078 private <T> T requireRequest(T request) { 079 return Objects.requireNonNull(request, "Request is required."); 080 } 081 082 /** 083 * Create a new subaccount under this API primary account. 084 * 085 * @param request Properties for the new subaccount. 086 * 087 * @return Details of the created subaccount. 088 * 089 * @throws SubaccountsResponseException If the request was unsuccessful. This could be for the following reasons: 090 * <ul> 091 * <li><b>401</b>: Credential is missing or invalid.</li> 092 * <li><b>403</b>: Action is forbidden.</li> 093 * <li><b>404</b>: The account ID provided does not exist in our system or you do not have access.</li> 094 * <li><b>422</b>: Validation error.</li> 095 * </ul> 096 */ 097 public Account createSubaccount(CreateSubaccountRequest request) { 098 return createSubaccount.execute(requireRequest(request)); 099 } 100 101 /** 102 * Change one or more properties of a subaccount. 103 * 104 * @param request Properties of the subaccount to update. 105 * 106 * @return Details of the updated subaccount. 107 * 108 * @throws SubaccountsResponseException If the request was unsuccessful. This could be for the following reasons: 109 * <ul> 110 * <li><b>401</b>: Credential is missing or invalid.</li> 111 * <li><b>403</b>: Action is forbidden.</li> 112 * <li><b>404</b>: The account ID provided does not exist in our system or you do not have access.</li> 113 * <li><b>422</b>: Validation error.</li> 114 * </ul> 115 */ 116 public Account updateSubaccount(UpdateSubaccountRequest request) { 117 return updateSubaccount.execute(requireRequest(request)); 118 } 119 120 /** 121 * Retrieve all subaccounts owned by the primary account. 122 * 123 * @return The primary account details and list of subaccounts associated with it. 124 * 125 * @throws SubaccountsResponseException If the request was unsuccessful. This could be for the following reasons: 126 * <ul> 127 * <li><b>401</b>: Credential is missing or invalid.</li> 128 * <li><b>403</b>: Action is forbidden.</li> 129 * <li><b>404</b>: The account ID provided does not exist in our system or you do not have access.</li> 130 * </ul> 131 */ 132 public ListSubaccountsResponse listSubaccounts() { 133 return listSubaccounts.execute(null); 134 } 135 136 /** 137 * Get information about a specific subaccount. 138 * 139 * @param subaccountApiKey Unique ID of the subaccount to retrieve. 140 * 141 * @return Details of the requested subaccount. 142 * 143 * @throws SubaccountsResponseException If the request was unsuccessful. This could be for the following reasons: 144 * <ul> 145 * <li><b>401</b>: Credential is missing or invalid.</li> 146 * <li><b>403</b>: Action is forbidden.</li> 147 * <li><b>404</b>: The account ID provided does not exist in our system or you do not have access.</li> 148 * </ul> 149 */ 150 public Account getSubaccount(String subaccountApiKey) { 151 return getSubaccount.execute(AbstractTransfer.validateAccountKey(subaccountApiKey, "Subaccount")); 152 } 153 154 /** 155 * Retrieve a list of credit transfers that have taken place for the primary account within a specified time period. 156 * 157 * @return The list of credit transfers. 158 * @see #listCreditTransfers(ListTransfersFilter) 159 * 160 * @throws SubaccountsResponseException If the request was unsuccessful. This could be for the following reasons: 161 * <ul> 162 * <li><b>401</b>: Credential is missing or invalid.</li> 163 * <li><b>403</b>: Action is forbidden.</li> 164 * <li><b>404</b>: The account ID provided does not exist in our system or you do not have access.</li> 165 * </ul> 166 */ 167 public List<MoneyTransfer> listCreditTransfers() { 168 return listCreditTransfers(ListTransfersFilter.builder().build()); 169 } 170 171 /** 172 * Retrieve a list of credit transfers that have taken place for the primary account within a specified time period. 173 * 174 * @param filter Additional parameters to narrow down the returned list by. 175 * 176 * @return The list of credit transfers. 177 * @see #listCreditTransfers() 178 * 179 * @throws SubaccountsResponseException If the request was unsuccessful. This could be for the following reasons: 180 * <ul> 181 * <li><b>401</b>: Credential is missing or invalid.</li> 182 * <li><b>403</b>: Action is forbidden.</li> 183 * <li><b>404</b>: The account ID provided does not exist in our system or you do not have access.</li> 184 * </ul> 185 */ 186 public List<MoneyTransfer> listCreditTransfers(ListTransfersFilter filter) { 187 return listCreditTransfers.execute(requireRequest(filter)).getCreditTransfers(); 188 } 189 190 /** 191 * Retrieve a list of balance transfers that have taken place for the primary account within a specified time period. 192 * 193 * @return The list of balance transfers. 194 * @see #listBalanceTransfers(ListTransfersFilter) 195 * 196 * @throws SubaccountsResponseException If the request was unsuccessful. This could be for the following reasons: 197 * <ul> 198 * <li><b>401</b>: Credential is missing or invalid.</li> 199 * <li><b>403</b>: Action is forbidden.</li> 200 * <li><b>404</b>: The account ID provided does not exist in our system or you do not have access.</li> 201 * </ul> 202 */ 203 public List<MoneyTransfer> listBalanceTransfers() { 204 return listBalanceTransfers(ListTransfersFilter.builder().build()); 205 } 206 207 /** 208 * Retrieve a list of balance transfers that have taken place for the primary account within a specified time period. 209 * 210 * @param filter Additional parameters to narrow down the returned list by. 211 * 212 * @return The list of balance transfers. 213 * @see #listBalanceTransfers() 214 * 215 * @throws SubaccountsResponseException If the request was unsuccessful. This could be for the following reasons: 216 * <ul> 217 * <li><b>401</b>: Credential is missing or invalid.</li> 218 * <li><b>403</b>: Action is forbidden.</li> 219 * <li><b>404</b>: The account ID provided does not exist in our system or you do not have access.</li> 220 * </ul> 221 */ 222 public List<MoneyTransfer> listBalanceTransfers(ListTransfersFilter filter) { 223 return listBalanceTransfers.execute(requireRequest(filter)).getBalanceTransfers(); 224 } 225 226 /** 227 * Transfer credit limit between the primary account and one of its subaccounts. 228 * 229 * @param request Properties of the credit transfer. 230 * 231 * @return Details of the transfer if successful. 232 * 233 * @throws SubaccountsResponseException If the request was unsuccessful. This could be for the following reasons: 234 * <ul> 235 * <li><b>401</b>: Credential is missing or invalid.</li> 236 * <li><b>403</b>: Action is forbidden.</li> 237 * <li><b>404</b>: The account ID provided does not exist in our system or you do not have access.</li> 238 * <li><b>422</b>: Validation error.</li> 239 * </ul> 240 */ 241 public MoneyTransfer transferCredit(MoneyTransfer request) { 242 return transferCredit.execute(requireRequest(request)); 243 } 244 245 /** 246 * Transfer balance between the primary account and one of its subaccounts. 247 * 248 * @param request Properties of the balance transfer. 249 * 250 * @return Details of the transfer if successful. 251 * 252 * @throws SubaccountsResponseException If the request was unsuccessful. This could be for the following reasons: 253 * <ul> 254 * <li><b>401</b>: Credential is missing or invalid.</li> 255 * <li><b>403</b>: Action is forbidden.</li> 256 * <li><b>404</b>: The account ID provided does not exist in our system or you do not have access.</li> 257 * <li><b>422</b>: Validation error.</li> 258 * </ul> 259 */ 260 public MoneyTransfer transferBalance(MoneyTransfer request) { 261 return transferBalance.execute(requireRequest(request)); 262 } 263 264 /** 265 * Transfer a number between subaccounts. 266 * 267 * @param request Properties of the number transfer. 268 * 269 * @return Details of the transfer if successful. 270 * 271 * @throws SubaccountsResponseException If the request was unsuccessful. This could be for the following reasons: 272 * <ul> 273 * <li><b>401</b>: Credential is missing or invalid.</li> 274 * <li><b>403</b>: Action is forbidden.</li> 275 * <li><b>404</b>: The account ID provided does not exist in our system or you do not have access.</li> 276 * <li><b>409</b>: Transfer conflict.</li> 277 * <li><b>422</b>: Validation error.</li> 278 * </ul> 279 */ 280 public NumberTransfer transferNumber(NumberTransfer request) { 281 return transferNumber.execute(requireRequest(request)); 282 } 283}