choiceqr 0.1.0 → 0.2.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA256:
3
- metadata.gz: 07dec0ce2e854c10973278cf04728e882f6402babed554baed28ad04760b267e
4
- data.tar.gz: 138b5ff77c3bfe9b9113fddd791bc32fbee5d59abe4a3a949c3037e72f7ee410
3
+ metadata.gz: c1977ab8cbeaec88217f43e89bdc837caccb65f844e1a8dfb0916395e8d25d23
4
+ data.tar.gz: 670d2b1b9edbe47c72ef1e2f0f86822deba3f7df451431bad0313ad5ffe2d863
5
5
  SHA512:
6
- metadata.gz: 5214c6437aab17feab020cdd34046e8001406667efc3936f5d1469903a13da27723e11ed008778807a886768566d2de1ec1354b24f99759c470ef0eed38148e9
7
- data.tar.gz: 33437df630e03f6718fd77d41df0e6fd5a195f81f4046fee2f18d9ea8f2f687bdc9b07590b8cc21e9709bb05efe083bcd744778e2e70e30993bcb46b227bac3a
6
+ metadata.gz: 157e389e0d57323bff53ea4f82ebc81c8c8eebc2f6df3d3f7072a073699b77a97be15334a744a0614d4305f305fcb7909d12d72a8ae430d7648709a1c490f6c7
7
+ data.tar.gz: 8fc87c2cdb3958d62122a9e2c50ea8d06b04dfb648b5526c69bed1f4195463935dbeaf5bac5f2f5a219ceebba7a5f87de96c00b47d879e15012a6637559b3436
data/README.md CHANGED
@@ -228,7 +228,26 @@ client = ChoiceQR::Client.new(
228
228
 
229
229
  ## Webhooks
230
230
 
231
- ChoiceQR pushes events (menu changes, new orders, booking updates, …) to a Webhook URL you configure when creating your application — there is no API for managing webhook subscriptions, so this gem does not include a webhook client. See [Webhooks](https://open-api.choiceqr.com/docs/content/webhooks) for the event payload shape; the `data` field of each event matches the corresponding resource's response schema, so you can wrap it yourself with `ChoiceQR::Resource.new(event["data"])` if useful.
231
+ ChoiceQR pushes events (menu changes, new orders, booking updates, …) to a Webhook URL you configure when creating your application — there is no API for managing webhook subscriptions, so there's no `client.webhooks`. `ChoiceQR::WebhookEvent` parses the payload your endpoint receives:
232
+
233
+ ```ruby
234
+ post "/webhooks/choiceqr" do
235
+ event = ChoiceQR::WebhookEvent.parse(request.body.read)
236
+
237
+ case event.type
238
+ when "dish.created", "dish.changed"
239
+ Dish.upsert_from_choiceqr(event.data) # same shape as Dishes#get
240
+ when "order.created"
241
+ Order.create_from_choiceqr(event.data)
242
+ when "section.positionChanged"
243
+ Section.reorder(event.data.items) # array of section ids
244
+ end
245
+ end
246
+ ```
247
+
248
+ `event.data`'s shape depends on `event.type` — usually the same entity schema the matching resource method returns, but `*.positionChanged` events carry `{items: [...ids]}` and `*.removed` events carry just an id. `ChoiceQR::WebhookEvent::TYPES` lists every documented event type (not enforced — an unrecognized `type` still parses fine). See [Webhooks](https://open-api.choiceqr.com/docs/content/webhooks) for the full type → shape mapping.
249
+
250
+ **ChoiceQR does not document a signature or secret for verifying a webhook's authenticity.** `WebhookEvent` parses the payload; it does not, and cannot, confirm the request actually came from ChoiceQR.
232
251
 
233
252
  ## Development
234
253
 
@@ -1,3 +1,3 @@
1
1
  module ChoiceQR
2
- VERSION = "0.1.0".freeze
2
+ VERSION = "0.2.0".freeze
3
3
  end
@@ -0,0 +1,122 @@
1
+ require "json"
2
+
3
+ module ChoiceQR
4
+ # Wraps an incoming webhook event payload — the thing your own server
5
+ # receives at the Webhook URL configured for your application (see
6
+ # https://open-api.choiceqr.com/docs/content/application), not something
7
+ # this gem calls the API for. ChoiceQR has no API for managing webhook
8
+ # subscriptions (the URL is set once in the app dashboard), so there is no
9
+ # corresponding client.webhooks resource — this class only parses the
10
+ # payload shape.
11
+ #
12
+ # IMPORTANT: ChoiceQR does not document a signature or secret for
13
+ # verifying that a webhook request genuinely came from ChoiceQR. This
14
+ # class parses the payload; it does not, and cannot, authenticate it.
15
+ #
16
+ # Usage (e.g. inside a Rack/Sinatra/Rails webhook endpoint):
17
+ #
18
+ # event = ChoiceQR::WebhookEvent.parse(request.body.read)
19
+ # event.id # => "unique_id"
20
+ # event.type # => "dish.created"
21
+ # event.lang_code # => "en"
22
+ # event.var_symbol # => company id
23
+ #
24
+ # case event.type
25
+ # when "dish.created", "dish.changed"
26
+ # event.data.name # data is the same Dish shape #dishes.get returns
27
+ # when "section.positionChanged"
28
+ # event.data.items # => array of section ids
29
+ # when /\.removed\z/
30
+ # event.data.id # => {_id: "..."} → :id
31
+ # end
32
+ #
33
+ # See https://open-api.choiceqr.com/docs/content/webhooks for the full
34
+ # event type → data shape mapping.
35
+ class WebhookEvent
36
+ # Every event type ChoiceQR documents, for reference — not enforced:
37
+ # #type is whatever string the payload contains, so an event type added
38
+ # to the API later still parses fine here.
39
+ TYPES = %w[
40
+ place.changed
41
+ sectionInfo.changed
42
+ section.created section.changed section.positionChanged section.removed
43
+ category.created category.changed category.positionChanged category.removed
44
+ dish.created dish.changed dish.positionChanged dish.removed
45
+ dishOption.changed
46
+ menuLabel.created menuLabel.changed menuLabel.removed
47
+ option.created option.changed option.positionChanged option.removed
48
+ import.full.done
49
+ marketplace.acceptance.enabled marketplace.acceptance.disabled
50
+ order.created order.accepted order.cancelled order.closed order.delivery.update
51
+ order.qrPayment.completed order.qrPayment.error
52
+ ].freeze
53
+
54
+ # +payload+ is a JSON String (e.g. a raw request body) or an
55
+ # already-parsed Hash.
56
+ def self.parse(payload)
57
+ new(payload.is_a?(String) ? JSON.parse(payload) : payload)
58
+ end
59
+
60
+ def initialize(attributes)
61
+ @resource = Resource.new(attributes)
62
+ end
63
+
64
+ def id
65
+ @resource.id
66
+ end
67
+
68
+ # The event type, e.g. "dish.created", "order.qrPayment.completed" — see
69
+ # TYPES.
70
+ def type
71
+ @resource.type
72
+ end
73
+
74
+ def lang_code
75
+ @resource.lang_code
76
+ end
77
+
78
+ # Uniq identifier of the company the event belongs to.
79
+ def var_symbol
80
+ @resource.var_symbol
81
+ end
82
+
83
+ # The event-specific payload. Its shape depends on #type — see the class
84
+ # docs above and https://open-api.choiceqr.com/docs/content/webhooks.
85
+ def data
86
+ @resource.data
87
+ end
88
+
89
+ # Hash-style access, for any envelope field not covered by a named
90
+ # reader above.
91
+ def [](key)
92
+ @resource[key]
93
+ end
94
+
95
+ def to_h
96
+ @resource.to_h
97
+ end
98
+
99
+ def inspect
100
+ "#<#{self.class.name} type=#{type.inspect} id=#{id.inspect}>"
101
+ end
102
+
103
+ def to_s
104
+ inspect
105
+ end
106
+
107
+ def respond_to_missing?(name, include_private = false)
108
+ @resource.respond_to?(name, include_private) || super
109
+ end
110
+
111
+ # Delegates to the underlying Resource, so any envelope field not given
112
+ # a named reader above (or a documented-but-misspelled one) is still
113
+ # reachable by dot access.
114
+ def method_missing(name, *, &)
115
+ if @resource.respond_to?(name)
116
+ @resource.public_send(name, *, &)
117
+ else
118
+ super
119
+ end
120
+ end
121
+ end
122
+ end
data/lib/choiceqr.rb CHANGED
@@ -3,6 +3,7 @@ require_relative "choiceqr/errors"
3
3
  require_relative "choiceqr/configuration"
4
4
  require_relative "choiceqr/key_transformer"
5
5
  require_relative "choiceqr/resource"
6
+ require_relative "choiceqr/webhook_event"
6
7
  require_relative "choiceqr/resources/base"
7
8
  require_relative "choiceqr/resources/place"
8
9
  require_relative "choiceqr/resources/section_info"
metadata CHANGED
@@ -1,7 +1,7 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: choiceqr
3
3
  version: !ruby/object:Gem::Version
4
- version: 0.1.0
4
+ version: 0.2.0
5
5
  platform: ruby
6
6
  authors:
7
7
  - Stockbird Team
@@ -142,6 +142,7 @@ files:
142
142
  - lib/choiceqr/resources/section_info.rb
143
143
  - lib/choiceqr/resources/sections.rb
144
144
  - lib/choiceqr/version.rb
145
+ - lib/choiceqr/webhook_event.rb
145
146
  homepage: https://github.com/stockbird-app/choiceqr
146
147
  licenses:
147
148
  - MIT