Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Feature/express checkout : Order express checkout feature #2

Open
wants to merge 7 commits into
base: feature/stripe_express_payment
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
134 changes: 134 additions & 0 deletions app/controllers/spree/api/v2/storefront/express_checkout_controller.rb
Original file line number Diff line number Diff line change
@@ -0,0 +1,134 @@
# frozen_string_literal: true

module Spree
module Api
module V2
module Storefront
class ExpressCheckoutController < ::Spree::Api::V2::BaseController
before_action :payment_intent_details, only: :create

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.update!(email: @customer_email || '[email protected]', 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
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
if @billing_address.present?
@order.update(billing_address: @billing_address)
else
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)
@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

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
end
end
1 change: 1 addition & 0 deletions app/models/spree/gateway/stripe_express_checkout.rb
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,7 @@

module Spree
class Gateway::StripeExpressCheckout < Gateway
preference :api_secret_key, :string

def auto_capture?
true
Expand Down
Empty file.
1 change: 1 addition & 0 deletions config/initializers/stripe.rb
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
require 'stripe'
1 change: 1 addition & 0 deletions config/routes.rb
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,7 @@
namespace :v2 do
namespace :storefront do
resources :stripe_payment, only: :create
resources :express_checkout, only: :create
end
end
end
Expand Down
3 changes: 2 additions & 1 deletion spree_stripe_express_checkout.gemspec
Original file line number Diff line number Diff line change
Expand Up @@ -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