Skip to content

Commit 8a7e9e6

Browse files
Jamie DwyerJamie Dwyer
authored andcommitted
Initial commit
0 parents  commit 8a7e9e6

File tree

3 files changed

+152
-0
lines changed

3 files changed

+152
-0
lines changed

.gitignore

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1 @@
1+
.env

Gemfile

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,6 @@
1+
source 'https://rubygems.org'
2+
3+
gem 'sinatra'
4+
gem 'httparty'
5+
gem 'shopify_api', '~> 4.0.7'
6+
gem 'dotenv'

app.rb

Lines changed: 145 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,145 @@
1+
require 'shopify_api'
2+
require 'sinatra'
3+
require 'httparty'
4+
require 'dotenv'
5+
6+
class GiftBasket < Sinatra::Base
7+
8+
def initialize
9+
Dotenv.load
10+
@key = ENV['API_KEY']
11+
@secret = ENV['API_SECRET']
12+
@app_url = "jamied.ngrok.io"
13+
@tokens = {}
14+
super
15+
end
16+
17+
get '/giftbasket/install' do
18+
shop = request.params['shop']
19+
scopes = "read_orders,read_products,write_products"
20+
21+
# construct the installation URL and redirect the merchant
22+
install_url = "http://#{shop}/admin/oauth/authorize?client_id=#{@key}"\
23+
"&scope=#{scopes}&redirect_uri=https://#{@app_url}/giftbasket/auth"
24+
25+
redirect install_url
26+
end
27+
28+
get '/giftbasket/auth' do
29+
# extract shop data from request parameters
30+
shop = request.params['shop']
31+
code = request.params['code']
32+
hmac = request.params['hmac']
33+
34+
# perform hmac validation to determine if the request is coming from Shopify
35+
h = request.params.reject{|k,_| k == 'hmac' || k == 'signature'}
36+
query = URI.escape(h.sort.collect{|k,v| "#{k}=#{v}"}.join('&'))
37+
digest = OpenSSL::HMAC.hexdigest(OpenSSL::Digest.new('sha256'), @secret, query)
38+
39+
if not (hmac == digest)
40+
return [403, "Authentication failed. Digest provided was: #{digest}"]
41+
end
42+
43+
# if we don't have an access token for this particular shop,
44+
# we'll post the OAuth request and receive the token in the response
45+
if @tokens[shop].nil?
46+
url = "https://#{shop}/admin/oauth/access_token"
47+
48+
payload = {
49+
client_id: @key,
50+
client_secret: @secret,
51+
code: code}
52+
53+
response = HTTParty.post(url, body: payload)
54+
55+
# if the response is successful, obtain the token and store it in a hash
56+
if response.code == 200
57+
@tokens[shop] = response['access_token']
58+
else
59+
return [500, "Something went wrong."]
60+
end
61+
end
62+
63+
# now that we have the token, we can instantiate a session
64+
session = ShopifyAPI::Session.new(shop, @tokens[shop])
65+
ShopifyAPI::Base.activate_session(session)
66+
67+
# create webhook for order creation if it doesn't exist
68+
if not ShopifyAPI::Webhook.find(:all).any?
69+
webhook = {
70+
topic: 'orders/create',
71+
address: "https://#{@app_url}/giftbasket/webhook/order_create",
72+
format: 'json'}
73+
74+
ShopifyAPI::Webhook.create(webhook)
75+
end
76+
77+
# redirect the merchant to the bulk editor
78+
bulk_edit_url = "https://www.shopify.com/admin/bulk"\
79+
"?resource_name=ProductVariant"\
80+
"&edit=metafields.test.ingredients:string"
81+
82+
redirect bulk_edit_url
83+
84+
end
85+
86+
helpers do
87+
def verify_webhook(hmac, data)
88+
digest = OpenSSL::Digest.new('sha256')
89+
calculated_hmac = Base64.encode64(OpenSSL::HMAC.digest(digest, @secret, data)).strip
90+
91+
hmac == calculated_hmac
92+
end
93+
end
94+
95+
post '/giftbasket/webhook/order_create' do
96+
# inspect hmac value in header and verify webhook
97+
hmac = request.env['HTTP_X_SHOPIFY_HMAC_SHA256']
98+
99+
request.body.rewind
100+
data = request.body.read
101+
webhook_ok = verify_webhook(hmac, data)
102+
103+
if webhook_ok
104+
shop = request.env['HTTP_X_SHOPIFY_SHOP_DOMAIN']
105+
token = @tokens[shop]
106+
107+
if not token.nil?
108+
session = ShopifyAPI::Session.new(shop, token)
109+
ShopifyAPI::Base.activate_session(session)
110+
else
111+
return [403, "You're not authorized to perform this action."]
112+
end
113+
else
114+
return [403, "You're not authorized to perform this action."]
115+
end
116+
117+
# parse the request body as JSON data
118+
json_data = JSON.parse data
119+
120+
line_items = json_data['line_items']
121+
122+
line_items.each do |line_item|
123+
variant_id = line_item['variant_id']
124+
125+
variant = ShopifyAPI::Variant.find(variant_id)
126+
127+
variant.metafields.each do |field|
128+
if field.key == 'ingredients'
129+
items = field.value.split(',')
130+
131+
items.each do |item|
132+
gift_item = ShopifyAPI::Variant.find(item)
133+
gift_item.inventory_quantity = gift_item.inventory_quantity - 1
134+
gift_item.save
135+
end
136+
end
137+
end
138+
end
139+
140+
return [200, "Webhook notification received successfully."]
141+
end
142+
143+
end
144+
145+
run GiftBasket.run!

0 commit comments

Comments
 (0)