Skip to content

Commit c6d91cb

Browse files
committed
feat: support redirect URL in payment link after the purchase is complete
1 parent b638697 commit c6d91cb

File tree

8 files changed

+88
-5
lines changed

8 files changed

+88
-5
lines changed

python/stripe_agent_toolkit/functions.py

Lines changed: 5 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -154,13 +154,14 @@ def list_prices(
154154
return stripe.Price.list(**prices_data).data
155155

156156

157-
def create_payment_link(context: Context, price: str, quantity: int):
157+
def create_payment_link(context: Context, price: str, quantity: int, redirect_url: Optional[str] = None):
158158
"""
159159
Create a payment link.
160160
161161
Parameters:
162162
price (str): The ID of the price.
163163
quantity (int): The quantity of the product.
164+
redirect_url (string, optional): The URL the customer will be redirected to after the purchase is complete.
164165
165166
Returns:
166167
stripe.PaymentLink: The created payment link.
@@ -173,6 +174,9 @@ def create_payment_link(context: Context, price: str, quantity: int):
173174
if account is not None:
174175
payment_link_data["stripe_account"] = account
175176

177+
if redirect_url:
178+
payment_link_data["after_completion"] = {"type": "redirect", "redirect": {"url": redirect_url}}
179+
176180
payment_link = stripe.PaymentLink.create(**payment_link_data)
177181

178182
return {"id": payment_link.id, "url": payment_link.url}

python/stripe_agent_toolkit/prompts.py

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -51,6 +51,7 @@
5151
It takes two arguments:
5252
- price (str): The ID of the price to create the payment link for.
5353
- quantity (int): The quantity of the product to include in the payment link.
54+
- redirect_url (string, optional): The URL the customer will be redirected to after the purchase is complete.
5455
"""
5556

5657
LIST_INVOICES_PROMPT = """

python/stripe_agent_toolkit/schema.py

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -104,6 +104,10 @@ class CreatePaymentLink(BaseModel):
104104
...,
105105
description="The quantity of the product to include.",
106106
)
107+
redirect_url: Optional[str] = Field(
108+
None,
109+
description="The URL the customer will be redirected to after the purchase is complete.",
110+
)
107111

108112

109113
class ListInvoices(BaseModel):

python/tests/test_functions.py

Lines changed: 18 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -343,6 +343,24 @@ def test_create_payment_link(self):
343343

344344
self.assertEqual(result, mock_payment_link)
345345

346+
def test_create_payment_link_with_redirect_url(self):
347+
with mock.patch("stripe.PaymentLink.create") as mock_function:
348+
mock_payment_link = {"id": "pl_123", "url": "https://example.com"}
349+
mock_function.return_value = stripe.PaymentLink.construct_from(
350+
mock_payment_link, "sk_test_123"
351+
)
352+
353+
result = create_payment_link(
354+
context={}, price="price_123", quantity=1, redirect_url="https://example.com"
355+
)
356+
357+
mock_function.assert_called_with(
358+
line_items=[{"price": "price_123", "quantity": 1, }],
359+
after_completion={"type": "redirect", "redirect": {"url": "https://example.com"}}
360+
)
361+
362+
self.assertEqual(result, mock_payment_link)
363+
346364
def test_create_payment_link_with_context(self):
347365
with mock.patch("stripe.PaymentLink.create") as mock_function:
348366
mock_payment_link = {"id": "pl_123", "url": "https://example.com"}

typescript/src/shared/paymentLinks/createPaymentLink.ts

Lines changed: 16 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -9,6 +9,7 @@ This tool will create a payment link in Stripe.
99
It takes two arguments:
1010
- price (str): The ID of the price to create the payment link for.
1111
- quantity (int): The quantity of the product to include in the payment link.
12+
- redirect_url (str, optional): The URL to redirect to after the payment is completed.
1213
`;
1314

1415
export const createPaymentLink = async (
@@ -19,7 +20,17 @@ export const createPaymentLink = async (
1920
try {
2021
const paymentLink = await stripe.paymentLinks.create(
2122
{
22-
line_items: [params],
23+
line_items: [{price: params.price, quantity: params.quantity}],
24+
...(params.redirect_url
25+
? {
26+
after_completion: {
27+
type: 'redirect',
28+
redirect: {
29+
url: params.redirect_url,
30+
},
31+
},
32+
}
33+
: undefined),
2334
},
2435
context.account ? {stripeAccount: context.account} : undefined
2536
);
@@ -39,6 +50,10 @@ export const createPaymentLinkParameters = (_context: Context = {}) =>
3950
.number()
4051
.int()
4152
.describe('The quantity of the product to include.'),
53+
redirect_url: z
54+
.string()
55+
.optional()
56+
.describe('The URL to redirect to after the payment is completed.'),
4257
});
4358

4459
const tool = (context: Context): Tool => ({

typescript/src/test/shared/paymentLinks/functions.test.ts

Lines changed: 35 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -72,4 +72,39 @@ describe('createPaymentLink', () => {
7272
});
7373
expect(result).toEqual(mockPaymentLink);
7474
});
75+
76+
it('should specify the redirect URL if included in params', async () => {
77+
const params = {
78+
line_items: [
79+
{
80+
price: 'price_123456',
81+
quantity: 1,
82+
},
83+
],
84+
after_completion: {
85+
type: 'redirect',
86+
redirect: {
87+
url: 'https://example.com',
88+
},
89+
},
90+
};
91+
92+
const mockPaymentLink = {
93+
id: 'pl_123456',
94+
url: 'https://example.com',
95+
};
96+
97+
const context = {};
98+
99+
stripe.paymentLinks.create.mockResolvedValue(mockPaymentLink);
100+
101+
const result = await createPaymentLink(stripe, context, {
102+
price: 'price_123456',
103+
quantity: 1,
104+
redirect_url: 'https://example.com',
105+
});
106+
107+
expect(stripe.paymentLinks.create).toHaveBeenCalledWith(params, undefined);
108+
expect(result).toEqual(mockPaymentLink);
109+
});
75110
});

typescript/src/test/shared/paymentLinks/parameters.test.ts

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -5,14 +5,14 @@ describe('createPaymentLinkParameters', () => {
55
const parameters = createPaymentLinkParameters({});
66

77
const fields = Object.keys(parameters.shape);
8-
expect(fields).toEqual(['price', 'quantity']);
9-
expect(fields.length).toBe(2);
8+
expect(fields).toEqual(['price', 'quantity', 'redirect_url']);
9+
expect(fields.length).toBe(3);
1010
});
1111

1212
it('should return the correct parameters if customer is specified', () => {
1313
const parameters = createPaymentLinkParameters({customer: 'cus_123'});
1414

1515
const fields = Object.keys(parameters.shape);
16-
expect(fields).toEqual(['price', 'quantity']);
16+
expect(fields).toEqual(['price', 'quantity', 'redirect_url']);
1717
});
1818
});

typescript/src/test/shared/paymentLinks/prompts.test.ts

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -11,6 +11,9 @@ describe('createPaymentLinkPrompt', () => {
1111
expect(prompt).toContain(
1212
'quantity (int): The quantity of the product to include in the payment link.'
1313
);
14+
expect(prompt).toContain(
15+
'redirect_url (str, optional): The URL to redirect to after the payment is completed.'
16+
);
1417
});
1518

1619
it('should return the correct prompt with customer context', () => {
@@ -23,5 +26,8 @@ describe('createPaymentLinkPrompt', () => {
2326
expect(prompt).toContain(
2427
'quantity (int): The quantity of the product to include in the payment link.'
2528
);
29+
expect(prompt).toContain(
30+
'redirect_url (str, optional): The URL to redirect to after the payment is completed.'
31+
);
2632
});
2733
});

0 commit comments

Comments
 (0)