Create Payment Methods
Tokenize Credit Cards
For this section, we implement the Card on File:
- Create a Payment Method by calling
/payment_methods
(via Tokenization), which contains the payer's credit card or payment bank. - Store the payment method ID for the user.
- When a payer is ready to buy, create a Payment by calling
/payments
, using the payment method ID.
For testing purposes in the stage environment, use the credit card values listed in the testing section here.
First, we create a Payment Method.
WePay.tokens.create({
"resource": "payment_methods",
"payment_methods": {
"type": "credit_card",
"credit_card": {
"card_number": "4111111111111111", // Visa test number.
"expiration_month": 4,
"expiration_year": 2023,
"cvv": "007",
"virtual_terminal_mode": "web",
"auto_update": false
}
}
}, {}, function(response) {
console.log(response);
});
payment_methods-f4059a38-5640-41f3-a426-ef915eacaefa
.Note
Tokens have a time-to-live (TTL) of 30 minutes.
trigger_verification
parameter is set to true
(default) on the WePay.tokens.create
JS call. Successful authorizations are reflected when the Payment Method has "status": "verified"
. Note:
trigger_verification
defaults to true
, and we strongly discourage sending a false
value. Checking the validity of a credit card upon submission offers the payer a chance to submit a different, valid payment method while they are still in your UI, in addition to reducing the number of unsuccessful payments overall.You can either immediately create a Payment, or you can create a Payment Method and process Payments at a later time.
Designate Or Identify A Card's Funding Source
BETA
Disabling the creation of debit or credit card payment methods is currently a closed BETA offering on API version 3.1.rc.1.3
.
We offer a method of allowing only a credit or debit card funding source during payment method creation. Alternatively, you can simply read the value on the payment method after creation to identify its funding source.
Designate A Funding SourceWhen creating a new payment method with
POST /payment_method
or POST /payments
, you can set the optional field card_funding
to debit
or credit
. The debit
value will only successfully create a payment method if the card's funding source is debit, while the credit
value will only successfully create a payment method if the card's funding source is credit. Test credentials
In our stage environment, use the following test credentials:
- 4242424242424242 for credit
- 4000056655665556 for debit
Your request may look like this:
{
"type": "credit_card",
"credit_card": {
"card_holder": {
"holder_name": "John Doe",
"address": {
"postal_code": "94122",
"country": "US"
}
},
"card_number": "4000056655665556",
"expiration_month": 1,
"expiration_year": 2042,
"cvv": "007",
"card_on_file": false,
"recurring": false,
"card_funding": "debit"
}
}
{
"type": "credit_card",
"credit_card": {
"card_holder": {
"holder_name": "John Doe",
"address": {
"postal_code": "94122",
"country": "US"
}
},
"card_number": "4242424242424242",
"expiration_month": 1,
"expiration_year": 2042,
"cvv": "007",
"card_on_file": false,
"recurring": false,
"card_funding": "credit"
}
}
WePay.tokens.create({
"resource": "payment_methods",
"payment_methods": {
"type": "credit_card",
"credit_card": {
"card_number": "4111111111111111", // Visa test number.
"expiration_month": 4,
"expiration_year": 2023,
"cvv": "007",
"virtual_terminal_mode": "web",
"auto_update": false,
"card_funding": {"credit / debit"}
}
}
}, {}, function(response) {
console.log(response);
});
card_funding
is not specified in your API request, the default value will be null
and this will allow a payment_method_id
to be created regardless of the card's funding source.Identify A Funding Source Once a card has been created, you can identify its funding source on the
card_funding
response parameter even if you did not set the parameter during creation. Note that the value can be null
, but this is a rare edge case that will only occur on very new card types / offerings that have not yet been incorporated in our bin lookup sources.Disable Prepaid/Gift Card Payment Methods
BETA
Disabling the creation of prepaid card payment methods is currently a closed BETA offering on API version 3.1.rc.1.3
.
We offer you a way to ensure that payment methods aren't being created with prepaid type cards including but not limited to: gift cards, reloadable, virtual, etc.
When creating a new payment method withPOST /payment_method
or POST /payments
, you can set the optional field bin_details.is_prepaid
to false
, indicating that you do not want a payment_method_id
to be created if we validate that the card information submitted is a prepaid type card. Below is an example request:
{
"type": "credit_card",
"credit_card": {
"card_holder": {
"holder_name": "John Doe",
"address": {
"postal_code": "94122",
"country": "US"
}
},
"card_number": "5496198584584769",
"expiration_month": 1,
"expiration_year": 2042,
"cvv": "007",
"card_on_file": false,
"recurring": false,
"bin_details": {
"is_prepaid": false
}
}
}
WePay.tokens.create({
"resource": "payment_methods",
"payment_methods": {
"type": "credit_card",
"credit_card": {
"card_number": "4111111111111111", // Visa test number.
"expiration_month": 4,
"expiration_year": 2023,
"cvv": "007",
"virtual_terminal_mode": "web",
"auto_update": false,
"bin_details": {
"is_prepaid": false
}
}
}
}, {}, function(response) {
console.log(response);
});
is_prepaid
to false
and prepaid card information is sent, the error PREPAID_VALIDATION_MISMATCH
will be returned and a payment_method_id
will not be created to make payments.Reminder: This is an optional field. If
is_prepaid
is not specified in your API request, the default value will be null
and this will allow a payment_method_id
to be created regardless if it is a prepaid card or not.Note
is_prepaid
is set to true
, a payment_method_id
will be created for prepaid type cards only.Tokenize Bank Accounts
Note
Only banks in the US can be used as payment methods.
This flow allows your platform to provide a custom UI for processing ACH payments. We highly recommend tokenizing raw bank account data even though it does not fall within the scope of PCI requirements. As a reminder, ACH payments are only supported for US Banks.
First, tokenize thepayment_bank_us
structure of a Payment Method:WePay.tokens.create({
"resource": "payment_methods",
"payment_methods": {
"type": "payment_bank_us",
"payment_bank_us": {
"account_holder": {
"holder_name": "Test Test",
"email": "foo@bar.com",
"address": {
"country": "US",
"postal_code": "94025"
}
},
"account_number": "124523092", // Use any 3-17 digit bank account number for testing.
"routing_number": "021000021", // Testing US routing number
"account_type": "checking"
}
}
}, {}, function(response) {
console.log(response);
});
token
from the response.Next, either:
- create a Payment immediately with the token ID, or
- create a Payment Method
Note
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).Create A Bank Account Payment With The Token ID
Use thetoken
parameter on the POST /payments
request: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-account-id}",
"amount": 20000,
"currency": "USD",
"fee_amount": 100,
"payment_method": {
"type": "bank_account_us",
"token": {
"id": "{payment_methods-TOKEN-HERE}"
},
},
"custom_data": {
"my_key": "invoice #54321"
},
"rbits": [{
"properties": {
"report_url": "example.com"
},
"receive_time": 1367958263,
"source": "guidestar",
"type": "business_report"
}]
}'
Create A Bank Account Payment Method With The Token ID
Use thetoken
parameter on the POST /payment_methods
request:curl -X POST \
--url 'https://stage-api.wepay.com/payment_methods' \
-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 '{
"token": {
"id": "{payment_methods-YOUR-TOKEN-HERE}"
},
"custom_data": {
"my_key": "invoice #54321"
},
"rbits": [{
"properties": {
"report_url": "example.com"
},
"receive_time": 1367958263,
"source": "guidestar",
"type": "business_report"
}]
}'
Unique-Key
header, described in our Standard Headers and Idempotency article. This header is required when calling POST /payments
and POST /refunds
in order to protect against duplicate processing, and is recommended on all other endpoints. You'll notice that the API response will send
"status": "unverified
. To move the status
to verified
, the payer will need to verify the micro deposit amounts that we send to the bank account.To verify a payment bank, you are responsible for:
- Collecting acceptance of WePay's Terms of Service and NACHA rules from the payer
- Handling the micro deposit verification flow with the payer
To handle the micro deposit verification flow, first build out a UI to accept two dollar amounts in cents from the payer. Next, build out an email flow through which the payer can access that UI and submit the micro deposit amounts. Once the payer submits those amounts, make a POST /payment_methods/{id}/verify_bank_deposits
call using the payment method ID in the endpoint and the amounts sent to your account holder by the payer in the JSON request body:
{
"microdeposits": [10, 55]
}
"status": "verified"
. Once a payment bank is in a verified status, you can use it in POST /payments
calls to process ACH payments. On the second failed verification attempt, the payment method object will have a
status
of disabled
. Subsequent requests to POST /payment_methods/{id}/verify_bank_deposits
after 2 failed attempts will return the following error:{
"error_code": "INVALID_PARAMS",
"error_message": "Invalid parameter(s).",
"details": [{
"target": ["payment_methods"],
"target_type": "HTTP_REQUEST_PATH",
"reason_code": "ID_NOT_FOUND",
"message": "ID 00000000-6261-5553-0000-00000003557c not found."
}]
}
payment_methods.microdeposit_verification_failed
Notification event topic will fire. If a payment was created prior to verification failure, it will move from a status
of pending
to canceled
. Payments with a bank account payment method pending verification can stay in a pending
state for 30 days before they will automatically move to canceled
. The constraint of only 2 verification attempts exists to protect against fraud in the ACH/Echeck sphere. If this occurs, the payer should double check their bank account credentials and resubmit payment. To this end, send a
DELETE /payment_methods/{id}
request to remove the abandoned Payment Method. 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 us. If the response from an issuing bank declines the payment and takes longer than 2 business days, then the payment will automatically be refunded.Inline Payment Methods
When creating inline payment methods in aPOST /payments
request, the authorization minimum is $1, include that in the amount in the payment. There will be a $1 pending charge that will drop off in 7 days or if the payment is canceled before that.