Skip to main content
Version: march-24-production

How to use the Payment API v2

In this article we present a few hands-on examples of how to use the FinDock Payment API.

The examples here use credit card as the payment method and FinDock as the source. If these terms (method and source) are unfamiliar to you, please read our getting started article.

New one-time payment

Payments are initiated by performing a POST to the FinDock /PaymentIntent endpoint. The request must have a body and an authorization header.

Request

The Root of the request contains the success and failure URLs and the origin (e.g. what website or platform is making the request). The Root may also include a webhook URL, but this attribute is not required. If the transaction is successful, the customer is redirected to the success URL. If the customer cancels the transaction, the redirection is to the failure URL. The origin is logged in Salesforce as a text string to indicate what form was used for initiating the transaction.

{
"SuccessURL": "https://www.example.com/success",
"FailureURL": "https://www.example.com/error"
}

The Payer object contains the details of the payer, Eric Johnson, in this example. AllowDepulication is set to true, so if Salesforce finds an existing Eric Johnson in the database (according to the deduplication rules), the existing contact shall be used.

Please note we put all the Contact and Account fields in a SalesforceFields object. In this object, you can pass any field - both standard Salesforce and custom - that is available on this object in your Salesforce environment.

    {
"SuccessURL": "https://www.example.com/success",
"FailureURL": "https://www.example.com/error",
"Payer": {
"Contact": {
"SalesforceFields": {
"FirstName":"Eric",
"LastName":"Johnson",
"Email":"eric@johnson.com",
"MailingStreet":"Rocket Rd",
"MailingCity":"Hawthorne0",
"MailingPostalCode":"CA 90250",
"MobilePhone":"98989898"
}
},
"Account":{
"SalesforceFields": {
"Name":"Johnson Family",
"Website":"www.spacex.com",
"BillingStreet":"Rocket Rd",
"BillingCity":"Hawthorne",
"BillingPostalCode":"CA 90250"
}
}
}
note

If you are using NPSP, we recommend adding AccountRecordTypeName to the Account declaration.

The Payment object indicates this request is a one-time transaction. The amount is 10, and since there is no CurrencyISOCode attributed, the default currency defined for the Salesforce org is used.

"OneTime": {
"Amount": "36"
},

The PaymentMethod object indicates the transaction uses the credit card payment method. Since this Salesforce org has several processors configured that can be used to perform credit card payments, we explicitly specify Mollie as the processor.

"PaymentMethod": {
"Name": "CreditCard",
"Processor": "PaymentHub-Stripe"
}
}
note

If no processor is provided, FinDock uses the default payment processor configured for this payment method in the FinDock setup. To find out which processor is the default, perform a GET on the /PaymentMethods endpoint.

The Settings object explicitly defines FinDock as the source. This means we are using FinDock Standalone and there are no source apps, such as Nonprofit Success Pack, in the Salesforce org that would need the payment data. You can leave theSourceConnector parameter out if you always want to use the default source connector in the Salesforce environment.

    "Settings": {
"SourceConnector": "PaymentHub"
}

The full message sent to https://your-org-url.force.com/services/apexrest/cpm/v2/PaymentIntent should look something like this:

{
"SuccessURL": "https://www.example.com/success",
"FailureURL": "https://www.example.com/error",
"Payer": {
"Contact": {
"SalesforceFields": {
"FirstName": "Eric",
"LastName": "Johnson",
"Email": "eric@johnson.com",
"MailingStreet": "Rocket Rd",
"MailingCity": "Hawthorne0",
"MailingPostalCode": "CA 90250",
"MobilePhone": "98989898"
}
},
"Account": {
"SalesforceFields": {
"Name": "Johnson Family",
"Website": "www.spacex.com",
"BillingStreet": "Rocket Rd",
"BillingCity": "Hawthorne",
"BillingPostalCode": "CA 90250"
}
}
},
"OneTime": {
"Amount": "36"
},
"PaymentMethod": {
"Name": "CreditCard",
"Processor": "PaymentHub-Stripe"
},
"Settings": {
"SourceConnector": "PaymentHub"
}
}

Response

The response on the new one-time payment request has a similar structure to the request:

{
"Settings": {
"SourceConnector": "PaymentHub",
"ProcessingType": "Default"
},
"RedirectURL": "https://redirect.test.findock.com/3xnllmuai2/PaymentHub-Stripe/checkout?publicKey=pk_test_eGC6TxzQ60CdjpAkt2RG3CwZ008WiiOn12&sessionId=cs_test_ifQhP4ggbSQrjJYoi3AEVrEmO3Agl5O6ihy4THgYtuswvW1yX9wjmA59",
"PaymentMethod": {
"Processor": "PaymentHub-Stripe",
"Name": "CreditCard"
},
"Id": "pi_vqv330n7dvd9j8210"
}

The Settings object response indicates that the payment was created with FinDock Standalone (PaymentHub) as SourceConnector.

The PaymentMethod object response indicates that the transaction will be processed as a Credit Card payment through Stripe.

The Id is an Id that identifies this Payment Intent. This id is stable across all communication from and to FinDock, and can be found:

  • on the created Inbound Report record in Salesforce. On this Inbound Report the API call is processed through Guided Matching.
  • in Webhook notifications to the WebhookURL you can specify in the request body.

You can also retrieve the status of the Payment through a GET request on the /PaymentIntent endpoint.

Guided Matching Payment Intent

For more information on processing and reconciliation of online Payments through Guided Matching, please read our processing and reconciliation article.

Finalizing the one-time transaction

Because this is a new payment for a new contact, the customer/donor needs to provide credit card details and should be forwarded to the RedirectURL in the response.

     "RedirectURL": "https://redirect.test.findock.com/3xnllmuai2/PaymentHub-Stripe/checkout?publicKey=pk_test_eGC6TxzQ60CdjpAkt2RG3CwZ008WiiOn12&sessionId=cs_test_ifQhP4ggbSQrjJYoi3AEVrEmO3Agl5O6ihy4THgYtuswvW1yX9wjmA59"

In our example, since Stripe is the processor, the payment form is a Stripe payment form.

Stripe Payment Page

note

Although this Stripe payment page is close to the production version, many payment processors show different pages for testing. We strongly recommend performing a ‘penny test’ with a real, small payment amount in your production environment to account for these differences in the test setup.

Once the customer completes the transaction, the customer is redirected to the SuccessURL or FailureURL value from the initial PaymentIntent. Parallely, FinDock receives a callback from the PSP (Stripe) and the following actions are performed in Salesforce through Guided Matching:

Guided Matching Notification steps

  • The installment record is updated (status is set to ‘Collected’ and amount is reduced by the amount paid to 0).

Installment Collected

  • A Payment record is created for the Installment.

Credit Card Payment

  • A Payment Profile is created related to the Contact based on the data provided by the PSP, like the type of credit card. If the Payment Profile had already existed for this contact, it would have been updated instead. This data can be used to personalize (e.g. pre-fill forms) future payment requests for this customer. Payment profiles are deduplicated automatically by FinDock.

Payment Profile

Pay existing outstanding installment

Payments are initiated by performing a POST to the FinDock /PaymentIntent endpoint. The request must have a body and an authorization header. Make sure the Installment you are trying to pay has an open amount.

Request

The request body is the same as for a new one-time payment with one important exception: an InstallmentId is added in the OneTime object. No Payer object is required, since this customer data is already in Salesforce. A basic request looks something like this:

{
"SuccessURL": "https://www.example.com/success",
"FailureURL": "https://www.example.com/error",
"OneTime":{
"Id":"a083X00001gpxeGQAQ"
},
"PaymentMethod": {
"Name": "CreditCard",
"Processor": "PaymentHub-Stripe"
},
"Settings": {
"SourceConnector": "PaymentHub"
}
}

Response

If additional actions are required from the customer, a redirectURL is returned in the response body. Once the transaction has been completed or cancelled, the PSP notifies FinDock through the callback, and FinDock updates the data in Salesforce accordingly.

   {
"Settings": {
"SourceConnector": "PaymentHub",
"ProcessingType": "Default"
},
"RedirectURL": "https://redirect.test.findock.com/3xnllmuai2/PaymentHub-Stripe/checkout?publicKey=pk_test_eGC6TxzQ60CdjpAkt2RG3CwZ008WiiOn12&sessionId=cs_test_l5JXe6THfn7e99Ip3OoGDf1SsT19fZrrsBvAhrmARWx6jU0QYi2EKS1Z",
"PaymentMethod": {
"Processor": "PaymentHub-Stripe",
"Name": "CreditCard"
},
"Id": "pi_2qha50n78o0qezuln"
}

New recurring payment

Payments are initiated by performing a POST to the FinDock /Payment endpoint. The request must have a body and an authorization header.

Request

The request body is the same as for a new, one-time payment except that it uses a Recurring object that replaces the Payment object. Some PSPs require an ‘initial’ transaction for authentication. In those cases both a Payment and a Recurring object is passed. Whether such an authorization is required can be queried from the GET /PaymentMethod and GET /PaymentProcessors endpoints. For further information, see the relevant PSP articles under Payment Extensions.

The Recurring object defines the amount and frequency of the recurring transaction, as well as the start date (when the first transaction can be billed).

    "Recurring": {
"Amount": "25",
"Frequency": "Monthly",
"StartDate": "2023-04-01"
}

Some PSPs may require an initial payment when setting up a new recurring payment. Some make it optional, while others disallow initial payment completely. This is part of the GET /PaymentMethod response which includes the InitialPaymentonRecurring parameter value. The options are:

  • Required: The recurring payment setup must include a one-time payment block.
  • Optional: The recurring payment setup may include a one-time payment block.
  • No: The recurring payment setup must not include a one-time payment block.

For example, if the initial payment is required, the above Recurring object would need a OneTime block like below.

    "Recurring": {
"Amount": "25",
"Frequency": "Monthly",
"StartDate": "2023-04-01"
}
"OneTime": {
"Amount": 25
},
info

The parameter RecurringRequiresInitialPayment [true | false] may be included in the GET /PaymentMethod response, but this parameter is deprecated and should not be used.

Response

In the response, you get a similar response to a OneTime request, with - in this case - a RedirectURL to perform an authorization.

   {
"Settings": {
"SourceConnector": "PaymentHub",
"ProcessingType": "Default"
},
"RedirectURL": "https://redirect.test.findock.com/3xnllmuai2/PaymentHub-Stripe/checkout?publicKey=pk_test_eGC6TxzQ60CdjpAkt2RG3CwZ008WiiOn12&sessionId=cs_test_FOnCWoRsNOVea8NBYMhOObAYvr7784jvKirv8mRkfxo0OxontIMduM6X",
"PaymentMethod": {
"Processor": "PaymentHub-Stripe",
"Name": "CreditCard"
},
"Id": "pi_1v0c50n728ke1inuu"
}

Recurring Credit Card Payment

Related to the Recurring Payment, you can find:

  • the first Installment that was created through the API request.
  • the Mandate with data (in this case a Stripe Credit Card token) to collect further installments through the Payment Schedule.
  • the Payment Profile with any Credit Card details that Stripe has returned.
tip

Override the Default Bank Statement Description field with Salesforce automation or by passing a value to the Description parameter in the Parameters block in the PaymentMethod object in your API call, to show the Payer a friendly description on their bank statement.

Next

Visit our API Reference to find more examples of Payment scenarios that can be executed through our API.

Check out the Integration checklist for additional tips on how to get the maximum value from our API.