44package com .brightcove .castlabs .client ;
55
66import java .io .IOException ;
7+ import java .io .UnsupportedEncodingException ;
78import java .util .List ;
89
10+ import com .brightcove .castlabs .client .request .LinkAccountToSubMerchantRequest ;
11+ import com .fasterxml .jackson .core .JsonProcessingException ;
912import com .google .common .collect .Lists ;
1013import org .apache .commons .io .IOUtils ;
1114import org .apache .commons .lang .StringUtils ;
1215import org .apache .http .Header ;
1316import org .apache .http .HttpEntity ;
17+ import org .apache .http .HttpStatus ;
1418import org .apache .http .NameValuePair ;
1519import org .apache .http .client .config .RequestConfig ;
1620import org .apache .http .client .entity .UrlEncodedFormEntity ;
@@ -162,7 +166,7 @@ protected String getUrlWithTicket(final String url) throws CastlabsException, IO
162166/**
163167 * Ingest one or more keys into the Castlabs keystore.
164168 *
165- * @param request Request parameters to pass to Castlabs
169+ * @param request Request parameters to pass to Castlabs
166170 * @param merchantId
167171 * @return response from Castlabs
168172 * @throws CastlabsException error reported by Castlabs
@@ -172,22 +176,10 @@ public IngestAssetsResponse ingestKeys(final IngestKeysRequest request, final St
172176throws CastlabsException ,IOException {
173177
174178final String uri =this .getUrlWithTicket (this .ingestionBaseUrl +"frontend/api/keys/v2/ingest/" +merchantId );
175- final HttpPost ingestRequest =new HttpPost (uri );
176- ingestRequest .addHeader ("Content-Type" ,"application/json" );
177- ingestRequest .setHeader ("Accept" ,"application/json" );
178-
179- if (this .connectionTimeoutSeconds >0 ) {
180- final int connectionTimeout =connectionTimeoutSeconds *1000 ;
181- final RequestConfig requestConfig =
182- RequestConfig .custom ().setConnectionRequestTimeout (connectionTimeout )
183- .setConnectTimeout (connectionTimeout )
184- .setSocketTimeout (connectionTimeout ).build ();
185- ingestRequest .setConfig (requestConfig );
186- }
187- ingestRequest .setEntity (new StringEntity (objectMapper .writeValueAsString (request )));
179+ final HttpPost httpRequest =createHttpPostRequest (uri ,request );
188180
189181final CloseableHttpClient httpclient =HttpClients .createDefault ();
190- try (final CloseableHttpResponse ingestResponse =httpclient .execute (ingestRequest )) {
182+ try (final CloseableHttpResponse ingestResponse =httpclient .execute (httpRequest )) {
191183if (ingestResponse !=null ) {
192184final int statusCode =ingestResponse .getStatusLine ().getStatusCode ();
193185if (200 !=statusCode ) {
@@ -212,7 +204,7 @@ public IngestAssetsResponse ingestKeys(final IngestKeysRequest request, final St
212204/**
213205 * Add a sub merchant account to Castlabs.
214206 *
215- * @param request Request parameters to pass to Castlabs
207+ * @param request Request parameters to pass to Castlabs
216208 * @param merchantUuid UUID for the merchant that the sub-merchant is being created off
217209 * @return response from Castlabs
218210 * @throws CastlabsException error reported by Castlabs
@@ -222,38 +214,75 @@ public AddSubMerchantAccountResponse addSubMerchantAccount(final AddSubMerchantA
222214throws IOException ,CastlabsException {
223215
224216final String uri =this .getUrlWithTicket (this .ingestionBaseUrl +"frontend/rest/reselling/v1/reseller/" +merchantUuid +"/submerchant/add" );
225- final HttpPost addResellerRequest =new HttpPost (uri );
226- addResellerRequest .addHeader ("Content-Type" ,"application/json" );
227- addResellerRequest .setHeader ("Accept" ,"application/json" );
228-
229- if (this .connectionTimeoutSeconds >0 ) {
230- final int connectionTimeout =connectionTimeoutSeconds *1000 ;
231- final RequestConfig requestConfig =
232- RequestConfig .custom ().setConnectionRequestTimeout (connectionTimeout )
233- .setConnectTimeout (connectionTimeout )
234- .setSocketTimeout (connectionTimeout ).build ();
235- addResellerRequest .setConfig (requestConfig );
236- }
237- addResellerRequest .setEntity (new StringEntity (objectMapper .writeValueAsString (request )));
217+ final HttpPost httpRequest =createHttpPostRequest (uri ,request );
238218
239219final CloseableHttpClient httpclient =HttpClients .createDefault ();
240- try (final CloseableHttpResponse httpResponse =httpclient .execute (addResellerRequest )) {
220+ try (final CloseableHttpResponse httpResponse =httpclient .execute (httpRequest )) {
241221final HttpEntity responseEntity =httpResponse .getEntity ();
242222if (responseEntity ==null ) {
243223throw new CastlabsException ("Empty response entity from Castlabs. HTTP Status: " +httpResponse .getStatusLine ().getStatusCode ());
244224 }
245225
246226final String responseBody =IOUtils .toString (responseEntity .getContent ());
247- if (StringUtils .isBlank (responseBody )) {
227+ if (StringUtils .isBlank (responseBody )) {
248228throw new CastlabsException ("Empty response entity from Castlabs. HTTP Status: " +httpResponse .getStatusLine ().getStatusCode ());
249229 }
250230
251231final AddSubMerchantAccountResponse response =objectMapper .readValue (responseBody ,AddSubMerchantAccountResponse .class );
252- if (response .getSubMerchantUuid () ==null ) {
232+ if (response .getSubMerchantUuid () ==null ) {
253233throw new CastlabsException ("Unexpected response from Castlabs: " +responseBody );
254234 }
255235return response ;
256236 }
257237 }
258238
239+ /**
240+ * Link an existing user/API account to a sub-merchant account.
241+ *
242+ * @param request Request parameters to pass to Castlabs
243+ * @param resellerUuid UUID for the merchant that the sub-merchant was created off
244+ * @throws CastlabsException error reported by Castlabs
245+ * @throws IOException network error while communicating with Castlabs REST API
246+ */
247+ public void linkAccountToSubMerchant (final LinkAccountToSubMerchantRequest request ,final String resellerUuid )
248+ throws IOException ,CastlabsException {
249+
250+ final String uri =this .getUrlWithTicket (this .ingestionBaseUrl +"frontend/rest/reselling/v1/reseller/" +resellerUuid +"/submerchant/linkAccount" );
251+ final HttpPost httpRequest =createHttpPostRequest (uri ,request );
252+
253+ final CloseableHttpClient httpclient =HttpClients .createDefault ();
254+ try (final CloseableHttpResponse httpResponse =httpclient .execute (httpRequest )) {
255+ final int statusCode =httpResponse .getStatusLine ().getStatusCode ();
256+
257+ if (statusCode !=HttpStatus .SC_NO_CONTENT ) {
258+ final HttpEntity responseEntity =httpResponse .getEntity ();
259+
260+ String responseBody ="" ;
261+ if (responseEntity !=null ) {
262+ responseBody =IOUtils .toString (responseEntity .getContent ());
263+ }
264+
265+ throw new CastlabsException ("Unexpected status code from Castlabs: " +statusCode +". Response body: " +responseBody );
266+ }
267+ }
268+ }
269+
270+ private HttpPost createHttpPostRequest (final String uri ,final Object body )throws JsonProcessingException ,UnsupportedEncodingException {
271+ final HttpPost request =new HttpPost (uri );
272+ request .addHeader ("Content-Type" ,"application/json" );
273+ request .setHeader ("Accept" ,"application/json" );
274+ request .setEntity (new StringEntity (objectMapper .writeValueAsString (body )));
275+
276+ if (this .connectionTimeoutSeconds >0 ) {
277+ final int connectionTimeout =connectionTimeoutSeconds *1000 ;
278+ final RequestConfig requestConfig =
279+ RequestConfig .custom ().setConnectionRequestTimeout (connectionTimeout )
280+ .setConnectTimeout (connectionTimeout )
281+ .setSocketTimeout (connectionTimeout ).build ();
282+ request .setConfig (requestConfig );
283+ }
284+
285+ return request ;
286+ }
287+
259288}