Fix top-up credit amounts
This commit is contained in:
parent
b3d7804ba1
commit
7063751bb0
|
@ -72,7 +72,7 @@ class UserCreditBase(ABC):
|
|||
|
||||
Args:
|
||||
user_id (str): The user ID.
|
||||
amount (int): The amount to top up.
|
||||
amount (int): The amount of credits to top up.
|
||||
|
||||
Returns:
|
||||
str: The redirect url to the payment page.
|
||||
|
@ -231,7 +231,7 @@ class UserCredit(UserCreditBase):
|
|||
async def top_up_credits(self, user_id: str, amount: int):
|
||||
if amount < 0:
|
||||
raise ValueError(f"Top up amount must not be negative: {amount}")
|
||||
|
||||
|
||||
await CreditTransaction.prisma().create(
|
||||
data={
|
||||
"userId": user_id,
|
||||
|
@ -258,7 +258,8 @@ class UserCredit(UserCreditBase):
|
|||
|
||||
# Create checkout session
|
||||
# https://docs.stripe.com/checkout/quickstart?client=react
|
||||
# amount param is always in the smallest currency unit (so cents for usd)
|
||||
# unit_amount param is always in the smallest currency unit (so cents for usd)
|
||||
# which equals to amount of credits
|
||||
checkout_session = stripe.checkout.Session.create(
|
||||
customer=user.stripeCustomerId,
|
||||
line_items=[
|
||||
|
@ -268,7 +269,7 @@ class UserCredit(UserCreditBase):
|
|||
"product_data": {
|
||||
"name": "AutoGPT Platform Credits",
|
||||
},
|
||||
"unit_amount": amount * 100,
|
||||
"unit_amount": amount,
|
||||
},
|
||||
"quantity": 1,
|
||||
}
|
||||
|
|
|
@ -60,3 +60,4 @@ class UpdatePermissionsRequest(pydantic.BaseModel):
|
|||
|
||||
class RequestTopUp(pydantic.BaseModel):
|
||||
amount: int
|
||||
"""Amount of credits to top up."""
|
||||
|
|
|
@ -3,7 +3,6 @@ import logging
|
|||
from collections import defaultdict
|
||||
from typing import TYPE_CHECKING, Annotated, Any, Sequence
|
||||
|
||||
from fastapi.responses import RedirectResponse
|
||||
import pydantic
|
||||
import stripe
|
||||
from autogpt_libs.auth.middleware import auth_middleware
|
||||
|
@ -42,9 +41,9 @@ from backend.server.model import (
|
|||
CreateAPIKeyRequest,
|
||||
CreateAPIKeyResponse,
|
||||
CreateGraph,
|
||||
RequestTopUp,
|
||||
SetGraphActiveVersion,
|
||||
UpdatePermissionsRequest,
|
||||
RequestTopUp,
|
||||
)
|
||||
from backend.server.utils import get_user_id
|
||||
from backend.util.service import get_service_client
|
||||
|
@ -137,10 +136,12 @@ async def get_user_credits(
|
|||
user_id: Annotated[str, Depends(get_user_id)],
|
||||
) -> dict[str, int]:
|
||||
# Credits can go negative, so ensure it's at least 0 for user to see.
|
||||
return {"credits": max(await _user_credit_model.get_or_refill_credit(user_id), 0)}
|
||||
return {"credits": max(await _user_credit_model.get_credits(user_id), 0)}
|
||||
|
||||
|
||||
@v1_router.post(path="/credits", tags=["credits"], dependencies=[Depends(auth_middleware)])
|
||||
@v1_router.post(
|
||||
path="/credits", tags=["credits"], dependencies=[Depends(auth_middleware)]
|
||||
)
|
||||
async def request_top_up(
|
||||
request: RequestTopUp, user_id: Annotated[str, Depends(get_user_id)]
|
||||
):
|
||||
|
@ -153,7 +154,7 @@ async def stripe_webhook(request: Request):
|
|||
# Get the raw request body
|
||||
payload = await request.body()
|
||||
# Get the signature header
|
||||
sig_header = request.headers.get('stripe-signature')
|
||||
sig_header = request.headers.get("stripe-signature")
|
||||
|
||||
try:
|
||||
event = stripe.Webhook.construct_event(
|
||||
|
@ -165,14 +166,12 @@ async def stripe_webhook(request: Request):
|
|||
except stripe.SignatureVerificationError:
|
||||
# Invalid signature
|
||||
raise HTTPException(status_code=400)
|
||||
|
||||
print(event)
|
||||
|
||||
if (
|
||||
event['type'] == 'checkout.session.completed'
|
||||
or event['type'] == 'checkout.session.async_payment_succeeded'
|
||||
event["type"] == "checkout.session.completed"
|
||||
or event["type"] == "checkout.session.async_payment_succeeded"
|
||||
):
|
||||
await _user_credit_model.fulfill_checkout(event['data']['object']['id'])
|
||||
await _user_credit_model.fulfill_checkout(event["data"]["object"]["id"])
|
||||
|
||||
return Response(status_code=200)
|
||||
|
||||
|
|
|
@ -167,7 +167,10 @@ export default function PrivatePage() {
|
|||
min="5"
|
||||
step="1"
|
||||
/>
|
||||
<Button onClick={() => requestTopUp(amount)} className="whitespace-nowrap">
|
||||
<Button
|
||||
onClick={() => requestTopUp(amount)}
|
||||
className="whitespace-nowrap"
|
||||
>
|
||||
Top-Up
|
||||
</Button>
|
||||
</div>
|
||||
|
|
|
@ -3,12 +3,14 @@ import { useCallback, useEffect, useMemo, useState } from "react";
|
|||
import { loadStripe } from "@stripe/stripe-js";
|
||||
import { useRouter } from "next/navigation";
|
||||
|
||||
const stripePromise = loadStripe(process.env.NEXT_PUBLIC_STRIPE_PUBLISHABLE_KEY!);
|
||||
const stripePromise = loadStripe(
|
||||
process.env.NEXT_PUBLIC_STRIPE_PUBLISHABLE_KEY!,
|
||||
);
|
||||
|
||||
export default function useCredits(): {
|
||||
credits: number | null;
|
||||
fetchCredits: () => void;
|
||||
requestTopUp: (amount: number) => Promise<void>;
|
||||
requestTopUp: (usd_amount: number) => Promise<void>;
|
||||
} {
|
||||
const [credits, setCredits] = useState<number | null>(null);
|
||||
const api = useMemo(() => new AutoGPTServerAPI(), []);
|
||||
|
@ -23,18 +25,24 @@ export default function useCredits(): {
|
|||
fetchCredits();
|
||||
}, [fetchCredits]);
|
||||
|
||||
const requestTopUp = useCallback(async (amount: number) => {
|
||||
const stripe = await stripePromise;
|
||||
const requestTopUp = useCallback(
|
||||
async (usd_amount: number) => {
|
||||
const stripe = await stripePromise;
|
||||
|
||||
if (!stripe) {
|
||||
console.error("Stripe failed to load");
|
||||
return;
|
||||
}
|
||||
if (!stripe) {
|
||||
console.error("Stripe failed to load");
|
||||
return;
|
||||
}
|
||||
|
||||
const response = await api.requestTopUp(amount);
|
||||
// Convert dollar amount to credit count
|
||||
const response = await api.requestTopUp(usd_amount * 100);
|
||||
|
||||
router.push(response.checkout_url);
|
||||
}, [api]);
|
||||
console.log(response);
|
||||
|
||||
router.push(response.checkout_url);
|
||||
},
|
||||
[api],
|
||||
);
|
||||
|
||||
return {
|
||||
credits,
|
||||
|
|
Loading…
Reference in New Issue