jebin2 commited on
Commit
b51ac5b
·
1 Parent(s): 74c51df
Files changed (1) hide show
  1. routers/payments.py +101 -60
routers/payments.py CHANGED
@@ -122,6 +122,86 @@ def generate_transaction_id() -> str:
122
  return f"txn_{uuid.uuid4().hex[:16]}"
123
 
124
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
125
  # =============================================================================
126
  # Endpoints
127
  # =============================================================================
@@ -261,16 +341,10 @@ async def verify_payment(
261
  detail="Transaction not found"
262
  )
263
 
264
- # Check if already processed
265
  if transaction.status == "paid":
266
- # Still update verified_by to track that client also called verify
267
- if transaction.verified_by == "webhook":
268
- transaction.verified_by = "both"
269
- await db.commit()
270
- logger.info(
271
- f"Payment {transaction.transaction_id} was already verified by webhook, "
272
- f"client also verified - marked as 'both'"
273
- )
274
 
275
  return VerifyPaymentResponse(
276
  success=True,
@@ -301,34 +375,21 @@ async def verify_payment(
301
  detail="Payment verification failed"
302
  )
303
 
304
- # Update transaction
305
- transaction.status = "paid"
306
- transaction.gateway_payment_id = request.razorpay_payment_id
307
- transaction.razorpay_signature = request.razorpay_signature
308
- transaction.paid_at = datetime.utcnow()
309
-
310
- # Track who verified - if webhook already set it, mark as "both"
311
- if transaction.verified_by == "webhook":
312
- transaction.verified_by = "both"
313
- else:
314
- transaction.verified_by = "client"
315
-
316
- # Add credits to user
317
- user.credits += transaction.credits_amount
318
-
319
- await db.commit()
320
-
321
- logger.info(
322
- f"Payment verified: {transaction.transaction_id}, "
323
- f"added {transaction.credits_amount} credits to user {user.user_id}, "
324
- f"new balance: {user.credits}"
325
  )
326
 
327
  return VerifyPaymentResponse(
328
  success=True,
329
  message="Payment successful! Credits added.",
330
  transaction_id=transaction.transaction_id,
331
- credits_added=transaction.credits_amount,
332
  new_balance=user.credits
333
  )
334
 
@@ -398,41 +459,21 @@ async def razorpay_webhook(
398
  )
399
  transaction = result.scalar_one_or_none()
400
 
401
- if transaction and transaction.status != "paid":
402
- # Update transaction
403
- transaction.status = "paid"
404
- transaction.gateway_payment_id = payment_id
405
- transaction.paid_at = datetime.utcnow()
406
-
407
- # Track who verified - if client already set it, mark as "both"
408
- if transaction.verified_by == "client":
409
- transaction.verified_by = "both"
410
- else:
411
- transaction.verified_by = "webhook"
412
-
413
- # Find user and add credits
414
  user_result = await db.execute(
415
  select(User).where(User.user_id == transaction.user_id)
416
  )
417
  user = user_result.scalar_one_or_none()
418
 
419
  if user:
420
- user.credits += transaction.credits_amount
421
- logger.info(
422
- f"Webhook: Added {transaction.credits_amount} credits "
423
- f"to user {user.user_id} for transaction {transaction.transaction_id}"
424
- )
425
-
426
- await db.commit()
427
-
428
- elif transaction and transaction.status == "paid":
429
- # Transaction already paid by client - update verified_by to "both"
430
- if transaction.verified_by == "client":
431
- transaction.verified_by = "both"
432
- await db.commit()
433
- logger.info(
434
- f"Webhook: Transaction {transaction.transaction_id} was already "
435
- f"verified by client - marked as 'both'"
436
  )
437
 
438
  # Handle payment failed event
 
122
  return f"txn_{uuid.uuid4().hex[:16]}"
123
 
124
 
125
+ def update_verified_by(transaction: PaymentTransaction, source: str) -> bool:
126
+ """
127
+ Update the verified_by field based on the verification source.
128
+
129
+ Args:
130
+ transaction: The payment transaction to update
131
+ source: Either "client" or "webhook"
132
+
133
+ Returns:
134
+ True if the value was changed, False otherwise
135
+ """
136
+ current = transaction.verified_by
137
+ other = "webhook" if source == "client" else "client"
138
+
139
+ if current == other:
140
+ # Already verified by the other source, mark as "both"
141
+ transaction.verified_by = "both"
142
+ return True
143
+ elif current is None or current == source:
144
+ # First verification or same source
145
+ transaction.verified_by = source
146
+ return current != source
147
+ # Already "both" or same value - no change needed
148
+ return False
149
+
150
+
151
+ async def process_successful_payment(
152
+ transaction: PaymentTransaction,
153
+ user: User,
154
+ payment_id: str,
155
+ source: str,
156
+ db: AsyncSession,
157
+ signature: Optional[str] = None
158
+ ) -> int:
159
+ """
160
+ Process a successful payment - update transaction and add credits.
161
+
162
+ Args:
163
+ transaction: The payment transaction
164
+ user: The user to credit
165
+ payment_id: Gateway payment ID
166
+ source: "client" or "webhook"
167
+ db: Database session
168
+ signature: Optional Razorpay signature (client-side only)
169
+
170
+ Returns:
171
+ Number of credits added (0 if already processed)
172
+ """
173
+ credits_added = 0
174
+
175
+ if transaction.status != "paid":
176
+ # First time processing - add credits
177
+ transaction.status = "paid"
178
+ transaction.gateway_payment_id = payment_id
179
+ transaction.paid_at = datetime.utcnow()
180
+ if signature:
181
+ transaction.razorpay_signature = signature
182
+
183
+ update_verified_by(transaction, source)
184
+
185
+ user.credits += transaction.credits_amount
186
+ credits_added = transaction.credits_amount
187
+
188
+ logger.info(
189
+ f"Payment processed ({source}): {transaction.transaction_id}, "
190
+ f"added {credits_added} credits to user {user.user_id}, "
191
+ f"new balance: {user.credits}"
192
+ )
193
+ else:
194
+ # Already paid - just update verified_by if needed
195
+ if update_verified_by(transaction, source):
196
+ logger.info(
197
+ f"Payment {transaction.transaction_id} was already verified, "
198
+ f"{source} also verified - marked as '{transaction.verified_by}'"
199
+ )
200
+
201
+ await db.commit()
202
+ return credits_added
203
+
204
+
205
  # =============================================================================
206
  # Endpoints
207
  # =============================================================================
 
341
  detail="Transaction not found"
342
  )
343
 
344
+ # Check if already processed - still track verification source
345
  if transaction.status == "paid":
346
+ update_verified_by(transaction, "client")
347
+ await db.commit()
 
 
 
 
 
 
348
 
349
  return VerifyPaymentResponse(
350
  success=True,
 
375
  detail="Payment verification failed"
376
  )
377
 
378
+ # Process the payment using helper function
379
+ credits_added = await process_successful_payment(
380
+ transaction=transaction,
381
+ user=user,
382
+ payment_id=request.razorpay_payment_id,
383
+ source="client",
384
+ db=db,
385
+ signature=request.razorpay_signature
 
 
 
 
 
 
 
 
 
 
 
 
 
386
  )
387
 
388
  return VerifyPaymentResponse(
389
  success=True,
390
  message="Payment successful! Credits added.",
391
  transaction_id=transaction.transaction_id,
392
+ credits_added=credits_added,
393
  new_balance=user.credits
394
  )
395
 
 
459
  )
460
  transaction = result.scalar_one_or_none()
461
 
462
+ if transaction:
463
+ # Find user
 
 
 
 
 
 
 
 
 
 
 
464
  user_result = await db.execute(
465
  select(User).where(User.user_id == transaction.user_id)
466
  )
467
  user = user_result.scalar_one_or_none()
468
 
469
  if user:
470
+ # Process payment using helper function
471
+ await process_successful_payment(
472
+ transaction=transaction,
473
+ user=user,
474
+ payment_id=payment_id,
475
+ source="webhook",
476
+ db=db
 
 
 
 
 
 
 
 
 
477
  )
478
 
479
  # Handle payment failed event