diff --git a/pom.xml b/pom.xml index d4d6643..84312db 100644 --- a/pom.xml +++ b/pom.xml @@ -6,7 +6,7 @@ com.osiris.payhook PayHook - 1.7 + 1.8 jar PayHook diff --git a/src/main/java/com/osiris/payhook/PayHook.java b/src/main/java/com/osiris/payhook/PayHook.java index 321474f..5d52e74 100644 --- a/src/main/java/com/osiris/payhook/PayHook.java +++ b/src/main/java/com/osiris/payhook/PayHook.java @@ -21,46 +21,48 @@ import java.util.Map; import java.util.Objects; +/** + * Contains methods for validating + * WebHook events/notifications and some + * utility methods. + */ public class PayHook { private boolean isSandboxMode = false; /** - * Parses the header, represented as {@link Map}, + * Parses the provided header {@link Map} * into a {@link WebhookEventHeader} object and returns it. - * @throws ParseHeaderException if this operation fails. */ public WebhookEventHeader parseAndGetHeader(Map headerAsMap) throws ParseHeaderException { // Check if all keys we need exist - String transmissionId = validateKeyAndGetValue(headerAsMap, Constants.PAYPAL_HEADER_TRANSMISSION_ID); - String timestamp = validateKeyAndGetValue(headerAsMap, Constants.PAYPAL_HEADER_TRANSMISSION_TIME); - String transmissionSignature = validateKeyAndGetValue(headerAsMap, Constants.PAYPAL_HEADER_TRANSMISSION_SIG); - String certUrl = validateKeyAndGetValue(headerAsMap, Constants.PAYPAL_HEADER_CERT_URL); - String authAlgorithm = validateKeyAndGetValue(headerAsMap, Constants.PAYPAL_HEADER_AUTH_ALGO); + String transmissionId = checkKeyAndGetValue(headerAsMap, Constants.PAYPAL_HEADER_TRANSMISSION_ID); + String timestamp = checkKeyAndGetValue(headerAsMap, Constants.PAYPAL_HEADER_TRANSMISSION_TIME); + String transmissionSignature = checkKeyAndGetValue(headerAsMap, Constants.PAYPAL_HEADER_TRANSMISSION_SIG); + String certUrl = checkKeyAndGetValue(headerAsMap, Constants.PAYPAL_HEADER_CERT_URL); + String authAlgorithm = checkKeyAndGetValue(headerAsMap, Constants.PAYPAL_HEADER_AUTH_ALGO); // Note that the webhook id and crc32 get set after the validation was run return new WebhookEventHeader(transmissionId, timestamp, transmissionSignature, authAlgorithm, certUrl); } /** - * Parses the body, represented as {@link String}, + * Parses the provided body {@link String} * into a {@link JsonObject} and returns it. - * @throws ParseBodyException if this operation fails. */ - public JsonObject parseAndGetBody(String bodyString) throws ParseBodyException { + public JsonObject parseAndGetBody(String bodyAsString) throws ParseBodyException { try{ - return JsonParser.parseString(bodyString).getAsJsonObject(); + return JsonParser.parseString(bodyAsString).getAsJsonObject(); } catch (Exception e) { throw new ParseBodyException(e.getMessage()); } } /** - * Checks if the provided key exists in the map and returns its value. - * The keys existence is checked by {@link String#equalsIgnoreCase(String)}, so that its case is ignored. + * Checks if the provided key exists in the provided map and returns its value.
+ * The keys existence is checked by {@link String#equalsIgnoreCase(String)}, so that its case is ignored.
* @return the value mapped to the provided key. - * @throws WebHookValidationException */ - public String validateKeyAndGetValue(Map map, String key) throws ParseHeaderException { + public String checkKeyAndGetValue(Map map, String key) throws ParseHeaderException { Objects.requireNonNull(map); Objects.requireNonNull(key); @@ -81,7 +83,8 @@ public String validateKeyAndGetValue(Map map, String key) throws } /** - * See {@link #validateWebhookEvent(WebhookEvent)} (WebHookEvent)} for details. + * Creates a new {@link WebhookEvent} and validates it.
+ * See {@link #validateWebhookEvent(WebhookEvent)} for details.
* @param validId your webhooks valid id. Get it from here: https://developer.paypal.com/developer/applications/ * @param validTypes your webhooks valid types/names. Here is a full list: https://developer.paypal.com/docs/api-basics/notifications/webhooks/event-names/ * @param header the http messages header as string. @@ -92,16 +95,20 @@ public void validateWebhookEvent(String validId, List validTypes, Webhoo } /** - * Performs various checks to see if the received {@link WebhookEvent} is valid or not. - * Performed checks: - * Is this events name/type in the valid events list? - * Are this events certificates valid? - * Is this events data/transmission-signature valid? - * Do the webhook ids match? - * @param event - * @return true if the webhook event is valid - * @throws WebHookValidationException if validation failed. IMPORTANT: MESSAGE MAY CONTAIN SENSITIVE INFORMATION! - * @throws ParseBodyException + * Validate the provided {@link WebhookEvent}.
+ * Throws an {@link Exception} if the validation fails.
+ * Performed checks:
+ *
    + *
  • Is the name/type valid?
  • + *
  • Are the certificates valid?
  • + *
  • Is the data/transmission-signature valid? (not in sandbox-mode)
  • + *
  • Do the webhook ids match? (not in sandbox-mode)
  • + *
+ * Note: Since the transmission-signature is not decoded in sandbox-mode + * {@link WebhookEventHeader#getWebhookId()} and {@link WebhookEventHeader#getCrc32()} + * will return encoded values, that are not readable. + * @param event The {@link WebhookEvent} to validate. + * @throws WebHookValidationException IMPORTANT: MESSAGE MAY CONTAIN SENSITIVE INFORMATION! */ public void validateWebhookEvent(WebhookEvent event) throws WebHookValidationException, ParseBodyException, IOException, CertificateException, KeyStoreException, NoSuchAlgorithmException, SignatureException, InvalidKeyException { WebhookEventHeader header = event.getHeader(); @@ -177,10 +184,9 @@ public void validateWebhookEvent(WebhookEvent event) throws WebHookValidationExc } /** - * Formats all of the WebHooks information to a String and returns it. - * @param webHookEvent + * Formats all of the {@link WebhookEvent} information to a {@link String} and returns it. */ - public String getWebhookAsString(WebhookEvent webHookEvent) { + public String getWebhookEventAsString(WebhookEvent webHookEvent) { Objects.requireNonNull(webHookEvent); StringBuilder stringBuilder = new StringBuilder(); @@ -214,10 +220,20 @@ public String getWebhookAsString(WebhookEvent webHookEvent) { return stringBuilder.toString(); } + /** + * See {@link PayHook#setSandboxMode(boolean)} for details. + */ public boolean isSandboxMode() { return isSandboxMode; } + /** + * Enable/Disable the sandbox-mode.
+ * Disabled by default.
+ * If enabled some validation checks, which only succeed for + * live applications, wont be done.
+ * See {@link PayHook#validateWebhookEvent(WebhookEvent)} for details. + */ public void setSandboxMode(boolean sandboxMode) { isSandboxMode = sandboxMode; } diff --git a/src/main/java/com/osiris/payhook/WebhookEvent.java b/src/main/java/com/osiris/payhook/WebhookEvent.java index 0e58e2b..a8c2476 100644 --- a/src/main/java/com/osiris/payhook/WebhookEvent.java +++ b/src/main/java/com/osiris/payhook/WebhookEvent.java @@ -6,6 +6,11 @@ import java.util.List; + +/** + * The in-memory representation of a Webhook event/notification.
+ * Can be validated through {@link PayHook#validateWebhookEvent(WebhookEvent)}. + */ public class WebhookEvent { private String validWebhookId; private List validTypesList; @@ -15,7 +20,8 @@ public class WebhookEvent { private boolean isValid = false; /** - * The in-memory representation of a webhook event. + * The in-memory representation of a Webhook event/notification.
+ * Can be validated through {@link PayHook#validateWebhookEvent(WebhookEvent)}. * @param validWebhookId your webhooks valid id. Get it from here: https://developer.paypal.com/developer/applications/ * @param validTypesList your webhooks valid types/names. Here is a full list: https://developer.paypal.com/docs/api-basics/notifications/webhooks/event-names/ * @param header the http messages header as {@link WebhookEventHeader}. diff --git a/src/main/java/com/osiris/payhook/WebhookEventHeader.java b/src/main/java/com/osiris/payhook/WebhookEventHeader.java index 2c79f93..556c2fd 100644 --- a/src/main/java/com/osiris/payhook/WebhookEventHeader.java +++ b/src/main/java/com/osiris/payhook/WebhookEventHeader.java @@ -1,5 +1,12 @@ package com.osiris.payhook; +import java.util.Map; + +/** + * Contains the {@link WebhookEvent}s headers + * essential information for its validation.
+ * Can be created thorough {@link PayHook#parseAndGetHeader(Map)}. + */ public class WebhookEventHeader { private String transmissionId; private String timestamp; @@ -9,6 +16,11 @@ public class WebhookEventHeader { private String authAlgorithm; private String certUrl; + /** + * Contains the {@link WebhookEvent}s headers + * essential information for its validation. + * Can be created thorough {@link PayHook#parseAndGetHeader(Map)}. + */ public WebhookEventHeader(String transmissionId, String timestamp, String transmissionSignature, String authAlgorithm, String certUrl) { this.transmissionId = transmissionId; this.timestamp = timestamp; @@ -36,27 +48,33 @@ public String getTimestamp() { } /** - * IMPORTANT: SINCE THE WEBHOOK ID IS INSIDE THE ENCRYPTED TRANSMISSION SIGNATURE, THIS RETURNS NULL + * The ID of the webhook resource for the destination URL to which PayPal delivers the event notification.
+ * IMPORTANT: SINCE THE WEBHOOK-ID IS INSIDE THE ENCODED TRANSMISSION-SIGNATURE, THIS RETURNS NULL * UNLESS YOU SUCCESSFULLY EXECUTED {@link PayHook#validateWebhookEvent(WebhookEvent)} ONCE BEFORE! - * The ID of the webhook resource for the destination URL to which PayPal delivers the event notification. */ public String getWebhookId() { return webhookId; } + /** + * See {@link WebhookEventHeader#getWebhookId()} for details. + */ public void setWebhookId(String webhookId) { this.webhookId = webhookId; } /** - * IMPORTANT: SINCE THE CRC32 IS INSIDE THE ENCRYPTED TRANSMISSION SIGNATURE, THIS RETURNS NULL + * The Cyclic Redundancy Check (CRC32) checksum for the body of the HTTP payload.
+ * IMPORTANT: SINCE THE CRC32 IS INSIDE THE ENCODED TRANSMISSION-SIGNATURE, THIS RETURNS NULL * UNLESS YOU SUCCESSFULLY EXECUTED {@link PayHook#validateWebhookEvent(WebhookEvent)} ONCE BEFORE! - * The Cyclic Redundancy Check (CRC32) checksum for the body of the HTTP payload. */ public String getCrc32() { return crc32; } + /** + * See {@link WebhookEventHeader#getCrc32()} for details. + */ public void setCrc32(String crc32) { this.crc32 = crc32; }