Process Payments

 

At this point merchants have been onboarded, and requirements to enable Payment and Payout capabilities have been met. Now you'll process a Payment from a payer to the merchant's WePay Account. The Clear Payment APIs allow you to build a secure, simple payment flow, and lets you describe different user experience journeys for Payments, Refunds, and Disputes.

As part of the integration, you'll be required to certify your payment processing infrastructure with specific attention to card network rules, NACHA rules and regulations pertaining to ACH and eCheck payments, and security. Use the following guides to ensure that your integration is compliant:

Calculate Fees

First, we'll review how fees work so that you can manage your platform's monetization regardless of the components you use for Payments. Note that the fee-collection method described here is geared towards Blended Rate pricing. Fees will work differently for your platform if you are implementing Merchant IC+ pricing.When you create a Payment, you'll define the total amount of fees that you will collect from it with the fee_amount parameter. The net (amount less fee_amount) will be deposited into your merchant's WePay Account, and the fees will be deposited into your platform's WePay partner account. Next, WePay will debit processing fees from your WePay partner account. This means that when you create a payment and describe fees, the value should be a sum of your platform's fees and WePay's processing fees.

Partners on Partner IC+ should calculate fee_amount assuming that fees will never be higher than 2.9% + $0.30

Example: Partners on Blended with Merchants on Blended

As an example, let's say that your contract with WePay has set credit card transaction fees at 3% + $0.30 per transaction. In addition, your platform charges $1.00 per transaction. If you then created a credit card payment for $100.00, you should calculate fees as 3% of the amount + $1.30. Thus, the value you would send for the fee_amount parameter would be 430.Note that fee amounts are notated in cents, so 430 represents $4.30.

The net that your merchant receives will be $95.70, and your platform will receive the full fee amount. WePay will then debit your platform WePay Account for the processing fees agreed to. Following the example above, your platform's net would be $1.00, and WePay would debit $3.30 from you.

Example: Variable + Flat Fee

If the platform wishes to charge a variable + flat fee, (as opposed to just a $1 rate), for example 2.65% + $0.20, It needs to be explicitly stated that if the partner wants to gross 2.65% + $0.20 per transaction, they need to calculate their fee in addition to the WePay fees which get debited from the partner account.

Be sure to review Card Network Rules on fees in order to charge fees in a compliant manner.

Use Payment Method Tokens

To immediately create a Payment, we'll send a POST request to the /payments endpoint. Before we get into the body of the call, we're going to add a Unique-Key to the header, so that a Payment can't execute twice. The value, of course, can be anything, as long as it's unique.
credit card tokenpayment bank token
Copy
Copied
curl -X POST \
  --url 'https://stage-api.wepay.com/payments' \
  -H 'App-Id: {your-app-id}'\
  -H 'App-Token: {your-app-token}'\
  -H 'Api-Version: 3.0'\
  -H 'Content-Type: application/json'\
  -H 'Unique-Key: {generate-a-unique-key}' \
  --data-raw '{
"account_id": "{merchant's-account-id}",
"amount": 1000,
"currency": "USD",
"payment_method": {
    "token": {
        "id": "payment_methods-YOUR-TOKEN-HERE"
        },
    "credit_card": {
        "card_holder": {
        "holder_name": "Test Test",
        "email": "foo@bar.com",
            "address": {
                "country": "US",
                "postal_code": "94025"
            }
        }
    }
},
“fee_amount”: 200
}'
Copy
Copied
curl -X POST \
  --url 'https://stage-api.wepay.com/payments' \
  -H 'App-Id: {your-app-id}'\
  -H 'App-Token: {your-app-token}'\
  -H 'Api-Version: 3.0'\
  -H 'Content-Type: application/json'\
  -H 'Unique-Key: {generate-a-unique-key}' \
  --data-raw '{
"account_id": "{merchant's-account-id}",
"amount": 1000,
"currency": "USD",
"payment_method": {
    "token": {
        "id": "payment_methods-YOUR-TOKEN-HERE"
        }
    }
},
Note the Unique-Key header, described in our Standard Headers and Idempotency articles. This header is required when creating Payments (POST /payments) and Refunds (POST /refunds) in order to protect against duplicate processing. Refer to the Risk Certification guide to identify standard required payment-level rBits and Risk Headers which will allow you to send WePay risk information about the payment. A payment may be flagged for manual risk review in which it is subject to 1-2 business days. The inclusion of payment-level rBits reduces the frequency and duration of manually reviewed payments as well as allows WePay's Risk team to accurately action a payment.
Note
Retrieve the response body by sending a successful POST /payments request and then a second, identical POST /payments request with the same Unique-Key header.

Once you execute this call, you'll have successfully created a payment for the amount of $10, with a fee of $2, for a total of $8 going to the merchant. The $2 fee goes to you, as the platform. If it is not specified, the Merchant receives $10 total.

Notes on payments with credit card tokens

  • First, we did not add auto_capture during tokenization because the default is true. The behavior of auto_capture being true means that WePay will execute the payment immediately. If you set auto_capture to false, you will need to capture it later, see Capture Authorized Payments below.
  • Second, the fee_amount allows the platform to set the fee for processing payment, with a hard limit of 20% of the transaction amount. In the above example, the amount to charge is 1000 ($10), and the fee is 200 ($2). We cap the fee at a maximum of 20% of the total amount. 201 ($2.01) wouldn't work, but 199 ($1.99) would.
  • In terms of processing, WePay will take the processing fee from the $2 (the default is 2.9% + $0.30 per transaction, but check with your WePay account manager for the most up to date fees), while the rest is given to your platform.
  • Lastly, although providing the cardholder information in both the POST /payments and POST /payment_methods requests are allowed, it is recommended that the cardholder information is provided in the POST /payments request. Providing the cardholder information in both the POST /payments and POST /payment_methods request will result in a TOKEN_CONFLICT response error.

This call will also convert the token into a Payment Method ID, which can be stored for future use.


Capture Authorized Payments

The above examples showcase payment flows where payment information is submitted and a payment is executed immediately upon the POST /payments call.

There are use cases where you'd like to authorize funds, but finalize payment at a later time (item is purchased, but charged when shipped). There are a few different ways to go about this:

Partial capture is only available to US E-commerce platforms.

Note
The rules for capturing payments with Card Present transactions can be found here.

Manual Capture

By sending the POST /payments call with the auto_capture parameter set to false, you will delay the payment from moving to an account's available balance by keeping the status in pending. Note that the amount in the initial POST /payments request cannot be changed during capture.Next, make a POST /payments/{id}/capture request to capture that Payment which will update the API status to completed. Using the payment ID, a new Unique-key, and no POST body, the second POST call will look something like this
Copy
Copied
curl -X POST \
  --url 'https://stage-api.wepay.com/payments/{id}/capture' \
  -H 'Accept: application/json' \
  -H 'App-Id: {YOUR-APP-ID}' \
  -H 'App-Token: {YOUR-APP-TOKEN}' \
  -H 'Api-Version: 3.0'\
  -H 'Content-Type: application/json' \
  -H 'Unique-Key: {NEW-UNIQUE-KEY}' \
Note
The final capture amount cannot be greater than the initial authorized amount. If capturing less than the initial authorized amount, see the Partial Capture section below.
On a successful capture call, the payment status will become completed, and the funds will become available for Payout.

Deferred Capture

First, deferred capture has a few requirements, of which at least one must be met:

  • Any deferred capture Payment must be Card Present
  • Any deferred capture Payment which is not Card Present must meet one of the following:
    • Payment Method is a credit card sent in the payment_method.credit_card structure
    • Payment Method is a tokenized credit card sent in the payment_method.token structure

Deferred capture covers use cases where a card is authorized up-front for an estimated amount, and then the Payment is captured at a designated time. Deferred capture is designed to cover Card Present use cases, but can also be used by PCI compliant platforms where card data is securely stored on your platform's servers.

To schedule a deferred capture payment, send a POST /payments request with the capture_at parameter set with a value of the epoch timestamp of the desired capture time. If the timestamp is in the past, an API error will occur, and the time must be no more than 7 days in the future from the initial POST /payments request. Your request should look something like this:
Copy
Copied
curl -X POST \
  --url 'https://stage-api.wepay.com/payments' \
  -H 'Accept: application/json' \
  -H 'App-Id: {YOUT-APP-ID}' \
  -H 'App-Token: {YOUR-APP-TOKEN}' \
  -H 'Api-Version: 3.0'\
  -H 'Content-Type: application/json' \
  -H 'Unique-Key: {UNIQUE-KEY}' \
  --data-raw '{
  "capture_at": 1580803200,
  "account_id": "abc123",
  "amount": 1000,
  "currency": "USD",
  "fee_amount": 30,
  "payment_method": {
    "credit_card": {
      "auto_update": true,
      "card_holder": {
        "address": {
          "city": "Redwood City",
          "country": "US",
          "line1": "350 Convention Way",
          "postal_code": "94025",
          "region": "CA"
        },
        "email": "example@wepay.com",
        "holder_name": "John Snow"
      },
      "card_number": "5496198584584769",
      "cvv": "007",
      "expiration_month": 4,
      "expiration_year": 2030,
      "virtual_terminal_mode": "web",
      "card_on_file": true,
      "recurring": false
    },
    "type": "credit_card"
  },
  "initiated_by": "customer"
}'
The API response will show a pending status until WePay automatically executes it at the time designated in the capture_at parameter. At that point, the Payment's status will either move to completed.Alternatively, you can manually capture the Payment before the time designated in the capture_at parameter. To do so, send a POST /payments/{id}/capture request at the desired capture time. The capture request should look like this:
Copy
Copied
curl -X POST \
  --url 'https://stage-api.wepay.com/payments/{id}/capture' \
  -H 'Accept: application/json' \
  -H 'App-Id: {YOUT-APP-ID}' \
  -H 'App-Token: {YOUR-APP-TOKEN}' \
  -H 'Api-Version: 3.0' \
  -H 'Content-Type: application/json' \
  -H 'Unique-Key: {NEW-UNIQUE-KEY}' \
Note
The final capture amount may be equal to or less than the initial amount authorized. The amount can also be updated up until the capture_at time.

Partial Capture

Another flow you may run into is partial captures, which is only available to US E-commerce platforms. Similar to the authorized payment example above, let's say a payer on your e-commerce platform purchases 2 items from a merchant. If that merchant is only able to ship one item, you can use a partial capture to execute the payment. Unlike capturing authorized payments, which require capturing the full amount, you can capture a partial amount. In the example below, we authorize $60 worth of goods, and partially capture $30 to finish the payment.

Note

While the final capture amount can be less, it cannot be greater than the initial authorized amount.

Start by sending a POST to /payments:
Copy
Copied
curl -X POST \
  --url 'https://stage-api.wepay.com/payments' \
  -H 'Accept: application/json' \
  -H 'App-Id: {YOUT-APP-ID}'\
  -H 'App-Token: {YOUR-APP-TOKEN}' \
  -H 'Api-Version: 3.0' \
  -H 'Content-Type: application/json' \
  -H 'Unique-Key: {UNIQUE-KEY}' \
  --data-raw '{
	"amount": 6000,
	"fee_amount": 300,
	"auto_capture": "false",
	"currency": "USD",
	"account_id": "account-id-here",
	"payment_method": {
		"token": {
			"id": "payment_methods-YOUR-TOKEN-HERE"
		}
	}
}'

Then, when ready to perform a partial capture, send a follow up call:

Copy
Copied
curl -X POST \
  --url 'https://stage-api.wepay.com/payments/{id}/capture' \
  -H 'Accept: application/json'\
  -H 'App-Id: {YOUT-APP-ID}'\
  -H 'App-Token: {YOUR-APP-TOKEN}'\
  -H 'Api-Version: 3.0'\
  -H 'Content-Type: application/json'\
  -H 'Unique-Key: {NEW-UNIQUE-KEY}' \
  --data-raw '{
	"amounts": {
		"amount": 3000,
		"currency": "USD",
		"fee_amount": 300
	}
}'

ACH

By default, ACH payments take 2 business days (excluding weekends and US holidays) to complete processing and be available to the merchant in a completed status. This window typically allows the issuing bank to process the request and send a response back to WePay. If the response from an issuing bank declines the payment and takes longer than 2 business days, then the payment will automatically be refunded.
Note
When a payment method is created using POST /payment_methods, the last_four variable that is returned will be the last four numbers of the bank account. However, if you have verified your account via Plaid, this might be the last four numbers of your tokenized bank account number (TAN).

CC Token

In order to create a payment which is captured at the time of creation, send a POST /payments request like so:

{/

Loading...
/}

Note the Unique-Key header, described in our Standard Headers and Idempotency articles. This header is required when creating Payments (POST /payments) and Refunds (POST /refunds) in order to protect against duplicate processing.
Note
Retrieve the response body by sending a second, identical POST /payments request with the same Unique-Key header.
The API response will contain a Payment Method ID which can be invoked for any future Payments from the same payer. Subscribe to the payment_method.updated topic to be notified when a credit card payment method expires, preemptively avoiding failed future Payments from the same Payer.