Skip to content

Commit 37b95e4

Browse files
authored
Merge pull request #1413 from Shopify/remove-old-webhook-handler
[Breaking] Remove deprecated ShopifyAPI::Webhooks::Handler interface
2 parents d625bee + 56882a9 commit 37b95e4

File tree

9 files changed

+23
-96
lines changed

9 files changed

+23
-96
lines changed

BREAKING_CHANGES_FOR_V15.md

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -81,8 +81,8 @@ module WebhookHandler
8181
extend ShopifyAPI::Webhooks::WebhookHandler
8282

8383
class << self
84-
def handle_webhook(data:)
85-
puts "Received webhook! topic: #{data.topic} shop: #{data.shop} body: #{data.body} webhook_id: #{data.webhook_id} api_version: #{data.api_version"
84+
def handle(data:)
85+
puts "Received webhook! topic: #{data.topic} shop: #{data.shop} body: #{data.body} webhook_id: #{data.webhook_id} api_version: #{data.api_version}"
8686
end
8787
end
8888
end

CHANGELOG.md

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -3,6 +3,9 @@
33
Note: For changes to the API, see https://shopify.dev/changelog?filter=api
44
## Unreleased
55

6+
### 15.0.0
7+
8+
- ⚠️ [Breaking] Removed deprecated `ShopifyAPI::Webhooks::Handler` interface. Apps must migrate to `ShopifyAPI::Webhooks::WebhookHandler` which provides `webhook_id` and `api_version` in addition to `topic`, `shop`, and `body`. See [BREAKING_CHANGES_FOR_V15.md](BREAKING_CHANGES_FOR_V15.md) for migration guide.
69
- Add support for 2025-10 API version
710
- Removed deprecated REST resources: `AccessScope`, `Product`, `ProductImage`, `PriceRule`, `ProductListing`, `ProductResourceFeedback`
811
- Updated `LATEST_SUPPORTED_ADMIN_VERSION` to `2025-10`

docs/usage/webhooks.md

Lines changed: 0 additions & 17 deletions
Original file line numberDiff line numberDiff line change
@@ -29,26 +29,9 @@ module WebhookHandler
2929
end
3030
```
3131

32-
**Note:** As of version 13.5.0 the `ShopifyAPI::Webhooks::Handler` class is still available to be used but will be removed in a future version of the gem.
33-
3432
### Best Practices
3533
It is recommended that in order to respond quickly to the Shopify webhook request that the handler not do any heavy logic or network calls, rather it should simply enqueue the work in some job queue in order to be executed later.
3634

37-
### Webhook Handler for versions 13.4.0 and prior
38-
If you want to register for an http webhook you need to implement a webhook handler which the `shopify_api` gem can use to determine how to process your webhook. You can make multiple implementations (one per topic) or you can make one implementation capable of handling all the topics you want to subscribe to. To do this simply make a module or class that includes or extends `ShopifyAPI::Webhooks::Handler` and implement the handle method which accepts the following named parameters: topic: `String`, shop: `String`, and body: `Hash[String, untyped]`. An example implementation is shown below:
39-
40-
```ruby
41-
module WebhookHandler
42-
extend ShopifyAPI::Webhooks::Handler
43-
44-
class << self
45-
def handle(topic:, shop:, body:)
46-
puts "Received webhook! topic: #{topic} shop: #{shop} body: #{body}"
47-
end
48-
end
49-
end
50-
```
51-
5235
## Add to Webhook Registry
5336

5437
The next step is to add all the webhooks you would like to subscribe to for any shop to the webhook registry. To do this you can call `ShopifyAPI::Webhooks::Registry.add_registration` for each webhook you would like to handle. `add_registration` accepts a topic string, a delivery_method symbol (currently supporting `:http`, `:event_bridge`, and `:pub_sub`), a webhook path (the relative path for an http webhook) and a handler. This only needs to be done once when the app is started and we recommend doing this at the same time that you setup `ShopifyAPI::Context`. An example is shown below to register an http webhook:

lib/shopify_api/webhooks/handler.rb

Lines changed: 0 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -11,18 +11,6 @@ class WebhookMetadata < T::Struct
1111
const :webhook_id, String
1212
end
1313

14-
module Handler
15-
include Kernel
16-
extend T::Sig
17-
extend T::Helpers
18-
interface!
19-
20-
sig do
21-
abstract.params(topic: String, shop: String, body: T::Hash[String, T.untyped]).void
22-
end
23-
def handle(topic:, shop:, body:); end
24-
end
25-
2614
module WebhookHandler
2715
include Kernel
2816
extend T::Sig

lib/shopify_api/webhooks/registration.rb

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -13,7 +13,7 @@ class Registration
1313
sig { returns(String) }
1414
attr_reader :topic
1515

16-
sig { returns(T.nilable(T.any(Handler, WebhookHandler))) }
16+
sig { returns(T.nilable(WebhookHandler)) }
1717
attr_reader :handler
1818

1919
sig { returns(T.nilable(T::Array[String])) }
@@ -26,7 +26,7 @@ class Registration
2626
attr_reader :filter
2727

2828
sig do
29-
params(topic: String, path: String, handler: T.nilable(T.any(Handler, WebhookHandler)),
29+
params(topic: String, path: String, handler: T.nilable(WebhookHandler),
3030
fields: T.nilable(T.any(String, T::Array[String])),
3131
metafield_namespaces: T.nilable(T::Array[String]),
3232
filter: T.nilable(String)).void

lib/shopify_api/webhooks/registry.rb

Lines changed: 3 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -17,7 +17,7 @@ class << self
1717
params(topic: String,
1818
delivery_method: Symbol,
1919
path: String,
20-
handler: T.nilable(T.any(Handler, WebhookHandler)),
20+
handler: T.nilable(WebhookHandler),
2121
fields: T.nilable(T.any(String, T::Array[String])),
2222
filter: T.nilable(String),
2323
metafield_namespaces: T.nilable(T::Array[String])).void
@@ -195,18 +195,8 @@ def process(request)
195195
raise Errors::NoWebhookHandler, "No webhook handler found for topic: #{request.topic}."
196196
end
197197

198-
if handler.is_a?(WebhookHandler)
199-
handler.handle(data: WebhookMetadata.new(topic: request.topic, shop: request.shop,
200-
body: request.parsed_body, api_version: request.api_version, webhook_id: request.webhook_id))
201-
else
202-
handler.handle(topic: request.topic, shop: request.shop, body: request.parsed_body)
203-
warning = <<~WARNING
204-
DEPRECATED: Use ShopifyAPI::Webhooks::WebhookHandler#handle instead of
205-
ShopifyAPI::Webhooks::Handler#handle.
206-
https://github.com/Shopify/shopify-api-ruby/blob/main/docs/usage/webhooks.md#create-a-webhook-handler
207-
WARNING
208-
ShopifyAPI::Logger.deprecated(warning, "15.0.0")
209-
end
198+
handler.handle(data: WebhookMetadata.new(topic: request.topic, shop: request.shop,
199+
body: request.parsed_body, api_version: request.api_version, webhook_id: request.webhook_id))
210200
end
211201

212202
private

test/test_helpers/fake_webhook_handler.rb

Lines changed: 3 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -2,17 +2,16 @@
22
# frozen_string_literal: true
33

44
require_relative "../../lib/shopify_api/webhooks/handler"
5-
65
module TestHelpers
76
class FakeWebhookHandler
8-
include ShopifyAPI::Webhooks::Handler
7+
include ShopifyAPI::Webhooks::WebhookHandler
98

109
def initialize(handler)
1110
@handler = handler
1211
end
1312

14-
def handle(topic:, shop:, body:)
15-
@handler.call(topic, shop, body)
13+
def handle(data:)
14+
@handler.call(data)
1615
end
1716
end
1817
end

test/test_helpers/new_fake_webhook_handler.rb

Lines changed: 0 additions & 17 deletions
This file was deleted.

test/webhooks/registry_test.rb

Lines changed: 10 additions & 29 deletions
Original file line numberDiff line numberDiff line change
@@ -194,7 +194,7 @@ def setup
194194
delivery_method: protocol,
195195
path: address,
196196
handler: TestHelpers::FakeWebhookHandler.new(
197-
lambda do |topic, shop, body|
197+
lambda do |data|
198198
end,
199199
),
200200
)
@@ -219,10 +219,12 @@ def test_process
219219
handler_called = false
220220

221221
handler = TestHelpers::FakeWebhookHandler.new(
222-
lambda do |topic, shop, body,|
223-
assert_equal(@topic, topic)
224-
assert_equal(@shop, shop)
225-
assert_equal({}, body)
222+
lambda do |data|
223+
assert_equal(@topic, data.topic)
224+
assert_equal(@shop, data.shop)
225+
assert_equal({}, data.body)
226+
assert_equal(@headers["x-shopify-webhook-id"], data.webhook_id)
227+
assert_equal(@headers["x-shopify-api-version"], data.api_version)
226228
handler_called = true
227229
end,
228230
)
@@ -242,33 +244,12 @@ def test_process_with_response_as_struct
242244
handler_called = false
243245

244246
handler = TestHelpers::FakeWebhookHandler.new(
245-
lambda do |topic, shop, body,|
246-
assert_equal(@topic, topic)
247-
assert_equal(@shop, shop)
248-
assert_equal({}, body)
249-
handler_called = true
250-
end,
251-
)
252-
253-
ShopifyAPI::Webhooks::Registry.add_registration(
254-
topic: @topic, path: "path", delivery_method: :http, handler: handler,
255-
)
256-
257-
ShopifyAPI::Webhooks::Registry.process(@webhook_request)
258-
259-
assert(handler_called)
260-
end
261-
262-
def test_process_new_handler
263-
handler_called = false
264-
265-
handler = TestHelpers::NewFakeWebhookHandler.new(
266247
lambda do |data|
267248
assert_equal(@topic, data.topic)
268249
assert_equal(@shop, data.shop)
269250
assert_equal({}, data.body)
270-
assert_equal("b1234-eefd-4c9e-9520-049845a02082", data.webhook_id)
271-
assert_equal("2024-01", data.api_version)
251+
assert_equal(@headers["x-shopify-webhook-id"], data.webhook_id)
252+
assert_equal(@headers["x-shopify-api-version"], data.api_version)
272253
handler_called = true
273254
end,
274255
)
@@ -441,7 +422,7 @@ def add_and_register_webhook(protocol, address, fields: nil, metafield_namespace
441422
delivery_method: protocol,
442423
path: address,
443424
handler: TestHelpers::FakeWebhookHandler.new(
444-
lambda do |topic, shop, body|
425+
lambda do |data|
445426
end,
446427
),
447428
fields: fields,

0 commit comments

Comments
 (0)