diff --git a/app/controllers/spree/affirm_controller.rb b/app/controllers/spree/affirm_controller.rb index e7972ed..dc53500 100644 --- a/app/controllers/spree/affirm_controller.rb +++ b/app/controllers/spree/affirm_controller.rb @@ -20,11 +20,12 @@ def confirm if affirm_checkout.save! payment = order.payments.create!({ payment_method_id: affirm_params[:payment_method_id], - source: affirm_checkout + source: affirm_checkout, + amount: order.total }) - hook = SolidusAffirm::Config.callback_hook.new - hook.authorize!(payment) - redirect_to hook.after_authorize_url(order) + + order.next! unless order.state == "confirm" + redirect_to checkout_state_path(order.state) end end end diff --git a/lib/solidus_affirm/callback_hook/base.rb b/lib/solidus_affirm/callback_hook/base.rb index 6bd1836..28e50af 100644 --- a/lib/solidus_affirm/callback_hook/base.rb +++ b/lib/solidus_affirm/callback_hook/base.rb @@ -1,14 +1,6 @@ module SolidusAffirm module CallbackHook class Base - def authorize!(payment) - payment.process! - authorized_affirm = Affirm::Charge.find(payment.response_code) - payment.amount = authorized_affirm.amount / 100.0 - payment.save! - payment.order.next! if payment.order.payment? - end - def after_authorize_url(order) order_state_checkout_path(order) end diff --git a/spec/fixtures/vcr_casettes/callback_hook_authorize_success.yml b/spec/fixtures/vcr_casettes/callback_hook_authorize_success.yml deleted file mode 100644 index 48eaf2f..0000000 --- a/spec/fixtures/vcr_casettes/callback_hook_authorize_success.yml +++ /dev/null @@ -1,133 +0,0 @@ ---- -http_interactions: -- request: - method: post - uri: https://sandbox.affirm.com/api/v2/charges - body: - encoding: UTF-8 - string: '{"checkout_token":"26VJRAAYE0MB0V25"}' - headers: - Authorization: - - Basic WFBTUTNDQTdQTE43Q0pDSzp3OW14a1FVcnlLalRZRHFPZlN2WVRlVEdvTElVUktwVQ== - User-Agent: - - Faraday v0.9.2 - Content-Type: - - application/json - Accept-Encoding: - - gzip;q=1.0,deflate;q=0.6,identity;q=0.3 - Accept: - - "*/*" - response: - status: - code: 200 - message: OK - headers: - Cache-Control: - - no-cache - Content-Type: - - application/json - Date: - - Thu, 02 Feb 2017 20:17:09 GMT - Server: - - openresty - Strict-Transport-Security: - - max-age=86400; includeSubDomains - X-Affirm-Request-Id: - - fdf64c5e-17df-4f5c-cf4a-cf050383c329 - Content-Length: - - '2003' - Connection: - - keep-alive - body: - encoding: UTF-8 - string: '{"currency": "USD", "id": "N330-Z6D4", "under_dispute": false, "user_id": - "7058-0675-OWZI", "details": {"merchant": {"public_api_key": "XPSQ3CA7PLN7CJCK", - "user_cancel_url": "http://localhost:3000/affirm/cancel?order_id=12&payment_method_id=4", - "user_confirmation_url": "http://localhost:3000/affirm/confirm?order_id=12&payment_method_id=4", - "name": "[TEST] Stembolt"}, "tax_amount": 2024, "billing": {"name": {"full": - "Peter Berkenbosch", "last": "Berkenbosch", "first": "Peter"}, "address": - {"city": "New York", "country": "USA", "zipcode": "10001", "line1": "20 W - 29th St", "line2": "", "state": "NY"}}, "checkout_type": "merchant", "order_id": - "R368883147", "items": {"ROR-00011": {"sku": "ROR-00011", "item_url": "http://9cfb58bc.ngrok.io/products/ruby-on-rails-tote", - "display_name": "Ruby on Rails Tote", "unit_price": 1599, "qty": 25, "item_type": - "physical", "item_image_url": "/spree/products/21/large/ror_tote.jpeg?1485939804"}}, - "shipping": {"name": {"full": "Peter Berkenbosch", "last": "Berkenbosch", - "first": "Peter"}, "address": {"city": "New York", "country": "USA", "zipcode": - "10001", "line1": "20 W 29th St", "line2": "", "state": "NY"}}, "currency": - "USD", "meta": {"release": "true", "user_timezone": "America/New_York", "__affirm_tracking_uuid": - "35f9a44b-586a-46e9-bdd2-1cf76804f756"}, "shipping_amount": 500, "total": - 42499, "config": {}, "api_version": "v2", "merchant_external_reference": "R368883147"}, - "refundable": false, "charge_event_count": 0, "events": [{"created": "2017-02-02T20:17:07Z", - "currency": "USD", "amount": 42499, "type": "auth", "id": "Q9QRCO9ZKTBVGME4", - "transaction_id": "5Mx10EEnyZUsfqbH"}], "pending": true, "merchant_external_reference": - "R368883147", "status": "authorized", "order_id": "R368883147", "void": false, - "expires": "2017-03-04T20:17:08Z", "payable": 0, "merchant_id": "3VXA5KS4ZA7IZLA3", - "auth_hold": 42499, "refunded_amount": 0, "created": "2017-02-02T14:59:44Z", - "amount": 42499, "balance": 42499, "financing_program": "default_3_6_12"}' - http_version: - recorded_at: Thu, 02 Feb 2017 20:17:09 GMT -- request: - method: get - uri: https://sandbox.affirm.com/api/v2/charges/N330-Z6D4 - body: - encoding: US-ASCII - string: '' - headers: - Authorization: - - Basic WFBTUTNDQTdQTE43Q0pDSzp3OW14a1FVcnlLalRZRHFPZlN2WVRlVEdvTElVUktwVQ== - User-Agent: - - Faraday v0.9.2 - Accept-Encoding: - - gzip;q=1.0,deflate;q=0.6,identity;q=0.3 - Accept: - - "*/*" - response: - status: - code: 200 - message: OK - headers: - Cache-Control: - - no-cache - Content-Type: - - application/json - Date: - - Thu, 02 Feb 2017 20:17:09 GMT - Server: - - openresty - Strict-Transport-Security: - - max-age=86400; includeSubDomains - X-Affirm-Request-Id: - - 27322aac-f934-48e6-c8fd-268a36c6be96 - Content-Length: - - '2003' - Connection: - - keep-alive - body: - encoding: UTF-8 - string: '{"currency": "USD", "id": "N330-Z6D4", "under_dispute": false, "user_id": - "7058-0675-OWZI", "details": {"merchant": {"public_api_key": "XPSQ3CA7PLN7CJCK", - "user_cancel_url": "http://localhost:3000/affirm/cancel?order_id=12&payment_method_id=4", - "user_confirmation_url": "http://localhost:3000/affirm/confirm?order_id=12&payment_method_id=4", - "name": "[TEST] Stembolt"}, "tax_amount": 2024, "billing": {"name": {"full": - "Peter Berkenbosch", "last": "Berkenbosch", "first": "Peter"}, "address": - {"city": "New York", "country": "USA", "zipcode": "10001", "line1": "20 W - 29th St", "line2": "", "state": "NY"}}, "checkout_type": "merchant", "order_id": - "R368883147", "items": {"ROR-00011": {"sku": "ROR-00011", "item_url": "http://9cfb58bc.ngrok.io/products/ruby-on-rails-tote", - "display_name": "Ruby on Rails Tote", "unit_price": 1599, "qty": 25, "item_type": - "physical", "item_image_url": "/spree/products/21/large/ror_tote.jpeg?1485939804"}}, - "shipping": {"name": {"full": "Peter Berkenbosch", "last": "Berkenbosch", - "first": "Peter"}, "address": {"city": "New York", "country": "USA", "zipcode": - "10001", "line1": "20 W 29th St", "line2": "", "state": "NY"}}, "currency": - "USD", "meta": {"release": "true", "user_timezone": "America/New_York", "__affirm_tracking_uuid": - "35f9a44b-586a-46e9-bdd2-1cf76804f756"}, "shipping_amount": 500, "total": - 42499, "config": {}, "api_version": "v2", "merchant_external_reference": "R368883147"}, - "refundable": false, "charge_event_count": 0, "events": [{"created": "2017-02-02T20:17:07Z", - "currency": "USD", "amount": 42499, "type": "auth", "id": "Q9QRCO9ZKTBVGME4", - "transaction_id": "5Mx10EEnyZUsfqbH"}], "pending": true, "merchant_external_reference": - "R368883147", "status": "authorized", "order_id": "R368883147", "void": false, - "expires": "2017-03-04T20:17:08Z", "payable": 0, "merchant_id": "3VXA5KS4ZA7IZLA3", - "auth_hold": 42499, "refunded_amount": 0, "created": "2017-02-02T14:59:44Z", - "amount": 42499, "balance": 42499, "financing_program": "default_3_6_12"}' - http_version: - recorded_at: Thu, 02 Feb 2017 20:17:09 GMT -recorded_with: VCR 3.0.3 diff --git a/spec/lib/solidus_affirm/callback_hook/base_spec.rb b/spec/lib/solidus_affirm/callback_hook/base_spec.rb deleted file mode 100644 index 9bf6aa2..0000000 --- a/spec/lib/solidus_affirm/callback_hook/base_spec.rb +++ /dev/null @@ -1,61 +0,0 @@ -require 'spec_helper' - -RSpec.describe SolidusAffirm::CallbackHook::Base do - let(:order) { create(:order_with_totals, state: order_state) } - let(:order_state) { "payment" } - let(:payment_method) do - create( - :affirm_payment_gateway, - preferred_public_api_key: "XPSQ3CA7PLN7CJCK", - preferred_private_api_key: "w9mxkQUryKjTYDqOfSvYTeTGoLIURKpU", - preferred_test_mode: true - ) - end - let(:checkout_token) { "26VJRAAYE0MB0V25" } - let(:affirm_payment_source) { create(:affirm_checkout, token: checkout_token) } - let(:payment) do - create( - :payment, - response_code: nil, - order: order, - source: affirm_payment_source, - payment_method: payment_method - ) - end - - subject { SolidusAffirm::CallbackHook::Base.new } - - describe "authorize!" do - context "with a valid payment setup" do - it "will set the payment amount to the affirm amount" do - VCR.use_cassette 'callback_hook_authorize_success' do - expect { subject.authorize!(payment) }.to change{ payment.amount }.from(0).to(424.99) - end - end - - it "will set the affirm charge id as the response_code on the payment" do - VCR.use_cassette 'callback_hook_authorize_success' do - expect { subject.authorize!(payment) }.to change{ payment.response_code }.from(nil).to("N330-Z6D4") - end - end - - context "when order state is payment" do - it "moves the order to the next state" do - VCR.use_cassette 'callback_hook_authorize_success' do - expect { subject.authorize!(payment) }.to change{ order.state }.from("payment").to("confirm") - end - end - end - - context "when order state is not payment" do - let(:order_state) { "confirm" } - - it "doesn't raise a StateMachines::InvalidTransition exception" do - VCR.use_cassette 'callback_hook_authorize_success' do - expect { subject.authorize!(payment) }.not_to raise_error - end - end - end - end - end -end diff --git a/spec/requests/affirm_controller_spec.rb b/spec/requests/affirm_controller_spec.rb index b3b8406..5bc0687 100644 --- a/spec/requests/affirm_controller_spec.rb +++ b/spec/requests/affirm_controller_spec.rb @@ -69,14 +69,48 @@ end it "redirect to the confirm page" do - VCR.use_cassette 'callback_hook_authorize_success' do + post '/affirm/confirm', params: { + checkout_token: checkout_token, + payment_method_id: payment_method.id, + order_id: order.id, + use_route: :spree + } + expect(response).to redirect_to('/checkout/confirm') + end + + it "sets the payment total to the order total" do + post '/affirm/confirm', params: { + checkout_token: checkout_token, + payment_method_id: payment_method.id, + order_id: order.id, + use_route: :spree + } + expect(order.payments.last.amount).to eq(order.total) + end + + it "moves the order to its next state" do + expect { post '/affirm/confirm', params: { checkout_token: checkout_token, payment_method_id: payment_method.id, order_id: order.id, use_route: :spree } - expect(response).to redirect_to('/checkout/confirm') + }.to change { order.reload.state }.from("payment").to("confirm") + end + + context "the order is already in confirm state" do + let(:order) { create(:order_with_totals, state: "confirm") } + + it "moves the order to its next state" do + expect { + post '/affirm/confirm', params: { + checkout_token: checkout_token, + payment_method_id: payment_method.id, + order_id: order.id, + use_route: :spree + } + }.not_to change { order.reload.state } end end end