Packages
shopifex
0.6.0
2.4.0
2.3.0
2.2.2
2.2.1
2.2.0
2.1.20
2.1.19
2.1.18
2.1.17
2.1.16
2.1.15
2.1.14
2.1.13
2.1.12
2.1.11
2.1.10
2.1.9
2.1.8
2.1.7
2.1.6
2.1.5
2.1.4
2.1.3
2.1.2
2.1.1
2.1.0
2.0.1
2.0.0
1.1.1
1.1.0
1.0.1
1.0.0
0.6.2
0.6.1
0.6.0
0.5.7
0.5.6
0.5.5
0.5.4
0.5.3
0.5.2
0.5.1
0.5.0
0.4.1
0.4.0
0.3.6
0.3.5
0.3.4
0.3.3
0.3.2
0.3.1
0.3.0
0.2.1
0.2.0
0.1.5
0.1.4
0.1.3
0.1.2
0.1.1
0.1.0
Phoenix boilerplate for Shopify Embedded App SDK
Current section
Files
Jump to
Current section
Files
lib/shopifex/plug/shopify_webhook.ex
defmodule Shopifex.Plug.ShopifyWebhook do
import Plug.Conn
require Logger
def init(options) do
# initialize options
options
end
@doc """
Ensures that the connection has a valid Shopify webhook HMAC token and puts the shop in conn.private
"""
def call(conn, _) do
{their_hmac, our_hmac} =
case conn.method do
"GET" ->
query_string =
conn.query_params
|> Enum.map(fn
{"hmac", _value} ->
nil
{"ids", value} ->
# This absolutely rediculous solution: https://community.shopify.com/c/Shopify-Apps/Hmac-Verification-for-Bulk-Actions/m-p/590611#M18504
ids =
Enum.map(value, fn id ->
"\"#{id}\""
end)
|> Enum.join(", ")
"ids=[#{ids}]"
{key, value} ->
"#{key}=#{value}"
end)
|> Enum.filter(&(!is_nil(&1)))
|> Enum.join("&")
{
conn.params["hmac"],
:crypto.hmac(
:sha256,
Application.fetch_env!(:shopifex, :secret),
query_string
)
|> Base.encode16()
|> String.downcase()
}
"POST" ->
case Plug.Conn.get_req_header(conn, "x-shopify-hmac-sha256") do
[header_hmac] ->
our_hmac =
:crypto.hmac(
:sha256,
Application.fetch_env!(:shopifex, :secret),
conn.assigns[:raw_body]
)
|> Base.encode64()
{header_hmac, our_hmac}
[] ->
conn
|> send_resp(401, "missing hmac signature")
|> halt()
end
end
if our_hmac == their_hmac do
shop =
case Plug.Conn.get_req_header(conn, "x-shopify-shop-domain") do
[shop_url] ->
shop_url
_ ->
conn.params["myshopify_domain"] || conn.query_params["shop"]
end
|> Shopifex.Shops.get_shop_by_url()
if shop do
Shopifex.Plug.ShopifySession.put_shop_in_session(conn, shop)
else
conn
|> send_resp(404, "no store found with url")
|> halt()
end
else
Logger.info("HMAC doesn't match " <> our_hmac)
conn
|> send_resp(401, "invalid hmac signature")
|> halt()
end
end
end