Add Stripe Cancellation Webhook (#1682)

This commit is contained in:
Jess Lee 2019-02-13 15:56:19 -05:00 committed by Mac Siri
parent 7492783964
commit 49e3878239
6 changed files with 77 additions and 1 deletions

View file

@ -130,6 +130,7 @@ variable :SLACK_WEBHOOK_URL, :String, default: "Optional"
# Stripe for payment system
variable :STRIPE_PUBLISHABLE_KEY, :String, default: "Optional"
variable :STRIPE_SECRET_KEY, :String, default: "Optional"
variable :STRIPE_CANCELLATION_SECRET, :String, default: "Optional"
# For browser webpush notifications (webpush gem) (totally random base64 nums)
variable :VAPID_PUBLIC_KEY, :String, default: "dGhpcyBpcyBkZXYudG8gdGVzdCBkYXRh"

View file

@ -0,0 +1,39 @@
class StripeCancellationsController < ApplicationController
skip_before_action :verify_authenticity_token, only: :create
def create
verify_stripe_signature
unsubscribe_customer
end
def verify_stripe_signature
payload = request.body.read
sig_header = request.env["HTTP_STRIPE_SIGNATURE"]
begin
Stripe::Webhook.construct_event(
payload, sig_header, Rails.configuration.stripe[:stripe_cancellation_secret]
)
rescue JSON::ParserError
# Invalid payload
status 400
return
rescue Stripe::SignatureVerificationError
# Invalid signature
status 400
return
end
end
def unsubscribe_customer
event = Stripe::Event.retrieve(params[:id])
stripe_id = event.data.object.customer
customer = Stripe::Customer.retrieve(stripe_id)
monthly_dues = event.data.object.items.data[0].plan.amount
user = User.where(stripe_id_code: stripe_id).first
MembershipService.new(customer, user, monthly_dues).unsubscribe_customer
render body: nil, status: 200
rescue Stripe::APIConnectionError, Stripe::StripeError
render body: nil, status: 400
end
end

View file

@ -42,6 +42,8 @@ class MembershipService
end
def cancel_subscription
return true if customer.subscriptions.none?
subscription.delete
end

View file

@ -1,6 +1,7 @@
Rails.configuration.stripe = {
publishable_key: ApplicationConfig["STRIPE_PUBLISHABLE_KEY"],
secret_key: ApplicationConfig["STRIPE_SECRET_KEY"]
secret_key: ApplicationConfig["STRIPE_SECRET_KEY"],
stripe_cancellation_secret: ApplicationConfig["STRIPE_CANCELLATION_SECRET"]
}
Stripe.api_key = Rails.configuration.stripe[:secret_key]

View file

@ -112,6 +112,7 @@ Rails.application.routes.draw do
resources :tags, only: [:index]
resources :stripe_subscriptions, only: %i[create update destroy]
resources :stripe_active_cards, only: %i[create update destroy]
resources :stripe_cancellations, only: [:create]
resources :live_articles, only: [:index]
resources :github_repos, only: %i[create update]
resources :buffered_articles, only: [:index]

View file

@ -0,0 +1,32 @@
require "rails_helper"
RSpec.describe "StripeCancellations", type: :request do
let(:user) { create(:user) }
let(:stripe_helper) { StripeMock.create_test_helper }
before do
StripeMock.start
allow_any_instance_of(StripeCancellationsController).to receive(:verify_stripe_signature).and_return(true)
end
after { StripeMock.stop }
it "mocks a stripe cancellation webhook" do
customer = Stripe::Customer.create(
email: user.email,
source: stripe_helper.generate_card_token,
)
MembershipService.new(customer, user, 12).subscribe_customer
user.reload
expect(user.monthly_dues).not_to eq(0)
event = StripeMock.mock_webhook_event(
"customer.subscription.deleted",
customer: user.stripe_id_code, total_count: 1,
)
post "/stripe_cancellations", params: event.as_json
user.reload
expect(user.monthly_dues).to eq(0)
expect(response).to have_http_status(200)
end
end