/** * */ package com.mcac0006.siftscience; import java.io.IOException; import javax.ws.rs.client.Client; import javax.ws.rs.client.ClientBuilder; import javax.ws.rs.client.Entity; import javax.ws.rs.client.Invocation.Builder; import javax.ws.rs.client.WebTarget; import javax.ws.rs.core.MediaType; import javax.ws.rs.core.Response; import org.codehaus.jackson.map.ObjectMapper; import org.codehaus.jackson.map.annotate.JsonSerialize.Inclusion; import com.mcac0006.siftscience.event.domain.Event; import com.mcac0006.siftscience.exception.SiftScienceException; import com.mcac0006.siftscience.label.domain.Label; import com.mcac0006.siftscience.result.domain.SiftScienceResponse; import com.mcac0006.siftscience.score.domain.SiftScienceScore; /** * This helper will take care of marshalling the content you wish to send to Sift Science and * also POST send it to Sift Science. * * <strong>This class is synchronous.</strong> * * @author <a href="mailto:matthew.cachia@gmail.com">Matthew Cachia</a> * */ public class SiftScienceHelper { private static ObjectMapper mapper; static { mapper = new ObjectMapper(); mapper.setSerializationInclusion(Inclusion.NON_NULL); } private SiftScienceHelper() {} /** * Sends an event ($transaction, $create_account, etc ...) to Sift Science. * * @param event - the content regarding the user (or session) in question. * @return the Sift Science response which denotes whether the request has been processed successfully or not. */ public static SiftScienceResponse send(final Event event) { return send(event, false); } /** * Sends an event ($transaction, $create_account, etc ...) to Sift Science. * * @param event - the content regarding the user (or session) in question. * @param returnAction - whether or not Sift should return a score and actions for the event * @return the Sift Science response which denotes whether the request has been processed successfully or not. */ public static SiftScienceResponse send(final Event event, boolean returnAction) { try { final Client client = ClientBuilder.newClient(); WebTarget target = client.target("https://api.siftscience.com/v203/events"); if (returnAction) { target = target.queryParam("return_action", "true"); } final Builder request = target.request(MediaType.APPLICATION_JSON_TYPE); final Response post = request.post(Entity.entity(serialize(event), MediaType.APPLICATION_JSON_TYPE)); return deserializeResponse(post.readEntity(String.class)); } catch (IOException e) { throw new SiftScienceException("Error generating JSON content to send event.", e); } } /** * Sends a Label ($label) to Sift Science. * * @param userId - the user in question * @param label - the content regarding the user in question. * @return the Sift Science response which denotes whether the request has been processed successfully or not. */ public static SiftScienceResponse send(final String userId, final Label label) { try { final Client client = ClientBuilder.newClient(); final WebTarget target = client.target("https://api.siftscience.com/v203/users/").path(userId).path("labels"); final Builder request = target.request(MediaType.APPLICATION_JSON_TYPE); final Response post = request.post(Entity.entity(serialize(label), MediaType.APPLICATION_JSON_TYPE)); return deserializeResponse(post.readEntity(String.class)); } catch (IOException e) { throw new SiftScienceException("Error generating JSON content to send label.", e); } } /** * Retrieve a risk assessment of a particular user. This is particularly useful to consult with Sift Science * before you proceed with any (user-invoked or system-invoked) operations (such as a purchase) on that user. * * @param apiKey - the api key to denote which Sift Science account to use. * @param userId - the user would you like to run a risk assessment on. * * @return a Sift Science score wrapped in a {@link SiftScienceScore} instance containing information such as the * fraud score and the reason. * * Refer to the class' JavaDocs for more information. */ public static SiftScienceScore getScore(final String apiKey, final String userId) { try { final Client client = ClientBuilder.newClient(); final WebTarget target = client.target("https://api.siftscience.com/v203/score/").path(userId).queryParam("api_key", apiKey); final Builder request = target.request(MediaType.APPLICATION_JSON_TYPE); final Response get = request.get(); return deserializeScore(get.readEntity(String.class)); } catch (IOException e) { throw new RuntimeException("Error generating JSON content to retrieve score request.", e); } } /** * <p>Serializes an event as a JSON envelope, ready to be sent to Sift Science.</p> * * <p><strong>Useful if you have your own way of sending the envelope.</strong> Should you require a way of * sending the envelope via Http, you can make use of {@link SiftScienceHelper#send(Event)}.</p> * * @param event the filled event POJO, ready to be serialized * @return the event in JSON form. * @throws IOException thrown whenever an error (unexpected or user-inflicted) has been found during serialization of the event. */ public static String serialize(final Event event) throws IOException { return mapper.writeValueAsString(event); } public static String serialize(final Label label) throws IOException { return mapper.writeValueAsString(label); } /** * <p>Deserializes a response after sending an {@link Event} or a {@link Label}. * * @param response the JSON envelope withholding Sift Science's response. * @return the response in POJO. * @throws IOException thrown whenever an error (unexpected or user-inflicted) has been found during deserialization of the event or label. */ public static SiftScienceResponse deserializeResponse(final String response) throws IOException { return mapper.readValue(response, SiftScienceResponse.class); } /** * <p>Deserializes the score returned by Sift Science.</p> * * <p><strong>Useful if you have your own way of sending and receiving requests.</strong> Should you require a way of * receiving the score Http, you can make use of {@link SiftScienceHelper#getScore(String, String)}.</p> * * @param scoreResponse the JSON envelope withholding Sift Science's response. * @return the response in POJO. * @throws IOException thrown whenever an error (unexpected or user-inflicted) has been found during deserialization of the score. */ public static SiftScienceScore deserializeScore(final String scoreResponse) throws IOException { return mapper.readValue(scoreResponse, SiftScienceScore.class); } }