Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Feat/datastore orderdesk #7

Closed
wants to merge 69 commits into from
Closed
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
69 commits
Select commit Hold shift + click to select a range
1c2bdff
refactor(prepaymentwebflow): allow for easier sharing
ndvo Mar 31, 2021
96fee04
feat(orderdesk): fetch items from orderdesk
ndvo Mar 31, 2021
71c22da
feat(orderdesk): wip compare items in cart to inventory
ndvo Mar 31, 2021
9756a3f
test(orderdesk): wip begin implementing tests
ndvo Apr 1, 2021
1174a80
lint jsdoc
ndvo Apr 1, 2021
fc46b67
dependencies: remove eslint-config-airbnb base as a dev dep
ndvo Apr 1, 2021
eb96342
feat(cartvalidator): add a cartvalidator module
ndvo Apr 2, 2021
6948181
fix(orderdeskclietn): fix orderdesk item definition
ndvo Apr 2, 2021
1ba4a3d
feat(orderdeskclient): convert to canonical
ndvo Apr 2, 2021
db5c196
test(cartvalidator): add tests
ndvo Apr 3, 2021
f3555ef
feat: centralize environment variables definition
ndvo Apr 6, 2021
f4533b7
docs(config): add basic documentation
ndvo Apr 6, 2021
a13c3f6
fix(config): standardize env variables while maintaining backwords co…
ndvo Apr 6, 2021
0d381c4
fix(config): standardize environment variables
ndvo Apr 6, 2021
dd4cb5d
fix: use centralized env variables
ndvo Apr 7, 2021
a0e0af1
refactor: separate a datastore class from the controller
ndvo Apr 7, 2021
5e51d34
test(orderdesk): add basic tests
ndvo Apr 7, 2021
8d818d0
doc(readme): incorporate datastore help
ndvo Apr 7, 2021
5d01509
doc(orderdesk): add a readme file
ndvo Apr 7, 2021
883a19c
feat(config): one variable credentials config
ndvo Apr 7, 2021
a5995b0
test: add chai as promised as a dependency
ndvo Apr 7, 2021
b45ea1b
feat(orderdesk): controls for webhook endpoints
ndvo Apr 7, 2021
2d14e0b
feat: add foxy webhook handler as a module
ndvo Apr 7, 2021
a3e94f3
chore: gitigore
ndvo Apr 7, 2021
b59955c
chore: install nyc & parse credentials
ndvo Apr 8, 2021
c8a5579
fix(orderdesk): update items filter
ndvo Apr 8, 2021
d0676c1
test(orderdesk): add datastore tests
ndvo Apr 8, 2021
81ca25e
fix(orderdesk): import error
ndvo Apr 8, 2021
3b066e8
fix(orderdesk): add foxy encryption key to the config validation
ndvo Apr 8, 2021
2ddd2aa
test(orderdesk): test config validation
ndvo Apr 8, 2021
8e58d03
fix(orderdesk): adhere to netlify functions convention
ndvo Apr 8, 2021
11a8ac2
fix(orderdesk): import error
ndvo Apr 8, 2021
21abd35
test(foxywebhook): add initial tests
ndvo Apr 8, 2021
e98ff98
fix(orderdesk): implement unit tests and consequent fixes
ndvo Apr 9, 2021
90a0a31
fix: config import
ndvo Apr 14, 2021
f7b9386
fix(datastore): import node-fetch
ndvo Apr 14, 2021
488f1b8
fix(orderdesk): preserve all fields of orderdesk item in canonical item
ndvo Apr 14, 2021
51c2ce5
fix(orderdesk): body must be parsed
ndvo Apr 14, 2021
1ac46a9
fix(orderdesk): headers are lowercase
ndvo Apr 14, 2021
839f504
fix(orderdesk): transaction deduction request
ndvo Apr 14, 2021
8f7e23a
fix(orderdesk): allow for pre-payment webhook to have no signature
ndvo Apr 14, 2021
f99d386
feat(orderdesk): create an order in OrderDesk
ndvo Apr 15, 2021
6dc8629
feat(datastore-integration): improve documentation
ndvo Apr 16, 2021
a569727
chore: update dependencies
ndvo Apr 16, 2021
9386d2a
docs: add missing jsdoc
ndvo Apr 16, 2021
9f00a32
fix(orderdesk): add keys to cannonical items regardless of content
ndvo Apr 16, 2021
5a510aa
test(orderdesk): fix test as content-type header is now required
ndvo Apr 16, 2021
1d3aaf5
fix(orderdesk): if there is no cart items pair is empty
ndvo Apr 16, 2021
f6bd8a4
fix: remove unused code
ndvo Apr 16, 2021
525dabf
test: fix mock cart
ndvo Apr 16, 2021
2ff46c9
docs(datastoreintegration): workflow graph
ndvo Apr 16, 2021
9619ffe
fix(prepayment-webflow): typo weblow to webflow
ndvo Apr 16, 2021
2ef4066
Update README.md
ndvo Apr 16, 2021
a933276
fix(orderdesk): remove unused code
ndvo Apr 16, 2021
4a1880c
Merge branch 'feat/datastore-orderdesk' of github.com:Foxy/foxy-node-…
ndvo Apr 16, 2021
c8c393d
chore: update dependency
ndvo Apr 16, 2021
e2611df
docs: Tidy readme
brettflorio Apr 17, 2021
77c94f2
refactor: move tests to test folder
ndvo Apr 17, 2021
9b265c0
Merge branch 'feat/datastore-orderdesk' of github.com:Foxy/foxy-node-…
ndvo Apr 17, 2021
65837a1
fix: typo: suficient -> sufficient
ndvo Apr 17, 2021
4fe13b5
fix(cartvalidation): consistent naming
ndvo Apr 17, 2021
45c5903
feat(orderdesk): inventory update skipping
ndvo Apr 17, 2021
6c51dd2
feat(orderdesk): skip updating inventory by default
ndvo Apr 17, 2021
31791f1
refactor(orderdesk): move message composition to FoxyWebhook class
ndvo Apr 17, 2021
0e6491f
test(cart): add basic tests
ndvo Apr 20, 2021
2595d75
refactor(idevaffiliate): use FoxyWebhook validate
ndvo Apr 20, 2021
27cc24b
refactor(idevaffiliate): refactor to ease tests and understanding
ndvo Apr 20, 2021
1fcd53c
Merge branch 'main' into feat/datastore-orderdesk
ndvo Apr 26, 2021
2a05c13
fix: node-api version downgrade
ndvo Apr 27, 2021
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
5 changes: 4 additions & 1 deletion .eslintrc.js
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,10 @@ module.exports = {
commonjs: true,
es2021: true,
},
extends: "@foxy.io",
extends: [
"@foxy.io",
"plugin:jsdoc/recommended"
],
parserOptions: {
ecmaVersion: 12,
},
Expand Down
22 changes: 21 additions & 1 deletion .gitignore
Original file line number Diff line number Diff line change
@@ -1,6 +1,13 @@
node_modules
dist

# Istanbul code coverage files and folders
.nyc_output
coverage

# ctags files
tags

# Local Netlify folder
.netlify

Expand All @@ -9,4 +16,17 @@ dist
.env

# VSCode and other editor-specific files
tempCodeRunner*
tempCodeRunner*

.idea

### Vim ###
[._]*.s[a-v][a-z]
[._]*.sw[a-p]
[._]s[a-v][a-z]
[._]sw[a-p]
Session.vim
.netrwhist
*~
.vimrc
.vimlocal
63 changes: 57 additions & 6 deletions README.md
Original file line number Diff line number Diff line change
@@ -1,15 +1,66 @@
# Netlify Serverless Functions for the Foxy.io API

This repository allows for easily creating serverless functions to work with the Foxy.io API, deployed using Netlify. The goal is to make this as approachable as possible, so we're avoiding unnecessary
This repository allows you to (more) easily create serverless functions to work with the Foxy.io API, deployed using Netlify. The goal is to make this as approachable as possible, so we try to have reasonable default behaviours, and Netlify is a great choice because of the one-click deployment. Once you deploy to Netlify, you can modify your own GitHub files to customize as needed.

## Functions

The functions provided in this repository can be used independently, or as a reference for building your own functinos.
Be sure to check the README for each function in the functions folder.
The functions provided in this repository can be used independently, or as a reference for building your own functions. Be sure to check the README for each function in the functions folder.

- [cart](src/functions/cart): Converts a cart between recurring and non-recurring.
- [idevaffiliate-marketplace](src/functions/idevaffiliate-marketplace):
- [pre-payment-webhook-webflow](src/functions/pre-payment-webhook-webflow): Validates the price and/or availability of items against Webflow CMS collections before a payment is processed.
- [cart](src/functions/cart): Converts a cart between recurring and non-recurring. Useful in an upsell flow.
- [idevaffiliate-marketplace](src/functions/idevaffiliate-marketplace): A marketplace-style integration, using iDevAffiliate.
- Datastore integrations:
- [pre-payment-webhook-webflow](src/functions/pre-payment-webhook-webflow): Validates the price and/or availability of items against Webflow CMS collections before a payment is processed.
- [datastore-integration-orderdesk](src/functions/datastore-integration-orderdesk): Validates the cart against OrderDesk and updates the inventory upon successful transaction.

### Data Store Integrations

Data store integrations allow you to verify the cart against a third-party Data Store.

Your customer workflow is basically unchanged.

The image below shows the order flow, with the gray steps showing the functionality provided by these functions (invisible to the customer). Notice that upon cart submit the pre-payment validation is triggered. The webhook makes a request to this function, which then gets the inventory and price information from your data store (Webflow or OrderDesk), and checks if the cart is valid.

![Data Store Integration workflow](https://github.com/Foxy/foxy-node-netlify-functions/blob/feat/datastore-orderdesk/images/datastore-integrations-workflow.png?raw=true)

- You may choose not to validate prices at all or for specific items.
- You may choose not to validate the inventory.
- Depending on your data store, you may have other configuration available.


#### Available DataStores

- [OrderDesk](https://www.orderdesk.com)
- [Webflow CMS](https://webflow.com)

#### The Foxy Pre-Payment Webhook

The pre-payment webhook fires before a transaction is submitted to the payment processor (Stripe, Authorize.net, PayPal, etc.). We'll use that with these functions to prevent overselling, and also to prevent product link/form tampering if you can't use Foxy's [link+form signing](https://wiki.foxycart.com/v/2.0/hmac_validation) (either directly or via [the Cloudflare Worker hmac signing function](https://github.com/Foxy/foxy-cloudflare-addtocart-signing) to do it automatically).

**It ignores existing subscriptions**. If a subscription start date is "today", the price will be checked. If it is in the past, the price is not checked.

#### Limitations

- It does not handle discounts.
- It does not handle item options, such as `price_mod`.
- Due to netlify time limit, and the need to make requests to the datastore, it
may break against large product databases if the Datastore do not allow for
requesting specific items directly. Check the README for your datastore
integration about this issue.

#### Usage

1. Read the short **Configuration** section in the datastore integration page.
- **Important**: Your datastore must meet some criteria for the webhook to work. Product items need a `code` field.
1. Grab the credentials needed for integrating with your datastore. Check the details in your datastore integration page.
1. Click the **deploy to Netlify** button at the end of this page.
- Netlify will provide you with a form for you to provide your configuration.
- The Webflow Prepayment Webhook requires only `FOXY_WEBFLOW_TOKEN`. The other settings are used for the other services in this repository.
1. Grab the URL for your webhook in Netlify. Be sure to get the correct URL for your specific webhook.
- To do this, after the deploy is finished, click the "functions" tab, look for your webhook function and copy the **Endpoint URL**.
1. Configure your prepayment webhook using your endpoint. Check the docs here: https://wiki.foxycart.com/v/2.0/pre_payment_webhook


# Development

## Localdev Setup

Expand Down
74 changes: 74 additions & 0 deletions doc/datastore-integration.dot
Original file line number Diff line number Diff line change
@@ -0,0 +1,74 @@
digraph G {
node [shape = box];
newrank=true;
rankdir=TB;


subgraph clusterCustomer {
label="Customer\n\nYour customer workflow\nremains fluid.";
chooseProduct[label="Choose\nproducts"];
goToCart[label="Go to\ncart"];
success[label="Success"];
goToCart->success[style=invis];
}

subgraph clusterFoxy {
label="Foxy.io";
cart[label="Cart"];
cartSubmit[label="Cart\nSubmit"];
cartProcess[label="Payment\nprocessing", color="gray"];
}

subgraph clusterWebhook {
label="Datastore Integration Webhook";
color="gray";
prepaymentValidation[label="Prepayment\ntransaction\nvalidation", color="gray"];
transactionCreated[label="Transaction\nCreated", color="gray"];

prepaymentValidation->transactionCreated[style=invis];
}

subgraph clusterDatastore {
label="Datastore";
color="gray";
getInventory[label="get\nInventory", color="gray"];
getPrice[label="get\nPrice", color="gray"];
updateInventory[label="update\nInventory", color="gray"];
}

chooseProduct->goToCart;

goToCart->cart;

cart->cartSubmit;

cartSubmit->prepaymentValidation[dir="both"; label="is trasaction valid?"; style="dashed", fontsize="10px"];

cartSubmit->cartProcess;

cartProcess->transactionCreated[label="successful transaction"; style="dashed", fontsize="10px"];

prepaymentValidation->getPrice[dir="both"; label="is price correct?", style="dashed", color=blue; fontcolor=blue; fontsize="10px"];
prepaymentValidation->getInventory[dir="both"; label="is price correct?", style="dashed", color=blue; fontcolor=blue; fontsize="10px"];
transactionCreated->updateInventory[label="update inventory", style="dashed", color=blue; fontcolor=blue; fontsize="10px"];

cartProcess->success;
cartSubmit->cart[label="if invalid,\ntry again", fontsize="10px", color="red", style="dashed", fontcolor=red];

{rank=same;
goToCart; cart;
}

{rank=same;
cartSubmit; prepaymentValidation;
}

{rank=same;
cartProcess; transactionCreated;
}

{rank=same;
chooseProduct; getInventory; updateInventory; getPrice
}

}
Binary file added images/datastore-integrations-workflow.png
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
9 changes: 5 additions & 4 deletions netlify.toml
Original file line number Diff line number Diff line change
Expand Up @@ -7,7 +7,8 @@
FOXY_API_CLIENT_ID = "Enter your Foxy.io API Client ID here."
FOXY_API_CLIENT_SECRET = "Enter your Foxy.io API Client Secret here."
FOXY_API_REFRESH_TOKEN = "Enter your Foxy.io API Refresh Token here."
DEFAULT_AUTOSHIP_FREQUENCY = "Default autoship frequency (such as `1m`)"
IDEV_SECRET_KEY = "iDevAffiliate secret key (from the API settings)"
IDEV_API_URL = "iDevAffiliate API URL (from the API settings; should end in `sale.php`)"
WEBFLOW_TOKEN = "Webflow Token (from Webflow's project settings, at the 'Integrations' tab)"
FOXY_DEFAULT_AUTOSHIP_FREQUENCY = "Default autoship frequency (such as `1m`)"
FOXY_IDEV_SECRET_KEY = "iDevAffiliate secret key (from the API settings)"
FOXY_IDEV_API_URL = "iDevAffiliate API URL (from the API settings; should end in `sale.php`)"
FOXY_WEBFLOW_TOKEN = "Get this from Webflow's project settings, at the 'Integrations' tab."
FOXY_DATASTORE_CREDENTIALS = "Datastore credentials"
Loading