Welcome to the Java SDK for the PAYONE Commerce Platform (api-version 1.40.0)! This repository contains a powerful, easy-to-use software development kit (SDK) designed to simplify the integration of online payment processing into your applications.
- PAYONE Commerce Platform Java SDK
- Easy Integration: Seamlessly integrate online payment processing into your application.
- Secure Transactions: Built with security best practices to ensure safe transactions.
- Extensive Documentation: Detailed documentation to help you get started quickly.
- Open Source: Fully open source and community-driven.
dependencies {
implementation group: 'io.github.payone-gmbh', name: 'pcp-serversdk-java', version: '1.6.0'
}You can find examples and detailed usage in the examples directory.
To use this SDK you need to construct a CommunicatorConfiguration which encapsulate everything needed to connect to the PAYONE Commerce Platform.
package org.usage.app;
import com.payone.commerce.platform.lib.CommunicatorConfiguration;
class App {
private Strint merchantId;
public static void main(String[] args) {
String apiKey = System.getenv("API_KEY");
String apiSecret = System.getenv("API_SECRET");
this.merchantId = System.getenv("MERCHANT_ID");
this.config = new CommunicatorConfiguration(apiKey, apiSecret, "api.preprod.commerce.payone.com");
}
}With the configuration you can create an API client for each reource you want to interact with. For example to create a commerce case you can use the CommerceCaseApiClient.
package org.usage.app;
import com.payone.commerce.platform.lib.CommunicatorConfiguration;
import com.payone.commerce.platform.lib.endpoints.CommerceCaseApiClient;
class App {
private CommunicatorConfiguration config;
private CommerceCaseApiClient client;
public void initCommerceCaseClient() {
this.client = new CommerceCaseApiClient(this.config);
}
}All payloads and reponses are availabe as java classes within the com.payone.commerce.platform.lib.models.* package. The serialization and deserialization is handled by the SDK internally. For example, to create an empty commerce case you can pass a CreateCommerceCaseRequest instance:
package org.usage.app;
import com.payone.commerce.platform.lib.CommunicatorConfiguration;
import com.payone.commerce.platform.lib.endpoints.CommerceCaseApiClient;
import com.payone.commerce.platform.lib.models.CreateCommerceCaseRequest;
class App {
private String merchantId;
private CommunicatorConfiguration config;
private CommerceCaseApiClient client;
public void createCommerceCase() {
CreateCommerceCaseRequest createCommerceCaseRequest = new CreateCommerceCaseRequest();
// this commerce case will be empty, but you can of course add some data
CreateCommerceCaseResponse commerceCase = commerceCaseClient.createCommerceCaseRequest(this.merchantId, createCommerceCaseRequest);
}
}The models directly map to the API as described in PAYONE Commerce Platform API Reference. For an in depth example you can take a look at the demo app.
The SDK allows you to customize the underlying OkHttpClient used for API requests. This gives you control over timeouts, interceptors, proxy settings, and SSL configurations. You can customize the HTTP client either globally for all API clients or for specific API clients.
To set a custom OkHttpClient for all API clients:
// Create a custom OkHttpClient
OkHttpClient customHttpClient = new OkHttpClient.Builder()
.connectTimeout(30, TimeUnit.SECONDS)
.readTimeout(30, TimeUnit.SECONDS)
.writeTimeout(30, TimeUnit.SECONDS)
.addInterceptor(new LoggingInterceptor()) // Your custom interceptor
.build();
// Set the custom client on the CommunicatorConfiguration
CommunicatorConfiguration config = new CommunicatorConfiguration(apiKey, apiSecret, "api.preprod.commerce.payone.com", "YourIntegrator");
config.setHttpClient(customHttpClient);
// All API clients created with this configuration will use the custom HTTP client
CheckoutApiClient checkoutClient = new CheckoutApiClient(config);
CommerceCaseApiClient commerceCaseClient = new CommerceCaseApiClient(config);For more granular control, you can set a custom OkHttpClient for specific API clients:
// Create a client with default settings
CheckoutApiClient checkoutClient = new CheckoutApiClient(config);
// Create a custom HTTP client for this specific API client
OkHttpClient clientSpecificHttpClient = new OkHttpClient.Builder()
.connectTimeout(60, TimeUnit.SECONDS)
.addInterceptor(new DebugInterceptor()) // Client-specific interceptor
.build();
// Set the custom client for this specific API client
checkoutClient.setHttpClient(clientSpecificHttpClient);When both global and client-specific HTTP clients are set, the SDK follows this priority order:
- Client-specific instance (if set)
- Global client from CommunicatorConfiguration (if set)
- Default client instance
This allows you to set general settings at the global level while still customizing specific clients when needed.
Note: The custom HTTP client should be configured before making any API requests.
To interact with certain client-side SDKs (such as the credit card tokenizer), you need to generate a short-lived authentication JWT token for your merchant. This token can be retrieved using the SDK as follows:
import com.payone.commerce.platform.lib.endpoints.AuthenticationApiClient;
import com.payone.commerce.platform.lib.models.AuthenticationToken;
// ...
AuthenticationApiClient authenticationApiClient = new AuthenticationApiClient(config);
AuthenticationToken token = authenticationApiClient.getAuthenticationTokens(merchantId, null);
System.out.println("JWT Token: " + token.getToken());
System.out.println("Token ID: " + token.getId());
System.out.println("Created: " + token.getCreationDate());
System.out.println("Expires: " + token.getExpirationDate());This token can then be used for secure operations such as initializing the credit card tokenizer or other client-side SDKs that require merchant authentication. The token is valid for a limited time (10 minutes) and should be handled securely.
Note: The getAuthenticationTokens method requires a valid merchantId. Optionally, you can provide an X-Request-ID header for tracing requests.
When making a request any client may throw a ApiException. There two subtypes of this exception:
ApiErrorReponseException: This exception is thrown when the API returns an well-formed error response. The given errors are deserialized intoAPIErrorobjects which are availble via thegetErrors()method on the exception. They usually contain useful information about what is wrong in your request or the state of the resource.ApiResponseRetrievalException: This exception is a catch-all exception for any error that cannot be turned into a helpful error response. This includes malformed responses or unknown responses.
Network errors are not wrap, you can should handle the standard IOExeption.
For most payment methods some information from the client is needed, e.g. payment information given by Apple when a payment via ApplePay suceeds. PAYONE provides client side SDKs which helps you interact the third party payment providers. You can find the SDKs under the PAYONE GitHub organization. Either way ensure to never store or even send credit card information to your server. The PAYONE Commerce Platform never needs access to the credit card information. The client side is responsible for safely retrieving a credit card token. This token must be used with this SDK.
This SDKs makes no assumption about how the networking between the client and your PHP server is done. If need to serialize a model to JSON or deserialize a client side request from a JSON string to a model you can use the static serializeToJson() and deserializeFromJson() methods on the JsonSerializer class:
package org.usage.app;
import com.fasterxml.jackson.core.JsonProcessingException;
import com.payone.commerce.platform.serializer.JsonSerializer;
import com.payone.commerce.platform.lib.models.AmountOfMoney;
import com.payone.commerce.platform.lib.models.applepay.ApplePayPayment;
class App {
public void handleClientResponse(String clientMessage) throws JsonProcessingException {
// apple pay payment from json string
ApplePayPayment payment = JsonSerializer.deserializeFromJson(clientMessage, ApplePayPayment.class);
}
public String amountOfMoneyJson() throws JsonProcessingException {
AmountOfMoney amountOfMoney = new AmountOfMoney()
.amount(3199L)
.currencyCode('EUR');
// returns:
// '{ "amount": 3199, currencyCode: "EUR" }'
return JsonSerializer.serializeToJson(amountOfMoney);
}
}When a client is successfully made a payment via ApplePay it receives a ApplePayPayment. This structure is accessible as the ApplePayPayment class. You can use the ApplePayTransformer to map an ApplePayPayment to a MobilePaymentMethodSpecificInput which can be used for payment executions or order requests. The transformer has a static method transformApplePayPaymentToMobilePaymentMethodSpecificInput() which takes an ApplePayPayment and returns a MobilePaymentMethodSpecificInput. The transformer does not check if the reponse is complete, if anything is missing the field will be set to null.
package org.usage.app;
import com.fasterxml.jackson.core.JsonProcessingException;
import com.payone.commerce.platform.serializer.JsonSerializer;
import com.payone.commerce.platform.lib.models.AmountOfMoney;
import com.payone.commerce.platform.lib.models.applepay.ApplePayPayment;
import com.payone.commerce.platform.lib.models.MobilePaymentMethodSpecificInput;
import com.payone.commerce.platform.lib.transformer.ApplePayTransformer;
class App {
public String getJsonStringFromRequestSomehow() {
// commmunicate with the client...
String message = "";
return message;
}
public void preparePaymentForApplePayPayment() {
ApplePayPayment payment = JsonSerializer.deserializeFromJson(this.getJsonStringFromRequestSomehow(), ApplePayPayment.class);
MobilePaymentMethodSpecificInput input = ApplePayTransformer.transformApplePayPaymentToMobilePaymentMethodSpecificInput(payment);
// wrap input into a larger request and send to PCP API
// ...
}
}This repo contains a demo app that showcases how to implement common use cases, like a Step-by-Step Checkout and an One-Stop-Checkout. For each use case the demo app contains a private method in the top level class App.
New: After startup, the demo app also tries to retrieve an authentication token for the merchant and prints it to the console immediately after successful retrieval. This demonstrates how to use the authentication-tokens endpoint for scenarios like credit card tokenization.
You can run the app to execute the code within in the sandbox API. This is a good way to test, if your setup is correct.
If you're using grald can run it within the demo app directory via:
API_KEY=api_key API_SECRET=api_secret MERCHANT_ID=123 COMMERCE_CASE_ID=234 CHECKOUT_ID=345 ./gradlew :app:runMake sure to provide all necessary environment variables:
API_KEYa valid api key for the PAYONE Commerce PlatformAPI_SECRETa valid api secret for the PAYONE Commerce PlatformMERCHANT_IDthe merchant id which is needed to identify entities, e.g. commerce cases and checkouts, that belong to you.
See Contributing
- Checkout develop branch
- Create release branch (release/0.1.0)
git checkout -b release/0.1.0- Run prepare-release.sh script to set correct version
./prepare-release.sh 0.1.0After calling the prepare_release.sh script, it is recommended to manually trigger the changelog generation script (which uses conventional-changelog).
-
Conventional Commit Messages:
- Ensure all commit messages follow the conventional commit format, which helps in automatic changelog generation.
- Commit messages should be in the format:
type(scope): subject.
-
Enforcing Commit Messages:
- We enforce conventional commit messages using Lefthook with commitlint.
- This setup ensures that all commit messages are validated before they are committed.
-
Generate Changelog:
- Run the changelog generation script to update the
CHANGELOG.mdfile:npm run changelog
- Review and commit the updated changelog before proceeding with the release.
- Run the changelog generation script to update the
- Create PR on
developbranch - Merge
developinmainbranch
After successfully merging all changes to the main branch, an admin can trigger a GitHub Action to finalize and publish the release. This action ensures that the release process is automated, consistent, and deploys the new release from the main branch.
Triggering the GitHub Action:
- Only admins can trigger the release action.
- Ensure that all changes are committed to the
mainbranch. - Navigate to the Actions tab on your GitHub repository and manually trigger the release action for the
mainbranch.
Once the release has been published to maven central, developers can start using the latest version of the SDK. However, if you want to make the release more visible and include detailed release notes, you can optionally create a GitHub release.
- Navigate to the Releases Page: Go to the "Releases" section of your repository on GitHub.
- Draft a New Release: Click "Draft a new release".
- Tag the Release: Select the version tag that corresponds to the version you just published on npm (e.g.,
v0.1.0). - Release Title: Add a descriptive title for the release (e.g.,
v0.1.0 - Initial Release). - Auto-Generated Release Notes: GitHub can automatically generate release notes based on merged pull requests and commit history. You can review these notes, adjust the content, and highlight important changes.
- Publish the Release: Once you're satisfied with the release notes, click "Publish release".
Creating a GitHub release is optional, but it can provide additional context and visibility for your users. For detailed guidance, refer to the GitHub documentation on managing releases.
This project is licensed under the MIT License - see the LICENSE file for details.
Thank you for using our SDK for Online Payments! If you have any questions or need further assistance, feel free to open an issue or contact us.