Ecosyste.ms: Awesome
An open API service indexing awesome lists of open source software.
https://github.com/orbit-apps/elixir-shopifyapi
https://github.com/orbit-apps/elixir-shopifyapi
library
Last synced: 15 days ago
JSON representation
- Host: GitHub
- URL: https://github.com/orbit-apps/elixir-shopifyapi
- Owner: orbit-apps
- License: apache-2.0
- Created: 2018-04-16T23:03:03.000Z (over 6 years ago)
- Default Branch: main
- Last Pushed: 2024-09-27T01:26:33.000Z (3 months ago)
- Last Synced: 2024-11-03T14:35:44.289Z (about 1 month ago)
- Topics: library
- Language: Elixir
- Size: 1.17 MB
- Stars: 29
- Watchers: 15
- Forks: 5
- Open Issues: 12
-
Metadata Files:
- Readme: README.md
- Changelog: CHANGELOG.md
- License: LICENSE
Awesome Lists containing this project
- awesome-shopify - orbit-apps/elixir-shopifyapi - ShopifyAPI and Plug.ShopifyAPI Elixir client. (Libraries / Elixir)
README
# ShopifyAPI and Plug.ShopifyAPI
- [ShopifyAPI and Plug.ShopifyAPI](#ShopifyAPI-and-PlugShopifyAPI)
- [Installation](#Installation)
- [Installing this app in a Shop](#Installing-this-app-in-a-Shop)
- [Configuration](#Configuration)
- [API Version](#API-Version)
- [Supervisor](#supervisor)
- [Background Runner](#Background-Runner)
- [Shops](#Shops)
- [Apps](#Apps)
- [AuthTokens](#AuthTokens)
- [Webhooks](#Webhooks)
- [GraphQL](#GraphQL)
- [Telemetry](#Telemetry)## Installation
The package can be installed by adding `shopify_api` to your list of dependencies in `mix.exs`.
```elixir
def deps do
[
{:shopify_api, github: "pixelunion/elixir-shopifyapi", tag: "v0.15.6"}
]
end
```Add it to your phoenix routes.
```elixir
scope "/shop" do
forward("/", ShopifyAPI.Router)
end
```To handle incoming webhooks from Shopify, add the `ShopifyAPI.Plugs.Webhook` to your `Endpoint` module (before the JSON parser configuration):
```elixir
plug ShopifyAPI.Plugs.Webhook,
app_name: "my-app-name",
prefix: "/shopify/webhook",
callback: {WebhookHandler, :handle_webhook, []}
```If you want persisted Apps, Shops, and Tokens add configuration to your functions.
```elixir
config :shopify_api, ShopifyAPI.AuthTokenServer,
initializer: {MyApp.AuthToken, :init, []},
persistence: {MyApp.AuthToken, :save, []}
config :shopify_api, ShopifyAPI.AppServer,
initializer: {MyApp.ShopifyApp, :init, []},
persistence: {MyApp.ShopifyApp, :save, []}
config :shopify_api, ShopifyAPI.ShopServer,
initializer: {MyApp.Shop, :init, []},
persistence: {MyApp.Shop, :save, []}
```## Installing this app in a Shop
There is a boilerplate repo for quickly getting up and running at [ShopifyApp](https://github.com/pixelunion/elixir-shopify-app)
1. Start something like ngrok
2. Configure your app to allow your ngrok url as one of the redirect_urls
3. Point your browser to `http://localhost:4000/shop/install?shop=your-shop.myshopify.com&app=yourapp` and it should prompt you to login and authorize it.## Configuration
### API Version
Shopify introduced API versioning here: https://help.shopify.com/en/api/versioning
Configure the version to use in your config.exs, it will default to a stable version as ref'd in the [request module](lib/shopify_api/rest/request.ex).
```elixir
config :shopify_api, ShopifyAPI.REST, api_version: "2019-04"
```### Supervisor
The ShopifyAPI has three servers for caching commonly-used structs - `AppServer`, `ShopServer`, and `AuthTokenServer`.
These act as a write-through caching layer for their corresponding data structure.A supervisor `ShopifyAPI.Supervisor` is provided to start up and supervise all three servers.
Add it to your application's supervision tree, and define [hooks for preloading data](#Installation).NOTE: Make sure you place the supervisor after any dependencies used in preloading the data. (ie Ecto)
Add the following to your application:
```elixir
def start(_type, _args) do
children = [
MyApp.Repo,
ShopifyAPI.Supervisor
]Supervisor.start_link(children, strategy: :one_for_one)
end
```## Webhooks
To set up your app to receive webhooks, first you'll need to add `ShopifyAPI.Plugs.Webhook` to your `Endpoint` module:
```elixir
plug ShopifyAPI.Plugs.Webhook,
app_name: "my-app-name",
prefix: "/shopify/webhook",
callback: {WebhookHandler, :handle_webhook, []}
```You'll also need to define a corresponding `WebhookHandler` module in your app:
```elixir
defmodule WebhookHandler do
def handle_webhook(app, shop, domain, payload) do
# TODO implement me!
end
end
```And there you go!
Now webhooks sent to `YOUR_URL/shopify/webhook` will be interpreted as webhooks for the `my-app-name` app.
If you append an app name to the URL in the Shopify configuration, that app will be used instead (e.g. `/shopify/webhook/private-app-name`).If you'd like to install webhooks using ShopifyAPI, we need to do a small bit more work:
```elixir
# Add this to your configuration so that ShopifyAPI knows the webhook prefix.
config :shopify_api, ShopifyAPI.Webhook, uri: "https://your-app-url/shop/webhook"
```Now once a shop is installed, you can create webhook subscriptions.
This will automatically append your app's name to the generated webhook URL:```elixir
token = ShopifyAPI.AuthTokenServer.get("shop domain", "app name")topic = "orders/create"
server_address = ShopifyAPI.REST.Webhook.webhook_uri(token)
webhook = %{topic: topic, address: server_address}ShopifyAPI.REST.Webhook.create(token, %{webhook: webhook})
```Documentation can be generated with [ExDoc](https://github.com/elixir-lang/ex_doc)
and published on [HexDocs](https://hexdocs.pm). Once published, the docs can
be found at [https://hexdocs.pm/shopify_api](https://hexdocs.pm/shopify_api).## GraphQL
`GraphQL` implementation handles GraphQL Queries against Shopify API using HTTPoison library as client, this initial implementation consists of hitting Shopify GraphQL and returning the response in a tuple `{:ok, %Response{}} | {:error, %Response{}}` containing the response and metadata(actualQueryCost, throttleStatus).
Configure the version to use in your config.exs, it will default to a stable version as ref'd in the [graphql module](lib/shopify_api/graphql.ex).
```elixir
config :shopify_api, ShopifyAPI.GraphQL, graphql_version: "2019-07"
```### GraphQL Response
Because `GraphQL responses` can be a little complex we are parsing/wraping responses `%HTTPoison.response` to `%GraphQL.Response`.
Successful response:
```elixir
{:ok, %ShopifyAPI.GraphQL.Response{response: %{}, metadata: %{}, status_code: code}}
```Failed response:
```elixir
{:error, %HTTPoison.Response{}}
```## Telemetry
The `shopify_api` library will emit events using the [`:telemetry`](https://github.com/beam-telemetry/telemetry) library. Consumers of `shopify_api` can then use these events for customized metrics aggregation and more.
The following telemetry events are generated:
- `[:shopify_api, :rest_request, :success]`
- `[:shopify_api, :rest_request, :failure]`
- `[:shopify_api, :throttling, :over_limit]`
- `[:shopify_api, :throttling, :within_limit]`
- `[:shopify_api, :graphql_request, :success]`
- `[:shopify_api, :graphql_request, :failure]`
- `[:shopify_api, :bulk_operation, :success]`
- `[:shopify_api, :bulk_operation, :failure]`As an example, you could use an external module to instrument API requests made by `shopify_api`:
```elixir
defmodule Instrumenter do
def setup do
events = [
[:shopify_api, :rest_request, :success],
[:shopify_api, :rest_request, :failure]
]:telemetry.attach_many("my-instrumenter", events, &handle_event/4, nil)
enddef handle_event([:shopify_api, :rest_request, :success], measurements, metadata, _config) do
# Ship success events
end
end```