Best Practices


Environment Setup

 

To ensure a successful integration, we recommend you avoid only using your app account for testing. Using APIs to create merchants and their accounts, and charging to these accounts, will lead to a solid understanding of access tokens, app and WePay fees, and both your and your merchants’ account transactions.


Using IPNs

 

IPNs are a considered a key component of a successful integration. We strongly recommend making use of the callback_uri on every appropriate API call. You can learn more in the IPN reference document.


Merchant Scope

 

When onboarding a merchant onto your platform, the merchant agrees to allow you to process payments for them. In other words, they grant you a set of permissions. The permissions you want to obtain from your merchants are defined in the “scope” parameter, which is described as a comma-separated list of permissions. This parameter is found in both the /oauth2/authorize and /user/register calls.

It is important to note that either call, used during initial onboarding, is the only opportunity to define the permissions to be requested. To look at it another way, the only way to modify a merchant’s permissions at a later date is to run them through the onboarding process again.

As such, we recommend to ask for all documented permissions up front. Fundamentally, merchants will want you to be able to do everything contained in the permissions. The merchant always has the ability to revoke access but we rarely, if ever, seen an issue in a partner taking this approach to permissions. It is the platform’s prerogative to limit the scope parameter to its immediate need, but please consider the friction it could cause your merchants if you need more permissions as your platform functionality evolves, as you will have to onboard your merchants again.


Recognizable Account Names

 

This best practice will leverage an excerpt from this article by Visa:

“The merchant name is the single most important factor in cardholder recognition of transactions. Therefore, it is critical that the merchant name, while reflecting the merchant’s “Doing Business As” (DBA) name, also be clearly identifiable to the cardholder.”

Payments made through WePay appear on your cardholder’s statements as WPY*account_name, where account name is defined in the /account/create and /account/modify calls. It is important for you to use easily recognizable and understandable merchant (account) names to avoid confusion, reduce support overhead, and mitigate potential chargebacks resulting from poor information delivery to the cardholder. The following identifies best practices for naming accounts within the parameters available from the card networks:

  • The merchant must be recognizable in the first 14 characters due to limitations imposed by the card networks
  • Many partners successfully use merchant names longer than 14 characters. However, care should be taken to make the first 14 characters understandable in the context of WPY*account_name.
  • The merchant name should not be composed of reference ids or other internal terminology.

Unique ID

 

This best practice is aimed at eliminating duplicate checkouts and unwanted payment declines by the issuing banks when two or more checkouts occur in rapid succession. This directly affects the experience of the merchants and payers on your platform.

While most API calls are quite harmless if a timeout occurs, others are not. Specifically, a timeout experienced during checkout creation is likely to cause either a missing or duplicate transaction, depending on how errors are processed.

With a synchronous API call, it is difficult to know the stage of the operation when the call results in a timeout. Did the request reach WePay servers? Did WePay’s response timeout on its return? If the call was handled on the server side, how do I retrieve the vital details of the operation?

We’re not going to answer these questions. Instead, we’re going to take a different approach to handling timeouts. Our approach is detailed below:

If you are unsure what happened, run the exact same call again and we will fulfill your original request. You don’t need to be concerned if the object was created or not.

To accomplish this, we will use one additional parameter and introduce a new concept when creating a checkout. This parameter is named “unique_id”, and the concept is called Idempotencey.

Idempotence: the property of certain operations in mathematics and computer science, that can be applied multiple times without changing the result beyond the initial application.

What does all this mean? If you use a new unique_id with each intended checkout creation, recovering from a timeout is as simple as making the exact same call again. To us, the unique_id parameter ensures no two checkout create calls are the same and that they can be uniquely identified in our system. When a checkout create call is accompanied by a unique_id, we check to see if it already exists in our system. If so, we return the information for the existing object. If not, we create the object. Either way, your original request is fulfilled.

Use the following pseudocode to ensure you create unique ids in the correct manner.

response create_checkout(amount, account_id, …) {
	//create the unique_id for this call
	uid = get_GUID()
	error_message = "there was an unknown error - please contact api@wepay.com for support"
	loop (some reasonable number of times){
		try {
			// call the /checkout/create endpoint and collect the response
			resp = wepay_checkout_create(uid, amount, account_id);

			// if there is an error in the response, and the error code is 1008
			// and the error message matches this string exactly,
			// then we need to continue through the loop to retry the checkout.
			// If *neither* of these two conditions are met,
			// then we need to return the response
			if (resp['error_code'] != 1008 ||
			resp['error_message'] != error_message)
				return resp;
		}
		catch (timeout) {
			// In the event of a timeout, do nothing and go through the loop again
			// to retry the checkout
		}
	}
}

Note: The unique_id is created at the beginning of the method and keeps its value throughout. Do not extend the functionality of this method to process other types of errors which are remedied by adjusting parameter values. In these circumstances, the unique_id is considered “used” in our system.


Fees

 

There are various fee settings of the /checkout/create call. There are fields to configure, which are amount, app_fee, and fee_payer. The fee_payer parameter has four acceptable values, where the payer, payee (merchant), application, and WePay participate in the transaction to varying degrees. We’ll walk through examples to help showcase how you can think about fees for your app platform.

For the vast majority of use cases, it’s fine to only use a fee_payer value of “payee_from_app”, which, in the context of the other three possibilities, is defined as:

The merchant pays the app_fee and the app platform pays the WePay processing fee.

In this most simple case, there are still four parties involved: the payer, merchant (payee), app platform, and WePay. Let’s step back and look at this simply from the amount and app_fee parameters. With this context, let’s re-examine fee settings:

The payer will pay the amount, the application will receive the app_fee, the remainder will go to the merchant, and the processing_fee will be paid by the application.

Examples

To keep the math simple, let’s assume the app platform is paying a 3% WePay fee (“processing_fee”) and every transaction will start with a $100 purchase. Make note of the resulting processing_fee, as it is always calculated against the amount passed in the API call.

Use Case 1: Platform advertises a fee of 4% to merchants.

  • amount = $100.00
  • app_fee= $4.00

The payer will pay the amount of $100, the application will receive the app_fee of $4, the remainder, $96, will go to the merchant, and the processing_fee of $3 will be paid by the application.

Use Case 2: Platform advertises a fee of 4% to the payer.

  • amount = $104.00
  • app_fee= $4.00

The payer will pay the amount of $104, the application will receive the app_fee of $4, the remainder, $100, will go to the merchant, and the processing_fee of $3.12 will be paid by the application.

Use Case 3: Platform advertises a fee of 4% where 3% is paid by the merchant and 1% is paid by the payer.

  • amount = $101.00
  • app_fee= $4.00

The payer will pay the amount ($101), the application will receive the app_fee ($4), the remainder ($97) will go to the merchant, and the processing_fee ($3.03) will be paid by the application.

Since the app_fee calculation is not dependent on the WePay fee, no maintenance is necessary if your WePay fee is adjusted.

This method should address the majority of use cases, but if you feel your situation is unique, please reach out to your WePay account manager for guidance.


Throttle Limits / Batching requests

 

In an effort to protect all our partners from poor performance, our system uses API throttling. Even the largest of partners rarely need their limits modified, but we do realize, under rare circumstances, exceptions must be made. If you feel you need a higher limit after testing reasonable use cases and implementing batch requests, we’re happy to evaluate your specific situation. You can read more about this in the throttling and batch calls reference pages.


Error Handling

 

These guidelines provide best practices on how best to handle WePay errors. Following these best practices will result in a better end-to-end experience from development to supporting end-users. You can find a basic summary of WePay API errors in the Error API Reference.

Error Content

Errors returned via the WePay API will include an error, error description, error code, details, and documentation URL:

Structure

{
  "error": "[type_of_error]", 
  "error_description": "[description_of_error]", 
  "error_code": [code_of_error],
  "details": [
  	{
  	  "target": "[parameter_that_caused_the_issue]",
      "target_type": "[describes_target]",
      "message": "[describes_the_problem]",
      "reason_code": [code_of_reason]
  	}],
  "documentation_url": "[error_api_reference_URL]""
}

Example

{
  "error": "processing_error",
  "error_description": "Unable to charge payment method: general decline",
  "error_code": 1008,
  "details": [],
  "documentation_url": "https://developer.wepay.com/api/general/errors#1008"
}

  • Error: A basic error category. Most errors are outlined in our general error page, but others include: invalid_parameter (similar to invalid_request) and throttle_exceeded (relating to the rate of API calls from your app).
  • Error Description: A brief description of what caused the error. You should parse this parameter and make the information available to your internal teams for debugging. Consuming and interpreting the Error Description is vital to troubleshooting and resolving errors since the Error and Error Code parameters alone can refer to many variations of the same type of error
  • Error Code: An integer that can be used to aggregate and analyze error trends. It can also be cross referenced on our general error page where you will find a corresponding general description. Please note that the general description will not always match the Error Description, so it is still important to parse the Error Description.
  • Details: An array containing detailed error information for /account/kyc API calls and /checkout* API calls with an in-line credit card. The array will be empty if the API call is not one of these.
  • Documentation URL: A URL to the relevant WePay Error article.

Interpreting Errors

  • Logging calls: Logging and storing all of your API calls (including those that result in an error) is highly recommended both for maintaining your own data set independent from WePay, and for handling errors. Having a log helps identify an issue’s origin.
  • HTTP Errors: For all HTTP response codes other than 2XX, the WePay API Error Code must be parsed out. Additionally, retrying the call will not resolve the issue in most cases, so further investigation of the error code is required. We suggest getting started by visiting WePay’s status page, paying special attention to the API component. Please note that HTTP timeout errors can look like an API error, and our status page is still the best place to get started on resolving.
  • Parsing errors: Use the Error Code to guide your programmatic handling and troubleshooting. Key error information is included in all of the parameters in an error response, so parsing everything out and either storing it or serving it up internally and/or externally is required for effective error resolution.
  • Handling errors by type: Errors can result from an issue on WePay’s end, an issue with how your app made or formatted the call, or a change to an object that prevents an API action your app is trying to take. For errors that result from a change that has been made to an object, you will want to build logic in your code to handle the error, rather than troubleshoot it. For example, error “4003: This payment method can no longer transact” should be handled with a lookup on the payment method and a message to the payer that a new payment method is needed when the lookup returns a deleted, expired, or invalid state.

Common Errors

Below we’ve outlined some of our most common errors along with our recommended action. We’ve also compiled a list our top errors from the past 6 months that you can view here.

1001: Access Token has been revoked
Access tokens become revoked if no KYC/settlement information is provided after disablement or if you issue a new token to the user. This error is common when a new token has been issued but the old one is being used in the API.

Recommended Remediation: If you did not log a new token, then you need to generate another new token for the user. Build your logic to log and use the new token any time one is generated through the Oauth2 API. That being said, you should not generate a new token when a user on your platform with a valid WePay wants to create additional WePay account(s) on your platform.

1008: There was an unknown error - Contact api@wepay.com
This error can occur for various reasons. Commonly, 1008 will return on duplicate attempts that already received a different error. Additionally, 1008 will return when a payment permanently fails or when edge case occur.

Recommended Remediation: Review your API log to determine if this error is returning on retried calls that initially returned a different error with more helpful context to troubleshoot and resolve. If not, then reach out to api@wepay.com. If this error returns on the /checkout/create endpoint AND you are utilizing unique IDs on Checkouts, retry the payment. If the Error Description returns with “Unique ID failed permanently,” then identify why the first /checkout/create call with that Unique ID failed and formulate a resolution plan from there.

Note

If you have not leveraged unique IDs for checkouts, please see our notes in our /checkout/create API Reference.

1008, 2002, 2003, 2004, 2005, 2006, 2007, 2008, or 2009: Unable to charge payment method: general decline
The card issuer declined the payment. Reasons that a card issuer might decline a charge include insufficient funds, card reported as lost/stolen, or general fraud concerns. That being said, the exact reason is not provided to WePay.

Recommended Remediation: Whenever an Error Description includes Unable to charge payment method: general decline, the payer will need to either use a different card or work directly with their card issuer as WePay can only process payments that the card issuer authorizes.

3002, 3302, 4002, 5002, 6002, or 7001: The User with that Access Token cannot access this object
This typically occurs when your app attempts to take action on an object such as a checkout, preapproval, or withdrawal that was initially created with an access token that has since been updated. That said, be sure to check that users onboarded with OAuth2 API have the full necessary scope.

Recommended Remediation: To resolve these errors, first examine your logs to confirm that you are sending the same access token that you currently have on file for the user. If you are, then check if any new tokens have been issued to that user that you did not log (/oauth2/token calls would issue a new token). If needed, follow the same remediation steps as “Access Token revoked” errors.

4003: This payment method can no longer transact
There are many reasons a payment method may not be able to transact. For instance, if WePay attempts to authorize a credit card but the authorization gets declined, the credit card object will move to an Invalid state and can no longer be used.

Recommended Remediation: You should first determine if the card is in a Deleted, Expired, or Invalid API state with a lookup call. If so, payer will need to submit a new payment method. Otherwise, please reach out to WePay’s merchant support.

3003: This account has been deleted
Sometimes users will inadvertently delete their WePay account from the merchant dashboard, or your records may not be up to date.

Recommended Remediation: Create a new account or reach out to WePay’s merchant support to re-enable the account.

Note

IPNs will send you an update as soon as an account is deleted rather than attempting an API call and receiving an error. Read more about our IPNs.

1010: You do not have sufficient permissions
Some WePay features require permission from a WePay Relationship Executive. The endpoints that require permission are marked with a green “Permission Required” banner in our API Reference.

Recommended Remediation: If you receive this error while attempting to create CAD or GBP accounts, reach out to api@wepay.com. For any other features, reach out to your Relationship Executive to determine your eligibility for the feature.

1007: Your app has been throttled for making too many calls. Please retry this call later
WePay will automatically throttle your API calls at 30 calls per 10 seconds in order to protect against attacks and coding errors.

Recommended Remediation: Retry the call later if you’ve experienced a one-off of this error. If you experience this error regularly, we recommend reviewing your call logs and identifying flows that can be optimized. If all else fails, reach out to your Technical Account Manager or api@wepay.com for further consultation.


Pre-Launch Checklist

 

  1. Review any necessary PCI Compliance requirements.
  2. Email api@wepay.com and send us your stage and production app ids (client ids) so we can migrate any administrative settings from stage to production.
  3. Perform a final check on your app fee settings.
  4. Perform a final check on your scope settings (OAuth2 or /user/register).
  5. Switch endpoints from stage to production.