Documentazione

1Introduction

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:

  1. Optional: The customer selects the payment method.

  2. The customer submits the order which is created.

  3. 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.

Seamless Lightbox Integration
Figure 1. The image shows an example of a seamless lightbox integration.

2Lightbox Integration Details

Before you start with the integration of the lightbox you should:

  1. Create an account and sign up.

  2. Create an application user under Account > Users > Application User.

  3. 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.

3System Interactions

lightbox
Figure 2. Sequence Diagram of the Lightbox Integration

3.1Process

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.

  1. 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.

  2. 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.

  3. 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.

  4. Call the JavaScript function LightboxCheckoutHandler.startPayment(paymentMethod, errorCallback) to display the lightbox. This function takes two optional arguments:

    paymentMethod

    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.

    errorCallback

    A JavaScript function can be passed as second argument, that is getting called in case of an error while opening the lightbox.

  5. 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.

  6. 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.

3.2Technical Details

The described steps above should now be explained a bit more in details including the API operations with example requests.

3.2.1Client-side Setup

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>

3.2.2Create a Transaction Object

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
}

3.2.3Build JavaScript URL

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.

3.2.4Fetch Possible Payment Methods

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
	}
]

3.2.5Update Transactions

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
}

3.2.6Confirm Transaction

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
}

3.2.7Fetch Transaction Update

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.

4Security Policy

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;