WePay

Building a crowdfunding site with WePay

Overview

WePay makes it easy to integrate payments into a crowdfunding site. In this section, you'll see how to:

  • Get a simple crowdfunding site integrated with just a few calls.
  • Take more control of the user experience while leaving PCI to WePay.

Scenario & Key Requirements

Your site is focused on teachers raising money for educational projects. Teachers post the projects they want to fund and the minimum amount of funding they will need to proceed. Your site signs up teachers, creates and hosts pages for each project, and allows donors to contribute. Now, you want to use WePay to handle the payments.

One of your key requirements is that fundraising can be open for a month or more for a project. Your site will need to use WePay's conditional payments capability so that no money changes hands until a "tipping point" in the fundraising is reached for each project.

At WePay, your teachers are the merchants, and the donors are the payers, and we'll use those terms in this guide

Simple Approach

To get up and running quickly, you decide for your first version that you'll leverage the WePay user experience as much as possible.

Creating accounts for your merchants.

Each of your merchants will get their own WePay payment account. This keeps all the money management with WePay. Your site will facilitate creating this account and will receive an access token that your site saves. This access token allows your site to handle checkout, get status, etc.

Creating a payment account involves 2 steps:

  1. Setup the merchant using OAuth2.
  2. Create a payment account for that merchant.

Setup a merchant using OAuth2

The easiest approach is to redirect to WePay's OAuth2 authorization URI. Your merchant will see a popup where they can set up their login.

https://www.wepay.com/v2/oauth2/authorize
?client_id=[your client id]
&redirect_uri=[your redirect uri ex. 'http://example.com/wepay']
&scope=[the permissions you want ex. manage_accounts,collect_payments]

When merchants complete this, follow up with the /oauth2/token call to receive an access token for this merchant:

  • PHP
  • cURL
  • Ruby
  • Python
<?php
    // WePay PHP SDK - http://git.io/mY7iQQ
    require 'wepay.php';

    // oauth2 parameters
    $code = $_GET['code']; // the code parameter from step 2
    $redirect_uri = "http://www.example.com/oauth2_redirect_uri"; // this is the redirect_uri you used in step 1

    // application settings
    $client_id = 123456789;
    $client_secret = "1a3b5c7d9";

    // change to useProduction for live environments
    Wepay::useStaging($client_id, $client_secret);

    $wepay = new WePay(NULL); // we don't have an access_token yet so we can pass NULL here

    // create an account for a user
    $response = WePay::getToken($code, $redirect_uri);

    // display the response
    print_r($response);
?>
curl https://stage.wepayapi.com/v2/oauth2/token \
	-d "client_id=123456789" \
	-d "client_secret=1a3b5c7d9" \
	-d "code=52sdga231sddd213jj9a" \
	-d "redirect_uri=http://www.example.com/oauth2_redirect_uri"
				
# WePay Ruby SDK - http://git.io/a_c2uQ
require 'wepay'

# application settings
client_id = '123456789'
client_secret = '1a3b5c7d9'
use_stage = true

wepay = WePay::Client.new(client_id, client_secret, use_stage)

# Get the OAuth 2.0 authorization URL. Send the user to this URL to authorize
# the application, then they will return to your `redirect_uri` with a code as
# a GET parameter.
redirect_uri = "http://myexamplesite.com/wepay"
redirect_to(wepay.oauth2_authorize_url(redirect_uri))

# Once you have the OAuth 2.0 code, you can request an access token.
response = wepay.oauth2_token(code, redirect_uri)
access_token = response['access_token']

# display the response
p response
# WePay Python SDK - http://git.io/v7Y1jA
from wepay import WePay

# oauth2 parameters
code = '52sdga231sddd213jj9a'; # the code parameter from step 2
redirect_uri = "http://www.example.com/oauth2_redirect_uri"; # this is the redirect_uri you used in step 1

# application settings
client_id = 123456789
client_secret = '1a3b5c7d9'
production = False

# set production to True for live environments
wepay = WePay(production, None)

# create an account for a user
response = wepay.get_token(redirect_uri, client_id, client_secret, code)

# display the response
print response

Create a payment account

Now that your site has an access token, the first order of business is to create a payment account. Although there are many optional arguments, all you need to provide for US merchants are the name of the account and a description. The name is typically based on your site's name, e.g. "Education Fundraising". The description is variable and up to you.

  • PHP
  • cURL
  • Ruby
  • Python
<?php
    // WePay PHP SDK - http://git.io/mY7iQQ
    require 'wepay.php';

    // application settings
    $client_id = 123456789;
    $client_secret = "1a3b5c7d9";
    $access_token = "STAGE_8a19aff55b85a436dad5cd1386db1999437facb5914b494f4da5f206a56a5d20";

    // change to useProduction for live environments
    Wepay::useStaging($client_id, $client_secret);

    $wepay = new WePay($access_token);

    // create an account for a user
    $response = $wepay->request('account/create/', array(
        'name'          => 'Account Name',
        'description'   => 'A description for your account.'
    ));

    // display the response
    print_r($response);
?>
curl https://stage.wepayapi.com/v2/account/create \
	-H "Authorization: Bearer STAGE_8a19aff55b85a436dad5cd1386db1999437facb5914b494f4da5f206a56a5d20" \
	-d "name=Account name" \
	-d "description=A description for your account."
				
# WePay Ruby SDK - http://git.io/a_c2uQ
require 'wepay'

# application settings
client_id = '123456789'
client_secret = '1a3b5c7d9'
use_stage = true
access_token = 'STAGE_8a19aff55b85a436dad5cd1386db1999437facb5914b494f4da5f206a56a5d20'

wepay = WePay::Client.new(client_id, client_secret, use_stage)

# create a payment account for a user
response = wepay.call('/account/create', access_token, {
    :name          => 'Account Name',
    :description   => 'A description for your account.'
})

# display the response
p response
# WePay Python SDK - http://git.io/v7Y1jA
from wepay import WePay

# application settings
access_token = 'STAGE_8a19aff55b85a436dad5cd1386db1999437facb5914b494f4da5f206a56a5d20'
production = False

# set production to True for live environments
wepay = WePay(production, access_token)

# create an account for a user
response = wepay.call('/account/create', {
    'name': 'Account Name',
    'description': 'A description for your account.'
})

# display the response
print response

Processing payments

Payment processing will require two calls, one at the time a payer donates, and another when the tipping point is reached and it's time to actually process the payments.

There are some choices you need to make for payment processing - here's what we'll use in this example:

  • You are charging a 5% fee and it will be taken out of the gross proceeds.
  • The WePay fee will also be taken out of the gross proceeds.

Taking payment information

Your platform will use a preapproval object to get payment information and validate the charge. This lets your site use WePay's popup window, so you don't have to think about the checkout UI or any security concerns.

Create the preapproval object:

  • PHP
  • cURL
  • Ruby
  • Python
<?php
    // WePay PHP SDK - http://git.io/mY7iQQ
    require 'wepay.php';

    // application settings
    $account_id = 123456789;
    $client_id = 9543125;
    $client_secret = "1a3b5c7d9";
    $access_token = "STAGE_8a19aff55b85a436dad5cd1386db1999437facb5914b494f4da5f206a56a5d20";

    // change to useProduction for live environments
    Wepay::useStaging($client_id, $client_secret);

    $wepay = new WePay($access_token);

    // create the pre-approval
    $response = $wepay->request('preapproval/create', array(
        'account_id'        => $account_id,
        'period'            => 'once',
        'amount'            => '19.99',
        'mode'              => 'regular',
        'short_description' => 'A pledge for the awesome project',
        'redirect_uri'      => 'http://example.com/success/'
    ));

    // display the response
    print_r($response);
?>
curl https://stage.wepayapi.com/v2/preapproval/create \
	-H "Authorization: Bearer STAGE_8a19aff55b85a436dad5cd1386db1999437facb5914b494f4da5f206a56a5d20" \
	-d "account_id=123456789" \
	-d "period=once" \
	-d "amount=19.99" \
	-d "mode=regular" \
	-d "short_description=A subscription to our magazine." \
	-d "redirect_uri=http://example.com/success/"
				
# WePay Ruby SDK - http://git.io/a_c2uQ
require 'wepay'

# application settings
account_id = 123456789
client_id = 9543125
client_secret = '1a3b5c7d9'
access_token = 'STAGE_8a19aff55b85a436dad5cd1386db1999437facb5914b494f4da5f206a56a5d20'

# set _use_stage to false for live environments
wepay = WePay.new(client_id, client_secret, _use_stage = true)

# create the pre-approval
response = wepay.call('/preapproval/create', access_token, {
    :account_id         => account_id,
    :period             => 'once',
    :amount             => '19.99',
    :mode               => 'regular',
    :short_description  => 'A pledge for the awesome project',
    :redirect_uri       => 'http://example.com/success/'
})

# display the response
p response
# WePay Python SDK - http://git.io/v7Y1jA
from wepay import WePay

# application settings
account_id = 123456789
access_token = 'STAGE_8a19aff55b85a436dad5cd1386db1999437facb5914b494f4da5f206a56a5d20'
production = False

# set production to True for live environments
wepay = WePay(production, access_token)

# create the pre-approval
response = wepay.call('/preapproval/create', {
    'account_id': account_id,
    'period': 'once',
    'amount': '19.99',
    'mode': 'regular',
    'short_description': 'A pledge for the awesome project',
    'redirect_uri': 'http://example.com/success/'
})

# display the response
print response

Your platform will know if the customer completed the transaction when WePay redirects to your callback URI. Save the preapproval ID returned in the response for use in the next step.

Charging the card

When the fundraising is over and the tipping point is met, use /checkout/create passing in the preapproval ID obtained before. Since the payer has already agreed to the charge, there is no further UI required and the credit card can be charged in background.

  • PHP
  • cURL
  • Ruby
  • Python
<?php
    // WePay PHP SDK - http://git.io/mY7iQQ
    require 'wepay.php';

    // application settings
    $account_id = 123456789; // the merchant's account_id
    $client_id = 9543125;
    $client_secret = "1a3b5c7d9";
    $access_token = "STAGE_8a19aff55b85a436dad5cd1386db1999437facb5914b494f4da5f206a56a5d20"; // the merchant's access_token
    $preapproval_id = "12345"; // The preapproval_id from step 1


    // change to useProduction for live environments
    Wepay::useStaging($client_id, $client_secret);

    $wepay = new WePay($access_token);

    // create the checkout
    $response = $wepay->request('checkout/create', array(
        'account_id'        => $account_id,
        'amount'            => '19.99',
        'short_description' => 'Payment for test project',
        'type'              => 'GOODS',
        'preapproval_id'    => $preapproval_id
    ));

    // display the response
    print_r($response);
?>
$ curl https://stage.wepayapi.com/v2/checkout/create \
    -H "Authorization: Bearer STAGE_8a19aff55b85a436dad5cd1386db1999437facb5914b494f4da5f206a56a5d20" \
    -d "account_id=12345" \
    -d "amount=19.99" \
    -d "short_description=Payment for test project" \
    -d "type=GOODS"
    -d "preapproval_id=12345"
				
# WePay Ruby SDK - http://git.io/a_c2uQ
require 'wepay'

# application settings
account_id = 123456789  # the merchant's account_id
client_id = 9543125
client_secret = '1a3b5c7d9'
access_token = 'STAGE_8a19aff55b85a436dad5cd1386db1999437facb5914b494f4da5f206a56a5d20' # the merchant's access_token
preapproval_id = '12345' # the preapproval_id from step 1

# set _use_stage to false for live environments
wepay = WePay.new(client_id, client_secret, _use_stage = true)

# create the checkout
response = wepay.call('/checkout/create', access_token, {
    :account_id         => account_id,
    :amount             => '19.99',
    :short_description  => 'Payment for test project',
    :type               => 'GOODS',
    :preapproval_id     => preapproval_id
})

# display the response
p response
# WePay Python SDK - http://git.io/v7Y1jA
from wepay import WePay

# application settings
account_id = 123456789 # the merchant's account_id
access_token = 'STAGE_8a19aff55b85a436dad5cd1386db1999437facb5914b494f4da5f206a56a5d20' # the merchant's access_token
preapproval_id = '12345' # the preapproval_id from step 1
production = False

# set production to True for live environments
wepay = WePay(production, access_token)

# create the checkout
response = wepay.call('/checkout/create', {
    'account_id': account_id,
    'amount': '19.99',
    'short_description': 'Payment for test project',
    'type': 'GOODS',
    'preapproval_id': preapproval_id
})

# display the response
print response

Even though a preapproval was obtained, there are some reasons a checkout from a preapproval can fail. Your platform still needs to look at the response and take action, e.g. re-engage the payer to have them resubmit their info.

Customizing the checkout experience

  • Reminder on risks and responsibilities.
  • Using /credit_card/create.
  • Turning off WePay emails and sending your own.

The first part of the user experience partners want to customize is usually the payment experience. Instead of using WePay's embedded iframe or pop-up window, as we did in the above example, your platform can completely own the checkout experience.

Before you jump in - a note on security

A big part of what WePay provides is minimizing the scope of security requirements for your platform. Using the approach in this section raises your platform's responsibility compared with the approach in the previous section. Please read our security page for more information.

Securely obtaining credit card info

You can design your credit card acceptance form any way you wish, but you need to use WePay's JavaScript library to securely send the credit card info directly to WePay's servers. Do not accept credit card information onto your own server and then call WePay's APIs.

WePay's JavaScript library uses the /credit_card/create API call to store the payer's credit card info securely on WePay's servers, and returns your platform a token. This token can then be used in a /checkout/create call to complete a transaction without any further user interaction.

A minimal credit card form looks like this:

Name:
Email:
Credit Card Number: (Example Card Numbers)
Expiration Month:
Expiration Year:
CVV:
Zipcode:

And the HTML source is here:

<script type="text/javascript" src="https://static.wepay.com/min/js/tokenization.v2.js">
</script>
<script type="text/javascript">
    WePay.set_endpoint("stage"); // change to "production" when live

function chargeCard(){
        var response = WePay.credit_card.create( {
            "client_id":118711,
            "user_name":document.getElementById('name').value,
            "email":document.getElementById('email').value,
            "cc_number":document.getElementById('cc-number').value,
            "cvv":document.getElementById('cc-cvv').value,
            "expiration_month":document.getElementById('cc-month').value,
            "expiration_year":document.getElementById('cc-year').value,
            "address":
                {
                    "zip":document.getElementById('zip').value
                }
        }, function(data) {
            if (data.error) {
                console.log(data);
                // handle error response
            } else {
                // call your own app's API to save the token inside the data;
                // show a success page
            }
        } );
    }
</script>
<table>
    <tr><td>Name: </td><td><input id="name" type="text"></input></td></tr>
    <tr><td>Email: </td><td><input id="email" type="text"></input></td></tr>
    <tr><td>Credit Card Number: </td><td><input id="cc-number" type="text"></input></td></tr>
    <tr><td>Expiration Month: </td><td><input id="cc-month" type="text"></input></td></tr>
    <tr><td>Expiration Year: </td><td><input id="cc-year" type="text"></input></td></tr>
    <tr><td>CVV: </td><td><input id="cc-cvv" type="text"></input></td></tr>
    <tr><td>Zipcode: </td><td><input id="zip" type="text"></input></td></tr>
    <tr><td></td><td><input type="submit" name="Submit" value="Submit" onclick="chargeCard()"/></td></tr>
</table>

The function chargeCard() is invoked when the user submits the checkout form. chargeCard extracts the credit card fields and maps them to WePay's JavaScript call WePay.credit_card_create. In this way, the sensitive information is passed directly to WePay's servers, and your platform receives a token for later use.

Your chargeCard function can take the data response and call your own server's APIs to store the token.

Completing checkout using a token

When it's time to charge the credit card, follow the /checkout/create example shown before, but this time add these parameters:

  • PHP
  • cURL
  • Ruby
  • Python
<?php
// WePay PHP SDK - http://git.io/mY7iQQ
require 'wepay.php';

// application settings
$account_id = 123456789;
$client_id = 123456789;
$client_secret = "1a3b5c7d9";
$access_token = "STAGE_8a19aff55b85a436dad5cd1386db1999437facb5914b494f4da5f206a56a5d20";

// credit card id to charge
$credit_card_id = 123456789;

// change to useProduction for live environments
Wepay::useStaging($client_id, $client_secret);

$wepay = new WePay($access_token);

// charge the credit card
$response = $wepay->request('checkout/create', array(
	'account_id'		=> $account_id,
	'amount'		=> '25.50',
	'currency'      =>  'USD',
	'short_description'	=> 'A brand new soccer ball',
	'type'			=> 'GOODS',
	'payment_method_id'	=> $credit_card_id, // user's credit_card_id
	'payment_method_type'	=> 'credit_card'
));

// display the response
print_r($response);
?>
$ curl https://stage.wepayapi.com/v2/checkout/create \
    -H "Authorization: Bearer STAGE_8a19aff55b85a436dad5cd1386db1999437facb5914b494f4da5f206a56a5d20" \
    -d "account_id=123456789" \
    -d "amount=25.50" \
    -d "short_description=A brand new soccer ball" \
    -d "type=GOODS" \
    -d "payment_method_id=12345" \
    -d "payment_method_type=credit_card"
# WePay Ruby SDK - http://git.io/a_c2uQ
require 'WePay_API_v2_Ruby_SDK.rb'

# application settings
account_id = 123456789
client_id = 123456789
client_secret = '1a3b5c7d9'
access_token = 'STAGE_8a19aff55b85a436dad5cd1386db1999437facb5914b494f4da5f206a56a5d20'

# credit card to charge
credit_card_id = 123456789

# set _use_stage to false for live environments
wepay = WePay.new(client_id, client_secret, _use_stage = true)

# charge the credit card
response = wepay.call('/checkout/create', access_token, {
	:account_id				=> account_id,
	:amount					=> '25.50',
	:short_description		=> 'A brand new soccer ball',
	:type					=> 'GOODS',
	:payment_method_id		=> credit_card_id, # the user's credit_card_id
	:payment_method_type	=> 'credit_card'
})

# display the response
p response
# WePay Python SDK - http://git.io/v7Y1jA
from wepay import WePay

# application settings
account_id = 123456789
access_token = 'STAGE_8a19aff55b85a436dad5cd1386db1999437facb5914b494f4da5f206a56a5d20'
production = False

# credit card id to charge
credit_card_id = 123456789

# set production to True for live environments
wepay = WePay(production, access_token)

# charge the credit card
response = wepay.call('/checkout/create', {
	'account_id': account_id,
	'amount': '25.50',
	'short_description': 'A brand new soccer ball',
	'type': 'GOODS',
	'payment_method_id': credit_card_id, # the user's credit_card_id
	'payment_method_type': 'credit_card'
})

# display the response
print response

Because your platform already has the card info, this usage of /checkout/create will immediately charge the card with no user interaction.

Sending your own emails to merchants and payers

Another way your platform can take more control of the user experience is to generate your own emails to merchants and payers during checkout. Your WePay account manager can assist in turning off specific emails.

Your platform should send a confirmation email when you first tokenize the card successfully and then to at least the payer when you actually charge the card. Your application probably already sends an email when a project reaches its tipping point so that you can include notice that you are charging the card as part of this email.