In this process, there are 3 parties involved:
Shop backend creates a payment in CT platform and obtains payment ID.
Shop backend sends POST request with the obtained payment ID to following Create API of paypal-integration.
http://paypal-plus-integration-server.com/${tenantName}/commercetools/create/payments/${ctpPaymentId}
For details, please see the section 1.1 of How to use
Shop backend updates user's details by posting the payment object to following Patch API of paypal-integration.
http://paypal-plus-integration-server.com/${tenantName}/commercetools/patch/payments/${ctpPaymentId}
For details, please see the section 1.1 of How to use
Shop front-end trigger Paypal-plus checkout function, customer is redirected to payment authorization page. Once completed, it returns a success URL which redirects the customer back to order confirmation page in the shop front-end.
After order confirmation, shop front-end extracts payer ID and Paypal payment ID, and send them to shop back-end. Back-end sends POST request to following Execute API of paypal-integration.
http://paypal-plus-integration-server.com/${tenantName}/commercetools/execute/payments/
The request of above API should be with payload as follow :
{"paypalPlusPaymentId": "${paymentId}", "paypalPlusPayerId": "${payerId}"}
See commercetools Paypal Plus Service Integration Guide documentation.
./gradlew bootRun
Local Run/Debug setting may be configured in /src/main/resources/config/application.yml
file. If the file exists - it overrides default /src/main/resources/application.yml
.
Local integration test setting may be configured in /src/test/resources/config/application.yml
file. If the file exists - it overrides main context config and config from /src/test/resources/application.yml
.
You must include 2 different CT client credentials and paypal_plus client credentials in order to make the integration tests pass successfully.
Note: keep this settings different from /src/main/resources/config/application.yml
,
which is used for local run/debug, because the integration tests will remove all data form the CTP project
Show available PayPal payment methods
Backend creates CTP payment and assigns it to the cart.
Required fields for the CTP cart:
Required fields for the CTP payment:
amountPlanned
cancelUrl
(custom field)successUrl
(custom field)reference
(custom field, up to 116 characters)languageCode
(custom field)paymentMethodInfo
needs to be set like this:"paymentMethodInfo": {
"paymentInterface": "PAYPAL_PLUS",
"method": "paypal"
}
Optional fields for the CTP payment:
experienceProfileId
(custom field): if the payment should be supplied with certain
Paypal Plus Experience Profile Id.
Note: looks like there is no certain clarity in PayPal Plus documentation/support
how the web experience profiles should be used, and potentially they will be deprecated in the future,
so we recommend not to use them unless you are completely sure what you achieve using them.
If you need prevent address change by customers (buyers) - use shippingPreference
below.
shippingPreference
(custom field): value of Payment#application_context#shipping_preference
enum.
This value is used to allow/block shipping address change by the customer (buyer). Reed more at
Application Context Documentation
Note: So far this feature is not properly documented by Paypal API developers, so the reference above actually refers to Orders API, instead of Payments API. Respective issues are created:
description
(custom field): if specified - Payment#transaction#description
field is set to this value. Otherwise the description falls back to the following string:
Reference: ${payment.custom.fields.reference}
Note: Maximum allowed length according to PayPal Plus API: 127
(including Reference:
prefix in case of fallback, so the reference
custom field
must be up to 116 characters long)
Backend POSTs CTP payment ID created in the previous step to Paypal-integration. Example:
POST http://paypal-plus-integration-server.com/${tenantName}/commercetools/create/payments/${ctpPaymentId}
If request was successful both response body and CTP payment object will have approvalUrl
defined.
Frontend uses returned approvalUrl
to render available payment methods as described in the Paypal Plus integration documentation.
Add user's addresses to Paypal Plus
POST http://paypal-plus-integration-server.com/${tenantName}/commercetools/patch/payments/${ctpPaymentId}
ppp.doContinue()
. Additionally,
ppp
object must be created with the following option:
var ppp = PAYPAL.apps.PPP({
onContinue: function () {
$.post("/url-to-your-shop-that-will-make-call-to-paypal-integration", function (data) {
if (data != false) {
ppp.doCheckout();
}
});
}
});
Execute payment after user successfully finished PayPal Plus checkout and was redirected back to the shop through successUrl
.
PayPal Plus will set 3 request parameters to successUrl
:
token
paymentId
- identifies this particular payment. Required for execute payment.PayerID
- identifies the particular payer. Required for execute payment.Example of successUrl
returned by PayPal Plus:
http://example.com/checkout/payment/success?paymentId=${paymentId}&token=${token}&PayerID=${payerId}
It is strongly recommended to compare the payment from Paypal to payment from CTP to see if there were any changes during the payment process. Example of how this can happen is described here. The possible changes could be:
Backend GET Paypal payment by paypalPaymentId
:
GET http://paypal-plus-integration-server.com/${tenantName}/paypalplus/payments/${paypalPaymentId}
The Paypal Plus payment object will be returned in payment
as JSON like this:
{"payment":"{\"id\":\"PAY-xxx\",\"intent\":\"sale\",\"cart\":\"1234abcd\", .... }"}
Backend extracts PayPal specific parameters: paymentId
, PayerID
and POSTs them in the request body to Paypal-integration for payment execution. Example:
POST http://paypal-plus-integration-server.com/${tenantName}/commercetools/execute/payments/
{"paypalPlusPaymentId": "${paymentId}", "paypalPlusPayerId": "${payerId}"}
In case of invoice payment, the bank details for the invoice will be saved as custom fields in the Payment object. Example:
{
"custom": {
"type": {
"typeId": "type",
"id": "1455d4e6-41b4-yyyy-xxxx-4f120864e231"
},
"fields": {
"reference": "6KF07542JV235932C",
"description": "Thank you for your order. Order number: 12345",
"paymentDueDate": "2017-09-27",
"amount": {
"centAmount": 200,
"currencyCode": "EUR"
},
"paidToIBAN": "DE1212121212123456789",
"paidToAccountBankName": "Deutsche Bank",
"paidToAccountHolderName": "PayPal Europe",
"paidToBIC": "DEUTDEDBPAL"
}
}
}
All endpoints accept and return data as JSON.
Return HTTP codes on create/payments
endpoint URL:
Return HTTP codes on execute/payments
endpoint URL:
Return HTTP codes on paypalplus/payments/${paypalPaymentId}
endpoint URL:
Common error codes
Additionally, response can contain additional response body. All fields of the response body are optional. Example:
{
"approvalUrl": "https://test.de", # applicable only in case of create payment
"errorCode": "", # only in case of error and represents a unique error code
"errorMessage": "Parameter 'x' is missing" # only in case of error
"payment": {"id":"XXX", "intent":"sale", ...} # only in case of getting the payment object
}
First case:
Possible solution: the backend calls patch/payments
endpoint every time user changes it.
Second case:
Possible solution: the backend has to compare total amount of the payment and total amount of payment's cart before calling execute/payments
endpoint.
In case of differences, the whole payment process must be restarted.
Request Professional Services team to add you as an encryptor/decryptor to
ps-keyring#commercetools-paypal-plus-integration
key.
Navigate to root
directory.
Run the following commands to:
Encrypt build-settings.sh
file (must be ignored by VCS):
gcloud kms encrypt \
--project=professionalserviceslabs \
--location=global \
--keyring=ps-keyring \
--key=commercetools-paypal-plus-integration \
--plaintext-file=build-settings.sh \
--ciphertext-file=build-settings.sh.enc
Decrypt build-settings.sh.enc
:
gcloud kms decrypt \
--project=professionalserviceslabs \
--location=global \
--keyring=ps-keyring \
--key=commercetools-paypal-plus-integration \
--plaintext-file=build-settings.sh \
--ciphertext-file=build-settings.sh.enc
This module is deployed as docker image to dockerhub.
The build and deployment of the docker are done using github actions.
On each push to the remote github repository, the github action ci is triggered, which builds the project and executes its tests.
The github action cd is used to create the docker-image and deploy it to dockerhub. This action is triggered when a git release tag is created.
There are two ways to create the release-tag:
git tag -a v1.0.1 -m "Minor text adjustments."
via Github UI