Packages
shopifex
0.3.2
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 =
Regex.named_captures(~r/(?:hmac=[^&]*)&(?'query_string'.*)/, conn.query_string)
|> case do
nil ->
""
regex_captures when is_map(regex_captures) ->
Map.get(regex_captures, "query_string", "")
end
|> URI.decode()
|> (fn query_string ->
if Map.has_key?(conn.query_params, "ids") do
# This absolutely rediculous solution: https://community.shopify.com/c/Shopify-Apps/Hmac-Verification-for-Bulk-Actions/m-p/590611#M18504
query_string = Regex.replace(~r/ids\[\]\=[0-9]*\&/, query_string, "")
ids_section = Enum.join(conn.query_params["ids"], ~s(", "))
~s(ids=["#{ids_section}"]&#{query_string})
else
query_string
end
end).()
{
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_url = conn.params["myshopify_domain"] || conn.query_params["shop"]
shop = Shopifex.Shops.get_shop_by_url(shop_url)
Shopifex.Plug.ShopifySession.put_shop_in_session(conn, shop)
else
Logger.info("HMAC doesn't match " <> our_hmac)
conn
|> send_resp(401, "invalid hmac signature")
|> halt()
end
end
end