This commit is contained in:
Krzysztof Czerwinski 2025-01-03 16:26:03 +01:00
parent c6eaa580dd
commit 7958143323
7 changed files with 28 additions and 18 deletions

View File

@ -80,7 +80,9 @@ class UserCreditBase(ABC):
pass pass
@abstractmethod @abstractmethod
async def fulfill_checkout(self, *, session_id: str | None = None, user_id: str | None = None): async def fulfill_checkout(
self, *, session_id: str | None = None, user_id: str | None = None
):
""" """
Fulfill the Stripe checkout session. Fulfill the Stripe checkout session.
@ -260,7 +262,7 @@ class UserCredit(UserCreditBase):
# Create checkout session # Create checkout session
# https://docs.stripe.com/checkout/quickstart?client=react # https://docs.stripe.com/checkout/quickstart?client=react
# unit_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 # which is equal to amount of credits
checkout_session = stripe.checkout.Session.create( checkout_session = stripe.checkout.Session.create(
customer=user.stripeCustomerId, customer=user.stripeCustomerId,
line_items=[ line_items=[
@ -297,21 +299,25 @@ class UserCredit(UserCreditBase):
return checkout_session.url or "" return checkout_session.url or ""
# https://docs.stripe.com/checkout/fulfillment # https://docs.stripe.com/checkout/fulfillment
async def fulfill_checkout(self, *, session_id: str | None = None, user_id: str | None = None): async def fulfill_checkout(
self, *, session_id: str | None = None, user_id: str | None = None
):
if (not session_id and not user_id) or (session_id and user_id): if (not session_id and not user_id) or (session_id and user_id):
raise ValueError("Either session_id or user_id must be provided") raise ValueError("Either session_id or user_id must be provided")
# Retrieve CreditTransaction # Retrieve CreditTransaction
credit_transaction = await CreditTransaction.prisma().find_first_or_raise( credit_transaction = await CreditTransaction.prisma().find_first_or_raise(
where={ where={
"OR": [ "OR": [
{"transactionKey": session_id} if session_id is not None else {"transactionKey": ""}, (
{"userId": user_id} if user_id is not None else {"userId": ""} {"transactionKey": session_id}
if session_id is not None
else {"transactionKey": ""}
),
{"userId": user_id} if user_id is not None else {"userId": ""},
] ]
}, },
order={ order={"createdAt": "desc"},
"createdAt": "desc"
}
) )
# This can be called multiple times for one id, so ignore if already fulfilled # This can be called multiple times for one id, so ignore if already fulfilled
@ -319,7 +325,9 @@ class UserCredit(UserCreditBase):
return return
# Retrieve the Checkout Session from the API # Retrieve the Checkout Session from the API
checkout_session = stripe.checkout.Session.retrieve(credit_transaction.transactionKey) checkout_session = stripe.checkout.Session.retrieve(
credit_transaction.transactionKey
)
# Check the Checkout Session's payment_status property # Check the Checkout Session's payment_status property
# to determine if fulfillment should be peformed # to determine if fulfillment should be peformed

View File

@ -179,7 +179,9 @@ async def stripe_webhook(request: Request):
event["type"] == "checkout.session.completed" event["type"] == "checkout.session.completed"
or event["type"] == "checkout.session.async_payment_succeeded" or event["type"] == "checkout.session.async_payment_succeeded"
): ):
await _user_credit_model.fulfill_checkout(session_id=event["data"]["object"]["id"]) await _user_credit_model.fulfill_checkout(
session_id=event["data"]["object"]["id"]
)
return Response(status_code=200) return Response(status_code=200)

View File

@ -18,7 +18,7 @@ export default function CreditsPage() {
api.fulfillCheckout(); api.fulfillCheckout();
setPatched(true); setPatched(true);
} }
}, [topupStatus]); }, [api, patched, topupStatus]);
return ( return (
<div className="w-full min-w-[800px] px-4 sm:px-8"> <div className="w-full min-w-[800px] px-4 sm:px-8">

View File

@ -33,14 +33,14 @@ export default function Page({}: {}) {
} catch (error) { } catch (error) {
console.error("Error fetching submissions:", error); console.error("Error fetching submissions:", error);
} }
}, [api, supabase]); }, [api]);
useEffect(() => { useEffect(() => {
if (!supabase) { if (!supabase) {
return; return;
} }
fetchData(); fetchData();
}, [supabase]); }, [supabase, fetchData]);
const onEditSubmission = useCallback((submission: StoreSubmissionRequest) => { const onEditSubmission = useCallback((submission: StoreSubmissionRequest) => {
setSubmissionData(submission); setSubmissionData(submission);
@ -56,7 +56,7 @@ export default function Page({}: {}) {
api.deleteStoreSubmission(submission_id); api.deleteStoreSubmission(submission_id);
fetchData(); fetchData();
}, },
[supabase], [api, supabase, fetchData],
); );
const onOpenPopout = useCallback(() => { const onOpenPopout = useCallback(() => {

View File

@ -61,7 +61,7 @@ function SearchResults({
}; };
fetchData(); fetchData();
}, [searchTerm, sort]); }, [api, searchTerm, sort]);
const agentsCount = agents.length; const agentsCount = agents.length;
const creatorsCount = creators.length; const creatorsCount = creators.length;

View File

@ -873,7 +873,7 @@ export default function useAgentGraph(
request: "save", request: "save",
state: "saving", state: "saving",
}); });
}, [saveAgent]); }, [saveAgent, saveRunRequest.state]);
const requestSaveAndRun = useCallback(() => { const requestSaveAndRun = useCallback(() => {
saveAgent(); saveAgent();

View File

@ -19,7 +19,7 @@ export default function useCredits(): {
const fetchCredits = useCallback(async () => { const fetchCredits = useCallback(async () => {
const response = await api.getUserCredit(); const response = await api.getUserCredit();
setCredits(response.credits); setCredits(response.credits);
}, []); }, [api]);
useEffect(() => { useEffect(() => {
fetchCredits(); fetchCredits();