feat: migrate payment service escrow operations to use centralized aitbc package HTTP client
Some checks failed
Some checks failed
- Replace httpx.AsyncClient with aitbc.AITBCHTTPClient in _create_bitcoin_escrow, release_payment, refund_payment - Remove async context manager in favor of direct AITBCHTTPClient usage - Replace status code checks with NetworkError exception handling - Remove httpx import (no longer needed) - Remove blank line after aitbc imports - Consistent error handling across all escrow operations
This commit is contained in:
@@ -10,7 +10,6 @@ from datetime import datetime, timedelta
|
|||||||
from __future__ import annotations
|
from __future__ import annotations
|
||||||
|
|
||||||
from aitbc import get_logger, AITBCHTTPClient, NetworkError
|
from aitbc import get_logger, AITBCHTTPClient, NetworkError
|
||||||
|
|
||||||
logger = get_logger(__name__)
|
logger = get_logger(__name__)
|
||||||
|
|
||||||
from ..domain.payment import JobPayment, PaymentEscrow
|
from ..domain.payment import JobPayment, PaymentEscrow
|
||||||
@@ -114,35 +113,36 @@ class PaymentService:
|
|||||||
async def _create_bitcoin_escrow(self, payment: JobPayment) -> None:
|
async def _create_bitcoin_escrow(self, payment: JobPayment) -> None:
|
||||||
"""Create an escrow for Bitcoin payments (exchange only)"""
|
"""Create an escrow for Bitcoin payments (exchange only)"""
|
||||||
try:
|
try:
|
||||||
async with httpx.AsyncClient() as client:
|
client = AITBCHTTPClient(timeout=30.0)
|
||||||
|
try:
|
||||||
# Call wallet daemon to create escrow
|
# Call wallet daemon to create escrow
|
||||||
response = await client.post(
|
escrow_data = client.post(
|
||||||
f"{self.wallet_base_url}/api/v1/escrow/create",
|
f"{self.wallet_base_url}/api/v1/escrow/create",
|
||||||
json={"amount": float(payment.amount), "currency": payment.currency, "timeout_seconds": 3600}, # 1 hour
|
json={"amount": float(payment.amount), "currency": payment.currency, "timeout_seconds": 3600}, # 1 hour
|
||||||
)
|
)
|
||||||
|
payment.escrow_address = escrow_data["address"]
|
||||||
|
payment.status = "escrowed"
|
||||||
|
payment.escrowed_at = datetime.utcnow()
|
||||||
|
payment.updated_at = datetime.utcnow()
|
||||||
|
|
||||||
if response.status_code == 200:
|
# Create escrow record
|
||||||
escrow_data = response.json()
|
escrow = PaymentEscrow(
|
||||||
payment.escrow_address = escrow_data["address"]
|
payment_id=payment.id,
|
||||||
payment.status = "escrowed"
|
amount=payment.amount,
|
||||||
payment.escrowed_at = datetime.utcnow()
|
currency=payment.currency,
|
||||||
payment.updated_at = datetime.utcnow()
|
address=escrow_data["address"],
|
||||||
|
expires_at=datetime.utcnow() + timedelta(hours=1),
|
||||||
|
)
|
||||||
|
if escrow is not None:
|
||||||
|
self.session.add(escrow)
|
||||||
|
|
||||||
# Create escrow record
|
self.session.commit()
|
||||||
escrow = PaymentEscrow(
|
logger.info(f"Created Bitcoin escrow for payment {payment.id}")
|
||||||
payment_id=payment.id,
|
except NetworkError as e:
|
||||||
amount=payment.amount,
|
logger.error(f"Failed to create Bitcoin escrow: {e}")
|
||||||
currency=payment.currency,
|
payment.status = "failed"
|
||||||
address=escrow_data["address"],
|
payment.updated_at = datetime.utcnow()
|
||||||
expires_at=datetime.utcnow() + timedelta(hours=1),
|
self.session.commit()
|
||||||
)
|
|
||||||
if escrow is not None:
|
|
||||||
self.session.add(escrow)
|
|
||||||
|
|
||||||
self.session.commit()
|
|
||||||
logger.info(f"Created Bitcoin escrow for payment {payment.id}")
|
|
||||||
else:
|
|
||||||
logger.error(f"Failed to create Bitcoin escrow: {response.text}")
|
|
||||||
|
|
||||||
except Exception as e:
|
except Exception as e:
|
||||||
logger.error(f"Error creating Bitcoin escrow: {e}")
|
logger.error(f"Error creating Bitcoin escrow: {e}")
|
||||||
@@ -161,37 +161,35 @@ class PaymentService:
|
|||||||
return False
|
return False
|
||||||
|
|
||||||
try:
|
try:
|
||||||
async with httpx.AsyncClient() as client:
|
client = AITBCHTTPClient(timeout=30.0)
|
||||||
|
try:
|
||||||
# Call wallet daemon to release escrow
|
# Call wallet daemon to release escrow
|
||||||
response = await client.post(
|
release_data = client.post(
|
||||||
f"{self.wallet_base_url}/api/v1/escrow/release",
|
f"{self.wallet_base_url}/api/v1/escrow/release",
|
||||||
json={"address": payment.escrow_address, "reason": reason or "Job completed successfully"},
|
json={"address": payment.escrow_address, "reason": reason or "Job completed successfully"},
|
||||||
)
|
)
|
||||||
|
payment.status = "released"
|
||||||
|
payment.released_at = datetime.utcnow()
|
||||||
|
payment.updated_at = datetime.utcnow()
|
||||||
|
payment.transaction_hash = release_data.get("transaction_hash")
|
||||||
|
|
||||||
if response.status_code == 200:
|
# Update escrow record
|
||||||
release_data = response.json()
|
escrow = (
|
||||||
payment.status = "released"
|
self.session.execute(select(PaymentEscrow).where(PaymentEscrow.payment_id == payment_id))
|
||||||
payment.released_at = datetime.utcnow()
|
.scalars()
|
||||||
payment.updated_at = datetime.utcnow()
|
.first()
|
||||||
payment.transaction_hash = release_data.get("transaction_hash")
|
)
|
||||||
|
|
||||||
# Update escrow record
|
if escrow:
|
||||||
escrow = (
|
escrow.is_released = True
|
||||||
self.session.execute(select(PaymentEscrow).where(PaymentEscrow.payment_id == payment_id))
|
escrow.released_at = datetime.utcnow()
|
||||||
.scalars()
|
|
||||||
.first()
|
|
||||||
)
|
|
||||||
|
|
||||||
if escrow:
|
self.session.commit()
|
||||||
escrow.is_released = True
|
logger.info(f"Released payment {payment_id} for job {job_id}")
|
||||||
escrow.released_at = datetime.utcnow()
|
return True
|
||||||
|
except NetworkError as e:
|
||||||
self.session.commit()
|
logger.error(f"Failed to release payment: {e}")
|
||||||
logger.info(f"Released payment {payment_id} for job {job_id}")
|
return False
|
||||||
return True
|
|
||||||
else:
|
|
||||||
logger.error(f"Failed to release payment: {response.text}")
|
|
||||||
return False
|
|
||||||
|
|
||||||
except Exception as e:
|
except Exception as e:
|
||||||
logger.error(f"Error releasing payment: {e}")
|
logger.error(f"Error releasing payment: {e}")
|
||||||
@@ -208,9 +206,10 @@ class PaymentService:
|
|||||||
return False
|
return False
|
||||||
|
|
||||||
try:
|
try:
|
||||||
async with httpx.AsyncClient() as client:
|
client = AITBCHTTPClient(timeout=30.0)
|
||||||
|
try:
|
||||||
# Call wallet daemon to refund
|
# Call wallet daemon to refund
|
||||||
response = await client.post(
|
refund_data = client.post(
|
||||||
f"{self.wallet_base_url}/api/v1/refund",
|
f"{self.wallet_base_url}/api/v1/refund",
|
||||||
json={
|
json={
|
||||||
"payment_id": payment_id,
|
"payment_id": payment_id,
|
||||||
@@ -219,31 +218,28 @@ class PaymentService:
|
|||||||
"reason": reason,
|
"reason": reason,
|
||||||
},
|
},
|
||||||
)
|
)
|
||||||
|
payment.status = "refunded"
|
||||||
|
payment.refunded_at = datetime.utcnow()
|
||||||
|
payment.updated_at = datetime.utcnow()
|
||||||
|
payment.refund_transaction_hash = refund_data.get("transaction_hash")
|
||||||
|
|
||||||
if response.status_code == 200:
|
# Update escrow record
|
||||||
refund_data = response.json()
|
escrow = (
|
||||||
payment.status = "refunded"
|
self.session.execute(select(PaymentEscrow).where(PaymentEscrow.payment_id == payment_id))
|
||||||
payment.refunded_at = datetime.utcnow()
|
.scalars()
|
||||||
payment.updated_at = datetime.utcnow()
|
.first()
|
||||||
payment.refund_transaction_hash = refund_data.get("transaction_hash")
|
)
|
||||||
|
|
||||||
# Update escrow record
|
if escrow:
|
||||||
escrow = (
|
escrow.is_refunded = True
|
||||||
self.session.execute(select(PaymentEscrow).where(PaymentEscrow.payment_id == payment_id))
|
escrow.refunded_at = datetime.utcnow()
|
||||||
.scalars()
|
|
||||||
.first()
|
|
||||||
)
|
|
||||||
|
|
||||||
if escrow:
|
self.session.commit()
|
||||||
escrow.is_refunded = True
|
logger.info(f"Refunded payment {payment_id} for job {job_id}")
|
||||||
escrow.refunded_at = datetime.utcnow()
|
return True
|
||||||
|
except NetworkError as e:
|
||||||
self.session.commit()
|
logger.error(f"Failed to refund payment: {e}")
|
||||||
logger.info(f"Refunded payment {payment_id} for job {job_id}")
|
return False
|
||||||
return True
|
|
||||||
else:
|
|
||||||
logger.error(f"Failed to refund payment: {response.text}")
|
|
||||||
return False
|
|
||||||
|
|
||||||
except Exception as e:
|
except Exception as e:
|
||||||
logger.error(f"Error refunding payment: {e}")
|
logger.error(f"Error refunding payment: {e}")
|
||||||
|
|||||||
Reference in New Issue
Block a user