diff --git a/.gitignore b/.gitignore index b3f16c1..6a439c8 100644 --- a/.gitignore +++ b/.gitignore @@ -3,3 +3,5 @@ .settings/ target/ mockapi/node_modules +/.idea/ +/sdk.iml diff --git a/mockapi/app.js b/mockapi/app.js index b39715b..fcf197a 100644 --- a/mockapi/app.js +++ b/mockapi/app.js @@ -3,69 +3,91 @@ var fs = require('fs'); var app = express.createServer(); -app.configure(function(){ +app.configure(function () { app.use(express.methodOverride()); app.use(express.bodyParser()); }); -app.post('/oauth/token', function(req, res) { - if(req.query["grant_type"]=="authorization_code") { - if(req.query["code"]=="bad code") { - res.send({"message":"Error validando el parámetro code","error":"invalid_grant","status":400,"cause":[]}, 400); - } else if(req.query["code"]=="valid code without refresh token") { +app.post('/oauth/token', function (req, res) { + if (req.query["grant_type"] == "authorization_code") { + if (req.query["code"] == "bad code") { res.send({ - "access_token" : "valid token", - "token_type" : "bearer", - "expires_in" : 10800, - "scope" : "write read" + "message": "Error validando el parámetro code", + "error": "invalid_grant", + "status": 400, + "cause": [] + }, 400); + } else if (req.query["code"] == "valid code without refresh token") { + res.send({ + "access_token": "valid token", + "token_type": "bearer", + "expires_in": 10800, + "scope": "write read" }); - } else if(req.query["code"]=="valid code with refresh token") { + } else if (req.query["code"] == "valid code with refresh token") { res.send({ - "access_token" : "valid token", - "token_type" : "bearer", - "expires_in" : 10800, - "refresh_token" : "valid refresh token", - "scope" : "write read" + "access_token": "valid token", + "token_type": "bearer", + "expires_in": 10800, + "refresh_token": "valid refresh token", + "scope": "write read" }); } else { res.send(404); } - } else if(req.query['grant_type']=='refresh_token') { - if(req.query['refresh_token']=='valid refresh token') { + } else if (req.query['grant_type'] == 'refresh_token') { + if (req.query['refresh_token'] == 'valid refresh token') { res.send({ - "access_token" : "valid token", - "token_type" : "bearer", - "expires_in" : 10800, - "scope" : "write read" + "access_token": "valid token", + "token_type": "bearer", + "expires_in": 10800, + "scope": "write read" }); } } }); -app.get('/sites', function(req, res) { - res.send([{"id":"MLA","name":"Argentina"},{"id":"MLB","name":"Brasil"},{"id":"MCO","name":"Colombia"},{"id":"MCR","name":"Costa Rica"},{"id":"MEC","name":"Ecuador"},{"id":"MLC","name":"Chile"},{"id":"MLM","name":"Mexico"},{"id":"MLU","name":"Uruguay"},{"id":"MLV","name":"Venezuela"},{"id":"MPA","name":"Panamá"},{"id":"MPE","name":"Perú"},{"id":"MPT","name":"Portugal"},{"id":"MRD","name":"Dominicana"}]); +app.get('/sites', function (req, res) { + res.send([{"id": "MLA", "name": "Argentina"}, {"id": "MLB", "name": "Brasil"}, { + "id": "MCO", + "name": "Colombia" + }, {"id": "MCR", "name": "Costa Rica"}, {"id": "MEC", "name": "Ecuador"}, { + "id": "MLC", + "name": "Chile" + }, {"id": "MLM", "name": "Mexico"}, {"id": "MLU", "name": "Uruguay"}, { + "id": "MLV", + "name": "Venezuela" + }, {"id": "MPA", "name": "Panamá"}, {"id": "MPE", "name": "Perú"}, {"id": "MPT", "name": "Portugal"}, { + "id": "MRD", + "name": "Dominicana" + }]); }); -app.get('/users/me', function(req, res) { - if(req.query['access_token']=='valid token') { - res.send({"id":123456,"nickname":"foobar"}); - } else if(req.query['access_token']=='expired token') { +app.get('/users/me', function (req, res) { + if (req.query['access_token'] == 'valid token') { + res.send({"id": 123456, "nickname": "foobar"}); + } else if (req.query['access_token'] == 'expired token') { res.send(404); } else { - res.send({"message":"The User ID must match the consultant's","error":"forbidden","status":403,"cause":[]}, 403); + res.send({ + "message": "The User ID must match the consultant's", + "error": "forbidden", + "status": 403, + "cause": [] + }, 403); } }); -app.post('/items', function(req, res) { - if(req.query['access_token']=='valid token') { - if(req.body && req.body.foo == "bar") { +app.post('/items', function (req, res) { + if (req.query['access_token'] == 'valid token') { + if (req.body && req.body.foo == "bar") { res.send(201); } else { res.send(400); } - } else if(req.query['access_token']=='expired token') { + } else if (req.query['access_token'] == 'expired token') { res.send(404); } else { res.send(403); @@ -73,31 +95,31 @@ app.post('/items', function(req, res) { }); -app.put('/items/123', function(req, res) { - if(req.query['access_token']=='valid token') { - if(req.body && req.body.foo == "bar") { +app.put('/items/123', function (req, res) { + if (req.query['access_token'] == 'valid token') { + if (req.body && req.body.foo == "bar") { res.send(200); } else { res.send(400); } - } else if(req.query['access_token']=='expired token') { + } else if (req.query['access_token'] == 'expired token') { res.send(404); } else { res.send(403); } }); -app.delete('/items/123', function(req, res) { - if(req.query['access_token']=='valid token') { +app.delete('/items/123', function (req, res) { + if (req.query['access_token'] == 'valid token') { res.send(200); - } else if(req.query['access_token']=='expired token') { + } else if (req.query['access_token'] == 'expired token') { res.send(404); } else { res.send(403); } }); -app.get('/echo/user_agent',function(req,res) { +app.get('/echo/user_agent', function (req, res) { if (req.headers['user-agent'].match(/MELI-JAVA-SDK-.*/)) res.send(200); else diff --git a/mockapi/package.json b/mockapi/package.json index e3497bb..3788de5 100644 --- a/mockapi/package.json +++ b/mockapi/package.json @@ -1,8 +1,8 @@ { - "name": "mockapi", - "version": "1.0.0", - "dependencies": { - "express" : "2.5.x" - }, - "engine": "node ~> 0.8.x" + "name": "mockapi", + "version": "1.0.0", + "dependencies": { + "express": "2.5.x" + }, + "engine": "node ~> 0.8.x" } diff --git a/pom.xml b/pom.xml index d6261c7..17b6ea1 100644 --- a/pom.xml +++ b/pom.xml @@ -1,58 +1,107 @@ - 4.0.0 - com.mercadolibre - sdk - 0.0.3-SNAPSHOT - - - repo - https://github.com/mercadolibre/java-sdk-repo/raw/master/releases - - - snapshot-repo - https://github.com/mercadolibre/java-sdk-repo/raw/master/snapshots - - + xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd"> + 4.0.0 - - - - org.apache.maven.plugins - maven-compiler-plugin - 2.0.2 - - 1.6 - 1.6 - - + com.mercadolibre + sdk + 0.0.4-SNAPSHOT - - org.apache.maven.plugins - maven-surefire-plugin - - true - - + + + com.ning + async-http-client + 1.7.4 + + + com.google.code.gson + gson + 2.8.2 + + + junit + junit + 4.12 + test + + + org.mockito + mockito-all + 1.10.19 + test + + + commons-io + commons-io + 2.6 + test + + - - + + + repo + https://github.com/mercadolibre/java-sdk-repo/raw/master/releases + + + snapshot-repo + https://github.com/mercadolibre/java-sdk-repo/raw/master/snapshots + + + + + + + org.apache.maven.plugins + maven-compiler-plugin + 3.7.0 + + 1.6 + 1.6 + + + + org.apache.maven.plugins + maven-site-plugin + 3.6 + + + + + + + + org.apache.maven.plugins + maven-project-info-reports-plugin + 2.9 + + false + + + + + index + summary + + + + + + org.apache.maven.plugins + maven-jxr-plugin + 2.5 + + + org.codehaus.mojo + cobertura-maven-plugin + 2.7 + + + html + xml + + + + + - - - junit - junit - 4.10 - - - com.ning - async-http-client - 1.7.4 - - - com.google.code.gson - gson - 2.2.2 - - diff --git a/src/main/java/com/mercadolibre/sdk/AuthorizationFailure.java b/src/main/java/com/mercadolibre/sdk/AuthorizationFailure.java index 38a06ae..e4be785 100644 --- a/src/main/java/com/mercadolibre/sdk/AuthorizationFailure.java +++ b/src/main/java/com/mercadolibre/sdk/AuthorizationFailure.java @@ -1,14 +1,15 @@ package com.mercadolibre.sdk; public class AuthorizationFailure extends Exception { + private static final long serialVersionUID = 8688100047490895706L; public AuthorizationFailure(String message) { - super(message); + super(message); - } + } public AuthorizationFailure(Throwable cause) { - super(cause); + super(cause); } } diff --git a/src/main/java/com/mercadolibre/sdk/Meli.java b/src/main/java/com/mercadolibre/sdk/Meli.java index 4a39897..9159874 100644 --- a/src/main/java/com/mercadolibre/sdk/Meli.java +++ b/src/main/java/com/mercadolibre/sdk/Meli.java @@ -16,316 +16,323 @@ import com.ning.http.client.Response; public class Meli { - - public static String apiUrl = "https://api.mercadolibre.com"; - - /** - * Availables auth sites. One user - application can only operate in one site - * - */ - - public static enum AuthUrls { - MLA("https://auth.mercadolibre.com.ar"), // Argentina - MLB("https://auth.mercadolivre.com.br"), // Brasil - MCO("https://auth.mercadolibre.com.co"), // Colombia - MCR("https://auth.mercadolibre.com.cr"), // Costa Rica - MEC("https://auth.mercadolibre.com.ec"), // Ecuador - MLC("https://auth.mercadolibre.cl"), // Chile - MLM("https://auth.mercadolibre.com.mx"), // Mexico - MLU("https://auth.mercadolibre.com.uy"), // Uruguay - MLV("https://auth.mercadolibre.com.ve"), // Venezuela - MPA("https://auth.mercadolibre.com.pa"), // Panama - MPE("https://auth.mercadolibre.com.pe"), // Peru - MPT("https://auth.mercadolibre.com.pt"), // Portugal - MRD("https://auth.mercadolibre.com.do"); // Dominicana - - private String value; - - - private AuthUrls(String value) { - this.value = value; - } - - public String getValue() { - return value; - } - }; - - private String accessToken; - private String refreshToken; - private Long clientId; - private String clientSecret; - private AsyncHttpClient http; - /** news **/ - private Long expiresIn; - private String scope; - private String userId; - private String tokenType; - - - - { - AsyncHttpClientConfig cf = new AsyncHttpClientConfig.Builder() - .setUserAgent("MELI-JAVA-SDK-0.0.4").build(); - http = new AsyncHttpClient(cf); - } - - public Meli(Long clientId, String clientSecret) { - this.clientId = clientId; - this.clientSecret = clientSecret; - } - public Meli(Long clientId, String clientSecret, String accessToken) { - this.accessToken = accessToken; - this.clientId = clientId; - this.clientSecret = clientSecret; - } + public static String apiUrl = "https://api.mercadolibre.com"; + + /** + * Availables auth sites. One user - application can only operate in one site + */ + + public static enum AuthUrls { + MLA("https://auth.mercadolibre.com.ar"), // Argentina + MLB("https://auth.mercadolivre.com.br"), // Brasil + MCO("https://auth.mercadolibre.com.co"), // Colombia + MCR("https://auth.mercadolibre.com.cr"), // Costa Rica + MEC("https://auth.mercadolibre.com.ec"), // Ecuador + MLC("https://auth.mercadolibre.cl"), // Chile + MLM("https://auth.mercadolibre.com.mx"), // Mexico + MLU("https://auth.mercadolibre.com.uy"), // Uruguay + MLV("https://auth.mercadolibre.com.ve"), // Venezuela + MPA("https://auth.mercadolibre.com.pa"), // Panama + MPE("https://auth.mercadolibre.com.pe"), // Peru + MPT("https://auth.mercadolibre.com.pt"), // Portugal + MRD("https://auth.mercadolibre.com.do"); // Dominicana + + private String value; - public Meli(Long clientId, String clientSecret, String accessToken, String refreshToken) { - this.accessToken = accessToken; - this.clientId = clientId; - this.clientSecret = clientSecret; - this.refreshToken = refreshToken; - } - public String getAccessToken() { - return this.accessToken; + private AuthUrls(String value) { + this.value = value; } - public String getRefreshToken() { - return this.refreshToken; + public String getValue() { + return value; } - /** news **/ - public Long getExpiresIn() { - return this.expiresIn; + } + + ; + + private String accessToken; + private String refreshToken; + private Long clientId; + private String clientSecret; + private AsyncHttpClient http; + /** + * news + **/ + private Long expiresIn; + private String scope; + private String userId; + private String tokenType; + + + { + AsyncHttpClientConfig cf = new AsyncHttpClientConfig.Builder() + .setUserAgent("MELI-JAVA-SDK-0.0.4").build(); + http = new AsyncHttpClient(cf); + } + + public Meli(Long clientId, String clientSecret) { + this.clientId = clientId; + this.clientSecret = clientSecret; + } + + public Meli(Long clientId, String clientSecret, String accessToken) { + this.accessToken = accessToken; + this.clientId = clientId; + this.clientSecret = clientSecret; + } + + public Meli(Long clientId, String clientSecret, String accessToken, String refreshToken) { + this.accessToken = accessToken; + this.clientId = clientId; + this.clientSecret = clientSecret; + this.refreshToken = refreshToken; + } + + public String getAccessToken() { + return this.accessToken; + } + + public String getRefreshToken() { + return this.refreshToken; + } + + /** + * news + **/ + public Long getExpiresIn() { + return this.expiresIn; + } + + public String getScope() { + return this.scope; + } + + public String getUserId() { + return this.userId; + } + + public String getTokenType() { + return this.tokenType; + } + + public void setHttp(AsyncHttpClient http) { + this.http = http; + } + + public Response get(String path) throws MeliException { + return get(path, new FluentStringsMap()); + } + + private BoundRequestBuilder prepareGet(String path, FluentStringsMap params) { + return http.prepareGet(apiUrl + path) + .addHeader("Accept", "application/json") + .setQueryParameters(params); + } + + + private BoundRequestBuilder prepareDelete(String path, + FluentStringsMap params) { + return http.prepareDelete(apiUrl + path) + .addHeader("Accept", "application/json") + .setQueryParameters(params); + } + + private BoundRequestBuilder preparePost(String path, + FluentStringsMap params, String body) { + return http.preparePost(apiUrl + path) + .addHeader("Accept", "application/json") + .setQueryParameters(params) + .setHeader("Content-Type", "application/json") + .setBody(body) + .setBodyEncoding("UTF-8"); + } + + private BoundRequestBuilder preparePut(String path, + FluentStringsMap params, String body) { + return http.preparePut(apiUrl + path) + .addHeader("Accept", "application/json") + .setQueryParameters(params) + .setHeader("Content-Type", "application/json").setBody(body) + .setBodyEncoding("UTF-8"); + } + + private BoundRequestBuilder preparePost(String path, FluentStringsMap params) { + return http.preparePost(apiUrl + path) + .addHeader("Accept", "application/json") + .setQueryParameters(params); + } + + + public Response get(String path, FluentStringsMap params) throws MeliException { + + BoundRequestBuilder r = prepareGet(path, params); + + Response response; + try { + response = r.execute().get(); + } catch (Exception e) { + throw new MeliException(e); } - public String getScope() { - return this.scope; - } - public String getUserId() { - return this.userId; + return response; + } + + public void refreshAccessToken() throws AuthorizationFailure { + FluentStringsMap params = new FluentStringsMap(); + params.add("grant_type", "refresh_token"); + params.add("client_id", String.valueOf(this.clientId)); + params.add("client_secret", this.clientSecret); + params.add("refresh_token", this.refreshToken); + try { + BoundRequestBuilder req = preparePost("/oauth/token", params); + parseToken(req); + } catch (AuthorizationFailure e1) { + System.out.println(e1.getMessage()); + } catch (Exception e) { + System.out.println(e.getMessage()); } - public String getTokenType() { - return this.tokenType; + } + + /** + * @param callback: The callback URL. Must be the applications redirect URI + * @param authUrl: The authorization URL. Get from Meli.AuthUrls + * @return the authorization URL + */ + public String getAuthUrl(String callback, AuthUrls authUrl) { + try { + return authUrl.getValue() + "/authorization?response_type=code&client_id=" + + clientId + + "&redirect_uri=" + + URLEncoder.encode(callback, "UTF-8"); + } catch (UnsupportedEncodingException e) { + return authUrl + "/authorization?response_type=code&client_id=" + + clientId + "&redirect_uri=" + callback; } - - public Response get(String path) throws MeliException { - return get(path, new FluentStringsMap()); + } + + public void authorize(String code, String redirectUri) throws AuthorizationFailure { + FluentStringsMap params = new FluentStringsMap(); + + params.add("grant_type", "authorization_code"); + params.add("client_id", String.valueOf(clientId)); + params.add("client_secret", clientSecret); + params.add("code", code); + params.add("redirect_uri", redirectUri); + + BoundRequestBuilder r = preparePost("/oauth/token", params); + + parseToken(r); + } + + private void parseToken(BoundRequestBuilder r) throws AuthorizationFailure { + Response response = null; + String responseBody = ""; + try { + response = r.execute().get(); + responseBody = response.getResponseBody(); + } catch (InterruptedException e) { + throw new AuthorizationFailure(e); + } catch (ExecutionException e) { + throw new AuthorizationFailure(e); + } catch (IOException e) { + throw new AuthorizationFailure(e); } - private BoundRequestBuilder prepareGet(String path, FluentStringsMap params) { - return http.prepareGet(apiUrl + path) - .addHeader("Accept", "application/json") - .setQueryParameters(params); + JsonParser p = new JsonParser(); + JsonObject object; + + try { + object = p.parse(responseBody).getAsJsonObject(); + } catch (JsonSyntaxException e) { + throw new AuthorizationFailure(responseBody); } + if (response.getStatusCode() == 200) { - private BoundRequestBuilder prepareDelete(String path, - FluentStringsMap params) { - return http.prepareDelete(apiUrl + path) - .addHeader("Accept", "application/json") - .setQueryParameters(params); - } - - private BoundRequestBuilder preparePost(String path, - FluentStringsMap params, String body) { - return http.preparePost(apiUrl + path) - .addHeader("Accept", "application/json") - .setQueryParameters(params) - .setHeader("Content-Type", "application/json").setBody(body) - .setBodyEncoding("UTF-8"); - } - - private BoundRequestBuilder preparePut(String path, - FluentStringsMap params, String body) { - return http.preparePut(apiUrl + path) - .addHeader("Accept", "application/json") - .setQueryParameters(params) - .setHeader("Content-Type", "application/json").setBody(body) - .setBodyEncoding("UTF-8"); - } - - private BoundRequestBuilder preparePost(String path, FluentStringsMap params) { - return http.preparePost(apiUrl + path) - .addHeader("Accept", "application/json") - .setQueryParameters(params); - } - - - - public Response get(String path, FluentStringsMap params) throws MeliException { - - BoundRequestBuilder r = prepareGet(path, params); - - Response response; - try { - response = r.execute().get(); - } catch (Exception e) { - throw new MeliException(e); - } - - - - return response; - } - - public void refreshAccessToken() throws AuthorizationFailure { - FluentStringsMap params = new FluentStringsMap(); - params.add("grant_type", "refresh_token"); - params.add("client_id", String.valueOf(this.clientId)); - params.add("client_secret", this.clientSecret); - params.add("refresh_token", this.refreshToken); - try { - BoundRequestBuilder req = preparePost("/oauth/token", params); - parseToken(req); - } catch (AuthorizationFailure e1) { - System.out.println(e1.getMessage()); - }catch (Exception e){ - System.out.println(e.getMessage()); - } + this.accessToken = object.get("access_token").getAsString(); - } + JsonElement jsonElement = object.get("refresh_token"); + this.refreshToken = jsonElement != null ? object.get( + "refresh_token").getAsString() : null; + /** News **/ + JsonElement jsonElementExpires = object.get("expires_in"); + this.expiresIn = jsonElementExpires != null ? Long.parseLong(object.get( + "expires_in").getAsString()) : null; + + JsonElement jsonElementScope = object.get("scope"); + this.scope = jsonElementScope != null ? object.get( + "scope").getAsString() : null; + + JsonElement jsonElementUserID = object.get("user_id"); + this.userId = jsonElementUserID != null ? object.get( + "user_id").getAsString() : null; - /** - * - * @param callback: The callback URL. Must be the applications redirect URI - * @param authUrl: The authorization URL. Get from Meli.AuthUrls - * @return the authorization URL - */ - public String getAuthUrl(String callback, AuthUrls authUrl) { - try { - return authUrl.getValue() + "/authorization?response_type=code&client_id=" - + clientId - + "&redirect_uri=" - + URLEncoder.encode(callback, "UTF-8"); - } catch (UnsupportedEncodingException e) { - return authUrl+"/authorization?response_type=code&client_id=" - + clientId + "&redirect_uri=" + callback; - } + JsonElement jsonElementToken = object.get("token_type"); + this.tokenType = jsonElementToken != null ? object.get( + "token_type").getAsString() : null; + + } else { + throw new AuthorizationFailure(object.get("message").getAsString()); } - public void authorize(String code, String redirectUri) throws AuthorizationFailure { - FluentStringsMap params = new FluentStringsMap(); + } - params.add("grant_type", "authorization_code"); - params.add("client_id", String.valueOf(clientId)); - params.add("client_secret", clientSecret); - params.add("code", code); - params.add("redirect_uri", redirectUri); + private boolean hasRefreshToken() { + return this.refreshToken != null && !this.refreshToken.isEmpty(); + } - BoundRequestBuilder r = preparePost("/oauth/token", params); + public Response post(String path, FluentStringsMap params, String body) throws MeliException { - parseToken(r); - } + BoundRequestBuilder r = preparePost(path, params, body); - private void parseToken(BoundRequestBuilder r) throws AuthorizationFailure { - Response response = null; - String responseBody = ""; - try { - response = r.execute().get(); - responseBody = response.getResponseBody(); - } catch (InterruptedException e) { - throw new AuthorizationFailure(e); - } catch (ExecutionException e) { - throw new AuthorizationFailure(e); - } catch (IOException e) { - throw new AuthorizationFailure(e); - } - - JsonParser p = new JsonParser(); - JsonObject object; - - try { - object = p.parse(responseBody).getAsJsonObject(); - } catch (JsonSyntaxException e) { - throw new AuthorizationFailure(responseBody); - } - - if (response.getStatusCode() == 200) { - - this.accessToken = object.get("access_token").getAsString(); - - JsonElement jsonElement = object.get("refresh_token"); - this.refreshToken = jsonElement != null ? object.get( - "refresh_token").getAsString() : null; - /** News **/ - JsonElement jsonElementExpires = object.get("expires_in"); - this.expiresIn = jsonElementExpires != null ? Long.parseLong(object.get( - "expires_in").getAsString()): null; - - JsonElement jsonElementScope = object.get("scope"); - this.scope = jsonElementScope != null ? object.get( - "scope").getAsString() : null; - - JsonElement jsonElementUserID = object.get("user_id"); - this.userId = jsonElementUserID != null ? object.get( - "user_id").getAsString() : null; - - JsonElement jsonElementToken = object.get("token_type"); - this.tokenType = jsonElementToken != null ? object.get( - "token_type").getAsString() : null; - - } else { - throw new AuthorizationFailure(object.get("message").getAsString()); - } - - } - - private boolean hasRefreshToken() { - return this.refreshToken != null && !this.refreshToken.isEmpty(); + Response response; + try { + response = r.execute().get(); + } catch (Exception e) { + throw new MeliException(e); } - public Response post(String path, FluentStringsMap params, String body) throws MeliException { - - BoundRequestBuilder r = preparePost(path, params, body); - - Response response; - try { - response = r.execute().get(); - } catch (Exception e) { - throw new MeliException(e); - } - - - return response; - } - - public Response put(String path, FluentStringsMap params, String body) throws MeliException { - - BoundRequestBuilder r = preparePut(path, params, body); - - Response response; - try { - response = r.execute().get(); - } catch (Exception e) { - throw new MeliException(e); - } - - return response; - } - - public Response delete(String path, FluentStringsMap params) throws MeliException { - BoundRequestBuilder r = prepareDelete(path, params); - - Response response; - try { - response = r.execute().get(); - } catch (Exception e) { - throw new MeliException(e); - } - - return response; - } - - public BoundRequestBuilder head(String path) { - return null; + + return response; + } + + public Response put(String path, FluentStringsMap params, String body) throws MeliException { + + BoundRequestBuilder r = preparePut(path, params, body); + + Response response; + try { + response = r.execute().get(); + } catch (Exception e) { + throw new MeliException(e); } - public BoundRequestBuilder options(String path) { - return null; + return response; + } + + public Response delete(String path, FluentStringsMap params) throws MeliException { + BoundRequestBuilder r = prepareDelete(path, params); + + Response response; + try { + response = r.execute().get(); + } catch (Exception e) { + throw new MeliException(e); } + + return response; + } + + public BoundRequestBuilder head(String path) { + return null; + } + + public BoundRequestBuilder options(String path) { + return null; + } } diff --git a/src/main/java/com/mercadolibre/sdk/MeliException.java b/src/main/java/com/mercadolibre/sdk/MeliException.java index 9650965..4544ea3 100644 --- a/src/main/java/com/mercadolibre/sdk/MeliException.java +++ b/src/main/java/com/mercadolibre/sdk/MeliException.java @@ -1,8 +1,9 @@ package com.mercadolibre.sdk; public class MeliException extends Exception { + public MeliException(Throwable cause) { - super(cause); + super(cause); } private static final long serialVersionUID = 7263275678852231779L; diff --git a/src/test/java/com/mercadolibre/sdk/MeliTest.java b/src/test/java/com/mercadolibre/sdk/MeliTest.java index b8fe0dc..2f5ece4 100644 --- a/src/test/java/com/mercadolibre/sdk/MeliTest.java +++ b/src/test/java/com/mercadolibre/sdk/MeliTest.java @@ -1,147 +1,162 @@ package com.mercadolibre.sdk; -import java.io.IOException; - -import org.junit.Assert; -import org.junit.Test; - +import com.ning.http.client.AsyncHttpClient; import com.ning.http.client.FluentStringsMap; +import com.ning.http.client.ListenableFuture; import com.ning.http.client.Response; +import org.apache.commons.io.IOUtils; +import org.junit.Test; -public class MeliTest extends Assert { - @Test - public void testGetAuthUrl() { - assertEquals( - "https://auth.mercadolibre.com.ar/authorization?response_type=code&client_id=123456&redirect_uri=http%3A%2F%2Fsomeurl.com", - new Meli(123456l, "client secret") - .getAuthUrl("http://someurl.com", Meli.AuthUrls.MLA)); - } +import java.io.FileInputStream; +import java.io.IOException; +import java.io.InputStream; +import java.util.concurrent.ExecutionException; - @Test(expected = AuthorizationFailure.class) - public void testAuthorizationFailure() throws AuthorizationFailure { +import static org.junit.Assert.assertEquals; +import static org.mockito.BDDMockito.given; +import static org.mockito.Matchers.any; +import static org.mockito.Matchers.anyString; +import static org.mockito.Mockito.mock; - Meli.apiUrl = "https://api.mercadolibre.com"; +public class MeliTest { - new Meli(123456l, "client secret").authorize("bad code", - "http://someurl.com"); + private enum HttpMethod { + GET, POST, PUT, DELETE } @Test - public void testAuthorizationSuccess() throws AuthorizationFailure { + public void getAuthUrl_returnsAuthUrl() { + Meli meli = new Meli(123456L, "client secret"); - Meli.apiUrl = "https://api.mercadolibre.com"; - Meli m = new Meli(123456l, "client secret"); - m.authorize("valid code with refresh token", "http://someurl.com"); + String authUrl = meli.getAuthUrl("http://someurl.com", Meli.AuthUrls.MLA); - assertEquals("valid token", m.getAccessToken()); - assertEquals("valid refresh token", m.getRefreshToken()); + assertEquals("https://auth.mercadolibre.com.ar/authorization?response_type=code&client_id=123456&redirect_uri=http%3A%2F%2Fsomeurl.com", authUrl); } @Test - public void testGet() throws MeliException, IOException { - Meli.apiUrl = "https://api.mercadolibre.com"; - Meli m = new Meli(123456l, "client secret", "valid token"); + public void authorize_withValidCode_returnsAccessToken() throws AuthorizationFailure, IOException, ExecutionException, InterruptedException { + String jsonResponse = getFileContent("authorization_success.json"); + int statusCode = 200; + Meli.apiUrl = "https://api.mercadolibre.com"; + Meli meli = new Meli(1234561L, "client secret"); + mockHttpRequest(meli, jsonResponse, statusCode, HttpMethod.POST, null); - Response response = m.get("/sites"); + meli.authorize("valid code with refresh token", "http://someurl.com"); - assertEquals(200, response.getStatusCode()); - assertFalse(response.getResponseBody().isEmpty()); + assertEquals("APP_USR-6092-3246532-cb45c82853f6e620bb0deda096b128d3-8035443", meli.getAccessToken()); + assertEquals("TG-5005b6b3e4b07e60756a3353", meli.getRefreshToken()); } - @Test - public void testGetWithRefreshToken() throws MeliException, IOException { - Meli.apiUrl = "https://api.mercadolibre.com"; - Meli m = new Meli(123456l, "client secret", "expired token", - "valid refresh token"); - - FluentStringsMap params = new FluentStringsMap(); - params.add("access_token", m.getAccessToken()); - Response response = m.get("/users/me", params); + @Test(expected = AuthorizationFailure.class) + public void authorize_withInvalidCode_throwsAuthorizationFailureException() throws AuthorizationFailure, IOException, ExecutionException, InterruptedException { + String jsonResponse = getFileContent("authorization_bad_request.json"); + int statusCode = 400; + Meli.apiUrl = "https://api.mercadolibre.com"; + Meli meli = new Meli(1234561L, "client secret"); + mockHttpRequest(meli, jsonResponse, statusCode, HttpMethod.POST, null); - assertEquals(200, response.getStatusCode()); - assertFalse(response.getResponseBody().isEmpty()); + meli.authorize("bad code", "http://someurl.com"); } @Test - public void testErrorHandling() throws IOException, MeliException { - Meli m = new Meli(123456l, "client secret", "invalid token"); - - FluentStringsMap params = new FluentStringsMap(); - params.add("access_token", m.getAccessToken()); - Response response = m.get("/users/me", params); - assertEquals(403, response.getStatusCode()); - } + public void get_withExistingEndpoint_returnsSuccessfulResponse() throws MeliException, IOException, ExecutionException, InterruptedException { + String jsonResponse = getFileContent("get_sites_success.json"); + Meli.apiUrl = "https://api.mercadolibre.com"; + Meli meli = new Meli(1234561L, "client secret", "valid token"); + int statusCode = 200; + mockHttpRequest(meli, jsonResponse, statusCode, HttpMethod.GET, null); - @Test - public void testUserAgent() throws IOException, MeliException { - Meli m = new Meli(123456l, "client secret", "invalid token"); + Response response = meli.get("/sites"); - FluentStringsMap params = new FluentStringsMap(); - params.add("access_token", m.getAccessToken()); - Response response = m.get("/echo/user_agent", params); - assertEquals(200, response.getStatusCode()); + assertEquals(200, response.getStatusCode()); + assertEquals(jsonResponse, response.getResponseBody()); } - public void testPost() throws MeliException { - Meli m = new Meli(123456l, "client secret", "valid token"); - - FluentStringsMap params = new FluentStringsMap(); - params.add("access_token", m.getAccessToken()); - Response r = m.post("/items", params, "{\"foo\":\"bar\"}"); - - assertEquals(201, r.getStatusCode()); + @Test + public void post_withExistingEndpoint_returnsSuccessfulResponse() throws MeliException, IOException, ExecutionException, InterruptedException { + String jsonResponse = getFileContent("post_item_success.json"); + Meli meli = new Meli(1234561L, "client secret", "valid token"); + FluentStringsMap params = new FluentStringsMap(); + params.add("access_token", meli.getAccessToken()); + int statusCode = 201; + String body = "{\"foo\":\"bar\"}"; + mockHttpRequest(meli, jsonResponse, statusCode, HttpMethod.POST, body); + + Response response = meli.post("/items", params, body); + + assertEquals(201, response.getStatusCode()); + assertEquals(jsonResponse, response.getResponseBody()); } - public void testPostWithRefreshToken() throws MeliException { - Meli m = new Meli(123456l, "client secret", "expired token", - "valid refresh token"); + @Test + public void put_withExistingItem_returnsSuccessfulResponse() throws MeliException, InterruptedException, ExecutionException, IOException { + int statusCode = 200; + Meli meli = new Meli(1234561L, "client secret", "valid token"); + String body = "{\"tags\":[\"immediate_payment\"]}"; + mockHttpRequest(meli, "", statusCode, HttpMethod.PUT, body); - FluentStringsMap params = new FluentStringsMap(); - params.add("access_token", m.getAccessToken()); - Response r = m.post("/items", params, "{\"foo\":\"bar\"}"); + FluentStringsMap params = new FluentStringsMap(); + params.add("access_token", meli.getAccessToken()); + Response response = meli.put("/items/123", params, "{\"tags\":[\"immediate_payment\"]}"); - assertEquals(201, r.getStatusCode()); + assertEquals(200, response.getStatusCode()); } - public void testPut() throws MeliException { - Meli m = new Meli(123456l, "client secret", "valid token"); + @Test + public void delete_WithExistingItem_returnsSuccessfulResponse() throws MeliException, InterruptedException, ExecutionException, IOException { + int statusCode = 200; + Meli meli = new Meli(1234561L, "client secret", "valid token"); + FluentStringsMap params = new FluentStringsMap(); + params.add("access_token", meli.getAccessToken()); + mockHttpRequest(meli, "", statusCode, HttpMethod.DELETE, null); - FluentStringsMap params = new FluentStringsMap(); - params.add("access_token", m.getAccessToken()); - Response r = m.put("/items/123", params, "{\"foo\":\"bar\"}"); + Response response = meli.delete("/items/123", params); - assertEquals(200, r.getStatusCode()); + assertEquals(200, response.getStatusCode()); } - public void testPutWithRefreshToken() throws MeliException { - Meli m = new Meli(123456l, "client secret", "expired token", - "valid refresh token"); - - FluentStringsMap params = new FluentStringsMap(); - params.add("access_token", m.getAccessToken()); - Response r = m.put("/items/123", params, "{\"foo\":\"bar\"}"); - - assertEquals(200, r.getStatusCode()); + private String getFileContent(String filename) throws IOException { + InputStream inputStream = new FileInputStream("src/test/resources/api_responses/" + filename); + return IOUtils.toString(inputStream, "UTF-8"); } - public void testDelete() throws MeliException { - Meli m = new Meli(123456l, "client secret", "valid token"); - - FluentStringsMap params = new FluentStringsMap(); - params.add("access_token", m.getAccessToken()); - Response r = m.delete("/items/123", params); - - assertEquals(200, r.getStatusCode()); + private void mockHttpRequest(Meli meli, String jsonResponse, int statusCode, HttpMethod httpMethod, String body) throws IOException, ExecutionException, InterruptedException { + Response responseMock = mock(Response.class); + given(responseMock.getStatusCode()).willReturn(statusCode); + given(responseMock.getResponseBody()).willReturn(jsonResponse); + + ListenableFuture listenableFutureMock = mock(ListenableFuture.class); + given(listenableFutureMock.get()).willReturn(responseMock); + + AsyncHttpClient.BoundRequestBuilder boundRequestBuilderMock = mock(AsyncHttpClient.BoundRequestBuilder.class); + given(boundRequestBuilderMock.addHeader(anyString(), anyString())).willReturn(boundRequestBuilderMock); + given(boundRequestBuilderMock.setQueryParameters(any(FluentStringsMap.class))).willReturn(boundRequestBuilderMock); + + if (body != null) { + given(boundRequestBuilderMock.setHeader(anyString(), anyString())).willReturn(boundRequestBuilderMock); + given(boundRequestBuilderMock.setBody(body)).willReturn(boundRequestBuilderMock); + given(boundRequestBuilderMock.setBodyEncoding(anyString())).willReturn(boundRequestBuilderMock); + } + + given(boundRequestBuilderMock.execute()).willReturn(listenableFutureMock); + + AsyncHttpClient asyncHttpClientMock = mock(AsyncHttpClient.class); + switch (httpMethod) { + case GET: + given(asyncHttpClientMock.prepareGet(anyString())).willReturn(boundRequestBuilderMock); + break; + case POST: + given(asyncHttpClientMock.preparePost(anyString())).willReturn(boundRequestBuilderMock); + break; + case PUT: + given(asyncHttpClientMock.preparePut(anyString())).willReturn(boundRequestBuilderMock); + break; + case DELETE: + given(asyncHttpClientMock.prepareDelete(anyString())).willReturn(boundRequestBuilderMock); + break; + } + + meli.setHttp(asyncHttpClientMock); } - public void testDeleteWithRefreshToken() throws MeliException { - Meli m = new Meli(123456l, "client secret", "expired token", - "valid refresh token"); - - FluentStringsMap params = new FluentStringsMap(); - params.add("access_token", m.getAccessToken()); - Response r = m.delete("/items/123", params); - - assertEquals(200, r.getStatusCode()); - } } \ No newline at end of file diff --git a/src/test/resources/api_responses/authorization_bad_request.json b/src/test/resources/api_responses/authorization_bad_request.json new file mode 100644 index 0000000..01c5abe --- /dev/null +++ b/src/test/resources/api_responses/authorization_bad_request.json @@ -0,0 +1,6 @@ +{ + "message": "invalid client_id or client_secret.", + "error": "invalid_client", + "status": 400, + "cause": [] +} \ No newline at end of file diff --git a/src/test/resources/api_responses/authorization_success.json b/src/test/resources/api_responses/authorization_success.json new file mode 100644 index 0000000..6720277 --- /dev/null +++ b/src/test/resources/api_responses/authorization_success.json @@ -0,0 +1,7 @@ +{ + "access_token" : "APP_USR-6092-3246532-cb45c82853f6e620bb0deda096b128d3-8035443", + "token_type" : "bearer", + "expires_in" : 10800, + "refresh_token" : "TG-5005b6b3e4b07e60756a3353", + "scope" : "write read" +} \ No newline at end of file diff --git a/src/test/resources/api_responses/get_sites_success.json b/src/test/resources/api_responses/get_sites_success.json new file mode 100644 index 0000000..358bd3b --- /dev/null +++ b/src/test/resources/api_responses/get_sites_success.json @@ -0,0 +1,82 @@ +[ + { + "id": "MLA", + "name": "Argentina" + }, + { + "id": "MLC", + "name": "Chile" + }, + { + "id": "MLU", + "name": "Uruguay" + }, + { + "id": "MPY", + "name": "Paraguay" + }, + { + "id": "MBO", + "name": "Bolivia" + }, + { + "id": "MHN", + "name": "Honduras" + }, + { + "id": "MCU", + "name": "Cuba" + }, + { + "id": "MGT", + "name": "Guatemala" + }, + { + "id": "MCO", + "name": "Colombia" + }, + { + "id": "MCR", + "name": "Costa Rica" + }, + { + "id": "MRD", + "name": "Dominicana" + }, + { + "id": "MSV", + "name": "El Salvador" + }, + { + "id": "MEC", + "name": "Ecuador" + }, + { + "id": "MPA", + "name": "Panamá" + }, + { + "id": "MLV", + "name": "Venezuela" + }, + { + "id": "MNI", + "name": "Nicaragua" + }, + { + "id": "MPE", + "name": "Perú" + }, + { + "id": "MPT", + "name": "Portugal" + }, + { + "id": "MLB", + "name": "Brasil" + }, + { + "id": "MLM", + "name": "Mexico" + } +] \ No newline at end of file diff --git a/src/test/resources/api_responses/post_item_success.json b/src/test/resources/api_responses/post_item_success.json new file mode 100644 index 0000000..89e62ca --- /dev/null +++ b/src/test/resources/api_responses/post_item_success.json @@ -0,0 +1,139 @@ +{ + "id": "MLA600190449", + "site_id": "MLA", + "title": "Iphone 6 64gb Space Gray Liberado", + "subtitle": null, + "seller_id": 118617944, + "category_id": "MLA352543", + "official_store_id": null, + "price": 16550, + "base_price": 16550, + "original_price": null, + "currency_id": "ARS", + "initial_quantity": 2, + "available_quantity": 2, + "sold_quantity": 0, + "buying_mode": "buy_it_now", + "listing_type_id": "bronze", + "start_time": "2016-01-13T18:10:29.000Z", + "stop_time": "2016-03-13T18:10:29.000Z", + "condition": "new", + "permalink": "http://articulo.mercadolibre.com.ar/MLA-600190449-iphone-6-64gb-space-gray-liberado-_JM", + "thumbnail": "http://mla-s1-p.mlstatic.com/873411-MLA20547233702_012016-I.jpg", + "secure_thumbnail": "https://a248.e.akamai.net/mla-s1-p.mlstatic.com/873411-MLA20547233702_012016-I.jpg", + "pictures": [ + { + "id": "873411-MLA20547233702_012016", + "url": "http://mla-s1-p.mlstatic.com/873411-MLA20547233702_012016-O.jpg", + "secure_url": "https://a248.e.akamai.net/mla-s1-p.mlstatic.com/873411-MLA20547233702_012016-O.jpg", + "size": "225x225", + "max_size": "225x225", + "quality": "" + }, + { + "id": "234411-MLA20547233720_012016", + "url": "http://mla-s1-p.mlstatic.com/234411-MLA20547233720_012016-O.jpg", + "secure_url": "https://a248.e.akamai.net/mla-s1-p.mlstatic.com/234411-MLA20547233720_012016-O.jpg", + "size": "259x194", + "max_size": "259x194", + "quality": "" + }, + { + "id": "768311-MLA20547233735_012016", + "url": "http://mla-s1-p.mlstatic.com/768311-MLA20547233735_012016-O.jpg", + "secure_url": "https://a248.e.akamai.net/mla-s1-p.mlstatic.com/768311-MLA20547233735_012016-O.jpg", + "size": "300x168", + "max_size": "300x168", + "quality": "" + } + ], + "video_id": null, + "descriptions": [ + { + "id": "MLA600190449-1007729488" + } + ], + "accepts_mercadopago": true, + "non_mercado_pago_payment_methods": [ + ], + "shipping": { + "mode": "me2", + "local_pick_up": true, + "free_shipping": true, + "free_methods": [ + { + "id": 73328, + "rule": { + "free_mode": "country", + "value": null + } + } + ], + "dimensions": null, + "tags": [ + ] + }, + "international_delivery_mode": "none", + "seller_address": { + "id": 138834162, + "comment": "", + "address_line": "", + "zip_code": "", + "city": { + "id": "TUxBQ05FVXF1ZW4", + "name": "Neuquén" + }, + "state": { + "id": "AR-Q", + "name": "Neuquén" + }, + "country": { + "id": "AR", + "name": "Argentina" + }, + "latitude": -38.95628353, + "longitude": -68.12749595, + "search_location": { + "neighborhood": { + "id": "", + "name": "" + }, + "city": { + "id": "TUxBQ05FVXF1ZW4", + "name": "Neuquén" + }, + "state": { + "id": "TUxBUE5FVW4xMzMzNQ", + "name": "Neuquén" + } + } + }, + "seller_contact": null, + "location": { + }, + "geolocation": { + "latitude": -38.96055205, + "longitude": -68.12525497 + }, + "coverage_areas": [ + ], + "attributes": [ + ], + "listing_source": "", + "variations": [ + ], + "status": "active", + "sub_status": [ + ], + "tags": [ + ], + "warranty": null, + "catalog_product_id": null, + "parent_item_id": null, + "differential_pricing": null, + "deal_ids": [ + ], + "automatic_relist": false, + "date_created": "2016-01-13T18:10:29.000Z", + "last_updated": "2016-01-13T18:26:54.000Z" +} \ No newline at end of file