Skip to content

Commit

Permalink
close #238 follow order state machine
Browse files Browse the repository at this point in the history
  • Loading branch information
theachoem committed Jan 16, 2025
1 parent 1242852 commit eda08f6
Show file tree
Hide file tree
Showing 9 changed files with 29 additions and 195 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -17,6 +17,8 @@ def request_update_payment
render_serialized_payload { serialize_resource(order) }
else
payment = find_payment(order, params[:payment_number])
return render_error_payload('Payment is void (refunded or canceled)') if payment.void?

context = payment.request_update

if context.success? && context.error_message.blank?
Expand Down
2 changes: 1 addition & 1 deletion app/models/spree/gateway/payway_v2.rb
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
module Spree
class Gateway::PaywayV2 < PaymentMethod
class Gateway::PaywayV2 < ::Spree::PaymentMethod
# preference :endpoint, :string
# preference :return_url, :string
# preference :continue_success_url, :string
Expand Down
46 changes: 2 additions & 44 deletions app/models/vpago/order_decorator.rb
Original file line number Diff line number Diff line change
Expand Up @@ -10,6 +10,7 @@ def self.prepended(base)
through: :line_items

base.state_machine.before_transition from: :cart, do: :ensure_valid_vendor_payment_methods
base.state_machine.before_transition to: :complete, do: :generate_line_items_total_metadata
end

def ensure_valid_vendor_payment_methods
Expand All @@ -25,30 +26,6 @@ def line_items_from_same_vendor?
line_items.joins(:variant).pluck('spree_variants.vendor_id').uniq.size == 1
end

# Make sure the order confirmation is delivered when the order has been paid for.
def finalize!
# lock all adjustments (coupon promotions, etc.)
all_adjustments.each(&:close)

# update payment and shipment(s) states, and save
updater.update_payment_state

shipments.each do |shipment|
shipment.update!(self)
shipment.finalize! if paid? || authorized?
end

updater.update_shipment_state
save!
updater.run_hooks

touch :completed_at

deliver_order_confirmation_email if !confirmation_delivered? && (paid? || authorized?)

consider_risk
end

def required_payway_payout?
line_items.any?(&:required_payway_payout?) || shipments.any?(&:required_payway_payout?)
end
Expand Down Expand Up @@ -90,29 +67,10 @@ def generate_line_items_total_metadata
line_items.each(&:update_total_metadata)
end

def send_confirmation_email!
return unless !confirmation_delivered? && (paid? || authorized?)

deliver_order_confirmation_email
end

def successful_payment
paid? || payments.any? { |p| p.after_pay_method? && p.authorized? }
end

alias paid_or_authorized? successful_payment

def authorized?
payments.last.authorized?
end

def order_adjustment_total
adjustments.eligible.sum(:amount)
end
end
end

if Spree::Order.included_modules.exclude?(Vpago::OrderDecorator)
Spree::Order.register_update_hook(:generate_line_items_total_metadata)
Spree::Order.prepend(Vpago::OrderDecorator)
end
Spree::Order.prepend(Vpago::OrderDecorator) if Spree::Order.included_modules.exclude?(Vpago::OrderDecorator)
48 changes: 0 additions & 48 deletions app/models/vpago/payment/vpago_payment_processing_decorator.rb

This file was deleted.

39 changes: 0 additions & 39 deletions app/models/vpago/payment_decorator.rb
Original file line number Diff line number Diff line change
Expand Up @@ -3,16 +3,6 @@ module PaymentDecorator
def self.prepended(base)
base.has_many :payouts, class_name: 'Spree::Payout', inverse_of: :payment
base.after_create -> { Vpago::PayoutsGenerator.new(self).call }, if: :should_generate_payouts?
base.after_update :capture_pre_auth, if: :state_changed_to_complete?
base.after_update :cancel_pre_auth, if: :state_changed_to_failed?
end

def state_changed_to_complete?
saved_change_to_state? && state == 'completed'
end

def state_changed_to_failed?
saved_change_to_state? && state == 'failed'
end

def should_generate_payouts?
Expand All @@ -23,41 +13,12 @@ def support_payout?
payment_method.support_payout?
end

# On the first call, everything works. The order is transitioned to complete and one Spree::Payment,
# which redirect the payment. But, after making the same call again,
# for instance because the payment wasn't completed or failed,
# another Spree::Payment is created but without a payment_url. So, if a consumer,
# for whatever reason, failed to complete the first payment, it would not be possible try again.
# This also meant that any consecutive Spree::Payment would not have a payment_url. The consumer is stuck

def build_source
return unless new_record?

return unless source_attributes.present? && source.blank? && payment_method.try(:payment_source_class)

self.source = payment_method.payment_source_class.new(source_attributes)
source.payment_method_id = payment_method.id
source.user_id = order.user_id if order

# Spree will not process payments if order is completed.
# We should call process! for completed orders to create a the gateway payment.
process! if order.completed?
end

def request_update
updater = payment_method.payment_request_updater.new(self, { ignore_on_failed: true })
updater.call
updater
end

def authorized?
if source.is_a? Spree::VpagoPaymentSource
pending?
else
false
end
end

def payment_url
return unless payment_method.type_payway_v2?

Expand Down
40 changes: 14 additions & 26 deletions lib/vpago/payment_status_marker.rb
Original file line number Diff line number Diff line change
Expand Up @@ -47,47 +47,35 @@ def update_payment_and_order
else
transition_to_failed!
end

order_updater
end

def transition_to_paid!
complete_payment!
complete_order!
confirm_payouts!
end

def transition_to_failed!
@payment.failure! unless @payment.failed?
@payment.order.update(state: 'payment')

notify_failed_payment
def complete_payment!
@payment.complete!
end

def order_updater
@payment.order.update_with_updater!
end
def complete_order!
context = Spree::Checkout::Complete.new.call(order: @payment.order)

def complete_payment!
return if @payment.completed?

# not follow state machine rule when it manual
if @options[:updated_by_user_id].present?
ApplicationRecord.transaction do
@payment.state_changes.create!(previous_state: @payment.state, next_state: 'completed', name: 'payment')
@payment.update(state: 'completed')
end
if context.success?
@payment.capture_pre_auth
confirm_payouts!
else
@payment.complete!
@error_message = context.error.value.full_messages.join(', ')
@payment.cancel_pre_auth
@payment.void!
end
end

def complete_order!
return if @payment.order.completed?
def transition_to_failed!
@payment.cancel_pre_auth
@payment.void!

order = @payment.order
order.finalize!
order.update(state: 'complete', completed_at: Time.zone.now)
notify_failed_payment
end

def payout_confirmed?
Expand Down
22 changes: 6 additions & 16 deletions lib/vpago/payway_v2/payment_request_updater.rb
Original file line number Diff line number Diff line change
Expand Up @@ -4,22 +4,11 @@ class PaymentRequestUpdater < ::Vpago::PaymentRequestUpdater
def call
return if @payment.order.paid?

if items_eligible?
process_payment_status
else
mark_items_as_ineligible
end
process_payment_status
end

private

def mark_items_as_ineligible
@error_message = 'Items are not eligible due to insufficient stock'
marker_options = @options.merge(status: false, description: @error_message)
marker = ::Vpago::PaymentStatusMarker.new(@payment, marker_options)
marker.call
end

def process_payment_status
checker = check_payway_status

Expand All @@ -38,9 +27,14 @@ def mark_payment_as_success(checker)
payway_v2_response: checker.json_response,
payout_total: checker.payout_total
}

marker_options = @options.merge(checker_result)
marker = ::Vpago::PaymentStatusMarker.new(@payment, marker_options)
marker.call

return unless marker.error_message&.present?

@error_message = marker.error_message
end

def mark_payment_as_failed(error_message)
Expand All @@ -56,10 +50,6 @@ def check_payway_status
trans_status.call
trans_status
end

def items_eligible?
@payment&.order&.line_items&.all?(&:sufficient_stock?) == true
end
end
end
end
4 changes: 4 additions & 0 deletions spec/lib/vpago/payment_status_marker_spec.rb
Original file line number Diff line number Diff line change
Expand Up @@ -11,6 +11,10 @@
before do
allow(checker).to receive(:check_transaction_url).and_return('https://checkout-sandbox.payway.com.kh/api/payment-gateway/v1/payments/check-transaction')
VCR.use_cassette('payway_v2_check_transaction_status_0') { checker.call }

# skip validation
allow(payment.order).to receive(:ensure_line_items_present).and_return(true)
allow(payment.order).to receive(:delivery_required?).and_return(false)
end

describe '#call' do
Expand Down
21 changes: 0 additions & 21 deletions spec/lib/vpago/payway_v2/payment_request_updater_spec.rb

This file was deleted.

0 comments on commit eda08f6

Please sign in to comment.