Differences
This shows you the differences between two versions of the page.
Both sides previous revisionPrevious revisionNext revision | Previous revision | ||
v:2.0:webhooks [2019/11/05 13:48] – [Sending Webhooks & Automatic Retries] marija | v:2.0:webhooks [2023/11/28 17:27] (current) – [Setting up your Webflow collections] marija | ||
---|---|---|---|
Line 3: | Line 3: | ||
===== Overview ===== | ===== Overview ===== | ||
- | Foxy's Webhook functionality allows you to create integrations which subscribe to notifications of new transactions | + | Foxy's Webhook functionality allows you to create integrations which subscribe to notifications of events |
+ | |||
+ | We currently have three different types of Webhook endpoints you can utilise, depending on your needs: | ||
- | We currently have four different types of Webhook endpoints you can utilise, depending on your needs: | ||
* [[# | * [[# | ||
- | * [[# | ||
* [[# | * [[# | ||
* [[# | * [[# | ||
Line 14: | Line 14: | ||
===== Sending Webhooks & Automatic Retries ===== | ===== Sending Webhooks & Automatic Retries ===== | ||
- | When a new transaction is placed and your webhooks are triggered, Foxy will wait for 1 minute for a response from your webhook endpoint. If a webhook fails to respond successfully (that is, if we don't receive a // | + | When webhooks are triggered |
+ | |||
+ | ===== Transaction Statuses ===== | ||
+ | |||
+ | For working with transactions with the webhook, a '' | ||
+ | |||
+ | ^ Status | ||
+ | | // | ||
+ | | '' | ||
+ | | '' | ||
+ | | '' | ||
+ | | '' | ||
+ | | '' | ||
+ | | '' | ||
+ | | '' | ||
+ | | '' | ||
+ | | '' | ||
+ | | '' | ||
+ | | '' | ||
+ | | '' | ||
+ | |||
+ | Those statuses that are marked as "// | ||
+ | |||
+ | The '' | ||
+ | |||
+ | Some gateways will trigger multiple web hooks to be sent for a single transaction, | ||
===== PayPal, Amazon Pay, and other Hosted Gateways ===== | ===== PayPal, Amazon Pay, and other Hosted Gateways ===== | ||
Line 22: | Line 47: | ||
</ | </ | ||
- | If you use any of the hosted gateways, note that every transaction may generate more than one notification. | + | If you use any of the hosted gateways |
- | Every time our IPN (Instant Payment Notification) server gets a notification from the gateway we also send you a notification. Generally, these notifications should arrive to your webhook endpoint in order, but it's possible that these webhooks are sent to your endpoint within a //very// short window (less than 0.5 seconds), and with possible network delays, your endpoint may receive the notifications out of order. Make sure you account for the '' | + | |
- | The webhook will include | + | Every time our IPN (Instant Payment Notification) server gets a notification from the gateway we also send you a notification. |
- | For instance, depending | + | The '' |
+ | |||
+ | Most hosted gateways usually send 2 notifications: | ||
Here is the current list of hosted gateways which take advantage of the status field: | Here is the current list of hosted gateways which take advantage of the status field: | ||
Line 46: | Line 72: | ||
* Mollie | * Mollie | ||
* Ogone | * Ogone | ||
+ | * PayPal Commerce Platform | ||
* PayPal Express Checkout | * PayPal Express Checkout | ||
* PayPal Plus | * PayPal Plus | ||
Line 61: | Line 88: | ||
: The title of the webhook | : The title of the webhook | ||
; '' | ; '' | ||
- | : The type of webhook - '' | + | : The type of webhook - '' |
; '' | ; '' | ||
: The error message received from the endpoint, trimmed to 500 characters. For the JSON Webhook this is the body of the response. | : The error message received from the endpoint, trimmed to 500 characters. For the JSON Webhook this is the body of the response. | ||
Line 69: | Line 96: | ||
Along with the error log, an email will also be sent to the store' | Along with the error log, an email will also be sent to the store' | ||
- | ==== Did the transaction | + | ==== Did the event complete? ==== |
- | The transaction | + | The event that triggered the webhook still completed successfully. If it was a transaction webhook, the customer was charged and you'll receive payment for the transaction as your chosen payment gateway processes it. |
==== Troubleshooting Webhook Errors ==== | ==== Troubleshooting Webhook Errors ==== | ||
Line 88: | Line 115: | ||
After triggering the transaction to be sent to your webhook again, the system will re-attempt the process again for another hour [[# | After triggering the transaction to be sent to your webhook again, the system will re-attempt the process again for another hour [[# | ||
+ | |||
====== JSON Webhook ====== | ====== JSON Webhook ====== | ||
The JSON webhook is, as you may have guessed, a JSON formatted payload sent to your endpoint. | The JSON webhook is, as you may have guessed, a JSON formatted payload sent to your endpoint. | ||
+ | |||
+ | The below documentation is for our latest version of our webhooks functionality (currently labelled as " | ||
+ | |||
+ | ===== Creating a webhook ===== | ||
+ | |||
+ | JSON webhooks can be created from the " | ||
+ | |||
+ | Each webhook requires a name, a URL and an encryption key (which will be automatically set with a value). Enter an identifying name and the URL to the endpoint that will be receiving the webhook payload. We'll explain how to create that endpoint in the next section. | ||
+ | |||
+ | If you'd like to provide your own encryption key for the webhook, click the "Show secret" | ||
+ | |||
+ | ==== Subscribed resources ==== | ||
+ | |||
+ | There are several different resource types that you can subscribe to for the webhooks, one resource per webhook. The following resource types are currently supported: | ||
+ | |||
+ | === Transactions === | ||
+ | |||
+ | Triggered whenever a transaction is completed, it's payment status is updated, or it is captured/ | ||
+ | |||
+ | Events: '' | ||
+ | |||
+ | === Subscriptions === | ||
+ | |||
+ | Triggered whenever a subscription resource is created or updated. Subscriptions are created when first purchased as part of a transaction, | ||
+ | |||
+ | Events: '' | ||
+ | |||
+ | === Customers === | ||
+ | |||
+ | Triggered whenever a customer resource is created or updated. Currently not triggered based on creation/ | ||
+ | |||
+ | Events: '' | ||
+ | |||
+ | |||
+ | <WRAP center round info 95%> | ||
+ | Note: Once you have created a webhook, it's not supported to change the subscribed resource type. If you need to change that for a given resource, you can delete the existing webhook and create another. | ||
+ | </ | ||
+ | |||
+ | |||
+ | ==== API filter query string ==== | ||
+ | |||
+ | The JSON webhooks uses our API as the source of data, and by default will just return the base resource as the payload (for example, the transaction webhook will just send the [[https:// | ||
+ | |||
+ | The following are examples of query strings that you might want to use: | ||
+ | |||
+ | === Transactions === | ||
+ | |||
+ | * Provide all data related to the transaction (default)\\ < | ||
+ | * Just send the transaction ID and status\\ < | ||
+ | |||
+ | === Subscriptions === | ||
+ | |||
+ | * Provide all data related to the subscription (default)\\ < | ||
+ | |||
+ | === Customers === | ||
+ | |||
+ | * Provide all data related to the customer (default)\\ < | ||
+ | |||
+ | ==== Saving The Webhook ==== | ||
+ | |||
+ | To save changes to the webhook, click the " | ||
+ | |||
+ | Upon saving, a '' | ||
+ | |||
+ | ===== Testing Webhooks: Helpful Tips ===== | ||
+ | |||
+ | It's often helpful to see exactly what the webhook request (sent to your servers) looks like. Though we don't offer this functionality natively, there are a variety of free services that you can use to send and view webhook requests. One we like is [[https:// | ||
+ | |||
+ | ===== Receiving a webhook ===== | ||
+ | |||
+ | Once you've configured your webhook - whenever actions happen that relate to the events you're subscribed to, a JSON payload containing information about that event will be sent to your endpoint. If your endpoint is secured with HTTPS, then the data is sent unencrypted ready for you to use. If your endpoint is not secured though, the data will be encrypted using '' | ||
+ | |||
+ | ==== Headers ==== | ||
+ | |||
+ | Any requests made to your webhook' | ||
+ | |||
+ | ^ Header ^ Description ^ | ||
+ | | '' | ||
+ | | '' | ||
+ | | '' | ||
+ | | '' | ||
+ | | '' | ||
+ | |||
+ | ==== Example Payload ==== | ||
+ | |||
+ | The JSON payload will follow the same structure as our Hypermedia API. Most of the objects will include the API's '' | ||
+ | |||
+ | The source of the payload data is our Hypermedia API, so you can use [[https:// | ||
+ | |||
+ | <WRAP center round info 95%> | ||
+ | Webhook payloads will always reflect the most current state of the resource at the time it was sent. If a webhook is resent, it will be the current state of the resource, rather than the state of the resource at the time that it was sent. | ||
+ | </ | ||
+ | |||
+ | |||
+ | In the example payloads below - to save space, the '' | ||
+ | |||
+ | === Transaction === | ||
+ | |||
+ | <code javascript> | ||
+ | " | ||
+ | " | ||
+ | " | ||
+ | " | ||
+ | " | ||
+ | " | ||
+ | { | ||
+ | " | ||
+ | " | ||
+ | " | ||
+ | " | ||
+ | " | ||
+ | " | ||
+ | }, | ||
+ | { | ||
+ | " | ||
+ | " | ||
+ | " | ||
+ | " | ||
+ | " | ||
+ | " | ||
+ | }, | ||
+ | { | ||
+ | " | ||
+ | " | ||
+ | " | ||
+ | " | ||
+ | " | ||
+ | " | ||
+ | } | ||
+ | ] | ||
+ | }, | ||
+ | " | ||
+ | " | ||
+ | " | ||
+ | " | ||
+ | " | ||
+ | " | ||
+ | " | ||
+ | " | ||
+ | " | ||
+ | " | ||
+ | " | ||
+ | " | ||
+ | " | ||
+ | " | ||
+ | " | ||
+ | }, | ||
+ | " | ||
+ | { | ||
+ | " | ||
+ | " | ||
+ | " | ||
+ | " | ||
+ | " | ||
+ | " | ||
+ | " | ||
+ | " | ||
+ | " | ||
+ | " | ||
+ | " | ||
+ | " | ||
+ | " | ||
+ | " | ||
+ | " | ||
+ | " | ||
+ | } | ||
+ | ], | ||
+ | " | ||
+ | { | ||
+ | " | ||
+ | " | ||
+ | " | ||
+ | { | ||
+ | " | ||
+ | " | ||
+ | " | ||
+ | " | ||
+ | " | ||
+ | " | ||
+ | " | ||
+ | }, | ||
+ | { | ||
+ | " | ||
+ | " | ||
+ | " | ||
+ | " | ||
+ | " | ||
+ | " | ||
+ | " | ||
+ | } | ||
+ | ], | ||
+ | " | ||
+ | " | ||
+ | " | ||
+ | " | ||
+ | " | ||
+ | " | ||
+ | " | ||
+ | " | ||
+ | " | ||
+ | " | ||
+ | " | ||
+ | " | ||
+ | " | ||
+ | " | ||
+ | " | ||
+ | " | ||
+ | " | ||
+ | " | ||
+ | " | ||
+ | " | ||
+ | " | ||
+ | " | ||
+ | " | ||
+ | " | ||
+ | " | ||
+ | " | ||
+ | " | ||
+ | " | ||
+ | } | ||
+ | }, | ||
+ | " | ||
+ | " | ||
+ | " | ||
+ | " | ||
+ | " | ||
+ | " | ||
+ | " | ||
+ | " | ||
+ | " | ||
+ | " | ||
+ | " | ||
+ | " | ||
+ | " | ||
+ | " | ||
+ | " | ||
+ | " | ||
+ | " | ||
+ | " | ||
+ | " | ||
+ | " | ||
+ | " | ||
+ | " | ||
+ | " | ||
+ | " | ||
+ | " | ||
+ | " | ||
+ | } | ||
+ | ], | ||
+ | " | ||
+ | { | ||
+ | " | ||
+ | " | ||
+ | " | ||
+ | " | ||
+ | " | ||
+ | " | ||
+ | " | ||
+ | " | ||
+ | " | ||
+ | " | ||
+ | } | ||
+ | ], | ||
+ | " | ||
+ | { | ||
+ | " | ||
+ | " | ||
+ | " | ||
+ | " | ||
+ | " | ||
+ | " | ||
+ | } | ||
+ | ], | ||
+ | " | ||
+ | { | ||
+ | " | ||
+ | " | ||
+ | " | ||
+ | " | ||
+ | " | ||
+ | " | ||
+ | " | ||
+ | " | ||
+ | " | ||
+ | } | ||
+ | ], | ||
+ | " | ||
+ | { | ||
+ | " | ||
+ | " | ||
+ | " | ||
+ | " | ||
+ | " | ||
+ | " | ||
+ | " | ||
+ | " | ||
+ | " | ||
+ | " | ||
+ | " | ||
+ | " | ||
+ | " | ||
+ | " | ||
+ | " | ||
+ | " | ||
+ | " | ||
+ | " | ||
+ | " | ||
+ | " | ||
+ | } | ||
+ | ], | ||
+ | " | ||
+ | { | ||
+ | " | ||
+ | " | ||
+ | " | ||
+ | " | ||
+ | " | ||
+ | " | ||
+ | " | ||
+ | " | ||
+ | " | ||
+ | " | ||
+ | " | ||
+ | " | ||
+ | " | ||
+ | " | ||
+ | } | ||
+ | ] | ||
+ | }, | ||
+ | " | ||
+ | " | ||
+ | " | ||
+ | " | ||
+ | " | ||
+ | " | ||
+ | " | ||
+ | " | ||
+ | " | ||
+ | " | ||
+ | " | ||
+ | " | ||
+ | " | ||
+ | " | ||
+ | " | ||
+ | " | ||
+ | " | ||
+ | " | ||
+ | " | ||
+ | " | ||
+ | " | ||
+ | " | ||
+ | " | ||
+ | " | ||
+ | " | ||
+ | " | ||
+ | }</ | ||
+ | |||
+ | Within the payload, the following attributes can be helpful for handling the payload: | ||
+ | |||
+ | ; '' | ||
+ | : What type of transaction this was, could be '' | ||
+ | |||
+ | === Subscription === | ||
+ | |||
+ | <code javascript> | ||
+ | " | ||
+ | // Note: These two links are included in order to illustrate where you can obtain subscription-related URLs. There are many other links included in the webhook, and you can explore them in our API documentation at https:// | ||
+ | " | ||
+ | " | ||
+ | " | ||
+ | " | ||
+ | }, | ||
+ | " | ||
+ | " | ||
+ | " | ||
+ | " | ||
+ | } | ||
+ | }, | ||
+ | " | ||
+ | " | ||
+ | " | ||
+ | " | ||
+ | " | ||
+ | { | ||
+ | " | ||
+ | " | ||
+ | " | ||
+ | " | ||
+ | " | ||
+ | " | ||
+ | }, | ||
+ | { | ||
+ | " | ||
+ | " | ||
+ | " | ||
+ | " | ||
+ | " | ||
+ | " | ||
+ | }, | ||
+ | { | ||
+ | " | ||
+ | " | ||
+ | " | ||
+ | " | ||
+ | " | ||
+ | " | ||
+ | } | ||
+ | ], | ||
+ | " | ||
+ | " | ||
+ | " | ||
+ | " | ||
+ | " | ||
+ | " | ||
+ | " | ||
+ | " | ||
+ | " | ||
+ | " | ||
+ | " | ||
+ | " | ||
+ | " | ||
+ | " | ||
+ | " | ||
+ | " | ||
+ | " | ||
+ | }, | ||
+ | " | ||
+ | " | ||
+ | " | ||
+ | " | ||
+ | " | ||
+ | " | ||
+ | " | ||
+ | " | ||
+ | " | ||
+ | " | ||
+ | " | ||
+ | " | ||
+ | " | ||
+ | " | ||
+ | " | ||
+ | " | ||
+ | " | ||
+ | } | ||
+ | }, | ||
+ | " | ||
+ | " | ||
+ | " | ||
+ | " | ||
+ | " | ||
+ | " | ||
+ | " | ||
+ | " | ||
+ | " | ||
+ | " | ||
+ | " | ||
+ | " | ||
+ | " | ||
+ | " | ||
+ | " | ||
+ | }, | ||
+ | " | ||
+ | " | ||
+ | " | ||
+ | " | ||
+ | { | ||
+ | " | ||
+ | " | ||
+ | " | ||
+ | { | ||
+ | " | ||
+ | " | ||
+ | " | ||
+ | " | ||
+ | " | ||
+ | " | ||
+ | " | ||
+ | }, | ||
+ | { | ||
+ | " | ||
+ | " | ||
+ | " | ||
+ | " | ||
+ | " | ||
+ | " | ||
+ | " | ||
+ | } | ||
+ | ], | ||
+ | " | ||
+ | " | ||
+ | " | ||
+ | " | ||
+ | " | ||
+ | " | ||
+ | " | ||
+ | " | ||
+ | " | ||
+ | " | ||
+ | " | ||
+ | " | ||
+ | " | ||
+ | " | ||
+ | " | ||
+ | " | ||
+ | " | ||
+ | " | ||
+ | " | ||
+ | " | ||
+ | " | ||
+ | " | ||
+ | " | ||
+ | " | ||
+ | " | ||
+ | " | ||
+ | " | ||
+ | " | ||
+ | } | ||
+ | }, | ||
+ | " | ||
+ | " | ||
+ | " | ||
+ | " | ||
+ | " | ||
+ | " | ||
+ | " | ||
+ | " | ||
+ | " | ||
+ | " | ||
+ | " | ||
+ | " | ||
+ | " | ||
+ | " | ||
+ | " | ||
+ | " | ||
+ | " | ||
+ | " | ||
+ | " | ||
+ | " | ||
+ | " | ||
+ | " | ||
+ | " | ||
+ | " | ||
+ | " | ||
+ | " | ||
+ | } | ||
+ | ], | ||
+ | " | ||
+ | { | ||
+ | " | ||
+ | " | ||
+ | " | ||
+ | " | ||
+ | " | ||
+ | " | ||
+ | } | ||
+ | ], | ||
+ | " | ||
+ | { | ||
+ | " | ||
+ | " | ||
+ | " | ||
+ | " | ||
+ | " | ||
+ | " | ||
+ | " | ||
+ | " | ||
+ | " | ||
+ | } | ||
+ | ] | ||
+ | }, | ||
+ | " | ||
+ | " | ||
+ | " | ||
+ | " | ||
+ | " | ||
+ | " | ||
+ | " | ||
+ | " | ||
+ | " | ||
+ | " | ||
+ | " | ||
+ | " | ||
+ | " | ||
+ | " | ||
+ | " | ||
+ | " | ||
+ | " | ||
+ | " | ||
+ | " | ||
+ | " | ||
+ | " | ||
+ | " | ||
+ | " | ||
+ | " | ||
+ | " | ||
+ | " | ||
+ | " | ||
+ | " | ||
+ | " | ||
+ | " | ||
+ | " | ||
+ | " | ||
+ | " | ||
+ | " | ||
+ | " | ||
+ | " | ||
+ | } | ||
+ | }, | ||
+ | " | ||
+ | " | ||
+ | " | ||
+ | " | ||
+ | " | ||
+ | " | ||
+ | " | ||
+ | " | ||
+ | " | ||
+ | " | ||
+ | " | ||
+ | " | ||
+ | " | ||
+ | }</ | ||
+ | |||
+ | |||
+ | === Customer === | ||
+ | |||
+ | <code javascript> | ||
+ | " | ||
+ | " | ||
+ | " | ||
+ | { | ||
+ | " | ||
+ | " | ||
+ | " | ||
+ | " | ||
+ | " | ||
+ | " | ||
+ | }, | ||
+ | { | ||
+ | " | ||
+ | " | ||
+ | " | ||
+ | " | ||
+ | " | ||
+ | " | ||
+ | }, | ||
+ | { | ||
+ | " | ||
+ | " | ||
+ | " | ||
+ | " | ||
+ | " | ||
+ | " | ||
+ | } | ||
+ | ], | ||
+ | " | ||
+ | " | ||
+ | " | ||
+ | " | ||
+ | " | ||
+ | " | ||
+ | " | ||
+ | " | ||
+ | " | ||
+ | " | ||
+ | " | ||
+ | " | ||
+ | " | ||
+ | " | ||
+ | " | ||
+ | " | ||
+ | " | ||
+ | }, | ||
+ | " | ||
+ | " | ||
+ | " | ||
+ | " | ||
+ | " | ||
+ | " | ||
+ | " | ||
+ | " | ||
+ | " | ||
+ | " | ||
+ | " | ||
+ | " | ||
+ | " | ||
+ | " | ||
+ | " | ||
+ | " | ||
+ | " | ||
+ | }, | ||
+ | " | ||
+ | " | ||
+ | " | ||
+ | " | ||
+ | " | ||
+ | " | ||
+ | " | ||
+ | " | ||
+ | " | ||
+ | }, | ||
+ | " | ||
+ | { | ||
+ | " | ||
+ | " | ||
+ | " | ||
+ | " | ||
+ | " | ||
+ | " | ||
+ | " | ||
+ | " | ||
+ | " | ||
+ | " | ||
+ | " | ||
+ | " | ||
+ | " | ||
+ | " | ||
+ | " | ||
+ | " | ||
+ | }, | ||
+ | { | ||
+ | " | ||
+ | " | ||
+ | " | ||
+ | " | ||
+ | " | ||
+ | " | ||
+ | " | ||
+ | " | ||
+ | " | ||
+ | " | ||
+ | " | ||
+ | " | ||
+ | " | ||
+ | " | ||
+ | " | ||
+ | " | ||
+ | } | ||
+ | ] | ||
+ | }, | ||
+ | " | ||
+ | " | ||
+ | " | ||
+ | " | ||
+ | " | ||
+ | " | ||
+ | " | ||
+ | " | ||
+ | " | ||
+ | " | ||
+ | " | ||
+ | " | ||
+ | " | ||
+ | " | ||
+ | " | ||
+ | }</ | ||
+ | |||
+ | |||
+ | ====== JSON Webhook (Legacy) ====== | ||
+ | |||
+ | The following information is for our legacy webhook functionality. If you're creating a new webhook, you'll use the new version documented above. | ||
===== Creating a webhook ===== | ===== Creating a webhook ===== | ||
Line 105: | Line 894: | ||
==== Webhook Events ==== | ==== Webhook Events ==== | ||
- | JSON webhooks can be triggered for different events that occur in your store, selected when creating or editing the webhook. Currently we support | + | JSON webhooks can be triggered for different events that occur in your store, selected when creating or editing the webhook. Currently we support events |
=== Transaction Created === | === Transaction Created === | ||
The Transaction Created webhook option receives any transaction for the store, whether it's a new transaction, | The Transaction Created webhook option receives any transaction for the store, whether it's a new transaction, | ||
+ | |||
+ | === Transaction Captured/ | ||
+ | |||
+ | <wrap hi>This currently relies on beta transaction editing functionality that is manually enabled on a per store basis.</ | ||
+ | |||
+ | The three events for Captured, Refunded and Voided occur when an existing transaction is either manually captured, refunded or voided. This can be triggered either through the transaction report section of the Foxy administration, | ||
+ | |||
+ | The original transaction (whether it was fully captured, or only authorized or verified) would have triggered the Transaction Created event at that time. The Captured, Refunded or Voided event is then in relation to the change of the payment status for the transaction. | ||
=== Subscription Cancelled === | === Subscription Cancelled === | ||
Line 114: | Line 911: | ||
The Subscription Cancelled event occurs when a subscription is actually ended, on the end date set on the subscription. | The Subscription Cancelled event occurs when a subscription is actually ended, on the end date set on the subscription. | ||
- | Subscriptions that are made inactive directly via the administration or the API **do not** trigger this event. Customers completing a '' | + | Subscriptions that are made inactive directly via the administration or the API **do not** trigger this event. Customers completing a '' |
===== Testing Webhooks: Helpful Tips ===== | ===== Testing Webhooks: Helpful Tips ===== | ||
Line 128: | Line 925: | ||
^ Header ^ Description ^ | ^ Header ^ Description ^ | ||
- | | '' | + | | '' |
| '' | | '' | ||
| '' | | '' | ||
Line 136: | Line 933: | ||
==== Example Payload ==== | ==== Example Payload ==== | ||
- | The JSON payload will follow much the same structure as our Hypermedia API. Most of the objects will include the API's '' | + | The JSON payload will follow much the same structure as our Hypermedia API. Most of the objects will include the API's '' |
The source of the payload data is our Hypermedia API, so you can use [[https:// | The source of the payload data is our Hypermedia API, so you can use [[https:// | ||
Line 441: | Line 1238: | ||
}, | }, | ||
" | " | ||
- | "currency": " | + | "currency_code": "USD", |
+ | " | ||
" | " | ||
" | " | ||
Line 470: | Line 1268: | ||
" | " | ||
" | " | ||
+ | " | ||
}</ | }</ | ||
Line 657: | Line 1456: | ||
if (is_array($parsedData)) { | if (is_array($parsedData)) { | ||
// Handle the payload | // Handle the payload | ||
- | | + | |
if ($event == " | if ($event == " | ||
// The following is an example of working with the transaction/ | // The following is an example of working with the transaction/ | ||
Line 685: | Line 1484: | ||
} | } | ||
} | } | ||
- | | + | |
} else { | } else { | ||
// JSON data not found | // JSON data not found | ||
Line 692: | Line 1491: | ||
return; | return; | ||
} | } | ||
+ | </ | ||
+ | |||
+ | === Node === | ||
+ | |||
+ | Note that you can also use the official [[https:// | ||
+ | <code javascript> | ||
+ | const crypto = require(' | ||
+ | const foxyEncryptionKey = ' | ||
+ | const foxyStoreId = ' | ||
+ | const foxyStoreDomain = ' | ||
+ | |||
+ | const http = require(' | ||
+ | const server = http.createServer(handleRequest); | ||
+ | |||
+ | const routes = { | ||
+ | ' | ||
+ | } | ||
+ | |||
+ | function handleRequest(request, | ||
+ | if (!validFoxyRequest(request)) { | ||
+ | response.statusCode = 403; // Forbidden | ||
+ | response.write(' | ||
+ | return response.end(); | ||
+ | } | ||
+ | const bodyChunks = []; | ||
+ | |||
+ | request.on(' | ||
+ | request.on(' | ||
+ | let body = Buffer.concat(bodyChunks).toString() | ||
+ | if (!validFoxySignature(request.headers[' | ||
+ | response.statusCode = 403; // Forbidden | ||
+ | response.write(' | ||
+ | return response.end(); | ||
+ | } | ||
+ | try { | ||
+ | body = JSON.parse(body); | ||
+ | } catch(e) { | ||
+ | response.statusCode = 400; // Bad Request | ||
+ | response.write(' | ||
+ | return response.end(); | ||
+ | } | ||
+ | const foxyEvent = request.headers[' | ||
+ | const responseData = routes[foxyEvent](request.headers, | ||
+ | console.log(responseData); | ||
+ | if (responseData) { | ||
+ | response.statusCode = 200; | ||
+ | response.write(JSON.stringify(responseData)); | ||
+ | return response.end(); | ||
+ | } | ||
+ | response.statusCode = 500; | ||
+ | response.end(); | ||
+ | }); | ||
+ | } | ||
+ | |||
+ | function validFoxyRequest(request) { | ||
+ | const postMethod = request.method === ' | ||
+ | const headers = request.headers; | ||
+ | const routeForEventExists = Object.keys(routes).includes(headers[' | ||
+ | const foxySignatureExists = !!headers[' | ||
+ | const foxyStoreIdIsCorrect = headers[' | ||
+ | const foxyStoreDomainIsCorrect = headers[' | ||
+ | return postMethod && routeForEventExists && foxySignatureExists && foxyStoreIdIsCorrect && foxyStoreDomainIsCorrect; | ||
+ | } | ||
+ | |||
+ | function validFoxySignature(signature, | ||
+ | const referenceSignature = crypto.createHmac(' | ||
+ | console.log(referenceSignature); | ||
+ | return signature === referenceSignature; | ||
+ | } | ||
+ | |||
+ | function handleTransactionCreated(headers, | ||
+ | const emailAddress = body[' | ||
+ | const billingCountry = body[' | ||
+ | const shippingCountry = body[' | ||
+ | // Check if there is a Product A and its size | ||
+ | let hasSmallA = false;; | ||
+ | let hasLargeA = false;; | ||
+ | for (let item of body[' | ||
+ | const name = item[' | ||
+ | const quantity = item[' | ||
+ | const category = item[' | ||
+ | if(item[' | ||
+ | for (let itemOption of item[' | ||
+ | if (itemOption[' | ||
+ | if (itemOption[' | ||
+ | hasSmallA = true; | ||
+ | return { | ||
+ | ok: true, | ||
+ | details: "has small A" | ||
+ | } | ||
+ | } else if (itemOption[' | ||
+ | hasLargeA = true; | ||
+ | return { | ||
+ | ok: true, | ||
+ | details: "has large A" | ||
+ | } | ||
+ | } | ||
+ | } | ||
+ | } | ||
+ | } | ||
+ | } | ||
+ | } | ||
+ | |||
+ | server.listen(80); | ||
</ | </ | ||
Line 706: | Line 1609: | ||
return halt 500, " | return halt 500, " | ||
end | end | ||
- | + | ||
post '/ | post '/ | ||
request.body.rewind | request.body.rewind | ||
Line 714: | Line 1617: | ||
parsedData = JSON.parse(data) | parsedData = JSON.parse(data) | ||
- | | + | |
# Handle the payload | # Handle the payload | ||
puts parsedData[' | puts parsedData[' | ||
Line 794: | Line 1697: | ||
</ | </ | ||
- | ====== Legacy XML Webhook ====== | ||
- | |||
- | The Legacy XML Webhook matches our previous XML datafeed functionality, | ||
- | |||
- | The only new functionality that the Webhooks version introduces beyond the documentation linked above is the ability to specify multiple endpoints from the " | ||
====== Zapier ====== | ====== Zapier ====== | ||
Line 822: | Line 1720: | ||
Before connecting Foxy to your Webflow site - you first need to create the necessary product collection within the Webflow CMS. For details on how to create collections - you can [[https:// | Before connecting Foxy to your Webflow site - you first need to create the necessary product collection within the Webflow CMS. For details on how to create collections - you can [[https:// | ||
- | We also have a tutorial | + | We also have tutorials |
If you're creating your own collections, | If you're creating your own collections, | ||
Line 871: | Line 1769: | ||
Beyond the [[# | Beyond the [[# | ||
+ | |||
+ | ==== Product code ... not found ==== | ||
Specifically, | Specifically, | ||
Line 880: | Line 1780: | ||
If you experience this error, you'll first want to confirm where the product was added to the cart and ensure that the link/form has the correct code associated with the product. To be able to re-feed the webhook to Webflow, you will need to update the product in the CMS to have the matching code to how it was sent. | If you experience this error, you'll first want to confirm where the product was added to the cart and ensure that the link/form has the correct code associated with the product. To be able to re-feed the webhook to Webflow, you will need to update the product in the CMS to have the matching code to how it was sent. | ||
+ | |||
+ | If the product code in the transaction matches the product in your collection, you will also want to confirm that the configured settings for your Webflow connection on the " | ||
+ | |||
+ | ==== This item can't be published / CollectionSchemaChangedError ==== | ||
If you've edited your product collections schema without publishing the page, Webflow will prevent any publishing requests via the API until the changes are published. If you experience this error, you'll see an error like this within your store' | If you've edited your product collections schema without publishing the page, Webflow will prevent any publishing requests via the API until the changes are published. If you experience this error, you'll see an error like this within your store' | ||
Line 886: | Line 1790: | ||
Webhooks processing problems: | Webhooks processing problems: | ||
Your Site Name (webflow): Conflict: This item can't be published, as your Collection structure changed since the last site publish. Make sure your staging and live Collections match to continue. | Your Site Name (webflow): Conflict: This item can't be published, as your Collection structure changed since the last site publish. Make sure your staging and live Collections match to continue. | ||
+ | </ | ||
+ | < | ||
+ | Webhooks processing problems: | ||
+ | Webflow (webflow): CollectionSchemaChangedError: | ||
</ | </ | ||
- | To fix this, simply ensure any changes to your collection' | + | To fix these types of errors, simply ensure any changes to your collection' |