Differences

This shows you the differences between two versions of the page.

Link to this comparison view

Both sides previous revisionPrevious revision
Next revision
Previous revision
v:2.0:pre_payment_webhook [2019/04/22 19:22] – [Pre-Payment Webhook] foxybrettv:2.0:pre_payment_webhook [2021/05/26 10:30] (current) – [Headers] adam
Line 9: Line 9:
   * Integrations with custom validation or fraud-check services (such as [[https://wiki.foxycart.com/integration/fraudlabspro|FraudLabsPro]]).   * Integrations with custom validation or fraud-check services (such as [[https://wiki.foxycart.com/integration/fraudlabspro|FraudLabsPro]]).
  
-==== Enabling the pre-payment Hook ====+===== Enabling the pre-payment Hook =====
  
 To enable the pre-payment hook, head to the "payment" setting page in your store's FoxyCart administration, ensuring that you've selected the [[.:payment_sets|payment set]] you're wanting to enable the hook for. Within the "Anti-Fraud Integrations" section, check the checkbox to "enable custom pre-payment hook" and complete the settings below. To enable the pre-payment hook, head to the "payment" setting page in your store's FoxyCart administration, ensuring that you've selected the [[.:payment_sets|payment set]] you're wanting to enable the hook for. Within the "Anti-Fraud Integrations" section, check the checkbox to "enable custom pre-payment hook" and complete the settings below.
Line 19: Line 19:
  
  
-==== Handling the request ====+===== Handling the request ===== 
 + 
 +==== Headers ==== 
 + 
 +Any requests made to your webhook's endpoint will also contain several special headers: 
 + 
 +^ Header ^ Description ^ 
 +| ''Foxy-Webhook-Event'' | Name of the event that triggered this payload. Currently ''validation/payment'' or ''validation/3ds''. | 
 +| ''Foxy-Store-ID'' | The ID of the store that this webhook was triggered for. | 
 +| ''Foxy-Store-Domain'' | The current Foxy store domain that this webhook was triggered for. | 
 + 
 +==== Events ==== 
 + 
 +The prepayment webhook is primarily triggered right before the payment is sent to your gateway for handling. For this trigger, the ''Foxy-Webhook-Event'' header will be ''validation/payment''
 + 
 +For a couple gateways though, we do also trigger the prepayment webhook prior to the 3DSv2 challenge occurring, which has an event header of ''validation/3ds''. These triggers exist for specific purposes, and are documented on the respective gateway wiki pages: 
 + 
 +  * [[gateways:opayo#special_considerationprepayment_webhook|Opayo]] 
 +  * [[gateways:barclaycard#special_considerationprepayment_webhook|Barclaycard]] 
 +==== Example Payload ====
  
 When the customer attempts to complete their purchase, after the Google reCAPTCHA is validated (if active), a POST request is sent off to your custom post-checkout hook endpoint with a JSON payload representing the current cart. It follows the same structure as our [[https://api.foxycart.com|Hypermedia API]], as the majority of the data comes from there. When the customer attempts to complete their purchase, after the Google reCAPTCHA is validated (if active), a POST request is sent off to your custom post-checkout hook endpoint with a JSON payload representing the current cart. It follows the same structure as our [[https://api.foxycart.com|Hypermedia API]], as the majority of the data comes from there.
Line 270: Line 289:
 </code> </code>
  
-=== Notes ===+==== Notes ====
  
   * The payload includes several ''_links'' arrays. These contain helpful URI's that could be used through the Hypermedia API if you're also making use of that. If not, these can be safely ignored.   * The payload includes several ''_links'' arrays. These contain helpful URI's that could be used through the Hypermedia API if you're also making use of that. If not, these can be safely ignored.
Line 281: Line 300:
  
  
-==== Sending a response ====+===== Sending a response =====
  
 In response, FoxyCart expects a JSON payload in the following format to be output on the page (prettified for display purposes): In response, FoxyCart expects a JSON payload in the following format to be output on the page (prettified for display purposes):
  
-=== Approve ===+==== Approve ====
  
 <code javascript> <code javascript>
Line 294: Line 313:
 </code> </code>
  
-=== Reject ===+Note that if you're using [[/gateways:square_platform|the Square Platform payment splitting integration]], an additional parameter of ''payment_logic'' can be passed through as well. 
 + 
 +==== Reject ====
  
 <code javascript> <code javascript>
Line 309: Line 330:
 </WRAP> </WRAP>
  
-==== Example Endpoint ====+===== Example Endpoint =====
  
-The following is an example PHP endpoint that could be used to handle the pre-payment hook:+The following is an example PHP endpoint that could be used to handle the pre-payment hook. Note that this is for illustrative purposes only. It'll work as is, but blocking based on IP or email isn't necessarily a recommended approach:
  
 <code php> <code php>
Line 320: Line 341:
 $response = array( $response = array(
     'ok' => true,     'ok' => true,
-    'details' => ''+    'details' => "Sorry, we couldn't process your transaction. Please contact us to proceed."
 ); );
  
 +$log_file = './log.txt';
 +$date = new DateTime();
 +$date_string = $date->format('Y-m-d H:i:s');
 +
 +$log_line = $date_string . ': ' . $cart_details['customer_ip'] . ' - '. $cart_details['_embedded']['fx:customer']['email'] . ' -- ';
 +
 +// Example: Loop through cart items and reject on specific product names
 foreach($cart_details['_embedded']['fx:items'] as $item) { foreach($cart_details['_embedded']['fx:items'] as $item) {
     if ($item['name'] == 'Example Product') {     if ($item['name'] == 'Example Product') {
Line 329: Line 357:
     }     }
 } }
 +
 +// Example: Reject on specific IP addresses
 +// The IPs to block should be in a separate file named `ips_to_reject.txt`
 +// Note that this looks for exact matches.
 +// If you wanted to check CIDR ranges, try adding something like https://github.com/tholu/php-cidr-match
 +$ips_to_reject = file('./ips_to_reject.txt', FILE_IGNORE_NEW_LINES | FILE_SKIP_EMPTY_LINES);
 +if ($ips_to_reject) {
 +  foreach ($ips_to_reject as $ip) {
 +    if ($ip == $cart_details['customer_ip']) {
 +      $log_line .= "IP MATCH: $ip";
 +      $response['ok'] = false;
 +      break;
 +    }
 +  }
 +}
 +
 +// Example: Reject on specific email addresses (exact matches)
 +// The emails to block should be in a separate file named `emails_to_reject.txt`
 +$emails_to_reject = file('./emails_to_reject.txt', FILE_IGNORE_NEW_LINES | FILE_SKIP_EMPTY_LINES);
 +if ($emails_to_reject) {
 +  foreach ($emails_to_reject as $email) {
 +    if (trim($email) == trim($cart_details['_embedded']['fx:customer']['email'])) {
 +      $log_line .= "EMAIL MATCH. REJECTING.";
 +      $response['ok'] = false;
 +      break;
 +    }
 +  }
 +}
 +
 +$log_line .= (string) $response['ok'] . "\n";
 +$fp = fopen($log_file, 'a');
 +fwrite($fp, $log_line);
  
 header('Content-Type: application/json'); header('Content-Type: application/json');
Line 334: Line 394:
 </code> </code>
  
-==== Debugging Errors ====+===== Debugging Errors =====
  
 If your pre-payment hook endpoint fails to return a response, or returns a non-JSON response, a error will be added to your store's error log in the administration.  If your pre-payment hook endpoint fails to return a response, or returns a non-JSON response, a error will be added to your store's error log in the administration. 

Site Tools