181 lines
5.5 KiB
Python
181 lines
5.5 KiB
Python
from http import HTTPStatus
|
|
|
|
from fastapi import APIRouter, Depends, HTTPException
|
|
from loguru import logger
|
|
from pydantic import BaseModel
|
|
|
|
from lnbits.core.crud.settings import set_settings_field
|
|
from lnbits.core.models.misc import SimpleStatus
|
|
from lnbits.core.models.wallets import WalletTypeInfo
|
|
from lnbits.core.services import update_cached_settings
|
|
from lnbits.core.services.fiat_providers import test_connection
|
|
from lnbits.decorators import check_admin, require_admin_key
|
|
from lnbits.fiat import RevolutWallet, StripeWallet, get_fiat_provider
|
|
from lnbits.fiat.base import CreateFiatSubscription, FiatSubscriptionResponse
|
|
|
|
fiat_router = APIRouter(tags=["Fiat API"], prefix="/api/v1/fiat")
|
|
|
|
|
|
class RevolutCreateWebhook(BaseModel):
|
|
url: str
|
|
endpoint: str | None = None
|
|
api_secret_key: str | None = None
|
|
api_version: str | None = None
|
|
|
|
|
|
class RevolutCreateWebhookResponse(BaseModel):
|
|
id: str | None = None
|
|
url: str
|
|
events: list[str] = []
|
|
signing_secret: str
|
|
already_exists: bool = False
|
|
|
|
|
|
@fiat_router.put(
|
|
"/check/{provider}",
|
|
status_code=HTTPStatus.OK,
|
|
dependencies=[Depends(check_admin)],
|
|
)
|
|
async def api_test_fiat_provider(provider: str) -> SimpleStatus:
|
|
return await test_connection(provider)
|
|
|
|
|
|
@fiat_router.post(
|
|
"/revolut/webhook",
|
|
status_code=HTTPStatus.OK,
|
|
dependencies=[Depends(check_admin)],
|
|
)
|
|
async def api_create_revolut_webhook(
|
|
data: RevolutCreateWebhook,
|
|
) -> RevolutCreateWebhookResponse:
|
|
try:
|
|
webhook = await RevolutWallet.create_webhook(
|
|
url=data.url,
|
|
endpoint=data.endpoint,
|
|
api_secret_key=data.api_secret_key,
|
|
api_version=data.api_version,
|
|
)
|
|
except ValueError as exc:
|
|
logger.warning(exc)
|
|
raise HTTPException(status_code=400, detail=str(exc)) from exc
|
|
except Exception as exc:
|
|
logger.warning(exc)
|
|
raise HTTPException(
|
|
status_code=500, detail="Failed to create Revolut webhook."
|
|
) from exc
|
|
|
|
signing_secret = webhook.get("signing_secret")
|
|
webhook_url = webhook.get("url") or data.url
|
|
if not signing_secret:
|
|
raise HTTPException(
|
|
status_code=502, detail="Revolut returned no webhook signing secret."
|
|
)
|
|
|
|
updated_settings = {
|
|
"revolut_payment_webhook_url": webhook_url,
|
|
"revolut_webhook_signing_secret": signing_secret,
|
|
}
|
|
for key, value in updated_settings.items():
|
|
await set_settings_field(key, value)
|
|
update_cached_settings(updated_settings)
|
|
|
|
return RevolutCreateWebhookResponse(
|
|
id=webhook.get("id"),
|
|
url=webhook_url,
|
|
events=webhook.get("events") or [],
|
|
signing_secret=signing_secret,
|
|
already_exists=webhook.get("already_exists", False),
|
|
)
|
|
|
|
|
|
@fiat_router.post(
|
|
"/{provider}/subscription",
|
|
status_code=HTTPStatus.OK,
|
|
)
|
|
async def create_subscription(
|
|
provider: str,
|
|
data: CreateFiatSubscription,
|
|
key_type: WalletTypeInfo = Depends(require_admin_key),
|
|
) -> FiatSubscriptionResponse:
|
|
logger.debug(
|
|
f"Creating subscription with provider '{provider}. '"
|
|
f"Subscription ID '{data.subscription_id}'."
|
|
)
|
|
|
|
fiat_provider = await get_fiat_provider(provider)
|
|
if not fiat_provider:
|
|
raise HTTPException(404, "Fiat provider not found")
|
|
|
|
wallet_id = data.payment_options.wallet_id
|
|
|
|
if wallet_id and wallet_id != key_type.wallet.id:
|
|
raise HTTPException(
|
|
403,
|
|
"Wallet id does not match your API key."
|
|
"Leave it empty to use your key's wallet.",
|
|
)
|
|
|
|
data.payment_options.wallet_id = key_type.wallet.id
|
|
subscription_response = await fiat_provider.create_subscription(
|
|
data.subscription_id, data.quantity, data.payment_options
|
|
)
|
|
if subscription_response.error_message:
|
|
logger.warning(
|
|
f"Failed to create subscription with provider '{provider}': "
|
|
f"{subscription_response.error_message}"
|
|
)
|
|
|
|
return subscription_response
|
|
|
|
|
|
@fiat_router.delete(
|
|
"/{provider}/subscription/{subscription_id}",
|
|
status_code=HTTPStatus.OK,
|
|
)
|
|
async def cancel_subscription(
|
|
provider: str,
|
|
subscription_id: str,
|
|
key_type: WalletTypeInfo = Depends(require_admin_key),
|
|
) -> FiatSubscriptionResponse:
|
|
fiat_provider = await get_fiat_provider(provider)
|
|
if not fiat_provider:
|
|
raise HTTPException(404, "Fiat provider not found")
|
|
|
|
resp = await fiat_provider.cancel_subscription(subscription_id, key_type.wallet.id)
|
|
|
|
return resp
|
|
|
|
|
|
@fiat_router.post(
|
|
"/{provider}/connection_token",
|
|
status_code=HTTPStatus.OK,
|
|
dependencies=[Depends(check_admin)],
|
|
)
|
|
async def connection_token(provider: str):
|
|
fiat_provider = await get_fiat_provider(provider)
|
|
if not fiat_provider:
|
|
raise HTTPException(status_code=404, detail="Fiat provider not found")
|
|
|
|
if provider != "stripe":
|
|
raise HTTPException(
|
|
status_code=400,
|
|
detail=f"Connection tokens are not supported for provider '{provider}'.",
|
|
)
|
|
|
|
if not isinstance(fiat_provider, StripeWallet):
|
|
raise HTTPException(
|
|
status_code=500, detail="Stripe wallet/provider not configured"
|
|
)
|
|
try:
|
|
tok = await fiat_provider.create_terminal_connection_token()
|
|
secret = tok.get("secret")
|
|
if not secret:
|
|
raise HTTPException(
|
|
status_code=502, detail="Stripe returned no connection token"
|
|
)
|
|
return {"secret": secret}
|
|
except Exception as e:
|
|
raise HTTPException(
|
|
status_code=500, detail="Failed to create connection token"
|
|
) from e
|