upgrades: factor out Stripe integration.
Factor out the Stripe code from the UserUpgrade class. Introduce a new PaymentTransaction abstract class that represents a payment with some payment processor, and a PaymentTransaction::Stripe class that implements transactions with Stripe. Note that we can't completely eliminate Stripe even though we no longer accept payments with it because we still need to be able to look up old payments in Stripe.
This commit is contained in:
@@ -8,7 +8,7 @@ class WebhooksController < ApplicationController
|
||||
def receive
|
||||
case params[:source]
|
||||
when "stripe"
|
||||
UserUpgrade.receive_webhook(request)
|
||||
PaymentTransaction::Stripe.receive_webhook(request)
|
||||
head 200
|
||||
when "discord"
|
||||
json = DiscordSlashCommand.receive_webhook(request)
|
||||
|
||||
55
app/logical/payment_transaction.rb
Normal file
55
app/logical/payment_transaction.rb
Normal file
@@ -0,0 +1,55 @@
|
||||
# frozen_string_literal: true
|
||||
|
||||
# A PaymentTransaction represents a payment in some payment processor's backend API.
|
||||
#
|
||||
# @see app/logical/payment_transaction/stripe.rb
|
||||
class PaymentTransaction
|
||||
attr_reader :user_upgrade
|
||||
delegate :recipient, :purchaser, :upgrade_type, :pending?, :stripe_id, to: :user_upgrade
|
||||
|
||||
def initialize(user_upgrade)
|
||||
@user_upgrade = user_upgrade
|
||||
end
|
||||
|
||||
# Initiate a new payment. Normally this sets up a checkout page with the payment processor, which
|
||||
# we redirect the user to. When the payment succeeds, the user is redirected to a success page and
|
||||
# the processor sends us a webhook, which we catch to finalize the upgrade. If the payment fails,
|
||||
# the user is redirected to an error page and the upgrade doesn't go through.
|
||||
#
|
||||
# Normally this returns a processor-specific transaction object containing an ID or URL, which is
|
||||
# used to redirect to the checkout page.
|
||||
def create!(country: "US", allow_promotion_codes: false)
|
||||
raise NotImplementedError
|
||||
end
|
||||
|
||||
# Refund a completed payment to the purchaser.
|
||||
def refund!
|
||||
raise NotImplementedError
|
||||
end
|
||||
|
||||
# Handle a webhook from the payment processor. Normally the payment processor sends us a webhook
|
||||
# to notify us of successful payments, which we listen for to complete the upgrade.
|
||||
def receive_webhook!(request)
|
||||
raise NotImplementedError
|
||||
end
|
||||
|
||||
# A public link to the payment processor's receipt for the transaction.
|
||||
def receipt_url
|
||||
nil
|
||||
end
|
||||
|
||||
# A private link to the transaction in the payment processor's admin area.
|
||||
def payment_url
|
||||
nil
|
||||
end
|
||||
|
||||
# The amount of money paid in the transaction.
|
||||
def amount
|
||||
nil
|
||||
end
|
||||
|
||||
# The currency used in the transaction.
|
||||
def currency
|
||||
nil
|
||||
end
|
||||
end
|
||||
190
app/logical/payment_transaction/stripe.rb
Normal file
190
app/logical/payment_transaction/stripe.rb
Normal file
@@ -0,0 +1,190 @@
|
||||
# frozen_string_literal: true
|
||||
|
||||
class PaymentTransaction::Stripe < PaymentTransaction
|
||||
delegate :stripe_id, to: :user_upgrade
|
||||
|
||||
def self.enabled?
|
||||
Danbooru.config.stripe_secret_key.present? && Danbooru.config.stripe_publishable_key.present? && Danbooru.config.stripe_webhook_secret.present?
|
||||
end
|
||||
|
||||
def create!(country: "US", allow_promotion_codes: false)
|
||||
checkout_session = ::Stripe::Checkout::Session.create(
|
||||
mode: "payment",
|
||||
success_url: Routes.user_upgrade_url(user_upgrade),
|
||||
cancel_url: Routes.new_user_upgrade_url(user_id: recipient.id),
|
||||
client_reference_id: "user_upgrade_#{user_upgrade.id}",
|
||||
customer_email: purchaser.email_address&.address,
|
||||
payment_method_types: payment_method_types(country),
|
||||
allow_promotion_codes: allow_promotion_codes.presence,
|
||||
line_items: [{
|
||||
price: upgrade_price_id(country),
|
||||
quantity: 1,
|
||||
}],
|
||||
discounts: [{
|
||||
coupon: promotion_discount_id,
|
||||
}],
|
||||
metadata: {
|
||||
user_upgrade_id: user_upgrade.id,
|
||||
purchaser_id: purchaser.id,
|
||||
recipient_id: recipient.id,
|
||||
purchaser_name: purchaser.name,
|
||||
recipient_name: recipient.name,
|
||||
upgrade_type: upgrade_type,
|
||||
country: country,
|
||||
is_gift: user_upgrade.is_gift?,
|
||||
level: user_upgrade.level,
|
||||
}
|
||||
)
|
||||
|
||||
user_upgrade.update!(stripe_id: checkout_session.id)
|
||||
checkout_session
|
||||
end
|
||||
|
||||
def refund!(reason = nil)
|
||||
::Stripe::Refund.create(payment_intent: payment_intent.id, reason: reason)
|
||||
end
|
||||
|
||||
concerning :WebhookMethods do
|
||||
class_methods do
|
||||
def receive_webhook(request)
|
||||
event = build_event(request)
|
||||
|
||||
case event.type
|
||||
when "checkout.session.completed"
|
||||
checkout_session_completed(event.data.object)
|
||||
when "charge.dispute.created"
|
||||
charge_dispute_created(event.data.object)
|
||||
when "radar.early_fraud_warning.created"
|
||||
radar_early_fraud_warning_created(event.data.object)
|
||||
end
|
||||
end
|
||||
|
||||
private def build_event(request)
|
||||
payload = request.body.read
|
||||
signature = request.headers["Stripe-Signature"]
|
||||
::Stripe::Webhook.construct_event(payload, signature, Danbooru.config.stripe_webhook_secret)
|
||||
end
|
||||
|
||||
private def checkout_session_completed(checkout)
|
||||
user_upgrade = UserUpgrade.find(checkout.metadata.user_upgrade_id)
|
||||
user_upgrade.process_upgrade!(checkout.payment_status)
|
||||
end
|
||||
|
||||
private def charge_dispute_created(dispute)
|
||||
Dmail.create_automated(to: User.owner, title: "Stripe Dispute", body: <<~EOS)
|
||||
Dispute: https://stripe.com/payments/#{dispute.charge}
|
||||
EOS
|
||||
end
|
||||
|
||||
private def radar_early_fraud_warning_created(fraud_warning)
|
||||
Dmail.create_automated(to: User.owner, title: "Stripe Early Fraud Warning", body: <<~EOS)
|
||||
Charge: https://stripe.com/payments/#{fraud_warning.charge}
|
||||
EOS
|
||||
end
|
||||
|
||||
private def register_webhook
|
||||
webhook = ::Stripe::WebhookEndpoint.create({
|
||||
url: Routes.webhook_user_upgrade_url(source: "stripe"),
|
||||
enabled_events: [
|
||||
"checkout.session.completed",
|
||||
"checkout.session.async_payment_failed",
|
||||
"checkout.session.async_payment_succeeded",
|
||||
"charge.dispute.created",
|
||||
"radar.early_fraud_warning.created",
|
||||
],
|
||||
})
|
||||
|
||||
webhook.secret
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
def receipt_url
|
||||
return nil if pending? || stripe_id.nil?
|
||||
charge.receipt_url
|
||||
end
|
||||
|
||||
def payment_url
|
||||
return nil if pending? || stripe_id.nil?
|
||||
"https://dashboard.stripe.com/payments/#{payment_intent.id}"
|
||||
end
|
||||
|
||||
def amount
|
||||
payment_intent.amount
|
||||
end
|
||||
|
||||
def currency
|
||||
payment_intent.currency
|
||||
end
|
||||
|
||||
private def checkout_session
|
||||
return nil if stripe_id.nil?
|
||||
@checkout_session ||= ::Stripe::Checkout::Session.retrieve(stripe_id)
|
||||
end
|
||||
|
||||
private def payment_intent
|
||||
return nil if checkout_session.nil?
|
||||
@payment_intent ||= ::Stripe::PaymentIntent.retrieve(checkout_session.payment_intent)
|
||||
end
|
||||
|
||||
private def charge
|
||||
payment_intent.charges.data.first
|
||||
end
|
||||
|
||||
private def payment_method_types(country)
|
||||
case country.to_s.upcase
|
||||
# Austria, https://stripe.com/docs/payments/bancontact
|
||||
when "AT"
|
||||
["card", "eps"]
|
||||
# Belgium, https://stripe.com/docs/payments/eps
|
||||
when "BE"
|
||||
["card", "bancontact"]
|
||||
# Germany, https://stripe.com/docs/payments/giropay
|
||||
when "DE"
|
||||
["card", "giropay"]
|
||||
# Netherlands, https://stripe.com/docs/payments/ideal
|
||||
when "NL"
|
||||
["card", "ideal"]
|
||||
# Poland, https://stripe.com/docs/payments/p24
|
||||
when "PL"
|
||||
["card", "p24"]
|
||||
else
|
||||
["card"]
|
||||
end
|
||||
end
|
||||
|
||||
private def preferred_currency(country)
|
||||
case country.to_s.upcase
|
||||
# Austria, Belgium, Germany, Netherlands, Poland
|
||||
when "AT", "BE", "DE", "NL", "PL"
|
||||
"eur"
|
||||
else
|
||||
"usd"
|
||||
end
|
||||
end
|
||||
|
||||
private def upgrade_price_id(country)
|
||||
case [upgrade_type, preferred_currency(country)]
|
||||
when ["gold", "usd"]
|
||||
Danbooru.config.stripe_gold_usd_price_id
|
||||
when ["gold", "eur"]
|
||||
Danbooru.config.stripe_gold_eur_price_id
|
||||
when ["platinum", "usd"]
|
||||
Danbooru.config.stripe_platinum_usd_price_id
|
||||
when ["platinum", "eur"]
|
||||
Danbooru.config.stripe_platinum_eur_price_id
|
||||
when ["gold_to_platinum", "usd"]
|
||||
Danbooru.config.stripe_gold_to_platinum_usd_price_id
|
||||
when ["gold_to_platinum", "eur"]
|
||||
Danbooru.config.stripe_gold_to_platinum_eur_price_id
|
||||
else
|
||||
raise NotImplementedError
|
||||
end
|
||||
end
|
||||
|
||||
private def promotion_discount_id
|
||||
if Danbooru.config.is_promotion?
|
||||
Danbooru.config.stripe_promotion_discount_id
|
||||
end
|
||||
end
|
||||
end
|
||||
@@ -4,6 +4,8 @@ class UserUpgrade < ApplicationRecord
|
||||
belongs_to :recipient, class_name: "User"
|
||||
belongs_to :purchaser, class_name: "User"
|
||||
|
||||
delegate :payment_url, :receipt_url, to: :transaction
|
||||
|
||||
enum upgrade_type: {
|
||||
gold: 0,
|
||||
platinum: 10,
|
||||
@@ -21,19 +23,7 @@ class UserUpgrade < ApplicationRecord
|
||||
scope :self_upgrade, -> { where("recipient_id = purchaser_id") }
|
||||
|
||||
def self.enabled?
|
||||
stripe_secret_key.present? && stripe_publishable_key.present? && stripe_webhook_secret.present?
|
||||
end
|
||||
|
||||
def self.stripe_secret_key
|
||||
Danbooru.config.stripe_secret_key
|
||||
end
|
||||
|
||||
def self.stripe_publishable_key
|
||||
Danbooru.config.stripe_publishable_key
|
||||
end
|
||||
|
||||
def self.stripe_webhook_secret
|
||||
Danbooru.config.stripe_webhook_secret
|
||||
Danbooru.config.user_upgrades_enabled?
|
||||
end
|
||||
|
||||
def self.gold_price
|
||||
@@ -147,74 +137,23 @@ class UserUpgrade < ApplicationRecord
|
||||
end
|
||||
end
|
||||
|
||||
concerning :StripeMethods do
|
||||
concerning :TransactionMethods do
|
||||
def create_checkout!(country: "US", allow_promotion_codes: false)
|
||||
methods = payment_method_types(country)
|
||||
currency = preferred_currency(country)
|
||||
price_id = upgrade_price_id(currency)
|
||||
|
||||
checkout = Stripe::Checkout::Session.create(
|
||||
mode: "payment",
|
||||
success_url: Routes.user_upgrade_url(self),
|
||||
cancel_url: Routes.new_user_upgrade_url(user_id: recipient.id),
|
||||
client_reference_id: "user_upgrade_#{id}",
|
||||
customer_email: purchaser.email_address&.address,
|
||||
payment_method_types: methods,
|
||||
allow_promotion_codes: allow_promotion_codes.presence,
|
||||
line_items: [{
|
||||
price: price_id,
|
||||
quantity: 1,
|
||||
}],
|
||||
discounts: [{
|
||||
coupon: promotion_discount_id,
|
||||
}],
|
||||
metadata: {
|
||||
user_upgrade_id: id,
|
||||
purchaser_id: purchaser.id,
|
||||
recipient_id: recipient.id,
|
||||
purchaser_name: purchaser.name,
|
||||
recipient_name: recipient.name,
|
||||
upgrade_type: upgrade_type,
|
||||
country: country,
|
||||
is_gift: is_gift?,
|
||||
level: level,
|
||||
}
|
||||
)
|
||||
|
||||
update!(stripe_id: checkout.id)
|
||||
checkout
|
||||
transaction.create!(country: country, allow_promotion_codes: allow_promotion_codes)
|
||||
end
|
||||
|
||||
def refund!(reason: nil)
|
||||
with_lock do
|
||||
return if refunded?
|
||||
|
||||
Stripe::Refund.create(payment_intent: payment_intent.id, reason: reason)
|
||||
transaction.refund!(reason)
|
||||
recipient.update!(level: previous_level)
|
||||
update!(status: "refunded")
|
||||
end
|
||||
end
|
||||
|
||||
def receipt_url
|
||||
return nil if pending? || stripe_id.nil?
|
||||
charge.receipt_url
|
||||
end
|
||||
|
||||
def payment_url
|
||||
return nil if pending? || stripe_id.nil?
|
||||
"https://dashboard.stripe.com/payments/#{payment_intent.id}"
|
||||
end
|
||||
|
||||
def checkout_session
|
||||
@checkout_session ||= Stripe::Checkout::Session.retrieve(stripe_id)
|
||||
end
|
||||
|
||||
def payment_intent
|
||||
@payment_intent ||= Stripe::PaymentIntent.retrieve(checkout_session.payment_intent)
|
||||
end
|
||||
|
||||
def charge
|
||||
payment_intent.charges.data.first
|
||||
def transaction
|
||||
PaymentTransaction::Stripe.new(self)
|
||||
end
|
||||
|
||||
def has_receipt?
|
||||
@@ -224,115 +163,5 @@ class UserUpgrade < ApplicationRecord
|
||||
def has_payment?
|
||||
!pending?
|
||||
end
|
||||
|
||||
def promotion_discount_id
|
||||
if Danbooru.config.is_promotion?
|
||||
Danbooru.config.stripe_promotion_discount_id
|
||||
end
|
||||
end
|
||||
|
||||
def upgrade_price_id(currency)
|
||||
case [upgrade_type, currency]
|
||||
when ["gold", "usd"]
|
||||
Danbooru.config.stripe_gold_usd_price_id
|
||||
when ["gold", "eur"]
|
||||
Danbooru.config.stripe_gold_eur_price_id
|
||||
when ["platinum", "usd"]
|
||||
Danbooru.config.stripe_platinum_usd_price_id
|
||||
when ["platinum", "eur"]
|
||||
Danbooru.config.stripe_platinum_eur_price_id
|
||||
when ["gold_to_platinum", "usd"]
|
||||
Danbooru.config.stripe_gold_to_platinum_usd_price_id
|
||||
when ["gold_to_platinum", "eur"]
|
||||
Danbooru.config.stripe_gold_to_platinum_eur_price_id
|
||||
else
|
||||
raise NotImplementedError
|
||||
end
|
||||
end
|
||||
|
||||
def payment_method_types(country)
|
||||
case country.to_s.upcase
|
||||
# Austria, https://stripe.com/docs/payments/bancontact
|
||||
when "AT"
|
||||
["card", "eps"]
|
||||
# Belgium, https://stripe.com/docs/payments/eps
|
||||
when "BE"
|
||||
["card", "bancontact"]
|
||||
# Germany, https://stripe.com/docs/payments/giropay
|
||||
when "DE"
|
||||
["card", "giropay"]
|
||||
# Netherlands, https://stripe.com/docs/payments/ideal
|
||||
when "NL"
|
||||
["card", "ideal"]
|
||||
# Poland, https://stripe.com/docs/payments/p24
|
||||
when "PL"
|
||||
["card", "p24"]
|
||||
else
|
||||
["card"]
|
||||
end
|
||||
end
|
||||
|
||||
def preferred_currency(country)
|
||||
case country.to_s.upcase
|
||||
# Austria, Belgium, Germany, Netherlands, Poland
|
||||
when "AT", "BE", "DE", "NL", "PL"
|
||||
"eur"
|
||||
else
|
||||
"usd"
|
||||
end
|
||||
end
|
||||
|
||||
class_methods do
|
||||
def register_webhook
|
||||
webhook = Stripe::WebhookEndpoint.create({
|
||||
url: Routes.webhook_user_upgrade_url(source: "stripe"),
|
||||
enabled_events: [
|
||||
"checkout.session.completed",
|
||||
"checkout.session.async_payment_failed",
|
||||
"checkout.session.async_payment_succeeded",
|
||||
"charge.dispute.created",
|
||||
"radar.early_fraud_warning.created",
|
||||
],
|
||||
})
|
||||
|
||||
webhook.secret
|
||||
end
|
||||
|
||||
def receive_webhook(request)
|
||||
event = build_event(request)
|
||||
|
||||
case event.type
|
||||
when "checkout.session.completed"
|
||||
checkout_session_completed(event.data.object)
|
||||
when "charge.dispute.created"
|
||||
charge_dispute_created(event.data.object)
|
||||
when "radar.early_fraud_warning.created"
|
||||
radar_early_fraud_warning_created(event.data.object)
|
||||
end
|
||||
end
|
||||
|
||||
def build_event(request)
|
||||
payload = request.body.read
|
||||
signature = request.headers["Stripe-Signature"]
|
||||
Stripe::Webhook.construct_event(payload, signature, stripe_webhook_secret)
|
||||
end
|
||||
|
||||
def checkout_session_completed(checkout)
|
||||
user_upgrade = UserUpgrade.find(checkout.metadata.user_upgrade_id)
|
||||
user_upgrade.process_upgrade!(checkout.payment_status)
|
||||
end
|
||||
|
||||
def charge_dispute_created(dispute)
|
||||
Dmail.create_automated(to: User.owner, title: "Stripe Dispute", body: <<~EOS)
|
||||
Dispute: https://stripe.com/payments/#{dispute.charge}
|
||||
EOS
|
||||
end
|
||||
|
||||
def radar_early_fraud_warning_created(fraud_warning)
|
||||
Dmail.create_automated(to: User.owner, title: "Stripe Early Fraud Warning", body: <<~EOS)
|
||||
Charge: https://stripe.com/payments/#{fraud_warning.charge}
|
||||
EOS
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
@@ -1,2 +1,2 @@
|
||||
var stripe = Stripe("<%= j UserUpgrade.stripe_publishable_key %>");
|
||||
var stripe = Stripe("<%= j Danbooru.config.stripe_publishable_key %>");
|
||||
stripe.redirectToCheckout({ sessionId: "<%= j @checkout.id %>" });
|
||||
|
||||
@@ -363,6 +363,11 @@ module Danbooru
|
||||
resolution_mismatch source_larger source_smaller]
|
||||
end
|
||||
|
||||
# Whether the Gold account upgrade page should be enabled.
|
||||
def user_upgrades_enabled?
|
||||
true
|
||||
end
|
||||
|
||||
def stripe_secret_key
|
||||
end
|
||||
|
||||
|
||||
@@ -9,8 +9,8 @@ class WebhooksControllerTest < ActionDispatch::IntegrationTest
|
||||
StripeMock.stop
|
||||
end
|
||||
|
||||
def post_webhook(*args, metadata: {}, payment_status: "paid")
|
||||
skip unless UserUpgrade.enabled?
|
||||
def post_stripe_webhook(*args, metadata: {}, payment_status: "paid")
|
||||
skip unless PaymentTransaction::Stripe.enabled?
|
||||
event = StripeMock.mock_webhook_event(*args, payment_status: payment_status, metadata: metadata)
|
||||
signature = generate_stripe_signature(event)
|
||||
headers = { "Stripe-Signature": signature }
|
||||
@@ -22,7 +22,7 @@ class WebhooksControllerTest < ActionDispatch::IntegrationTest
|
||||
# https://stripe.com/docs/webhooks/signatures
|
||||
def generate_stripe_signature(event)
|
||||
time = Time.now
|
||||
secret = UserUpgrade.stripe_webhook_secret
|
||||
secret = Danbooru.config.stripe_webhook_secret
|
||||
signature = Stripe::Webhook::Signature.compute_signature(time, event.to_json, secret)
|
||||
Stripe::Webhook::Signature.generate_header(time, signature, scheme: Stripe::Webhook::Signature::EXPECTED_SCHEME)
|
||||
end
|
||||
@@ -58,7 +58,7 @@ class WebhooksControllerTest < ActionDispatch::IntegrationTest
|
||||
|
||||
context "for a payment_intent.created event" do
|
||||
should "work" do
|
||||
post_webhook("payment_intent.created")
|
||||
post_stripe_webhook("payment_intent.created")
|
||||
|
||||
assert_response 200
|
||||
end
|
||||
@@ -68,7 +68,7 @@ class WebhooksControllerTest < ActionDispatch::IntegrationTest
|
||||
context "for completed event with an unpaid payment status" do
|
||||
should "not upgrade the user" do
|
||||
@user_upgrade = create(:self_gold_upgrade)
|
||||
post_webhook("checkout.session.completed", metadata: { user_upgrade_id: @user_upgrade.id }, payment_status: "unpaid")
|
||||
post_stripe_webhook("checkout.session.completed", metadata: { user_upgrade_id: @user_upgrade.id }, payment_status: "unpaid")
|
||||
|
||||
assert_response 200
|
||||
assert_equal("processing", @user_upgrade.reload.status)
|
||||
@@ -80,7 +80,7 @@ class WebhooksControllerTest < ActionDispatch::IntegrationTest
|
||||
context "to Gold" do
|
||||
should "upgrade the user" do
|
||||
@user_upgrade = create(:self_gold_upgrade)
|
||||
post_webhook("checkout.session.completed", metadata: { user_upgrade_id: @user_upgrade.id })
|
||||
post_stripe_webhook("checkout.session.completed", metadata: { user_upgrade_id: @user_upgrade.id })
|
||||
|
||||
assert_response 200
|
||||
assert_equal("complete", @user_upgrade.reload.status)
|
||||
@@ -91,7 +91,7 @@ class WebhooksControllerTest < ActionDispatch::IntegrationTest
|
||||
context "to Platinum" do
|
||||
should "upgrade the user" do
|
||||
@user_upgrade = create(:self_platinum_upgrade)
|
||||
post_webhook("checkout.session.completed", metadata: { user_upgrade_id: @user_upgrade.id })
|
||||
post_stripe_webhook("checkout.session.completed", metadata: { user_upgrade_id: @user_upgrade.id })
|
||||
|
||||
assert_response 200
|
||||
assert_equal("complete", @user_upgrade.reload.status)
|
||||
@@ -102,7 +102,7 @@ class WebhooksControllerTest < ActionDispatch::IntegrationTest
|
||||
context "from Gold to Platinum" do
|
||||
should "upgrade the user" do
|
||||
@user_upgrade = create(:self_gold_to_platinum_upgrade)
|
||||
post_webhook("checkout.session.completed", metadata: { user_upgrade_id: @user_upgrade.id })
|
||||
post_stripe_webhook("checkout.session.completed", metadata: { user_upgrade_id: @user_upgrade.id })
|
||||
|
||||
assert_response 200
|
||||
assert_equal("complete", @user_upgrade.reload.status)
|
||||
@@ -115,7 +115,7 @@ class WebhooksControllerTest < ActionDispatch::IntegrationTest
|
||||
context "to Gold" do
|
||||
should "upgrade the user" do
|
||||
@user_upgrade = create(:gift_gold_upgrade)
|
||||
post_webhook("checkout.session.completed", metadata: { user_upgrade_id: @user_upgrade.id })
|
||||
post_stripe_webhook("checkout.session.completed", metadata: { user_upgrade_id: @user_upgrade.id })
|
||||
|
||||
assert_response 200
|
||||
assert_equal("complete", @user_upgrade.reload.status)
|
||||
@@ -126,7 +126,7 @@ class WebhooksControllerTest < ActionDispatch::IntegrationTest
|
||||
context "to Platinum" do
|
||||
should "upgrade the user" do
|
||||
@user_upgrade = create(:gift_platinum_upgrade)
|
||||
post_webhook("checkout.session.completed", metadata: { user_upgrade_id: @user_upgrade.id })
|
||||
post_stripe_webhook("checkout.session.completed", metadata: { user_upgrade_id: @user_upgrade.id })
|
||||
|
||||
assert_response 200
|
||||
assert_equal("complete", @user_upgrade.reload.status)
|
||||
@@ -137,7 +137,7 @@ class WebhooksControllerTest < ActionDispatch::IntegrationTest
|
||||
context "from Gold to Platinum" do
|
||||
should "upgrade the user" do
|
||||
@user_upgrade = create(:gift_gold_to_platinum_upgrade)
|
||||
post_webhook("checkout.session.completed", metadata: { user_upgrade_id: @user_upgrade.id })
|
||||
post_stripe_webhook("checkout.session.completed", metadata: { user_upgrade_id: @user_upgrade.id })
|
||||
|
||||
assert_response 200
|
||||
assert_equal("complete", @user_upgrade.reload.status)
|
||||
|
||||
@@ -3,11 +3,11 @@ StripeMock.webhook_fixture_path = "test/fixtures/stripe-webhooks"
|
||||
module StripeTestHelper
|
||||
def mock_stripe!
|
||||
setup do
|
||||
StripeMock.start unless UserUpgrade.enabled?
|
||||
StripeMock.start unless PaymentTransaction::Stripe.enabled?
|
||||
end
|
||||
|
||||
teardown do
|
||||
StripeMock.stop unless UserUpgrade.enabled?
|
||||
StripeMock.stop unless PaymentTransaction::Stripe.enabled?
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
@@ -44,7 +44,7 @@ class UserUpgradeTest < ActiveSupport::TestCase
|
||||
context "for a gifted upgrade" do
|
||||
context "to Gold" do
|
||||
should "prefill the Stripe checkout page with the purchaser's email address" do
|
||||
skip "Stripe API keys not configured" unless UserUpgrade.enabled?
|
||||
skip "Stripe API keys not configured" unless PaymentTransaction::Stripe.enabled?
|
||||
|
||||
@user = create(:user, email_address: build(:email_address))
|
||||
@user_upgrade = create(:gift_gold_upgrade, purchaser: @user)
|
||||
@@ -64,48 +64,48 @@ class UserUpgradeTest < ActiveSupport::TestCase
|
||||
@user_upgrade = create(:self_gold_upgrade)
|
||||
@checkout = @user_upgrade.create_checkout!(country: "US")
|
||||
|
||||
assert_equal(UserUpgrade.gold_price, @user_upgrade.payment_intent.amount)
|
||||
assert_equal("usd", @user_upgrade.payment_intent.currency)
|
||||
assert_equal(UserUpgrade.gold_price, @user_upgrade.transaction.amount)
|
||||
assert_equal("usd", @user_upgrade.transaction.currency)
|
||||
end
|
||||
|
||||
should "choose the right price in USD for a platinum upgrade" do
|
||||
@user_upgrade = create(:self_platinum_upgrade)
|
||||
@checkout = @user_upgrade.create_checkout!(country: "US")
|
||||
|
||||
assert_equal(UserUpgrade.platinum_price, @user_upgrade.payment_intent.amount)
|
||||
assert_equal("usd", @user_upgrade.payment_intent.currency)
|
||||
assert_equal(UserUpgrade.platinum_price, @user_upgrade.transaction.amount)
|
||||
assert_equal("usd", @user_upgrade.transaction.currency)
|
||||
end
|
||||
|
||||
should "choose the right price in USD for a gold to platinum upgrade" do
|
||||
@user_upgrade = create(:self_gold_to_platinum_upgrade)
|
||||
@checkout = @user_upgrade.create_checkout!(country: "US")
|
||||
|
||||
assert_equal(UserUpgrade.gold_to_platinum_price, @user_upgrade.payment_intent.amount)
|
||||
assert_equal("usd", @user_upgrade.payment_intent.currency)
|
||||
assert_equal(UserUpgrade.gold_to_platinum_price, @user_upgrade.transaction.amount)
|
||||
assert_equal("usd", @user_upgrade.transaction.currency)
|
||||
end
|
||||
|
||||
should "choose the right price in EUR for a gold upgrade" do
|
||||
@user_upgrade = create(:self_gold_upgrade)
|
||||
@checkout = @user_upgrade.create_checkout!(country: "DE")
|
||||
|
||||
assert_equal(0.8 * UserUpgrade.gold_price, @user_upgrade.payment_intent.amount)
|
||||
assert_equal("eur", @user_upgrade.payment_intent.currency)
|
||||
assert_equal(0.8 * UserUpgrade.gold_price, @user_upgrade.transaction.amount)
|
||||
assert_equal("eur", @user_upgrade.transaction.currency)
|
||||
end
|
||||
|
||||
should "choose the right price in EUR for a platinum upgrade" do
|
||||
@user_upgrade = create(:self_platinum_upgrade)
|
||||
@checkout = @user_upgrade.create_checkout!(country: "DE")
|
||||
|
||||
assert_equal(0.8 * UserUpgrade.platinum_price, @user_upgrade.payment_intent.amount)
|
||||
assert_equal("eur", @user_upgrade.payment_intent.currency)
|
||||
assert_equal(0.8 * UserUpgrade.platinum_price, @user_upgrade.transaction.amount)
|
||||
assert_equal("eur", @user_upgrade.transaction.currency)
|
||||
end
|
||||
|
||||
should "choose the right price in EUR for a gold to platinum upgrade" do
|
||||
@user_upgrade = create(:self_gold_to_platinum_upgrade)
|
||||
@checkout = @user_upgrade.create_checkout!(country: "DE")
|
||||
|
||||
assert_equal(0.8 * UserUpgrade.gold_to_platinum_price, @user_upgrade.payment_intent.amount)
|
||||
assert_equal("eur", @user_upgrade.payment_intent.currency)
|
||||
assert_equal(0.8 * UserUpgrade.gold_to_platinum_price, @user_upgrade.transaction.amount)
|
||||
assert_equal("eur", @user_upgrade.transaction.currency)
|
||||
end
|
||||
end
|
||||
|
||||
@@ -119,49 +119,49 @@ class UserUpgradeTest < ActiveSupport::TestCase
|
||||
@checkout = @user_upgrade.create_checkout!(country: "US")
|
||||
|
||||
assert_equal(["card"], @checkout.payment_method_types)
|
||||
assert_equal("usd", @user_upgrade.payment_intent.currency)
|
||||
assert_equal("usd", @user_upgrade.transaction.currency)
|
||||
end
|
||||
|
||||
should "choose the right payment methods for AT" do
|
||||
@checkout = @user_upgrade.create_checkout!(country: "AT")
|
||||
|
||||
assert_equal(["card", "eps"], @checkout.payment_method_types)
|
||||
assert_equal("eur", @user_upgrade.payment_intent.currency)
|
||||
assert_equal("eur", @user_upgrade.transaction.currency)
|
||||
end
|
||||
|
||||
should "choose the right payment methods for BE" do
|
||||
@checkout = @user_upgrade.create_checkout!(country: "BE")
|
||||
|
||||
assert_equal(["card", "bancontact"], @checkout.payment_method_types)
|
||||
assert_equal("eur", @user_upgrade.payment_intent.currency)
|
||||
assert_equal("eur", @user_upgrade.transaction.currency)
|
||||
end
|
||||
|
||||
should "choose the right payment methods for DE" do
|
||||
@checkout = @user_upgrade.create_checkout!(country: "DE")
|
||||
|
||||
assert_equal(["card", "giropay"], @checkout.payment_method_types)
|
||||
assert_equal("eur", @user_upgrade.payment_intent.currency)
|
||||
assert_equal("eur", @user_upgrade.transaction.currency)
|
||||
end
|
||||
|
||||
should "choose the right payment methods for NL" do
|
||||
@checkout = @user_upgrade.create_checkout!(country: "NL")
|
||||
|
||||
assert_equal(["card", "ideal"], @checkout.payment_method_types)
|
||||
assert_equal("eur", @user_upgrade.payment_intent.currency)
|
||||
assert_equal("eur", @user_upgrade.transaction.currency)
|
||||
end
|
||||
|
||||
should "choose the right payment methods for PL" do
|
||||
@checkout = @user_upgrade.create_checkout!(country: "PL")
|
||||
|
||||
assert_equal(["card", "p24"], @checkout.payment_method_types)
|
||||
assert_equal("eur", @user_upgrade.payment_intent.currency)
|
||||
assert_equal("eur", @user_upgrade.transaction.currency)
|
||||
end
|
||||
|
||||
should "choose the right payment methods for an unsupported country" do
|
||||
@checkout = @user_upgrade.create_checkout!(country: "MX")
|
||||
|
||||
assert_equal(["card"], @checkout.payment_method_types)
|
||||
assert_equal("usd", @user_upgrade.payment_intent.currency)
|
||||
assert_equal("usd", @user_upgrade.transaction.currency)
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
Reference in New Issue
Block a user