Process Payments
Now that you’ve authorized a card, you’re ready to create your first Card Present payment.
Create a Payment
To create a payment, use the encoded payment method in the payment_method.encoded_payment_method
parameter on the POST /payments API request. Be sure to use the value as is, without adding any characters or spaces.
Note
An encoded payment method can only be used once, and every Card Present transaction will need a newly-generated encoded payment method. That said, an encoded payment method will be valid for as long as the authorization. This amount of time will vary depending on the card issuer, but it will generally be 7 days.
So far, you should have the following data points to include in your POST /payments request:
- The merchant’s Account ID (this must be the same Account ID which owns the Terminal).
- The currency of the transaction (only USD is currently supported).
- The encoded payment method (returned by the Card Present SDK).
- The authorized amount (returned by the Card Present SDK).
Your request thus far would look like the following:
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: {guid}’ \
--data-raw '{
"account_id": "{merchant’s-account-id}",
"amount": "{desired-capture-amount}",
"fee_amount": {calculate-processing-and-platform-fees},
"currency”: “USD",
"payment_method": {
"encoded_payment_method": "{value-from-CP-SDK}""
}
}’
amount
The amount captured (i.e. the value for the amount
parameter in the POST /payments request) should match the amount authorized. In order to capture a different amount, see the Capture Payments section below. Related information on capture scenarios can be found in the Delayed Capture
section below as well.
fee_amount
WePay recommends charging, at minimum, WePay’s processing fees in this parameter. Remember that WePay’s processing fees are collected from your platform’s WePay account, which collects funds based on the fee_amount
parameter values on Payments facilitated by your platform.
To do this, find your rates in your contract and use those rates to calculate the processing fee per transaction. If your platform’s business model relies on fees per transaction, this would be the place to add those fees in, as well.
Tipping
Tips provided on the receipt will need to be added to the total by the merchant and submitted to your platform via your merchant UI. This means that you should build a check specifically for terminals with tip.mode
set to prompt_on_receipt
, and use deferred capture to adjust the amount
once the merchant has submitted tip amounts at the end of the day.
Tips provided on the terminal are included in the amount parameter of the authorization info object in the auth response from the Card Present SDK.
Denomination
It is important to note that the Card Present SDK represents amounts in dollars while the Payments API represents amounts in cents. For instance, $1.00 in the Card Present SDK should be printed as 1.00, and in the API it should be printed as 100.
Handle 500 Errors
After a Card Present authorization returns from the SDK, the payer’s portion of the transaction can be considered complete.
That said, it is possible to receive a 500 HTTP error on the subsequent POST /payments request. It is recommended to build out automated retry logic to handle 500’s in the Card Present context, but it is up to your platform to design and implement the appropriate retry solution for your use case.
In your design phase, take the following requirements into consideration:
- Use the same Unique-Key when re-trying a single transaction
- A single transaction is defined as the same payer, payment method, and purchase content
- This means that even if the payer comes back 5 minutes later to re-try the payment after you received a 500, the same Unique-Key should be used.
Print Receipts
On the Verifone V400m terminal, merchants can print receipts from the device. Identify terminals with printer capabilities by examining the available printer flag in the Card Present SDK.
Verifone V400m terminals display an option for merchants to print a receipt after a successful authorization. If this option is selected, run the print receipt function in the Card Present SDK.
For further receipt requirements, see the Card Present receipt guide, and the Card Present card network rules regarding receipts.
Signatures must be collected in the following cases:
- NFC/contactless transaction
- Keyed entry transaction
Additionally, merchants are encouraged to collect signature on receipt if they accept tip, and/or if they wish to validate the terms of sale (such as “all sales final”).
Capture Payments
There are two overall methods of capturing payments with an encoded payment method:
Instant Capture
When calling POST /payments, the auto_capture
parameter defaults to true
even if it’s not included in the request. This results in an instant capture of the Payment, which requires tips on receipts to be calculated into the total before calling POST /payments.
Asynchronous Capture
Once a card has been successfully authorized (resulting in an encoded payment method in the Card Present SDK response), a POST /payments does not need to happen right away. Authorizations are generally valid up to 7 days after the in-person transaction, though the exact timeframe depends on the card issuer.
Risks:
- Auth expiration before a payment can be captured
- Lost auths due to inadequate logging
To manage the above risks, WePay recommends capturing payment as soon as possible, and communicating with merchants that payments can never be captured 7 days after the in-person transaction. Additionally, send a POST /payments request immediately after an authorization with the relevant store and forward parameters (described further below), and then capture that payment later to help with logging encoded payment methods.
Here is the high-level asynchronous capture flow:
The below use cases outline, at a high-level, different methods of implementing asynchronous capture.
Capture a Payment with no changes
- Capture method: manual or delayed
- Manual: Send the POST /payments/{id}/capture request with no JSON body.
- Delayed: Set the
capture_at
time in the initial POST /payments API request. The Payment will automatically capture at the designated time.
Capture a Payment with a total less than the authorized amount
- Capture method: partial
- Partial: Send the POST /payments/{id}/capture request with the new total in the
amounts
parameter. Be sure to adjust the platform fees so that they do not exceed 20% of the total.
Capture a Payment with a total greater than the authorized amount
- Capture method: manual or delayed
- Manual: Send the POST /payments/{id}/capture request with the new total in the
amounts
parameter. Adjust the platform fees as needed, and keep in mind that they cannot exceed 20% of the total. - Delayed: Set the
capture_at
time in the initial POST /payments request. Before the capture time, send a POST /payments/{id} request to update the amounts on the payment. Adjust fees as needed, and keep in mind that they cannot exceed 20% of the total.
High-Level Capture Flows
All capture flows begin with authorizing a card on the terminal.
Manual Capture | Delayed Capture | Partial Capture | |
---|---|---|---|
|
|
|
|
Delayed Capture
Use delayed capture to create an API payment which will automatically capture at a designated time up to 7 days from authorization. To create a payment with delayed capture, send a POST /payments API request like this:
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' \
--data-raw '{
"account_id": "{merchant’s-account-id}",
"amount": "{desired-capture-amount}",
"capture_at": {calculate-UNIX-timestamp-within-7-days-of-current-time}
"fee_amount": {calculate-processing-and-platform-fees},
"currency”: “USD",
"payment_method": {
"encoded_payment_method": "{value-from-CP-SDK}"
}
}'
For the sake of example, let’s say the current date and time when you’re sending POST /payments is March 18, 2020 at 3:29:29 PM PST. The farthest out that this payment can be captured would be March 25, 2020 at 3:29:29 PM PST. This means that the maximum UNIX timestamp that you can set as the value for capture_at
is 1585175369
.
Manual Capture
Manual capture allows a card to be authorized and an API Payment to be created, but the final capture information can be different and the final capture time can be any time within 7 days of authorization.
The final capture amount can be greater than the authorized amount. Capturing an amount less than the authorized amount is considered partial capture. Data related to the payment can be updated, such as Level 2/Level 3 data and custom_data
.
Payments using manual capture are typically dependent upon finalized information from the merchant or payer, which is why delayed capture would not be ideal for these payments. Manual capture allows the capture request to be sent as soon as payment details are finalized (i.e. shipping, tip, any changes to amount
, or any changes to data), rather than waiting for the capture_at
time set in delayed capture.
When creating a payment designated for manual capture, the API request will look like this:
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' \
--data-raw '{
"account_id": "{merchant’s-account-id}",
"amount": "{desired-capture-amount}",
"auto_capture": false,
"fee_amount": {calculate-processing-and-platform-fees},
"currency”: “USD",
"payment_method": {
"encoded_payment_method": "{value-from-CP-SDK}""
}
}'
If rBits or the reference_id
need to be updated in addition to amounts
, do so using a POST /payments/{id} request:
curl -X POST \
--url 'https://stage-api.wepay.com/payments/{id}' \
-H 'App-Id: {your-app-id}' \
-H 'App-Token: {your-app-token}' \
-H 'Api-Version: 3.0' \
-H 'Content-Type: application/json' \
--data-raw '{
"reference_id": "{new-reference-id}",
"amounts": {
"amount": {new-capture-amount},
"currency": "USD",
"fee_amount": {fee-amount}
}
}'
The manual capture can be executed using a POST /payments/{id}/capture request with the amounts
and/or custom_data
JSON blocks, or with no JSON body.
With a JSON body:
curl -X POST \
--url 'https://stage-api.wepay.com/payments/{id}/capture' \
-H 'App-Id: {your-app-id}' \
-H 'App-Token: {your-app-token}' \
-H 'Api-Version: 3.0' \
-H 'Content-Type: application/json' \
--data-raw '{
"amounts": {
"amount": {new-capture-amount},
"currency": "USD",
"fee_amount": {fee-amount}
}
}'
Without a JSON body:
curl -X POST \
--url 'https://stage-api.wepay.com/payments/{id}/capture' \
-H 'App-Id: {your-app-id}' \
-H 'App-Token: {your-app-token}' \
-H 'Api-Version: 3.0' \
-H 'Content-Type: application/json' \
Partial Capture
Partial capture is a version of manual capture which allows a card to be authorized and an API Payment to be created, but the final amount in the manual capture request is less than the authorized amount.
To plan for partial capture scenarios, create Payments with a POST /payments request where the auto_capture
parameter is set to false
. The merchant should then have the option to update the amount for capture for 7 days after the API request. Once the merchant is satisfied, execute a payments/{id}/capture
call to finish.
Your POST /payments requests when partial capture is an option should look like this:
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' \
--data-raw '{
"account_id": "{merchant’s-account-id}",
"amount": "{desired-capture-amount}",
"auto_capture": false,
"fee_amount": {calculate-processing-and-platform-fees},
"currency”: “USD",
"payment_method": {
"encoded_payment_method": "{value-from-CP-SDK}""
}
}'
Alternatively, if you want to protect against expired authorizations before capture, use the delayed capture flow. Set a capture_at
time for the Payment within 7 days, and either set auto_capture
to true
or exclude it from the request. There is no need to call /payments/{id}/capture if you choose this flow
.
If the merchant opts to partially capture the Payment, then send a POST /payments/{id}/capture request like this:
curl -X POST \
--url 'https://stage-api.wepay.com/payments/{id}/capture' \
-H 'App-Id: {your-app-id}' \
-H 'App-Token: {your-app-token}' \
-H 'Api-Version: 3.0' \
-H 'Content-Type: application/json' \
--data-raw '{
"amounts": {
"amount": {new-capture-amount},
"currency": "USD",
"fee_amount": {fee-amount}
}
}'
Manage Payment Operations
Partners leveraging WePay’s Clear solution must provide merchants with the tools to manage operations after a payment has been created.
Note
Partners leveraging WePay’s Link solution can direct merchants to their Chase dashboard for these tools.
Issue Refunds
Refund Card Present payments with the Refund API.
For more in-depth guidance, see the Clear developer guide.
Void Payments
Void Card Present payments with the Cancel API.
In order to construct this API request, provide a UI-input for the merchant to submit the text to be used as the value for the cancel_reason
parameter.
Your request may look something like this:
curl -X POST \
--url 'https://stage-api.wepay.com/payments/{ID}/cancel' \
-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' \
--data-raw '{
"cancel_reason": "item(s) delayed - cannot fulfill order"
}'
A successful response will result in a voided payment.
Warning
Terminal payments can only be canceled within 90 minutes of the authorization.
To effectively release an authorization after an API Payment has been created and past the 90-minute window from authorization, take the following steps:
- Call POST /payments/{id} to update the
amount
value to100
- Call POST /payments/{id}/capture within 72 hours from authorization request
- Issue a refund for the remaining dollar with a POST /refunds request
Handle Disputes
Retaining signed receipts for Card Present payments is the best method to challenge any disputes a merchant may receive.
For more in-depth guidance, see the Clear developer guide.
Next Up: Test and Launch
Work through test cases and launch your Card Present integration.
- Use WePay’s magic testing values
- Certify your integration against WePay’s guides
Questions? Need help? Visit our support page!