Skip to content
This repository has been archived by the owner on Mar 27, 2023. It is now read-only.

Commit

Permalink
Updates the transaction model's state events to accurately reflect GC's
Browse files Browse the repository at this point in the history
webhooks.
  • Loading branch information
osahyoun committed May 18, 2016
1 parent 1b0a885 commit 9d16830
Show file tree
Hide file tree
Showing 10 changed files with 152 additions and 35 deletions.
4 changes: 1 addition & 3 deletions app/models/payment/go_cardless/subscription.rb
@@ -1,5 +1,4 @@
class Payment::GoCardless::Subscription < ActiveRecord::Base

class Charge
attr_reader :subscription, :event

Expand Down Expand Up @@ -33,11 +32,10 @@ class Payment::GoCardless::Subscription < ActiveRecord::Base

belongs_to :page
belongs_to :action
belongs_to :customer, class_name: 'Payment::GoCardless::Customer'
belongs_to :customer, class_name: 'Payment::GoCardless::Customer'
belongs_to :payment_method, class_name: 'Payment::GoCardless::PaymentMethod'
has_many :transactions, class_name: 'Payment::GoCardless::Transaction', foreign_key: :subscription_id


ACTION_FROM_STATE = {
created: :create,
cancelled: :cancel,
Expand Down
26 changes: 14 additions & 12 deletions app/models/payment/go_cardless/transaction.rb
Expand Up @@ -6,32 +6,36 @@ class Payment::GoCardless::Transaction < ActiveRecord::Base
belongs_to :payment_method, class_name: 'Payment::GoCardless::PaymentMethod'
belongs_to :subscription, class_name: 'Payment::GoCardless::Subscription'

validates :go_cardless_id, presence: true, allow_blank: false

ACTION_FROM_STATE = {
submitted: :submit,
confirmed: :confirm,
cancelled: :cancel,
failed: :fail,
charged_back: :charge_back,
paid_out: :pay_out
}

aasm do
state :pending_customer_approval, initial: true
state :pending_submission
state :created, initial: true
state :submitted
state :confirmed
state :paid_out
state :cancelled
state :customer_approval_denied
state :failed
state :charged_back

event :run_submit do
transitions from: [:pending_customer_approval, :pending_submission], to: :submitted
transitions from: :created, to: :submitted
end

event :run_confirm do
transitions from: [:pending_customer_approval, :pending_submission, :submitted], to: :confirmed
transitions from: [:created, :submitted], to: :confirmed
end

event :run_payout do
transitions from: [:pending_customer_approval, :pending_submission, :submitted, :confirmed], to: :paid_out
end

event :run_deny do
transitions to: :customer_approval_denied
transitions from: [:created, :submitted, :confirmed], to: :paid_out
end

event :run_cancel do
Expand All @@ -46,6 +50,4 @@ class Payment::GoCardless::Transaction < ActiveRecord::Base
transitions to: :charged_back
end
end

validates :go_cardless_id, presence: true, allow_blank: false
end
12 changes: 12 additions & 0 deletions lib/payment_processor/go_cardless/webhook_handler/payment.rb
Expand Up @@ -3,6 +3,18 @@ module GoCardless
module WebhookHandler
class Payment
include Processable

def action
@action ||= ::Payment::GoCardless::Transaction::ACTION_FROM_STATE[ @event['action'].to_sym ]
end

def record
@record ||= ::Payment::GoCardless::Transaction.find_by(go_cardless_id: payment_id)
end

def payment_id
@event['links']['payment']
end
end
end
end
Expand Down
@@ -1,3 +1,5 @@
require_relative 'payment'

module PaymentProcessor::GoCardless
module WebhookHandler
class ProcessEvents
Expand Down
Expand Up @@ -7,7 +7,7 @@ def initialize(event)
end

def process
if record.send("may_run_#{action}?")
if action and record.send("may_run_#{action}?")
record.send("run_#{action}!", @event)
end
end
Expand Down
Expand Up @@ -19,4 +19,3 @@ def subscription_id
end
end
end

6 changes: 5 additions & 1 deletion spec/factories/actions.rb
Expand Up @@ -5,6 +5,10 @@
link "MyString"
created_user false
subscribed_user false
end

trait :with_member_and_page do
member
page
end
end
end
122 changes: 114 additions & 8 deletions spec/lib/payment_processor/go_cardless/webhook_handler_spec.rb
Expand Up @@ -2,6 +2,8 @@

module PaymentProcessor::GoCardless
describe WebhookHandler do
let(:page) { create(:page) }

let(:events) do
[
{
Expand Down Expand Up @@ -100,7 +102,7 @@ module PaymentProcessor::GoCardless
WebhookHandler::ProcessEvents.process(events)
end

it 'sets state to appropriate event' do
it 'sets updates state on payment method record' do
expect(payment_method.reload.active?).to be(true)
end

Expand Down Expand Up @@ -141,9 +143,10 @@ module PaymentProcessor::GoCardless
end

describe "Subscriptions" do
let(:page) { create(:page) }
let(:pending_first) { true }
let(:action) { create(:action, page: page, form_data: { recurrence_number: 1 }) }
let!(:payment_method) { create(:payment_go_cardless_payment_method, go_cardless_id: 'MD0000PTV0CA1K' ) }
let!(:subscription) { create(:payment_go_cardless_subscription, go_cardless_id: 'index_ID_123', payment_method: payment_method, page: page) }
let!(:subscription) { create(:payment_go_cardless_subscription, go_cardless_id: 'index_ID_123', payment_method: payment_method, action: action, page: page) }

let(:events) do
[
Expand Down Expand Up @@ -212,6 +215,7 @@ module PaymentProcessor::GoCardless

describe 'general behaviour' do
before do
allow( ChampaignQueue ).to receive(:push)
WebhookHandler::ProcessEvents.process(positive_events)
end

Expand Down Expand Up @@ -254,7 +258,7 @@ module PaymentProcessor::GoCardless
end

describe 'with created payment event' do
let(:events) do
let(:first_events) do
[
{"id"=>"EVTESTJG8GPP7G",
"created_at"=>"2016-04-14T11:32:20.343Z",
Expand All @@ -280,19 +284,121 @@ module PaymentProcessor::GoCardless
]
end


let(:second_events) do
[
{"id"=>"XEVTESTJG8GPP7G",
"created_at"=>"2016-04-14T11:32:20.343Z",
"resource_type"=>"subscriptions",
"action"=>"customer_approval_granted",
"links"=>{"payment"=>"payment_ID_1234", "subscription"=>"index_ID_123"},
"details"=>
{"origin"=>"customer",
"cause"=>"customer_approval_granted",
"description"=>"The customer granted approval for this subscription"},
"metadata"=>{}},

{"id"=>"XEVTEST4VAXTFZD",
"created_at"=>"2016-04-14T11:43:00.208Z",
"resource_type"=>"subscriptions",
"action"=>"payment_created",
"links"=>{"payment"=>"payment_ID_1234", "subscription"=>"index_ID_123"},
"details"=>
{"origin"=>"gocardless",
"cause"=>"payment_created",
"description"=>"Payment created by a subscription."},
"metadata"=>{}}
]
end


before do
WebhookHandler::ProcessEvents.process(events)
allow( ChampaignQueue ).to receive(:push)
WebhookHandler::ProcessEvents.process(first_events)
end

it 'state stays as active' do
expect(subscription.reload.active?).to be(true)
end

context 'first created payment' do
it "doesn't post to queue" do
expect( ChampaignQueue ).not_to have_received(:push)
end
end

context 'second created payment' do
before do
WebhookHandler::ProcessEvents.process(second_events)
end

it "posts to queue" do
expect( ChampaignQueue ).to have_received(:push)
.with({type: "subscription-payment", recurring_id: "index_ID_123" })
end
end
end
end

describe "Payments" do; end
describe "Payments" do
context 'from subscription' do
let(:events) do
[
{"id"=>"EV0005XF2PEPV3",
"created_at"=>"2016-05-05T12:42:55.781Z",
"resource_type"=>"mandates",
"action"=>"created",
"links"=>{"mandate"=>"MD0000QSNJZ13N"},
"details"=>
{"origin"=>"api",
"cause"=>"mandate_created",
"description"=>"Mandate created via the API."},
"metadata"=>{}},
{"id"=>"EV0005XF2QKCY7",
"created_at"=>"2016-05-05T12:42:56.480Z",
"resource_type"=>"subscriptions",
"action"=>"created",
"links"=>{"subscription"=>"SB00002TX3VY2P"},
"details"=>
{"origin"=>"api",
"cause"=>"subscription_created",
"description"=>"Subscription created via the API."},
"metadata"=>{}},
{"id"=>"EV0005XF2RY3Z2",
"created_at"=>"2016-05-05T12:42:56.733Z",
"resource_type"=>"payments",
"action"=>"created",
"links"=>{"subscription"=>"SB00002TX3VY2P", "payment"=>"PM00019VHGW3W1"},
"details"=>
{"origin"=>"gocardless",
"cause"=>"payment_created",
"description"=>"Payment created by a subscription"},
"metadata"=>{}},
{"id"=>"EV0005XF2S9FZA",
"created_at"=>"2016-05-05T12:42:56.765Z",
"resource_type"=>"subscriptions",
"action"=>"payment_created",
"links"=>{"payment"=>"PM00019VHGW3W1", "subscription"=>"SB00002TX3VY2P"},
"details"=>
{"origin"=>"gocardless",
"cause"=>"payment_created",
"description"=>"Payment created by a subscription."},
"metadata"=>{}}
]
end

let!(:action) { create(:action, :with_member_and_page) }
let!(:payment_method) { create(:payment_go_cardless_payment_method, go_cardless_id: 'MD0000QSNJZ13N' ) }
let!(:subscription) { create(:payment_go_cardless_subscription, go_cardless_id: 'SB00002TX3VY2P', page: page, action: action ) }

before do
WebhookHandler::ProcessEvents.process(events)
end

describe "Payouts" do; end
it 'creates a transaction record' do
expect(Payment::GoCardless::Transaction.count).to eq(1)
end
end
end
end
end

8 changes: 1 addition & 7 deletions spec/models/payment/go_cardless/transaction_spec.rb
Expand Up @@ -71,7 +71,7 @@
subject { create :payment_go_cardless_transaction }

it 'has initial state' do
expect(subject.pending_customer_approval?).to be(true)
expect(subject.created?).to be(true)
end

context 'submission allowed' do
Expand Down Expand Up @@ -152,12 +152,6 @@
}.to change{ subject.reload.cancelled? }.from(false).to(true)
end

it 'can be denied' do
expect{
subject.run_deny!
}.to change{ subject.reload.customer_approval_denied? }.from(false).to(true)
end

it 'can be charged back' do
expect{
subject.run_charge_back!
Expand Down
4 changes: 2 additions & 2 deletions spec/requests/api/go_cardless/webhooks_spec.rb
Expand Up @@ -55,9 +55,9 @@
})
end

it 'is confirmed' do
it 'is created' do
expect(
subject.pending_customer_approval?
subject.created?
).to be(true)
end
end
Expand Down

0 comments on commit 9d16830

Please sign in to comment.