spree_razorpay_checkout 0.1.0 → 0.1.1

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA256:
3
- metadata.gz: a4d76121b7886a9c83e9b776340876ba0e95576521dbe2e7cf3b29702a6be65a
4
- data.tar.gz: 8c4cc0283ec0333f52a296ed0c71c81c5d95f8efb2bd38c54a66613abe0d3869
3
+ metadata.gz: e72dc88db8b53ff22661766a04c41d6a4b481d6183638de96d767983682f4c74
4
+ data.tar.gz: 033dd1d5f35534ccdbecaaaa5655e21a7065563684592be0c19cd94625742f77
5
5
  SHA512:
6
- metadata.gz: b2566259b590a119fa88ff3b58e50ebe875b8bfa66b0fadcf2bde579ced610e3e249d77567211295f3d5f1a13e152e5bd4b52a4c75abe0cef306be0ced7df11b
7
- data.tar.gz: d407724116949e1c8c78d534269ab1fc8c9022b489eca2a554ca640951e1a2bdc318db49b529fd85bcad849ef1f55070e5c5a62fcc8ef376257ccf7592c22607
6
+ metadata.gz: 5e69954e3d286c3e7e6cfcacfa3866c7aca7f61eaf5097861ac4fe3d437b1da154b28e1bf1122dab2914fec8a69344111c4abb3e970048de221e7a6f38d68ad9
7
+ data.tar.gz: 9206adcb915d630577fbd26b8d69a6a4465202d6dfc20c6e5e604dcd9218d200017ba087b8986179f3c87027c09665388504124babea8d6622a1a50a111a47ff
data/README.md CHANGED
@@ -4,68 +4,56 @@
4
4
  style="height: 100px; border-radius: 12em;"
5
5
  />
6
6
 
7
+ This Razorpay Checkout Reprository is mentioned in official [Spree Commerce Docs](https://spreecommerce.org/docs/integrations/payments/razorpay).
8
+
7
9
  ## Razorpay Extension for Spree Commerce v5
8
10
  RazorPay is the only payments solution in India that allows businesses to accept, process and disburse payments with its product suite.
9
11
 
10
- ## Installation (Traditional)
12
+ ## Installation
11
13
 
12
- 1. Add this to your Gemfile with this line:
14
+ 1. Add Gem:
13
15
 
14
16
  ```ruby
15
- gem 'spree_razorpay_checkout'
17
+ bundle add spree_razorpay_checkout
16
18
  ```
17
19
 
18
- 2. Install the Gem using Bundle Install:
19
-
20
- ```ruby
21
- bundle install
22
- ```
23
-
24
- 3. Copy & Run Migrations:
20
+ 2. Install the Gem:
25
21
 
26
22
  ```ruby
27
23
  bundle exec rails g spree_razorpay_checkout:install
28
24
  ```
29
25
 
30
- 4. Compile Assests for Proper Images & JS loading:
31
-
26
+ 3. Compile Assets (Optional):
32
27
  ```ruby
33
- RAILS_ENV=development bin/rails assets:precompile
28
+ bin/rails assets:precompile
34
29
  ```
35
30
 
36
- 5. Start Server:
37
-
38
- ```ruby
31
+ 4. Start Server:
32
+ ```ruby
39
33
  foreman start -f Procfile.dev
40
34
  ```
41
35
 
42
36
  ## Installation (For Docker)
43
37
 
44
- 1. Add this your Gemfile with this line:
38
+ 1. Add Gem using docker compose:
45
39
 
46
40
  ```ruby
47
- gem 'spree_razorpay_checkout'
41
+ docker compose run web bundle add spree_razorpay_checkout
48
42
  ```
49
43
 
50
44
  2. Install the Gem using Docker's Bundle Install:
51
45
 
52
- ```ruby
53
- docker compose run web bundle install
54
- ```
55
-
56
- 3. Run Install Generator to Copy Migrations in Docker way:
57
-
58
46
  ```ruby
59
47
  docker compose run web bundle exec rails g spree_razorpay_checkout:install
60
48
  ```
61
49
 
62
- 4. Compile Assests for Razorpay logo & assets (Recommended):
50
+ 3. Compile Assests for Razorpay logo & assets (Recommended):
63
51
 
64
52
  ```ruby
65
53
  docker compose run web bundle exec rails assets:precompile
66
54
  ```
67
55
 
68
- 5. Re-Start Server (Recommended):
56
+ 4. Re-Start Server (Recommended):
69
57
 
70
58
  ```ruby
71
59
  docker compose down
@@ -114,6 +102,60 @@ Thankyou for supporting this plugin. if you find any issues related to plugin yo
114
102
 
115
103
  ---
116
104
 
105
+ ## Uninstallation
106
+
107
+ 1. Uninstall Gem:
108
+
109
+ ```ruby
110
+ gem uninstall spree_razorpay_checkout
111
+ gem uninstall razorpay
112
+ ```
113
+
114
+ 2. Update Gemfile:
115
+
116
+ ```ruby
117
+ bundle install
118
+ ```
119
+
120
+ 3. Remove Migrations:
121
+
122
+ ```ruby
123
+ rm db/migrate/*_create_spree_razorpay_checkouts.spree_razorpay_checkout.rb
124
+ ```
125
+
126
+ 4. Open Rails Console:
127
+
128
+ ```ruby
129
+ rails c
130
+
131
+ 5. Drop Razorpay Database:
132
+
133
+ ```ruby
134
+ ActiveRecord::Base.connection.drop_table(:spree_razorpay_checkouts)
135
+ ``````
136
+ 6. Check Razorpay (You should see "nill"):
137
+
138
+ ```ruby
139
+ defined?(Razorpay) # => nil
140
+ ```
141
+ Note: If you see "nill" then Razorpay is completely uninstalled from Spree commerce, either if you see "constant" try "gem uninstall razorpay" & "bundle update".
142
+
143
+
144
+ ### Roadmap
145
+
146
+ | **Features** | **Status** |
147
+ |-----------------------------------------|------------|
148
+ | Auto-Capture Order in Razorpay | Working |
149
+ | Test Button for Testmode | Working |
150
+ | Razorpay order creation using [OrdersAPI](https://razorpay.com/docs/payments/orders/apis/) | Working |
151
+ | Fetching Total Amount in Modal | Working |
152
+ | Order Creation after Payment | Working |
153
+ | Razorpay Logo in Order's Page | Working |
154
+ | Admin "Capture" order button | Working |
155
+ | Admin side "Refund" order | Pending |
156
+ | E-Mail after successful order | Pending |
157
+ | Disable Pay Button for Accidental Order | Partial |
158
+
117
159
  ### Contributing
118
160
 
119
161
  Contributions are welcome! Please open issues or submit pull requests to help improve this plugin for the Spree + Razorpay community in India.
@@ -0,0 +1 @@
1
+ <svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 38 24" width="38" height="24" aria-labelledby="pi-payu"><path opacity=".07" d="M35 0H3C1.3 0 0 1.3 0 3v18c0 1.7 1.4 3 3 3h32c1.7 0 3-1.3 3-3V3c0-1.7-1.4-3-3-3"/><path fill="#fff" d="M35 1c1.1 0 2 .9 2 2v18c0 1.1-.9 2-2 2H3c-1.1 0-2-.9-2-2V3c0-1.1.9-2 2-2z"/><style>.st0{opacity:7.000000e-02;enable-background:new}.st1{fill:#fff}</style><path class="st0" d="M35 0H3C1.3 0 0 1.3 0 3v18c0 1.7 1.4 3 3 3h32c1.7 0 3-1.3 3-3V3c0-1.7-1.4-3-3-3"/><path class="st1" d="M35 1c1.1 0 2 .9 2 2v18c0 1.1-.9 2-2 2H3c-1.1 0-2-.9-2-2V3c0-1.1.9-2 2-2z"/><path class="st0" d="M35 0H3C1.3 0 0 1.3 0 3v18c0 1.7 1.4 3 3 3h32c1.7 0 3-1.3 3-3V3c0-1.7-1.4-3-3-3"/><path class="st1" d="M35 1c1.1 0 2 .9 2 2v18c0 1.1-.9 2-2 2H3c-1.1 0-2-.9-2-2V3c0-1.1.9-2 2-2z"/><g transform="matrix(.85 0 0 .85 4.5 1.8)"><path id="Fill-17" style="fill-rule:evenodd;clip-rule:evenodd;fill:#3395ff" d="m16.2 9-.9 3 4.8-3-3 11.6h3.1l4.6-17.2z"/><path id="Fill-19" d="m11.1 15.7-1.4 4.9h6.5l2.6-10z" style="fill-rule:evenodd;clip-rule:evenodd;fill:#072654"/></g></svg>
@@ -3,15 +3,20 @@ module Spree
3
3
  extend ActiveSupport::Concern
4
4
 
5
5
  def update_razorpay_checkout
6
- razorpay_checkout = Spree::RazorpayCheckout.find_or_initialize_by(order_id: order.try(:id))
7
- razorpay_checkout.update_columns(update_razorpay_response)
6
+ return unless order
7
+ razorpay_checkout = Spree::RazorpayCheckout.find_or_initialize_by(order_id: order.id)
8
+ razorpay_checkout.assign_attributes(update_razorpay_response)
9
+ razorpay_checkout.save! if razorpay_checkout.changed?
10
+ rescue => e
11
+ Rails.logger.error("Failed to update RazorpayCheckout: #{e.message}")
8
12
  end
9
13
 
10
14
  def update_razorpay_response
11
15
  {
12
16
  razorpay_payment_id: params['razorpay_payment_id'],
13
17
  razorpay_order_id: params['razorpay_order_id'],
14
- razorpay_signature: params['razorpay_signature']
18
+ razorpay_signature: params['razorpay_signature'],
19
+ status: (defined?(razorpay_payment) && razorpay_payment.try(:status)) || params['status']
15
20
  }
16
21
  end
17
22
  end
@@ -4,67 +4,72 @@ module Spree
4
4
 
5
5
  include Spree::RazorPay
6
6
 
7
- #Step 1: Create Razorpay Order before payment
7
+ # Step 1: Create Razorpay Order (Kept from the "New" version for security)
8
8
  def create_order
9
- razorpay_order_id = ::Razorpay::RpOrder::Api.new.create(params[:order_id])
9
+ order = Spree::Order.find_by(id: params[:order_id])
10
+ return render json: { success: false, error: 'Order not found' }, status: :not_found unless order
11
+
12
+ razorpay_order_id, amount = ::Razorpay::RpOrder::Api.new.create(order.id)
10
13
 
11
14
  if razorpay_order_id.present?
12
- render json: { success: true, razorpay_order_id: razorpay_order_id }
15
+ render json: { success: true, razorpay_order_id: razorpay_order_id, amount: amount }
13
16
  else
14
17
  render json: { success: false, error: "Failed to create Razorpay order" }, status: :unprocessable_entity
15
18
  end
16
19
  end
17
20
 
18
- #Step 2: Razorpay callback after payment
21
+ # Step 2: Handle Response
19
22
  def razor_response
20
- if valid_signature? && razorpay_payment_id.present?
21
- begin
22
- gateway.verify_and_capture_razorpay_payment(order, razorpay_payment_id)
23
-
24
- #Update the record created during create_order
25
- checkout_record = Spree::RazorpayCheckout.find_by(
26
- order_id: order.id,
27
- razorpay_order_id: params[:razorpay_order_id]
28
- )
29
-
30
- if checkout_record
31
- checkout_record.update!(
32
- razorpay_payment_id: razorpay_payment_id,
33
- razorpay_signature: params[:razorpay_signature],
34
- status: razorpay_payment.status,
35
- payment_method: razorpay_payment.method,
36
- card_id: razorpay_payment.card_id,
37
- bank: razorpay_payment.bank,
38
- wallet: razorpay_payment.wallet,
39
- vpa: razorpay_payment.vpa,
40
- email: razorpay_payment.email,
41
- contact: razorpay_payment.contact
42
- )
43
- else
44
- Rails.logger.warn("RazorpayCheckout record not found for order #{order.id}")
45
- end
46
-
47
- # Add payment to Spree order
48
- order.razor_payment(razorpay_payment, payment_method, params[:razorpay_signature])
49
- order.next
50
-
51
- flash['order_completed'] = true if order.completed?
52
- redirect_to checkout_state_path_or_completion and return
53
- rescue StandardError => e
54
- Rails.logger.error("Razorpay Error: #{e.message}")
55
- flash[:error] = "Razorpay Error: #{e.message}"
56
- end
57
- else
58
- flash[:error] = 'Razorpay payment verification failed'
23
+ # 1. Find the Order
24
+ order = Spree::Order.find_by(number: params[:order_id] || params[:order_number])
25
+ unless order
26
+ flash[:error] = "Order not found."
27
+ return redirect_to checkout_state_path(:payment)
59
28
  end
60
29
 
61
- redirect_to checkout_state_path(order.state)
30
+ # 2. Verify Signature
31
+ unless valid_signature?
32
+ flash[:error] = "Payment signature verification failed."
33
+ return redirect_to checkout_state_path(order.state)
34
+ end
35
+
36
+ begin
37
+ # 3. Capture and Verify Payment on Razorpay
38
+ razorpay_payment = gateway.verify_and_capture_razorpay_payment(order, razorpay_payment_id)
39
+
40
+ # 4. Create Spree Payment Record
41
+ spree_payment = order.razor_payment(razorpay_payment, payment_method, params[:razorpay_signature])
42
+
43
+ # 5. FORCE COMPLETE THE PAYMENT
44
+ # This ensures the payment is marked 'completed' immediately
45
+ if spree_payment.respond_to?(:complete!)
46
+ spree_payment.complete!
47
+ end
48
+
49
+ # 6. Advance Order State
50
+ # Keep calling next! until the order is fully finalized
51
+ while !order.completed?
52
+ order.next!
53
+ end
54
+
55
+ # 7. Force update payment state to 'paid'
56
+ order.update(payment_state: 'paid') if order.respond_to?(:payment_state)
57
+
58
+ # 8. Redirect to the specific Token URL
59
+ #flash['order_completed'] = true
60
+ redirect_to completion_route
61
+
62
+ rescue StandardError => e
63
+ Rails.logger.error("Razorpay Error: #{e.message}\n#{e.backtrace.join("\n")}")
64
+ flash[:error] = "Payment Error: #{e.message}"
65
+ redirect_to checkout_state_path(order.state)
66
+ end
62
67
  end
63
68
 
64
69
  private
65
70
 
66
71
  def razorpay_payment_id
67
- params[:razorpay_payment_id]
72
+ params[:razorpay_payment_id] || params.dig(:payment_source, payment_method.id.to_s, :razorpay_payment_id)
68
73
  end
69
74
 
70
75
  def razorpay_payment
@@ -72,34 +77,44 @@ module Spree
72
77
  end
73
78
 
74
79
  def valid_signature?
80
+ p_id = payment_method.id.to_s
81
+ r_order_id = params[:razorpay_order_id] || params.dig(:payment_source, p_id, :razorpay_order_id)
82
+ r_pay_id = razorpay_payment_id
83
+ r_sig = params[:razorpay_signature] || params.dig(:payment_source, p_id, :razorpay_signature)
84
+
75
85
  Razorpay::Utility.verify_payment_signature(
76
- razorpay_order_id: params[:razorpay_order_id],
77
- razorpay_payment_id: params[:razorpay_payment_id],
78
- razorpay_signature: params[:razorpay_signature]
86
+ razorpay_order_id: r_order_id,
87
+ razorpay_payment_id: r_pay_id,
88
+ razorpay_signature: r_sig
79
89
  )
80
90
  rescue Razorpay::Error => e
81
91
  Rails.logger.error("Razorpay signature verification failed: #{e.message}")
82
92
  false
83
93
  end
84
94
 
85
- def order
86
- @order ||= Spree::Order.find_by(number: params[:order_id])
87
- end
88
-
89
95
  def payment_method
90
- @payment_method ||= Spree::PaymentMethod.find(params[:payment_method_id])
96
+ @payment_method ||= Spree::PaymentMethod.find_by(id: params[:payment_method_id]) || Spree::PaymentMethod.find_by(type: 'Spree::Gateway::RazorpayGateway')
91
97
  end
92
98
 
93
99
  def gateway
94
- @gateway ||= payment_method
100
+ payment_method
95
101
  end
96
102
 
97
- def checkout_state_path_or_completion
98
- order.completed? ? completion_route : checkout_state_path(order.state)
103
+ def order
104
+ @order ||= Spree::Order.find_by(number: params[:order_id] || params[:order_number])
99
105
  end
100
-
106
+
101
107
  def completion_route
102
- order_path(order)
108
+ # Retrieve the guest token (supports both old and new Spree versions)
109
+ token = order.respond_to?(:guest_token) ? order.guest_token : order.token
110
+
111
+ if token.present?
112
+ # Manually construct the URL: /checkout/TOKEN/complete
113
+ "/checkout/#{token}/complete"
114
+ else
115
+ # Fallback if no token exists (standard logged-in user path)
116
+ spree.order_path(order)
117
+ end
103
118
  end
104
119
  end
105
120
  end
@@ -10,7 +10,7 @@ module Spree
10
10
  preference :merchant_name, :string, default: 'Razorpay'
11
11
  preference :merchant_description, :text, default: 'Razorpay Payment Gateway'
12
12
  preference :merchant_address, :string, default: 'Razorpay, Bangalore, India'
13
- preference :theme_color, :string, default: '#F37254'
13
+ preference :theme_color, :string, default: '#2e5bff'
14
14
 
15
15
  def supports?(_source)
16
16
  true
@@ -20,8 +20,16 @@ module Spree
20
20
  false
21
21
  end
22
22
 
23
+ def name
24
+ 'Razorpay Secure (UPI, Wallets, Cards & Netbanking)'
25
+ end
26
+
27
+ def method_type
28
+ 'razorpay'
29
+ end
30
+
23
31
  def payment_source_class
24
- nil
32
+ 'razorpay'
25
33
  end
26
34
 
27
35
  def payment_icon_name
@@ -56,10 +64,6 @@ module Spree
56
64
  true
57
65
  end
58
66
 
59
- def method_type
60
- 'razorpay'
61
- end
62
-
63
67
  def request_type
64
68
  'DEFAULT'
65
69
  end
@@ -76,11 +80,12 @@ module Spree
76
80
  payment.state != 'void'
77
81
  end
78
82
 
83
+ # Not used directly (we use custom flow), but kept it for compatibility
79
84
  def purchase(_amount, _transaction_details, _gateway_options = {})
80
85
  ActiveMerchant::Billing::Response.new(true, 'Razorpay success')
81
86
  end
82
87
 
83
- def capture(*)
88
+ def capture(*args)
84
89
  simulated_successful_billing_response
85
90
  end
86
91
 
@@ -92,20 +97,37 @@ module Spree
92
97
  ActiveMerchant::Billing::Response.new(true, 'Refund successful')
93
98
  end
94
99
 
100
+ def cancel(payment, _options = {})
101
+ # If `payment` is a Spree::Payment, use its source
102
+ source = if payment.respond_to?(:source)
103
+ payment.source else payment end
104
+ payment.void! if payment.respond_to?(:void!)
105
+ if source.respond_to?(:razorpay_payment_id)
106
+ # Uncomment if you want to actually trigger refund
107
+ # Razorpay::Payment.fetch(source.razorpay_payment_id).refund
108
+ OpenStruct.new(success?: true, authorization: source.razorpay_payment_id)
109
+ else
110
+ # fallback for string/unknown source
111
+ OpenStruct.new(success?: true, authorization: nil)
112
+ end
113
+ rescue => e
114
+ Rails.logger.error("Razorpay cancel failed: #{e.message}")
115
+ OpenStruct.new(success?: false, message: e.message)
116
+ end
117
+
118
+ # Verify signature, fetch payment and capture if required. Returns Razorpay::Payment object.
95
119
  def verify_and_capture_razorpay_payment(order, razorpay_payment_id)
96
120
  Razorpay.setup(current_key_id, current_key_secret)
97
121
 
98
122
  begin
99
123
  payment = Razorpay::Payment.fetch(razorpay_payment_id)
100
-
101
- unless payment.status == 'authorized'
102
- raise Spree::Core::GatewayError, 'Payment not authorized'
124
+ # If payment is not captured and auto_capture set true, capture it
125
+ if payment.status == 'authorized'
126
+ amount = (order.total.to_f * 100).to_i
127
+ payment = payment.capture(amount: amount)
103
128
  end
104
129
 
105
- # Capture only if you're not using auto-capture (your setting says auto_capture = true)
106
- payment.capture(amount: (order.total * 100).to_i)
107
130
  payment
108
-
109
131
  rescue Razorpay::Error => e
110
132
  raise Spree::Core::GatewayError, "Razorpay error: #{e.message}"
111
133
  end
@@ -1,4 +1,25 @@
1
1
  module Spree
2
- class RazorpayCheckout < ActiveRecord::Base
2
+ class RazorpayCheckout < Spree::Base
3
+ self.table_name = 'spree_razorpay_checkouts'
4
+
5
+ belongs_to :order, class_name: 'Spree::Order', optional: true
6
+
7
+ # Appears in Spree Admin > Payments
8
+ def name
9
+ "Razorpay"
10
+ end
11
+
12
+ def method_type
13
+ "razorpay"
14
+ end
15
+
16
+ # Optional — to show the payment IDs in admin
17
+ def payment_id
18
+ self.razorpay_payment_id
19
+ end
20
+
21
+ def order_id
22
+ self.razorpay_order_id
23
+ end
3
24
  end
4
25
  end
@@ -5,26 +5,31 @@ module SpreeRazorpayCheckout
5
5
  (total.to_f * 100).to_i
6
6
  end
7
7
 
8
+ # Create a Spree::Payment and return it so controller can complete it
8
9
  def razor_payment(payment_object, payment_method, razorpay_signature)
9
- payments.create!(
10
- source: ::Spree::RazorpayCheckout.create!(
11
- order_id: id,
12
- razorpay_payment_id: payment_object.id,
13
- razorpay_order_id: payment_object.order_id,
14
- razorpay_signature: razorpay_signature,
15
- status: payment_object.status,
16
- payment_method: payment_object.method,
17
- card_id: payment_object.card_id,
18
- bank: payment_object.bank,
19
- wallet: payment_object.wallet,
20
- vpa: payment_object.vpa,
21
- email: payment_object.email,
22
- contact: payment_object.contact
23
- ),
10
+ source = ::Spree::RazorpayCheckout.create!(
11
+ order_id: id,
12
+ razorpay_payment_id: payment_object.id,
13
+ razorpay_order_id: payment_object.order_id,
14
+ razorpay_signature: razorpay_signature,
15
+ status: payment_object.status,
16
+ payment_method: payment_object.method,
17
+ card_id: payment_object.card_id,
18
+ bank: payment_object.bank,
19
+ wallet: payment_object.wallet,
20
+ vpa: payment_object.vpa,
21
+ email: payment_object.email,
22
+ contact: payment_object.contact
23
+ )
24
+
25
+ payment = payments.create!(
26
+ source: source,
24
27
  payment_method: payment_method,
25
28
  amount: total,
26
- response_code: payment_object.status
29
+ response_code: payment_object.id
27
30
  )
31
+
32
+ payment
28
33
  end
29
34
 
30
35
  ::Spree::Order.prepend SpreeRazorpayCheckout::Spree::OrderDecorator
@@ -5,18 +5,19 @@ module Razorpay
5
5
 
6
6
  def create(order_id)
7
7
  @order = Spree::Order.find_by(id: order_id)
8
+ raise "Order not found" unless order
8
9
 
9
10
  razorpay_order = Razorpay::Order.create(order_create_params)
10
11
 
11
12
  if razorpay_order.try(:id).present?
12
13
  log_order_in_db(razorpay_order.id)
13
- return razorpay_order.id
14
+ return [razorpay_order.id, order.inr_amt_in_paise]
14
15
  end
15
16
 
16
- ''
17
+ ['', 0]
17
18
  rescue StandardError => e
18
19
  Rails.logger.error("Razorpay Order create failed: #{e.message}")
19
- ''
20
+ ['', 0]
20
21
  end
21
22
 
22
23
  private
@@ -24,7 +25,7 @@ module Razorpay
24
25
  def order_create_params
25
26
  {
26
27
  amount: order.inr_amt_in_paise,
27
- currency: order.currency,
28
+ currency: order.currency || 'INR',
28
29
  receipt: order.number
29
30
  }
30
31
  end
@@ -1,5 +1,5 @@
1
1
  <p class="mb-1">
2
- Razorpay is the only payments solution in India that allows businesses to accept, process and disburse payments with its product suite.
2
+ Razorpay India powers your store with simple, secure, and scalable payments across UPI, cards, wallets, and more.
3
3
  </p>
4
4
 
5
5
  <div class="d-flex align-items-center">
@@ -7,9 +7,5 @@
7
7
  <%= payment_method_icon_tag 'master', class: 'm-1' %>
8
8
  <%= payment_method_icon_tag 'google_pay', class: 'm-1' %>
9
9
  <%= payment_method_icon_tag 'amazon', class: 'm-1' %>
10
- <%= payment_method_icon_tag 'mobikwik', class: 'm-1' %>
11
10
  <%= payment_method_icon_tag 'upi', class: 'm-1' %>
12
- <%= payment_method_icon_tag 'rupay', class: 'm-1' %>
13
- <%= payment_method_icon_tag 'paytm', class: 'm-1' %>
14
- <%= payment_method_icon_tag 'payzapp', class: 'm-1' %>
15
- </div>
11
+ </div>
@@ -47,7 +47,9 @@ function setupRazorpay() {
47
47
  }
48
48
  });
49
49
 
50
- razorpayBtn.addEventListener("click", function () {
50
+ razorpayBtn.addEventListener("click", function (e) {
51
+ e.preventDefault(); // Prevent any default button behavior
52
+
51
53
  fetch("/razorpay/create_order", {
52
54
  method: "POST",
53
55
  headers: {
@@ -72,10 +74,19 @@ function setupRazorpay() {
72
74
  description: "<%= payment_method.preferred_merchant_description.presence || 'Order Payment' %>",
73
75
  handler: function (response) {
74
76
  razorpayCompleted = true;
77
+
78
+ // 1. Populate Hidden Fields
75
79
  document.getElementById("razorpay_payment_id").value = response.razorpay_payment_id;
76
80
  document.getElementById("razorpay_order_id").value = response.razorpay_order_id;
77
81
  document.getElementById("razorpay_signature").value = response.razorpay_signature;
78
- form.requestSubmit();
82
+
83
+ // 2. Change Form Action to your custom controller
84
+ form.action = "/razorpay/response?order_id=<%= @order.number %>&payment_method_id=" + razorpayMethodId;
85
+ form.method = "POST";
86
+
87
+ // 3. Submit the Form (Standard Browser Submit)
88
+ // To ensures the redirect works correctly
89
+ form.submit();
79
90
  },
80
91
  modal: {
81
92
  ondismiss: function () {
@@ -88,15 +99,15 @@ function setupRazorpay() {
88
99
  contact: "<%= @order.bill_address&.phone %>"
89
100
  },
90
101
  theme: {
91
- color: "<%= payment_method.preferred_theme_color.presence || '#3399cc' %>"
102
+ color: "<%= payment_method.preferred_theme_color.presence || '#2e5bff' %>"
92
103
  }
93
104
  };
94
- delete options.session;
95
105
 
96
106
  const rzp = new Razorpay(options);
97
107
  rzp.open();
98
108
  })
99
- .catch(() => {
109
+ .catch((err) => {
110
+ console.error(err);
100
111
  alert("Error creating Razorpay order. Please refresh and try again.");
101
112
  });
102
113
  });
@@ -1,4 +1,5 @@
1
1
  # Logo Location
2
2
  Rails.application.config.assets.precompile += %w[
3
3
  payment_icons/razorpay.svg
4
- ]
4
+ payment_icons/razorpaycheckout.svg
5
+ ]
data/config/routes.rb CHANGED
@@ -1,5 +1,6 @@
1
1
  Spree::Core::Engine.add_routes do
2
- # Add your extension routes here
2
+
3
3
  post '/razorpay/create_order', to: 'razorpay#create_order'
4
- post '/razorpay/response', to: 'razorpay#razor_response', as: :razorpay_response
4
+ #Accept both POST and PATCH
5
+ match '/razorpay/response', to: 'razorpay#razor_response', via: [:post, :patch], as: :razorpay_response
5
6
  end
@@ -1,9 +1,9 @@
1
1
  class CreateSpreeRazorpayCheckouts < ActiveRecord::Migration[6.1]
2
2
  def change
3
3
  create_table :spree_razorpay_checkouts do |t|
4
- t.string :order_id
5
- t.string :razorpay_payment_id
4
+ t.references :order, null: true, foreign_key: { to_table: :spree_orders }
6
5
  t.string :razorpay_order_id
6
+ t.string :razorpay_payment_id
7
7
  t.string :razorpay_signature
8
8
  t.string :status
9
9
  t.string :payment_method
@@ -16,5 +16,8 @@ class CreateSpreeRazorpayCheckouts < ActiveRecord::Migration[6.1]
16
16
 
17
17
  t.timestamps
18
18
  end
19
+
20
+ add_index :spree_razorpay_checkouts, :razorpay_order_id
21
+ add_index :spree_razorpay_checkouts, :razorpay_payment_id
19
22
  end
20
- end
23
+ end
@@ -1,5 +1,5 @@
1
1
  module SpreeRazorpayCheckout
2
- VERSION = '0.1.0'.freeze
2
+ VERSION = '0.1.1'.freeze
3
3
 
4
4
  module_function
5
5
 
metadata CHANGED
@@ -1,14 +1,14 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: spree_razorpay_checkout
3
3
  version: !ruby/object:Gem::Version
4
- version: 0.1.0
4
+ version: 0.1.1
5
5
  platform: ruby
6
6
  authors:
7
7
  - Umesh Ravani
8
8
  autorequire:
9
9
  bindir: bin
10
10
  cert_chain: []
11
- date: 2025-08-07 00:00:00.000000000 Z
11
+ date: 2025-11-20 00:00:00.000000000 Z
12
12
  dependencies:
13
13
  - !ruby/object:Gem::Dependency
14
14
  name: razorpay
@@ -28,14 +28,14 @@ dependencies:
28
28
  name: spree
29
29
  requirement: !ruby/object:Gem::Requirement
30
30
  requirements:
31
- - - "~>"
31
+ - - ">="
32
32
  - !ruby/object:Gem::Version
33
33
  version: '5.0'
34
34
  type: :runtime
35
35
  prerelease: false
36
36
  version_requirements: !ruby/object:Gem::Requirement
37
37
  requirements:
38
- - - "~>"
38
+ - - ">="
39
39
  - !ruby/object:Gem::Version
40
40
  version: '5.0'
41
41
  - !ruby/object:Gem::Dependency
@@ -103,6 +103,7 @@ extra_rdoc_files: []
103
103
  files:
104
104
  - README.md
105
105
  - app/assets/images/payment_icons/razorpay.svg
106
+ - app/assets/images/payment_icons/razorpaycheckout.svg
106
107
  - app/assets/javascripts/spree/frontend/process_razorpay.js
107
108
  - app/assets/javascripts/spree/frontend/spree_razorpay.js
108
109
  - app/controllers/concerns/spree/razor_pay.rb