Class: SpreeRazorpayCheckout::HandleWebhookEventJob

Inherits:
ActiveJob::Base
  • Object
show all
Defined in:
app/jobs/spree_razorpay_checkout/handle_webhook_event_job.rb

Instance Method Summary collapse

Instance Method Details

#perform(event) ⇒ Object



5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
# File 'app/jobs/spree_razorpay_checkout/handle_webhook_event_job.rb', line 5

def perform(event)
  payload = event['payload']
  payment_entity = payload.dig('payment', 'entity') || payload.dig('order', 'entity')
  
  # Razorpay might send the ID in slightly different places depending on the event
  razorpay_order_id = payment_entity['order_id'] || payload.dig('order', 'entity', 'id')
  razorpay_payment_id = payment_entity['id'] 
  
  checkout_record = Spree::RazorpayCheckout.find_by(razorpay_order_id: razorpay_order_id)
  return unless checkout_record
  
  order = checkout_record.order
  return if order.completed? || order.canceled?
  
  gateway = Spree::Gateway::RazorpayGateway.active.first
  return unless gateway
  
  order.with_lock do
    # 1. Capture the abandoned payment via API
    begin
      rzp_payment = ::Razorpay::Payment.fetch(razorpay_payment_id)
      if rzp_payment.status == 'authorized'
        amount_in_cents = (order.total_minus_store_credits.to_f * 100).to_i
        rzp_payment.capture({ amount: amount_in_cents })
      end
    rescue StandardError => e
      Rails.logger.error("Webhook Razorpay Capture Failed: #{e.message}")
      return
    end
  
    checkout_record.update!(
      razorpay_payment_id: razorpay_payment_id,
      status: 'captured'
    )
  
    # 2. Create the Spree::Payment record natively
    payment = order.payments.find_or_create_by!(
      response_code: razorpay_payment_id,
      payment_method_id: gateway.id
    ) do |p|
      p.amount = order.total
      p.source = checkout_record
      p.state = 'checkout'
    end
  
    # 3. Mark the payment as completed
    payment.process! if payment.checkout?
    payment.complete! if payment.pending? || payment.processing?
  
    # Tell Spree to recalculate the payment state
    order.updater.update_payment_state
    
    # Loop through the checkout steps (Payment -> Confirm -> Complete)
    until order.completed? || order.state == 'complete'
      order.next!
    end
    
  end
end