@bigbinary/neeto-payments-frontend 4.0.4 → 4.0.6

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.
Files changed (69) hide show
  1. package/README.md +798 -541
  2. package/app/javascript/src/translations/de.json +3 -1
  3. package/app/javascript/src/translations/es.json +3 -1
  4. package/app/javascript/src/translations/fr.json +3 -1
  5. package/dist/AccountsDashboard.js +11 -11
  6. package/dist/AccountsDashboard.js.map +1 -1
  7. package/dist/AdminCancelRecurringPaymentButton.js +1 -1
  8. package/dist/CashPaymentButton.js +2 -2
  9. package/dist/ConfirmCashPaymentButton.js +2 -2
  10. package/dist/{CopyButtonWrapper-SoJkwX-d.js → CopyButtonWrapper-B79WRogM.js} +2 -2
  11. package/dist/{CopyButtonWrapper-SoJkwX-d.js.map → CopyButtonWrapper-B79WRogM.js.map} +1 -1
  12. package/dist/CustomerCancelRecurringPaymentForm.js +1 -1
  13. package/dist/{ExportModal-CWKMcZgh.js → ExportModal-B4zqaXJ1.js} +2 -2
  14. package/dist/{ExportModal-CWKMcZgh.js.map → ExportModal-B4zqaXJ1.js.map} +1 -1
  15. package/dist/ManualUpiConnect.js +1 -1
  16. package/dist/ManualUpiPayment.js +2 -2
  17. package/dist/ManualUpiPaymentConfirmButton.js +2 -2
  18. package/dist/ManualUpiPaymentRejectButton.js +2 -2
  19. package/dist/PaymentsDashboard.js +3 -3
  20. package/dist/PayoutsDashboard.js +12 -12
  21. package/dist/PayoutsDashboard.js.map +1 -1
  22. package/dist/PayoutsPage.js +4 -4
  23. package/dist/RazorpayPaymentButton.js +2 -2
  24. package/dist/RecurringPaymentSettings.js +1 -1
  25. package/dist/RefundsDashboard.js +3 -3
  26. package/dist/SplitTransfersDashboard.js +3 -3
  27. package/dist/TaxesDashboard.js +1 -1
  28. package/dist/buildStripeTransactionLink.js +1 -1
  29. package/dist/cjs/AccountsDashboard.js +9 -9
  30. package/dist/cjs/AccountsDashboard.js.map +1 -1
  31. package/dist/cjs/{CopyButtonWrapper-Ds1k64E0.js → CopyButtonWrapper-CzQmYDby.js} +1 -2
  32. package/dist/cjs/{CopyButtonWrapper-Ds1k64E0.js.map → CopyButtonWrapper-CzQmYDby.js.map} +1 -1
  33. package/dist/cjs/PaymentsDashboard.js +1 -1
  34. package/dist/cjs/PayoutsDashboard.js +9 -9
  35. package/dist/cjs/PayoutsDashboard.js.map +1 -1
  36. package/dist/cjs/PayoutsPage.js +2 -2
  37. package/dist/cjs/RefundsDashboard.js +1 -1
  38. package/dist/cjs/SplitTransfersDashboard.js +1 -1
  39. package/dist/cjs/index.js +3 -4
  40. package/dist/cjs/index.js.map +1 -1
  41. package/dist/cjs/{renderFunctions-5a8kYG9p.js → renderFunctions-9xNgMpUY.js} +2 -2
  42. package/dist/cjs/{renderFunctions-5a8kYG9p.js.map → renderFunctions-9xNgMpUY.js.map} +1 -1
  43. package/dist/constants.js +1 -1
  44. package/dist/{dashboard-BIedGLbE.js → dashboard-W7nZb7Nt.js} +2 -2
  45. package/dist/{dashboard-BIedGLbE.js.map → dashboard-W7nZb7Nt.js.map} +1 -1
  46. package/dist/getAmountInSmallestCurrencyUnit.js +1 -1
  47. package/dist/getAmountWithAppliedTax.js +1 -1
  48. package/dist/getFormattedAmount.js +1 -1
  49. package/dist/getFormattedTaxAmount.js +1 -1
  50. package/dist/getFormattedTipAmount.js +1 -1
  51. package/dist/getQrCodeValue.js +1 -1
  52. package/dist/getTaxAmount.js +1 -1
  53. package/dist/getTipAmount.js +1 -1
  54. package/dist/{index-Cw8BnbrE.js → index-DrwJCsVB.js} +2 -2
  55. package/dist/{index-Cw8BnbrE.js.map → index-DrwJCsVB.js.map} +1 -1
  56. package/dist/index.js +9 -12
  57. package/dist/index.js.map +1 -1
  58. package/dist/{renderFunctions-CEWqSB96.js → renderFunctions-CwG8PO6s.js} +4 -4
  59. package/dist/{renderFunctions-CEWqSB96.js.map → renderFunctions-CwG8PO6s.js.map} +1 -1
  60. package/dist/{usePaymentApi-AuXKzJ-d.js → usePaymentApi--FTQFayz.js} +2 -2
  61. package/dist/{usePaymentApi-AuXKzJ-d.js.map → usePaymentApi--FTQFayz.js.map} +1 -1
  62. package/dist/{usePaymentApi-DSL5iVNT.js → usePaymentApi-CnXIy7y7.js} +2 -2
  63. package/dist/{usePaymentApi-DSL5iVNT.js.map → usePaymentApi-CnXIy7y7.js.map} +1 -1
  64. package/dist/{usePaymentApi-CditWIud.js → usePaymentApi-D57hcC0x.js} +2 -2
  65. package/dist/{usePaymentApi-CditWIud.js.map → usePaymentApi-D57hcC0x.js.map} +1 -1
  66. package/dist/{usePlatformApi-CvRR6Wi5.js → usePlatformApi-CG6LhSj3.js} +3 -3
  67. package/dist/{usePlatformApi-CvRR6Wi5.js.map → usePlatformApi-CG6LhSj3.js.map} +1 -1
  68. package/dist/useRazorpayPayment.js +2 -2
  69. package/package.json +11 -11
package/README.md CHANGED
@@ -1,64 +1,72 @@
1
1
  # neeto-payments-nano
2
2
 
3
- The `neeto-payments-nano` is a comprehensive payment processing solution designed for the Neeto ecosystem. Implemented as a Ruby on Rails engine with associated React frontend components (`@bigbinary/neeto-payments-frontend`), it provides a unified interface for managing payments across different providers, abstracting away provider-specific complexities.
3
+ The `neeto-payments-nano` is a comprehensive payment processing solution
4
+ designed for the Neeto ecosystem. Implemented as a Ruby on Rails engine with
5
+ associated React frontend components (`@bigbinary/neeto-payments-frontend`), it
6
+ provides a unified interface for managing payments across different providers,
7
+ abstracting away provider-specific complexities.
4
8
 
5
9
  This engine enables host applications to:
6
10
 
7
- - Integrate with multiple payment providers (Stripe, Razorpay, UPI).
8
- - Process payments.
9
- - Handle payment splits for marketplace scenarios (Stripe).
10
- - Manage refunds.
11
- - Store and reuse payment methods securely (optional).
12
- - Configure fee structures and apply taxes/discounts.
13
- - Provide administrative dashboards for monitoring transactions, refunds, payouts, and accounts.
11
+ - Integrate with multiple payment providers (Stripe, Razorpay, UPI).
12
+ - Process payments.
13
+ - Handle payment splits for marketplace scenarios (Stripe).
14
+ - Manage refunds.
15
+ - Store and reuse payment methods securely (optional).
16
+ - Configure fee structures and apply taxes/discounts.
17
+ - Provide administrative dashboards for monitoring transactions, refunds,
18
+ payouts, and accounts.
14
19
 
15
20
  # Table of Contents
16
21
 
17
- - [Installation (Backend Engine)](#installation-backend-engine)
18
- - [1. Add the Gem](#1-add-the-gem)
19
- - [2. Install Gems](#2-install-gems)
20
- - [3. Install Migrations](#3-install-migrations)
21
- - [4. Run Migrations](#4-run-migrations)
22
- - [5. Mount the Engine](#5-mount-the-engine)
23
- - [Configuration (Backend Engine)](#configuration-backend-engine)
24
- - [1. Initializer](#1-initializer)
25
- - [2. Model Associations](#2-model-associations)
26
- - [3. Secrets and Credentials](#3-secrets-and-credentials)
27
- - [4. Stripe Connect Signup](#4-stripe-connect-signup)
28
- - [5. OAuth Callback URI Registration](#5-oauth-callback-uri-registration)
29
- - [Frontend Integration](#frontend-integration)
30
- - [1. Install Frontend Package](#1-install-frontend-package)
31
- - [2. Install Peer Dependencies](#2-install-peer-dependencies)
32
- - [3. Components](#3-components)
33
- - [4. Hooks](#4-hooks)
34
- - [5. Constants](#5-constants)
35
- - [6. API Calls - Specify Providers](#4-api-calls---specify-providers)
36
- - [Core Concepts](#core-concepts)
37
- - [Webhook Handling](#webhook-handling)
38
- - [Development Environment Setup](#development-environment-setup)
39
- - [1. Tunneling](#1-tunneling)
40
- - [2. Stripe Webhook Setup (Manual)](#2-stripe-webhook-setup-manual)
41
- - [3. Razorpay Webhook Setup (Manual)](#3-razorpay-webhook-setup-manual)
42
- - [Authentication (JWT for OAuth)](#authentication-jwt-for-oauth)
43
- - [Callbacks](#callbacks)
44
- - [Mandatory Callbacks](#mandatory-callbacks)
45
- - [Optional Callbacks (Implement as needed)](#optional-callbacks-implement-as-needed)
46
- - [Exposed Entities](#exposed-entities)
47
- - [API Endpoints](#api-endpoints)
48
- - [Incineration Concern](#incineration-concern)
49
- - [Deprecated Patterns](#deprecated-patterns)
50
- - [Development Environment Setup](#development-environment-setup-1)
51
- - [Helper methods](#helper-methods)
52
- - [Testing & Debugging](#testing--debugging)
53
- - [Gotchas & Tips](#gotchas--tips)
54
- - [Publishing](#publishing)
22
+ - [Installation (Backend Engine)](#installation-backend-engine)
23
+ - [1. Add the Gem](#1-add-the-gem)
24
+ - [2. Install Gems](#2-install-gems)
25
+ - [3. Install Migrations](#3-install-migrations)
26
+ - [4. Run Migrations](#4-run-migrations)
27
+ - [5. Mount the Engine](#5-mount-the-engine)
28
+ - [Configuration (Backend Engine)](#configuration-backend-engine)
29
+ - [1. Initializer](#1-initializer)
30
+ - [2. Model Associations](#2-model-associations)
31
+ - [3. Secrets and Credentials](#3-secrets-and-credentials)
32
+ - [4. Stripe Connect Signup](#4-stripe-connect-signup)
33
+ - [5. OAuth Callback URI Registration](#5-oauth-callback-uri-registration)
34
+ - [Frontend Integration](#frontend-integration)
35
+ - [1. Install Frontend Package](#1-install-frontend-package)
36
+ - [2. Install Peer Dependencies](#2-install-peer-dependencies)
37
+ - [3. Components](#3-components)
38
+ - [4. Hooks](#4-hooks)
39
+ - [5. Constants](#5-constants)
40
+ - [6. API Calls - Specify Providers](#4-api-calls---specify-providers)
41
+ - [Core Concepts](#core-concepts)
42
+ - [Webhook Handling](#webhook-handling)
43
+ - [Development Environment Setup](#development-environment-setup)
44
+ - [1. Tunneling](#1-tunneling)
45
+ - [2. Stripe Webhook Setup (Manual)](#2-stripe-webhook-setup-manual)
46
+ - [3. Razorpay Webhook Setup (Manual)](#3-razorpay-webhook-setup-manual)
47
+ - [Authentication (JWT for OAuth)](#authentication-jwt-for-oauth)
48
+ - [Callbacks](#callbacks)
49
+ - [Mandatory Callbacks](#mandatory-callbacks)
50
+ - [Optional Callbacks (Implement as needed)](#optional-callbacks-implement-as-needed)
51
+ - [Exposed Entities](#exposed-entities)
52
+ - [API Endpoints](#api-endpoints)
53
+ - [Incineration Concern](#incineration-concern)
54
+ - [Deprecated Patterns](#deprecated-patterns)
55
+ - [Development Environment Setup](#development-environment-setup-1)
56
+ - [Helper methods](#helper-methods)
57
+ - [Testing & Debugging](#testing--debugging)
58
+ - [Gotchas & Tips](#gotchas--tips)
59
+ - [Publishing](#publishing)
55
60
 
56
61
  ## Installation (Backend Engine)
57
62
 
58
- Follow these steps to integrate the `neeto-payments-engine` into your host Rails application:
63
+ Follow these steps to integrate the `neeto-payments-engine` into your host Rails
64
+ application:
59
65
 
60
66
  ### 1. Add the Gem
67
+
61
68
  Add the gem to your application's `Gemfile`:
69
+
62
70
  ```ruby
63
71
  # Gemfile
64
72
  source "NEETO_GEM_SERVER_URL" do
@@ -67,37 +75,51 @@ end
67
75
  ```
68
76
 
69
77
  ### 2. Install Gems
78
+
70
79
  Run bundler to install the gem and its dependencies:
80
+
71
81
  ```bash
72
82
  bundle install
73
83
  ```
74
84
 
75
85
  ### 3. Install Migrations
76
- Copy the engine's database migrations into your host application. **This step is crucial.**
86
+
87
+ Copy the engine's database migrations into your host application. **This step is
88
+ crucial.**
89
+
77
90
  ```bash
78
91
  bundle exec rails neeto_payments_engine:install:migrations
79
92
  ```
80
93
 
81
94
  ### 4. Run Migrations
95
+
82
96
  Apply the migrations to your database:
97
+
83
98
  ```bash
84
99
  bundle exec rails db:migrate
85
100
  ```
86
101
 
87
102
  ### 5. Mount the Engine
103
+
88
104
  Add the engine's routes to your application's `config/routes.rb`:
105
+
89
106
  ```ruby
90
107
  # config/routes.rb
91
108
  mount NeetoPaymentsEngine::Engine, at: "/payments" # Or your preferred mount point
92
109
  ```
110
+
93
111
  This makes the engine's API endpoints available, by default under `/payments`.
94
112
 
95
- Once the installation is done, we have to do some configuration for the engine to work as intended. Please go through the whole README to complete the process of setting up `neeto-payments-nano` in your host app.
113
+ Once the installation is done, we have to do some configuration for the engine
114
+ to work as intended. Please go through the whole README to complete the process
115
+ of setting up `neeto-payments-nano` in your host app.
96
116
 
97
117
  ## Configuration (Backend Engine)
98
118
 
99
119
  ### 1. Initializer
100
- Create an initializer file `config/initializers/neeto_payments_engine.rb` to configure the engine:
120
+
121
+ Create an initializer file `config/initializers/neeto_payments_engine.rb` to
122
+ configure the engine:
101
123
 
102
124
  ```ruby
103
125
  # config/initializers/neeto_payments_engine.rb
@@ -113,10 +135,23 @@ NeetoPaymentsEngine.providers_holdable_class = {
113
135
  upi: "Organization" # Typically Organization that owns the UPI VPA list
114
136
  }
115
137
  ```
116
- - **`providers_holdable_class`:** This hash maps each payment provider type supported by the engine to the class name (as a String) of the model in your host application that will "hold" or own the integration for that provider. The engine uses polymorphic associations (`holdable_type`, `holdable_id`) based on this setting to link payment provider accounts (like `Stripe::Account`, `Integrations::Razorpay`) to your application's models. Failing to configure this correctly will result in errors when the engine attempts to find or create payment provider integrations. Example: In NeetoCal each `User` can connect their own `stripe_standard` account, but in NeetoPay, only one `stripe_standard` account can exist in an `Organization`.
138
+
139
+ - **`providers_holdable_class`:** This hash maps each payment provider type
140
+ supported by the engine to the class name (as a String) of the model in your
141
+ host application that will "hold" or own the integration for that provider.
142
+ The engine uses polymorphic associations (`holdable_type`, `holdable_id`)
143
+ based on this setting to link payment provider accounts (like
144
+ `Stripe::Account`, `Integrations::Razorpay`) to your application's models.
145
+ Failing to configure this correctly will result in errors when the engine
146
+ attempts to find or create payment provider integrations. Example: In NeetoCal
147
+ each `User` can connect their own `stripe_standard` account, but in NeetoPay,
148
+ only one `stripe_standard` account can exist in an `Organization`.
117
149
 
118
150
  ### 2. Model Associations
119
- Ensure the models specified in `providers_holdable_class` have the correct `has_one` or `has_many` associations defined to link to the engine's integration models. Adapt the following examples based on your configuration:
151
+
152
+ Ensure the models specified in `providers_holdable_class` have the correct
153
+ `has_one` or `has_many` associations defined to link to the engine's integration
154
+ models. Adapt the following examples based on your configuration:
120
155
 
121
156
  ```ruby
122
157
  # app/models/organization.rb (Example if Organization is a holdable)
@@ -152,7 +187,10 @@ class User < ApplicationRecord
152
187
  end
153
188
  ```
154
189
 
155
- Add associations to your **Payable** models (e.g., `Invoice`, `Booking`, `Meeting` - the item being paid for) - you don't need to add this until you create your `Payable` models in your host app:
190
+ Add associations to your **Payable** models (e.g., `Invoice`, `Booking`,
191
+ `Meeting` - the item being paid for) - you don't need to add this until you
192
+ create your `Payable` models in your host app:
193
+
156
194
  ```ruby
157
195
  # app/models/invoice.rb (Example Payable Model)
158
196
  class Invoice < ApplicationRecord
@@ -165,125 +203,156 @@ end
165
203
  ```
166
204
 
167
205
  ### 3. Secrets and Credentials
168
- Configure API keys and secrets securely using environment variables and secrets file.
169
-
170
- **Essential ENV variables for `neeto-payments-engine`:**
171
-
172
- * **`.env.development` (Commit this file):** Contains non-sensitive defaults, placeholders, or development-specific configurations.
173
- ```dotenv
174
- # .env.development
175
-
176
- # Base URL of your host application (adjust port if needed)
177
- APP_URL='http://app.lvh.me:<APP_PORT>/'
178
206
 
179
- # --- Stripe ---
180
- # Base URL for OAuth callback (using tunnelto 'connect' subdomain for dev)
181
- STRIPE_CALLBACK_BASE_URL="https://connect.tunnelto.dev" # Or your tunnel URL
207
+ Configure API keys and secrets securely using environment variables and secrets
208
+ file.
182
209
 
183
- # --- Razorpay (if used) ---
184
- RAZORPAY_CLIENT_SECRET="rzp_test_..." # Test Key ID can often be committed
185
- RAZORPAY_CLIENT_ID="..." # OAuth Client ID is usually safe
186
- RAZORPAY_WEBHOOK_SECRET=".." # webhook secret
187
- RAZORPAY_CALLBACK_BASE_URL="https://connect.tunnelto.dev" # Or your tunnel URL
188
- ```
189
-
190
- * **`.env.local` (Add this file to `.gitignore` - DO NOT COMMIT):** Contains sensitive API keys, secrets, and private keys. This file overrides values in `.env.development`.
191
-
192
- ```dotenv
193
- # .env.local (DO NOT COMMIT THIS FILE)
194
-
195
- # --- Stripe ---
196
- STRIPE_SECRET_KEY="sk_test_..." # Your TEST Stripe Secret Key
197
- STRIPE_WEBHOOK_SECRET="whsec_..." # Your TEST Stripe Webhook Signing Secret (from manual setup)
198
- # Can find this from Stripe dashboard
199
- STRIPE_PUBLISHABLE_KEY="pk_test_..."
200
- # First sign up for Stripe Connect, then go to OAuth section of Stripe
201
- # Connect to get the client id. You'd also have to register OAuth callback
202
- # URI in that page.
203
- STRIPE_CLIENT_ID="ca_..."
204
-
205
- # --- Razorpay (if used) ---
206
- RAZORPAY_KEY_SECRET="..." # Your TEST Razorpay Key Secret
207
- RAZORPAY_WEBHOOK_SECRET="..." # Your TEST Razorpay Webhook Secret (you set this)
208
- RAZORPAY_CLIENT_SECRET="..." # Your TEST Razorpay OAuth Client Secret
209
-
210
- # --- JWT Keys ---
211
- # Generate using: openssl genrsa -out private.pem 2048 && openssl rsa -in private.pem -pubout -out public.pem
212
- # Copy the *entire* content including -----BEGIN...----- and -----END...----- lines.
213
- CONNECT_PRIVATE_KEY="-----BEGIN RSA PRIVATE KEY-----
214
- ...your private key content...
215
- -----END RSA PRIVATE KEY-----"
216
- CONNECT_PUBLIC_KEY="-----BEGIN PUBLIC KEY-----
217
- ...your public key content...
218
- -----END PUBLIC KEY-----"
219
-
220
- # --- Optional ---
221
- # OPEN_EXCHANGE_RATE_API_KEY="your_actual_key" # Sensitive API key
222
- ```
223
-
224
- **Loading Secrets:** Ensure these secrets are loaded into `Rails.application.secrets`. An example `config/secrets.yml` structure:
225
-
226
- ```yaml
227
- # config/secrets.yml
228
- default: &default
229
- host: <%= ENV['APP_URL'] %>
230
- stripe:
231
- publishable_key: <%= ENV['STRIPE_PUBLISHABLE_KEY'] %>
232
- secret_key: <%= ENV['STRIPE_SECRET_KEY'] %>
233
- client_id: <%= ENV['STRIPE_CLIENT_ID'] %>
234
- webhooks:
235
- secret: <%= ENV['STRIPE_WEBHOOK_SECRET'] %>
236
- razorpay:
237
- key_id: <%= ENV["RAZORPAY_KEY_ID"] %>
238
- key_secret: <%= ENV["RAZORPAY_KEY_SECRET"] %>
239
- client_id: <%= ENV["RAZORPAY_CLIENT_ID"] %>
240
- client_secret: <%= ENV["RAZORPAY_CLIENT_SECRET"] %>
241
- oauth_callback_base_url: <%= ENV["RAZORPAY_CALLBACK_BASE_URL"] %>
242
- webhook:
243
- secret: <%= ENV["RAZORPAY_WEBHOOK_SECRET"] %>
244
- jwt:
245
- connect_private_key: <%= ENV['CONNECT_PRIVATE_KEY'].inspect %>
246
- connect_public_key: <%= ENV['CONNECT_PUBLIC_KEY'].inspect %>
247
-
248
- # Optional: If using Open Exchange Rates for currency conversion
249
- open_exchange_rates:
250
- api_key: <%= ENV["OPEN_EXCHANGE_RATE_API_KEY"] %>
251
- # ... other secrets ...
252
-
253
- development:
254
- <<: *default
255
- # Development specific overrides
256
-
257
- production:
258
- <<: *default
259
- # Production specific overrides (use credentials!)
260
- ```
210
+ **Essential ENV variables for `neeto-payments-engine`:**
261
211
 
262
- **Secrets Management:**
263
- - **Development:** Use `.env.local` (which is typically gitignored) to store sensitive keys locally.
264
- - **Staging/Production:** Use environment variables managed by your deployment platform (e.g., NeetoDeploy, Heroku Config Vars) or Rails encrypted credentials. **Do not commit secrets directly into your repository.**
212
+ - **`.env.development` (Commit this file):** Contains non-sensitive defaults,
213
+ placeholders, or development-specific configurations.
214
+
215
+ ```dotenv
216
+ # .env.development
217
+
218
+ # Base URL of your host application (adjust port if needed)
219
+ APP_URL='http://app.lvh.me:<APP_PORT>/'
220
+
221
+ # --- Stripe ---
222
+ # Base URL for OAuth callback (using tunnelto 'connect' subdomain for dev)
223
+ STRIPE_CALLBACK_BASE_URL="https://connect.tunnelto.dev" # Or your tunnel URL
224
+
225
+ # --- Razorpay (if used) ---
226
+ RAZORPAY_CLIENT_SECRET="rzp_test_..." # Test Key ID can often be committed
227
+ RAZORPAY_CLIENT_ID="..." # OAuth Client ID is usually safe
228
+ RAZORPAY_WEBHOOK_SECRET=".." # webhook secret
229
+ RAZORPAY_CALLBACK_BASE_URL="https://connect.tunnelto.dev" # Or your tunnel URL
230
+ ```
231
+
232
+ - **`.env.local` (Add this file to `.gitignore` - DO NOT COMMIT):** Contains
233
+ sensitive API keys, secrets, and private keys. This file overrides values in
234
+ `.env.development`.
235
+
236
+ ```dotenv
237
+ # .env.local (DO NOT COMMIT THIS FILE)
238
+
239
+ # --- Stripe ---
240
+ STRIPE_SECRET_KEY="sk_test_..." # Your TEST Stripe Secret Key
241
+ STRIPE_WEBHOOK_SECRET="whsec_..." # Your TEST Stripe Webhook Signing Secret (from manual setup)
242
+ # Can find this from Stripe dashboard
243
+ STRIPE_PUBLISHABLE_KEY="pk_test_..."
244
+ # First sign up for Stripe Connect, then go to OAuth section of Stripe
245
+ # Connect to get the client id. You'd also have to register OAuth callback
246
+ # URI in that page.
247
+ STRIPE_CLIENT_ID="ca_..."
248
+
249
+ # --- Razorpay (if used) ---
250
+ RAZORPAY_KEY_SECRET="..." # Your TEST Razorpay Key Secret
251
+ RAZORPAY_WEBHOOK_SECRET="..." # Your TEST Razorpay Webhook Secret (you set this)
252
+ RAZORPAY_CLIENT_SECRET="..." # Your TEST Razorpay OAuth Client Secret
253
+
254
+ # --- JWT Keys ---
255
+ # Generate using: openssl genrsa -out private.pem 2048 && openssl rsa -in private.pem -pubout -out public.pem
256
+ # Copy the *entire* content including -----BEGIN...----- and -----END...----- lines.
257
+ CONNECT_PRIVATE_KEY="-----BEGIN RSA PRIVATE KEY-----
258
+ ...your private key content...
259
+ -----END RSA PRIVATE KEY-----"
260
+ CONNECT_PUBLIC_KEY="-----BEGIN PUBLIC KEY-----
261
+ ...your public key content...
262
+ -----END PUBLIC KEY-----"
263
+
264
+ # --- Optional ---
265
+ # OPEN_EXCHANGE_RATE_API_KEY="your_actual_key" # Sensitive API key
266
+ ```
267
+
268
+ **Loading Secrets:** Ensure these secrets are loaded into
269
+ `Rails.application.secrets`. An example `config/secrets.yml` structure:
270
+
271
+ ```yaml
272
+ # config/secrets.yml
273
+ default: &default
274
+ host: <%= ENV['APP_URL'] %>
275
+ stripe:
276
+ publishable_key: <%= ENV['STRIPE_PUBLISHABLE_KEY'] %>
277
+ secret_key: <%= ENV['STRIPE_SECRET_KEY'] %>
278
+ client_id: <%= ENV['STRIPE_CLIENT_ID'] %>
279
+ webhooks:
280
+ secret: <%= ENV['STRIPE_WEBHOOK_SECRET'] %>
281
+ razorpay:
282
+ key_id: <%= ENV["RAZORPAY_KEY_ID"] %>
283
+ key_secret: <%= ENV["RAZORPAY_KEY_SECRET"] %>
284
+ client_id: <%= ENV["RAZORPAY_CLIENT_ID"] %>
285
+ client_secret: <%= ENV["RAZORPAY_CLIENT_SECRET"] %>
286
+ oauth_callback_base_url: <%= ENV["RAZORPAY_CALLBACK_BASE_URL"] %>
287
+ webhook:
288
+ secret: <%= ENV["RAZORPAY_WEBHOOK_SECRET"] %>
289
+ jwt:
290
+ connect_private_key: <%= ENV['CONNECT_PRIVATE_KEY'].inspect %>
291
+ connect_public_key: <%= ENV['CONNECT_PUBLIC_KEY'].inspect %>
292
+
293
+ # Optional: If using Open Exchange Rates for currency conversion
294
+ open_exchange_rates:
295
+ api_key: <%= ENV["OPEN_EXCHANGE_RATE_API_KEY"] %>
296
+ # ... other secrets ...
297
+
298
+ development:
299
+ <<: *default
300
+ # Development specific overrides
301
+
302
+ production:
303
+ <<: *default
304
+ # Production specific overrides (use credentials!)
305
+ ```
306
+
307
+ **Secrets Management:**
308
+
309
+ - **Development:** Use `.env.local` (which is typically gitignored) to store
310
+ sensitive keys locally.
311
+ - **Staging/Production:** Use environment variables managed by your deployment
312
+ platform (e.g., NeetoDeploy, Heroku Config Vars) or Rails encrypted
313
+ credentials. **Do not commit secrets directly into your repository.**
265
314
 
266
315
  ### 4. Stripe Connect Signup
267
- You **must** sign up for Stripe Connect via the Stripe dashboard, even if you only intend to use a Stripe Platform account. This registration enables the necessary APIs for account management and OAuth flows used by the engine.
316
+
317
+ You **must** sign up for Stripe Connect via the Stripe dashboard, even if you
318
+ only intend to use a Stripe Platform account. This registration enables the
319
+ necessary APIs for account management and OAuth flows used by the engine.
268
320
 
269
321
  ### 5. OAuth Callback URI Registration
270
- Register the following callback URIs in your respective payment provider dashboards:
271
- * **Stripe:** `https://<your_connect_subdomain_or_app_domain>/payments/api/v1/public/stripe/oauth/callback`
272
- * `<your_connect_subdomain_or_app_domain>`: This should be the publicly accessible URL that routes to your Rails app. In development, this is typically your `tunnelto` URL using the `connect` subdomain (e.g., `https://connect.tunnelto.dev`). In production, it might be your main application domain or a dedicated subdomain.
273
- * **Razorpay:** `https://<your_razorpay_oauth_base_url>/payments/api/v1/public/razorpay/oauth/callback`
274
- * `<your_razorpay_oauth_base_url>`: This must match the value you configured for `RAZORPAY_OAUTH_CALLBACK_BASE_URL`. Use the `connect` subdomain via `tunnelto` in development.
322
+
323
+ Register the following callback URIs in your respective payment provider
324
+ dashboards:
325
+
326
+ - **Stripe:**
327
+ `https://<your_connect_subdomain_or_app_domain>/payments/api/v1/public/stripe/oauth/callback`
328
+ - `<your_connect_subdomain_or_app_domain>`: This should be the publicly
329
+ accessible URL that routes to your Rails app. In development, this is
330
+ typically your `tunnelto` URL using the `connect` subdomain (e.g.,
331
+ `https://connect.tunnelto.dev`). In production, it might be your main
332
+ application domain or a dedicated subdomain.
333
+ - **Razorpay:**
334
+ `https://<your_razorpay_oauth_base_url>/payments/api/v1/public/razorpay/oauth/callback`
335
+ - `<your_razorpay_oauth_base_url>`: This must match the value you configured
336
+ for `RAZORPAY_OAUTH_CALLBACK_BASE_URL`. Use the `connect` subdomain via
337
+ `tunnelto` in development.
275
338
 
276
339
  ## Frontend Integration
277
340
 
278
- Integrate the React components provided by the `@bigbinary/neeto-payments-frontend` package.
341
+ Integrate the React components provided by the
342
+ `@bigbinary/neeto-payments-frontend` package.
279
343
 
280
344
  ### 1. Install Frontend Package
345
+
281
346
  ```bash
282
347
  yarn add @bigbinary/neeto-payments-frontend
283
348
  ```
284
349
 
285
350
  ### 2. Install Peer Dependencies
286
- If the host app already includes all of the following peer deps, then you don't have to install anything explicitly. Use the latest version of each of these peer dependencies if you need to install:
351
+
352
+ If the host app already includes all of the following peer deps, then you don't
353
+ have to install anything explicitly. Use the latest version of each of these
354
+ peer dependencies if you need to install:
355
+
287
356
  ```bash
288
357
  # DO NOT INSTALL THE VERSIONS MENTIONED BELOW AS IT MIGHT BE OUTDATED.
289
358
  # ALWAYS PREFER INSTALLING THE LATEST VERSIONS.
@@ -291,344 +360,398 @@ If the host app already includes all of the following peer deps, then you don't
291
360
  # what's causing the breakage.
292
361
  yarn add @babel/runtime@7.26.10 @bigbinary/neeto-cist@1.0.15 @bigbinary/neeto-commons-frontend@4.13.28 @bigbinary/neeto-editor@1.45.23 @bigbinary/neeto-filters-frontend@4.3.15 @bigbinary/neeto-icons@1.20.31 @bigbinary/neeto-molecules@3.16.1 @bigbinary/neetoui@8.2.75 @honeybadger-io/js@6.10.1 @honeybadger-io/react@6.1.25 @tailwindcss/container-queries@^0.1.1 @tanstack/react-query@5.59.20 @tanstack/react-query-devtools@5.59.20 antd@5.22.0 axios@1.8.2 buffer@^6.0.3 classnames@2.5.1 crypto-browserify@3.12.1 dompurify@^3.2.4 formik@2.4.6 https-browserify@1.0.0 i18next@22.5.1 js-logger@1.6.1 mixpanel-browser@^2.45.0 os-browserify@0.3.0 path-browserify@^1.0.1 qs@^6.11.2 ramda@0.29.0 react@18.2.0 react-dom@18.2.0 react-helmet@^6.1.0 react-i18next@12.3.1 react-router-dom@5.3.3 react-toastify@8.0.2 source-map-loader@4.0.1 stream-browserify@^3.0.0 stream-http@3.2.0 tailwindcss@3.4.14 tty-browserify@0.0.1 url@^0.11.0 util@^0.12.5 vm-browserify@1.1.2 yup@0.32.11 zustand@4.3.2
293
362
  ```
294
- *Note: Carefully manage potential version conflicts with your host application.*
363
+
364
+ _Note: Carefully manage potential version conflicts with your host application._
295
365
 
296
366
  ### 3. Components
297
- Import components into your React application as needed.
298
367
 
299
- 1. `TaxesDashboard` ([source code](https://github.com/bigbinary/neeto-payments-nano/blob/main/app/javascript/src/components/TaxesDashboard/index.jsx))
300
-
301
- **Props**
302
- - `feeId`: The unique identifier for the tax fee.
303
- - `breadcrumbs`: Data for rendering the header breadcrumbs.
304
- - `paymentUrl` _(optional)_: The URL of the pricing page to redirect users if payments are not enabled.
305
- - `headerSize` _(optional)_: Specifies the size of the header. Default size is `small`
306
- - `noDataHelpText` _(optional)_: Help text displayed when there is no data available.
307
- - `onTaxesChange` _(optional)_: Callback function triggered after performing actions in the taxes dashboard.
308
- - `titleHelpPopoverProps`_(optional)_: Data for the header help popover.
309
-
310
- **Usage**
311
- ```jsx
312
- import React from "react";
313
- import { TaxesDashboard } from "@bigbinary/neeto-payments-frontend";
314
-
315
- const App = () => {
316
- return (
317
- <TaxesDashboard
318
- feeId={fee.id}
319
- breadcrumbs={[{text: "Settings" ,link: routes.admin.form.settings}]}
320
- />
321
- );
322
- };
323
- ```
368
+ Import components into your React application as needed.
324
369
 
325
- 2. `PaymentsDashboard` ([source code](https://github.com/bigbinary/neeto-payments-nano/blob/main/app/javascript/src/components/PaymentsDashboard/index.jsx))
326
-
327
- **Props**
328
- - `dashboardKind`: Accepts either `connected` or `platform` (default: `platform`). Use `connected` to display payments related to split transfers. Use `platform` to display payments received from customers.
329
- - `payableEntityColumns`: To specify the columns from the payable entity
330
- which need to be additionally displayed. It is an optional prop that defaults to `[]` if not specified.
331
- - `searchProps`: Allows specifying additional columns to be included in the search functionality. By default, only the `identifier` column from the payments table is searchable.
332
- - `holdableIds`: Provide the holdable IDs for each payment provider when the holdable entity is not a `User` or `Organization` model.
333
-
334
- **Usage**
335
- ```jsx
336
- import React from "react";
337
- import { PaymentsDashboard } from "@bigbinary/neeto-payments-frontend";
338
-
339
- const App = () => {
340
-
341
- // neeto-filters-engine search prop syntax.
342
- const SEARCH_PROPS = {
343
- node: "bookings:payable.meeting.name",
344
- model: "Meeting",
345
- placeholder: "Search by identifier or meeting name",
346
- };
347
-
348
- // Only required if the payment provider holdable modal is not a User or Organization
349
- const holdableIds = { stripeStandard: formId, razorpay: formId }
350
-
351
- const payableEntityColumns = {
352
- title: "Submission",
353
- dataIndex: ["payable", "id"],
354
- key: "submission",
355
- ellipsis: true,
356
- width: "300px",,
357
- },
370
+ 1. `TaxesDashboard`
371
+ ([source code](https://github.com/bigbinary/neeto-payments-nano/blob/main/app/javascript/src/components/TaxesDashboard/index.jsx))
358
372
 
359
- return (
360
- <PaymentsDashboard
361
- {...{ payableEntityColumns, holdableIds }}
362
- searchProps={SEARCH_PROPS}
363
- />
364
- );
365
- };
366
- ```
367
- 3. `RefundsDashboard` ([source code](https://github.com/bigbinary/neeto-payments-nano/blob/main/app/javascript/src/components/RefundsDashboard/index.jsx))
373
+ **Props**
368
374
 
369
- **Props**
370
- - `payableEntityColumns`: To specify the columns from the payable entity
371
- which need to be additionally displayed. It is an optional prop that defaults to `[]` if not specified.
372
- - `searchProps`: Allows specifying additional columns to be included in the search functionality. By default, only the `identifier` column from the refunds table is searchable.
375
+ - `feeId`: The unique identifier for the tax fee.
376
+ - `breadcrumbs`: Data for rendering the header breadcrumbs.
377
+ - `paymentUrl` _(optional)_: The URL of the pricing page to redirect users if
378
+ payments are not enabled.
379
+ - `headerSize` _(optional)_: Specifies the size of the header. Default size
380
+ is `small`
381
+ - `noDataHelpText` _(optional)_: Help text displayed when there is no data
382
+ available.
383
+ - `onTaxesChange` _(optional)_: Callback function triggered after performing
384
+ actions in the taxes dashboard.
385
+ - `titleHelpPopoverProps`_(optional)_: Data for the header help popover.
373
386
 
374
387
  **Usage**
375
- ```jsx
376
- import React from "react";
377
- import { SplitTransfersDashboard } from "@bigbinary/neeto-payments-frontend";
378
-
379
- const App = () => {
380
-
381
- // neeto-filters-engine search prop syntax.
382
- const SEARCH_PROPS = {
383
- node: "bookings:payable.meeting.name",
384
- model: "Meeting",
385
- placeholder: "Search by identifier or meeting name",
386
- };
387
-
388
- const payableEntityColumns = {
389
- title: "Submission",
390
- dataIndex: ["payable", "id"],
391
- key: "submission",
392
- ellipsis: true,
393
- width: "300px",,
394
- },
395
-
396
- return (
397
- <SplitTransfersDashboard
398
- {...{ payableEntityColumns }}
399
- searchProps={SEARCH_PROPS}
400
- />
401
- );
402
- };
403
- ```
404
388
 
405
- 4. `SplitTransfersDashboard` ([source code](https://github.com/bigbinary/neeto-payments-nano/blob/main/app/javascript/src/components/SplitTransfersDashboard/index.jsx))
389
+ ```jsx
390
+ import React from "react";
391
+ import { TaxesDashboard } from "@bigbinary/neeto-payments-frontend";
392
+
393
+ const App = () => {
394
+ return (
395
+ <TaxesDashboard
396
+ feeId={fee.id}
397
+ breadcrumbs={[{ text: "Settings", link: routes.admin.form.settings }]}
398
+ />
399
+ );
400
+ };
401
+ ```
402
+
403
+ 2. `PaymentsDashboard`
404
+ ([source code](https://github.com/bigbinary/neeto-payments-nano/blob/main/app/javascript/src/components/PaymentsDashboard/index.jsx))
405
+
406
+ **Props**
407
+
408
+ - `dashboardKind`: Accepts either `connected` or `platform` (default:
409
+ `platform`). Use `connected` to display payments related to split
410
+ transfers. Use `platform` to display payments received from customers.
411
+ - `payableEntityColumns`: To specify the columns from the payable entity
412
+ which need to be additionally displayed. It is an optional prop that
413
+ defaults to `[]` if not specified.
414
+ - `searchProps`: Allows specifying additional columns to be included in the
415
+ search functionality. By default, only the `identifier` column from the
416
+ payments table is searchable.
417
+ - `holdableIds`: Provide the holdable IDs for each payment provider when the
418
+ holdable entity is not a `User` or `Organization` model.
406
419
 
407
- **Props**
408
- - `payableEntityColumns`: To specify the columns from the payable entity
409
- which need to be additionally displayed. It is an optional prop that defaults to `[]` if not specified.
410
- - `searchProps`: Allows specifying additional columns to be included in the search functionality. By default, only the `identifier` column from the payment splits table is searchable.
411
420
  **Usage**
412
- ```jsx
413
- import React from "react";
414
- import { RefundsDashboard } from "@bigbinary/neeto-payments-frontend";
415
-
416
- const App = () => {
417
-
418
- // neeto-filters-engine search prop syntax.
419
- const SEARCH_PROPS = {
420
- node: "bookings:payable.meeting.name",
421
- model: "Meeting",
422
- placeholder: "Search by identifier or meeting name",
423
- };
424
-
425
- const payableEntityColumns = {
426
- title: "Submission",
427
- dataIndex: ["payable", "id"],
428
- key: "submission",
429
- ellipsis: true,
430
- width: "300px",,
431
- },
432
421
 
433
- return (
434
- <RefundsDashboard
435
- {...{ payableEntityColumns }}
436
- searchProps={SEARCH_PROPS}
437
- />
438
- );
439
- };
440
- ```
422
+ ```jsx
423
+ import React from "react";
424
+ import { PaymentsDashboard } from "@bigbinary/neeto-payments-frontend";
425
+
426
+ const App = () => {
427
+
428
+ // neeto-filters-engine search prop syntax.
429
+ const SEARCH_PROPS = {
430
+ node: "bookings:payable.meeting.name",
431
+ model: "Meeting",
432
+ placeholder: "Search by identifier or meeting name",
433
+ };
434
+
435
+ // Only required if the payment provider holdable modal is not a User or Organization
436
+ const holdableIds = { stripeStandard: formId, razorpay: formId }
437
+
438
+ const payableEntityColumns = {
439
+ title: "Submission",
440
+ dataIndex: ["payable", "id"],
441
+ key: "submission",
442
+ ellipsis: true,
443
+ width: 300,
444
+ },
445
+
446
+ return (
447
+ <PaymentsDashboard
448
+ {...{ payableEntityColumns, holdableIds }}
449
+ searchProps={SEARCH_PROPS}
450
+ />
451
+ );
452
+ };
453
+ ```
454
+
455
+ 3. `RefundsDashboard`
456
+ ([source code](https://github.com/bigbinary/neeto-payments-nano/blob/main/app/javascript/src/components/RefundsDashboard/index.jsx))
457
+
458
+ **Props**
459
+
460
+ - `payableEntityColumns`: To specify the columns from the payable entity
461
+ which need to be additionally displayed. It is an optional prop that
462
+ defaults to `[]` if not specified.
463
+ - `searchProps`: Allows specifying additional columns to be included in the
464
+ search functionality. By default, only the `identifier` column from the
465
+ refunds table is searchable.
441
466
 
467
+ **Usage**
442
468
 
443
- 5. `AccountsDashboard` ([source code](https://github.com/bigbinary/neeto-payments-nano/blob/main/app/javascript/src/components/AccountsDashboard/index.jsx))
469
+ ```jsx
470
+ import React from "react";
471
+ import { SplitTransfersDashboard } from "@bigbinary/neeto-payments-frontend";
472
+
473
+ const App = () => {
474
+
475
+ // neeto-filters-engine search prop syntax.
476
+ const SEARCH_PROPS = {
477
+ node: "bookings:payable.meeting.name",
478
+ model: "Meeting",
479
+ placeholder: "Search by identifier or meeting name",
480
+ };
481
+
482
+ const payableEntityColumns = {
483
+ title: "Submission",
484
+ dataIndex: ["payable", "id"],
485
+ key: "submission",
486
+ ellipsis: true,
487
+ width: 300,
488
+ },
489
+
490
+ return (
491
+ <SplitTransfersDashboard
492
+ {...{ payableEntityColumns }}
493
+ searchProps={SEARCH_PROPS}
494
+ />
495
+ );
496
+ };
497
+ ```
498
+
499
+ 4. `SplitTransfersDashboard`
500
+ ([source code](https://github.com/bigbinary/neeto-payments-nano/blob/main/app/javascript/src/components/SplitTransfersDashboard/index.jsx))
501
+
502
+ **Props**
503
+
504
+ - `payableEntityColumns`: To specify the columns from the payable entity
505
+ which need to be additionally displayed. It is an optional prop that
506
+ defaults to `[]` if not specified.
507
+ - `searchProps`: Allows specifying additional columns to be included in the
508
+ search functionality. By default, only the `identifier` column from the
509
+ payment splits table is searchable. **Usage**
510
+
511
+ ```jsx
512
+ import React from "react";
513
+ import { RefundsDashboard } from "@bigbinary/neeto-payments-frontend";
514
+
515
+ const App = () => {
516
+
517
+ // neeto-filters-engine search prop syntax.
518
+ const SEARCH_PROPS = {
519
+ node: "bookings:payable.meeting.name",
520
+ model: "Meeting",
521
+ placeholder: "Search by identifier or meeting name",
522
+ };
523
+
524
+ const payableEntityColumns = {
525
+ title: "Submission",
526
+ dataIndex: ["payable", "id"],
527
+ key: "submission",
528
+ ellipsis: true,
529
+ width: 300,
530
+ },
531
+
532
+ return (
533
+ <RefundsDashboard
534
+ {...{ payableEntityColumns }}
535
+ searchProps={SEARCH_PROPS}
536
+ />
537
+ );
538
+ };
539
+ ```
540
+
541
+ 5. `AccountsDashboard`
542
+ ([source code](https://github.com/bigbinary/neeto-payments-nano/blob/main/app/javascript/src/components/AccountsDashboard/index.jsx))
444
543
 
445
544
  **Usage**
446
- ```jsx
447
- import React from "react";
448
- import { AccountsDashboard } from "@bigbinary/neeto-payments-frontend";
449
545
 
450
- const App = () => {
546
+ ```jsx
547
+ import React from "react";
548
+ import { AccountsDashboard } from "@bigbinary/neeto-payments-frontend";
451
549
 
452
- return (<AccountsDashboard />);
453
- };
454
- ```
550
+ const App = () => {
551
+ return <AccountsDashboard />;
552
+ };
553
+ ```
455
554
 
456
- 6. `PayoutsDashboard` ([source code](https://github.com/bigbinary/neeto-payments-nano/blob/main/app/javascript/src/components/PayoutsDashboard/index.jsx))
555
+ 6. `PayoutsDashboard`
556
+ ([source code](https://github.com/bigbinary/neeto-payments-nano/blob/main/app/javascript/src/components/PayoutsDashboard/index.jsx))
457
557
 
458
- **Props**
459
- - `isPlatformEnabled`: Indicates whether platform integration is enabled.
460
- - `payoutsPageRoute`: The route used to display detailed payout information.
558
+ **Props**
461
559
 
560
+ - `isPlatformEnabled`: Indicates whether platform integration is enabled.
561
+ - `payoutsPageRoute`: The route used to display detailed payout information.
462
562
 
463
563
  **Usage**
464
- ```jsx
465
- import React from "react";
466
- import { PayoutsDashboard } from "@bigbinary/neeto-payments-frontend";
467
-
468
- const App = () => {
469
-
470
- return (
471
- <PayoutsDashboard
472
- isPlatformEnabled={true}
473
- payoutsPageRoute={routes.admin.payments.payouts.show}
474
- />
475
- );
476
- };
477
- ```
478
- 7. `RazorpayPaymentButton` ([source code](https://github.com/bigbinary/neeto-payments-nano/blob/main/app/javascript/src/components/RazorpayPaymentButton.jsx))
479
-
480
- **Props**
481
- - `label`: The button label. Defaults to `Pay`.
482
- - `payableId`: The ID of the payable entity.
483
- - `discountCode`: The discount code to be applied, if any.
484
- - `email`: The customer's email address.
485
- - `name`: The customer's name.
486
- - `theme`: The theme configuration object.
487
- - `payableType`: The type of the payable entity.
488
- - `onBeforePayment`: A callback function triggered before the payment is initiated.
489
- - `onSuccessfulPayment`: A callback function triggered after a successful payment.
490
- - `onFailedPayment`: A callback function triggered after a failed payment.
491
-
492
- **Usage**
493
- ```jsx
494
- import React from "react";
495
- import { RazorpayPaymentButton } from "@bigbinary/neeto-payments-frontend";
496
-
497
- const App = () => {
498
-
499
- return (
500
- <RazorpayPaymentButton
501
- email={customer.email}
502
- name={customer.name}
503
- discountCode={discountCode.code}
504
- payableId={booking.id}
505
- theme={meeting.theme}
506
- />
507
- );
508
- };
509
- ```
510
-
511
- 8. `ConfirmUpiPaymentButton` ([source code](https://github.com/bigbinary/neeto-payments-nano/blob/main/app/javascript/src/components/ConfirmUpiPaymentButton/index.jsx))
512
564
 
513
- **Props**
514
- - `vpas`: A list of UPI IDs presented for the user to select during confirmation.
515
- - `identifier`: The unique identifier associated with the payment.
516
- - `paymentId`: The ID of the payment.
517
- - `onSuccess`: A callback function triggered upon successful confirmation.
565
+ ```jsx
566
+ import React from "react";
567
+ import { PayoutsDashboard } from "@bigbinary/neeto-payments-frontend";
568
+
569
+ const App = () => {
570
+ return (
571
+ <PayoutsDashboard
572
+ isPlatformEnabled={true}
573
+ payoutsPageRoute={routes.admin.payments.payouts.show}
574
+ />
575
+ );
576
+ };
577
+ ```
578
+
579
+ 7. `RazorpayPaymentButton`
580
+ ([source code](https://github.com/bigbinary/neeto-payments-nano/blob/main/app/javascript/src/components/RazorpayPaymentButton.jsx))
581
+
582
+ **Props**
583
+
584
+ - `label`: The button label. Defaults to `Pay`.
585
+ - `payableId`: The ID of the payable entity.
586
+ - `discountCode`: The discount code to be applied, if any.
587
+ - `email`: The customer's email address.
588
+ - `name`: The customer's name.
589
+ - `theme`: The theme configuration object.
590
+ - `payableType`: The type of the payable entity.
591
+ - `onBeforePayment`: A callback function triggered before the payment is
592
+ initiated.
593
+ - `onSuccessfulPayment`: A callback function triggered after a successful
594
+ payment.
595
+ - `onFailedPayment`: A callback function triggered after a failed payment.
518
596
 
519
- **Usage**
597
+ **Usage**
520
598
 
521
- ```jsx
522
- import React from "react";
523
- import { ConfirmUpiPaymentButton } from "@bigbinary/neeto-payments-frontend";
599
+ ```jsx
600
+ import React from "react";
601
+ import { RazorpayPaymentButton } from "@bigbinary/neeto-payments-frontend";
602
+
603
+ const App = () => {
604
+ return (
605
+ <RazorpayPaymentButton
606
+ email={customer.email}
607
+ name={customer.name}
608
+ discountCode={discountCode.code}
609
+ payableId={booking.id}
610
+ theme={meeting.theme}
611
+ />
612
+ );
613
+ };
614
+ ```
615
+
616
+ 8. `ConfirmUpiPaymentButton`
617
+ ([source code](https://github.com/bigbinary/neeto-payments-nano/blob/main/app/javascript/src/components/ConfirmUpiPaymentButton/index.jsx))
618
+
619
+ **Props**
620
+
621
+ - `vpas`: A list of UPI IDs presented for the user to select during
622
+ confirmation.
623
+ - `identifier`: The unique identifier associated with the payment.
624
+ - `paymentId`: The ID of the payment.
625
+ - `onSuccess`: A callback function triggered upon successful confirmation.
524
626
 
525
- const App = () => {
627
+ **Usage**
526
628
 
527
- return (
528
- <ConfirmUpiPaymentButton
529
- identifier={payment.identifier}
530
- payableId={payment.payableId}
531
- paymentId={payment.paymentId}
532
- vpas={meeting.fee.vpas}
533
- />
534
- );
535
- };
536
- ```
629
+ ```jsx
630
+ import React from "react";
631
+ import { ConfirmUpiPaymentButton } from "@bigbinary/neeto-payments-frontend";
632
+
633
+ const App = () => {
634
+ return (
635
+ <ConfirmUpiPaymentButton
636
+ identifier={payment.identifier}
637
+ payableId={payment.payableId}
638
+ paymentId={payment.paymentId}
639
+ vpas={meeting.fee.vpas}
640
+ />
641
+ );
642
+ };
643
+ ```
537
644
 
538
645
  ### 4. Hooks
539
646
 
540
- 1. `useStripePromise` ([source code](https://github.com/bigbinary/neeto-payments-nano/blob/main/app/javascript/src/hooks/useStripePromise.js))
647
+ 1. `useStripePromise`
648
+ ([source code](https://github.com/bigbinary/neeto-payments-nano/blob/main/app/javascript/src/hooks/useStripePromise.js))
649
+
650
+ This hook can used to provide the value for the `stripe` prop of the Stripe
651
+ `Element` component.
541
652
 
542
- This hook can used to provide the value for the `stripe` prop of the Stripe `Element` component.
653
+ **Usage**
543
654
 
544
- **Usage**
655
+ ```jsx
656
+ import React from "react";
657
+ import { useStripePromise } from "@bigbinary/neeto-payments-frontend";
545
658
 
546
- ```jsx
547
- import React from "react";
548
- import { useStripePromise } from "@bigbinary/neeto-payments-frontend";
659
+ const App = () => {
549
660
 
550
- const App = () => {
661
+ const stripePromise = useStripePromise({
662
+ stripePlatformAccount // The integration object for the Stripe platform account. No value is required if the platform account integration is not configured.
551
663
 
552
- const stripePromise = useStripePromise({
553
- stripePlatformAccount // The integration object for the Stripe platform account. No value is required if the platform account integration is not configured.
664
+ stripeAccountIdentifier: paymentRecipient?.stripeConnectedAccount?.identifier, // Stripe Standard account integration identifier
665
+ });
554
666
 
555
- stripeAccountIdentifier: paymentRecipient?.stripeConnectedAccount?.identifier, // Stripe Standard account integration identifier
556
- });
667
+ return (
668
+ <Elements stripe={stripePromise}>
669
+ </Elements>
670
+ );
671
+ };
672
+ ```
557
673
 
558
- return (
559
- <Elements stripe={stripePromise}>
560
- </Elements>
561
- );
562
- };
563
- ```
564
- 2. `useRazorpayPayment` ([source code](https://github.com/bigbinary/neeto-payments-nano/blob/main/app/javascript/src/hooks/useRazorpayPayment.js))
674
+ 2. `useRazorpayPayment`
675
+ ([source code](https://github.com/bigbinary/neeto-payments-nano/blob/main/app/javascript/src/hooks/useRazorpayPayment.js))
565
676
 
566
- This hook returns a function that can be used to initiate a Razorpay payment. Use it only if you want to trigger the payment flow through a custom button in the host application.
677
+ This hook returns a function that can be used to initiate a Razorpay payment.
678
+ Use it only if you want to trigger the payment flow through a custom button
679
+ in the host application.
567
680
 
681
+ **Usage**
568
682
 
569
- **Usage**
683
+ ```jsx
684
+ import React from "react";
685
+ import { useRazorpayPayment } from "@bigbinary/neeto-payments-frontend";
686
+
687
+ const App = () => {
688
+ const { makePayment } = useRazorpayPayment({
689
+ payableId, // The ID of the payable entity.
690
+ onBeforePayment, // A callback function triggered before the payment is initiated.
691
+ onSuccessfulPayment, // A callback function triggered after a successful payment.
692
+ onFailedPayment, // A callback function triggered after a failed payment.
693
+ customAmount, // The custom amount value to be used when a fee of type `range` or `variable` is configured.
694
+ });
695
+ };
696
+ ```
570
697
 
571
- ```jsx
572
- import React from "react";
573
- import { useRazorpayPayment } from "@bigbinary/neeto-payments-frontend";
698
+ ### 5. constants
574
699
 
575
- const App = () => {
700
+ 1. CURRENCY_OPTIONS
576
701
 
577
- const { makePayment } = useRazorpayPayment({
578
- payableId, // The ID of the payable entity.
579
- onBeforePayment, // A callback function triggered before the payment is initiated.
580
- onSuccessfulPayment, // A callback function triggered after a successful payment.
581
- onFailedPayment, // A callback function triggered after a failed payment.
582
- customAmount, // The custom amount value to be used when a fee of type `range` or `variable` is configured.
702
+ A list of supported currencies in `{ value, label }` format. This can be used
703
+ as options for the NeetoUI `Select` component.
583
704
 
584
- });
705
+ ### 6. utils
585
706
 
586
- };
587
- ```
707
+ 1. `getFormattedAmount({ amount, taxes=[], isTaxEnabled = false})`
588
708
 
589
- ### 5. constants
709
+ Returns the final amount as a **string**, truncated to **2 decimal places**,
710
+ after applying taxes if `isTaxEnabled` is set to `true` and taxes are
711
+ present.
590
712
 
591
- 1. CURRENCY_OPTIONS
713
+ #### Parameter keys
592
714
 
593
- A list of supported currencies in `{ value, label }` format. This can be used as options for the NeetoUI `Select` component.
715
+ - `amount`: The base amount to which taxes may be applied.
716
+ - `taxes`: List of tax objects with `value` and `kind` (`"percentage"` or
717
+ `"fixed"`). Defaults is `[]`
718
+ - `isTaxEnabled` : Whether taxes should be applied. Defaults to `false`.
594
719
 
595
- ### 6. utils
720
+ #### Returns:
596
721
 
597
- 1. `getFormattedAmount({ amount, taxes=[], isTaxEnabled = false})`
722
+ - `string`: Final amount with up to 2 decimal places (truncated, not
723
+ rounded).
598
724
 
599
- Returns the final amount as a **string**, truncated to **2 decimal places**, after applying taxes if `isTaxEnabled` is set to `true` and taxes are present.
725
+ #### Example:
600
726
 
601
- #### Parameter keys
602
- - `amount`: The base amount to which taxes may be applied.
603
- - `taxes`: List of tax objects with `value` and `kind` (`"percentage"` or `"fixed"`). Defaults is `[]`
604
- - `isTaxEnabled` : Whether taxes should be applied. Defaults to `false`.
727
+ ```js
728
+ getFormattedAmount([{ kind: "percentage", value: 23 }], "39.59", true); // "48.69"
729
+ ```
605
730
 
606
- #### Returns:
607
- - `string`: Final amount with up to 2 decimal places (truncated, not rounded).
731
+ 1. `getFormattedTaxAmount({ amount, taxes=[]})`
608
732
 
609
- #### Example:
610
- ```js
611
- getFormattedAmount([{ kind: "percentage", value: 23 }], "39.59", true); // → "48.69"
612
- ```
733
+ Returns the total tax amount as a **string**, truncated to **2 decimal
734
+ places**
613
735
 
614
- 1. `getFormattedTaxAmount({ amount, taxes=[]})`
736
+ #### Parameter keys
615
737
 
616
- Returns the total tax amount as a **string**, truncated to **2 decimal places**
738
+ - `amount`: The base amount on which tax will be calculated
739
+ - `taxes`: List of tax objects with `value` and `kind` (`"percentage"` or
740
+ `"fixed"`). Defaults is `[]`
617
741
 
618
- #### Parameter keys
619
- - `amount`: The base amount on which tax will be calculated
620
- - `taxes`: List of tax objects with `value` and `kind` (`"percentage"` or `"fixed"`). Defaults is `[]`
742
+ #### Returns:
621
743
 
622
- #### Returns:
623
- - `string`: Total tax amount with up to 2 decimal places (truncated, not rounded).
744
+ - `string`: Total tax amount with up to 2 decimal places (truncated, not
745
+ rounded).
624
746
 
625
- #### Example:
626
- ```js
627
- getFormattedTaxAmount([{ kind: "percentage", value: 23 }], "100"); // → "23.00"
628
- ```
747
+ #### Example:
629
748
 
749
+ ```js
750
+ getFormattedTaxAmount([{ kind: "percentage", value: 23 }], "100"); // → "23.00"
751
+ ```
630
752
 
631
753
  ### 6. Others
754
+
632
755
  ```
633
756
  // Example: Payment Settings Page
634
757
  import React, { useState, useEffect } from 'react';
@@ -725,12 +848,17 @@ export default PaymentSettingsPage;
725
848
  ```
726
849
 
727
850
  ### 4. API Calls - Specify Providers
728
- When calling the `/api/v1/integrations` endpoint (or other APIs that might implicitly check integrations), **you must pass the `providers` parameter** listing only the providers your application uses. Omitting this or including unused providers can lead to errors if the engine tries to load configurations or associations that don't exist for your setup.
851
+
852
+ When calling the `/api/v1/integrations` endpoint (or other APIs that might
853
+ implicitly check integrations), **you must pass the `providers` parameter**
854
+ listing only the providers your application uses. Omitting this or including
855
+ unused providers can lead to errors if the engine tries to load configurations
856
+ or associations that don't exist for your setup.
729
857
 
730
858
  ```javascript
731
859
  // Correct: Fetching only Stripe Standard integration status
732
- axios.get('/payments/api/v1/integrations', {
733
- params: { providers: ["stripe_standard"] }
860
+ axios.get("/payments/api/v1/integrations", {
861
+ params: { providers: ["stripe_standard"] },
734
862
  });
735
863
 
736
864
  // Incorrect (if not using all providers): Might cause errors
@@ -739,23 +867,39 @@ axios.get('/payments/api/v1/integrations', {
739
867
 
740
868
  ## Core Concepts
741
869
 
742
- - **Polymorphic Associations:** `payable` (what's being paid for), `accountable` (the payment account, e.g., `Stripe::Account`), and `holdable` (owner of the integration, e.g., `Organization`) link the engine to host app models dynamically based on configuration.
743
- - **Single Table Inheritance (STI):** Used for provider-specific models like `Payments::Stripe`, `Payments::Razorpay`, `Integrations::Razorpay`.
744
- - **Service Objects:** Encapsulate business logic (e.g., `Stripe::Payments::CreateService`).
745
- - **Callbacks:** Host applications implement methods in `NeetoPaymentsEngine::Callbacks` to customize behavior. See the [Callbacks](#callbacks) section.
746
- - **Webhooks:** Asynchronous events from providers update payment statuses. See [Webhook Handling](#webhook-handling).
747
- - **JWT Authentication:** Secures OAuth callback flows using RSA keys.
870
+ - **Polymorphic Associations:** `payable` (what's being paid for), `accountable`
871
+ (the payment account, e.g., `Stripe::Account`), and `holdable` (owner of the
872
+ integration, e.g., `Organization`) link the engine to host app models
873
+ dynamically based on configuration.
874
+ - **Single Table Inheritance (STI):** Used for provider-specific models like
875
+ `Payments::Stripe`, `Payments::Razorpay`, `Integrations::Razorpay`.
876
+ - **Service Objects:** Encapsulate business logic (e.g.,
877
+ `Stripe::Payments::CreateService`).
878
+ - **Callbacks:** Host applications implement methods in
879
+ `NeetoPaymentsEngine::Callbacks` to customize behavior. See the
880
+ [Callbacks](#callbacks) section.
881
+ - **Webhooks:** Asynchronous events from providers update payment statuses. See
882
+ [Webhook Handling](#webhook-handling).
883
+ - **JWT Authentication:** Secures OAuth callback flows using RSA keys.
748
884
 
749
885
  ## Webhook Handling
750
886
 
751
- - Webhooks are crucial for updating payment statuses asynchronously.
752
- - Endpoints are available at `/payments/api/v1/public/<provider>/webhooks`.
753
- - Signatures are verified using configured secrets.
887
+ - Webhooks are crucial for updating payment statuses asynchronously.
888
+ - Endpoints are available at `/payments/api/v1/public/<provider>/webhooks`.
889
+ - Signatures are verified using configured secrets.
754
890
 
755
891
  ### Development Environment Setup
756
892
 
757
893
  #### 1. Tunneling
758
- Use a tool like `ngrok` or `tunnelto` to expose your local development server to the internet. The `connect` subdomain is reserved within Neeto for receiving callbacks from third-party services. Refer to [Using Tunnelto](https://neeto-engineering.neetokb.com/articles/using-tunnelto) and [Exposing Tunnelto Locally](https://neeto-engineering.neetokb.com/articles/writing-payment-tests) for more details.
894
+
895
+ Use a tool like `ngrok` or `tunnelto` to expose your local development server to
896
+ the internet. The `connect` subdomain is reserved within Neeto for receiving
897
+ callbacks from third-party services. Refer to
898
+ [Using Tunnelto](https://neeto-engineering.neetokb.com/articles/using-tunnelto)
899
+ and
900
+ [Exposing Tunnelto Locally](https://neeto-engineering.neetokb.com/articles/writing-payment-tests)
901
+ for more details.
902
+
759
903
  ```bash
760
904
  # Example using tunnelto
761
905
  tunnelto --subdomain connect --port <YOUR_RAILS_APP_PORT>
@@ -763,38 +907,61 @@ tunnelto --subdomain connect --port <YOUR_RAILS_APP_PORT>
763
907
  ```
764
908
 
765
909
  #### 2. Stripe Webhook Setup (Manual)
766
- * Go to your **Stripe Test Dashboard** > Developers > Webhooks.
767
- * Click "Add endpoint".
768
- * Endpoint URL: `https://connect.tunnelto.dev/payments/api/v1/public/stripe/webhooks` (replace with your actual tunnel URL).
769
- * Select events to listen to. Refer to `config/stripe/webhooks.yml` in the engine for the required list (e.g., `payment_intent.succeeded`, `charge.refunded`, `account.updated`).
770
- * Click "Add endpoint".
771
- * After creation, find the **Signing secret** (starts with `whsec_...`).
772
- * **Copy this secret** and set it as the `STRIPE_WEBHOOK_SECRET` in your local `.env.local` or development credentials.
773
- * **Note:** The `neeto_payments_engine:stripe:webhooks:subscribe` rake task is **not recommended** for development setup as it doesn't create the endpoint and might show outdated secrets. Manual setup provides better control and ensures you have the correct, current secret. Refer to the [Official Stripe Webhook Documentation](https://docs.stripe.com/webhooks) for more details.
910
+
911
+ - Go to your **Stripe Test Dashboard** > Developers > Webhooks.
912
+ - Click "Add endpoint".
913
+ - Endpoint URL:
914
+ `https://connect.tunnelto.dev/payments/api/v1/public/stripe/webhooks` (replace
915
+ with your actual tunnel URL).
916
+ - Select events to listen to. Refer to `config/stripe/webhooks.yml` in the
917
+ engine for the required list (e.g., `payment_intent.succeeded`,
918
+ `charge.refunded`, `account.updated`).
919
+ - Click "Add endpoint".
920
+ - After creation, find the **Signing secret** (starts with `whsec_...`).
921
+ - **Copy this secret** and set it as the `STRIPE_WEBHOOK_SECRET` in your local
922
+ `.env.local` or development credentials.
923
+ - **Note:** The `neeto_payments_engine:stripe:webhooks:subscribe` rake task is
924
+ **not recommended** for development setup as it doesn't create the endpoint
925
+ and might show outdated secrets. Manual setup provides better control and
926
+ ensures you have the correct, current secret. Refer to the
927
+ [Official Stripe Webhook Documentation](https://docs.stripe.com/webhooks) for
928
+ more details.
774
929
 
775
930
  #### 3. Razorpay Webhook Setup (Manual)
776
- * Go to your **Razorpay Partners Dashboard**.
777
- * Go to Applications
778
- * Create a new application or open the existing application
779
- * Add test webhook
780
- * Webhook URL: `https://connect.tunnelto.dev/payments/api/v1/public/razorpay/webhooks` (replace with your tunnel URL).
781
- * Set a **Secret** (create a strong random string).
782
- * Select Active Events (e.g., `payment.authorized`, `payment.captured`, `payment.failed`, `refund.processed`, `refund.failed`).
783
- * Save the webhook.
784
- * **Copy the Secret you set** and configure it as `RAZORPAY_WEBHOOK_SECRET` in your local development environment.
931
+
932
+ - Go to your **Razorpay Partners Dashboard**.
933
+ - Go to Applications
934
+ - Create a new application or open the existing application
935
+ - Add test webhook
936
+ - Webhook URL:
937
+ `https://connect.tunnelto.dev/payments/api/v1/public/razorpay/webhooks`
938
+ (replace with your tunnel URL).
939
+ - Set a **Secret** (create a strong random string).
940
+ - Select Active Events (e.g., `payment.authorized`, `payment.captured`,
941
+ `payment.failed`, `refund.processed`, `refund.failed`).
942
+ - Save the webhook.
943
+ - **Copy the Secret you set** and configure it as `RAZORPAY_WEBHOOK_SECRET` in
944
+ your local development environment.
785
945
 
786
946
  ## Authentication (JWT for OAuth)
787
947
 
788
- - Secures the OAuth callback flow for connecting Stripe/Razorpay accounts.
789
- - Uses RSA public/private keys (`CONNECT_PUBLIC_KEY`, `CONNECT_PRIVATE_KEY`) configured in your secrets.
790
- - The `ConnectLinkService` creates a short-lived JWT containing user context when initiating the OAuth flow.
791
- - The `JwtService` verifies the token signature using the public key upon callback.
948
+ - Secures the OAuth callback flow for connecting Stripe/Razorpay accounts.
949
+ - Uses RSA public/private keys (`CONNECT_PUBLIC_KEY`, `CONNECT_PRIVATE_KEY`)
950
+ configured in your secrets.
951
+ - The `ConnectLinkService` creates a short-lived JWT containing user context
952
+ when initiating the OAuth flow.
953
+ - The `JwtService` verifies the token signature using the public key upon
954
+ callback.
792
955
 
793
956
  ## Callbacks
794
957
 
795
- Host applications **must** implement specific methods within a `NeetoPaymentsEngine::Callbacks` module (e.g., in `app/lib/neeto_payments_engine/callbacks.rb`) to tailor the engine's behavior to their domain logic.
958
+ Host applications **must** implement specific methods within a
959
+ `NeetoPaymentsEngine::Callbacks` module (e.g., in
960
+ `app/lib/neeto_payments_engine/callbacks.rb`) to tailor the engine's behavior to
961
+ their domain logic.
796
962
 
797
963
  ### Mandatory Callbacks
964
+
798
965
  ```ruby
799
966
  # app/lib/neeto_payments_engine/callbacks.rb
800
967
  module NeetoPaymentsEngine
@@ -814,6 +981,7 @@ end
814
981
  ```
815
982
 
816
983
  ### Optional Callbacks (Implement as needed)
984
+
817
985
  ```ruby
818
986
  # app/lib/neeto_payments_engine/callbacks.rb
819
987
  module NeetoPaymentsEngine
@@ -956,19 +1124,33 @@ end
956
1124
 
957
1125
  ## Exposed Entities
958
1126
 
959
- The engine exposes various models, services, jobs, and tasks for integration and extension:
960
-
961
- - **Models:** `Payment`, `Fee`, `Refund`, `Split`, `Payments::Split`, `Stripe::Account`, `Stripe::PlatformAccount`, `Integration`, `Customer`, `PaymentMethod`, `Payout`, `WebhookEvent`, etc. Host apps primarily interact with these through ActiveRecord associations defined on their own models.
962
- - **Services:** Encapsulate core logic (e.g., `Stripe::Payments::CreateService`, `Razorpay::Accounts::CreateService`, `SplitTransfersFilterService`, `ExportCsvService`). While mostly used internally, filter and export services might be invoked directly or indirectly via controllers.
963
- - **Jobs:** Handle background tasks (`Stripe::WebhooksJob`, `StripePlatform::CreatePaymentSplitsJob`, `ExportCsvJob`, `CreatePaymentMethodDomainJob`). These are queued and processed by Sidekiq.
964
- - **Concerns:** Reusable modules (`Amountable`, `PaymentProcessable`, `Taxable`, `Stripe::Accountable`, `Refundable`). Mostly for internal engine use.
965
- - **Rake Tasks:**
966
- - `neeto_payments_engine:stripe:account:integrate`: Seeds a sample Stripe connected account. **Development/Testing only.**
967
- - `neeto_payments_engine:stripe:webhooks:subscribe`: **Do not rely on this for setup.** See [Webhook Handling](#webhook-handling) for manual setup instructions.
1127
+ The engine exposes various models, services, jobs, and tasks for integration and
1128
+ extension:
1129
+
1130
+ - **Models:** `Payment`, `Fee`, `Refund`, `Split`, `Payments::Split`,
1131
+ `Stripe::Account`, `Stripe::PlatformAccount`, `Integration`, `Customer`,
1132
+ `PaymentMethod`, `Payout`, `WebhookEvent`, etc. Host apps primarily interact
1133
+ with these through ActiveRecord associations defined on their own models.
1134
+ - **Services:** Encapsulate core logic (e.g., `Stripe::Payments::CreateService`,
1135
+ `Razorpay::Accounts::CreateService`, `SplitTransfersFilterService`,
1136
+ `ExportCsvService`). While mostly used internally, filter and export services
1137
+ might be invoked directly or indirectly via controllers.
1138
+ - **Jobs:** Handle background tasks (`Stripe::WebhooksJob`,
1139
+ `StripePlatform::CreatePaymentSplitsJob`, `ExportCsvJob`,
1140
+ `CreatePaymentMethodDomainJob`). These are queued and processed by Sidekiq.
1141
+ - **Concerns:** Reusable modules (`Amountable`, `PaymentProcessable`, `Taxable`,
1142
+ `Stripe::Accountable`, `Refundable`). Mostly for internal engine use.
1143
+ - **Rake Tasks:**
1144
+ - `neeto_payments_engine:stripe:account:integrate`: Seeds a sample Stripe
1145
+ connected account. **Development/Testing only.**
1146
+ - `neeto_payments_engine:stripe:webhooks:subscribe`: **Do not rely on this for
1147
+ setup.** See [Webhook Handling](#webhook-handling) for manual setup
1148
+ instructions.
968
1149
 
969
1150
  ## API Endpoints
970
1151
 
971
- The engine exposes several API endpoints under the configured mount path (default `/payments`). Here are some key ones:
1152
+ The engine exposes several API endpoints under the configured mount path
1153
+ (default `/payments`). Here are some key ones:
972
1154
 
973
1155
  | Method | Path | Description | Authentication |
974
1156
  | :----- | :------------------------------------------------ | :----------------------------------------------------------------------- | :------------- |
@@ -1015,20 +1197,39 @@ The engine exposes several API endpoints under the configured mount path (defaul
1015
1197
  | POST | `/api/v1/public/razorpay/webhooks` | Razorpay webhook receiver endpoint. | Razorpay Sig. |
1016
1198
  | POST | `/api/v1/public/stripe_platform/webhooks` | Stripe Platform webhook receiver endpoint. | Stripe Sig. |
1017
1199
 
1018
- *Note: "Host App Auth" means the endpoint relies on the host application's authentication (e.g., `authenticate_user!`). "JWT" means authentication relies on the JWT generated during the OAuth flow. "Open" means no authentication. "Stripe Sig." / "Razorpay Sig." means verification is done via webhook signatures.*
1200
+ _Note: "Host App Auth" means the endpoint relies on the host application's
1201
+ authentication (e.g., `authenticate_user!`). "JWT" means authentication relies
1202
+ on the JWT generated during the OAuth flow. "Open" means no authentication.
1203
+ "Stripe Sig." / "Razorpay Sig." means verification is done via webhook
1204
+ signatures._
1019
1205
 
1020
1206
  ## Incineration Concern
1021
1207
 
1022
- If your host application uses `neeto-org-incineration-engine`, you need to integrate `NeetoPaymentsEngine` models correctly. The `NeetoPaymentsEngine::Fee` model often requires special handling as it might be associated with host application models (`feeable`).
1023
-
1024
- 1. **Initial Setup:** When first adding `neeto-payments-engine`, add `NeetoPaymentsEngine::Fee` to the `SKIPPED_MODELS` list in your host application's `IncinerableConcern` implementation (e.g., in `app/models/concerns/incinerable_concern.rb`). This prevents incineration errors before associations are correctly set up especially while running the whole test suite in host app.
1208
+ If your host application uses `neeto-org-incineration-engine`, you need to
1209
+ integrate `NeetoPaymentsEngine` models correctly. The `NeetoPaymentsEngine::Fee`
1210
+ model often requires special handling as it might be associated with host
1211
+ application models (`feeable`).
1212
+
1213
+ 1. **Initial Setup:** When first adding `neeto-payments-engine`, add
1214
+ `NeetoPaymentsEngine::Fee` to the `SKIPPED_MODELS` list in your host
1215
+ application's `IncinerableConcern` implementation (e.g., in
1216
+ `app/models/concerns/incinerable_concern.rb`). This prevents incineration
1217
+ errors before associations are correctly set up especially while running the
1218
+ whole test suite in host app.
1025
1219
  ```ruby
1026
1220
  # In your host app's IncinerableConcern
1027
1221
  # TODO: Incinerate Fee based on Entity later
1028
1222
  SKIPPED_MODELS = ["NeetoActivitiesEngine::Activity", "NeetoPaymentsEngine::Fee"]
1029
1223
  ```
1030
- 2. **Define Associations Later(optional):** Add the `has_one :fee, as: :feeable` association to your host application models that should have fees (e.g., `Product`, `ServicePlan`).
1031
- 3. **Update Incineration Logic(optional):** Once associations are defined, **remove** `"NeetoPaymentsEngine::Fee"` from `SKIPPED_MODELS`. You must then update your `IncinerableConcern.associated_models` method to include logic that correctly finds and targets `NeetoPaymentsEngine::Fee` records associated with the organization being incinerated, likely through the `feeable` association.
1224
+ 2. **Define Associations Later(optional):** Add the
1225
+ `has_one :fee, as: :feeable` association to your host application models
1226
+ that should have fees (e.g., `Product`, `ServicePlan`).
1227
+ 3. **Update Incineration Logic(optional):** Once associations are defined,
1228
+ **remove** `"NeetoPaymentsEngine::Fee"` from `SKIPPED_MODELS`. You must then
1229
+ update your `IncinerableConcern.associated_models` method to include logic
1230
+ that correctly finds and targets `NeetoPaymentsEngine::Fee` records
1231
+ associated with the organization being incinerated, likely through the
1232
+ `feeable` association.
1032
1233
 
1033
1234
  ```ruby
1034
1235
  # In your host app's IncinerableConcern
@@ -1048,30 +1249,50 @@ If your host application uses `neeto-org-incineration-engine`, you need to integ
1048
1249
  # rest of the code
1049
1250
  end
1050
1251
  ```
1051
- Consult the engine's own `NeetoPaymentsEngine::IncinerableConcern` (`app/models/concerns/neeto_payments_engine/incinerable_concern.rb`) for the list of models it defines and how it targets them for deletion, to avoid duplication and ensure comprehensive cleanup.
1252
+
1253
+ Consult the engine's own `NeetoPaymentsEngine::IncinerableConcern`
1254
+ (`app/models/concerns/neeto_payments_engine/incinerable_concern.rb`) for the
1255
+ list of models it defines and how it targets them for deletion, to avoid
1256
+ duplication and ensure comprehensive cleanup.
1052
1257
 
1053
1258
  ## Deprecated Patterns
1054
1259
 
1055
- Please be aware of the following deprecations and use the recommended alternatives:
1260
+ Please be aware of the following deprecations and use the recommended
1261
+ alternatives:
1056
1262
 
1057
1263
  1. **Configuration `holdable_class`:**
1058
- * **Deprecated:** The singular `NeetoPaymentsEngine.holdable_class = "ClassName"` configuration.
1059
- * **Recommended:** Use the hash-based `NeetoPaymentsEngine.providers_holdable_class = { provider: "ClassName", ... }` to configure holdable models per provider. This provides more flexibility.
1264
+
1265
+ - **Deprecated:** The singular
1266
+ `NeetoPaymentsEngine.holdable_class = "ClassName"` configuration.
1267
+ - **Recommended:** Use the hash-based
1268
+ `NeetoPaymentsEngine.providers_holdable_class = { provider: "ClassName", ... }`
1269
+ to configure holdable models per provider. This provides more flexibility.
1060
1270
 
1061
1271
  2. **Holdable-Scoped APIs:**
1062
- * **Deprecated:** API endpoints previously located under `/api/v1/<provider>/holdables/:holdable_id/...` are deprecated.
1063
- * **Recommended:** Use the newer API structure:
1064
- * For general integration status: `/api/v1/integrations` (passing the `providers` param).
1065
- * For provider-specific account management: `/api/v1/<provider>/accounts/...`.
1066
- * For provider-specific resources like payouts: `/api/v1/<provider>/payouts/...`.
1272
+
1273
+ - **Deprecated:** API endpoints previously located under
1274
+ `/api/v1/<provider>/holdables/:holdable_id/...` are deprecated.
1275
+ - **Recommended:** Use the newer API structure:
1276
+ - For general integration status: `/api/v1/integrations` (passing the
1277
+ `providers` param).
1278
+ - For provider-specific account management:
1279
+ `/api/v1/<provider>/accounts/...`.
1280
+ - For provider-specific resources like payouts:
1281
+ `/api/v1/<provider>/payouts/...`.
1067
1282
 
1068
1283
  3. **`Charge` Model/Concept:**
1069
- * **Deprecated:** Older versions might have referred to payment processing entities as `Charge`.
1070
- * **Recommended:** The primary entity for payment processing is now `NeetoPaymentsEngine::Payment` (and its STI subclasses like `Payments::Stripe`). Use `Payment` in associations and logic. The concept of `Fee` (`NeetoPaymentsEngine::Fee`) represents the configuration of *what* to charge, while `Payment` represents the actual transaction.
1284
+ - **Deprecated:** Older versions might have referred to payment processing
1285
+ entities as `Charge`.
1286
+ - **Recommended:** The primary entity for payment processing is now
1287
+ `NeetoPaymentsEngine::Payment` (and its STI subclasses like
1288
+ `Payments::Stripe`). Use `Payment` in associations and logic. The concept
1289
+ of `Fee` (`NeetoPaymentsEngine::Fee`) represents the configuration of
1290
+ _what_ to charge, while `Payment` represents the actual transaction.
1071
1291
 
1072
1292
  ## Development Environment Setup
1073
1293
 
1074
- To run the engine locally integrated with a host application, ensure the following processes are running:
1294
+ To run the engine locally integrated with a host application, ensure the
1295
+ following processes are running:
1075
1296
 
1076
1297
  1. **Rails Server:** Starts the main web application.
1077
1298
  ```bash
@@ -1086,14 +1307,18 @@ To run the engine locally integrated with a host application, ensure the followi
1086
1307
  ```bash
1087
1308
  bundle exec sidekiq -e development -C config/sidekiq.yml
1088
1309
  ```
1089
- 4. **Tunneling Service (for Webhooks/OAuth):** Exposes your local server to the internet. Use the `connect` subdomain for OAuth callbacks.
1310
+ 4. **Tunneling Service (for Webhooks/OAuth):** Exposes your local server to the
1311
+ internet. Use the `connect` subdomain for OAuth callbacks.
1090
1312
  ```bash
1091
1313
  # Using tunnelto (replace <YOUR_APP_PORT> with your Rails server port, e.g., 3000)
1092
1314
  tunnelto --subdomain connect --port <YOUR_APP_PORT>
1093
1315
  ```
1094
- *Note: The `connect` subdomain is conventionally used across Neeto applications for receiving callbacks from third-party services like Stripe/Razorpay OAuth.*
1316
+ _Note: The `connect` subdomain is conventionally used across Neeto
1317
+ applications for receiving callbacks from third-party services like
1318
+ Stripe/Razorpay OAuth._
1095
1319
 
1096
1320
  The `Procfile.dev.PAYMENTS` might look like this:
1321
+
1097
1322
  ```yaml
1098
1323
  web: bundle exec rails s
1099
1324
  vite: yarn dev
@@ -1102,62 +1327,94 @@ worker: bundle exec sidekiq -e development -C config/sidekiq.yml
1102
1327
  ```
1103
1328
 
1104
1329
  ## Helper methods
1105
- - `currency_format_with_symbol`
1106
- This helper method converts a currency code (like "INR" or "USD") into its corresponding symbol and returns the formatted amount with the symbol. Example $10.00.
1107
-
1108
- Usage in host application:
1109
- - In general modules (e.g., Services or View helpers)
1110
- ```ruby
1111
- module ApplicationHelper
1112
- include ::NeetoPaymentsEngine::CurrencyFormatHelper
1113
-
1114
- def formatted_amount
1115
- currency_format_with_symbol(payment&.amount, payment&.currency)
1116
- end
1330
+
1331
+ - `currency_format_with_symbol` This helper method converts a currency code
1332
+ (like "INR" or "USD") into its corresponding symbol and returns the formatted
1333
+ amount with the symbol. Example $10.00.
1334
+
1335
+ Usage in host application:
1336
+
1337
+ - In general modules (e.g., Services or View helpers)
1338
+
1339
+ ```ruby
1340
+ module ApplicationHelper
1341
+ include ::NeetoPaymentsEngine::CurrencyFormatHelper
1342
+
1343
+ def formatted_amount
1344
+ currency_format_with_symbol(payment&.amount, payment&.currency)
1117
1345
  end
1118
- ```
1346
+ end
1347
+ ```
1348
+
1349
+ - In mailers
1350
+
1351
+ 1. Include the helper in your mailer:
1119
1352
 
1120
- - In mailers
1353
+ ```ruby
1354
+ class Packages::PurchaseConfirmedMailer < ApplicationMailer
1355
+ helper ::NeetoPaymentsEngine::CurrencyFormatHelper
1121
1356
 
1122
- 1. Include the helper in your mailer:
1123
- ```ruby
1124
- class Packages::PurchaseConfirmedMailer < ApplicationMailer
1125
- helper ::NeetoPaymentsEngine::CurrencyFormatHelper
1357
+ def customer_email
1358
+ end
1359
+ end
1360
+ ```
1126
1361
 
1127
- def customer_email
1128
- end
1129
- end
1130
- ```
1131
- 2. Use the method in the mailer view:
1132
- ```ruby
1133
- <%= "#{currency_format_with_symbol(@purchase.payment&.amount,@purchase.payment&.currency)}" %>
1134
- ```
1362
+ 2. Use the method in the mailer view:
1363
+ ```ruby
1364
+ <%= "#{currency_format_with_symbol(@purchase.payment&.amount,@purchase.payment&.currency)}" %>
1365
+ ```
1135
1366
 
1136
1367
  ## Testing & Debugging
1137
1368
 
1138
- - **Dummy App:** Use the `test/dummy` app within the engine's repository for isolated testing.
1139
- - **Test Helpers:** Utilize `NeetoPaymentsEngine::TestHelpers` (includes `HttpRequestHelpers`) for stubbing API calls to Stripe/Razorpay (`test/helpers/http_request_helpers/`).
1140
- - **Stripe Test Cards:**
1141
- * Valid Card: `4242 4242 4242 4242`
1142
- * Declined Card: `4000 0000 0000 0002`
1143
- * Expiry Date: Any future date (e.g., `12/30`)
1144
- * CVC: Any 3 digits (e.g., `123`)
1145
- * ZIP Code: Any valid ZIP (e.g., `12345`)
1146
- * [More Stripe Test Cards](https://docs.stripe.com/testing)
1147
- - **Razorpay Test Cards/UPI:** Refer to [Razorpay Testing Docs](https://razorpay.com/docs/payments/payments/test-card-details/).
1148
- - **Logging:** Check Rails logs (`log/development.log`) for detailed output from the engine's `LogActivityHelper`.
1149
- - **Provider Dashboards:** Use the Stripe and Razorpay **Test Mode** dashboards to view API logs, payment details, webhook attempts, and specific error messages.
1150
- - **JWT Debugging:** Use tools like [jwt.io](https://jwt.io) to decode JWTs generated during OAuth flows. Paste the token and the **public key** (`CONNECT_PUBLIC_KEY`) to verify the signature and inspect the payload (check `exp` claim for expiry).
1369
+ - **Dummy App:** Use the `test/dummy` app within the engine's repository for
1370
+ isolated testing.
1371
+ - **Test Helpers:** Utilize `NeetoPaymentsEngine::TestHelpers` (includes
1372
+ `HttpRequestHelpers`) for stubbing API calls to Stripe/Razorpay
1373
+ (`test/helpers/http_request_helpers/`).
1374
+ - **Stripe Test Cards:**
1375
+ - Valid Card: `4242 4242 4242 4242`
1376
+ - Declined Card: `4000 0000 0000 0002`
1377
+ - Expiry Date: Any future date (e.g., `12/30`)
1378
+ - CVC: Any 3 digits (e.g., `123`)
1379
+ - ZIP Code: Any valid ZIP (e.g., `12345`)
1380
+ - [More Stripe Test Cards](https://docs.stripe.com/testing)
1381
+ - **Razorpay Test Cards/UPI:** Refer to
1382
+ [Razorpay Testing Docs](https://razorpay.com/docs/payments/payments/test-card-details/).
1383
+ - **Logging:** Check Rails logs (`log/development.log`) for detailed output from
1384
+ the engine's `LogActivityHelper`.
1385
+ - **Provider Dashboards:** Use the Stripe and Razorpay **Test Mode** dashboards
1386
+ to view API logs, payment details, webhook attempts, and specific error
1387
+ messages.
1388
+ - **JWT Debugging:** Use tools like [jwt.io](https://jwt.io) to decode JWTs
1389
+ generated during OAuth flows. Paste the token and the **public key**
1390
+ (`CONNECT_PUBLIC_KEY`) to verify the signature and inspect the payload (check
1391
+ `exp` claim for expiry).
1151
1392
 
1152
1393
  ## Gotchas & Tips
1153
1394
 
1154
- - **`providers_holdable_class` is Mandatory:** Forgetting to configure this in the initializer will lead to errors when the engine tries to find associated accounts.
1155
- - **Specify `providers` in API Calls:** When calling `/api/v1/integrations`, always pass the `providers` param listing only the providers you actually use in your host app (e.g., `params: { providers: ["stripe_standard"] }`). Failing to do so might cause errors if the engine tries to load an unconfigured provider (like UPI).
1156
- - **Stripe Connect Signup:** You *must* complete the Stripe Connect signup process in your Stripe account, even for platform-only usage.
1157
- - **Webhook Secrets in Dev:** Manually created webhook endpoint secrets from Stripe/Razorpay dashboards are the source of truth for development, not necessarily what rake tasks might print.
1158
- - **JWT Key Security:** Treat your JWT private key with the same security as your API secret keys.
1159
- - **Migration Order:** Always run `bundle exec rails neeto_payments_engine:install:migrations` *before* `db:migrate` when setting up or upgrading. We also need to run this rake task and migration after we run `./bin/setup` in the host app.
1395
+ - **`providers_holdable_class` is Mandatory:** Forgetting to configure this in
1396
+ the initializer will lead to errors when the engine tries to find associated
1397
+ accounts.
1398
+ - **Specify `providers` in API Calls:** When calling `/api/v1/integrations`,
1399
+ always pass the `providers` param listing only the providers you actually use
1400
+ in your host app (e.g., `params: { providers: ["stripe_standard"] }`). Failing
1401
+ to do so might cause errors if the engine tries to load an unconfigured
1402
+ provider (like UPI).
1403
+ - **Stripe Connect Signup:** You _must_ complete the Stripe Connect signup
1404
+ process in your Stripe account, even for platform-only usage.
1405
+ - **Webhook Secrets in Dev:** Manually created webhook endpoint secrets from
1406
+ Stripe/Razorpay dashboards are the source of truth for development, not
1407
+ necessarily what rake tasks might print.
1408
+ - **JWT Key Security:** Treat your JWT private key with the same security as
1409
+ your API secret keys.
1410
+ - **Migration Order:** Always run
1411
+ `bundle exec rails neeto_payments_engine:install:migrations` _before_
1412
+ `db:migrate` when setting up or upgrading. We also need to run this rake task
1413
+ and migration after we run `./bin/setup` in the host app.
1160
1414
 
1161
1415
  ## Publishing
1162
1416
 
1163
- For instructions on building and releasing the `@bigbinary/neeto-payments-frontend` NPM package and the `neeto-payments-engine` Ruby gem, please refer to the internal guide: [Building and Releasing Packages](https://neeto-engineering.neetokb.com/articles/building-and-releasing-packages).
1417
+ For instructions on building and releasing the
1418
+ `@bigbinary/neeto-payments-frontend` NPM package and the `neeto-payments-engine`
1419
+ Ruby gem, please refer to the internal guide:
1420
+ [Building and Releasing Packages](https://neeto-engineering.neetokb.com/articles/building-and-releasing-packages).