Building a Crowdfunding Platform

    This recipe demonstrates how to build a simple crowdfunding platform that collects payment information from campaign backers, performing the actual charge when the campaign achieves its funding goal within the specified time limit.

    Crowdfunding aims to democratize fundraising, making it easier for users to collect money from donors for creative projects, charitable causes, and more. Crowdfunding platforms boost the discoverability of fundraising campaigns and provide powerful tools that help fundraisers engage with their donors.

    The ability to accept payments is a vital part of any crowdfunding platform. Connect’s flexible APIs simplify payment processing for crowdfunding platform implementors—making it easy to collect donations, and to distribute raised funds to trustworthy organizers, while retaining a percentage for the platform operator. Successful crowdfunding platforms like Kickstarter, Indiegogo, and GoFundMe all rely on Connect for their payment processing needs.

    Creating accounts

    Connect supports three different account types, each with its own advantages and unique characteristics. For the purposes of this recipe, the crowdfunding example uses Express accounts, which are the fastest way to get started with Connect. Express provides its own user onboarding process, which collects payout information and handles identity verification.

    Each user who wants to create a crowdfunding campaign will register their own Express account on your platform. Express onboarding uses an OAuth connection flow to collect the user’s information and return the user to your application.

    To get started with your integration, you need two pieces of information from your platform settings:

    • Your client_id, a unique identifier for your platform, generated by Stripe
    • Your redirect_uri, a URL-encoded address that points to the page on your website to which the user is redirected after connecting their account. If you do not include the redirect_uri parameter in your request, Stripe defaults to using the first address you have configured as the redirect destination in your Dashboard.

    With these two pieces of information in hand, you’re ready to create the OAuth link:

    curl https://connect.stripe.com/express/oauth/authorize?redirect_uri=https://{ADDRESS}&client_id={CLIENT_ID}&state={STATE_VALUE}
    

    To prevent CSRF attacks, add the state parameter, passing along a unique token as the value. We’ll include the state you gave us when we redirect the user back to your site.

    After the user clicks the link on your site, they’ll be taken to Stripe’s website, where they’ll be prompted to provide contact and payout information. To test the Express onboarding process, you can use (000) 000-0000 when it asks for a phone number. Instead of sending you an SMS message or e-mail, Stripe lets you complete verification by inputting the code 000-000.

    After the user completes the onboarding process, they are redirected back to your site, to the URL established as your platform’s redirect_uri. For successful connections, Stripe passes along two query parameters in the URL:

    • The state value, if provided
    • An authorization code

    The last step is to use the provided code to make a POST request to our token endpoint to complete the connection and fetch the user’s account ID:

    curl https://connect.stripe.com/oauth/token \
       -d client_secret=sk_test_BQokikJOvBiI2HlWgH4olfQ2 \
       -d code="{AUTHORIZATION_CODE}" \
       -d grant_type=authorization_code
    

    Stripe returns a response containing the account ID and authentication credentials for the user. The user is now connected to your platform. The stripe_user_id property, returned by the API, is the Stripe account ID for the newly created account. Use this account ID to add a business_url for the crowdfunding campaign, and store the account ID in your database so that you can later use the ID to perform destination charges against that account.

    Collecting payment information

    In this example, customers provide their payment information when they back a crowdfunding campaign, but they aren’t charged until the campaign completes. To save the payment information and associate it with a customer for later use, create a Customer and attach a Source. The following code shows how to use the Koa framework to make a server-side endpoint that creates a Customer, attaching tokenized payment information received from a POST request:

    const stripe = require("stripe")("xxx");
    
    router.post("/payment", async ctx => {
      let {email, card} = ctx.request.body;
      let customer = await stripe.customers.create({
        email, source: card.token.id
      });
    
      // Store the customer.id in your database
      // You can use the ID to retrieve the customer from Stripe's APIs later
    
      ctx.body = {success: true};
    });
    

    In the browser, use Elements to securely collect and tokenize the customer’s payment information. The following code demonstrates how to obtain a token and send it to the server with the W3C Fetch API:

    const stripe = Stripe("xxx");
    const elements = stripe.elements();
    const stripeCard = elements.create("card");
    
    let elCard = document.getElementById("card");
    let elPayment = document.getElementById("payment");
    
    stripeCard.mount(elCard);
    elPayment.addEventListener("click", async () => {
      let card = await stripe.createToken(stripeCard);
      let response = await fetch("/payment", {
        method: "POST",
        headers: {"Content-Type": "application/json"},
        body: JSON.stringify({email: "xxx", card})
      });
    
      console.log(await response.json());
    });
    

    In the code example, the JSON payload sent to the server includes the customer’s email address and the tokenized representation of their payment information. You could potentially add other relevant information, like the amount that the user chose to contribute or the reward tier that they chose. On the server, you would store that information in your database so that you could use it later when you perform the charge or fulfill backer rewards.

    Performing the charge

    If the crowdfunding campaign meets its fundraising goal (a precondition built into this recipe’s scenario), the platform can charge all of the customers who contributed to the campaign. Connect supports several different charge types, accommodating a range of different fund flows. In a crowdfunding application, the easiest approach is to use a destination charge, which performs the charge on the platform account and directs all or some of the total amount to the user’s account.

    Many crowdfunding platforms monetize their service by charging transaction fees. For example, a crowdfunding platform might keep a percentage of the money that it helps its users raise from customers. Destination charges make it easy for Connect platforms to collect their fees. When the amount of money sent to the destination account is less than the total amount of the charge, the platform keeps the rest. To collect a fee for the platform, simply subtract the desired fee from the destination amount.

    To charge all of the customers who contributed to the campaign, retrieve them from your database and perform a destination charge for each one. The following code demonstrates how to iterate over the customers and perform the charges:

    let charges = customers.map(customer =>
      stripe.charges.create({
        customer, amount: xxx, currency: "usd",
        destination: {amount: xxx, account: "xxx"}
      }));
    

    The charge will automatically use the customer’s default source. If your platform lets customers input multiple credit cards and choose which one to use for a given payment, you can specify the source ID when creating the charge. If the customer’s source is set as reusable, you can perform subsequent charges for the customer (when they back another campaign, for example) without having to collect payment information again.

    Handling payouts

    When the destination charges complete successfully, the raised funds (minus any fee retained by the platform) will be available in the user’s Express account. Your platform can use payouts to send the user’s money to their bank account. To give your connected account users the best possible experience, you can use Instant Payouts to immediately send the funds to their bank account. Or you can configure a schedule for automatic payouts, sending the user their money at regular intervals. You can optionally use manual payouts instead if you would like to exercise more control over moving funds from the user’s Express account balance to their bank account.

    Express accounts come with a dashboard that lets the user update their account information and see their current balance and payout history. To integrate the Express dashboard into your platform, use the Create Login Link API to generate a single-use URL that allows the user to access the dashboard:

    stripe.accounts.createLoginLink("{CONNECTED_STRIPE_ACCOUNT_ID}");
    

    The URL expires a brief period after you retrieve it from the API, so you should use it promptly. Typically, you should use the API to generate the link on demand when the user intends to visit their dashboard.

    Handling refunds

    You can refund a user’s crowdfunding payment in whole or in part. By default, refunds for destination charges are taken from the balance of the platform account. If you would like to recover the refunded money from the destination account, you can use the reverse_transfer parameter when you create the refund:

    stripe.refunds.create({
      charge: "{CHARGE_ID}",
      reverse_transfer: true,
    })
    

    Other recipes

    Looking to build another type of platform? Check out these other recipes.