Automatic Payment Application

Automate applying payments to NetSuite invoices by payment amount or a shared identifier.

Eliminate customized integrations or manual payment application by using SuiteSync to match Stripe payments to NetSuite invoices. The matching process is flexible, error resistant, and is not time-bound. After a payment is matched to an invoice, SuiteSync handles all refunds, disputes, bank reconciliation, etc. There are no additional integrations needed for the remainder of the order lifecycle.

Here are some examples where this is helpful:

  • Invoices are imported into NetSuite using a CSV generated from a homegrown system. Stripe payments need to be matched to the NetSuite invoice and refunds, disputes, bank reconciliation, needs to be automated.
  • SalesForce, Docusign, and Stripe manages sales and initial payment, and NetSuite is used for A/R. SalesForce opportunities are pushed to NetSuite as Invoices, but the Stripe payment needs to be applied to the open NetSuite Invoice.
  • Invoices are created in NetSuite but paid through Stripe on a billing portal within your custom application. Invoices and payment need to be pushed into NetSuite.
  • Stripe handles subscription billing but invoices in NetSuite are created later on by a custom system. Payments created by Stripe's recurring payments system need to be matched to NetSuite invoices.

Here's a short video walkthrough:

In most cases, there is a disconnect between the system creating the Stripe charge and the system creating invoices in NetSuite. This eliminates the need to coordinate or integrate these systems: one system can create a payment, another can create the invoice in NetSuite—SuiteSync manages applying the payment to the correct invoice.

Here’s how it works:

  1. SuiteSync pushes the Stripe payment to NetSuite as an unapplied CustomerPayment
  2. A search is run for an open invoice that matches the payment, either by customer & amount or a custom identifier (more information below).
  3. If a match is found, the CustomerPayment is applied against the matching invoice.
  4. If an invoice match is not found, the search process repeats every hour for three days.
  5. If no match is found after three days, the CustomerPayment is added to a saved search that your billing team can use to manually apply the payment.
  6. Regardless of if a match is found, the payment is reconciled against a bank deposit and fees are calculated.
  7. If the charge is later refunded or disputed, the integration handles creating the required CreditMemo and CustomerRefund in NetSuite automatically.

Note that if you have the internal ID of the invoice you'd like to connect a payment to, you shouldn't use this workflow and instead you should connect the payment directly to a NetSuite invoice using metadata. Here's an example.

Here's a visual overview:

Payment Application Overview

Technical Overview

Matching on Common Identifier

If you have a common identifier (e.g. a shared order ID) that can be passed to the Stripe charge and added to the NetSuite invoice the integration can apply a payment to a NetSuite invoice based on that identifier.

Here's what your system is responsible for:

  1. Adding a common identifier to the Stripe charge and the NetSuite Invoice
  • You can add your identifier to a field on the Stripe charge metadata (or the description field). During the onboarding process, we'll configure your account to pull from that specific metadata field.
  • The integration can match on a standard or custom NetSuite field. Pushing your identifier to a custom field on the NetSuite Invoice works great.
  1. If you expect to have a large number of unmatched invoices, it may be helpful to ensure that charges are created "under" a customer record in Stripe with the same email as the corresponding NetSuite customer. This ensures that if an invoice match is not found the payment is connected to the correct NetSuite customer.

Here's what SuiteSync handles:

  1. Immediately the Stripe charge is created as an unapplied customer payment
  2. Every hour for three days (this can be customized) a search is run for an open invoice with a matching identifier.
  3. If a match is found, the payment is applied to the Invoice. If the invoice is associated with a different customer than the initial payment, the customer on the payment is changed to the Invoice's customer.
  4. If no match is found after three days, a memo is added to the payment. It is also added to the "Unapplied Stripe Payments" queue (a saved search that is added to your account). It's possible to mark the payment for automatic application (aka "auto apply", a NetSuite feature) if an exact match was not found.
  5. Refunds, disputes, reconciliation, etc.

View Example Implementation

Some technical details to keep in mind:

  • The common identifier in Stripe is not sanitized. It’s important that the identifier is passed into Stripe exactly as it is stored in NetSuite. Make sure you strip all whitespace or other extra characters from the identifier that is not present on the NetSuite side.
  • The field in NetSuite must be a free-form text field. Date, lists, reference fields, etc are not supported right now.
  • Matching is not dependent on the order of operations. The invoice could be created before or after the charge is created in Stripe.
  • The common identifier does not need to be added immediately when the charge is created. It can be added anytime within the retry window.
  • If there are multiple matches for a Stripe charge, the charge is applied to the oldest invoice.
  • The currency of the created invoice must match the currency of the Stripe charge.
  • If you'd like to re-trigger the match operation after three days this can be done using metadata. Contact support to enable this feature.

Matching one payment to multiple invoices

In some cases, you'll have one payment in Stripe that should be applied to multiple invoices in NetSuite. This is supported by passing a comma-separated list of common identifiers to the Stripe payment.

Here's how it works:

  1. A Stripe charge is created with a list of NetSuite invoice identifiers. For example: INV1,INV2,INV3,INV34
  2. For each identifier, a matching invoice is searched for. The unapplied amount on a payment is applied to the matching invoices' amount due in the order that they are specified in the comma separated list.
  3. The rest of the process works identically to when a charge is matched against a single invoice.

View Example Implementation

Some technical details to keep in mind:

  • There is no way to specify the amount that should be applied to a specific invoice. For instance, if you have a $100 payment and four open invoices of $100 there is no way to instruct the integration to apply the invoice evenly across those four invoices. The full $100 would is applied against the first invoice. For this case, we recommend using a SuiteSync afterSubmit hook on the CustomerPayment to manage this custom application logic.
  • Payments are applied in the order that they are specified in the comma-separated list in conjunction with the order that they are found in NetSuite. For example, if the first invoice in the comma-separated list on the Stripe charge is not found in NetSuite (e.g. not created yet), the full amount of the payment is applied to the second invoice in the list. If you need to control the timing around when the matching operation is kicked off in SuiteSync, you can do so by using the netsuite_block_integration metadata flag.
  • Refunds and disputes will be "created from" the first invoice the payment is applied to. The line item used on the credit memo will be a "Stripe Refund Item" that isn't tied back to the original items on the invoices.

Matching on Payment Amount

If the Stripe charge has a customer record, an open invoice associated with the corresponding NetSuite customer with an "amount remaining" (plus/minus $0.05) is searched for. Customers can be matched automatically based on email or linked manually.

Your system is responsible for:

  1. Ensuring the Stripe customer is linked to the same customer the NetSuite Invoice is created against. Here’s an example of how to link a Stripe customer to a NetSuite customer.
  2. Creating a Stripe charge with an amount that matches the total amount due. Note that a tolerance amount can be configured to enable payments to match if they are within a couple of cents of the amount due on an open NetSuite Invoice. Slight mismatches can often occur in more complex invoice structures where NetSuite rounds decimal numbers in an unexpected way.

View Example Implementation

What if the payment amount does not match the invoice amount due? What if I have multiple payments against a single invoice?

If the amount of the payment does not match the amount due on the invoice, SuiteSync will not automatically match the payment against the invoice. However, if a match is not found, the "auto apply" feature of NetSuite can be used to automatically apply the payment against the customer's open invoices.

Here are some use cases where this approach is helpful:

  1. A customer purchases and product and pays for the product with multiple payments (i.e. payment installments)
  2. A customer pre-orders a product or service and places a percentage deposit

Here's how this works:

  1. Create a customer in Stripe.
  2. Create a payment in Stripe with that customer. It's often helpful to add an identifier to payment that's unique to your system that can be pulled into a field on the NetSuite payment record.
  3. Separately, either before or after the above steps, create an Invoice in NetSuite. Ensure that the customer in NetSuite has the same email as the customer in Stripe (if that's not possible, you'll need to link the Stripe customer to NetSuite using metadata)
  4. The integration creates a CustomerPayment, and after it cannot find a match, it enables "auto apply" in NetSuite and tags the payment with a message indicating that an automatic match cannot be found.

If customers only have one open invoice at a time, this works perfectly. The payment is automatically applied against the invoice!

If customers have multiple open invoices, you should match on a custom identifier instead.

If you are looking to implement payment installments, or limit the number of times a subscription auto-renews, you can use Stripe's subscriptions in combination with the undocumented max_occurrences parameter to automatically charge customers a certain number of times. Here's more information on this feature.

After a Match is Found

Regardless of which matching method is used, SuiteSync automates the remainder of the order/payment lifecycle

  1. Handling refunds or disputes created against the charge. Refunds or disputes are represented as a CreditMemo and CustomerRefund.
  2. Reconciling payments, refunds, and disputes to the correct bank deposit.
  3. Calculating processing fees, fee refunds, dispute fees, etc.
  4. Handling creating refunds in Stripe from NetSuite.

Common Questions

What happens if no match is found?

If no match is found, the auto-match operation is re-run every hour for the next three days.

After a three day period if no match is found, Stripe Error: no invoice match found is added to the memo of the CustomerPayment. Additionally, the CustomerPayment is added to a saved search that we'll add to your account. This saved search allows you to keep track of payments that could not be matched to a corresponding invoice.

If no match is found, there’s an optional feature available which enables "auto apply" on the CustomerPayment.

If a CustomerPayments is manually applied does the integration continue to search for a match?

No. As soon as the CustomerPayment is fully applied to one or more invoices, SuiteSync stops searching for matches.

Can I manually apply a portion of a CustomerPayment, and let SuiteSync auto-match the remaining unapplied amount?

Yes. The auto-match functionality looks at the unapplied amount of a CustomerPayment and the amount remaining amount on invoices to determine a match.

How are refunds and disputes handled?

If the charge is successfully linked to an invoice, both a CreditMemo and CustomerRefund are created to handle both the income and cash representation of the refund. Disputes function in a very similar way.

It’s also possible to initiate a refund from NetSuite, by creating a CreditMemo on the associated invoice or by creating a CustomerRefund applied directly against the CustomerPayment. This is an optional feature.

How can I find all unmatched payments?

A saved search is added to your NetSuite account which identifies any unmatched payments.

Note that payments only appear in this saved search after the three long days of searching tirelessly through the NetSuite database has passed. It's sad when a payment can't find it's home, but your finance team can use this saved search to make sure these unmatched payments aren't left out of the party.

Can payments be matched to a CashSale?

No. Since a CashSale represents an invoice and payment in a single record there is no way to represent an unmatched payment when a CashSale is used. Only invoices are supported.