chub-dev 0.1.0 → 0.1.2-beta.0

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 (139) hide show
  1. package/README.md +55 -0
  2. package/bin/chub-mcp +2 -0
  3. package/dist/airtable/docs/database/javascript/DOC.md +1437 -0
  4. package/dist/airtable/docs/database/python/DOC.md +1735 -0
  5. package/dist/amplitude/docs/analytics/javascript/DOC.md +1282 -0
  6. package/dist/amplitude/docs/analytics/python/DOC.md +1199 -0
  7. package/dist/anthropic/docs/claude-api/javascript/DOC.md +503 -0
  8. package/dist/anthropic/docs/claude-api/python/DOC.md +389 -0
  9. package/dist/asana/docs/tasks/DOC.md +1396 -0
  10. package/dist/assemblyai/docs/transcription/DOC.md +1043 -0
  11. package/dist/atlassian/docs/confluence/javascript/DOC.md +1347 -0
  12. package/dist/atlassian/docs/confluence/python/DOC.md +1604 -0
  13. package/dist/auth0/docs/identity/javascript/DOC.md +968 -0
  14. package/dist/auth0/docs/identity/python/DOC.md +1199 -0
  15. package/dist/aws/docs/s3/javascript/DOC.md +1773 -0
  16. package/dist/aws/docs/s3/python/DOC.md +1807 -0
  17. package/dist/binance/docs/trading/javascript/DOC.md +1315 -0
  18. package/dist/binance/docs/trading/python/DOC.md +1454 -0
  19. package/dist/braintree/docs/gateway/javascript/DOC.md +1278 -0
  20. package/dist/braintree/docs/gateway/python/DOC.md +1179 -0
  21. package/dist/chromadb/docs/embeddings-db/javascript/DOC.md +1263 -0
  22. package/dist/chromadb/docs/embeddings-db/python/DOC.md +1707 -0
  23. package/dist/clerk/docs/auth/javascript/DOC.md +1220 -0
  24. package/dist/clerk/docs/auth/python/DOC.md +274 -0
  25. package/dist/cloudflare/docs/workers/javascript/DOC.md +918 -0
  26. package/dist/cloudflare/docs/workers/python/DOC.md +994 -0
  27. package/dist/cockroachdb/docs/distributed-db/DOC.md +1500 -0
  28. package/dist/cohere/docs/llm/DOC.md +1335 -0
  29. package/dist/datadog/docs/monitoring/javascript/DOC.md +1740 -0
  30. package/dist/datadog/docs/monitoring/python/DOC.md +1815 -0
  31. package/dist/deepgram/docs/speech/javascript/DOC.md +885 -0
  32. package/dist/deepgram/docs/speech/python/DOC.md +685 -0
  33. package/dist/deepl/docs/translation/javascript/DOC.md +887 -0
  34. package/dist/deepl/docs/translation/python/DOC.md +944 -0
  35. package/dist/deepseek/docs/llm/DOC.md +1220 -0
  36. package/dist/directus/docs/headless-cms/javascript/DOC.md +1128 -0
  37. package/dist/directus/docs/headless-cms/python/DOC.md +1276 -0
  38. package/dist/discord/docs/bot/javascript/DOC.md +1090 -0
  39. package/dist/discord/docs/bot/python/DOC.md +1130 -0
  40. package/dist/elasticsearch/docs/search/DOC.md +1634 -0
  41. package/dist/elevenlabs/docs/text-to-speech/javascript/DOC.md +336 -0
  42. package/dist/elevenlabs/docs/text-to-speech/python/DOC.md +552 -0
  43. package/dist/firebase/docs/auth/DOC.md +1015 -0
  44. package/dist/gemini/docs/genai/javascript/DOC.md +691 -0
  45. package/dist/gemini/docs/genai/python/DOC.md +555 -0
  46. package/dist/github/docs/octokit/DOC.md +1560 -0
  47. package/dist/google/docs/bigquery/javascript/DOC.md +1688 -0
  48. package/dist/google/docs/bigquery/python/DOC.md +1503 -0
  49. package/dist/hubspot/docs/crm/javascript/DOC.md +1805 -0
  50. package/dist/hubspot/docs/crm/python/DOC.md +2033 -0
  51. package/dist/huggingface/docs/transformers/DOC.md +948 -0
  52. package/dist/intercom/docs/messaging/javascript/DOC.md +1844 -0
  53. package/dist/intercom/docs/messaging/python/DOC.md +1797 -0
  54. package/dist/jira/docs/issues/javascript/DOC.md +1420 -0
  55. package/dist/jira/docs/issues/python/DOC.md +1492 -0
  56. package/dist/kafka/docs/streaming/javascript/DOC.md +1671 -0
  57. package/dist/kafka/docs/streaming/python/DOC.md +1464 -0
  58. package/dist/landingai-ade/docs/api/DOC.md +620 -0
  59. package/dist/landingai-ade/docs/sdk/python/DOC.md +489 -0
  60. package/dist/landingai-ade/docs/sdk/typescript/DOC.md +542 -0
  61. package/dist/landingai-ade/skills/SKILL.md +489 -0
  62. package/dist/launchdarkly/docs/feature-flags/javascript/DOC.md +1191 -0
  63. package/dist/launchdarkly/docs/feature-flags/python/DOC.md +1671 -0
  64. package/dist/linear/docs/tracker/DOC.md +1554 -0
  65. package/dist/livekit/docs/realtime/javascript/DOC.md +303 -0
  66. package/dist/livekit/docs/realtime/python/DOC.md +163 -0
  67. package/dist/mailchimp/docs/marketing/DOC.md +1420 -0
  68. package/dist/meilisearch/docs/search/DOC.md +1241 -0
  69. package/dist/microsoft/docs/onedrive/javascript/DOC.md +1421 -0
  70. package/dist/microsoft/docs/onedrive/python/DOC.md +1549 -0
  71. package/dist/mongodb/docs/atlas/DOC.md +2041 -0
  72. package/dist/notion/docs/workspace-api/javascript/DOC.md +1435 -0
  73. package/dist/notion/docs/workspace-api/python/DOC.md +1400 -0
  74. package/dist/okta/docs/identity/javascript/DOC.md +1171 -0
  75. package/dist/okta/docs/identity/python/DOC.md +1401 -0
  76. package/dist/openai/docs/chat/javascript/DOC.md +407 -0
  77. package/dist/openai/docs/chat/python/DOC.md +568 -0
  78. package/dist/paypal/docs/checkout/DOC.md +278 -0
  79. package/dist/pinecone/docs/sdk/javascript/DOC.md +984 -0
  80. package/dist/pinecone/docs/sdk/python/DOC.md +1395 -0
  81. package/dist/plaid/docs/banking/javascript/DOC.md +1163 -0
  82. package/dist/plaid/docs/banking/python/DOC.md +1203 -0
  83. package/dist/playwright-community/skills/login-flows/SKILL.md +108 -0
  84. package/dist/postmark/docs/transactional-email/DOC.md +1168 -0
  85. package/dist/prisma/docs/orm/javascript/DOC.md +1419 -0
  86. package/dist/prisma/docs/orm/python/DOC.md +1317 -0
  87. package/dist/qdrant/docs/vector-search/javascript/DOC.md +1221 -0
  88. package/dist/qdrant/docs/vector-search/python/DOC.md +1653 -0
  89. package/dist/rabbitmq/docs/message-queue/javascript/DOC.md +1193 -0
  90. package/dist/rabbitmq/docs/message-queue/python/DOC.md +1243 -0
  91. package/dist/razorpay/docs/payments/javascript/DOC.md +1219 -0
  92. package/dist/razorpay/docs/payments/python/DOC.md +1330 -0
  93. package/dist/redis/docs/key-value/javascript/DOC.md +1851 -0
  94. package/dist/redis/docs/key-value/python/DOC.md +2054 -0
  95. package/dist/registry.json +2817 -0
  96. package/dist/replicate/docs/model-hosting/DOC.md +1318 -0
  97. package/dist/resend/docs/email/DOC.md +1271 -0
  98. package/dist/salesforce/docs/crm/javascript/DOC.md +1241 -0
  99. package/dist/salesforce/docs/crm/python/DOC.md +1183 -0
  100. package/dist/search-index.json +1 -0
  101. package/dist/sendgrid/docs/email-api/javascript/DOC.md +371 -0
  102. package/dist/sendgrid/docs/email-api/python/DOC.md +656 -0
  103. package/dist/sentry/docs/error-tracking/javascript/DOC.md +1073 -0
  104. package/dist/sentry/docs/error-tracking/python/DOC.md +1309 -0
  105. package/dist/shopify/docs/storefront/DOC.md +457 -0
  106. package/dist/slack/docs/workspace/javascript/DOC.md +933 -0
  107. package/dist/slack/docs/workspace/python/DOC.md +271 -0
  108. package/dist/square/docs/payments/javascript/DOC.md +1855 -0
  109. package/dist/square/docs/payments/python/DOC.md +1728 -0
  110. package/dist/stripe/docs/api/DOC.md +1727 -0
  111. package/dist/stripe/docs/payments/DOC.md +1726 -0
  112. package/dist/stytch/docs/auth/javascript/DOC.md +1813 -0
  113. package/dist/stytch/docs/auth/python/DOC.md +1962 -0
  114. package/dist/supabase/docs/client/DOC.md +1606 -0
  115. package/dist/twilio/docs/messaging/python/DOC.md +469 -0
  116. package/dist/twilio/docs/messaging/typescript/DOC.md +946 -0
  117. package/dist/vercel/docs/platform/DOC.md +1940 -0
  118. package/dist/weaviate/docs/vector-db/javascript/DOC.md +1268 -0
  119. package/dist/weaviate/docs/vector-db/python/DOC.md +1388 -0
  120. package/dist/zendesk/docs/support/javascript/DOC.md +2150 -0
  121. package/dist/zendesk/docs/support/python/DOC.md +2297 -0
  122. package/package.json +22 -6
  123. package/skills/get-api-docs/SKILL.md +84 -0
  124. package/src/commands/annotate.js +83 -0
  125. package/src/commands/build.js +12 -1
  126. package/src/commands/feedback.js +150 -0
  127. package/src/commands/get.js +83 -42
  128. package/src/commands/search.js +7 -0
  129. package/src/index.js +43 -17
  130. package/src/lib/analytics.js +90 -0
  131. package/src/lib/annotations.js +57 -0
  132. package/src/lib/bm25.js +170 -0
  133. package/src/lib/cache.js +69 -6
  134. package/src/lib/config.js +8 -3
  135. package/src/lib/identity.js +99 -0
  136. package/src/lib/registry.js +103 -20
  137. package/src/lib/telemetry.js +86 -0
  138. package/src/mcp/server.js +177 -0
  139. package/src/mcp/tools.js +251 -0
@@ -0,0 +1,1330 @@
1
+ ---
2
+ name: payments
3
+ description: "Razorpay Python SDK coding guidelines for building payment systems with orders, payments, refunds, and subscriptions"
4
+ metadata:
5
+ languages: "python"
6
+ versions: "1.4.2"
7
+ updated-on: "2026-03-02"
8
+ source: maintainer
9
+ tags: "razorpay,payments,india,checkout,upi"
10
+ ---
11
+
12
+ # Razorpay Python Coding Guidelines
13
+
14
+ You are a Razorpay payment gateway coding expert. Help me with writing code using the Razorpay Python SDK for building payment systems with orders, payments, refunds, subscriptions, customers, and invoices.
15
+
16
+ Please follow the following guidelines when generating code.
17
+
18
+ You can find the official SDK documentation and code samples here:
19
+ https://razorpay.com/docs/payments/server-integration/python/
20
+
21
+ ## Golden Rule: Use the Correct and Current SDK
22
+
23
+ Always use the official Razorpay Python SDK, which is the standard library for all Razorpay API interactions.
24
+
25
+ **Library Name:** Razorpay Python SDK
26
+ **Python Package:** `razorpay`
27
+ **Current Version:** 1.4.2
28
+ **Supported Python Versions:** Python 3.12+
29
+
30
+ **Installation:**
31
+ - **Correct:** `pip install razorpay`
32
+
33
+ **APIs and Usage:**
34
+ - **Correct:** `import razorpay`
35
+ - **Correct:** `client = razorpay.Client(auth=("YOUR_KEY_ID", "YOUR_KEY_SECRET"))`
36
+ - **Correct:** `client.order.create(data={...})` for creating orders
37
+ - **Correct:** `client.payment.fetch(payment_id)` for fetching payments
38
+ - **Incorrect:** Using unofficial Razorpay libraries or wrappers
39
+ - **Incorrect:** Exposing credentials in client-side applications
40
+
41
+ ## Authentication and Initialization
42
+
43
+ The Razorpay Python library requires your Key ID and Key Secret for authentication. You can obtain these from the Razorpay Dashboard at Settings > API Keys.
44
+
45
+ ### Environment Variables (Recommended)
46
+
47
+ Set up environment variables for secure credential management:
48
+
49
+ ```python
50
+ import os
51
+ import razorpay
52
+ from dotenv import load_dotenv
53
+
54
+ # Load environment variables
55
+ load_dotenv()
56
+
57
+ # Initialize Razorpay client
58
+ client = razorpay.Client(auth=(
59
+ os.environ.get('RAZORPAY_KEY_ID'),
60
+ os.environ.get('RAZORPAY_KEY_SECRET')
61
+ ))
62
+ ```
63
+
64
+ ### Direct Initialization
65
+
66
+ ```python
67
+ import razorpay
68
+
69
+ # Initialize client with credentials
70
+ client = razorpay.Client(auth=(
71
+ 'rzp_test_xxxxxxxxxx',
72
+ 'your_key_secret_here'
73
+ ))
74
+ ```
75
+
76
+ ### Client Configuration Options
77
+
78
+ ```python
79
+ import razorpay
80
+
81
+ # Enable retry on network errors
82
+ client = razorpay.Client(auth=(
83
+ os.environ.get('RAZORPAY_KEY_ID'),
84
+ os.environ.get('RAZORPAY_KEY_SECRET')
85
+ ))
86
+
87
+ # Enable automatic retry
88
+ client.enable_retry(True)
89
+
90
+ # Set custom app details
91
+ client.set_app_details({
92
+ "title": "My Application",
93
+ "version": "1.0.0"
94
+ })
95
+ ```
96
+
97
+ ## Orders API
98
+
99
+ ### Create Order
100
+
101
+ Create an order before accepting payments from customers:
102
+
103
+ ```python
104
+ import razorpay
105
+ import os
106
+
107
+ client = razorpay.Client(auth=(
108
+ os.environ.get('RAZORPAY_KEY_ID'),
109
+ os.environ.get('RAZORPAY_KEY_SECRET')
110
+ ))
111
+
112
+ def create_order():
113
+ try:
114
+ data = {
115
+ 'amount': 50000, # Amount in paise (50000 paise = ₹500)
116
+ 'currency': 'INR',
117
+ 'receipt': 'receipt_order_12345',
118
+ 'notes': {
119
+ 'key1': 'value1',
120
+ 'key2': 'value2'
121
+ }
122
+ }
123
+
124
+ order = client.order.create(data=data)
125
+ print('Order ID:', order['id'])
126
+ print('Order:', order)
127
+ return order
128
+ except Exception as e:
129
+ print('Error creating order:', str(e))
130
+ raise
131
+ ```
132
+
133
+ ### Fetch Order Details
134
+
135
+ ```python
136
+ def fetch_order(order_id):
137
+ try:
138
+ order = client.order.fetch(order_id)
139
+ print('Order details:', order)
140
+ return order
141
+ except Exception as e:
142
+ print('Error fetching order:', str(e))
143
+ raise
144
+ ```
145
+
146
+ ### Fetch All Orders
147
+
148
+ ```python
149
+ def fetch_all_orders():
150
+ try:
151
+ options = {
152
+ 'count': 10, # Number of orders to fetch (default: 10, max: 100)
153
+ 'skip': 0, # Number of orders to skip (for pagination)
154
+ 'from': 1640995200, # Unix timestamp (fetch orders from this time)
155
+ 'to': 1672531199 # Unix timestamp (fetch orders till this time)
156
+ }
157
+
158
+ orders = client.order.all(options)
159
+ print('Orders:', orders)
160
+ return orders
161
+ except Exception as e:
162
+ print('Error fetching orders:', str(e))
163
+ raise
164
+ ```
165
+
166
+ ### Fetch Payments for an Order
167
+
168
+ ```python
169
+ def fetch_order_payments(order_id):
170
+ try:
171
+ payments = client.order.payments(order_id)
172
+ print('Payments for order:', payments)
173
+ return payments
174
+ except Exception as e:
175
+ print('Error fetching order payments:', str(e))
176
+ raise
177
+ ```
178
+
179
+ ### Update Order
180
+
181
+ ```python
182
+ def update_order(order_id):
183
+ try:
184
+ data = {
185
+ 'notes': {
186
+ 'updated_key': 'updated_value'
187
+ }
188
+ }
189
+
190
+ order = client.order.edit(order_id, data)
191
+ print('Order updated:', order)
192
+ return order
193
+ except Exception as e:
194
+ print('Error updating order:', str(e))
195
+ raise
196
+ ```
197
+
198
+ ## Payments API
199
+
200
+ ### Fetch Payment Details
201
+
202
+ ```python
203
+ def fetch_payment(payment_id):
204
+ try:
205
+ payment = client.payment.fetch(payment_id)
206
+ print('Payment details:', payment)
207
+ return payment
208
+ except Exception as e:
209
+ print('Error fetching payment:', str(e))
210
+ raise
211
+ ```
212
+
213
+ ### Fetch All Payments
214
+
215
+ ```python
216
+ def fetch_all_payments():
217
+ try:
218
+ options = {
219
+ 'count': 10,
220
+ 'skip': 0,
221
+ 'from': 1640995200,
222
+ 'to': 1672531199
223
+ }
224
+
225
+ payments = client.payment.all(options)
226
+ print('Payments:', payments)
227
+ return payments
228
+ except Exception as e:
229
+ print('Error fetching payments:', str(e))
230
+ raise
231
+ ```
232
+
233
+ ### Capture Payment
234
+
235
+ Capture an authorized payment:
236
+
237
+ ```python
238
+ def capture_payment(payment_id, amount):
239
+ try:
240
+ data = {
241
+ 'amount': amount, # Amount in paise
242
+ 'currency': 'INR'
243
+ }
244
+
245
+ payment = client.payment.capture(payment_id, amount)
246
+ print('Payment captured:', payment)
247
+ return payment
248
+ except Exception as e:
249
+ print('Error capturing payment:', str(e))
250
+ raise
251
+ ```
252
+
253
+ ### Update Payment
254
+
255
+ ```python
256
+ def update_payment(payment_id):
257
+ try:
258
+ data = {
259
+ 'notes': {
260
+ 'note_key_1': 'updated value 1',
261
+ 'note_key_2': 'updated value 2'
262
+ }
263
+ }
264
+
265
+ payment = client.payment.edit(payment_id, data)
266
+ print('Payment updated:', payment)
267
+ return payment
268
+ except Exception as e:
269
+ print('Error updating payment:', str(e))
270
+ raise
271
+ ```
272
+
273
+ ### Fetch Card Details
274
+
275
+ ```python
276
+ def fetch_card_details(payment_id):
277
+ try:
278
+ card = client.payment.fetch_card_details(payment_id)
279
+ print('Card details:', card)
280
+ return card
281
+ except Exception as e:
282
+ print('Error fetching card details:', str(e))
283
+ raise
284
+ ```
285
+
286
+ ## Refunds API
287
+
288
+ ### Create Refund
289
+
290
+ ```python
291
+ def create_refund(payment_id):
292
+ try:
293
+ data = {
294
+ 'amount': 10000, # Amount in paise to refund
295
+ 'speed': 'normal', # 'normal' or 'optimum'
296
+ 'notes': {
297
+ 'notes_key_1': 'Refund reason'
298
+ },
299
+ 'receipt': 'Receipt No. 31'
300
+ }
301
+
302
+ refund = client.payment.refund(payment_id, data)
303
+ print('Refund created:', refund)
304
+ return refund
305
+ except Exception as e:
306
+ print('Error creating refund:', str(e))
307
+ raise
308
+ ```
309
+
310
+ ### Fetch Refund Details
311
+
312
+ ```python
313
+ def fetch_refund(refund_id):
314
+ try:
315
+ refund = client.refund.fetch(refund_id)
316
+ print('Refund details:', refund)
317
+ return refund
318
+ except Exception as e:
319
+ print('Error fetching refund:', str(e))
320
+ raise
321
+ ```
322
+
323
+ ### Fetch All Refunds for a Payment
324
+
325
+ ```python
326
+ def fetch_payment_refunds(payment_id):
327
+ try:
328
+ refunds = client.payment.refunds(payment_id)
329
+ print('Refunds:', refunds)
330
+ return refunds
331
+ except Exception as e:
332
+ print('Error fetching refunds:', str(e))
333
+ raise
334
+ ```
335
+
336
+ ### Fetch All Refunds
337
+
338
+ ```python
339
+ def fetch_all_refunds():
340
+ try:
341
+ options = {
342
+ 'count': 10,
343
+ 'skip': 0,
344
+ 'from': 1640995200,
345
+ 'to': 1672531199
346
+ }
347
+
348
+ refunds = client.refund.all(options)
349
+ print('All refunds:', refunds)
350
+ return refunds
351
+ except Exception as e:
352
+ print('Error fetching all refunds:', str(e))
353
+ raise
354
+ ```
355
+
356
+ ### Update Refund
357
+
358
+ ```python
359
+ def update_refund(refund_id):
360
+ try:
361
+ data = {
362
+ 'notes': {
363
+ 'updated_note': 'Updated refund note'
364
+ }
365
+ }
366
+
367
+ refund = client.refund.edit(refund_id, data)
368
+ print('Refund updated:', refund)
369
+ return refund
370
+ except Exception as e:
371
+ print('Error updating refund:', str(e))
372
+ raise
373
+ ```
374
+
375
+ ## Customers API
376
+
377
+ ### Create Customer
378
+
379
+ ```python
380
+ def create_customer():
381
+ try:
382
+ data = {
383
+ 'name': 'John Doe',
384
+ 'email': 'john.doe@example.com',
385
+ 'contact': '+919876543210',
386
+ 'fail_existing': 0, # 0 to return existing customer if exists, 1 to fail
387
+ 'notes': {
388
+ 'customer_type': 'premium'
389
+ }
390
+ }
391
+
392
+ customer = client.customer.create(data)
393
+ print('Customer created:', customer)
394
+ return customer
395
+ except Exception as e:
396
+ print('Error creating customer:', str(e))
397
+ raise
398
+ ```
399
+
400
+ ### Fetch Customer Details
401
+
402
+ ```python
403
+ def fetch_customer(customer_id):
404
+ try:
405
+ customer = client.customer.fetch(customer_id)
406
+ print('Customer details:', customer)
407
+ return customer
408
+ except Exception as e:
409
+ print('Error fetching customer:', str(e))
410
+ raise
411
+ ```
412
+
413
+ ### Update Customer
414
+
415
+ ```python
416
+ def update_customer(customer_id):
417
+ try:
418
+ data = {
419
+ 'name': 'Jane Doe',
420
+ 'email': 'jane.doe@example.com',
421
+ 'contact': '+919876543211'
422
+ }
423
+
424
+ customer = client.customer.edit(customer_id, data)
425
+ print('Customer updated:', customer)
426
+ return customer
427
+ except Exception as e:
428
+ print('Error updating customer:', str(e))
429
+ raise
430
+ ```
431
+
432
+ ### Fetch All Customers
433
+
434
+ ```python
435
+ def fetch_all_customers():
436
+ try:
437
+ options = {
438
+ 'count': 10,
439
+ 'skip': 0
440
+ }
441
+
442
+ customers = client.customer.all(options)
443
+ print('Customers:', customers)
444
+ return customers
445
+ except Exception as e:
446
+ print('Error fetching customers:', str(e))
447
+ raise
448
+ ```
449
+
450
+ ## Subscriptions API
451
+
452
+ ### Create Subscription
453
+
454
+ ```python
455
+ import time
456
+
457
+ def create_subscription():
458
+ try:
459
+ data = {
460
+ 'plan_id': 'plan_xxxxxxxxxxxxx',
461
+ 'customer_notify': 1,
462
+ 'quantity': 1,
463
+ 'total_count': 12,
464
+ 'start_at': int(time.time()) + 86400, # Start after 1 day
465
+ 'addons': [
466
+ {
467
+ 'item': {
468
+ 'name': 'Extra Storage',
469
+ 'amount': 5000,
470
+ 'currency': 'INR'
471
+ }
472
+ }
473
+ ],
474
+ 'notes': {
475
+ 'subscription_type': 'premium'
476
+ }
477
+ }
478
+
479
+ subscription = client.subscription.create(data)
480
+ print('Subscription created:', subscription)
481
+ return subscription
482
+ except Exception as e:
483
+ print('Error creating subscription:', str(e))
484
+ raise
485
+ ```
486
+
487
+ ### Fetch Subscription Details
488
+
489
+ ```python
490
+ def fetch_subscription(subscription_id):
491
+ try:
492
+ subscription = client.subscription.fetch(subscription_id)
493
+ print('Subscription details:', subscription)
494
+ return subscription
495
+ except Exception as e:
496
+ print('Error fetching subscription:', str(e))
497
+ raise
498
+ ```
499
+
500
+ ### Cancel Subscription
501
+
502
+ ```python
503
+ def cancel_subscription(subscription_id):
504
+ try:
505
+ data = {
506
+ 'cancel_at_cycle_end': 0 # 0 to cancel immediately, 1 to cancel at end of cycle
507
+ }
508
+
509
+ subscription = client.subscription.cancel(subscription_id, data)
510
+ print('Subscription cancelled:', subscription)
511
+ return subscription
512
+ except Exception as e:
513
+ print('Error cancelling subscription:', str(e))
514
+ raise
515
+ ```
516
+
517
+ ### Fetch All Subscriptions
518
+
519
+ ```python
520
+ def fetch_all_subscriptions():
521
+ try:
522
+ options = {
523
+ 'count': 10,
524
+ 'skip': 0
525
+ }
526
+
527
+ subscriptions = client.subscription.all(options)
528
+ print('Subscriptions:', subscriptions)
529
+ return subscriptions
530
+ except Exception as e:
531
+ print('Error fetching subscriptions:', str(e))
532
+ raise
533
+ ```
534
+
535
+ ### Update Subscription
536
+
537
+ ```python
538
+ def update_subscription(subscription_id):
539
+ try:
540
+ data = {
541
+ 'plan_id': 'plan_yyyyyyyyyyy',
542
+ 'quantity': 2,
543
+ 'remaining_count': 6
544
+ }
545
+
546
+ subscription = client.subscription.edit(subscription_id, data)
547
+ print('Subscription updated:', subscription)
548
+ return subscription
549
+ except Exception as e:
550
+ print('Error updating subscription:', str(e))
551
+ raise
552
+ ```
553
+
554
+ ## Plans API
555
+
556
+ ### Create Plan
557
+
558
+ ```python
559
+ def create_plan():
560
+ try:
561
+ data = {
562
+ 'period': 'monthly',
563
+ 'interval': 1,
564
+ 'item': {
565
+ 'name': 'Premium Plan',
566
+ 'amount': 99900, # Amount in paise
567
+ 'currency': 'INR',
568
+ 'description': 'Premium monthly subscription'
569
+ },
570
+ 'notes': {
571
+ 'plan_type': 'premium'
572
+ }
573
+ }
574
+
575
+ plan = client.plan.create(data)
576
+ print('Plan created:', plan)
577
+ return plan
578
+ except Exception as e:
579
+ print('Error creating plan:', str(e))
580
+ raise
581
+ ```
582
+
583
+ ### Fetch Plan Details
584
+
585
+ ```python
586
+ def fetch_plan(plan_id):
587
+ try:
588
+ plan = client.plan.fetch(plan_id)
589
+ print('Plan details:', plan)
590
+ return plan
591
+ except Exception as e:
592
+ print('Error fetching plan:', str(e))
593
+ raise
594
+ ```
595
+
596
+ ### Fetch All Plans
597
+
598
+ ```python
599
+ def fetch_all_plans():
600
+ try:
601
+ options = {
602
+ 'count': 10,
603
+ 'skip': 0
604
+ }
605
+
606
+ plans = client.plan.all(options)
607
+ print('Plans:', plans)
608
+ return plans
609
+ except Exception as e:
610
+ print('Error fetching plans:', str(e))
611
+ raise
612
+ ```
613
+
614
+ ## Invoices API
615
+
616
+ ### Create Invoice
617
+
618
+ ```python
619
+ import time
620
+
621
+ def create_invoice():
622
+ try:
623
+ data = {
624
+ 'type': 'invoice',
625
+ 'description': 'Invoice for the month of January 2025',
626
+ 'customer': {
627
+ 'name': 'John Doe',
628
+ 'email': 'john.doe@example.com',
629
+ 'contact': '+919876543210'
630
+ },
631
+ 'line_items': [
632
+ {
633
+ 'name': 'Premium Subscription',
634
+ 'description': 'Monthly subscription',
635
+ 'amount': 99900,
636
+ 'currency': 'INR',
637
+ 'quantity': 1
638
+ }
639
+ ],
640
+ 'currency': 'INR',
641
+ 'email_notify': 1,
642
+ 'sms_notify': 1,
643
+ 'date': int(time.time())
644
+ }
645
+
646
+ invoice = client.invoice.create(data)
647
+ print('Invoice created:', invoice)
648
+ return invoice
649
+ except Exception as e:
650
+ print('Error creating invoice:', str(e))
651
+ raise
652
+ ```
653
+
654
+ ### Fetch Invoice Details
655
+
656
+ ```python
657
+ def fetch_invoice(invoice_id):
658
+ try:
659
+ invoice = client.invoice.fetch(invoice_id)
660
+ print('Invoice details:', invoice)
661
+ return invoice
662
+ except Exception as e:
663
+ print('Error fetching invoice:', str(e))
664
+ raise
665
+ ```
666
+
667
+ ### Fetch All Invoices
668
+
669
+ ```python
670
+ def fetch_all_invoices():
671
+ try:
672
+ options = {
673
+ 'count': 10,
674
+ 'skip': 0
675
+ }
676
+
677
+ invoices = client.invoice.all(options)
678
+ print('Invoices:', invoices)
679
+ return invoices
680
+ except Exception as e:
681
+ print('Error fetching invoices:', str(e))
682
+ raise
683
+ ```
684
+
685
+ ### Cancel Invoice
686
+
687
+ ```python
688
+ def cancel_invoice(invoice_id):
689
+ try:
690
+ invoice = client.invoice.cancel(invoice_id)
691
+ print('Invoice cancelled:', invoice)
692
+ return invoice
693
+ except Exception as e:
694
+ print('Error cancelling invoice:', str(e))
695
+ raise
696
+ ```
697
+
698
+ ### Issue Invoice
699
+
700
+ ```python
701
+ def issue_invoice(invoice_id):
702
+ try:
703
+ invoice = client.invoice.issue(invoice_id)
704
+ print('Invoice issued:', invoice)
705
+ return invoice
706
+ except Exception as e:
707
+ print('Error issuing invoice:', str(e))
708
+ raise
709
+ ```
710
+
711
+ ### Update Invoice
712
+
713
+ ```python
714
+ def update_invoice(invoice_id):
715
+ try:
716
+ data = {
717
+ 'notes': {
718
+ 'updated_note': 'Updated invoice note'
719
+ }
720
+ }
721
+
722
+ invoice = client.invoice.edit(invoice_id, data)
723
+ print('Invoice updated:', invoice)
724
+ return invoice
725
+ except Exception as e:
726
+ print('Error updating invoice:', str(e))
727
+ raise
728
+ ```
729
+
730
+ ## Payment Verification
731
+
732
+ ### Verify Payment Signature
733
+
734
+ Verify payment signatures to ensure payment authenticity:
735
+
736
+ ```python
737
+ import hmac
738
+ import hashlib
739
+
740
+ # Method 1: Using Razorpay's built-in utility
741
+ def verify_payment_signature(order_id, payment_id, signature):
742
+ try:
743
+ params_dict = {
744
+ 'razorpay_order_id': order_id,
745
+ 'razorpay_payment_id': payment_id,
746
+ 'razorpay_signature': signature
747
+ }
748
+
749
+ # This will raise SignatureVerificationError if signature is invalid
750
+ client.utility.verify_payment_signature(params_dict)
751
+ print('Payment signature verified successfully')
752
+ return True
753
+ except razorpay.errors.SignatureVerificationError as e:
754
+ print('Invalid payment signature:', str(e))
755
+ return False
756
+ except Exception as e:
757
+ print('Error verifying payment signature:', str(e))
758
+ return False
759
+
760
+ # Method 2: Manual verification
761
+ def verify_payment_signature_manual(order_id, payment_id, signature):
762
+ try:
763
+ key_secret = os.environ.get('RAZORPAY_KEY_SECRET')
764
+
765
+ # Create the expected signature
766
+ message = f"{order_id}|{payment_id}"
767
+ generated_signature = hmac.new(
768
+ key_secret.encode(),
769
+ message.encode(),
770
+ hashlib.sha256
771
+ ).hexdigest()
772
+
773
+ # Compare signatures
774
+ is_valid = hmac.compare_digest(generated_signature, signature)
775
+
776
+ if is_valid:
777
+ print('Payment signature verified successfully')
778
+ return True
779
+ else:
780
+ print('Invalid payment signature')
781
+ return False
782
+ except Exception as e:
783
+ print('Error verifying payment signature:', str(e))
784
+ return False
785
+ ```
786
+
787
+ ## Webhook Handling and Validation
788
+
789
+ ### Flask Webhook Integration
790
+
791
+ Handle and validate incoming Razorpay webhooks:
792
+
793
+ ```python
794
+ from flask import Flask, request, jsonify
795
+ import razorpay
796
+ import os
797
+ import hmac
798
+ import hashlib
799
+
800
+ app = Flask(__name__)
801
+
802
+ client = razorpay.Client(auth=(
803
+ os.environ.get('RAZORPAY_KEY_ID'),
804
+ os.environ.get('RAZORPAY_KEY_SECRET')
805
+ ))
806
+
807
+ def validate_webhook_signature(webhook_body, signature, secret):
808
+ """Validate webhook signature"""
809
+ try:
810
+ generated_signature = hmac.new(
811
+ secret.encode(),
812
+ webhook_body,
813
+ hashlib.sha256
814
+ ).hexdigest()
815
+
816
+ return hmac.compare_digest(generated_signature, signature)
817
+ except Exception as e:
818
+ print('Error validating webhook:', str(e))
819
+ return False
820
+
821
+ @app.route('/webhook', methods=['POST'])
822
+ def handle_webhook():
823
+ # Get the webhook signature from headers
824
+ signature = request.headers.get('X-Razorpay-Signature')
825
+ webhook_secret = os.environ.get('RAZORPAY_WEBHOOK_SECRET')
826
+
827
+ # Get raw request body
828
+ webhook_body = request.get_data()
829
+
830
+ # Validate signature
831
+ is_valid = validate_webhook_signature(webhook_body, signature, webhook_secret)
832
+
833
+ if not is_valid:
834
+ return jsonify({'error': 'Invalid signature'}), 400
835
+
836
+ # Parse webhook event
837
+ event = request.get_json()
838
+
839
+ print('Webhook event:', event.get('event'))
840
+
841
+ # Handle different event types
842
+ event_type = event.get('event')
843
+
844
+ if event_type == 'payment.authorized':
845
+ handle_payment_authorized(event['payload']['payment']['entity'])
846
+ elif event_type == 'payment.captured':
847
+ handle_payment_captured(event['payload']['payment']['entity'])
848
+ elif event_type == 'payment.failed':
849
+ handle_payment_failed(event['payload']['payment']['entity'])
850
+ elif event_type == 'order.paid':
851
+ handle_order_paid(event['payload']['order']['entity'])
852
+ elif event_type == 'refund.created':
853
+ handle_refund_created(event['payload']['refund']['entity'])
854
+ elif event_type == 'subscription.activated':
855
+ handle_subscription_activated(event['payload']['subscription']['entity'])
856
+ elif event_type == 'subscription.cancelled':
857
+ handle_subscription_cancelled(event['payload']['subscription']['entity'])
858
+ elif event_type == 'invoice.paid':
859
+ handle_invoice_paid(event['payload']['invoice']['entity'])
860
+ else:
861
+ print('Unhandled event:', event_type)
862
+
863
+ return jsonify({'status': 'ok'}), 200
864
+
865
+ def handle_payment_authorized(payment):
866
+ print('Payment authorized:', payment['id'])
867
+ # Capture the payment or perform other actions
868
+
869
+ def handle_payment_captured(payment):
870
+ print('Payment captured:', payment['id'])
871
+ # Update order status, send confirmation email, etc.
872
+
873
+ def handle_payment_failed(payment):
874
+ print('Payment failed:', payment['id'])
875
+ # Notify customer, update order status, etc.
876
+
877
+ def handle_order_paid(order):
878
+ print('Order paid:', order['id'])
879
+ # Process order fulfillment
880
+
881
+ def handle_refund_created(refund):
882
+ print('Refund created:', refund['id'])
883
+ # Update records, notify customer
884
+
885
+ def handle_subscription_activated(subscription):
886
+ print('Subscription activated:', subscription['id'])
887
+ # Grant access to subscription features
888
+
889
+ def handle_subscription_cancelled(subscription):
890
+ print('Subscription cancelled:', subscription['id'])
891
+ # Revoke access, send cancellation email
892
+
893
+ def handle_invoice_paid(invoice):
894
+ print('Invoice paid:', invoice['id'])
895
+ # Update invoice status, send receipt
896
+
897
+ if __name__ == '__main__':
898
+ app.run(port=3000, debug=True)
899
+ ```
900
+
901
+ ### Using Razorpay's Webhook Verification Utility
902
+
903
+ ```python
904
+ @app.route('/webhook', methods=['POST'])
905
+ def handle_webhook_with_utility():
906
+ signature = request.headers.get('X-Razorpay-Signature')
907
+ webhook_secret = os.environ.get('RAZORPAY_WEBHOOK_SECRET')
908
+ webhook_body = request.get_data().decode('utf-8')
909
+
910
+ try:
911
+ # Verify webhook signature using Razorpay utility
912
+ client.utility.verify_webhook_signature(
913
+ webhook_body,
914
+ signature,
915
+ webhook_secret
916
+ )
917
+
918
+ # Process webhook event
919
+ event = request.get_json()
920
+ # Handle event...
921
+
922
+ return jsonify({'status': 'ok'}), 200
923
+ except razorpay.errors.SignatureVerificationError:
924
+ return jsonify({'error': 'Invalid signature'}), 400
925
+ ```
926
+
927
+ ## Transfers API (Route)
928
+
929
+ ### Create Transfer
930
+
931
+ Transfer funds to linked accounts:
932
+
933
+ ```python
934
+ def create_transfer(payment_id):
935
+ try:
936
+ data = {
937
+ 'transfers': [
938
+ {
939
+ 'account': 'acc_xxxxxxxxxxxxx',
940
+ 'amount': 10000, # Amount in paise
941
+ 'currency': 'INR',
942
+ 'notes': {
943
+ 'name': 'Transfer to vendor',
944
+ 'roll_no': 'IEC2011025'
945
+ },
946
+ 'linked_account_notes': ['branch'],
947
+ 'on_hold': 0, # 0 to transfer immediately, 1 to hold
948
+ 'on_hold_until': None
949
+ }
950
+ ]
951
+ }
952
+
953
+ transfer = client.payment.transfer(payment_id, data)
954
+ print('Transfer created:', transfer)
955
+ return transfer
956
+ except Exception as e:
957
+ print('Error creating transfer:', str(e))
958
+ raise
959
+ ```
960
+
961
+ ### Fetch Transfer Details
962
+
963
+ ```python
964
+ def fetch_transfer(transfer_id):
965
+ try:
966
+ transfer = client.transfer.fetch(transfer_id)
967
+ print('Transfer details:', transfer)
968
+ return transfer
969
+ except Exception as e:
970
+ print('Error fetching transfer:', str(e))
971
+ raise
972
+ ```
973
+
974
+ ### Fetch All Transfers
975
+
976
+ ```python
977
+ def fetch_all_transfers():
978
+ try:
979
+ options = {
980
+ 'count': 10,
981
+ 'skip': 0
982
+ }
983
+
984
+ transfers = client.transfer.all(options)
985
+ print('Transfers:', transfers)
986
+ return transfers
987
+ except Exception as e:
988
+ print('Error fetching transfers:', str(e))
989
+ raise
990
+ ```
991
+
992
+ ## Virtual Accounts API
993
+
994
+ ### Create Virtual Account
995
+
996
+ ```python
997
+ import time
998
+
999
+ def create_virtual_account():
1000
+ try:
1001
+ data = {
1002
+ 'receivers': {
1003
+ 'types': ['bank_account']
1004
+ },
1005
+ 'description': 'Virtual Account for customer XYZ',
1006
+ 'customer_id': 'cust_xxxxxxxxxxxxx',
1007
+ 'close_by': int(time.time()) + 86400 * 30, # Close after 30 days
1008
+ 'notes': {
1009
+ 'purpose': 'Rent collection'
1010
+ }
1011
+ }
1012
+
1013
+ virtual_account = client.virtual_account.create(data)
1014
+ print('Virtual Account created:', virtual_account)
1015
+ return virtual_account
1016
+ except Exception as e:
1017
+ print('Error creating virtual account:', str(e))
1018
+ raise
1019
+ ```
1020
+
1021
+ ### Fetch Virtual Account Details
1022
+
1023
+ ```python
1024
+ def fetch_virtual_account(va_id):
1025
+ try:
1026
+ virtual_account = client.virtual_account.fetch(va_id)
1027
+ print('Virtual Account details:', virtual_account)
1028
+ return virtual_account
1029
+ except Exception as e:
1030
+ print('Error fetching virtual account:', str(e))
1031
+ raise
1032
+ ```
1033
+
1034
+ ### Fetch All Virtual Accounts
1035
+
1036
+ ```python
1037
+ def fetch_all_virtual_accounts():
1038
+ try:
1039
+ options = {
1040
+ 'count': 10,
1041
+ 'skip': 0
1042
+ }
1043
+
1044
+ virtual_accounts = client.virtual_account.all(options)
1045
+ print('Virtual Accounts:', virtual_accounts)
1046
+ return virtual_accounts
1047
+ except Exception as e:
1048
+ print('Error fetching virtual accounts:', str(e))
1049
+ raise
1050
+ ```
1051
+
1052
+ ### Close Virtual Account
1053
+
1054
+ ```python
1055
+ def close_virtual_account(va_id):
1056
+ try:
1057
+ virtual_account = client.virtual_account.close(va_id)
1058
+ print('Virtual Account closed:', virtual_account)
1059
+ return virtual_account
1060
+ except Exception as e:
1061
+ print('Error closing virtual account:', str(e))
1062
+ raise
1063
+ ```
1064
+
1065
+ ## Error Handling
1066
+
1067
+ ### Comprehensive Error Handling
1068
+
1069
+ ```python
1070
+ import razorpay.errors as errors
1071
+
1072
+ def safe_api_call():
1073
+ try:
1074
+ data = {
1075
+ 'amount': 50000,
1076
+ 'currency': 'INR',
1077
+ 'receipt': 'receipt_12345'
1078
+ }
1079
+
1080
+ order = client.order.create(data=data)
1081
+
1082
+ return {
1083
+ 'success': True,
1084
+ 'data': order
1085
+ }
1086
+ except errors.BadRequestError as e:
1087
+ print('Bad Request Error:', e)
1088
+ return {
1089
+ 'success': False,
1090
+ 'error': {
1091
+ 'code': 400,
1092
+ 'message': str(e)
1093
+ }
1094
+ }
1095
+ except errors.UnauthorizedError as e:
1096
+ print('Unauthorized Error:', e)
1097
+ return {
1098
+ 'success': False,
1099
+ 'error': {
1100
+ 'code': 401,
1101
+ 'message': 'Invalid API credentials'
1102
+ }
1103
+ }
1104
+ except errors.ServerError as e:
1105
+ print('Server Error:', e)
1106
+ return {
1107
+ 'success': False,
1108
+ 'error': {
1109
+ 'code': 500,
1110
+ 'message': 'Razorpay server error'
1111
+ }
1112
+ }
1113
+ except errors.GatewayError as e:
1114
+ print('Gateway Error:', e)
1115
+ return {
1116
+ 'success': False,
1117
+ 'error': {
1118
+ 'code': 502,
1119
+ 'message': 'Gateway error occurred'
1120
+ }
1121
+ }
1122
+ except Exception as e:
1123
+ print('Unknown error:', e)
1124
+ return {
1125
+ 'success': False,
1126
+ 'error': {
1127
+ 'code': 500,
1128
+ 'message': str(e)
1129
+ }
1130
+ }
1131
+ ```
1132
+
1133
+ ### Specific Error Handling
1134
+
1135
+ ```python
1136
+ def handle_specific_errors():
1137
+ try:
1138
+ payment = client.payment.fetch('pay_xxxxxxxxxxxxx')
1139
+ return payment
1140
+ except errors.BadRequestError as e:
1141
+ print('Bad Request - Invalid parameters')
1142
+ raise
1143
+ except errors.UnauthorizedError as e:
1144
+ print('Unauthorized - Invalid API credentials')
1145
+ raise
1146
+ except errors.NotFoundError as e:
1147
+ print('Not Found - Resource does not exist')
1148
+ raise
1149
+ except errors.ServerError as e:
1150
+ print('Internal Server Error - Razorpay issue')
1151
+ raise
1152
+ except Exception as e:
1153
+ print('Unknown error:', str(e))
1154
+ raise
1155
+ ```
1156
+
1157
+ ## Complete Payment Flow Example
1158
+
1159
+ ### Flask Server Integration
1160
+
1161
+ ```python
1162
+ from flask import Flask, request, jsonify
1163
+ import razorpay
1164
+ import os
1165
+ import time
1166
+
1167
+ app = Flask(__name__)
1168
+
1169
+ client = razorpay.Client(auth=(
1170
+ os.environ.get('RAZORPAY_KEY_ID'),
1171
+ os.environ.get('RAZORPAY_KEY_SECRET')
1172
+ ))
1173
+
1174
+ # Step 1: Create order
1175
+ @app.route('/create-order', methods=['POST'])
1176
+ def create_order():
1177
+ try:
1178
+ data = request.get_json()
1179
+ amount = data.get('amount')
1180
+ currency = data.get('currency', 'INR')
1181
+
1182
+ order_data = {
1183
+ 'amount': amount * 100, # Convert to paise
1184
+ 'currency': currency,
1185
+ 'receipt': f"receipt_{int(time.time())}",
1186
+ 'notes': {
1187
+ 'description': 'Order payment'
1188
+ }
1189
+ }
1190
+
1191
+ order = client.order.create(data=order_data)
1192
+
1193
+ return jsonify({
1194
+ 'success': True,
1195
+ 'order': {
1196
+ 'id': order['id'],
1197
+ 'amount': order['amount'],
1198
+ 'currency': order['currency']
1199
+ },
1200
+ 'key_id': os.environ.get('RAZORPAY_KEY_ID')
1201
+ }), 200
1202
+ except Exception as e:
1203
+ print('Error creating order:', str(e))
1204
+ return jsonify({
1205
+ 'success': False,
1206
+ 'message': 'Failed to create order'
1207
+ }), 500
1208
+
1209
+ # Step 2: Verify payment
1210
+ @app.route('/verify-payment', methods=['POST'])
1211
+ def verify_payment():
1212
+ try:
1213
+ data = request.get_json()
1214
+ razorpay_order_id = data.get('razorpay_order_id')
1215
+ razorpay_payment_id = data.get('razorpay_payment_id')
1216
+ razorpay_signature = data.get('razorpay_signature')
1217
+
1218
+ params_dict = {
1219
+ 'razorpay_order_id': razorpay_order_id,
1220
+ 'razorpay_payment_id': razorpay_payment_id,
1221
+ 'razorpay_signature': razorpay_signature
1222
+ }
1223
+
1224
+ # Verify signature
1225
+ client.utility.verify_payment_signature(params_dict)
1226
+
1227
+ # Payment is successful, fetch payment details
1228
+ payment = client.payment.fetch(razorpay_payment_id)
1229
+
1230
+ return jsonify({
1231
+ 'success': True,
1232
+ 'message': 'Payment verified successfully',
1233
+ 'payment': {
1234
+ 'id': payment['id'],
1235
+ 'amount': payment['amount'],
1236
+ 'status': payment['status']
1237
+ }
1238
+ }), 200
1239
+ except razorpay.errors.SignatureVerificationError:
1240
+ return jsonify({
1241
+ 'success': False,
1242
+ 'message': 'Payment verification failed'
1243
+ }), 400
1244
+ except Exception as e:
1245
+ print('Error verifying payment:', str(e))
1246
+ return jsonify({
1247
+ 'success': False,
1248
+ 'message': 'Payment verification error'
1249
+ }), 500
1250
+
1251
+ # Step 3: Fetch payment details
1252
+ @app.route('/payment/<payment_id>', methods=['GET'])
1253
+ def get_payment(payment_id):
1254
+ try:
1255
+ payment = client.payment.fetch(payment_id)
1256
+ return jsonify({
1257
+ 'success': True,
1258
+ 'payment': payment
1259
+ }), 200
1260
+ except Exception as e:
1261
+ print('Error fetching payment:', str(e))
1262
+ return jsonify({
1263
+ 'success': False,
1264
+ 'message': 'Failed to fetch payment'
1265
+ }), 500
1266
+
1267
+ if __name__ == '__main__':
1268
+ app.run(port=3000, debug=True)
1269
+ ```
1270
+
1271
+ ## Security Best Practices
1272
+
1273
+ ### Never Expose Credentials
1274
+
1275
+ ```python
1276
+ # Good - Use environment variables
1277
+ import os
1278
+
1279
+ client = razorpay.Client(auth=(
1280
+ os.environ.get('RAZORPAY_KEY_ID'),
1281
+ os.environ.get('RAZORPAY_KEY_SECRET')
1282
+ ))
1283
+
1284
+ # Bad - Hardcoded credentials
1285
+ client = razorpay.Client(auth=(
1286
+ 'rzp_test_xxxxxxxxxxxx',
1287
+ 'your_secret_here'
1288
+ ))
1289
+ ```
1290
+
1291
+ ### Always Validate Webhooks
1292
+
1293
+ ```python
1294
+ # Always verify webhook signatures before processing
1295
+ is_valid = validate_webhook_signature(
1296
+ webhook_body,
1297
+ signature,
1298
+ os.environ.get('RAZORPAY_WEBHOOK_SECRET')
1299
+ )
1300
+
1301
+ if not is_valid:
1302
+ return jsonify({'error': 'Invalid signature'}), 400
1303
+ ```
1304
+
1305
+ ### Verify Payment Signatures
1306
+
1307
+ ```python
1308
+ # Always verify payment signatures on the server
1309
+ params_dict = {
1310
+ 'razorpay_order_id': order_id,
1311
+ 'razorpay_payment_id': payment_id,
1312
+ 'razorpay_signature': signature
1313
+ }
1314
+
1315
+ client.utility.verify_payment_signature(params_dict)
1316
+ ```
1317
+
1318
+ ## Useful Links
1319
+
1320
+ - **Documentation:** https://razorpay.com/docs/
1321
+ - **API Reference:** https://razorpay.com/docs/api/
1322
+ - **Python SDK Docs:** https://razorpay.com/docs/payments/server-integration/python/
1323
+ - **PyPI Package:** https://pypi.org/project/razorpay/
1324
+ - **GitHub Repository:** https://github.com/razorpay/razorpay-python
1325
+ - **Dashboard:** https://dashboard.razorpay.com/
1326
+ - **Support:** https://razorpay.com/support/
1327
+
1328
+ ## Notes
1329
+
1330
+ This guide covers the core functionality of the Razorpay Python SDK. The SDK provides comprehensive support for all Razorpay services including payments, orders, refunds, subscriptions, customers, invoices, transfers, and virtual accounts. Always use environment variables for credentials and validate all payment signatures and webhook signatures to ensure security. The SDK requires Python 3.12 or higher and provides utilities for payment verification and webhook signature validation.