A cardholder must be created before issuing virtual cards. The cardholder will have a verified billing address and will be eligible to receive virtual cards.
Once you have a cardholder, you can create a virtual card under their name. This step generates a virtual card with a predefined spending limit. Stripe allows you to customize the card’s spending controls, including setting daily, monthly, or per-transaction limits. Find more information on spending controls in the Stripe docs.
create-card.ts
asyncfunctioncreateCard(cardholderId:string){const card =await stripe.issuing.cards.create({ cardholder: cardholderId, currency:'usd', type:'virtual', spending_controls:{ allowed_categories:['charitable_and_social_service_organizations_fundraising'],// Choose to block certain categories instead of allowing them// blocked_categories: ['automated_cash_disburse'], spending_limits:[{ amount:7500,// $75.00 measured in cents interval:'daily',// all_time, daily, weekly, monthly, yearly, per_authorization}],},});console.log('Card created:', card.id);return card;}const cardholderId ="ic_INPUT_CARDHOLDER_ID_HERE"// replace with your cardholder id from the previous stepconst virtual_card =createCard(cardholderId);
create-card.ts
asyncfunctioncreateCard(cardholderId:string){const card =await stripe.issuing.cards.create({ cardholder: cardholderId, currency:'usd', type:'virtual', spending_controls:{ allowed_categories:['charitable_and_social_service_organizations_fundraising'],// Choose to block certain categories instead of allowing them// blocked_categories: ['automated_cash_disburse'], spending_limits:[{ amount:7500,// $75.00 measured in cents interval:'daily',// all_time, daily, weekly, monthly, yearly, per_authorization}],},});console.log('Card created:', card.id);return card;}const cardholderId ="ic_INPUT_CARDHOLDER_ID_HERE"// replace with your cardholder id from the previous stepconst virtual_card =createCard(cardholderId);
create-card.py
defcreate_card(cardholder_id): card = stripe.issuing.Card.create( cardholder=cardholder_id, currency='usd',type='virtual', spending_controls={"allowed_categories":['charitable_and_social_service_organizations_fundraising'],# Choose to block certain categories instead of allowing them# "blocked_categories": ['automated_cash_disburse'],"spending_limits":[{"amount":7500,# measured in cents"interval":"daily",# all_time, daily, weekly, monthly, yearly, per_authorization}]},)print("Card created:", card.id)return cardcardholder_id ="ic_INPUT_CARDHOLDER_ID_HERE"# replace with your card id from the previous stepvirtual_card = create_card(cardholder_id)
This function returns all the details needed to complete an online purchase.
After creating a virtual card, you’ll need to retrieve its details (card number, expiration date, and CVC) to use it for transactions. The returned data can be used to automatically enter the card details when needed.
get-card.ts
exportasyncfunctiongetCard(cardId:string){const card =await stripe.issuing.cards.retrieve( cardId,{expand:['number','cvc']});const cardInfo ={ cardholder_firstName: card.cardholder.name.split(' ')[0], cardholder_lastName: card.cardholder.name.split(' ')[1], cardholder_email: card.cardholder.email, cardholder_phone: card.cardholder.phone_number, cardholder_address: card.cardholder.billing.address, card_number: card.number, expiration_month: card.exp_month, expiration_year: card.exp_year.toString().slice(-2),// 2028 -> 28 cvc: card.cvc, brand: card.brand, currency: card.currency,};console.log('Card info:', cardInfo);return cardInfo;}const cardId ="ic_INPUT_CARD_ID_HERE";// replace with your card id from the previous stepgetCard(cardId);
get-card.ts
exportasyncfunctiongetCard(cardId:string){const card =await stripe.issuing.cards.retrieve( cardId,{expand:['number','cvc']});const cardInfo ={ cardholder_firstName: card.cardholder.name.split(' ')[0], cardholder_lastName: card.cardholder.name.split(' ')[1], cardholder_email: card.cardholder.email, cardholder_phone: card.cardholder.phone_number, cardholder_address: card.cardholder.billing.address, card_number: card.number, expiration_month: card.exp_month, expiration_year: card.exp_year.toString().slice(-2),// 2028 -> 28 cvc: card.cvc, brand: card.brand, currency: card.currency,};console.log('Card info:', cardInfo);return cardInfo;}const cardId ="ic_INPUT_CARD_ID_HERE";// replace with your card id from the previous stepgetCard(cardId);
get-card.py
defgetCard(card_id): card = stripe.issuing.Card.retrieve(card_id, expand=['number','cvc']) card_info ={'cardholder_firstName': card.cardholder.name.split(' ')[0],'cardholder_lastName': card.cardholder.name.split(' ')[1],'cardholder_email': card.cardholder.email,'cardholder_phone': card.cardholder.phone_number,'cardholder_address': card.cardholder.billing.address,'card_number': card.number,'expiration_month': card.exp_month,'expiration_year':str(card.exp_year)[-2:],# 2028 -> 28'cvc': card.cvc,'brand': card.brand,'currency': card.currency,}print('Card info:', card_info)return card_infocard_id ="ic_REPLACE_WITH_YOUR_CARD_ID_HERE"# replace with your card id from the previous stepcard_info = getCard(card_id)
In this step, you will automate filling in the credit card payment form. This example walks you through navigating to the Red Cross donation page, selecting a donation amount, and completing the payment process using the virtual card details retrieved earlier.
import{ Stagehand }from"@browserbasehq/stagehand";import dotenv from"dotenv";import{ getCard }from"./get-card.js";dotenv.config();const stagehand =newStagehand({ env:"BROWSERBASE",});const cardId ="ic_INPUT_CARD_ID_HERE";// replace with your card id from the previous stepasyncfunctionmain(){await stagehand.init();const page = stagehand.page;console.log(`Watching session: https://www.browserbase.com/sessions/${stagehand.browserbaseSessionID}`);const paymentInfo =awaitgetCard(cardId);// Navigate to Red Cross donation pageawait page.goto('https://www.redcross.org/donate/donation.html/')const donationAmount =await page.observe({ instruction:"Find the donation amounts, and click $75", returnAction:true, onlyVisible:false,});// Click the first donation amountawait page.act(donationAmount[0])// Find the continue button and click itconst continueButton =await page.observe({ instruction:"Find the continue button and click it", returnAction:true, onlyVisible:false,});await page.act(continueButton[0])// Find the credit card button and click itconst creditCardButton =await page.observe({ instruction:"Find the credit card button and click it", returnAction:true, onlyVisible:false,});await page.act(creditCardButton[0])await page.act({action:"click the continue button"})const formValues =await page.observe({ instruction:`Fill in the form with the following values: ${JSON.stringify(paymentInfo)}`, returnAction:true, onlyVisible:false,});console.log("formValues", formValues);// Fill in the form with the valuesfor(const value of formValues){await page.act(value);}await page.waitForTimeout(10000);// Click the submit buttonawait page.act({action:"click the donate button"})await stagehand.close();}main().catch(console.error);
import{ Stagehand }from"@browserbasehq/stagehand";import dotenv from"dotenv";import{ getCard }from"./get-card.js";dotenv.config();const stagehand =newStagehand({ env:"BROWSERBASE",});const cardId ="ic_INPUT_CARD_ID_HERE";// replace with your card id from the previous stepasyncfunctionmain(){await stagehand.init();const page = stagehand.page;console.log(`Watching session: https://www.browserbase.com/sessions/${stagehand.browserbaseSessionID}`);const paymentInfo =awaitgetCard(cardId);// Navigate to Red Cross donation pageawait page.goto('https://www.redcross.org/donate/donation.html/')const donationAmount =await page.observe({ instruction:"Find the donation amounts, and click $75", returnAction:true, onlyVisible:false,});// Click the first donation amountawait page.act(donationAmount[0])// Find the continue button and click itconst continueButton =await page.observe({ instruction:"Find the continue button and click it", returnAction:true, onlyVisible:false,});await page.act(continueButton[0])// Find the credit card button and click itconst creditCardButton =await page.observe({ instruction:"Find the credit card button and click it", returnAction:true, onlyVisible:false,});await page.act(creditCardButton[0])await page.act({action:"click the continue button"})const formValues =await page.observe({ instruction:`Fill in the form with the following values: ${JSON.stringify(paymentInfo)}`, returnAction:true, onlyVisible:false,});console.log("formValues", formValues);// Fill in the form with the valuesfor(const value of formValues){await page.act(value);}await page.waitForTimeout(10000);// Click the submit buttonawait page.act({action:"click the donate button"})await stagehand.close();}main().catch(console.error);
Playwright
from playwright.sync_api import Playwright, sync_playwrightfrom browserbase import Browserbasefrom get_card import getCardimport osimport dotenvdotenv.load_dotenv()bb = Browserbase(api_key=os.environ["BROWSERBASE_API_KEY"])cardId ="ic_INPUT_CARD_ID_HERE"# replace with your card id from the previous stepdefrun(playwright: Playwright)->None: session = bb.sessions.create( project_id=os.environ["BROWSERBASE_PROJECT_ID"],) browser = playwright.chromium.connect_over_cdp(session.connect_url) context = browser.contexts[0] page = context.pages[0] payment_info = getCard(cardId)# Watch the sessionprint(f"Session URL: https://browserbase.com/sessions/{session.id}")# Navigate to the donation page page.goto("https://www.redcross.org/donate/donation.html")# Perform actions on the donation page page.click("#modf-handle-0-radio") page.click("text=Continue") page.click("text=credit card")# Fill billing information page.fill("input[name='bill_to_forename']", payment_info["cardholder_firstName"]) page.fill("input[name='bill_to_surname']", payment_info["cardholder_lastName"]) page.fill("input[name='bill_to_email']", payment_info["cardholder_email"]) page.fill("input[name='bill_to_phone']", payment_info["cardholder_phone"])# Fill in the address information page.fill("input[name='bill_to_address_line1']", payment_info["cardholder_address"]["line1"]) page.fill("input[name='bill_to_address_city']", payment_info["cardholder_address"]["city"]) page.fill("input[name='bill_to_address_postal_code']", payment_info["cardholder_address"]["postal_code"]) page.select_option("select#bill_to_address_state", payment_info["cardholder_address"]["state"])# Fill in the card information page.fill("input#cardnumber", payment_info["card_number"]) page.fill("input#MM",str(payment_info["expiration_month"])) page.fill("input#YY",str(payment_info["expiration_year"])) page.fill("input#CVC",str(payment_info["cvc"]))# Click donate button page.click("text=Donate") page.close() browser.close()if __name__ =="__main__":with sync_playwright()as playwright: run(playwright)
🎉 You made an online purchase with Stripe and Browserbase!