spree_stripe 1.2.8 → 1.4.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 +4 -4
- data/README.md +1 -1
- data/app/assets/images/payment_icons/banktransfer.svg +3 -0
- data/app/assets/images/payment_icons/sepadebit.svg +22 -0
- data/app/controllers/spree/api/v2/storefront/stripe/payment_intents_controller.rb +1 -1
- data/app/controllers/spree_stripe/payment_intents_controller.rb +1 -1
- data/app/helpers/spree_stripe/checkout_helper_decorator.rb +15 -0
- data/app/javascript/spree_stripe/controllers/stripe_button_controller.js +2 -0
- data/app/javascript/spree_stripe/controllers/stripe_controller.js +4 -2
- data/app/jobs/spree_stripe/create_tax_transaction_job.rb +10 -0
- data/app/models/spree_stripe/calculators/stripe_tax.rb +96 -0
- data/app/models/spree_stripe/gateway.rb +78 -4
- data/app/models/spree_stripe/order_decorator.rb +14 -0
- data/app/models/spree_stripe/payment_decorator.rb +2 -2
- data/app/models/spree_stripe/payment_intent.rb +16 -1
- data/app/models/spree_stripe/payment_method_decorator.rb +1 -1
- data/app/models/spree_stripe/payment_sources/bank_transfer.rb +17 -0
- data/app/models/spree_stripe/payment_sources/sepa_debit.rb +4 -0
- data/app/models/spree_stripe/shipment_decorator.rb +21 -0
- data/app/presenters/spree_stripe/payment_intent_presenter.rb +8 -16
- data/app/presenters/spree_stripe/statement_descriptor_suffix_presenter.rb +35 -0
- data/app/presenters/spree_stripe/tax_presenter.rb +63 -0
- data/app/services/spree_stripe/complete_order.rb +9 -3
- data/app/services/spree_stripe/create_payment.rb +9 -0
- data/app/services/spree_stripe/create_source.rb +2 -0
- data/app/services/spree_stripe/webhook_handlers/payment_intent_payment_failed.rb +1 -4
- data/app/views/spree_stripe/_quick_checkout.html.erb +2 -1
- data/config/initializers/spree.rb +1 -0
- data/config/locales/en.yml +1 -0
- data/lib/spree_stripe/engine.rb +5 -3
- data/lib/spree_stripe/version.rb +1 -1
- data/lib/spree_stripe.rb +3 -1
- metadata +12 -7
checksums.yaml
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
---
|
|
2
2
|
SHA256:
|
|
3
|
-
metadata.gz:
|
|
4
|
-
data.tar.gz:
|
|
3
|
+
metadata.gz: ed3fcc600ad3010c438e0fd42e964612f151d1bfacf1fab96bc781ca2e5d2fe2
|
|
4
|
+
data.tar.gz: c57032392b824d12f83aa4b63bc452cfdd88d22da8a88452426d150cddb226a4
|
|
5
5
|
SHA512:
|
|
6
|
-
metadata.gz:
|
|
7
|
-
data.tar.gz:
|
|
6
|
+
metadata.gz: f39b40bd6e0ceceb9f152fe4f2f7a2337368bd41bb823bbd1a403a2d126bc2b5c4446e82cd288758f93c422c8360cab41fb6f92bfeeb73ac5eb4ca0dc2ff4c5d
|
|
7
|
+
data.tar.gz: 8464c1cbbc5d25fb74390cd500f1ec8a7dddf2615d2281407ae8fe3ab361b5738e11aa1223d2c9c75a76a991122eba0f248f5152706b645aad44ee3acf985686
|
data/README.md
CHANGED
|
@@ -140,7 +140,7 @@ We’re thrilled to unveil [Spree 5](https://spreecommerce.org/announcing-spree-
|
|
|
140
140
|
- New integrations: a native [Stripe integration](https://github.com/spree/spree_stripe), and also Stripe Connect, Klaviyo integrations available with the Enterprise Edition
|
|
141
141
|
- Enterprise Edition Admin Features: Audit Log, [Multi-Vendor Marketplace](https://spreecommerce.org/marketplace-ecommerce/), [Multi-tenant / White-label SaaS eCommerce](https://spreecommerce.org/multi-tenant-white-label-ecommerce/)
|
|
142
142
|
|
|
143
|
-
Read the [full Spree 5 announcement here](https://spreecommerce.org/announcing-spree-5-the-biggest-open-source-release-ever/).
|
|
143
|
+
Read the [full Spree 5 announcement here](https://spreecommerce.org/announcing-spree-5-the-biggest-open-source-release-ever/) and the [changelog of Spree 5](https://github.com/spree/spree/releases) followup improvements.
|
|
144
144
|
|
|
145
145
|
Check out the [Spree 5 demo](https://demo.spreecommerce.org/) for yourself, including this Stripe integration.
|
|
146
146
|
|
|
@@ -0,0 +1,3 @@
|
|
|
1
|
+
<svg xmlns="http://www.w3.org/2000/svg" fill="none" viewBox="0 0 24 24" stroke-width="1.5" stroke="currentColor" class="size-6">
|
|
2
|
+
<path stroke-linecap="round" stroke-linejoin="round" d="M2.25 18.75a60.07 60.07 0 0 1 15.797 2.101c.727.198 1.453-.342 1.453-1.096V18.75M3.75 4.5v.75A.75.75 0 0 1 3 6h-.75m0 0v-.375c0-.621.504-1.125 1.125-1.125H20.25M2.25 6v9m18-10.5v.75c0 .414.336.75.75.75h.75m-1.5-1.5h.375c.621 0 1.125.504 1.125 1.125v9.75c0 .621-.504 1.125-1.125 1.125h-.375m1.5-1.5H21a.75.75 0 0 0-.75.75v.75m0 0H3.75m0 0h-.375a1.125 1.125 0 0 1-1.125-1.125V15m1.5 1.5v-.75A.75.75 0 0 0 3 15h-.75M15 10.5a3 3 0 1 1-6 0 3 3 0 0 1 6 0Zm3 0h.008v.008H18V10.5Zm-12 0h.008v.008H6V10.5Z" />
|
|
3
|
+
</svg>
|
|
@@ -0,0 +1,22 @@
|
|
|
1
|
+
<svg xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" version="1.0" id="katman_1" x="0px" y="0px" style="enable-background:new 0 0 1190.55 841.89;" xml:space="preserve" viewBox="238.65 160 712.7 521">
|
|
2
|
+
<style type="text/css">
|
|
3
|
+
.st0{fill:#26367D;}
|
|
4
|
+
.st1{clip-path:url(#SVGID_00000165933728503162618370000013584018841918814628_);}
|
|
5
|
+
.st2{fill:#FFFFFF;}
|
|
6
|
+
.st3{fill:#FBBA2C;}
|
|
7
|
+
</style>
|
|
8
|
+
<path class="st0" d="M302,160h586c34.99,0,63.35,28.36,63.35,63.35v394.3c0,34.99-28.36,63.35-63.35,63.35H302 c-34.99,0-63.35-28.36-63.35-63.35v-394.3C238.65,188.36,267.01,160,302,160z"/>
|
|
9
|
+
<g>
|
|
10
|
+
<defs>
|
|
11
|
+
<rect id="SVGID_1_" x="341.04" y="162.96" width="507.9" height="506.81"/>
|
|
12
|
+
</defs>
|
|
13
|
+
<clipPath id="SVGID_00000137126528663880082090000017192719521453020821_">
|
|
14
|
+
<use xlink:href="#SVGID_1_" style="overflow:visible;"/>
|
|
15
|
+
</clipPath>
|
|
16
|
+
<g style="clip-path:url(#SVGID_00000137126528663880082090000017192719521453020821_);">
|
|
17
|
+
<path class="st0" d="M367.09,226.31h455.81c14.38,0,26.04,13.62,26.04,30.41v319.29c0,16.79-11.66,30.41-26.04,30.41H367.09 c-14.38,0-26.05-13.62-26.05-30.41V256.72C341.04,239.93,352.71,226.31,367.09,226.31z"/>
|
|
18
|
+
<path class="st2" d="M404.53,381.92c0,3.22,0,5.34,1.06,8.55c0,1.09,1.05,2.12,1.05,3.22c2.06,13.91,8.3,20.27,21.76,21.38 c9.3,1.08,19.64,2.12,29,3.22c5.18,0,8.3,3.22,8.3,9.58c0,6.38-2.06,10.69-8.3,10.69h-18.64c-6.24,0-8.3-3.22-9.3-12.81h-24.82 v9.66c0,1.08,1.06,3.22,1.06,4.24c1.05,9.6,7.24,16.03,16.58,18.15c6.22,1.09,12.4,1.09,18.64,2.12h18.64 c6.24-1.09,11.4-2.12,17.58-4.24c7.24-2.12,12.42-7.48,13.46-16.03c1.06-7.48,1.06-16.03,1.06-23.5 c-1.05-8.55-5.16-14.94-13.46-17.1l-18.64-3.23c-6.22-1.09-12.42-1.09-18.64-1.09c-7.24,0-9.3-3.22-9.3-9.58 c0-7.48,3.12-9.6,9.3-10.69h10.34c9.3,0,11.4,1.11,12.42,10.69v1.09h24.82v-6.43c0-13.91-6.22-22.47-20.7-24.6 c-14.46-2.12-28.98-2.12-43.46,1.09c-11.4,2.12-16.58,7.48-18.64,20.27C405.55,378.69,404.53,379.8,404.53,381.92z M631.19,458.83 v-27.8h35.18c13.46,0,22.76-8.55,24.82-21.38c1.06-8.55,2.06-17.1,1.06-25.61c-1.06-19.24-10.34-28.82-28.98-29.93 c-17.58-1.09-35.18-1.09-52.82-1.09c-4.12,0-5.18,1.11-5.18,5.35v101.5C613.61,459.92,622.91,459.92,631.19,458.83z M631.19,407.53V377.6c0,0,2.06-2.12,3.12-2.12h18.64c7.24,1.11,10.36,4.32,10.36,11.78v10.69c0,6.43-2.06,9.58-8.3,9.58H631.19z M708.83,459.92c1.06-5.34,2.06-11.77,4.18-17.1c0-1.11,2.06-2.14,3.12-2.14h33.1c1.06,0,2.06,2.12,3.12,3.22 c2.06,5.35,3.12,10.69,5.18,16.03h27.94c-1.06-2.12-2.06-5.34-3.12-7.46l-27.94-96.23c0-1.09-2.06-3.22-3.12-3.22h-39.34 c-4.18,12.88-7.24,25.67-11.4,38.49c-6.24,22.41-13.46,45.9-19.64,68.37C680.9,459.87,708.83,459.92,708.83,459.92z M747.12,421.43h-26.94c4.12-15,8.3-31.01,12.42-45.96h1.05c4.18,15,9.34,29.93,13.46,45.96H747.12z"/>
|
|
19
|
+
<path class="st3" d="M575.35,441.71c-16.6,0-29-7.46-34.18-19.24h37.28l4.12-11.77h-45.58v-8.55l46.59,2.12l5.16-13.86h-49.68 c5.16-14.94,18.64-22.46,36.22-22.46c7.44-0.05,14.81,1.44,21.76,4.26l4.12-14.94c-4.12-2.14-13.46-4.26-26.92-4.26 c-27.95,0-49.71,13.91-56.94,38.49h-12.35l-5.18,11.78h15.52v9.53h-9.3l-6.22,11.78h17.58c6.24,21.37,25.88,34.18,53.82,34.18 c13.46,0,23.82-2.12,27.94-4.26l-3.12-14.94C591.93,440.69,583.63,441.71,575.35,441.71z"/>
|
|
20
|
+
</g>
|
|
21
|
+
</g>
|
|
22
|
+
</svg>
|
|
@@ -56,7 +56,7 @@ module Spree
|
|
|
56
56
|
render_error_payload(Spree.t('order_already_completed'))
|
|
57
57
|
elsif order != spree_current_order
|
|
58
58
|
raise ActiveRecord::RecordNotFound
|
|
59
|
-
elsif
|
|
59
|
+
elsif @payment_intent.accepted?
|
|
60
60
|
spree_authorize! :update, spree_current_order, order_token
|
|
61
61
|
|
|
62
62
|
SpreeStripe::CompleteOrder.new(payment_intent: @payment_intent).call
|
|
@@ -26,7 +26,7 @@ module SpreeStripe
|
|
|
26
26
|
elsif @order.completed?
|
|
27
27
|
redirect_to spree.checkout_complete_path(@order.token), status: :see_other
|
|
28
28
|
# if the payment intent is successful, we need to process the payment and complete the order
|
|
29
|
-
elsif @
|
|
29
|
+
elsif @payment_intent_record.accepted?
|
|
30
30
|
@order = SpreeStripe::CompleteOrder.new(payment_intent: @payment_intent_record).call
|
|
31
31
|
|
|
32
32
|
# set the session flag to indicate that the order was placed now
|
|
@@ -0,0 +1,15 @@
|
|
|
1
|
+
module SpreeStripe
|
|
2
|
+
module CheckoutHelperDecorator
|
|
3
|
+
def checkout_payment_sources(payment_method = nil)
|
|
4
|
+
payment_sources = super(payment_method)
|
|
5
|
+
return payment_sources if payment_sources.empty? || !payment_method.stripe?
|
|
6
|
+
|
|
7
|
+
wallet_sources, non_wallet_sources = payment_sources.partition { |source| source.wallet_type.present? }
|
|
8
|
+
unique_wallet_sources = wallet_sources.sort_by(&:created_at).reverse.uniq { |source| [source.wallet_type, source.cc_type, source.last_digits, source.month, source.year] }
|
|
9
|
+
|
|
10
|
+
non_wallet_sources + unique_wallet_sources
|
|
11
|
+
end
|
|
12
|
+
end
|
|
13
|
+
end
|
|
14
|
+
|
|
15
|
+
Spree::CheckoutHelper.prepend(SpreeStripe::CheckoutHelperDecorator)
|
|
@@ -25,6 +25,7 @@ export default class extends Controller {
|
|
|
25
25
|
checkoutValidateOrderForPaymentPath: String,
|
|
26
26
|
shippingRequired: { type: Boolean, default: true },
|
|
27
27
|
returnUrl: String,
|
|
28
|
+
phoneRequired: { type: Boolean, default: false },
|
|
28
29
|
}
|
|
29
30
|
|
|
30
31
|
static targets = ['container']
|
|
@@ -104,6 +105,7 @@ export default class extends Controller {
|
|
|
104
105
|
|
|
105
106
|
event.resolve({
|
|
106
107
|
emailRequired: true,
|
|
108
|
+
phoneNumberRequired: this.phoneRequiredValue,
|
|
107
109
|
shippingAddressRequired: this.shippingRequiredValue,
|
|
108
110
|
allowedShippingCountries: this.availableCountriesValue,
|
|
109
111
|
// If we want to collect shipping address then we need to provide at least one shipping option, it will be updated to the real ones in the `shippingaddresschange` event
|
|
@@ -13,7 +13,8 @@ export default class extends Controller {
|
|
|
13
13
|
colorText: String,
|
|
14
14
|
paymentIntentPath: String,
|
|
15
15
|
checkoutPath: String,
|
|
16
|
-
checkoutValidateOrderForPaymentPath: String
|
|
16
|
+
checkoutValidateOrderForPaymentPath: String,
|
|
17
|
+
paymentElementAdditionalOptions: { type: Object, default: {} }
|
|
17
18
|
}
|
|
18
19
|
|
|
19
20
|
static targets = [
|
|
@@ -96,7 +97,8 @@ export default class extends Controller {
|
|
|
96
97
|
postalCode: 'never'
|
|
97
98
|
}
|
|
98
99
|
}
|
|
99
|
-
}
|
|
100
|
+
},
|
|
101
|
+
...this.paymentElementAdditionalOptionsValue
|
|
100
102
|
})
|
|
101
103
|
paymentElement.mount(this.paymentElementTarget)
|
|
102
104
|
paymentElement.on('change', (event) => {
|
|
@@ -0,0 +1,10 @@
|
|
|
1
|
+
module SpreeStripe
|
|
2
|
+
class CreateTaxTransactionJob < BaseJob
|
|
3
|
+
def perform(store_id, payment_intent_id, tax_calculation_id)
|
|
4
|
+
store = Spree::Store.find(store_id)
|
|
5
|
+
gateway = store.stripe_gateway
|
|
6
|
+
|
|
7
|
+
gateway.create_tax_transaction(payment_intent_id, tax_calculation_id) if gateway.present?
|
|
8
|
+
end
|
|
9
|
+
end
|
|
10
|
+
end
|
|
@@ -0,0 +1,96 @@
|
|
|
1
|
+
module SpreeStripe
|
|
2
|
+
module Calculators
|
|
3
|
+
class StripeTax < ::Spree::Calculator
|
|
4
|
+
def self.description
|
|
5
|
+
'Stripe tax calculator'
|
|
6
|
+
end
|
|
7
|
+
|
|
8
|
+
def compute_line_item(line_item)
|
|
9
|
+
order = line_item.order
|
|
10
|
+
return 0.to_d unless stripe_tax_enabled?(order)
|
|
11
|
+
|
|
12
|
+
tax_calculation_data = get_or_create_tax_calculation(order)
|
|
13
|
+
return 0.to_d unless tax_calculation_data.present?
|
|
14
|
+
|
|
15
|
+
# Find the tax line for this specific line item
|
|
16
|
+
line_items = tax_calculation_data.dig('line_items', 'data') || []
|
|
17
|
+
stripe_line_item = line_items.find do |line|
|
|
18
|
+
line['reference'].to_s == line_item.id.to_s
|
|
19
|
+
end
|
|
20
|
+
|
|
21
|
+
# Debug logging
|
|
22
|
+
if stripe_line_item.nil?
|
|
23
|
+
Rails.logger.debug "Stripe Tax: No line item found for reference #{line_item.id}. Available references: #{line_items.map { |li| li['reference'] }.join(', ')}"
|
|
24
|
+
return 0.to_d
|
|
25
|
+
end
|
|
26
|
+
|
|
27
|
+
# Get the tax amount for this line item from amount_tax field
|
|
28
|
+
amount_in_cents = stripe_line_item['amount_tax'] || 0
|
|
29
|
+
Rails.logger.debug "Stripe Tax: Line item #{line_item.id} tax amount: #{amount_in_cents} cents"
|
|
30
|
+
amount_money = Spree::Money.from_cents(amount_in_cents, { currency: order.currency })
|
|
31
|
+
amount_money.to_d
|
|
32
|
+
end
|
|
33
|
+
|
|
34
|
+
def compute_shipment(shipment)
|
|
35
|
+
order = shipment.order
|
|
36
|
+
return 0.to_d unless stripe_tax_enabled?(order)
|
|
37
|
+
|
|
38
|
+
tax_calculation_data = get_or_create_tax_calculation(order)
|
|
39
|
+
return 0.to_d unless tax_calculation_data.present?
|
|
40
|
+
|
|
41
|
+
# Get the shipping cost tax breakdown
|
|
42
|
+
shipping_cost = tax_calculation_data['shipping_cost']
|
|
43
|
+
return 0.to_d unless shipping_cost.present?
|
|
44
|
+
|
|
45
|
+
# Get the tax amount for shipping
|
|
46
|
+
amount_in_cents = shipping_cost['amount_tax'] || 0
|
|
47
|
+
amount_money = Spree::Money.from_cents(amount_in_cents, { currency: order.currency })
|
|
48
|
+
amount_money.to_d
|
|
49
|
+
end
|
|
50
|
+
|
|
51
|
+
private
|
|
52
|
+
|
|
53
|
+
def stripe_tax_enabled?(order)
|
|
54
|
+
stripe_gateway = order.store.stripe_gateway
|
|
55
|
+
stripe_gateway.present? && stripe_gateway.active?
|
|
56
|
+
end
|
|
57
|
+
|
|
58
|
+
def get_or_create_tax_calculation(order)
|
|
59
|
+
return unless order.tax_address.present?
|
|
60
|
+
return if order.state.in?(%w[cart address])
|
|
61
|
+
|
|
62
|
+
stripe_gateway = order.store.stripe_gateway
|
|
63
|
+
|
|
64
|
+
cache_key = [
|
|
65
|
+
order.number,
|
|
66
|
+
order.currency,
|
|
67
|
+
order.item_total,
|
|
68
|
+
order.item_count,
|
|
69
|
+
order.line_items.reload.map { |li| [li.id, li.quantity, li.taxable_amount].compact }.flatten.join('_'),
|
|
70
|
+
order.shipments.map { |s| [s.shipping_method&.id, s.cost].compact }.flatten.join('_'),
|
|
71
|
+
order.tax_address&.cache_key_with_version,
|
|
72
|
+
].compact.join('_')
|
|
73
|
+
|
|
74
|
+
tax_calculation = Rails.cache.fetch("stripe_tax_calculation_#{cache_key}", expires_in: 1.hour) do
|
|
75
|
+
stripe_gateway.create_tax_calculation(order).to_hash.deep_stringify_keys
|
|
76
|
+
rescue => e
|
|
77
|
+
Rails.error.report(e, context: { order_id: order.id }, source: 'spree_stripe')
|
|
78
|
+
{}
|
|
79
|
+
end
|
|
80
|
+
|
|
81
|
+
return nil unless tax_calculation.present?
|
|
82
|
+
|
|
83
|
+
# persist the tax calculation in the order for future use
|
|
84
|
+
# we will need this to create tax transaction
|
|
85
|
+
order.stripe_tax_calculation_id = tax_calculation['id']
|
|
86
|
+
order.save!
|
|
87
|
+
|
|
88
|
+
tax_calculation
|
|
89
|
+
rescue => e
|
|
90
|
+
Rails.error.report(e, context: { order_id: order.id }, source: 'spree_stripe')
|
|
91
|
+
nil
|
|
92
|
+
end
|
|
93
|
+
|
|
94
|
+
end
|
|
95
|
+
end
|
|
96
|
+
end
|
|
@@ -2,6 +2,9 @@ module SpreeStripe
|
|
|
2
2
|
class Gateway < ::Spree::Gateway
|
|
3
3
|
include SpreeStripe::Gateway::Tax if defined?(SpreeStripe::Gateway::Tax)
|
|
4
4
|
|
|
5
|
+
DELAYED_NOTIFICATION_PAYMENT_METHOD_TYPES = %w[sepa_debit us_bank_account].freeze
|
|
6
|
+
BANK_PAYMENT_METHOD_TYPES = %w[customer_balance us_bank_account].freeze
|
|
7
|
+
|
|
5
8
|
preference :publishable_key, :password
|
|
6
9
|
preference :secret_key, :password
|
|
7
10
|
|
|
@@ -23,6 +26,28 @@ module SpreeStripe
|
|
|
23
26
|
self.class
|
|
24
27
|
end
|
|
25
28
|
|
|
29
|
+
def payment_intent_accepted?(payment_intent)
|
|
30
|
+
payment_intent.status.in?(payment_intent_accepted_statuses(payment_intent))
|
|
31
|
+
end
|
|
32
|
+
|
|
33
|
+
def payment_intent_delayed_notification?(payment_intent)
|
|
34
|
+
payment_method = payment_intent.payment_method
|
|
35
|
+
return false unless payment_method.respond_to?(:type)
|
|
36
|
+
|
|
37
|
+
payment_intent.payment_method.type.in?(DELAYED_NOTIFICATION_PAYMENT_METHOD_TYPES)
|
|
38
|
+
end
|
|
39
|
+
|
|
40
|
+
def payment_intent_charge_not_required?(payment_intent)
|
|
41
|
+
payment_intent_bank_payment_method?(payment_intent)
|
|
42
|
+
end
|
|
43
|
+
|
|
44
|
+
def payment_intent_bank_payment_method?(payment_intent)
|
|
45
|
+
payment_method = payment_intent.payment_method
|
|
46
|
+
return false unless payment_method.respond_to?(:type)
|
|
47
|
+
|
|
48
|
+
payment_intent.payment_method.type.in?(BANK_PAYMENT_METHOD_TYPES)
|
|
49
|
+
end
|
|
50
|
+
|
|
26
51
|
# @param amount_in_cents [Integer] the amount in cents to capture
|
|
27
52
|
# @param payment_source [Spree::CreditCard | Spree::PaymentSource]
|
|
28
53
|
# @param gateway_options [Hash] this is an instance of Spree::Payment::GatewayOptions.to_hash
|
|
@@ -52,7 +77,7 @@ module SpreeStripe
|
|
|
52
77
|
payment = ensure_payment_intent_exists_for_payment(payment, amount_in_cents, payment_source)
|
|
53
78
|
stripe_payment_intent = retrieve_payment_intent(payment.response_code)
|
|
54
79
|
|
|
55
|
-
response = if stripe_payment_intent
|
|
80
|
+
response = if payment_intent_accepted?(stripe_payment_intent)
|
|
56
81
|
# payment intent is already confirmed via Stripe JS SDK
|
|
57
82
|
stripe_payment_intent
|
|
58
83
|
else
|
|
@@ -92,8 +117,13 @@ module SpreeStripe
|
|
|
92
117
|
end
|
|
93
118
|
end
|
|
94
119
|
|
|
95
|
-
def void(response_code,
|
|
96
|
-
|
|
120
|
+
def void(response_code, _source, _gateway_options)
|
|
121
|
+
return failure('Response code is blank') if response_code.blank?
|
|
122
|
+
|
|
123
|
+
protect_from_error do
|
|
124
|
+
response = cancel_payment_intent(response_code)
|
|
125
|
+
success(response.id, response)
|
|
126
|
+
end
|
|
97
127
|
end
|
|
98
128
|
|
|
99
129
|
def cancel(payment_intent_id, payment = nil)
|
|
@@ -205,7 +235,7 @@ module SpreeStripe
|
|
|
205
235
|
end
|
|
206
236
|
|
|
207
237
|
def retrieve_payment_intent(payment_intent_id)
|
|
208
|
-
send_request { Stripe::PaymentIntent.retrieve(payment_intent_id) }
|
|
238
|
+
send_request { Stripe::PaymentIntent.retrieve({ id: payment_intent_id, expand: ['payment_method'] }) }
|
|
209
239
|
end
|
|
210
240
|
|
|
211
241
|
def confirm_payment_intent(payment_intent_id)
|
|
@@ -271,6 +301,43 @@ module SpreeStripe
|
|
|
271
301
|
end
|
|
272
302
|
end
|
|
273
303
|
|
|
304
|
+
def create_tax_calculation(order)
|
|
305
|
+
protect_from_error do
|
|
306
|
+
send_request do
|
|
307
|
+
Stripe::Tax::Calculation.create(
|
|
308
|
+
SpreeStripe::TaxPresenter.new(order: order).call
|
|
309
|
+
)
|
|
310
|
+
end
|
|
311
|
+
end
|
|
312
|
+
end
|
|
313
|
+
|
|
314
|
+
def create_tax_transaction(payment_intent_id, tax_calculation_id)
|
|
315
|
+
protect_from_error do
|
|
316
|
+
payload = {
|
|
317
|
+
calculation: tax_calculation_id,
|
|
318
|
+
reference: payment_intent_id,
|
|
319
|
+
expand: ['line_items']
|
|
320
|
+
}
|
|
321
|
+
|
|
322
|
+
send_request { Stripe::Tax::Transaction.create_from_calculation(payload) }
|
|
323
|
+
end
|
|
324
|
+
end
|
|
325
|
+
|
|
326
|
+
def attach_customer_to_credit_card(user)
|
|
327
|
+
payment_method_id = user&.default_credit_card&.gateway_payment_profile_id
|
|
328
|
+
return if payment_method_id.blank? || user&.default_credit_card&.gateway_customer_profile_id.present?
|
|
329
|
+
|
|
330
|
+
customer = fetch_or_create_customer(user: user)
|
|
331
|
+
return if customer.blank?
|
|
332
|
+
|
|
333
|
+
send_request { Stripe::PaymentMethod.attach(payment_method_id, { customer: customer.profile_id }) }
|
|
334
|
+
|
|
335
|
+
user.default_credit_card.update(gateway_customer_profile_id: customer.profile_id, gateway_customer_id: customer.id)
|
|
336
|
+
rescue Stripe::StripeError => e
|
|
337
|
+
Rails.error.report(e, context: { payment_method_id: id, user_id: user.id }, source: 'spree_stripe')
|
|
338
|
+
nil
|
|
339
|
+
end
|
|
340
|
+
|
|
274
341
|
def apple_domain_association_file_content
|
|
275
342
|
@apple_domain_association_file_content ||= apple_developer_merchantid_domain_association&.download
|
|
276
343
|
end
|
|
@@ -382,5 +449,12 @@ module SpreeStripe
|
|
|
382
449
|
|
|
383
450
|
SpreeStripe::CustomerPresenter.new(name: name, email: email, address: address).call
|
|
384
451
|
end
|
|
452
|
+
|
|
453
|
+
def payment_intent_accepted_statuses(payment_intent)
|
|
454
|
+
statuses = %w[succeeded]
|
|
455
|
+
statuses << 'processing' if payment_intent_delayed_notification?(payment_intent)
|
|
456
|
+
statuses << 'requires_action' if payment_intent_charge_not_required?(payment_intent)
|
|
457
|
+
statuses
|
|
458
|
+
end
|
|
385
459
|
end
|
|
386
460
|
end
|
|
@@ -2,6 +2,8 @@ module SpreeStripe
|
|
|
2
2
|
module OrderDecorator
|
|
3
3
|
def self.prepended(base)
|
|
4
4
|
base.has_many :payment_intents, class_name: 'SpreeStripe::PaymentIntent', dependent: :destroy
|
|
5
|
+
|
|
6
|
+
base.store_accessor :private_metadata, :stripe_tax_calculation_id
|
|
5
7
|
end
|
|
6
8
|
|
|
7
9
|
def update_payment_intents
|
|
@@ -23,6 +25,18 @@ module SpreeStripe
|
|
|
23
25
|
|
|
24
26
|
payment_intents.update_all(customer_id: customer_id) if customer_id.present?
|
|
25
27
|
end
|
|
28
|
+
|
|
29
|
+
def persist_user_credit_card
|
|
30
|
+
super
|
|
31
|
+
stripe_gateway = store.stripe_gateway
|
|
32
|
+
return if stripe_gateway.blank?
|
|
33
|
+
|
|
34
|
+
stripe_gateway.attach_customer_to_credit_card(user)
|
|
35
|
+
end
|
|
36
|
+
|
|
37
|
+
def stripe_payment_intent
|
|
38
|
+
@stripe_payment_intent ||= payment_intents.last.stripe_payment_intent
|
|
39
|
+
end
|
|
26
40
|
end
|
|
27
41
|
end
|
|
28
42
|
|
|
@@ -14,13 +14,13 @@ module SpreeStripe
|
|
|
14
14
|
'pass' => 'P',
|
|
15
15
|
'unchecked' => 'I'
|
|
16
16
|
}
|
|
17
|
-
}.freeze
|
|
17
|
+
}.freeze unless defined?(AVS_CODES)
|
|
18
18
|
|
|
19
19
|
CVV_CODES = {
|
|
20
20
|
'pass' => 'M',
|
|
21
21
|
'fail' => 'N',
|
|
22
22
|
'unchecked' => 'P'
|
|
23
|
-
}.freeze
|
|
23
|
+
}.freeze unless defined?(CVV_CODES)
|
|
24
24
|
|
|
25
25
|
def self.prepended(base)
|
|
26
26
|
base.store_accessor :private_metadata, :stripe_charge_id
|
|
@@ -26,12 +26,27 @@ module SpreeStripe
|
|
|
26
26
|
delegate :api_options, to: :payment_method
|
|
27
27
|
delegate :store, :currency, to: :order
|
|
28
28
|
|
|
29
|
+
def accepted?
|
|
30
|
+
payment_method.payment_intent_accepted?(stripe_payment_intent)
|
|
31
|
+
end
|
|
32
|
+
|
|
33
|
+
def successful?
|
|
34
|
+
stripe_payment_intent.status == 'succeeded'
|
|
35
|
+
end
|
|
36
|
+
|
|
37
|
+
def charge_not_required?
|
|
38
|
+
payment_method.payment_intent_charge_not_required?(stripe_payment_intent)
|
|
39
|
+
end
|
|
40
|
+
|
|
29
41
|
def stripe_payment_intent
|
|
30
42
|
@stripe_payment_intent ||= payment_method.retrieve_payment_intent(stripe_id)
|
|
31
43
|
end
|
|
32
44
|
|
|
33
45
|
def stripe_charge
|
|
34
|
-
@stripe_charge ||=
|
|
46
|
+
@stripe_charge ||= begin
|
|
47
|
+
latest_charge = stripe_payment_intent.latest_charge
|
|
48
|
+
latest_charge.present? ? payment_method.retrieve_charge(latest_charge) : nil
|
|
49
|
+
end
|
|
35
50
|
end
|
|
36
51
|
|
|
37
52
|
# here we create a payment if it doesn't exist
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
module SpreeStripe
|
|
2
2
|
module PaymentMethodDecorator
|
|
3
|
-
STRIPE_TYPE = 'SpreeStripe::Gateway'.freeze
|
|
3
|
+
STRIPE_TYPE = 'SpreeStripe::Gateway'.freeze unless defined?(STRIPE_TYPE)
|
|
4
4
|
|
|
5
5
|
def self.prepended(base)
|
|
6
6
|
base.has_many :payment_methods_webhook_keys, class_name: 'SpreeStripe::PaymentMethodsWebhookKey'
|
|
@@ -0,0 +1,17 @@
|
|
|
1
|
+
module SpreeStripe
|
|
2
|
+
module PaymentSources
|
|
3
|
+
class BankTransfer < ::Spree::PaymentSource
|
|
4
|
+
def actions
|
|
5
|
+
%w[credit]
|
|
6
|
+
end
|
|
7
|
+
|
|
8
|
+
def self.display_name
|
|
9
|
+
Spree.t(:bank_transfer)
|
|
10
|
+
end
|
|
11
|
+
|
|
12
|
+
def name
|
|
13
|
+
Spree.t(:bank_transfer)
|
|
14
|
+
end
|
|
15
|
+
end
|
|
16
|
+
end
|
|
17
|
+
end
|
|
@@ -0,0 +1,21 @@
|
|
|
1
|
+
module SpreeStripe
|
|
2
|
+
module ShipmentDecorator
|
|
3
|
+
def self.prepended(base)
|
|
4
|
+
base.state_machine.after_transition to: :shipped, do: :create_tax_transaction_async
|
|
5
|
+
end
|
|
6
|
+
|
|
7
|
+
private
|
|
8
|
+
|
|
9
|
+
def create_tax_transaction_async
|
|
10
|
+
return unless order.fully_shipped?
|
|
11
|
+
return if order.stripe_tax_calculation_id.blank?
|
|
12
|
+
|
|
13
|
+
payment_intent = order.payment_intents.last
|
|
14
|
+
return if payment_intent.blank?
|
|
15
|
+
|
|
16
|
+
SpreeStripe::CreateTaxTransactionJob.perform_later(order.store_id, payment_intent.stripe_id, order.stripe_tax_calculation_id)
|
|
17
|
+
end
|
|
18
|
+
end
|
|
19
|
+
end
|
|
20
|
+
|
|
21
|
+
Spree::Shipment.prepend(SpreeStripe::ShipmentDecorator) if Spree::Shipment.included_modules.exclude?(SpreeStripe::ShipmentDecorator)
|
|
@@ -1,7 +1,6 @@
|
|
|
1
1
|
module SpreeStripe
|
|
2
2
|
class PaymentIntentPresenter
|
|
3
3
|
SETUP_FUTURE_USAGE = 'off_session'
|
|
4
|
-
STATEMENT_DESCRIPTOR_MAX_CHARACTERS = 22
|
|
5
4
|
|
|
6
5
|
def initialize(amount:, order:, customer: nil, payment_method_id: nil, off_session: false)
|
|
7
6
|
@amount = amount
|
|
@@ -50,12 +49,14 @@ module SpreeStripe
|
|
|
50
49
|
|
|
51
50
|
private
|
|
52
51
|
|
|
52
|
+
attr_reader :order, :amount, :customer, :ship_address, :payment_method_id
|
|
53
|
+
|
|
53
54
|
def basic_payload
|
|
54
55
|
{
|
|
55
56
|
amount: amount,
|
|
56
57
|
customer: customer,
|
|
57
58
|
currency: order.currency,
|
|
58
|
-
statement_descriptor_suffix:
|
|
59
|
+
statement_descriptor_suffix: statement_descriptor_suffix,
|
|
59
60
|
automatic_payment_methods: {
|
|
60
61
|
enabled: true
|
|
61
62
|
},
|
|
@@ -66,18 +67,8 @@ module SpreeStripe
|
|
|
66
67
|
}
|
|
67
68
|
end
|
|
68
69
|
|
|
69
|
-
def
|
|
70
|
-
|
|
71
|
-
descriptor = "#{order.number} #{billing_name}".strip
|
|
72
|
-
|
|
73
|
-
if descriptor.length > STATEMENT_DESCRIPTOR_MAX_CHARACTERS
|
|
74
|
-
additional_char_count = descriptor.length - STATEMENT_DESCRIPTOR_MAX_CHARACTERS + 1
|
|
75
|
-
short_billing_name = billing_name[0...-additional_char_count]
|
|
76
|
-
|
|
77
|
-
descriptor = "#{order.number} #{short_billing_name}".strip
|
|
78
|
-
end
|
|
79
|
-
|
|
80
|
-
descriptor
|
|
70
|
+
def statement_descriptor_suffix
|
|
71
|
+
SpreeStripe::StatementDescriptorSuffixPresenter.new(order_description: order.number).call
|
|
81
72
|
end
|
|
82
73
|
|
|
83
74
|
def new_payment_method_payload
|
|
@@ -85,6 +76,9 @@ module SpreeStripe
|
|
|
85
76
|
payment_method_options: {
|
|
86
77
|
card: {
|
|
87
78
|
setup_future_usage: SETUP_FUTURE_USAGE
|
|
79
|
+
},
|
|
80
|
+
sepa_debit: {
|
|
81
|
+
setup_future_usage: SETUP_FUTURE_USAGE
|
|
88
82
|
}
|
|
89
83
|
}
|
|
90
84
|
}
|
|
@@ -97,7 +91,5 @@ module SpreeStripe
|
|
|
97
91
|
confirm: @off_session # confirm is required for off_session payments
|
|
98
92
|
}
|
|
99
93
|
end
|
|
100
|
-
|
|
101
|
-
attr_reader :order, :amount, :customer, :ship_address, :payment_method_id
|
|
102
94
|
end
|
|
103
95
|
end
|
|
@@ -0,0 +1,35 @@
|
|
|
1
|
+
module SpreeStripe
|
|
2
|
+
class StatementDescriptorSuffixPresenter
|
|
3
|
+
STATEMENT_DESCRIPTOR_MAX_CHARS = 10
|
|
4
|
+
STATEMENT_DESCRIPTOR_NOT_ALLOWED_CHARS = /[<>'"*\\]/.freeze
|
|
5
|
+
STATEMENT_PREFIX = 'O#'
|
|
6
|
+
|
|
7
|
+
def initialize(order_description:)
|
|
8
|
+
@order_description = order_description.to_s
|
|
9
|
+
end
|
|
10
|
+
|
|
11
|
+
def call
|
|
12
|
+
return if stripped_order_description.blank?
|
|
13
|
+
|
|
14
|
+
if stripped_order_description.count("A-Z") > 0
|
|
15
|
+
stripped_order_description
|
|
16
|
+
else
|
|
17
|
+
"#{STATEMENT_PREFIX}#{stripped_order_description}"[0...STATEMENT_DESCRIPTOR_MAX_CHARS].strip
|
|
18
|
+
end
|
|
19
|
+
end
|
|
20
|
+
|
|
21
|
+
private
|
|
22
|
+
|
|
23
|
+
attr_reader :order_description
|
|
24
|
+
|
|
25
|
+
def stripped_order_description
|
|
26
|
+
@stripped_order_description ||= begin
|
|
27
|
+
AnyAscii.transliterate(order_description)
|
|
28
|
+
.gsub(STATEMENT_DESCRIPTOR_NOT_ALLOWED_CHARS, '')
|
|
29
|
+
.strip
|
|
30
|
+
.upcase[0...STATEMENT_DESCRIPTOR_MAX_CHARS]
|
|
31
|
+
.strip
|
|
32
|
+
end
|
|
33
|
+
end
|
|
34
|
+
end
|
|
35
|
+
end
|
|
@@ -0,0 +1,63 @@
|
|
|
1
|
+
module SpreeStripe
|
|
2
|
+
class TaxPresenter
|
|
3
|
+
SHIPPING_TAX_CODE = 'txcd_92010001'.freeze
|
|
4
|
+
TAX_BEHAVIOR = 'exclusive'.freeze
|
|
5
|
+
|
|
6
|
+
def initialize(order:)
|
|
7
|
+
@order = order
|
|
8
|
+
end
|
|
9
|
+
|
|
10
|
+
attr_reader :order
|
|
11
|
+
|
|
12
|
+
def call
|
|
13
|
+
{
|
|
14
|
+
currency: order.currency.downcase,
|
|
15
|
+
line_items: build_line_items_attributes(order.line_items),
|
|
16
|
+
customer_details: {
|
|
17
|
+
address: build_address_attributes(order.tax_address),
|
|
18
|
+
address_source: 'shipping',
|
|
19
|
+
},
|
|
20
|
+
shipping_cost: {
|
|
21
|
+
amount: calculate_shipping_cost(order.shipments),
|
|
22
|
+
tax_behavior: TAX_BEHAVIOR,
|
|
23
|
+
tax_code: SHIPPING_TAX_CODE
|
|
24
|
+
},
|
|
25
|
+
expand: [
|
|
26
|
+
'line_items.data.tax_breakdown',
|
|
27
|
+
'shipping_cost.tax_breakdown'
|
|
28
|
+
]
|
|
29
|
+
}
|
|
30
|
+
end
|
|
31
|
+
|
|
32
|
+
private
|
|
33
|
+
|
|
34
|
+
def build_line_items_attributes(line_items)
|
|
35
|
+
line_items.map do |line_item|
|
|
36
|
+
{
|
|
37
|
+
reference: line_item.id,
|
|
38
|
+
tax_behavior: TAX_BEHAVIOR,
|
|
39
|
+
amount: Spree::Money.new(line_item.taxable_amount, currency: order.currency).cents,
|
|
40
|
+
quantity: line_item.quantity
|
|
41
|
+
}
|
|
42
|
+
end
|
|
43
|
+
end
|
|
44
|
+
|
|
45
|
+
def build_address_attributes(address)
|
|
46
|
+
return {} if address.blank?
|
|
47
|
+
|
|
48
|
+
{
|
|
49
|
+
line1: address.address1,
|
|
50
|
+
city: address.city,
|
|
51
|
+
state: address.state_text,
|
|
52
|
+
postal_code: address.zipcode,
|
|
53
|
+
country: address.country_iso
|
|
54
|
+
}
|
|
55
|
+
end
|
|
56
|
+
|
|
57
|
+
def calculate_shipping_cost(shipments)
|
|
58
|
+
zero_money = Spree::Money.new(0, currency: order.currency)
|
|
59
|
+
shipment_money = shipments.sum(zero_money, &:display_cost)
|
|
60
|
+
shipment_money.cents
|
|
61
|
+
end
|
|
62
|
+
end
|
|
63
|
+
end
|
|
@@ -9,7 +9,7 @@ module SpreeStripe
|
|
|
9
9
|
def call
|
|
10
10
|
order = payment_intent.order
|
|
11
11
|
|
|
12
|
-
return order if order.completed? || order.canceled?
|
|
12
|
+
return order if (order.completed? && order.paid?) || order.canceled?
|
|
13
13
|
|
|
14
14
|
charge = payment_intent.stripe_charge
|
|
15
15
|
|
|
@@ -21,10 +21,14 @@ module SpreeStripe
|
|
|
21
21
|
payment = payment_intent.find_or_create_payment!
|
|
22
22
|
|
|
23
23
|
# process the payment
|
|
24
|
-
|
|
24
|
+
if payment_intent.successful?
|
|
25
|
+
payment.process!
|
|
26
|
+
else
|
|
27
|
+
payment.authorize!
|
|
28
|
+
end
|
|
25
29
|
|
|
26
30
|
# complete the order
|
|
27
|
-
Spree::Dependencies.checkout_complete_service.constantize.call(order: order)
|
|
31
|
+
Spree::Dependencies.checkout_complete_service.constantize.call(order: order) unless order.completed?
|
|
28
32
|
end
|
|
29
33
|
|
|
30
34
|
order.reload
|
|
@@ -34,6 +38,8 @@ module SpreeStripe
|
|
|
34
38
|
|
|
35
39
|
# we need to perform this for quick checkout orders which do not have these fields filled
|
|
36
40
|
def add_customer_information(order, charge)
|
|
41
|
+
return order if charge.blank?
|
|
42
|
+
|
|
37
43
|
billing_details = charge.billing_details
|
|
38
44
|
address = billing_details.address
|
|
39
45
|
|
|
@@ -19,6 +19,15 @@ module SpreeStripe
|
|
|
19
19
|
stripe_billing_details: stripe_charge.billing_details,
|
|
20
20
|
gateway: gateway
|
|
21
21
|
).call
|
|
22
|
+
elsif payment_intent.charge_not_required?
|
|
23
|
+
stripe_payment_intent = payment_intent.stripe_payment_intent
|
|
24
|
+
source = SpreeStripe::CreateSource.new(
|
|
25
|
+
order: order,
|
|
26
|
+
stripe_payment_method_details: stripe_payment_intent.payment_method,
|
|
27
|
+
stripe_payment_method_id: stripe_payment_intent.payment_method.id,
|
|
28
|
+
stripe_billing_details: nil,
|
|
29
|
+
gateway: gateway
|
|
30
|
+
).call
|
|
22
31
|
end
|
|
23
32
|
|
|
24
33
|
# sometimes a job is re-tried and creates a double payment record so we need to avoid it!
|
|
@@ -34,6 +34,8 @@ module SpreeStripe
|
|
|
34
34
|
SpreeStripe::PaymentSources::Link.create!(source_params)
|
|
35
35
|
when 'affirm'
|
|
36
36
|
SpreeStripe::PaymentSources::Affirm.create!(source_params)
|
|
37
|
+
when 'customer_balance', 'us_bank_account'
|
|
38
|
+
SpreeStripe::PaymentSources::BankTransfer.create!(source_params)
|
|
37
39
|
else
|
|
38
40
|
raise "[STRIPE] Unknown payment method #{stripe_payment_method_details.type}"
|
|
39
41
|
end
|
|
@@ -2,16 +2,13 @@ module SpreeStripe
|
|
|
2
2
|
module WebhookHandlers
|
|
3
3
|
class PaymentIntentPaymentFailed
|
|
4
4
|
def call(event)
|
|
5
|
-
return unless ['affirm', 'afterpay_clearpay'].include?(event.data.object&.last_payment_error&.payment_method&.type)
|
|
6
|
-
|
|
7
5
|
payment_intent = SpreeStripe::PaymentIntent.find_by(stripe_id: event.data.object.id)
|
|
8
6
|
return if payment_intent.nil?
|
|
9
7
|
|
|
10
8
|
order = payment_intent.order
|
|
11
|
-
|
|
12
9
|
return if order.canceled?
|
|
13
10
|
|
|
14
|
-
order.cancel!
|
|
11
|
+
order.cancel! if order.can_cancel?
|
|
15
12
|
end
|
|
16
13
|
end
|
|
17
14
|
end
|
|
@@ -23,7 +23,8 @@
|
|
|
23
23
|
checkout_stripe_button_checkout_validate_gift_card_data_path_value: respond_to?(:validate_gift_card_data_api_v2_storefront_checkout_path) ? spree.validate_gift_card_data_api_v2_storefront_checkout_path : nil,
|
|
24
24
|
checkout_stripe_button_checkout_validate_order_for_payment_path_value: spree.validate_order_for_payment_api_v2_storefront_checkout_path,
|
|
25
25
|
checkout_stripe_button_return_url_value: spree.stripe_payment_intent_url(current_stripe_payment_intent),
|
|
26
|
-
checkout_stripe_button_shipping_required_value: @order.respond_to?(:quick_checkout_require_address?) ? @order.quick_checkout_require_address? : true
|
|
26
|
+
checkout_stripe_button_shipping_required_value: @order.respond_to?(:quick_checkout_require_address?) ? @order.quick_checkout_require_address? : true,
|
|
27
|
+
checkout_stripe_button_phone_required_value: Spree::Config[:address_requires_phone]
|
|
27
28
|
} do %>
|
|
28
29
|
<div id="payment-request-button"></div>
|
|
29
30
|
|
|
@@ -1,5 +1,6 @@
|
|
|
1
1
|
Rails.application.config.after_initialize do
|
|
2
2
|
Rails.application.config.spree.payment_methods << SpreeStripe::Gateway
|
|
3
|
+
Rails.application.config.spree.calculators.tax_rates << SpreeStripe::Calculators::StripeTax
|
|
3
4
|
|
|
4
5
|
if Rails.application.config.respond_to?(:spree_storefront)
|
|
5
6
|
Rails.application.config.spree_storefront.head_partials << 'spree_stripe/head'
|
data/config/locales/en.yml
CHANGED
data/lib/spree_stripe/engine.rb
CHANGED
|
@@ -14,9 +14,11 @@ module SpreeStripe
|
|
|
14
14
|
end
|
|
15
15
|
|
|
16
16
|
initializer 'spree_stripe.assets' do |app|
|
|
17
|
-
app.config.assets
|
|
18
|
-
|
|
19
|
-
|
|
17
|
+
if app.config.respond_to?(:assets)
|
|
18
|
+
app.config.assets.paths << root.join('app/javascript')
|
|
19
|
+
app.config.assets.paths << root.join('vendor/javascript')
|
|
20
|
+
app.config.assets.precompile += %w[spree_stripe_manifest]
|
|
21
|
+
end
|
|
20
22
|
end
|
|
21
23
|
|
|
22
24
|
initializer 'spree_stripe.importmap', before: 'importmap' do |app|
|
data/lib/spree_stripe/version.rb
CHANGED
data/lib/spree_stripe.rb
CHANGED
metadata
CHANGED
|
@@ -1,14 +1,13 @@
|
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
|
2
2
|
name: spree_stripe
|
|
3
3
|
version: !ruby/object:Gem::Version
|
|
4
|
-
version: 1.
|
|
4
|
+
version: 1.4.0
|
|
5
5
|
platform: ruby
|
|
6
6
|
authors:
|
|
7
7
|
- Vendo Connect Inc.
|
|
8
|
-
autorequire:
|
|
9
8
|
bindir: bin
|
|
10
9
|
cert_chain: []
|
|
11
|
-
date:
|
|
10
|
+
date: 1980-01-02 00:00:00.000000000 Z
|
|
12
11
|
dependencies:
|
|
13
12
|
- !ruby/object:Gem::Dependency
|
|
14
13
|
name: spree
|
|
@@ -178,7 +177,6 @@ dependencies:
|
|
|
178
177
|
- - ">="
|
|
179
178
|
- !ruby/object:Gem::Version
|
|
180
179
|
version: '0'
|
|
181
|
-
description:
|
|
182
180
|
email: hello@spreecommerce.org
|
|
183
181
|
executables: []
|
|
184
182
|
extensions: []
|
|
@@ -188,7 +186,9 @@ files:
|
|
|
188
186
|
- README.md
|
|
189
187
|
- Rakefile
|
|
190
188
|
- app/assets/config/spree_stripe_manifest.js
|
|
189
|
+
- app/assets/images/payment_icons/banktransfer.svg
|
|
191
190
|
- app/assets/images/payment_icons/link.svg
|
|
191
|
+
- app/assets/images/payment_icons/sepadebit.svg
|
|
192
192
|
- app/controllers/spree/api/v2/storefront/stripe/base_controller.rb
|
|
193
193
|
- app/controllers/spree/api/v2/storefront/stripe/payment_intents_controller.rb
|
|
194
194
|
- app/controllers/spree/api/v2/storefront/stripe/setup_intents_controller.rb
|
|
@@ -197,15 +197,18 @@ files:
|
|
|
197
197
|
- app/controllers/spree_stripe/store_controller_decorator.rb
|
|
198
198
|
- app/controllers/stripe_event/webhook_controller_decorator.rb
|
|
199
199
|
- app/helpers/spree_stripe/base_helper.rb
|
|
200
|
+
- app/helpers/spree_stripe/checkout_helper_decorator.rb
|
|
200
201
|
- app/javascript/spree_stripe/application.js
|
|
201
202
|
- app/javascript/spree_stripe/controllers/stripe_button_controller.js
|
|
202
203
|
- app/javascript/spree_stripe/controllers/stripe_controller.js
|
|
203
204
|
- app/jobs/spree_stripe/base_job.rb
|
|
204
205
|
- app/jobs/spree_stripe/complete_order_job.rb
|
|
206
|
+
- app/jobs/spree_stripe/create_tax_transaction_job.rb
|
|
205
207
|
- app/jobs/spree_stripe/create_webhook_endpoint_job.rb
|
|
206
208
|
- app/jobs/spree_stripe/register_domain_job.rb
|
|
207
209
|
- app/jobs/spree_stripe/update_customer_job.rb
|
|
208
210
|
- app/models/spree_stripe/base.rb
|
|
211
|
+
- app/models/spree_stripe/calculators/stripe_tax.rb
|
|
209
212
|
- app/models/spree_stripe/credit_card_decorator.rb
|
|
210
213
|
- app/models/spree_stripe/custom_domain_decorator.rb
|
|
211
214
|
- app/models/spree_stripe/gateway.rb
|
|
@@ -219,16 +222,20 @@ files:
|
|
|
219
222
|
- app/models/spree_stripe/payment_sources/affirm.rb
|
|
220
223
|
- app/models/spree_stripe/payment_sources/after_pay.rb
|
|
221
224
|
- app/models/spree_stripe/payment_sources/alipay.rb
|
|
225
|
+
- app/models/spree_stripe/payment_sources/bank_transfer.rb
|
|
222
226
|
- app/models/spree_stripe/payment_sources/ideal.rb
|
|
223
227
|
- app/models/spree_stripe/payment_sources/klarna.rb
|
|
224
228
|
- app/models/spree_stripe/payment_sources/link.rb
|
|
225
229
|
- app/models/spree_stripe/payment_sources/przelewy24.rb
|
|
226
230
|
- app/models/spree_stripe/payment_sources/sepa_debit.rb
|
|
231
|
+
- app/models/spree_stripe/shipment_decorator.rb
|
|
227
232
|
- app/models/spree_stripe/store_decorator.rb
|
|
228
233
|
- app/models/spree_stripe/user_decorator.rb
|
|
229
234
|
- app/models/spree_stripe/webhook_key.rb
|
|
230
235
|
- app/presenters/spree_stripe/customer_presenter.rb
|
|
231
236
|
- app/presenters/spree_stripe/payment_intent_presenter.rb
|
|
237
|
+
- app/presenters/spree_stripe/statement_descriptor_suffix_presenter.rb
|
|
238
|
+
- app/presenters/spree_stripe/tax_presenter.rb
|
|
232
239
|
- app/serializers/spree/api/v2/platform/affirm_serializer.rb
|
|
233
240
|
- app/serializers/spree/api/v2/platform/after_pay_serializer.rb
|
|
234
241
|
- app/serializers/spree/api/v2/platform/alipay_serializer.rb
|
|
@@ -292,7 +299,6 @@ homepage: https://github.com/spree/spree_stripe
|
|
|
292
299
|
licenses:
|
|
293
300
|
- AGPL-3.0-or-later
|
|
294
301
|
metadata: {}
|
|
295
|
-
post_install_message:
|
|
296
302
|
rdoc_options: []
|
|
297
303
|
require_paths:
|
|
298
304
|
- lib
|
|
@@ -308,8 +314,7 @@ required_rubygems_version: !ruby/object:Gem::Requirement
|
|
|
308
314
|
version: '0'
|
|
309
315
|
requirements:
|
|
310
316
|
- none
|
|
311
|
-
rubygems_version:
|
|
312
|
-
signing_key:
|
|
317
|
+
rubygems_version: 4.0.2
|
|
313
318
|
specification_version: 4
|
|
314
319
|
summary: Official Spree Commerce Stripe payment gateway extension
|
|
315
320
|
test_files: []
|