From 1f93622b88d14f5e908aad4f14d4f8cd18b63a3a Mon Sep 17 00:00:00 2001 From: Mausam Pun Date: Thu, 12 Sep 2024 17:05:02 +0545 Subject: [PATCH 1/7] WIP : Express order checkout --- .../storefront/express_checkout_controller.rb | 99 +++++++++++++++++++ config/routes.rb | 1 + 2 files changed, 100 insertions(+) create mode 100644 app/controllers/spree/api/v2/storefront/express_checkout_controller.rb diff --git a/app/controllers/spree/api/v2/storefront/express_checkout_controller.rb b/app/controllers/spree/api/v2/storefront/express_checkout_controller.rb new file mode 100644 index 0000000..e96322b --- /dev/null +++ b/app/controllers/spree/api/v2/storefront/express_checkout_controller.rb @@ -0,0 +1,99 @@ +# frozen_string_literal: true + +module Spree + module Api + module V2 + module Storefront + class ExpressCheckoutController < ::Spree::Api::V2::BaseController + # before_action :require_spree_current_user + + def create + @order = if params[:order_id].present? + Spree::Order.find(params[:order_id]) + else + Spree::Order.find_by(number: params[:order_number]) + end + + @order.next + + # Attach the address of the stock location to the order + attach_address + + # Attach the shipping method to the order + attach_shipping_method + + # Process the payment + payment_method = Spree::PaymentMethod.find_by(type: 'Spree::Gateway::StripeExpressCheckout') + + payment = @order.payments.build( + payment_method_id: payment_method.id, + response_code: params[:payment_intent_id], + amount: @order.total, + source: create_source(payment_method), + state: 'checkout' + ) + + begin + if payment.save + if payment.state == 'checkout' + payment.process! + end + + @order.next + + render json: { message: 'Order and Payment created successfully' }, status: :ok + else + render json: { error: 'Payment could not be completed' }, status: :unprocessable_entity + end + rescue StateMachines::InvalidTransition => e + render json: { error: e.message }, status: :unprocessable_entity + rescue StandardError => e + render json: { error: e.message }, status: :unprocessable_entity + end + end + + private + + def attach_address + vendor_sl = @order.line_items.first.vendor.stock_locations.first + + sl_address = Spree::Address.find_by(label: vendor_sl.name) + + if sl_address.present? + @order.update(billing_address: sl_address) + else + address = Spree::Address.create!(first_name: 'Anonymous', last_name: 'User', address1: vendor_sl.address1, + city: vendor_sl.city, zipcode: vendor_sl.zipcode, phone: '1234567890', + state: vendor_sl.state, label: vendor_sl.name, country: vendor_sl.country) + @order.update(billing_address: address) + end + + @order.update(use_billing: true) + @order.next + end + + def attach_shipping_method + shipping_rates = @order.shipments.first.shipping_rates + targeted_rate = shipping_rates.find_by(cost: 0) + + shipping_rates.update_all(selected: false) + targeted_rate.update!(selected: true) + + @order.shipments.first.update_amounts + @order.update_totals + @order.persist_totals + @order.next + end + + def create_source(payment_method) + Spree::StripeExpressCheckoutSource.create!( + payment_intent_id: params[:payment_intent_id], + payment_intent_secret: params[:payment_intent_secret], + payment_method_id: payment_method.id + ) + end + end + end + end + end +end diff --git a/config/routes.rb b/config/routes.rb index 8087ff3..edc1a40 100644 --- a/config/routes.rb +++ b/config/routes.rb @@ -4,6 +4,7 @@ namespace :v2 do namespace :storefront do resources :stripe_payment, only: :create + resources :express_checkout, only: :create end end end From 71581182e64f296d77140980fd8aec3e1cad7850 Mon Sep 17 00:00:00 2001 From: Mausam Pun Date: Fri, 13 Sep 2024 13:38:53 +0545 Subject: [PATCH 2/7] add default address --- .../v2/storefront/express_checkout_controller.rb | 16 ++++++++-------- 1 file changed, 8 insertions(+), 8 deletions(-) diff --git a/app/controllers/spree/api/v2/storefront/express_checkout_controller.rb b/app/controllers/spree/api/v2/storefront/express_checkout_controller.rb index e96322b..503db49 100644 --- a/app/controllers/spree/api/v2/storefront/express_checkout_controller.rb +++ b/app/controllers/spree/api/v2/storefront/express_checkout_controller.rb @@ -55,16 +55,16 @@ def create private def attach_address - vendor_sl = @order.line_items.first.vendor.stock_locations.first + default_address = Spree::Address.find_by(label: 'default') - sl_address = Spree::Address.find_by(label: vendor_sl.name) - - if sl_address.present? - @order.update(billing_address: sl_address) + if default_address.present? + @order.update(billing_address: default_address) else - address = Spree::Address.create!(first_name: 'Anonymous', last_name: 'User', address1: vendor_sl.address1, - city: vendor_sl.city, zipcode: vendor_sl.zipcode, phone: '1234567890', - state: vendor_sl.state, label: vendor_sl.name, country: vendor_sl.country) + country = Spree::Country.find_by(iso: 'US') + state = country.states.first + address = Spree::Address.create!(first_name: 'Anonymous', last_name: 'User', address1: 'Kathmandu', + city: 'Kathmandu', zipcode: '12345', phone: '1234567890', + state: , label: 'default', country: ) @order.update(billing_address: address) end From e0fdef7a03d1c7ba94af075d3e8cf981ff8ebcef Mon Sep 17 00:00:00 2001 From: Mausam Pun Date: Fri, 13 Sep 2024 17:27:37 +0545 Subject: [PATCH 3/7] add email to order --- .../spree/api/v2/storefront/express_checkout_controller.rb | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/app/controllers/spree/api/v2/storefront/express_checkout_controller.rb b/app/controllers/spree/api/v2/storefront/express_checkout_controller.rb index 503db49..f5afb4b 100644 --- a/app/controllers/spree/api/v2/storefront/express_checkout_controller.rb +++ b/app/controllers/spree/api/v2/storefront/express_checkout_controller.rb @@ -39,7 +39,7 @@ def create payment.process! end - @order.next + @order.update!(email: 'no_email@email.com', state: 'complete') render json: { message: 'Order and Payment created successfully' }, status: :ok else @@ -68,7 +68,7 @@ def attach_address @order.update(billing_address: address) end - @order.update(use_billing: true) + @order.update!(use_billing: true) @order.next end From e78d20e4755ba17ad52bd37cb3e7d8cc4ff648a8 Mon Sep 17 00:00:00 2001 From: Mausam Pun Date: Fri, 13 Sep 2024 23:01:14 +0545 Subject: [PATCH 4/7] update the completed at in order --- .../spree/api/v2/storefront/express_checkout_controller.rb | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/app/controllers/spree/api/v2/storefront/express_checkout_controller.rb b/app/controllers/spree/api/v2/storefront/express_checkout_controller.rb index f5afb4b..195adcb 100644 --- a/app/controllers/spree/api/v2/storefront/express_checkout_controller.rb +++ b/app/controllers/spree/api/v2/storefront/express_checkout_controller.rb @@ -39,7 +39,7 @@ def create payment.process! end - @order.update!(email: 'no_email@email.com', state: 'complete') + @order.update!(email: 'no_email@email.com', state: 'complete', completed_at: Time.zone.now) render json: { message: 'Order and Payment created successfully' }, status: :ok else From 0d368d704890ced2cdfd8bceb8df8176487998b2 Mon Sep 17 00:00:00 2001 From: Mausam Pun Date: Mon, 16 Sep 2024 14:37:27 +0545 Subject: [PATCH 5/7] update the email and phone and billing address as per the billing details of the transaction in the stripe --- .../storefront/express_checkout_controller.rb | 59 +++++++++++++++---- .../spree/gateway/stripe_express_checkout.rb | 1 + spree_stripe_express_checkout.gemspec | 3 +- 3 files changed, 50 insertions(+), 13 deletions(-) diff --git a/app/controllers/spree/api/v2/storefront/express_checkout_controller.rb b/app/controllers/spree/api/v2/storefront/express_checkout_controller.rb index 195adcb..434fa9b 100644 --- a/app/controllers/spree/api/v2/storefront/express_checkout_controller.rb +++ b/app/controllers/spree/api/v2/storefront/express_checkout_controller.rb @@ -5,7 +5,7 @@ module Api module V2 module Storefront class ExpressCheckoutController < ::Spree::Api::V2::BaseController - # before_action :require_spree_current_user + before_action :payment_intent_details, only: :create def create @order = if params[:order_id].present? @@ -39,7 +39,10 @@ def create payment.process! end - @order.update!(email: 'no_email@email.com', state: 'complete', completed_at: Time.zone.now) + @order.update!(email: @customer_email || 'no_email@email.com', state: 'complete', completed_at: Time.zone.now) + + order_updater = Spree::OrderUpdater.new(@order) + order_updater.update render json: { message: 'Order and Payment created successfully' }, status: :ok else @@ -55,17 +58,21 @@ def create private def attach_address - default_address = Spree::Address.find_by(label: 'default') - - if default_address.present? - @order.update(billing_address: default_address) + if @billing_address.present? + @order.update(billing_address: @billing_address) else - country = Spree::Country.find_by(iso: 'US') - state = country.states.first - address = Spree::Address.create!(first_name: 'Anonymous', last_name: 'User', address1: 'Kathmandu', - city: 'Kathmandu', zipcode: '12345', phone: '1234567890', - state: , label: 'default', country: ) - @order.update(billing_address: address) + default_address = Spree::Address.find_by(label: 'default') + + if default_address.present? + @order.update(billing_address: default_address) + else + country = Spree::Country.find_by(iso: 'US') + state = country.states.first + address = Spree::Address.create!(first_name: 'Anonymous', last_name: 'User', address1: 'Kathmandu', + city: 'Kathmandu', zipcode: '12345', phone: '1234567890', + state: , label: 'default', country: ) + @order.update(billing_address: address) + end end @order.update!(use_billing: true) @@ -92,6 +99,34 @@ def create_source(payment_method) payment_method_id: payment_method.id ) end + + def payment_intent_details + payment_intent = Stripe::PaymentIntent.retrieve( + params[:payment_intent_id], + { api_key: Spree::Gateway::StripeExpressCheckout.first.preferred_api_secret_key } + ) + + payment_method = Stripe::PaymentMethod.retrieve( + payment_intent.payment_method, + { api_key: Spree::Gateway::StripeExpressCheckout.first.preferred_api_secret_key } + ) + + billing_details = payment_method.billing_details + + # build address from the stripe's billing details + first_name = billing_details.name.split(' ').first + last_name = billing_details.name.split(' ').last + address1 = billing_details.address.line1 + address2 = billing_details.address.line2 + city = billing_details.address.city + zipcode = billing_details.address.postal_code + phone = billing_details.phone || '1234567890' + country = Spree::Country.find_by(iso: billing_details.address.country) + state = country.states.find_by(abbr: billing_details.address.state) + + @billing_address = Spree::Address.create!(first_name:, last_name:, address1:, address2:, city:, zipcode:, phone:, state:, country:) + @customer_email = billing_details.email + end end end end diff --git a/app/models/spree/gateway/stripe_express_checkout.rb b/app/models/spree/gateway/stripe_express_checkout.rb index 6c80fb9..b13f904 100644 --- a/app/models/spree/gateway/stripe_express_checkout.rb +++ b/app/models/spree/gateway/stripe_express_checkout.rb @@ -2,6 +2,7 @@ module Spree class Gateway::StripeExpressCheckout < Gateway + preference :api_secret_key, :string def auto_capture? true diff --git a/spree_stripe_express_checkout.gemspec b/spree_stripe_express_checkout.gemspec index f58e116..a6009ff 100644 --- a/spree_stripe_express_checkout.gemspec +++ b/spree_stripe_express_checkout.gemspec @@ -22,7 +22,8 @@ Gem::Specification.new do |s| s.add_dependency 'spree', '>= 4.5.0' s.add_dependency 'spree_extension' - s.add_dependency 'spree_gateway' + s.add_dependency 'spree_gateway', '~> 3.11.0' + s.add_dependency 'stripe', '~> 12.6.0' s.add_development_dependency 'spree_dev_tools' end From f70df92b72a066737665d51bf8cad078f7e2599c Mon Sep 17 00:00:00 2001 From: Mausam Pun Date: Mon, 16 Sep 2024 14:53:27 +0545 Subject: [PATCH 6/7] update the initializer to require stripe --- config/initializers/stripe.rb | 1 + 1 file changed, 1 insertion(+) create mode 100644 config/initializers/stripe.rb diff --git a/config/initializers/stripe.rb b/config/initializers/stripe.rb new file mode 100644 index 0000000..c372a7e --- /dev/null +++ b/config/initializers/stripe.rb @@ -0,0 +1 @@ +require 'stripe' \ No newline at end of file From 79679934b40c51d4c1d1d056ac5a51b1cfcc3c08 Mon Sep 17 00:00:00 2001 From: Mausam Pun Date: Mon, 16 Sep 2024 22:00:57 +0545 Subject: [PATCH 7/7] add the dummy view file to rescure broken payment page in spree frontend --- .../spree/checkout/payment/_stripe_express_checkout.html.erb | 0 1 file changed, 0 insertions(+), 0 deletions(-) create mode 100644 app/views/spree/checkout/payment/_stripe_express_checkout.html.erb diff --git a/app/views/spree/checkout/payment/_stripe_express_checkout.html.erb b/app/views/spree/checkout/payment/_stripe_express_checkout.html.erb new file mode 100644 index 0000000..e69de29