spree_uber_direct 0.1.4

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.
Files changed (52) hide show
  1. checksums.yaml +7 -0
  2. data/.env +7 -0
  3. data/.gitignore +27 -0
  4. data/.rspec +3 -0
  5. data/CHANGELOG.md +170 -0
  6. data/CONTRIBUTING.md +29 -0
  7. data/Gemfile +27 -0
  8. data/LICENSE.md +9 -0
  9. data/README.md +74 -0
  10. data/Rakefile +23 -0
  11. data/app/controllers/spree/admin/uber_direct_credentials_controller.rb +52 -0
  12. data/app/controllers/spree/admin/uber_direct_delivery_mappings_controller.rb +12 -0
  13. data/app/controllers/spree/admin/uber_direct_webhook_events_controller.rb +10 -0
  14. data/app/controllers/spree_uber_direct/webhooks_controller.rb +112 -0
  15. data/app/jobs/spree_uber_direct/base_job.rb +5 -0
  16. data/app/jobs/spree_uber_direct/delivery_dispatch_job.rb +21 -0
  17. data/app/jobs/spree_uber_direct/delivery_webhook_job.rb +17 -0
  18. data/app/models/spree/calculator/shipping/uber_direct_quote.rb +62 -0
  19. data/app/models/spree_uber_direct/credential.rb +33 -0
  20. data/app/models/spree_uber_direct/delivery_mapping.rb +27 -0
  21. data/app/models/spree_uber_direct/order_decorator.rb +42 -0
  22. data/app/models/spree_uber_direct/quote_mapping.rb +25 -0
  23. data/app/models/spree_uber_direct/refund_event.rb +34 -0
  24. data/app/models/spree_uber_direct/webhook_event.rb +34 -0
  25. data/app/services/spree_uber_direct/address_payload.rb +35 -0
  26. data/app/services/spree_uber_direct/alerting.rb +18 -0
  27. data/app/services/spree_uber_direct/client.rb +155 -0
  28. data/app/services/spree_uber_direct/delivery_dispatcher.rb +118 -0
  29. data/app/services/spree_uber_direct/delivery_status_mapper.rb +73 -0
  30. data/app/services/spree_uber_direct/quote.rb +97 -0
  31. data/app/services/spree_uber_direct/webhook_verifier.rb +17 -0
  32. data/app/subscribers/spree_uber_direct/order_completed_subscriber.rb +30 -0
  33. data/app/views/spree/admin/uber_direct_credentials/show.html.erb +55 -0
  34. data/app/views/spree/admin/uber_direct_delivery_mappings/index.html.erb +5 -0
  35. data/app/views/spree/admin/uber_direct_webhook_events/index.html.erb +5 -0
  36. data/config/initializers/spree.rb +14 -0
  37. data/config/initializers/spree_admin_uber_direct_navigation.rb +30 -0
  38. data/config/initializers/spree_admin_uber_direct_tables.rb +101 -0
  39. data/config/routes.rb +22 -0
  40. data/db/migrate/20260821000001_create_spree_uber_direct_credentials.rb +36 -0
  41. data/db/migrate/20260821030001_create_spree_uber_direct_quote_mappings.rb +48 -0
  42. data/db/migrate/20260821040001_create_spree_uber_direct_delivery_mappings.rb +42 -0
  43. data/db/migrate/20260821040002_create_spree_uber_direct_webhook_events.rb +37 -0
  44. data/db/migrate/20260823010001_create_spree_uber_direct_refund_events.rb +39 -0
  45. data/lib/spree_uber_direct/configuration.rb +8 -0
  46. data/lib/spree_uber_direct/engine.rb +45 -0
  47. data/lib/spree_uber_direct/factories.rb +37 -0
  48. data/lib/spree_uber_direct/version.rb +7 -0
  49. data/lib/spree_uber_direct.rb +12 -0
  50. data/lib/tasks/spree_uber_direct.rake +30 -0
  51. data/spree_uber_direct.gemspec +51 -0
  52. metadata +182 -0
@@ -0,0 +1,37 @@
1
+ FactoryBot.define do
2
+ # Define your Spree extensions Factories within this file to enable applications, and other extensions to use and override them.
3
+ #
4
+ # Example adding this to your spec_helper will load these Factories for use:
5
+ # require 'spree_uber_direct/factories'
6
+
7
+ factory :uber_direct_credential, class: 'SpreeUberDirect::Credential' do
8
+ store
9
+ client_id { 'test-client-id' }
10
+ client_secret { 'test-client-secret' }
11
+ customer_id { 'test-customer-id' }
12
+ uber_environment { 'sandbox' }
13
+ webhook_signing_secret { 'test-webhook-signing-secret' }
14
+ end
15
+
16
+ factory :uber_direct_quote_mapping, class: 'SpreeUberDirect::QuoteMapping' do
17
+ order
18
+ sequence(:external_quote_id) { |i| "dqt_#{i}" }
19
+ quoted_fee_cents { 599 }
20
+ currency { 'USD' }
21
+ quote_expires_at { 15.minutes.from_now }
22
+ end
23
+
24
+ factory :uber_direct_delivery_mapping, class: 'SpreeUberDirect::DeliveryMapping' do
25
+ order
26
+ sequence(:external_delivery_id) { |i| "del_#{i}" }
27
+ last_status { 'pending' }
28
+ tracking_url { 'https://www.ubereats.com/orders/abc123' }
29
+ end
30
+
31
+ factory :uber_direct_webhook_event, class: 'SpreeUberDirect::WebhookEvent' do
32
+ sequence(:delivery_id) { |i| "del_#{i}" }
33
+ status { 'pickup' }
34
+ sequence(:payload_digest) { |i| "digest-#{i}" }
35
+ payload { { 'delivery_id' => 'del_1', 'status' => 'pickup' } }
36
+ end
37
+ end
@@ -0,0 +1,7 @@
1
+ module SpreeUberDirect
2
+ VERSION = '0.1.4'.freeze
3
+
4
+ def gem_version
5
+ Gem::Version.new(VERSION)
6
+ end
7
+ end
@@ -0,0 +1,12 @@
1
+ require 'spree'
2
+ require 'spree_uber_direct/engine'
3
+ require 'spree_uber_direct/version'
4
+ require 'spree_uber_direct/configuration'
5
+
6
+ module SpreeUberDirect
7
+ mattr_accessor :queue
8
+
9
+ def self.queue
10
+ @@queue ||= Spree.queues.default
11
+ end
12
+ end
@@ -0,0 +1,30 @@
1
+ namespace :spree_uber_direct do
2
+ # M1 verification: proves the OAuth client_credentials flow actually
3
+ # works against a real Sandbox account — fetches a real token from
4
+ # auth.uber.com, then calls a real Direct endpoint with it. Uses
5
+ # `credential: nil` to read UBER_DIRECT_CLIENT_ID/CLIENT_SECRET/CUSTOMER_ID
6
+ # from ENV directly, same convenience path spree_square's demo rake tasks
7
+ # use, rather than requiring a Credential row to exist first.
8
+ desc 'Verify Uber Direct sandbox credentials: fetch a real OAuth token and call a real endpoint'
9
+ task verify_connection: :environment do
10
+ client = SpreeUberDirect::Client.new(credential: nil)
11
+ puts "Environment: #{client.sandbox? ? 'sandbox' : 'production'}"
12
+
13
+ # Delivery Quotes has no "list" endpoint — a deliberately-invalid quote
14
+ # request (missing required fields) is the simplest real round trip
15
+ # that proves both legs work: a real OAuth token was minted (a token
16
+ # failure surfaces as a distinct 401 from auth.uber.com, not this),
17
+ # and it was accepted by a real Direct endpoint (a 4xx validation
18
+ # response — not a 401/403 — proves the token itself was valid).
19
+ begin
20
+ client.create_quote({})
21
+ puts 'Unexpected: an empty quote request was accepted outright.'
22
+ rescue SpreeUberDirect::RequestError => e
23
+ if e.status == 401 || e.status == 403
24
+ abort "Auth failed (#{e.status}): #{e.body.inspect} — check UBER_DIRECT_CLIENT_ID/CLIENT_SECRET/CUSTOMER_ID."
25
+ else
26
+ puts "OAuth token acquired and accepted. Endpoint responded #{e.status} (expected — the request body was intentionally incomplete): #{e.body.inspect}"
27
+ end
28
+ end
29
+ end
30
+ end
@@ -0,0 +1,51 @@
1
+ # encoding: UTF-8
2
+ lib = File.expand_path('../lib/', __FILE__)
3
+ $LOAD_PATH.unshift lib unless $LOAD_PATH.include?(lib)
4
+
5
+ require 'spree_uber_direct/version'
6
+
7
+ Gem::Specification.new do |s|
8
+ s.platform = Gem::Platform::RUBY
9
+ s.name = 'spree_uber_direct'
10
+ s.version = SpreeUberDirect::VERSION
11
+ s.summary = 'Spree Commerce Uber Direct Delivery Extension'
12
+ s.description = 'Dispatches completed Spree orders as Uber Direct deliveries — live delivery-fee ' \
13
+ 'quoting during checkout, dispatch on order completion, and delivery status synced ' \
14
+ 'back via webhooks. A second, independent delivery provider alongside spree_doordash ' \
15
+ '— same shipping-method-based routing pattern, offered as an additional choice, not ' \
16
+ 'a replacement.'
17
+ s.required_ruby_version = '>= 3.2'
18
+
19
+ s.author = 'Amit Solanki'
20
+ s.email = 'amit@prayantr.com'
21
+ s.homepage = 'https://github.com/amitkssolanki/spree_uber_direct'
22
+ s.license = 'MIT'
23
+
24
+ s.metadata = {
25
+ 'homepage_uri' => s.homepage,
26
+ 'source_code_uri' => s.homepage,
27
+ 'changelog_uri' => "#{s.homepage}/blob/main/CHANGELOG.md",
28
+ 'bug_tracker_uri' => "#{s.homepage}/issues"
29
+ }
30
+
31
+ s.files = `git ls-files -z`.split("\x0").reject do |f|
32
+ f.start_with?('spec/') && !f.start_with?('spec/fixtures')
33
+ end
34
+ s.require_path = 'lib'
35
+ s.requirements << 'none'
36
+
37
+ spree_version = '>= 5.4.0.beta'
38
+ s.add_dependency 'spree', spree_version
39
+ s.add_dependency 'spree_admin', spree_version
40
+
41
+ # No official Ruby SDK for Uber Direct (the real one, uber/uber-direct-sdk,
42
+ # is JS/TS-only) — plain OAuth2 client_credentials + REST against
43
+ # api.uber.com via Faraday, already a transitive dependency through Spree
44
+ # itself. No jwt dependency needed here (unlike spree_doordash) — Uber
45
+ # Direct auth is a cached bearer token, not a per-request signed JWT.
46
+ s.add_dependency 'faraday'
47
+
48
+ s.add_development_dependency 'spree_dev_tools'
49
+ s.add_development_dependency 'webmock'
50
+ s.add_development_dependency 'gem-release'
51
+ end
metadata ADDED
@@ -0,0 +1,182 @@
1
+ --- !ruby/object:Gem::Specification
2
+ name: spree_uber_direct
3
+ version: !ruby/object:Gem::Version
4
+ version: 0.1.4
5
+ platform: ruby
6
+ authors:
7
+ - Amit Solanki
8
+ bindir: bin
9
+ cert_chain: []
10
+ date: 1980-01-02 00:00:00.000000000 Z
11
+ dependencies:
12
+ - !ruby/object:Gem::Dependency
13
+ name: spree
14
+ requirement: !ruby/object:Gem::Requirement
15
+ requirements:
16
+ - - ">="
17
+ - !ruby/object:Gem::Version
18
+ version: 5.4.0.beta
19
+ type: :runtime
20
+ prerelease: false
21
+ version_requirements: !ruby/object:Gem::Requirement
22
+ requirements:
23
+ - - ">="
24
+ - !ruby/object:Gem::Version
25
+ version: 5.4.0.beta
26
+ - !ruby/object:Gem::Dependency
27
+ name: spree_admin
28
+ requirement: !ruby/object:Gem::Requirement
29
+ requirements:
30
+ - - ">="
31
+ - !ruby/object:Gem::Version
32
+ version: 5.4.0.beta
33
+ type: :runtime
34
+ prerelease: false
35
+ version_requirements: !ruby/object:Gem::Requirement
36
+ requirements:
37
+ - - ">="
38
+ - !ruby/object:Gem::Version
39
+ version: 5.4.0.beta
40
+ - !ruby/object:Gem::Dependency
41
+ name: faraday
42
+ requirement: !ruby/object:Gem::Requirement
43
+ requirements:
44
+ - - ">="
45
+ - !ruby/object:Gem::Version
46
+ version: '0'
47
+ type: :runtime
48
+ prerelease: false
49
+ version_requirements: !ruby/object:Gem::Requirement
50
+ requirements:
51
+ - - ">="
52
+ - !ruby/object:Gem::Version
53
+ version: '0'
54
+ - !ruby/object:Gem::Dependency
55
+ name: spree_dev_tools
56
+ requirement: !ruby/object:Gem::Requirement
57
+ requirements:
58
+ - - ">="
59
+ - !ruby/object:Gem::Version
60
+ version: '0'
61
+ type: :development
62
+ prerelease: false
63
+ version_requirements: !ruby/object:Gem::Requirement
64
+ requirements:
65
+ - - ">="
66
+ - !ruby/object:Gem::Version
67
+ version: '0'
68
+ - !ruby/object:Gem::Dependency
69
+ name: webmock
70
+ requirement: !ruby/object:Gem::Requirement
71
+ requirements:
72
+ - - ">="
73
+ - !ruby/object:Gem::Version
74
+ version: '0'
75
+ type: :development
76
+ prerelease: false
77
+ version_requirements: !ruby/object:Gem::Requirement
78
+ requirements:
79
+ - - ">="
80
+ - !ruby/object:Gem::Version
81
+ version: '0'
82
+ - !ruby/object:Gem::Dependency
83
+ name: gem-release
84
+ requirement: !ruby/object:Gem::Requirement
85
+ requirements:
86
+ - - ">="
87
+ - !ruby/object:Gem::Version
88
+ version: '0'
89
+ type: :development
90
+ prerelease: false
91
+ version_requirements: !ruby/object:Gem::Requirement
92
+ requirements:
93
+ - - ">="
94
+ - !ruby/object:Gem::Version
95
+ version: '0'
96
+ description: Dispatches completed Spree orders as Uber Direct deliveries — live delivery-fee
97
+ quoting during checkout, dispatch on order completion, and delivery status synced
98
+ back via webhooks. A second, independent delivery provider alongside spree_doordash
99
+ — same shipping-method-based routing pattern, offered as an additional choice, not
100
+ a replacement.
101
+ email: amit@prayantr.com
102
+ executables: []
103
+ extensions: []
104
+ extra_rdoc_files: []
105
+ files:
106
+ - ".env"
107
+ - ".gitignore"
108
+ - ".rspec"
109
+ - CHANGELOG.md
110
+ - CONTRIBUTING.md
111
+ - Gemfile
112
+ - LICENSE.md
113
+ - README.md
114
+ - Rakefile
115
+ - app/controllers/spree/admin/uber_direct_credentials_controller.rb
116
+ - app/controllers/spree/admin/uber_direct_delivery_mappings_controller.rb
117
+ - app/controllers/spree/admin/uber_direct_webhook_events_controller.rb
118
+ - app/controllers/spree_uber_direct/webhooks_controller.rb
119
+ - app/jobs/spree_uber_direct/base_job.rb
120
+ - app/jobs/spree_uber_direct/delivery_dispatch_job.rb
121
+ - app/jobs/spree_uber_direct/delivery_webhook_job.rb
122
+ - app/models/spree/calculator/shipping/uber_direct_quote.rb
123
+ - app/models/spree_uber_direct/credential.rb
124
+ - app/models/spree_uber_direct/delivery_mapping.rb
125
+ - app/models/spree_uber_direct/order_decorator.rb
126
+ - app/models/spree_uber_direct/quote_mapping.rb
127
+ - app/models/spree_uber_direct/refund_event.rb
128
+ - app/models/spree_uber_direct/webhook_event.rb
129
+ - app/services/spree_uber_direct/address_payload.rb
130
+ - app/services/spree_uber_direct/alerting.rb
131
+ - app/services/spree_uber_direct/client.rb
132
+ - app/services/spree_uber_direct/delivery_dispatcher.rb
133
+ - app/services/spree_uber_direct/delivery_status_mapper.rb
134
+ - app/services/spree_uber_direct/quote.rb
135
+ - app/services/spree_uber_direct/webhook_verifier.rb
136
+ - app/subscribers/spree_uber_direct/order_completed_subscriber.rb
137
+ - app/views/spree/admin/uber_direct_credentials/show.html.erb
138
+ - app/views/spree/admin/uber_direct_delivery_mappings/index.html.erb
139
+ - app/views/spree/admin/uber_direct_webhook_events/index.html.erb
140
+ - config/initializers/spree.rb
141
+ - config/initializers/spree_admin_uber_direct_navigation.rb
142
+ - config/initializers/spree_admin_uber_direct_tables.rb
143
+ - config/routes.rb
144
+ - db/migrate/20260821000001_create_spree_uber_direct_credentials.rb
145
+ - db/migrate/20260821030001_create_spree_uber_direct_quote_mappings.rb
146
+ - db/migrate/20260821040001_create_spree_uber_direct_delivery_mappings.rb
147
+ - db/migrate/20260821040002_create_spree_uber_direct_webhook_events.rb
148
+ - db/migrate/20260823010001_create_spree_uber_direct_refund_events.rb
149
+ - lib/spree_uber_direct.rb
150
+ - lib/spree_uber_direct/configuration.rb
151
+ - lib/spree_uber_direct/engine.rb
152
+ - lib/spree_uber_direct/factories.rb
153
+ - lib/spree_uber_direct/version.rb
154
+ - lib/tasks/spree_uber_direct.rake
155
+ - spree_uber_direct.gemspec
156
+ homepage: https://github.com/amitkssolanki/spree_uber_direct
157
+ licenses:
158
+ - MIT
159
+ metadata:
160
+ homepage_uri: https://github.com/amitkssolanki/spree_uber_direct
161
+ source_code_uri: https://github.com/amitkssolanki/spree_uber_direct
162
+ changelog_uri: https://github.com/amitkssolanki/spree_uber_direct/blob/main/CHANGELOG.md
163
+ bug_tracker_uri: https://github.com/amitkssolanki/spree_uber_direct/issues
164
+ rdoc_options: []
165
+ require_paths:
166
+ - lib
167
+ required_ruby_version: !ruby/object:Gem::Requirement
168
+ requirements:
169
+ - - ">="
170
+ - !ruby/object:Gem::Version
171
+ version: '3.2'
172
+ required_rubygems_version: !ruby/object:Gem::Requirement
173
+ requirements:
174
+ - - ">="
175
+ - !ruby/object:Gem::Version
176
+ version: '0'
177
+ requirements:
178
+ - none
179
+ rubygems_version: 3.6.9
180
+ specification_version: 4
181
+ summary: Spree Commerce Uber Direct Delivery Extension
182
+ test_files: []