Update payment micro-service to handle status update

This commit is contained in:
jetli 2025-01-22 00:21:54 -08:00
parent d47823124f
commit 9f5e0d1706
3 changed files with 127 additions and 2 deletions

View File

@ -84,3 +84,16 @@ class PaymentHub:
return await self.stripe_manager.invoke_checkout_session_webhook( return await self.stripe_manager.invoke_checkout_session_webhook(
payload, stripe_signature payload, stripe_signature
) )
async def handle_account_update(
self,
account_id: str,
details_submitted: bool,
payouts_enabled: bool,
charges_enabled: bool
) -> bool:
return await self.payment_manager.update_stripe_account_status(
account_id,
setup=details_submitted,
verified=payouts_enabled and charges_enabled
)

View File

@ -1,11 +1,13 @@
from typing import Dict, Optional from typing import Dict, Optional
from backend.services.project.models import ProjectDoc from backend.services.project.models import ProjectDoc
from backend.services.payment.models import IncomeProfileDoc from backend.services.payment.models import IncomeProfileDoc
from datetime import datetime
from common.log.module_logger import ModuleLogger
class PaymentManager: class PaymentManager:
def __init__(self) -> None: def __init__(self) -> None:
pass self.module_logger = ModuleLogger(sender_id=PaymentManager)
async def fetch_wechat_qr_code(self, project_id: str) -> Optional[Dict[str, any]]: async def fetch_wechat_qr_code(self, project_id: str) -> Optional[Dict[str, any]]:
project = await ProjectDoc.get(project_id) project = await ProjectDoc.get(project_id)
@ -26,3 +28,79 @@ class PaymentManager:
0 0
].stripe_account_id ].stripe_account_id
return None return None
async def update_stripe_account_status(
self,
stripe_account_id: str,
setup: bool,
verified: bool
) -> bool:
try:
# Should use IncomeProfileDoc to be consistent with other methods
payment_profile = await IncomeProfileDoc.find_one(
{"bank_account.money_collecting_methods": {
"$elemMatch": {
"stripe_account_id": stripe_account_id
}
}}
)
if not payment_profile:
await self.module_logger.log_warning(
warning="No payment profile found for Stripe account",
properties={
"stripe_account_id": stripe_account_id,
"action": "update_stripe_account_status"
}
)
return False
# Update the stripe method status
updated = False
# Need to check if money_collecting_methods exists and is not empty
if payment_profile.bank_account and payment_profile.bank_account.money_collecting_methods:
for method in payment_profile.bank_account.money_collecting_methods:
if method.stripe_account_id == stripe_account_id:
method.setup = setup
method.verified = verified
method.last_update_time = int(datetime.now().timestamp())
updated = True
break # Exit loop once found and updated
if updated:
await payment_profile.save()
await self.module_logger.log_info(
info="Successfully updated Stripe account status",
properties={
"stripe_account_id": stripe_account_id,
"user_id": payment_profile.user_id,
"setup": setup,
"verified": verified
}
)
return True
# Log warning with more context
await self.module_logger.log_warning(
warning="Stripe account not found in payment methods",
properties={
"stripe_account_id": stripe_account_id,
"user_id": payment_profile.user_id if payment_profile else None,
"has_bank_account": bool(payment_profile and payment_profile.bank_account),
"has_methods": bool(payment_profile and payment_profile.bank_account and payment_profile.bank_account.money_collecting_methods)
}
)
return False
except Exception as e:
await self.module_logger.log_exception(
exception=e,
info="Failed to update Stripe account status",
properties={
"stripe_account_id": stripe_account_id,
"setup": setup,
"verified": verified,
"error": str(e)
}
)
return False

View File

@ -1,9 +1,10 @@
from fastapi import APIRouter from fastapi import APIRouter, Request, Header
from backend.application.payment_hub import PaymentHub from backend.application.payment_hub import PaymentHub
from typing import Dict, Optional, Tuple from typing import Dict, Optional, Tuple
from decimal import Decimal from decimal import Decimal
from fastapi.responses import JSONResponse from fastapi.responses import JSONResponse
from fastapi.encoders import jsonable_encoder from fastapi.encoders import jsonable_encoder
import stripe
router = APIRouter() router = APIRouter()
payment_hub = PaymentHub() payment_hub = PaymentHub()
@ -184,3 +185,36 @@ async def fetch_checkout_session_url(transaction_id: str) -> Optional[str]:
) )
async def invoke_checkout_session_webhook(payload: str, stripe_signature: str): async def invoke_checkout_session_webhook(payload: str, stripe_signature: str):
return await payment_hub.invoke_checkout_session_webhook(payload, stripe_signature) return await payment_hub.invoke_checkout_session_webhook(payload, stripe_signature)
@router.post(
"/webhook/account",
operation_id="stripe_account_webhook",
summary="Handle Stripe account webhook events",
)
async def handle_account_webhook(
request: Request,
stripe_signature: str = Header(None)
):
payload = await request.body()
try:
event = stripe.Webhook.construct_event(
payload,
stripe_signature,
app_settings.STRIPE_WEBHOOK_SECRET
)
# Handle account.updated event
if event.type == 'account.updated':
account = event.data.object
return await payment_hub.handle_account_update(
account_id=account.id,
details_submitted=account.details_submitted,
payouts_enabled=account.payouts_enabled,
charges_enabled=account.charges_enabled
)
except Exception as e:
raise HTTPException(status_code=400, detail=str(e))
return JSONResponse(content={"status": "success"})