1. Payment Complete Webhook Overview
The Payment Complete Webhook provides a method to get payment data into Payments2Us/Salesforce. The payment details will be created in the Payment Txn Object and processed by our Batch Processor to perform the creation of Accounts/Contacts/Opportunity/Campaign members as per standard Payments2Us processing.
Setting up and using Webhooks will require advanced admin skills or developer skills. For this reason, this guide is all that is available under standard support. Should you require more information and/or assistance, one of our premium support packages is required.
2. License Key
2.1. Obtaining a License Option Key
You can see the pricing for Webhook API at: Payment2us pricing plans
To order a license key, please contact support @ payments2us.com
After your order has been processed, you will receive an email with the license key details. You need to update your Salesforce instance to have this key entered against all merchant facilities.
Details on where/how to enter the License Option Key are in the email that you'll receive.
3. Authentication
This service is a REST service and can be accessed using the oAuth flow or as a public URL using Force.com Sites.
Both options need to have the header Payments2Us-Key set.
oAuth
- We recommend the oAuth Option.
- This involves creating a connected App and using the oAuth flow.
- The User that Authenticates the App must have the Permission Set "Payment2Us API" assigned
Force.com Sites
- This option is useful when using Webhooks through Zapier or similar integration products that do not have an oAuth option for webhooks.
- The Force.com Sites User must have the Permission Set "Payment2Us API" assigned.
4. Webhook endpoint URL
The endpoint is:
https://{your salesforce instance}/services/apexrest/AAkPay/v1/wh/PaymentComplete/{payment form record id}
Where {payment form record id} is the salesforce record Id of the Payment Form record (1).
Where "your salseforce instance" can be either a my salesforce domain reference or a force.com site (Not recommended option (2) ).
5. Header Parameters
The following Header parameters are required
- Content-Type : application/vnd.api+json
- Payments2Us-Key : {Webhook Secret Key}
You can locate the Webhook Secret Key from the Payment Form "Webhook Secret Key".
If this field is blank, assign your own values. The values entered should be random text and should be at least 10 characters long - The values entered here are defined by you and should be just known to your org. Please note that these values will not be visible on save as the field is encrypted.
Should there already be a value in this field - for example you are using this form with Shopify or similar App, then it is ok to use those values as your secret key, but it would be a better option to use a different Payment Payment Form by Cloning the current one and entering your own parameters.
6. Sample Request Body
Http Method: POST
{
"Reference" : {
"UniqueOrderNo" : "1002",
"Status" : "Receipting Complete",
"PaymentOptionId" :"a022G00000MmTB6",
"OpportunityId" : "0062G00000hYvSu",
"CampaignId" : "701A0000000ZY7y",
"PayerIPAddress" : "201.201.0.0"
},
"Contact": {
"ContactId" : "0032G00002Kpoko",
"Title" : "CEO",
"Salutation" : "Mr",
"FirstName" : "John",
"LastName" : "Smith",
"MailingStreet" : "100 Collins St",
"MailingCity" : "Melbourne",
"MailingState" : "VIC",
"MailingPostalCode" : "3000",
"MailingCountry" : "Australia",
"OtherStreet" : "100 Collins St",
"OtherCity" : "Melbourne",
"OtherState" : "VIC",
"OtherPostalCode" : "3000",
"OtherCountry" : "Australia",
"Phone" : "03 8080 9000",
"MobilePhone" : "0419 99 9999",
"Email" : "john.smith@mailinator.com",
"MembershipId" : "100"
},
"Account" : {
"AccountId" : "001A000000q9rJt",
"PaymentBy" : "Company",
"PaymentByName" : "Smith Enterprises"
},
"TransactionDetail" : {
"Amount": 100.00,
"DonationAmount": 40.00,
"FreightAmount": 0.00,
"DiscountBasis": "Amount",
"DiscountValue": 10.00,
"TaxAmount": 9.09,
"CurrencyCode" : "AUD",
"TaxCalculation" : "Amounts Include Tax",
"PayFrequency" : "Monthly",
"PaymentDay" : "1",
"PaymentFor" : "Widget and Donation",
"PaymentMethod": "Credit Card",
"TransactionDate" : "2021-05-23",
"BankDepositDate" : "2021-05-24"
},
"PaymentGatewayResponse": {
"PaymentStatus": "1",
"TxnRef" : "ch_1I4gUIGksEkehvPvt0hPl4hk",
"PaymentResponseCode" : "",
"PaymentResponseText" : "approved_by_network",
"PaymentResponseDesc" : "Payment complete",
"BillingToken" : "0000120002798754",
"CustomerProfileId" : "cus_IfugQUWoWiKqy0",
"CardType":"Visa",
"MaskedCardNumber": "4557....1110",
"CardExpiry" : {
"CardExpiryMonth" : 12,
"CardExpiryYear" : 2025
}
},
"CustomFields" : {
"CustomRefFieldName" : "Application__c",
"CustomRefFieldId" : "a0k2G00000PcvQN",
"CustomField1Name" : "Colour__c",
"CustomField1Value" : "Red",
"CustomField2Name" : "",
"CustomField2Value" : "",
"CustomField3Name" : "",
"CustomField3Value" : "",
"CustomField4Name" : "",
"CustomField4Value" : "",
"CustomFieldsNVP" : [{
"CustomFieldName" : "Colour__c",
"CustomFieldValue" : "Red"
}
]
},
"ShoppingCartDetails" : {
"cartlines" : [{
"itemcode" : "SKU2006-001",
"itemdesc":"my item notes for SKU",
"quantity" : 10.00,
"unitprice" :100.00,
"tax" : 10.00
}]
}
}
7. Sample Response
8. Element Descriptions
Element | Description | Salesforce Field |
Reference | AAkPay__Payment_Txn__c (Object) | |
|
Used to locate existing Payment Txn where the record type is "Payment" and the AAkPay__Reference__c field matches this value. If a Payment is located and has a status of Confirmation, Payment Complete or Receipting Complete then it will update updated, otherwise an error will be returned for any other status |
AAkPay__Reference__c |
|
Must be one of: Confirmation, Payment Complete or Receipting Complete. If left blank then Payment Complete is used | AAkPay__Status__c |
|
Salesforce Record Id for the Payment Option used | AAkPay__payment_Option__c |
|
Salesforce Record Id for the Opportunity. If left blank, then if enabled, the normal Payments to us processing will be used to create an opportunity. | AAkPay__Opportunity__c |
|
Salesforce Record Id for the Opportunity. | AAkPay__Campaign__c |
|
The IP address of the payer/donor that made the donation | AAkPay__IP_Address__c |
Contact | AAkPay__Payment_Txn__c (Object) | |
|
Salesforce Record Id for the Contact. If not specified, the Payments2Us Matching routines will be used to located or create a Contact | AAkPay__Contact__c |
|
Contacts Job Title | AAkPay__Title__c |
|
Contacts Salutation e.g. Mr, Mrs, Dr etc. | AAkPay__Salutation__c |
|
Contacts First Name | AAkPay__FirstName__c |
|
Contacts Last Name | AAkPay__LastName__c |
|
Contacts Mailing Street | AAkPay__MailingStreet__c |
|
Contacts Mailing City | AAkPay__MailingCity__c |
|
Contacts Mailing State. If not specified, the default State from the Merchant Facility is used. | AAkPay__MailingState__c |
|
Contacts Mailing Postal Code | AAkPay__MailingPostalCode__c |
|
Contacts Mailing Country. If not supplied, the default country on the Merchant Facility is used. | AAkPay__MailingCountry__c |
|
Contacts Other Street | AAkPay__OtherStreet__c |
|
Contacts Other City | AAkPay__OtherCity__c |
|
Contacts Other State | AAkPay__OtherState__c |
|
Contacts Other Postal Code | AAkPay__OtherPostalCode__c |
|
Contacts Other Country | AAkPay__OtherCountry__c |
|
Contacts Phone | AAkPay__Phone__c |
|
Contacts Mobile Phone | AAkPay__MobilePhone__c |
Contacts Email | AAkPay__Email__c |
|
|
Membership No. If not specified, one is populated automatically from the Membership Next No. auto number field on the Payment Txn. | AAkPay__Membership_Id__c |
Account | AAkPay__Payment_Txn__c (Object) | |
|
Salesforce Record Id for the Account. If not specified, the Payments2Us Matching routines will be used to located or create a Account. | AAkPay__Account__c |
|
"Individual", "Company" etc. Determines if this transaction is at the contact (Individual) level or at the organisation (Company) level. This should match one of the options selected on the Payment Form (Payments2Us Tab) being used | AAkPay__Donation_By__c |
|
If "PaymentBy" is NOT individual then a value should be specified here as the transaction is for a Company/Organisation type transaction. | AAkPay__Donation_By_Name__c |
TransactionDetail |
AAkPay__Payment_Txn__c (Object) | |
Amount |
Amount of the payment exclusive of taxes, freight, service fee, surcharges. | AAkPay__Amount__c |
DonationAmount |
Amount of the donation. This field will not incur taxes. | AAkPay__Donation_Amount__c |
FreightAmount |
Freight Amount | AAkPay__Freight__c |
DiscountBasis |
Basis for a discount given. Values are "Amount" or "Percent". This value is used in conjunction with "DiscountValue" field. | AAkPay__Discount_Basis__c |
DiscountValue |
If the DiscountBasis is "Amount", then the value is assigned to the AAkPay__Discount_Amt__c field. If the DiscountBasis is "Percent" then the value is assigned to the AAkPay__Discount__c field. | AAkPay__Discount_Amt__c or AAkPay__Discount__c |
TaxAmount |
This value is only applicable when the Tax Calculation is "Tax Amount Specified Inclusive" or "Tax Amount Specified Exclusive". If the Tax Calculation is not one of these, then the tax amount is automatically calculated. | AAkPay__Tax_Amount__c |
CurrencyCode |
3 Digit ISO Currency Code. If not specified, the Default Currency on the Merchant Facility is assigned. |
AAkPay__Currency__c
When multi currency is enabled, CurrencyIsoCode is updated. |
TaxCalculation |
Determines how Tax is calculated. If blank, then the "Tax Calculation" on the Merchant Facility is used. Valid "No Tax", "Amounts Include Tax", "Amounts Exclude Tax", "Tax Amount Specified Inclusive", "Tax Amount Specified Exclusive" |
AAkPay__Tax_Calculation__c |
PayFrequency |
If left blank, "One-off" will be assigned. If the value set here is NOT "One-off" AND a valid is in "BillingToken" then a Recurring Payment record will be created during the Matching process. Valid values include: "One-off","One-off - Authorise","Daily","Weekly","Fortnightly","4 Weeks","Monthly","Bi-Monthly","Quarterly","Six Monthly","Annually","Two Yearly". |
AAkPay__Regular_Pymt_Freq__c |
PaymentMethod |
Method of Payment. Valid Values include "Credit Card", "Manual", "Direct Debit" | AAkPay__Method_of_Payment__c and AAkPay__Payment_Source__c |
TransactionDate |
Date of the transaction in YYYY-MM-DD format | AAkPay__Transaction_Date__c |
BankDepositDate |
Date the payment is expected to be settled in the bank account in YYYY-MM-DD format | AAkPay__Bank_Deposit_Date__c |
PaymentGatewayResponse |
AAkPay__Payment_Txn__c (Object) | |
PaymentStatus |
This should be "1" if the payment was successful. If left blank, this will be set to "1" | AAkPay__Payment_Status__c |
TxnRef |
The Payment Gateway Response transaction reference. NOTE, this is required for refunds through Payments2Us. For Windcave, "dpsTxnRef". For Stripe, Charges or Payment Intention - "Id". For EziDebit, "PaymentID" from "Payment Detail" For NAB Transact, "txnID" from "PeriodicItem". For DataTrans, "transactionId". For Authorize.net, "transId". |
AAkPay__dpsTxnRef__c |
PaymentResponseCode |
Payment Gateway Response code. | AAkPay__Payment_Response_Code__c |
PaymentResponseText |
Payment Gateway Response text. | AAkPay__Payment_Response_Text__c |
PaymentResponseDesc |
Payment Gateway Response description. | AAkPay__Payment_Response_Desc__c |
BillingToken |
The Payment Gateway Reference to the Token or Card Details on file. This is required for Regular Payments/Donations. It must be supplied if PayFrequency is NOT One-off. | AAkPay__DpsBillingId__c |
CustomerProfileId |
The Payment Gateway Reference to the Customer on file. This is required for some payment gateways for Regular Payments/Donations. If the Payment Gateway requires this, then it must be supplied if PayFrequency is NOT One-off. . For Stripe, Customer - "Id". For EziDebit, "CustomerRef" from "New Customer" For NAB Transact, Please assign unique reference of GUID. For DataTrans, "transactionId". For Authorize.net, "customerProfileId". |
AAkPay__Payment_Gateway_Customer_ProfileId__c |
CardType |
Type of card - e.g Visa, Mastercard etc. | AAkPay__Payment_CC__c |
MaskedCardNumber |
Masked version of the Credit Card. DO NOT send full card details through. | AAkPay__Payment_CC_No__c |
CardExpiry |
||
CardExpiryMonth |
2 Digit expiry month of the card. Used for expiry reminders in regular giving. For example "02" for February. | AAkPay__Payment_CC_Exp_Date_Month__c |
CardExpiryYear |
4 Digit expiry month of the card. Used for expiry reminders in regular giving. For example 2021. | AAkPay__Payment_CC_Exp_Date_Year__c |
CustomFields |
AAkPay__Payment_Txn__c (Object) | |
CustomRefFieldName |
API field name for a lookup reference field on the Payment Txn Object. Note, this cannot be a Payments2Us standard field/managed package field. | |
CustomRefFieldId |
Used in conjunction with "CustomRefFieldName". This is a 15 or 18 digit record Id for the lookup field/object. | |
CustomField1Name |
API field name of a field on the Payment Txn Object. Note, this cannot be a Payments2Us standard field/managed package field. | |
CustomField1Value |
Used in conjunction with "CustomField1Name". This is a value to populate in the field. | |
CustomField2Name |
API field name of a field on the Payment Txn Object. Note, this cannot be a Payments2Us standard field/managed package field. | |
CustomField2Value |
Used in conjunction with "CustomField2Name". This is a value to populate in the field. | |
CustomField3Name |
API field name of a field on the Payment Txn Object. Note, this cannot be a Payments2Us standard field/managed package field. | |
CustomField3Value |
Used in conjunction with "CustomField3Name". This is a value to populate in the field. | |
CustomField4Name |
API field name of a field on the Payment Txn Object. Note, this cannot be a Payments2Us standard field/managed package field. | |
CustomField4Value |
Used in conjunction with "CustomField4Name". This is a value to populate in the field. | |
CustomFieldsNVP |
This array is an alternative method to the Custom Fields [1..4] Name/Value that can be entered above. This element note allows for upto 10 name/value pairs. |
|
CustomFieldName |
API field name of a field on the Payment Txn Object. Note, this cannot be a Payments2Us standard field/managed package field. | |
CustomFieldValue |
Used in conjunction with "CustomFieldName". This is a value to populate in the field. | |
ShoppingCartDetails | These details are similar to Shopping Cart Details URL Parameter. | AAkPay__Payment_Item__c (Object) |
|
Array of shopping cart line items | |
|
Product Item Code | AAkPay__Product_Id__c and AAkPay__SKU__c |
|
Product Description | AAkPay__Item_Description__c |
|
Quantity in cart | AAkPay__Quantity__c |
|
Unit price of product | AAkPay__Price__c |
|
Discount amount given | AAkPay__Discount__c |
|
Tax amount charged | AAkPay__Tax_Amount__c |
9. Example with Zapier
The below is an example using Zapier Webhook POST.
- Webhook endpoint URL
- Select "Json" Payload Type
- Payload Elements. All fields in the Reference Element start with "Reference__". Please Note the double underscore
- Header Parameters
10. Visualforce and/or Apex Code Option
If you are using a Visualforce page or similar on a Force.com Sites page, then you will need to use the Apex code method as described below.
As with all options with the webhook, this guide is provided as is and to provide the assistance and experienced developer should be able to use. If you need further help, you'll need to subscribe to a Premium Support block.
10.1. Create an Apex controller Class
Create a new Apex Controller class. Below is an example.
// (c) AAkonsult Pty Ltd, 2021
// Very basic Sample only. This is not production ready
public with sharing class payments2UsWebhookPCSAMPLECon {
public string orderNumber {get;set;}
public string firstName {get;set;}
public string lastName {get;set;}
public pageReference Cancel() {
// do something here
return null;
}
public pageReference Confirm() {
AAkPay.payments2UsWebhookPaymentCompleteJSON p2usCompleteWH = new AAkPay.payments2UsWebhookPaymentCompleteJSON();
AAkPay.payments2UsWebhookPaymentCompleteJSON.cls_Reference p2usReference = new AAkPay.payments2UsWebhookPaymentCompleteJSON.cls_Reference();
p2usReference.UniqueOrderNo = orderNumber;
p2usCompleteWH.Reference = p2usReference;
AAkPay.payments2UsWebhookPaymentCompleteJSON.cls_Contact p2usContact = new AAkPay.payments2UsWebhookPaymentCompleteJSON.cls_Contact();
p2usContact.firstName = firstName;
p2usContact.lastName = lastName;
p2usCompleteWH.Contact = p2usContact;
string JSONStr = JSON.serialize(p2usCompleteWH);
id paymentFormId = [Select Id from AAkPay__Payment_Type__c where AAkPay__Payment_Setting__r.AAkPay__Active__c = true and AAkPay__Payment_Setting__r.AAkPay__Organisation_id__c = :UserInfo.getOrganizationId() order by AAkPay__Payment_Setting__r.AAkPay__Active__c DESC, AAkPay__Payment_Setting__r.AAkPay__Primary__c DESC, AAkPay__Primary_Payment_Type__c DESC limit 1].id; // you should updated code so locate correct one. Also manage if does not exist
AAkPay.payments2UsWebhook p2usWebhook = new AAkPay.payments2UsWebhook();
AAkPay.payments2UsWebhookRespJSON Resp = p2usWebhook.PaymentComplete(JSONStr,paymentFormId);
system.debug(Resp); // Do something based on the response.
return null;
}
}
10.2. Create a Visualforce Page
We would suggest cloning the example page included with the package. This is: payments2UsWebhookPCExample. The code is shown below.
Make sure you update the controller name in the visualforce page to the Apex Class controller created above.
<!-- (c) AAkonsult Pty Ltd, 2021 -->
<apex:page showHeader="false" standardStylesheets="false" sidebar="false" docType="html-5.0" controller="AAkPay.payments2UsWebhookPCSAMPLECon" applyBodyTag="False" applyHtmlTag="False">
<head>
<title>SAMPLE PAGE FOR WEBHOOK</title>
<apex:slds />
</head>
<body>
<apex:form id="theFormCheckout" styleClass="slds-scope">
<!-- PAGE HEADER -->
<div class="slds-page-header" role="banner">
<div class="slds-grid">
<div class="slds-col slds-has-flexi-truncate">
<div class="slds-media slds-no-space slds-grow">
<div class="slds-media__figure">
<div class="slds-media__figure">
<svg class="slds-icon slds-page-header__icon slds-icon slds-icon-standard-contact" aria-hidden="true">
<use xmlns:xlink="http://www.w3.org/1999/xlink" xlink:href="{!URLFOR($Asset.SLDS, 'assets/icons/standard-sprite/svg/symbols.svg#contact')}" />
</svg>
</div>
</div>
<div class="slds-media__body">
<p class="slds-text-title_caps slds-line-height_reset">Payments2Us Webhook API Sample</p>
<h1 class="slds-page-header__title slds-m-right_small slds-align-middle slds-truncate" title="Payments2Us Webhook API Sample">Payments2Us Webhook API SAMPLE</h1>
</div>
</div>
</div>
<div class="slds-col slds-no-flex slds-grid slds-align-top">
<div class="slds-button-group" role="group">
<apex:commandLink styleClass="slds-button slds-button--neutral" action="{!Cancel}" value="{!$Label.aakpay__cancel_label}" status="status" id="cancelBtn"/>
<apex:commandLink styleClass="slds-button slds-button--neutral slds-m-right--xx-small slds-button_brand" action="{!confirm}" value="{!$Label.aakpay__label_confirm}" id="ConfirmBtn">
</apex:commandLink>
</div>
</div>
</div>
</div>
<!-- / PAGE HEADER -->
<!-- CARD -->
<div class="slds-section slds-is-open">
<h3 class="slds-section__title slds-theme--shade primaryPaletteBorder test-id__section-header-container" ><span class="section-header-title slds-p-horizontal--small slds-truncate">Payments2Us Webhook API SAMPLE</span>
</h3>
<div class="slds-section__content section__content">
<div class="slds-grid slds-wrap">
<div id="orderNumber" class="slds-col slds-p-horizontal_medium slds-size--1-of-1 slds-medium-size--12-of-12 ">
<div class="slds-form-element">
<label class="slds-form-element__label" for="inputorderNumber">
<span id="orderNumberLabelRequired"><abbr class="slds-required" title="required">*</abbr>
</span>
Order Number
</label>
<div class="slds-form-element__control">
<apex:inputText value="{!orderNumber}" styleClass="slds-input slds-input orderNumber" id="orderNumber"/>
</div>
</div>
</div>
<div id="firstname" class="slds-col slds-p-horizontal_medium slds-size--1-of-1 slds-medium-size--12-of-12 ">
<div class="slds-form-element">
<label class="slds-form-element__label" for="inputFirstName">
<span id="firstNameLabelRequired"><abbr class="slds-required" title="required">*</abbr>
</span>
First Name
</label>
<div class="slds-form-element__control">
<apex:inputText value="{!firstName}" styleClass="slds-input slds-input firstName" id="firstname"/>
</div>
</div>
</div>
<div id="lastname" class="slds-col slds-p-horizontal_medium slds-size--1-of-1 slds-medium-size--12-of-12 ">
<div class="slds-form-element">
<label class="slds-form-element__label" for="inputLastName">
<span id="lastNameLabelRequired"><abbr class="slds-required" title="required">*</abbr>
</span>
Last Name
</label>
<div class="slds-form-element__control">
<apex:inputText value="{!lastName}" styleClass="slds-input slds-input lastName" id="lastName"/>
</div>
</div>
</div>
</div>
</div>
</div>
<!-- / CARD -->
<div class="slds-backdrop slds-backdrop--close"></div>
<!-- SPINNER -->
<div class="slds-spinner_container spinner slds-hide" style="position:fixed">
<div role="status" class="slds-spinner slds-spinner--large">
<span class="slds-assistive-text">Loading</span>
<div class="slds-spinner__dot-a"></div>
<div class="slds-spinner__dot-b"></div>
</div>
</div>
<!-- / SPINNER -->
</apex:form>
</body>
</apex:page>
10.3. Update Force.com Sites security
Add the Visualforce Page and Apex apex class to the Force.com Sites Profile.
In setup, search "Sites". Click into Sites. Click into the site you wish to use. Then click Public Access settings and update "Enabled Apex Class Access" and "Enabled Visualforce Pages Access"
10.4. Example Sample page
The below shows an example of the page working.
This is NOT a commercial grade form - it is purely an example page to provide assistance for developers.
When confirming the data, a Payment Txn record is created in Salesforce.