spree_razorpay_checkout 0.1.0 → 0.1.2

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: ce91b0aa0a699af98af1026d7d4ee7273d42f60264fb2a437d6148fd2a5b5aae
4
+ data.tar.gz: a124ad28f283318d9e11f9b5c106391ca27fa84a63fcac0059c53c72fc559a6d
5
5
  SHA512:
6
- metadata.gz: b2566259b590a119fa88ff3b58e50ebe875b8bfa66b0fadcf2bde579ced610e3e249d77567211295f3d5f1a13e152e5bd4b52a4c75abe0cef306be0ced7df11b
7
- data.tar.gz: d407724116949e1c8c78d534269ab1fc8c9022b489eca2a554ca640951e1a2bdc318db49b529fd85bcad849ef1f55070e5c5a62fcc8ef376257ccf7592c22607
6
+ metadata.gz: 5134c27e23b733c35611c670bcff05ca88fc706fe38372a5d45f40ff5e9fce4c0491420eb9c11971ef9f92aa5eb30d89c6c137a92fc3060b183a3c2698e57474
7
+ data.tar.gz: 6d18efe3da267fc36c039dcdf4975b91fe2bff36f88178726e2f108e01bd9c7a7e9d7d6a2910b237ca14ee043129843ed7d2d5c22adf06756c27c893def5102c
data/README.md CHANGED
@@ -4,105 +4,118 @@
4
4
  style="height: 100px; border-radius: 12em;"
5
5
  />
6
6
 
7
- ## Razorpay Extension for Spree Commerce v5
7
+ This Razorpay Checkout Reprository is mentioned in official [Spree Commerce Docs](https://spreecommerce.org/docs/integrations/payments/razorpay).
8
+
9
+ ## Razorpay Extension for Spree Commerce v5.2
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
72
60
  docker compose up -d
73
61
  ```
62
+ ## Upgrade to Latest Version:
63
+
64
+ 1. Change version in Spree's GemFile:
65
+
66
+ ```ruby
67
+ gem "spree_razorpay_checkout", "~> 0.1.1"
68
+ ```
69
+
70
+ 2. Run Bundle Updator to Patch updated files:
71
+
72
+ ```ruby
73
+ bundle update
74
+ ```
75
+
76
+ 3. Migrate Database Tables (Recommended):
77
+
78
+ ```ruby
79
+ rails db:migrate
80
+ ```
81
+
82
+ 4. Re-Start Server (Recommended):
83
+
84
+ ```ruby
85
+ bin/rails restart
86
+ ```
74
87
 
75
88
  ## Plugin Configuration
76
- 6. Get keys from Razorpay Dashboard [here](https://dashboard.razorpay.com/app/website-app-settings/api-keys).
89
+ 1. Get keys from Razorpay Dashboard [here](https://dashboard.razorpay.com/app/website-app-settings/api-keys).
77
90
 
78
91
  <img width="1186" height="735" alt="razorpay dashboard" src="https://github.com/user-attachments/assets/f390685d-550b-4814-8785-4fcc32746f15" />
79
92
 
80
- 7. Make Sure to include both Razorpay Live & Test Keys from Razorpay Dashboard:
93
+ 2. Make Sure to include both Razorpay Live & Test Keys from Razorpay Dashboard:
81
94
 
82
95
  <img width="1121" height="736" alt="Admin Dashboard - Razorpay Plugin" src="https://github.com/user-attachments/assets/f45efc43-b1db-4c79-9ad3-e3d672014676" />
83
96
 
84
97
 
85
- 8. Drag Razorpay to Top in Payment Methods to make it Default:
98
+ 3. Drag Razorpay to Top in Payment Methods to make it Default:
86
99
 
87
100
  <img width="1121" height="726" alt="Payment Methods - Razorpay Plugin" src="https://github.com/user-attachments/assets/8e39086d-85a6-42a2-b9fb-75299044e6d6" />
88
101
 
89
102
  ## Checkout View
90
103
 
91
- 9. Checkout Page:
104
+ 4. Checkout Page:
92
105
 
93
106
  <img width="507" height="639" alt="Razorpay Checkout Page" src="https://github.com/user-attachments/assets/ddca8536-fa94-4502-96fa-4cd2219f3c17" />
94
107
 
95
- 10. Razorpay Modal to Capture Payments:
108
+ 5. Razorpay Modal to Capture Payments:
96
109
 
97
110
  <img width="767" height="728" alt="Razorpay Modal" src="https://github.com/user-attachments/assets/da83105f-8510-44ae-ac7c-28960cf3a0b3" />
98
111
 
99
- 11. Order Page (Customer View):
112
+ 6. Order Page (Customer View):
100
113
 
101
- <img width="863" height="733" alt="Razorpay in Order Page Client" src="https://github.com/user-attachments/assets/51b80fe6-4007-4223-b978-8ce65a3238de" />
114
+ <img width="940" height="648" alt="Customers Orders Page Razorpay Spree" src="https://github.com/user-attachments/assets/3361da09-9f01-4101-8c3e-de5ae94394de" />
102
115
 
103
- 12. Order Page (Admin View):
116
+ 7. Order Page (Admin View):
104
117
 
105
- <img width="820" height="543" alt="Admin Orders Page Razorpay" src="https://github.com/user-attachments/assets/6d95d1ab-83a0-4ad8-9528-353cc7315630" />
118
+ <img width="800" height="562" alt="Admin Orders Page Razorpay Spree" src="https://github.com/user-attachments/assets/895b1081-e20a-47b8-845f-ce2eb621acd7" />
106
119
 
107
120
  Thankyou for supporting this plugin. if you find any issues related to plugin you are open to contribute and support which can help more Spree users in India.
108
121
 
@@ -114,6 +127,62 @@ Thankyou for supporting this plugin. if you find any issues related to plugin yo
114
127
 
115
128
  ---
116
129
 
130
+ ## Uninstallation
131
+
132
+ 1. Uninstall Gem:
133
+
134
+ ```ruby
135
+ gem uninstall spree_razorpay_checkout
136
+ gem uninstall razorpay
137
+ ```
138
+
139
+ 2. Update Gemfile:
140
+
141
+ ```ruby
142
+ bundle install
143
+ ```
144
+
145
+ 3. Remove Migrations:
146
+
147
+ ```ruby
148
+ rm db/migrate/*_create_spree_razorpay_checkouts.spree_razorpay_checkout.rb
149
+ ```
150
+
151
+ 4. Open Rails Console:
152
+
153
+ ```ruby
154
+ rails c
155
+
156
+ 5. Drop Razorpay Database:
157
+
158
+ ```ruby
159
+ ActiveRecord::Base.connection.drop_table(:spree_razorpay_checkouts)
160
+ ``````
161
+ 6. Check Razorpay (You should see "nill"):
162
+
163
+ ```ruby
164
+ defined?(Razorpay) # => nil
165
+ ```
166
+ Note: If you see "nill" then Razorpay is completely uninstalled from Spree commerce, either if you see "constant" try "gem uninstall razorpay" & "bundle update".
167
+
168
+
169
+ ### Roadmap
170
+
171
+ | **Features** | **Progress** | **Status** |
172
+ |-----------------------------------------------------------|--------------|------------|
173
+ | Auto-Capture Order in Razorpay | Working | ✅ |
174
+ | Test Button for Testmode | Working | ✅ |
175
+ | Razorpay order creation using [OrdersAPI](https://razorpay.com/docs/payments/orders/apis/) | Working | ✅ |
176
+ | Fetching Exact Total Amount in Modal | Working | ✅ |
177
+ | Order Creation after Successful Payment | Working | ✅ |
178
+ | Razorpay Logo in Admin/Order's Page | Working | ✅ |
179
+ | Admin side "Capture" order button | Working | ✅ |
180
+ | Admin side "Cancel" order button | Working | ✅ |
181
+ | Admin side "Refund" order button | Pending | ❌ |
182
+ | E-Mail after successful order | Working | ✅ |
183
+ | Disable Pay Button for Accidental Order | Working | ✅ |
184
+ | Razorpay Affordability Widget in Product Details Page | Upcoming | ⏳ |
185
+
117
186
  ### Contributing
118
187
 
119
188
  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,21 @@
1
+ <?xml version="1.0" encoding="UTF-8"?>
2
+ <svg width="1896px" height="401px" viewBox="0 0 1896 401" version="1.1" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink">
3
+ <!-- Generator: Sketch 46.2 (44496) - http://www.bohemiancoding.com/sketch -->
4
+ <title>Group</title>
5
+ <desc>Created with Sketch.</desc>
6
+ <defs></defs>
7
+ <g id="Page-1" stroke="none" stroke-width="1" fill="none" fill-rule="evenodd">
8
+ <g id="Group">
9
+ <path d="M451.9209,151.4937 C448.9309,162.6497 443.1359,170.8377 434.5349,176.0657 C425.9239,181.2927 413.8469,183.9117 398.2689,183.9117 L348.7769,183.9117 L366.1509,119.0807 L415.6429,119.0807 C431.2089,119.0807 441.8959,121.6947 447.7019,126.9217 C453.4969,132.1547 454.9109,140.3437 451.9209,151.4937 M503.1739,150.0967 C509.4679,126.6377 506.8589,108.6267 495.3509,96.0797 C483.8409,83.5327 463.6739,77.2627 434.8709,77.2627 L324.3909,77.2627 L257.8969,325.4027 L311.5719,325.4027 L338.3809,225.3777 L373.5809,225.3777 C381.4739,225.3777 387.6869,226.6577 392.2309,229.2137 C396.7849,231.7747 399.4509,236.3067 400.2739,242.8037 L409.8479,325.4027 L467.3589,325.4027 L458.0289,248.3847 C456.1279,231.1897 448.2589,221.0827 434.4309,218.0637 C452.0599,212.9577 466.8259,204.4677 478.7179,192.6167 C490.5989,180.7717 498.7579,166.6017 503.1739,150.0967" id="Fill-1" fill="#072654"></path>
10
+ <path d="M633.625,236.533 C629.14,253.258 622.231,266.042 612.901,274.868 C603.56,283.7 592.386,288.111 579.382,288.111 C566.122,288.111 557.128,283.758 552.387,275.042 C547.623,266.332 547.461,253.733 551.889,237.228 C556.305,220.735 563.352,207.841 573.053,198.539 C582.742,189.255 594.09,184.602 607.105,184.602 C620.11,184.602 628.919,189.082 633.485,198.024 C638.053,206.966 638.11,219.802 633.625,236.533 L633.625,236.533 Z M657.153,148.706 L650.431,173.8 C647.521,164.736 641.9,157.538 633.578,152.195 C625.245,146.852 614.918,144.174 602.608,144.174 C587.506,144.174 572.983,148.069 559.052,155.852 C545.12,163.64 532.938,174.617 522.519,188.786 C512.099,202.961 504.461,219.107 499.604,237.228 C494.748,255.356 493.774,271.328 496.695,285.149 C499.616,298.977 505.944,309.605 515.691,317.04 C525.428,324.481 537.969,328.19 553.303,328.19 C565.612,328.19 577.342,325.635 588.469,320.523 C599.595,315.418 609.041,308.325 616.818,299.266 L609.807,325.403 L661.731,325.403 L709.079,148.706 L657.153,148.706 Z" id="Fill-3" fill="#072654"></path>
11
+ <polygon id="Fill-5" fill="#072654" points="895.79 148.7061 744.882 148.7061 734.334 188.0911 822.155 188.0911 706.042 288.4581 696.132 325.4031 851.92 325.4031 862.478 286.0241 768.388 286.0241 886.263 184.2541"></polygon>
12
+ <path d="M1028.6514,236.1853 C1023.9804,253.6053 1017.0604,266.6273 1007.9044,275.2223 C998.7484,283.8163 987.6674,288.1103 974.6634,288.1103 C947.4714,288.1103 938.5234,270.8113 947.7964,236.1853 C952.4094,218.9903 959.3634,206.0383 968.6594,197.3283 C977.9654,188.6123 989.2324,184.2543 1002.4804,184.2543 C1015.4844,184.2543 1024.2584,188.6123 1028.7794,197.3283 C1033.2984,206.0383 1033.2644,218.9903 1028.6514,236.1853 M1059.0304,155.3243 C1047.0804,147.8943 1031.8154,144.1743 1013.2244,144.1743 C994.4014,144.1743 976.9694,147.8943 960.9174,155.3243 C944.8644,162.7653 931.1984,173.4523 919.9214,187.3893 C908.6314,201.3323 900.4954,217.5943 895.5114,236.1853 C890.5274,254.7763 889.9484,271.0323 893.7734,284.9753 C897.5864,298.9183 905.5144,309.6053 917.5914,317.0403 C929.6574,324.4813 945.0954,328.1903 963.9194,328.1903 C982.5094,328.1903 999.7674,324.4813 1015.7054,317.0403 C1031.6184,309.6053 1045.2374,298.9183 1056.5264,284.9753 C1067.8034,271.0323 1075.9404,254.7763 1080.9244,236.1853 C1085.9084,217.5943 1086.4884,201.3323 1082.6744,187.3893 C1078.8494,173.4523 1070.9674,162.7653 1059.0304,155.3243" id="Fill-7" fill="#072654"></path>
13
+ <path d="M1602.1367,236.533 C1597.6517,253.258 1590.7427,266.042 1581.4127,274.868 C1572.0817,283.7 1560.8857,288.111 1547.8817,288.111 C1534.6457,288.111 1525.6397,283.758 1520.8987,275.042 C1516.1347,266.332 1515.9727,253.733 1520.4007,237.228 C1524.8167,220.735 1531.8637,207.841 1541.5647,198.539 C1551.2537,189.255 1562.6017,184.602 1575.6167,184.602 C1588.6217,184.602 1597.4307,189.082 1601.9967,198.024 C1606.5647,206.966 1606.6217,219.802 1602.1367,236.533 L1602.1367,236.533 Z M1625.6647,148.706 L1618.9427,173.8 C1616.0327,164.736 1610.4117,157.538 1602.0897,152.195 C1593.7567,146.852 1583.4297,144.174 1571.1197,144.174 C1556.0177,144.174 1541.4947,148.069 1527.5637,155.852 C1513.6317,163.64 1501.4497,174.617 1491.0307,188.786 C1480.6107,202.961 1472.9717,219.107 1468.1157,237.228 C1463.2597,255.356 1462.2967,271.328 1465.2067,285.149 C1468.1267,298.977 1474.4447,309.605 1484.2027,317.04 C1493.9397,324.481 1506.4807,328.19 1521.8147,328.19 C1534.1227,328.19 1545.8537,325.635 1556.9797,320.523 C1568.1067,315.418 1577.5527,308.325 1585.3297,299.266 L1578.3187,325.403 L1630.2427,325.403 L1677.5907,148.706 L1625.6647,148.706 Z" id="Fill-9" fill="#072654"></path>
14
+ <path d="M1244.165,196.1055 L1257.401,148.0105 C1252.904,145.6865 1246.946,144.5225 1239.517,144.5225 C1227.66,144.5225 1216.243,147.4835 1205.244,153.4115 C1195.798,158.4975 1187.754,165.6365 1180.962,174.5815 L1187.847,148.6815 L1172.813,148.7065 L1135.938,148.7065 L1088.227,325.4025 L1140.87,325.4025 L1165.616,233.0505 C1169.221,219.5765 1175.688,209.0635 1185.042,201.5125 C1194.372,193.9615 1206.02,190.1825 1219.964,190.1825 C1228.563,190.1825 1236.619,192.1585 1244.165,196.1055" id="Fill-11" fill="#072654"></path>
15
+ <path d="M1390.6973,237.2256 C1386.2693,253.7306 1379.4083,266.3296 1370.1123,275.0396 C1360.7943,283.7556 1349.6433,288.1076 1336.6393,288.1076 C1323.6233,288.1076 1314.7573,283.6976 1310.0393,274.8656 C1305.3103,266.0396 1305.1943,253.2606 1309.6793,236.5296 C1314.1653,219.7996 1321.1423,206.9626 1330.6243,198.0206 C1340.1043,189.0786 1351.3593,184.5986 1364.3753,184.5986 C1377.1473,184.5986 1385.8293,189.2526 1390.4303,198.5426 C1395.0203,207.8376 1395.1133,220.7376 1390.6973,237.2256 M1427.4853,155.8486 C1417.7153,148.0656 1405.2783,144.1776 1390.1873,144.1776 C1376.9393,144.1776 1364.3293,147.1966 1352.3903,153.2356 C1340.4183,159.2856 1330.7173,167.5206 1323.2753,177.9806 L1323.4433,176.8216 L1332.2873,148.6786 L1322.1103,148.6786 L1322.1103,148.7036 L1280.9003,148.7036 L1267.8153,197.5656 C1267.6643,198.1336 1267.5373,198.6636 1267.3853,199.2376 L1213.4093,400.6806 L1266.0423,400.6806 L1293.2213,299.2696 C1295.8863,308.3216 1301.4273,315.4146 1309.8193,320.5206 C1318.2103,325.6316 1328.5603,328.1876 1340.8813,328.1876 C1356.2163,328.1876 1370.7963,324.4786 1384.6463,317.0376 C1398.4863,309.6076 1410.5163,298.9736 1420.7173,285.1466 C1430.9273,271.3306 1438.4623,255.3526 1443.3183,237.2256 C1448.1753,219.1036 1449.1823,202.9586 1446.3663,188.7836 C1443.5503,174.6136 1437.2443,163.6376 1427.4853,155.8486" id="Fill-13" fill="#072654"></path>
16
+ <path d="M1895.5381,148.7554 L1895.5721,148.7064 L1863.6921,148.7064 C1862.6731,148.7064 1861.7741,148.7354 1860.8421,148.7554 L1844.2961,148.7554 L1835.8351,160.5434 C1835.1571,161.4314 1834.4791,162.3254 1833.7491,163.3624 L1832.8271,164.7274 L1765.5851,258.3754 L1751.6421,148.7064 L1696.5641,148.7064 L1724.4561,315.3544 L1662.8591,400.6834 L1664.6151,400.6834 L1696.0651,400.6834 L1717.7341,400.6834 L1732.6621,379.5374 C1733.1021,378.9074 1733.4791,378.3914 1733.9491,377.7254 L1751.3691,353.0284 L1751.8681,352.3214 L1829.8131,241.8274 L1895.4851,148.8284 L1895.5721,148.7554 L1895.5381,148.7554 Z" id="Fill-15" fill="#072654"></path>
17
+ <polygon id="Fill-17" fill="#3395FF" points="122.6338 105.6902 106.8778 163.6732 197.0338 105.3642 138.0748 325.3482 197.9478 325.4032 285.0458 0.4822"></polygon>
18
+ <path d="M25.5947,232.9246 L0.8077,325.4026 L123.5337,325.4026 C123.5337,325.4026 173.7317,137.3196 173.7457,137.2656 C173.6987,137.2956 25.5947,232.9246 25.5947,232.9246" id="Fill-19" fill="#072654"></path>
19
+ </g>
20
+ </g>
21
+ </svg>
@@ -0,0 +1,33 @@
1
+ <?xml version="1.0" encoding="UTF-8"?>
2
+ <svg id="Layer_1" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" version="1.1" viewBox="0 0 1896 401">
3
+ <!-- Generator: Adobe Illustrator 29.3.0, SVG Export Plug-In . SVG Version: 2.1.0 Build 146) -->
4
+ <defs>
5
+ <style>
6
+ .st0 {
7
+ fill: #fff;
8
+ }
9
+
10
+ .st0, .st1 {
11
+ fill-rule: evenodd;
12
+ }
13
+
14
+ .st1 {
15
+ fill: #3395ff;
16
+ }
17
+ </style>
18
+ </defs>
19
+ <g id="Page-1">
20
+ <g id="Group">
21
+ <path id="Fill-1" class="st0" d="M451.9,151.5c-3,11.2-8.8,19.3-17.4,24.6-8.6,5.2-20.7,7.8-36.3,7.8h-49.5l17.4-64.8h49.5c15.6,0,26.3,2.6,32.1,7.8,5.8,5.2,7.2,13.4,4.2,24.6M503.2,150.1c6.3-23.5,3.7-41.5-7.8-54-11.5-12.5-31.7-18.8-60.5-18.8h-110.5l-66.5,248.1h53.7l26.8-100h35.2c7.9,0,14.1,1.3,18.6,3.8,4.6,2.6,7.2,7.1,8,13.6l9.6,82.6h57.5l-9.3-77c-1.9-17.2-9.8-27.3-23.6-30.3,17.6-5.1,32.4-13.6,44.3-25.4,11.9-11.8,20-26,24.5-42.5"/>
22
+ <path id="Fill-3" class="st0" d="M633.6,236.5c-4.5,16.7-11.4,29.5-20.7,38.3-9.3,8.8-20.5,13.2-33.5,13.2s-22.3-4.4-27-13.1c-4.8-8.7-4.9-21.3-.5-37.8,4.4-16.5,11.5-29.4,21.2-38.7,9.7-9.3,21-13.9,34.1-13.9s21.8,4.5,26.4,13.4c4.6,8.9,4.6,21.8.1,38.5h0ZM657.2,148.7l-6.7,25.1c-2.9-9.1-8.5-16.3-16.9-21.6-8.3-5.3-18.7-8-31-8s-29.6,3.9-43.6,11.7c-13.9,7.8-26.1,18.8-36.5,32.9-10.4,14.2-18.1,30.3-22.9,48.4-4.9,18.1-5.8,34.1-2.9,47.9,2.9,13.8,9.2,24.5,19,31.9,9.7,7.4,22.3,11.1,37.6,11.1s24-2.6,35.2-7.7c11.1-5.1,20.6-12.2,28.3-21.3l-7,26.1h51.9l47.3-176.7h-51.9Z"/>
23
+ <polygon id="Fill-5" class="st0" points="895.8 148.7 744.9 148.7 734.3 188.1 822.2 188.1 706 288.5 696.1 325.4 851.9 325.4 862.5 286 768.4 286 886.3 184.3 895.8 148.7"/>
24
+ <path id="Fill-7" class="st0" d="M1028.7,236.2c-4.7,17.4-11.6,30.4-20.7,39-9.2,8.6-20.2,12.9-33.2,12.9-27.2,0-36.1-17.3-26.9-51.9,4.6-17.2,11.6-30.1,20.9-38.9,9.3-8.7,20.6-13.1,33.8-13.1s21.8,4.4,26.3,13.1c4.5,8.7,4.5,21.7-.1,38.9M1059,155.3c-11.9-7.4-27.2-11.1-45.8-11.1s-36.3,3.7-52.3,11.1c-16.1,7.4-29.7,18.1-41,32.1-11.3,13.9-19.4,30.2-24.4,48.8s-5.6,34.8-1.7,48.8c3.8,13.9,11.7,24.6,23.8,32.1,12.1,7.4,27.5,11.1,46.3,11.1s35.8-3.7,51.8-11.1c15.9-7.4,29.5-18.1,40.8-32.1,11.3-13.9,19.4-30.2,24.4-48.8s5.6-34.9,1.8-48.8c-3.8-13.9-11.7-24.6-23.6-32.1"/>
25
+ <path id="Fill-9" class="st0" d="M1602.1,236.5c-4.5,16.7-11.4,29.5-20.7,38.3-9.3,8.8-20.5,13.2-33.5,13.2s-22.2-4.4-27-13.1c-4.8-8.7-4.9-21.3-.5-37.8,4.4-16.5,11.5-29.4,21.2-38.7,9.7-9.3,21-13.9,34.1-13.9s21.8,4.5,26.4,13.4c4.6,8.9,4.6,21.8.1,38.5h0ZM1625.7,148.7l-6.7,25.1c-2.9-9.1-8.5-16.3-16.9-21.6-8.3-5.3-18.7-8-31-8s-29.6,3.9-43.6,11.7c-13.9,7.8-26.1,18.8-36.5,32.9-10.4,14.2-18.1,30.3-22.9,48.4-4.9,18.1-5.8,34.1-2.9,47.9,2.9,13.8,9.2,24.5,19,31.9,9.7,7.4,22.3,11.1,37.6,11.1s24-2.6,35.2-7.7c11.1-5.1,20.6-12.2,28.3-21.3l-7,26.1h51.9l47.3-176.7h-51.9Z"/>
26
+ <path id="Fill-11" class="st0" d="M1244.2,196.1l13.2-48.1c-4.5-2.3-10.5-3.5-17.9-3.5-11.9,0-23.3,3-34.3,8.9-9.4,5.1-17.5,12.2-24.3,21.2l6.9-25.9h-15s-36.9,0-36.9,0l-47.7,176.7h52.6l24.7-92.4c3.6-13.5,10.1-24,19.4-31.5,9.3-7.6,21-11.3,34.9-11.3s16.7,2,24.2,5.9"/>
27
+ <path id="Fill-13" class="st0" d="M1390.7,237.2c-4.4,16.5-11.3,29.1-20.6,37.8-9.3,8.7-20.5,13.1-33.5,13.1s-21.9-4.4-26.6-13.2c-4.7-8.8-4.8-21.6-.4-38.3,4.5-16.7,11.5-29.6,20.9-38.5,9.5-8.9,20.7-13.4,33.8-13.4s21.5,4.7,26.1,13.9c4.6,9.3,4.7,22.2.3,38.7M1427.5,155.8c-9.8-7.8-22.2-11.7-37.3-11.7s-25.9,3-37.8,9.1c-12,6.1-21.7,14.3-29.1,24.7l.2-1.2,8.8-28.1h-10.2s-41.2,0-41.2,0l-13.1,48.9c-.2.6-.3,1.1-.4,1.7l-54,201.4h52.6l27.2-101.4c2.7,9.1,8.2,16.1,16.6,21.3,8.4,5.1,18.7,7.7,31.1,7.7s29.9-3.7,43.8-11.1c13.8-7.4,25.9-18.1,36.1-31.9,10.2-13.8,17.7-29.8,22.6-47.9,4.9-18.1,5.9-34.3,3-48.4-2.8-14.2-9.1-25.1-18.9-32.9"/>
28
+ <path id="Fill-15" class="st0" d="M1895.5,148.8h0s-31.9,0-31.9,0c-1,0-1.9,0-2.9,0h-16.5l-8.5,11.8c-.7.9-1.4,1.8-2.1,2.8l-.9,1.4-67.2,93.6-13.9-109.7h-55.1l27.9,166.6-61.6,85.3h54.9l14.9-21.1c.4-.6.8-1.1,1.3-1.8l17.4-24.7.5-.7,77.9-110.5,65.7-93h0c0,0,0,0,0,0Z"/>
29
+ <polygon id="Fill-17" class="st1" points="122.6 105.7 106.9 163.7 197 105.4 138.1 325.3 197.9 325.4 285 .5 122.6 105.7"/>
30
+ <path id="Fill-19" class="st0" d="M25.6,232.9L.8,325.4h122.7s50.2-188.1,50.2-188.1c0,0-148.2,95.7-148.2,95.7"/>
31
+ </g>
32
+ </g>
33
+ </svg>
@@ -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>
@@ -0,0 +1,29 @@
1
+ <svg id="Layer_2" data-name="Layer 2" xmlns="http://www.w3.org/2000/svg" viewBox="0 0 232.55 132.88" width="160" height="160">
2
+ <defs>
3
+ <style>
4
+ .cls-1 {
5
+ stroke-miterlimit: 10;
6
+ }
7
+ .cls-1, .cls-2 {
8
+ fill: none;
9
+ stroke: #bababa;
10
+ stroke-linecap: round;
11
+ stroke-width: 3px;
12
+ }
13
+ .cls-3 {
14
+ fill: #bababa;
15
+ }
16
+ .cls-2 {
17
+ stroke-linejoin: round;
18
+ }
19
+ </style>
20
+ </defs>
21
+ <g id="Layer_1-2" data-name="Layer 1">
22
+ <polyline class="cls-1" points="1.5 18.16 203.71 18.16 203.71 65.59"/>
23
+ <polyline class="cls-2" points="171.76 72.65 231.05 72.65 225.69 65.59 231.05 72.65 225.69 79.71"/>
24
+ <circle class="cls-3" cx="9.57" cy="10.07" r="2.95"/>
25
+ <circle class="cls-3" cx="18.79" cy="10.07" r="2.95"/>
26
+ <circle class="cls-3" cx="27.84" cy="10.07" r="2.95"/>
27
+ <path class="cls-1" d="m203.71,18.16V4.81c0-1.83-1.48-3.31-3.31-3.31H4.81c-1.83,0-3.31,1.48-3.31,3.31v123.27c0,1.83,1.48,3.31,3.31,3.31h195.59c1.83,0,3.31-1.48,3.31-3.31v-48.36"/>
28
+ </g>
29
+ </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,64 @@ 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
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
+ order&.reload
11
+
12
+ return render json: { success: false, error: 'Order not found' }, status: :not_found unless order
13
+
14
+ if order.outstanding_balance <= 0
15
+ return render json: { success: false, error: "Order is already paid" }, status: :unprocessable_entity
16
+ end
17
+
18
+ razorpay_order_id, amount = ::Razorpay::RpOrder::Api.new.create(order.id)
10
19
 
11
20
  if razorpay_order_id.present?
12
- render json: { success: true, razorpay_order_id: razorpay_order_id }
21
+ render json: { success: true, razorpay_order_id: razorpay_order_id, amount: amount }
13
22
  else
14
23
  render json: { success: false, error: "Failed to create Razorpay order" }, status: :unprocessable_entity
15
24
  end
16
25
  end
17
26
 
18
- #Step 2: Razorpay callback after payment
27
+ # Step 2: Handle Response
19
28
  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'
29
+ order = Spree::Order.find_by(number: params[:order_id] || params[:order_number])
30
+ unless order
31
+ flash[:error] = "Order not found."
32
+ return redirect_to checkout_state_path(:payment)
59
33
  end
60
34
 
61
- redirect_to checkout_state_path(order.state)
35
+ unless valid_signature?
36
+ flash[:error] = "Payment signature verification failed."
37
+ return redirect_to checkout_state_path(order.state)
38
+ end
39
+
40
+ begin
41
+ razorpay_payment = gateway.verify_and_capture_razorpay_payment(order, razorpay_payment_id)
42
+ spree_payment = order.razor_payment(razorpay_payment, payment_method, params[:razorpay_signature])
43
+
44
+ if razorpay_payment.status == 'captured'
45
+ spree_payment.complete!
46
+ elsif razorpay_payment.status == 'authorized'
47
+ spree_payment.pend!
48
+ end
49
+ while !order.completed?
50
+ order.next!
51
+ end
52
+ redirect_to completion_route
53
+
54
+ rescue StandardError => e
55
+ Rails.logger.error("Razorpay Error: #{e.message}\n#{e.backtrace.join("\n")}")
56
+ flash[:error] = "Payment Error: #{e.message}"
57
+ redirect_to checkout_state_path(order.state)
58
+ end
62
59
  end
63
60
 
64
61
  private
65
62
 
66
63
  def razorpay_payment_id
67
- params[:razorpay_payment_id]
64
+ params[:razorpay_payment_id] || params.dig(:payment_source, payment_method.id.to_s, :razorpay_payment_id)
68
65
  end
69
66
 
70
67
  def razorpay_payment
@@ -72,34 +69,41 @@ module Spree
72
69
  end
73
70
 
74
71
  def valid_signature?
72
+ p_id = payment_method.id.to_s
73
+ r_order_id = params[:razorpay_order_id] || params.dig(:payment_source, p_id, :razorpay_order_id)
74
+ r_pay_id = razorpay_payment_id
75
+ r_sig = params[:razorpay_signature] || params.dig(:payment_source, p_id, :razorpay_signature)
76
+
75
77
  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]
78
+ razorpay_order_id: r_order_id,
79
+ razorpay_payment_id: r_pay_id,
80
+ razorpay_signature: r_sig
79
81
  )
80
82
  rescue Razorpay::Error => e
81
83
  Rails.logger.error("Razorpay signature verification failed: #{e.message}")
82
84
  false
83
85
  end
84
86
 
85
- def order
86
- @order ||= Spree::Order.find_by(number: params[:order_id])
87
- end
88
-
89
87
  def payment_method
90
- @payment_method ||= Spree::PaymentMethod.find(params[:payment_method_id])
88
+ @payment_method ||= Spree::PaymentMethod.find_by(id: params[:payment_method_id]) || Spree::PaymentMethod.find_by(type: 'Spree::Gateway::RazorpayGateway')
91
89
  end
92
90
 
93
91
  def gateway
94
- @gateway ||= payment_method
92
+ payment_method
95
93
  end
96
94
 
97
- def checkout_state_path_or_completion
98
- order.completed? ? completion_route : checkout_state_path(order.state)
95
+ def order
96
+ @order ||= Spree::Order.find_by(number: params[:order_id] || params[:order_number])
99
97
  end
100
-
98
+
101
99
  def completion_route
102
- order_path(order)
100
+ token = order.respond_to?(:guest_token) ? order.guest_token : order.token
101
+
102
+ if token.present?
103
+ "/checkout/#{token}/complete"
104
+ else
105
+ spree.order_path(order)
106
+ end
103
107
  end
104
108
  end
105
109
  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.inr_amt_in_paise
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,23 @@
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
+ def name
8
+ "Razorpay Secure (UPI, Wallets, Cards & Netbanking)"
9
+ end
10
+
11
+ def method_type
12
+ "razorpay"
13
+ end
14
+
15
+ def payment_id
16
+ self.razorpay_payment_id
17
+ end
18
+
19
+ def order_id
20
+ self.razorpay_order_id
21
+ end
3
22
  end
4
23
  end
@@ -1,30 +1,57 @@
1
1
  module SpreeRazorpayCheckout
2
2
  module Spree
3
3
  module OrderDecorator
4
+
4
5
  def inr_amt_in_paise
5
- (total.to_f * 100).to_i
6
+ payments.reload
7
+
8
+ prepaid_amount = payments.select do |p|
9
+ valid_state = %w[checkout pending processing completed].include?(p.state)
10
+
11
+ not_razorpay = !p.source_type.to_s.include?('RazorpayCheckout') &&
12
+ !p.payment_method&.type.to_s.include?('RazorpayGateway')
13
+
14
+ valid_state && not_razorpay
15
+ end.sum(&:amount)
16
+
17
+ amount_needed = total - prepaid_amount
18
+
19
+ Rails.logger.info "Razorpay Calc: Total=#{total}, Prepaid=#{prepaid_amount}, Needed=#{amount_needed}"
20
+
21
+ return 0 if amount_needed <= 0
22
+
23
+ (amount_needed.to_f * 100).to_i
6
24
  end
7
25
 
8
26
  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
- ),
27
+
28
+ amount_to_charge = (inr_amt_in_paise / 100.0)
29
+
30
+ amount_to_charge = total if amount_to_charge <= 0
31
+
32
+ source = ::Spree::RazorpayCheckout.create!(
33
+ order_id: id,
34
+ razorpay_payment_id: payment_object.id,
35
+ razorpay_order_id: payment_object.order_id,
36
+ razorpay_signature: razorpay_signature,
37
+ status: payment_object.status,
38
+ payment_method: payment_object.method,
39
+ card_id: payment_object.card_id,
40
+ bank: payment_object.bank,
41
+ wallet: payment_object.wallet,
42
+ vpa: payment_object.vpa,
43
+ email: payment_object.email,
44
+ contact: payment_object.contact
45
+ )
46
+
47
+ payment = payments.create!(
48
+ source: source,
24
49
  payment_method: payment_method,
25
- amount: total,
26
- response_code: payment_object.status
50
+ amount: amount_to_charge,
51
+ response_code: payment_object.id
27
52
  )
53
+
54
+ payment
28
55
  end
29
56
 
30
57
  ::Spree::Order.prepend SpreeRazorpayCheckout::Spree::OrderDecorator
@@ -5,27 +5,30 @@ module Razorpay
5
5
 
6
6
  def create(order_id)
7
7
  @order = Spree::Order.find_by(id: order_id)
8
-
9
- razorpay_order = Razorpay::Order.create(order_create_params)
10
-
8
+ raise "Order not found" unless order
9
+ params = order_create_params
10
+ Rails.logger.info "Razorpay::Order.create Params: #{params.inspect}"
11
+ razorpay_order = Razorpay::Order.create(params)
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, params[:amount]]
14
15
  end
15
-
16
- ''
16
+ ['', 0]
17
17
  rescue StandardError => e
18
18
  Rails.logger.error("Razorpay Order create failed: #{e.message}")
19
- ''
19
+ Rails.logger.error(e.backtrace.join("\n"))
20
+ ['', 0]
20
21
  end
21
22
 
22
23
  private
23
24
 
24
25
  def order_create_params
26
+ amt = order.inr_amt_in_paise
25
27
  {
26
- amount: order.inr_amt_in_paise,
27
- currency: order.currency,
28
- receipt: order.number
28
+ amount: amt.to_i,
29
+ currency: (order.currency || 'INR').to_s,
30
+ receipt: order.number.to_s,
31
+ payment_capture: 1
29
32
  }
30
33
  end
31
34
 
@@ -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>
@@ -1,190 +1,200 @@
1
1
  <script>
2
- document.addEventListener("turbo:load", setupRazorpay);
3
- document.addEventListener("turbo:frame-load", function (e) {
4
- if (e.target.id === "checkout_payment_methods") setupRazorpay();
5
- });
6
-
7
- function setupRazorpay() {
8
- const razorpayMethodId = "<%= payment_method.id %>";
9
- const form = document.querySelector("#checkout_form_payment");
10
- const payBtn = document.getElementById("checkout-payment-submit");
11
- const razorpayBtn = document.getElementById("razorpay-custom-button");
12
-
13
- if (!form || !payBtn || !razorpayBtn) return;
14
-
15
- let razorpayCompleted = false;
16
-
17
- function getSelectedPaymentMethodId() {
18
- const selected = document.querySelector('input[name="order[payments_attributes][][payment_method_id]"]:checked');
19
- const fallback = document.querySelector('input[type="hidden"][name="order[payments_attributes][][payment_method_id]"]');
20
- return selected?.value || fallback?.value;
21
- }
22
-
23
- function toggleButtons() {
24
- const selectedId = getSelectedPaymentMethodId();
25
- const isRazorpay = selectedId === razorpayMethodId;
26
-
27
- if (isRazorpay) {
28
- payBtn.classList.add("hidden");
29
- razorpayBtn.classList.remove("hidden");
30
- } else {
31
- razorpayBtn.classList.add("hidden");
32
- payBtn.classList.remove("hidden");
2
+ (function() {
3
+ const RAZORPAY_METHOD_ID = "<%= payment_method.id %>";
4
+ const ORDER_ID = "<%= @order.id %>";
5
+ const ORDER_NUMBER = "<%= @order.number %>";
6
+ const KEY_ID = "<%= payment_method.current_key_id %>";
7
+ const MERCHANT_NAME = "<%= payment_method.preferred_merchant_name.presence || 'Razorpay Store' %>";
8
+ const MERCHANT_DESC = "<%= payment_method.preferred_merchant_description.presence || 'Order Payment' %>";
9
+ const THEME_COLOR = "<%= payment_method.preferred_theme_color.presence || '#2e5bff' %>";
10
+
11
+ const USER_NAME = "<%= @order.bill_address&.firstname %> <%= @order.bill_address&.lastname %>";
12
+ const USER_EMAIL = "<%= @order.email %>";
13
+ const USER_CONTACT = "<%= @order.bill_address&.phone %>";
14
+
15
+ window.razorpayTransactionSuccess = false;
16
+
17
+ function resetButtonState() {
18
+ const btn = document.getElementById("razorpay-custom-button");
19
+ if (btn) {
20
+ btn.disabled = false;
21
+ if (btn.dataset.originalHtml) {
22
+ btn.innerHTML = btn.dataset.originalHtml;
23
+ }
24
+ }
33
25
  }
34
- }
35
-
36
- toggleButtons();
37
26
 
38
- document.querySelectorAll('input[name="order[payments_attributes][][payment_method_id]"]').forEach((radio) => {
39
- radio.addEventListener("change", toggleButtons);
40
- });
27
+ function getSelectedPaymentMethodId() {
28
+ const selected = document.querySelector('input[name="order[payments_attributes][][payment_method_id]"]:checked');
29
+ const fallback = document.querySelector('input[type="hidden"][name="order[payments_attributes][][payment_method_id]"]');
30
+ return selected?.value || fallback?.value;
31
+ }
41
32
 
42
- form.addEventListener("submit", function (e) {
43
- const selectedId = getSelectedPaymentMethodId();
44
- if (selectedId === razorpayMethodId && !razorpayCompleted) {
45
- e.preventDefault();
46
- alert("Please complete the Razorpay payment first.");
33
+ function updatePaymentUI() {
34
+ const payBtn = document.getElementById("checkout-payment-submit");
35
+ const razorpayBtn = document.getElementById("razorpay-custom-button");
36
+
37
+ if (!payBtn || !razorpayBtn) return;
38
+
39
+ if (getSelectedPaymentMethodId() === RAZORPAY_METHOD_ID) {
40
+ payBtn.style.display = 'none';
41
+ razorpayBtn.style.display = 'flex';
42
+ } else {
43
+ razorpayBtn.style.display = 'none';
44
+ payBtn.style.display = 'block';
45
+ }
47
46
  }
48
- });
49
-
50
- razorpayBtn.addEventListener("click", function () {
51
- fetch("/razorpay/create_order", {
52
- method: "POST",
53
- headers: {
54
- "Content-Type": "application/json",
55
- "X-CSRF-Token": document.querySelector('meta[name="csrf-token"]').content
56
- },
57
- body: JSON.stringify({ order_id: "<%= @order.id %>" })
58
- })
59
- .then(response => response.json())
60
- .then(data => {
61
- if (!data.success) {
62
- alert("Failed to initiate Razorpay payment. Please try again.");
63
- return;
47
+
48
+ document.addEventListener("change", function(e) {
49
+ if (e.target && e.target.name === "order[payments_attributes][][payment_method_id]") {
50
+ updatePaymentUI();
64
51
  }
52
+ });
65
53
 
66
- const options = {
67
- key: "<%= payment_method.current_key_id %>",
68
- order_id: data.razorpay_order_id,
69
- amount: data.amount,
70
- currency: "INR",
71
- name: "<%= payment_method.preferred_merchant_name.presence || 'Razorpay Store' %>",
72
- description: "<%= payment_method.preferred_merchant_description.presence || 'Order Payment' %>",
73
- handler: function (response) {
74
- razorpayCompleted = true;
75
- document.getElementById("razorpay_payment_id").value = response.razorpay_payment_id;
76
- document.getElementById("razorpay_order_id").value = response.razorpay_order_id;
77
- document.getElementById("razorpay_signature").value = response.razorpay_signature;
78
- form.requestSubmit();
79
- },
80
- modal: {
81
- ondismiss: function () {
82
- razorpayCompleted = false;
83
- }
84
- },
85
- prefill: {
86
- name: "<%= @order.bill_address&.firstname %> <%= @order.bill_address&.lastname %>",
87
- email: "<%= @order.email %>",
88
- contact: "<%= @order.bill_address&.phone %>"
54
+ document.addEventListener("turbo:frame-render", function() { setTimeout(updatePaymentUI, 50); });
55
+ document.addEventListener("turbo:load", updatePaymentUI);
56
+
57
+ document.addEventListener("submit", function(e) {
58
+ const form = document.querySelector("#checkout_form_payment");
59
+ if (e.target === form) {
60
+ if (getSelectedPaymentMethodId() === RAZORPAY_METHOD_ID && !window.razorpayTransactionSuccess) {
61
+ e.preventDefault();
62
+ e.stopPropagation();
63
+ alert("Please click the Razorpay button to proceed.");
64
+ return false;
65
+ }
66
+ }
67
+ });
68
+
69
+ document.addEventListener("click", function(e) {
70
+ const btn = e.target.closest("#razorpay-custom-button");
71
+ if (!btn) return;
72
+
73
+ e.preventDefault();
74
+
75
+ if (!btn.dataset.originalHtml) {
76
+ btn.dataset.originalHtml = btn.innerHTML;
77
+ }
78
+ btn.disabled = true;
79
+ btn.innerHTML = '<span style="font-style: oblique;">Processing...</span>';
80
+
81
+ fetch("/razorpay/create_order", {
82
+ method: "POST",
83
+ headers: {
84
+ "Content-Type": "application/json",
85
+ "X-CSRF-Token": document.querySelector('meta[name="csrf-token"]').content
89
86
  },
90
- theme: {
91
- color: "<%= payment_method.preferred_theme_color.presence || '#3399cc' %>"
87
+ body: JSON.stringify({ order_id: ORDER_ID })
88
+ })
89
+ .then(response => response.json())
90
+ .then(data => {
91
+ if (!data.success) {
92
+ throw new Error(data.error || "Server Error");
92
93
  }
93
- };
94
- delete options.session;
95
-
96
- const rzp = new Razorpay(options);
97
- rzp.open();
98
- })
99
- .catch(() => {
100
- alert("Error creating Razorpay order. Please refresh and try again.");
94
+
95
+ const options = {
96
+ key: KEY_ID,
97
+ order_id: data.razorpay_order_id,
98
+ amount: data.amount,
99
+ currency: "INR",
100
+ name: MERCHANT_NAME,
101
+ description: MERCHANT_DESC,
102
+ handler: function (response) {
103
+ window.razorpayTransactionSuccess = true;
104
+ document.getElementById("razorpay_payment_id").value = response.razorpay_payment_id;
105
+ document.getElementById("razorpay_order_id").value = response.razorpay_order_id;
106
+ document.getElementById("razorpay_signature").value = response.razorpay_signature;
107
+
108
+ const form = document.querySelector("#checkout_form_payment");
109
+ form.action = "/razorpay/response?order_id=" + ORDER_NUMBER + "&payment_method_id=" + RAZORPAY_METHOD_ID;
110
+ form.method = "POST";
111
+ form.submit();
112
+ },
113
+ modal: {
114
+ ondismiss: function () {
115
+ resetButtonState();
116
+ }
117
+ },
118
+ prefill: {
119
+ name: USER_NAME,
120
+ email: USER_EMAIL,
121
+ contact: USER_CONTACT
122
+ },
123
+ theme: {
124
+ color: THEME_COLOR
125
+ }
126
+ };
127
+
128
+ const rzp = new Razorpay(options);
129
+ rzp.open();
130
+ })
131
+ .catch((err) => {
132
+ console.error(err);
133
+ alert("Unable to initiate payment: " + err.message);
134
+ resetButtonState();
135
+ });
101
136
  });
102
- });
103
- }
137
+ })();
104
138
  </script>
105
139
 
106
140
  <style>
107
141
  #razorpay-custom-button {
108
- background: black !important;
109
- color: #bababa !important;
110
- border: none !important;
111
- padding: 12px !important;
112
- font-size: 0.8rem !important;
113
- font-style: italic !important;
114
- font-weight: 300 !important;
115
- border-radius: 100px !important;
116
- cursor: pointer !important;
117
- width: 100% !important;
118
- margin: 15px 0 !important;
119
- box-shadow: 0 4px 15px rgba(102, 126, 234, 0.4) !important;
142
+ background: linear-gradient(180deg, rgb(0 26 72) 0%, rgb(1 4 30) 50%, #000000 100%) !important;
143
+ color: white !important;
144
+ border: none !important;
145
+ padding: 13px 100px 13px 100px !important;
146
+ font-size: 0.8rem !important;
147
+ font-weight: 400 !important;
148
+ border-radius: 50px !important;
149
+ cursor: pointer !important;
150
+ width: max-content !important;
151
+ place-self: center;
152
+ margin: 20px 0 !important;
153
+ box-shadow: 0 4px 15px rgba(19, 100, 241, 0.5) !important;
154
+ transition: all 0.3s ease !important;
155
+ display: flex !important;
156
+ align-items: center !important;
157
+ justify-content: center !important;
158
+ }
159
+ #razorpay-custom-button:hover {
160
+ box-shadow: 0 6px 20px rgba(19, 100, 241, 0.7) !important;
161
+ transform: translateY(-1px) !important;
120
162
  }
121
163
  #razorpay-custom-button:active {
122
- background: linear-gradient(104deg, rgb(19, 100, 241), rgb(0, 17, 173) 30%) !important;
164
+ transform: translateY(1px) !important;
165
+ box-shadow: 0 2px 10px rgba(19, 100, 241, 0.4) !important;
166
+ }
167
+ #razorpay-custom-button:disabled {
168
+ background: #ccc !important;
169
+ cursor: not-allowed !important;
170
+ box-shadow: none !important;
123
171
  }
124
172
  </style>
125
173
 
126
174
  <script src="https://checkout.razorpay.com/v1/checkout.js"></script>
127
175
  <div style="display: flex; justify-content: center;">
128
- <svg id="Layer_2" data-name="Layer 2" xmlns="http://www.w3.org/2000/svg" viewBox="0 0 232.55 132.88" width="160" height="160">
129
- <defs>
130
- <style>
131
- .cls-1 {
132
- stroke-miterlimit: 10;
133
- }
134
-
135
- .cls-1, .cls-2 {
136
- fill: none;
137
- stroke: #bababa;
138
- stroke-linecap: round;
139
- stroke-width: 3px;
140
- }
141
-
142
- .cls-3 {
143
- fill: #bababa;
144
- }
145
-
146
- .cls-2 {
147
- stroke-linejoin: round;
148
- }
149
- </style>
150
- </defs>
151
- <g id="Layer_1-2" data-name="Layer 1">
152
- <polyline class="cls-1" points="1.5 18.16 203.71 18.16 203.71 65.59"/>
153
- <polyline class="cls-2" points="171.76 72.65 231.05 72.65 225.69 65.59 231.05 72.65 225.69 79.71"/>
154
- <circle class="cls-3" cx="9.57" cy="10.07" r="2.95"/>
155
- <circle class="cls-3" cx="18.79" cy="10.07" r="2.95"/>
156
- <circle class="cls-3" cx="27.84" cy="10.07" r="2.95"/>
157
- <path class="cls-1" d="m203.71,18.16V4.81c0-1.83-1.48-3.31-3.31-3.31H4.81c-1.83,0-3.31,1.48-3.31,3.31v123.27c0,1.83,1.48,3.31,3.31,3.31h195.59c1.83,0,3.31-1.48,3.31-3.31v-48.36"/>
158
- </g>
159
- </svg>
176
+ <%= image_tag 'payment_icons/window_modal.svg', width: 140, height: 100, class: 'ml-2', alt: 'Razorpay Modal Window' %>
160
177
  </div>
161
- <p style="max-width: 600px; margin: 10px auto; text-align: center;">
178
+
179
+ <p style="max-width: 600px;margin: 10px auto;text-align: center;color: var(--color-neutral-600);font-size: 13px;">
162
180
  After clicking “Complete order”, you will be redirected to <br>
163
181
  Razorpay Secure (UPI, Cards, Wallets, NetBanking) to complete <br>
164
182
  your purchase securely.
165
183
  </p>
166
-
184
+ <div style="display: flex; justify-content: center; align-items: center;">
185
+ <%= payment_method_icon_tag 'visa', class: 'm-1' %>
186
+ <%= payment_method_icon_tag 'master', class: 'm-1' %>
187
+ <%= payment_method_icon_tag 'google_pay', class: 'm-1' %>
188
+ <%= payment_method_icon_tag 'amazon', class: 'm-1' %>
189
+ <%= payment_method_icon_tag 'upi', class: 'm-1' %>
190
+ </div>
167
191
  <!-- Hidden Razorpay input field -->
168
192
  <input type="hidden" name="payment_source[<%= payment_method.id %>][razorpay_payment_id]" id="razorpay_payment_id" value="">
169
193
  <input type="hidden" name="payment_source[<%= payment_method.id %>][razorpay_order_id]" id="razorpay_order_id" value="">
170
194
  <input type="hidden" name="payment_source[<%= payment_method.id %>][razorpay_signature]" id="razorpay_signature" value="">
171
195
 
172
196
  <!-- Custom Razorpay Button -->
173
- <button id="razorpay-custom-button" type="button">
174
- <svg xmlns="http://www.w3.org/2000/svg" viewBox="500 0 400 400" width="160" height="25" style="vertical-align: bottom; margin-right: 50%; margin-left: 40%; justify-self: center !important;">
175
- <g id="Page-1" stroke="none" stroke-width="1" fill="none" fill-rule="evenodd">
176
- <g id="Group">
177
- <path d="M451.9209,151.4937 C448.9309,162.6497 443.1359,170.8377 434.5349,176.0657 C425.9239,181.2927 413.8469,183.9117 398.2689,183.9117 L348.7769,183.9117 L366.1509,119.0807 L415.6429,119.0807 C431.2089,119.0807 441.8959,121.6947 447.7019,126.9217 C453.4969,132.1547 454.9109,140.3437 451.9209,151.4937 M503.1739,150.0967 C509.4679,126.6377 506.8589,108.6267 495.3509,96.0797 C483.8409,83.5327 463.6739,77.2627 434.8709,77.2627 L324.3909,77.2627 L257.8969,325.4027 L311.5719,325.4027 L338.3809,225.3777 L373.5809,225.3777 C381.4739,225.3777 387.6869,226.6577 392.2309,229.2137 C396.7849,231.7747 399.4509,236.3067 400.2739,242.8037 L409.8479,325.4027 L467.3589,325.4027 L458.0289,248.3847 C456.1279,231.1897 448.2589,221.0827 434.4309,218.0637 C452.0599,212.9577 466.8259,204.4677 478.7179,192.6167 C490.5989,180.7717 498.7579,166.6017 503.1739,150.0967" id="Fill-1" fill="#fff"></path>
178
- <path d="M633.625,236.533 C629.14,253.258 622.231,266.042 612.901,274.868 C603.56,283.7 592.386,288.111 579.382,288.111 C566.122,288.111 557.128,283.758 552.387,275.042 C547.623,266.332 547.461,253.733 551.889,237.228 C556.305,220.735 563.352,207.841 573.053,198.539 C582.742,189.255 594.09,184.602 607.105,184.602 C620.11,184.602 628.919,189.082 633.485,198.024 C638.053,206.966 638.11,219.802 633.625,236.533 L633.625,236.533 Z M657.153,148.706 L650.431,173.8 C647.521,164.736 641.9,157.538 633.578,152.195 C625.245,146.852 614.918,144.174 602.608,144.174 C587.506,144.174 572.983,148.069 559.052,155.852 C545.12,163.64 532.938,174.617 522.519,188.786 C512.099,202.961 504.461,219.107 499.604,237.228 C494.748,255.356 493.774,271.328 496.695,285.149 C499.616,298.977 505.944,309.605 515.691,317.04 C525.428,324.481 537.969,328.19 553.303,328.19 C565.612,328.19 577.342,325.635 588.469,320.523 C599.595,315.418 609.041,308.325 616.818,299.266 L609.807,325.403 L661.731,325.403 L709.079,148.706 L657.153,148.706 Z" id="Fill-3" fill="#fff"></path>
179
- <polygon id="Fill-5" fill="#fff" points="895.79 148.7061 744.882 148.7061 734.334 188.0911 822.155 188.0911 706.042 288.4581 696.132 325.4031 851.92 325.4031 862.478 286.0241 768.388 286.0241 886.263 184.2541"></polygon>
180
- <path d="M1028.6514,236.1853 C1023.9804,253.6053 1017.0604,266.6273 1007.9044,275.2223 C998.7484,283.8163 987.6674,288.1103 974.6634,288.1103 C947.4714,288.1103 938.5234,270.8113 947.7964,236.1853 C952.4094,218.9903 959.3634,206.0383 968.6594,197.3283 C977.9654,188.6123 989.2324,184.2543 1002.4804,184.2543 C1015.4844,184.2543 1024.2584,188.6123 1028.7794,197.3283 C1033.2984,206.0383 1033.2644,218.9903 1028.6514,236.1853 M1059.0304,155.3243 C1047.0804,147.8943 1031.8154,144.1743 1013.2244,144.1743 C994.4014,144.1743 976.9694,147.8943 960.9174,155.3243 C944.8644,162.7653 931.1984,173.4523 919.9214,187.3893 C908.6314,201.3323 900.4954,217.5943 895.5114,236.1853 C890.5274,254.7763 889.9484,271.0323 893.7734,284.9753 C897.5864,298.9183 905.5144,309.6053 917.5914,317.0403 C929.6574,324.4813 945.0954,328.1903 963.9194,328.1903 C982.5094,328.1903 999.7674,324.4813 1015.7054,317.0403 C1031.6184,309.6053 1045.2374,298.9183 1056.5264,284.9753 C1067.8034,271.0323 1075.9404,254.7763 1080.9244,236.1853 C1085.9084,217.5943 1086.4884,201.3323 1082.6744,187.3893 C1078.8494,173.4523 1070.9674,162.7653 1059.0304,155.3243" id="Fill-7" fill="#fff"></path>
181
- <path d="M1602.1367,236.533 C1597.6517,253.258 1590.7427,266.042 1581.4127,274.868 C1572.0817,283.7 1560.8857,288.111 1547.8817,288.111 C1534.6457,288.111 1525.6397,283.758 1520.8987,275.042 C1516.1347,266.332 1515.9727,253.733 1520.4007,237.228 C1524.8167,220.735 1531.8637,207.841 1541.5647,198.539 C1551.2537,189.255 1562.6017,184.602 1575.6167,184.602 C1588.6217,184.602 1597.4307,189.082 1601.9967,198.024 C1606.5647,206.966 1606.6217,219.802 1602.1367,236.533 L1602.1367,236.533 Z M1625.6647,148.706 L1618.9427,173.8 C1616.0327,164.736 1610.4117,157.538 1602.0897,152.195 C1593.7567,146.852 1583.4297,144.174 1571.1197,144.174 C1556.0177,144.174 1541.4947,148.069 1527.5637,155.852 C1513.6317,163.64 1501.4497,174.617 1491.0307,188.786 C1480.6107,202.961 1472.9717,219.107 1468.1157,237.228 C1463.2597,255.356 1462.2967,271.328 1465.2067,285.149 C1468.1267,298.977 1474.4447,309.605 1484.2027,317.04 C1493.9397,324.481 1506.4807,328.19 1521.8147,328.19 C1534.1227,328.19 1545.8537,325.635 1556.9797,320.523 C1568.1067,315.418 1577.5527,308.325 1585.3297,299.266 L1578.3187,325.403 L1630.2427,325.403 L1677.5907,148.706 L1625.6647,148.706 Z" id="Fill-9" fill="#fff"></path>
182
- <path d="M1244.165,196.1055 L1257.401,148.0105 C1252.904,145.6865 1246.946,144.5225 1239.517,144.5225 C1227.66,144.5225 1216.243,147.4835 1205.244,153.4115 C1195.798,158.4975 1187.754,165.6365 1180.962,174.5815 L1187.847,148.6815 L1172.813,148.7065 L1135.938,148.7065 L1088.227,325.4025 L1140.87,325.4025 L1165.616,233.0505 C1169.221,219.5765 1175.688,209.0635 1185.042,201.5125 C1194.372,193.9615 1206.02,190.1825 1219.964,190.1825 C1228.563,190.1825 1236.619,192.1585 1244.165,196.1055" id="Fill-11" fill="#fff"></path>
183
- <path d="M1390.6973,237.2256 C1386.2693,253.7306 1379.4083,266.3296 1370.1123,275.0396 C1360.7943,283.7556 1349.6433,288.1076 1336.6393,288.1076 C1323.6233,288.1076 1314.7573,283.6976 1310.0393,274.8656 C1305.3103,266.0396 1305.1943,253.2606 1309.6793,236.5296 C1314.1653,219.7996 1321.1423,206.9626 1330.6243,198.0206 C1340.1043,189.0786 1351.3593,184.5986 1364.3753,184.5986 C1377.1473,184.5986 1385.8293,189.2526 1390.4303,198.5426 C1395.0203,207.8376 1395.1133,220.7376 1390.6973,237.2256 M1427.4853,155.8486 C1417.7153,148.0656 1405.2783,144.1776 1390.1873,144.1776 C1376.9393,144.1776 1364.3293,147.1966 1352.3903,153.2356 C1340.4183,159.2856 1330.7173,167.5206 1323.2753,177.9806 L1323.4433,176.8216 L1332.2873,148.6786 L1322.1103,148.6786 L1322.1103,148.7036 L1280.9003,148.7036 L1267.8153,197.5656 C1267.6643,198.1336 1267.5373,198.6636 1267.3853,199.2376 L1213.4093,400.6806 L1266.0423,400.6806 L1293.2213,299.2696 C1295.8863,308.3216 1301.4273,315.4146 1309.8193,320.5206 C1318.2103,325.6316 1328.5603,328.1876 1340.8813,328.1876 C1356.2163,328.1876 1370.7963,324.4786 1384.6463,317.0376 C1398.4863,309.6076 1410.5163,298.9736 1420.7173,285.1466 C1430.9273,271.3306 1438.4623,255.3526 1443.3183,237.2256 C1448.1753,219.1036 1449.1823,202.9586 1446.3663,188.7836 C1443.5503,174.6136 1437.2443,163.6376 1427.4853,155.8486" id="Fill-13" fill="#fff"></path>
184
- <path d="M1895.5381,148.7554 L1895.5721,148.7064 L1863.6921,148.7064 C1862.6731,148.7064 1861.7741,148.7354 1860.8421,148.7554 L1844.2961,148.7554 L1835.8351,160.5434 C1835.1571,161.4314 1834.4791,162.3254 1833.7491,163.3624 L1832.8271,164.7274 L1765.5851,258.3754 L1751.6421,148.7064 L1696.5641,148.7064 L1724.4561,315.3544 L1662.8591,400.6834 L1664.6151,400.6834 L1696.0651,400.6834 L1717.7341,400.6834 L1732.6621,379.5374 C1733.1021,378.9074 1733.4791,378.3914 1733.9491,377.7254 L1751.3691,353.0284 L1751.8681,352.3214 L1829.8131,241.8274 L1895.4851,148.8284 L1895.5721,148.7554 L1895.5381,148.7554 Z" id="Fill-15" fill="#fff"></path>
185
- <polygon id="Fill-17" fill="#3395FF" points="122.6338 105.6902 106.8778 163.6732 197.0338 105.3642 138.0748 325.3482 197.9478 325.4032 285.0458 0.4822"></polygon>
186
- <path d="M25.5947,232.9246 L0.8077,325.4026 L123.5337,325.4026 C123.5337,325.4026 173.7317,137.3196 173.7457,137.2656 C173.6987,137.2956 25.5947,232.9246 25.5947,232.9246" id="Fill-19" fill="#fff"></path>
187
- </g>
188
- </g>
189
- </svg>
197
+ <button id="razorpay-custom-button" type="button" class="btn btn-primary w-100 flex items-center justify-center gap-1" style="display: none;">
198
+ <span style="color: #3395ff;font-style: oblique;font-weight: 400;">Pay via</span>
199
+ <%= image_tag 'payment_icons/razorpay_logo_light.svg', width: 100, height: 50, class: 'ml-2', alt: 'Razorpay Pay Button' %>
190
200
  </button>
@@ -1,4 +1,10 @@
1
- # Logo Location
2
- Rails.application.config.assets.precompile += %w[
1
+ # Only run this if Sprockets is loaded (Spree 4.x / 5.0)
2
+ if Rails.configuration.respond_to?(:assets) && defined?(Sprockets)
3
+ Rails.application.config.assets.precompile += %w[
4
+ payment_icons/razorpay_logo_dark.svg
5
+ payment_icons/razorpay_logo_light.svg
3
6
  payment_icons/razorpay.svg
4
- ]
7
+ payment_icons/razorpaycheckout.svg
8
+ payment_icons/window_modal.svg
9
+ ]
10
+ end
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.2'.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.2
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-12-03 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,10 @@ 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/razorpay_logo_dark.svg
107
+ - app/assets/images/payment_icons/razorpay_logo_light.svg
108
+ - app/assets/images/payment_icons/razorpaycheckout.svg
109
+ - app/assets/images/payment_icons/window_modal.svg
106
110
  - app/assets/javascripts/spree/frontend/process_razorpay.js
107
111
  - app/assets/javascripts/spree/frontend/spree_razorpay.js
108
112
  - app/controllers/concerns/spree/razor_pay.rb