In order to create a payment over the platform you have the choice between the payment page integration
where the customer is redirected to our payment page, the iframe integration
where the payment form
is placed in an iframe using our JavaScript integration or the lightbox integration
in order to achieve a seamless and PCI DSS
compliant integration in your checkout.
The lightbox integration allows to display the form to collect the payment information as an overlay box in the checkout, after the order has been confirmed. This allows the following process (simplified) in the merchant application:
Optional: The customer selects the payment method.
The customer submits the order which is created.
The lightbox is displayed where the customer can chose the payment method (if not done is step 1) and enter his payment information.
The benefit of using this integration compared to the payment page is that the integration is seamless and the customer never notices that the merchant website is left. Also, the lightbox integration is less complicated than the iframe one.
Before you start with the integration of the lightbox you should:
Create an account and sign up.
Create an application user under Account > Users > Application User.
Learn how to authenticate and connect to our web service.
Note
|
Please have a look at our github repository where we offer
ready to download SDKs in different languages that facilitate your integration efforts drastically.
|
We offer you also an API Client that allows you to test the requests sent to the API and see the responses.
Below we are going to describe the integration process in details. In order to better understand this have a look at the system integrations diagramm above.
Create a transaction object
with the Transaction Service
. To create a transaction object
you can provide all the information you have in this state. The more information you provide the
better we can prevalidate the data and might be able to rule out some payment methods which will
not work for this data. Most of the provided data can be updated before the transaction is actually
confirmed.
Once the transaction object is created, the possible payment methods can be fetched by using
fetch possible payment methods
on the Transaction Service
by providing the transactionId
returned by the initial request
and the integration mode lightbox
. The method returns all payment methods
which are suitable to the current transaction. The method can either be used to check if a particular payment method
is active or to render all available payment methods. This depends on the use case.
To collect the payment information in the lightbox, you need to include a JavaScript file on the web page from which the lightbox
should be opened. This URL to this JavaScript file can be fetched
via buildJavaScriptUrl.
Include the script using the <script>
tag.
Call the JavaScript function LightboxCheckoutHandler.startPayment(paymentMethod, errorCallback)
to display
the lightbox. This function takes two optional arguments:
Pass the ID of the payment method configuration to the function to preselect this method. If this argument is omitted, the customer can select the payment method in the lightbox.
A JavaScript function can be passed as second argument, that is getting called in case of an error while opening the lightbox.
After the customer has entered his payment information and the payment is processed (or failed), the customer will be redirected to the successUrl
(or failedUrl
) defined on the transaction object.
Listen to the notification on the defined webhook URL to mark the order in the merchant system as authorized
or failed
.
This notification listener is important because the customer may close the window before returning back to merchant
application. The state of the transaction can be fetched at any time through the API.
The described steps above should now be explained a bit more in details including the API operations with example requests.
The payment acceptance via lightbox provides a seamless way to collect payment information from your customers. This method is not only seamlessly integrated, it also fulfills all PCI DSS requirements for merchants to keep you out of scope as good as possible and still achieves an integrated checkout flow.
Below you will find an example of the client-side setup.
<button id="pay-button">Pay</button>
<script src="jquery.js" type="text/javascript"></script>
<script src="{ JavaScript URL }" type="text/javascript"></script>
<script type="text/javascript">
// Set here the id of the payment method configuration the customer chose.
var paymentMethodConfigurationId = 1;
$('#pay-button').on('click', function(){
window.LightboxCheckoutHandler.startPayment(paymentMethodConfigurationId, function(){
alert('An error occurred during the initialization of the payment lightbox.');
});
});
</script>
In order to create a transaction object you have to use the
Transaction Create Operation.
Here you provide the customer details that you have including the line items and prices.
This will create a pending
transaction in your space.
Note
|
Provide as many information as you were able to collect from your client at this stage. The more information we have the more accurate the selection of possible payment methods will be. |
Request
{
"billingAddress":{
"city":"Winterthur",
"commercialRegisterNumber":"",
"country":"CH",
"dateOfBirth":"",
"emailAddress":"[email protected]",
"familyName":"Test",
"gender":"",
"givenName":"Sam",
"mobilePhoneNumber":"",
"organizationName":"Wallee AG",
"phoneNumber":"",
"postCode":"8400",
"salesTaxNumber":"",
"salutation":"",
"socialSecurityNumber":"",
"state":"",
"street":"General-Guisan-Strasse 47"
},
"currency":"EUR",
"language":"de-CH",
"lineItems":[
{
"amountIncludingTax":"11.87",
"name":"Barbell Pull Up Bar",
"quantity":"1",
"shippingRequired":"true",
"sku":"barbell-pullup",
"type":"PRODUCT",
"uniqueId":"barbell-pullup"
},
{
"amountIncludingTax":"559",
"name":"Rowing Machine",
"quantity":"1",
"shippingRequired":"true",
"sku":"rowing-machine",
"type":"PRODUCT",
"uniqueId":"rowing-machine"
},
{
"amountIncludingTax":"17.98",
"name":"Super Whey Protein",
"quantity":"4",
"shippingRequired":"true",
"sku":"super-whey",
"taxes":[
{
"rate":"10",
"title":"VAT"
},
{
"rate":"3.5",
"title":"Supplement Fee"
}
],
"type":"PRODUCT",
"uniqueId":"super-whey"
},
{
"amountIncludingTax":"12.5",
"name":"Special Chär Test",
"quantity":"1",
"shippingRequired":"false",
"sku":"special-chär-test",
"type":"SHIPPING",
"uniqueId":"special-chär-test"
},
{
"amountIncludingTax":"12.5",
"name":"Standard Shipping",
"quantity":"1",
"shippingRequired":"false",
"sku":"standard-shipping",
"type":"SHIPPING",
"uniqueId":"standard-shipping"
},
{
"amountIncludingTax":"-10",
"name":"Spring Discount",
"quantity":"1",
"shippingRequired":"false",
"sku":"spring-discount",
"type":"DISCOUNT",
"uniqueId":"spring-discount"
}
],
"merchantReference":"DEV-2630",
"shippingAddress":{
"city":"Winterthur",
"commercialRegisterNumber":"",
"country":"CH",
"dateOfBirth":"",
"emailAddress":"[email protected]",
"familyName":"Test",
"gender":"",
"givenName":"Sam",
"mobilePhoneNumber":"",
"organizationName":"Wallee AG",
"phoneNumber":"",
"postCode":"8400",
"salesTaxNumber":"",
"salutation":"",
"socialSecurityNumber":"",
"state":"",
"street":"General-Guisan-Strasse 47"
}
}
Response
The response that you will receive contains the id
(in the example below 109472
) that will now be
used to perform further operations with this transactions.
{
"acceptHeader": null,
"allowedPaymentMethodBrands": [],
"allowedPaymentMethodConfigurations": [],
"authorizationAmount": 603.85,
"authorizationTimeoutOn": "2017-12-07T08:44:09.119Z",
"authorizedOn": null,
"autoConfirmationEnabled": true,
"billingAddress": {
"city": "Winterthur",
"commercialRegisterNumber": "",
"country": "CH",
"dateOfBirth": null,
"dependentLocality": null,
"emailAddress": "[email protected]",
"familyName": "Test",
"gender": null,
"givenName": "Sam",
"legalOrganizationForm": null,
"mobilePhoneNumber": "",
"organizationName": null,
"phoneNumber": "",
"postCode": "8400",
"postalState": null,
"salesTaxNumber": "",
"salutation": "",
"socialSecurityNumber": "",
"sortingCode": null,
"street": "General-Guisan-Strasse 47"
},
"chargeRetryEnabled": true,
"completedOn": null,
"completionTimeoutOn": null,
"confirmedBy": 0,
"confirmedOn": null,
"createdBy": 0,
"createdOn": "2017-12-07T08:14:09.119Z",
"currency": "EUR",
"customerEmailAddress": null,
"customerId": null,
"customersPresence": "VIRTUAL_PRESENT",
"endOfLife": "2017-12-21T08:14:09.119Z",
"failedOn": null,
"failedUrl": null,
"failureReason": null,
"group": {
"beginDate": "2017-12-07T08:14:09.124Z",
"customerId": null,
"endDate": "2017-12-07T08:14:09.124Z",
"id": 109478,
"linkedSpaceId": 396,
"plannedPurgeDate": "2017-12-07T08:19:09.124Z",
"state": "PENDING",
"version": 1
},
"id": 109472,
"internetProtocolAddress": null,
"internetProtocolAddressCountry": null,
"invoiceMerchantReference": null,
"language": "de-CH",
"lineItems": [
{
"aggregatedTaxRate": 0,
"amountExcludingTax": 11.87,
"amountIncludingTax": 11.87,
"attributes": {},
"name": "Barbell Pull Up Bar",
"quantity": 1,
"shippingRequired": true,
"sku": "barbell-pullup",
"taxAmount": 0,
"taxAmountPerUnit": 0,
"taxes": [],
"type": "PRODUCT",
"uniqueId": "barbell-pullup",
"unitPriceExcludingTax": 11.87,
"unitPriceIncludingTax": 11.87
},
{
"aggregatedTaxRate": 0,
"amountExcludingTax": 559,
"amountIncludingTax": 559,
"attributes": {},
"name": "Rowing Machine",
"quantity": 1,
"shippingRequired": true,
"sku": "rowing-machine",
"taxAmount": 0,
"taxAmountPerUnit": 0,
"taxes": [],
"type": "PRODUCT",
"uniqueId": "rowing-machine",
"unitPriceExcludingTax": 559,
"unitPriceIncludingTax": 559
},
{
"aggregatedTaxRate": 13.5,
"amountExcludingTax": 15.84,
"amountIncludingTax": 17.98,
"attributes": {},
"name": "Super Whey Protein",
"quantity": 4,
"shippingRequired": true,
"sku": "super-whey",
"taxAmount": 2.14,
"taxAmountPerUnit": 0.54,
"taxes": [
{
"rate": 10,
"title": "VAT"
},
{
"rate": 3.5,
"title": "Supplement Fee"
}
],
"type": "PRODUCT",
"uniqueId": "super-whey",
"unitPriceExcludingTax": 3.96,
"unitPriceIncludingTax": 4.5
},
{
"aggregatedTaxRate": 0,
"amountExcludingTax": 12.5,
"amountIncludingTax": 12.5,
"attributes": {},
"name": "Special Chär Test",
"quantity": 1,
"shippingRequired": false,
"sku": "special-chär-test",
"taxAmount": 0,
"taxAmountPerUnit": 0,
"taxes": [],
"type": "SHIPPING",
"uniqueId": "special-chär-test",
"unitPriceExcludingTax": 12.5,
"unitPriceIncludingTax": 12.5
},
{
"aggregatedTaxRate": 0,
"amountExcludingTax": 12.5,
"amountIncludingTax": 12.5,
"attributes": {},
"name": "Standard Shipping",
"quantity": 1,
"shippingRequired": false,
"sku": "standard-shipping",
"taxAmount": 0,
"taxAmountPerUnit": 0,
"taxes": [],
"type": "SHIPPING",
"uniqueId": "standard-shipping",
"unitPriceExcludingTax": 12.5,
"unitPriceIncludingTax": 12.5
},
{
"aggregatedTaxRate": 0,
"amountExcludingTax": -10,
"amountIncludingTax": -10,
"attributes": {},
"name": "Spring Discount",
"quantity": 1,
"shippingRequired": false,
"sku": "spring-discount",
"taxAmount": 0,
"taxAmountPerUnit": 0,
"taxes": [],
"type": "DISCOUNT",
"uniqueId": "spring-discount",
"unitPriceExcludingTax": -10,
"unitPriceIncludingTax": -10
}
],
"linkedSpaceId": 396,
"merchantReference": null,
"metaData": {},
"paymentConnectorConfiguration": null,
"plannedPurgeDate": "2017-12-21T08:14:09.119Z",
"processingOn": null,
"refundedAmount": 0,
"shippingAddress": {
"city": "Winterthur",
"commercialRegisterNumber": "",
"country": "CH",
"dateOfBirth": null,
"dependentLocality": null,
"emailAddress": "[email protected]",
"familyName": "Test",
"gender": null,
"givenName": "Sam",
"legalOrganizationForm": null,
"mobilePhoneNumber": "",
"organizationName": null,
"phoneNumber": "",
"postCode": "8400",
"postalState": null,
"salesTaxNumber": "",
"salutation": "",
"socialSecurityNumber": "",
"sortingCode": null,
"street": "General-Guisan-Strasse 47"
},
"shippingMethod": null,
"spaceViewId": null,
"state": "PENDING",
"successUrl": null,
"timeZone": "Z",
"token": null,
"userAgentHeader": null,
"userFailureMessage": null,
"userInterfaceType": null,
"version": 1
}
In order to get the URL to the JavaScript URL you can use the buildJavaScriptUrl operation to get an URL pointing to the java script that should be included in your checkout to create the lightbox. Insert the JavaScript on your page where the lightbox should be displayed as shown in the client-site example above.
In order to integrate the iframe seamlessly in your checkout you will have to fetch the possible payment methods and render the options in the checkout.
This will return the payment method id
which should then be set in the JavaScript
using the paymentMethodConfigurationId
.
Response
The response returns the possible payment methods for the given transactionId.
[
{
"dataCollectionType": "ONSITE",
"description": {
"availableLanguages": [
"en-US"
],
"displayName": "",
"items": [
{
"language": "en-US",
"languageCode": "en",
"translation": ""
}
]
},
"id": 510,
"imageResourcePath": null,
"linkedSpaceId": 396,
"name": "Credit / Debit Card",
"oneClickPaymentMode": "ALLOW",
"paymentMethod": 1457546097597,
"plannedPurgeDate": null,
"resolvedDescription": {
"de-DE": "Bezahlen Sie bequem per Kredit- oder Debitkarte.",
"en-US": "Pay conveniently with your credit or debit card."
},
"resolvedImageUrl": "https://checkout.postfinance.ch/s/396/resource/icon/payment/method/credit-debit-card.svg",
"resolvedTitle": {
"de-DE": "Kredit- / Debitkarte",
"en-US": "Credit / Debit Card"
},
"sortOrder": 1,
"spaceId": 396,
"state": "ACTIVE",
"title": {
"availableLanguages": [
"en-US"
],
"displayName": "",
"items": [
{
"language": "en-US",
"languageCode": "en",
"translation": ""
}
]
},
"version": 2
}
]
Transaction properties can be updated as long as they are not in the confirmed
state. In
order to do this use the update
operation on the Transaction service.
Note
|
Have a look at the Object Versioning / Locking
Section to describe how you have to handle the version property to prevent optimistic locking.
|
Request
In the example below we are going to update the line items and get rid of the discount line item that we added in the example above.
{
"billingAddress": {
"city": "Winterthur",
"country": "CH",
"emailAddress": "[email protected]",
"familyName": "Test",
"givenName": "Sam",
"postCode": "8400",
"street": "General-Guisan-Strasse 47"
},
"currency": "EUR",
"id": 109472,
"language": "de-CH",
"lineItems": [
{
"amountIncludingTax": "11.87",
"name": "Barbell Pull Up Bar",
"quantity": "1",
"sku": "barbell-pullup",
"type": "PRODUCT",
"uniqueId": "barbell-pullup"
},
{
"amountIncludingTax": "559",
"name": "Rowing Machine",
"quantity": "1",
"sku": "rowing-machine",
"type": "PRODUCT",
"uniqueId": "rowing-machine"
},
{
"amountIncludingTax": "17.98",
"name": "Super Whey Protein",
"quantity": "4",
"sku": "super-whey",
"type": "PRODUCT",
"uniqueId": "super-whey"
},
{
"amountIncludingTax": "12.5",
"name": "Special Chär Test",
"quantity": "1",
"sku": "special-chär-test",
"type": "SHIPPING",
"uniqueId": "special-chär-test"
},
{
"amountIncludingTax": "12.5",
"name": "Standard Shipping",
"quantity": "1",
"sku": "standard-shipping",
"type": "SHIPPING",
"uniqueId": "standard-shipping"
}
],
"shippingAddress": {
"city": "Winterthur",
"country": "CH",
"emailAddress": "[email protected]",
"familyName": "Test",
"givenName": "Sam",
"postCode": "8400",
"street": "General-Guisan-Strasse 47"
},
"version": 3
}
Response
The response contains the updated transaction object.
{
"billingAddress": {
"city": "Winterthur",
"country": "CH",
"emailAddress": "[email protected]",
"familyName": "Test",
"givenName": "Sam",
"postCode": "8400",
"street": "General-Guisan-Strasse 47"
},
"currency": "EUR",
"id": 109472,
"language": "de-CH",
"lineItems": [
{
"amountIncludingTax": "11.87",
"name": "Barbell Pull Up Bar",
"quantity": "1",
"sku": "barbell-pullup",
"type": "PRODUCT",
"uniqueId": "barbell-pullup"
},
{
"amountIncludingTax": "559",
"name": "Rowing Machine",
"quantity": "1",
"sku": "rowing-machine",
"type": "PRODUCT",
"uniqueId": "rowing-machine"
},
{
"amountIncludingTax": "17.98",
"name": "Super Whey Protein",
"quantity": "4",
"sku": "super-whey",
"type": "PRODUCT",
"uniqueId": "super-whey"
},
{
"amountIncludingTax": "12.5",
"name": "Special Chär Test",
"quantity": "1",
"sku": "special-chär-test",
"type": "SHIPPING",
"uniqueId": "special-chär-test"
},
{
"amountIncludingTax": "12.5",
"name": "Standard Shipping",
"quantity": "1",
"sku": "standard-shipping",
"type": "SHIPPING",
"uniqueId": "standard-shipping"
}
],
"shippingAddress": {
"city": "Winterthur",
"country": "CH",
"emailAddress": "[email protected]",
"familyName": "Test",
"givenName": "Sam",
"postCode": "8400",
"street": "General-Guisan-Strasse 47"
},
"version": 3
}
In case the auto confirm property is not set the transaction has to be confirmed. We recommend to do this step anyways
The confirm transaction step should be done once the inputs of the customer have been validated and
the pending order is created in your application (see step 7 in the process above).
You can use the confirm operation to confirm
the transaction and also set the merchant reference
as you do now have an order number in your
application.
Request
{
"billingAddress": {
"city": "Winterthur",
"country": "CH",
"emailAddress": "[email protected]",
"familyName": "Test",
"givenName": "Sam",
"postCode": "8400",
"street": "General-Guisan-Strasse 47"
},
"currency": "EUR",
"id": 109472,
"language": "de-CH",
"lineItems": [
{
"amountIncludingTax": "11.87",
"name": "Barbell Pull Up Bar",
"quantity": "1",
"sku": "barbell-pullup",
"type": "PRODUCT",
"uniqueId": "barbell-pullup"
},
],
"merchantReference": "DEV-2630",
"shippingAddress": {
"city": "Winterthur",
"country": "CH",
"emailAddress": "[email protected]",
"familyName": "Test",
"givenName": "Sam",
"postCode": "8400",
"street": "General-Guisan-Strasse 47"
},
"version": 5
}
In order to be updated about the transaction state you should register webhook notification on your side. The webhooks will update you about state changes of the selected entities and should trigger your application to further process the transaction results.
More Information about webhooks, webhooks listener and their configuration can be found in the Webhooks Documentation.
If content security policy restrictions are applied in the shop, in order for this integration to work the following restrictions must be removed for https://checkout.postfinance.ch:
URLs which can be loaded as valid sources for JavaScript.
Allow inline script executions.
URLs which can be loaded using iframe interfaces.
URLs which can be loaded using script interfaces.
For example the following header would allow that by setting CSP: script-src directive to allow loading https://checkout.postfinance.ch URLs as valid sources for JavaScript, Unsafe inline script policy to allow inline script executions, CSP: frame-src directive to allow loading https://checkout.postfinance.ch URLs using iframe interfaces, CSP: connect-src directive to allow loading https://checkout.postfinance.ch URLs using script interfaces.
content-security-policy: script-src https://checkout.postfinance.ch 'unsafe-inline'; frame-src https://checkout.postfinance.ch; connect-src https://checkout.postfinance.ch;