Voxie Shopify Integration Handoff === The current Shopify integration at the time of writing is an MVP stab at the feature. There are a few unfinished tasks that will prevent the feature from being scalable, as well as some code smells in the current implementation that need to be addressed sooner than later. ## Big issues ### Throttling Shopify's Rest Admin API has standard responses for rate limiting documented here: https://help.shopify.com/en/api/reference/rest-admin-api-rate-limits Throttling our outbound requests and handling 429's from Shopify is a MUST for our integration to be considered safe for Voxie customers. An important consideration is that our private app integration is not the only integration making requests to a Shopify store and we're sharing the bucket with all the integrations that individual store has added, which I believe includes public app integrations as well. ### Jobs Currently webhooks and data syncs are handled synchronously which is a big problem at scale. One instance of this is the `App\Console\CommandsShopifyCheckAbandonedCarts` command. This command gets triggered once every minute from an AWS Lambda which hits the `App\Http\Controllers\Api\WebhookCommandController` to kick off the "job". For one that class was a quick and dirty implementation and really should not be doing so much work but aside from that the actual request to shopify and logic needs to be kicked off from a job and ideally multiple jobs. Rather than looping over every store integration in the system and querying for abandoned checkouts we could be chunking the stores into more reasonably sized batches of work. ### Versioning A few things to be aware of with Shopify: 1. New versions of their API are released quarterly 2. API versions are only supported for 3 quarters 3. Our app's implementation gets the version from user input The last point is the most important one. After gaining more knowledge about Shopify's API it's clear that users should not have any say in the API version. It should be maintained by us internally. The other two points are important too. 1 year from now the API could change and the current integration with Shopify may break. Shopify automatically defers API calls to the oldest supported version even if you pass an older unsupported version in your query. For example, we currently wrote our implementation against version `2019-04` which will be supported for the next 3 releases. However, this time next year if we try to use `2019-04`, Shopify will default to version `2019-07` instead which may have breaking changes we didn't account for. **It's important that Voxie adopts a maintenance schedule to keep the Shopify integration up to date with their API.** More details about versioning can be found in the official docs: https://help.shopify.com/en/api/versioning#the-api-version-release-schedule ## Minor issues - Remove `App\Events\Checkout` in favour of `App\ShopifyCheckout`. - The class was meant to be a temporary POPO while two features were being worked on in parallel. Unfortunately, the cleanup task just hasn't gotten priority yet. But it definitely needs to be refactored out in favour of `App\Checkout` instead - Reconsider `App\Checkout` and `App\ShopifyCheckout` - Originally we decided to add a `data` property to `Checkout` and serialize the actual checkout data from each vender i.e. Shopify, Magento, Woo-Commerce etc - The idea was that the implementation would have a small impact on the overall integration design and could be easy to refactor later instead of landing on a schema that locked us in when we don't know what the other vendor checkouts look like yet or if we ever need to support them. - It's been a bit more cumbersome to work with than anticipated and `App\ShopifyCheckout` could probably just be an Eloquent model with a polymorphic relationship between `App\Checkout`. This would allow the flexibility of supporting other vendor checkouts while still getting all the eloquent conveniences we’re essentially re-creating in our serializer - Rename occurrences of "cart" to "checkout". Early on we referred to "abandoned checkouts" as "abandoned carts". Shopify actually distinguishes between "Checkout" and "Cart" as different things so we should keep our naming straight on our end. "Cart" and "Checkout" should not be interchangeable terms, and currently in our app they mean the same thing.