Server Side SDK general module
Overview
Server Side SDK is API wrapper implemented on Java.
Installation
Manually deploy artifacts to your dependency management system.
Examples for local maven repository:
-
sdk.pom
mvn install:install-file -Dfile="sdk.pom" -DpomFile="sdk.pom"
-
core.jar
usingcore.pom
mvn install:install-file -Dfile="core.jar" -DpomFile="core.pom"
-
api-client.jar
usingapi-client.pom
mvn install:install-file -Dfile="api-client.jar" -DpomFile="api-client.pom"
Requirements
- Java 1.8 or later
Gradle users
Add this dependency to your project's build file:
implementation "net.payrdr.integrations:api-client:1.0.0"
Maven users
Add this dependency to your project's POM:
<dependency>
<groupId>net.payrdr.integrations</groupId>
<artifactId>api-client</artifactId>
<version>1.0-SNAPSHOT</version>
</dependency>
Usage
Basic usage with minimal configuration:
import net.payrdr.integrations.sdk.apiclient.regiserOrder.RegisterOrderResponse;
import net.payrdr.integrations.sdk.apiclient.regiserOrder.RegisterOrderRequest;
import net.payrdr.integrations.sdk.apiclient.ApiClient;
public class ApiExample {
public static void main(String[] args) {
ApiClient client = new ApiClient.Builder()
.username(username)
.password(password)
.baseUrl(baseUrl)
.build();
RegisterOrderRequest request = RegisterOrderRequest.builder()
.setAmount(10000)
.setReturnUrl("https://mybestmerchantreturnurl.com")
.build();
RegisterOrderResponse response = client.registerOrder(request);
}
}
Configuration
Base URL
Static URL prefix for every API method.
Example: https://dev.bpcbt.com/payment/rest/register.do
. Here:
-
https://dev.bpcbt.com/payment
- base prefix -
/rest/register.do
- exact method reference
Request authentication customization
Configured authenticator would be used by default in API client.
Prebuilt authentication options:
- Username and password can be configured using
ApiClient.Builder.username(String)
along withApiClient.Builder.password(String)
methods. Builder would raise aConfigurationException
in case when only username or only password is provided. - Merchant token can be configured via
ApiClient.Builder.token(String)
.ConfigurationException
is thrown when the token is passed with username or password. - Noop authentication. When neither username and password nor token is passed.
If built-in authentication methods are not enough, feel free to extend net.payrdr.integrations.sdk.apiclient.ApiRequestAuthenticator
and provide it to the builder via authenticator(ApiRequestAuthenticator)
method.
Enabling request signature
To have a possibility to sign requests, first contact technical support service to enable signatures for you. Then upload a certificate using Merchant Portal.
You need to provide a key pair to ApiClient to generate a hash and a signature using your secret key in the process of sending a request.
Private RSA key can be configured in two ways:
-
(Default way) Create
net.payrdr.integrations.sdk.apiclient.PrivateKeyInfo
with the parameters:- String
type
- one of "PKCS8", "JKS", "PKCS12" supported keystore types. - String
path
- absolute path to keystore file.ConfigurationException
is thrown if the keystore is not readable. - String
password
- keystore password AND entry password. Both should be protected with the same password. Used with "JKS" and "PKCS12" keystore types. - String
alias
- keystore entry alias for desired key. Used with "JKS" and "PKCS12" keystore types.
import net.payrdr.integrations.sdk.apiclient.ApiClient; public class ApiExample { public static void main(String[] args) { ApiClient client = new ApiClient.Builder() .username(username) .password(password) .baseUrl(baseUrl) .keyInfo(PrivateKeyInfo.builder() .path("/some/absolute/keystore/path/filename.jks") .type("JKS") .password("keystore_and_entry_password") .alias("keystoreEntryAlias") .build()) .build(); } }
- Implement
net.payrdr.integrations.sdk.core.security.PrivateKeyProvider
interface and pass implementation toApiClient.Builder.keyProvider(PrivateKeyProvider)
:
import net.payrdr.integrations.sdk.apiclient.ApiClient; public class ApiExample { public static void main(String[] args) { ApiClient client = new ApiClient.Builder() .username(username) .password(password) .baseUrl(baseUrl) .keyProvider(new PrivateKeyProvider() { @Override public PrivateKey provide() { //Do some magic here and provide private rsa key return null; } }) .build(); } }
- String
Signature algorithm
Default request signature algorithm is SHA256WithRSA. Default net.payrdr.integrations.sdk.core.security.SHA256WithRSASigner
would be initialized using provided java.security.PrivateKey
.
During request execution, the request body would be transformed to hash (X-Hash
) and the signature value (X-Signature
) and passed in the request headers.
X-Hash: GDrobAlCcpdOOlVuqra7Oogl/4s3vToGOXGpf3t/wJ0=
X-Signature: TJrm6jYAf2ssp/iYoDb3B+nuPqQ572oe/3a2RQ4oG2BFbmeRcoiITvR6tybNsbRHvRRlJys/2xFBW9ilee9GCN9WwYJ9h/MDyUEktj6NLZOztBAWi+7S8LDaiEWd+MUdTqe0hdiqo/lY2uIlEMTtkqTB7LsbEhrJ6NhJdpSxrstAnpyGIrGfldt0Vz+gz+YQ5XXrwhD6HyGShqV+tXzxcMdezWJJJ8vH5C0s 4jij2PuoauUSHkTrSc4vIJl/TPMliLJNsC5KCXka4/1hSr0exawFBekRldFnv5YvFakWJUN3kEc8 w3uauzTDh+CG0/Vxs/3gNun7e9ik9kCpwdiSMw==
No additional configuration is needed to use default SHA256WithRSASigner.
Custom algorithm can be implemented using net.payrdr.integrations.sdk.core.security.RequestSigner
interface.
Pass your implementation to ApiClient.Builder.requestSigner(RequestSigner)
method:
import net.payrdr.integrations.sdk.apiclient.ApiClient;
public class ApiExample {
public static void main(String[] args) {
ApiClient client = new ApiClient.Builder()
.username(username)
.password(password)
.baseUrl(baseUrl)
.requestSigner(new RequestSigner() {
@Override
public void init(PrivateKey privateKey) {
//do some magic with provided private key
}
@Override
public void sign(HttpRequest request) {
// Here we can customize request signature. Key would be loaded by KeyProvider
}
})
.build();
}
}
HTTP client customization
By default, built-in HttpClient wraps HttpsUrlConnection
.
Customization handles:
-
Request timeouts.
Default values are 60000 ms for read timeout and 5000 ms for connect timeout.
Read timeout and connect timeout may be customized via corresponding methods inApiClient.Builder
:import net.payrdr.integrations.sdk.apiclient.ApiClient; public class ApiExample { public static void main(String[] args) { ApiClient client = new ApiClient.Builder() .username(username) .password(password) .baseUrl(baseUrl) .readTimeout(1000) // Custom timeouts; .connectTimeout(2000) .build(); } }
-
Default TLS TrustStore can be extended or replaced:
- Append single certificate from file system to trust store via
customCertPath(String path)
method
import net.payrdr.integrations.sdk.apiclient.ApiClient; public class ApiExample { public static void main(String[] args) { ApiClient client = new ApiClient.Builder() .username(username) .password(password) .baseUrl(baseUrl) // Merge certificate from file system into system trust store and provide it to httpClient .customCertPath("/path/to/custom/certificate.cer") // X.509 Certificate file format .build(); } }
- Append all keystore certificates to trust store via
customTrustStore(java.security.KeyStore)
method
import net.payrdr.integrations.sdk.apiclient.ApiClient; public class ApiExample { public static void main(String[] args) { ApiClient client = new ApiClient.Builder() .username(username) .password(password) .baseUrl(baseUrl) // Merge all certificates from provided keystore with system trust store and provide it httpClient .customTrustStore(KeyStore.getInstance("JKS")) // Load it your own way .build(); } }
- Replace default trust store with
java.security.KeyStore
usingtrustStore
method
import net.payrdr.integrations.sdk.apiclient.ApiClient; public class ApiExample { public static void main(String[] args) { ApiClient client = new ApiClient.Builder() .username(username) .password(password) .baseUrl(baseUrl) // Provide custom trust store to httpClient. .trustStore(KeyStore.getInstance("JKS")) //Load it your own way. .build(); } }
- Append single certificate from file system to trust store via
Custom HTTP client implementation
HTTP client can be replaced with your own implementation using net.payrdr.integrations.sdk.core.http.(HttpClient,HttpRequest,HttpResponse)
interfaces:
import net.payrdr.integrations.sdk.apiclient.ApiClient;
import net.payrdr.integrations.sdk.core.http.HttpClient;
import net.payrdr.integrations.sdk.core.http.HttpRequest;
import net.payrdr.integrations.sdk.core.http.HttpResponse;
public class ApiExample {
public static void main(String[] args) {
ApiClient client = new ApiClient.Builder()
.username(username)
.password(password)
.baseUrl(baseUrl)
.httpClient(new HttpClient() {
@Override
public HttpResponse execute(HttpRequest request) {
// do some magic and transform HttpRequest into HttpResponse
return null;
}
@Override
public HttpRequest requestInstance() {
// return some implementation of HttpRequest.
return null;
}
})
.build();
}
}
Serialization/deserialization customization
Content-types supported by default for request serialization:
- application/json" with "application/json; charset=UTF-8" via Gson library
- "application/x-www-form-urlencoded"
Cotent-types supported by default for response deserialization:
- "application/json" and "application/json; charset=UTF-8" via Gson library
- "text/plain;charset=utf-8"
- "application/x-www-form-urlencoded"
- "text/html;charset=iso-8859-1"
Customization
Custom serializer can be implemented using net.payrdr.integrations.sdk.apiclient.serialization.RequestSerializer
and net.payrdr.integrations.sdk.apiclient.serialization.ResponseDeserializer
interfaces.
Implementations can be registered via ApiClient.Builder.registerSerializer(RequestSerializer)
and ApiClient.Builder.registerDeserializer(ResponseDeserializer)
methods.
import net.payrdr.integrations.sdk.apiclient.ApiClient;
public class ApiExample {
public static void main(String[] args) {
ApiClient client = new ApiClient.Builder()
.username(username)
.password(password)
.baseUrl(baseUrl)
.registerSerializer(new RequestSerializer() {
@Override
public ContentType getContentType() {
//register new ContentType in cache
return ContentType.of("custom/content-type");
}
@Override
public String serialize(ApiRequest request) {
return "MY_CUSTOM_SERIALIZATION";
}
})
.registerDeserializer(new ResponseDeserializer() {
@Override
public ContentType getContentType() {
//use registered ContentType from cache
return ContentType.of("custom/content-type");
}
@Override
public <T extends ApiResponse> T deserialize(String responseBody, Class<T> responseType) {
//DO THE DESERIALIZATION MAGIC IN HERE
return (T) new ApiResponse() {};
}
})
.build();
}
}
Also you can customize Gson library configurations using ApiClient.Builder.gson(Gson)
method:
import net.payrdr.integrations.sdk.apiclient.ApiClient;
public class ApiExample {
public static void main(String[] args) {
ApiClient client = new ApiClient.Builder()
.username(username)
.password(password)
.baseUrl(baseUrl)
.gson(new GsonBuilder()
.setFieldNamingPolicy(FieldNamingPolicy.IDENTITY)
.setDateFormat("yyyy-MM-dd'T'HH:mm:ss")
.create())
.build();
}
}
Exceptions
All exceptions are RuntimeException
and can be of the following types:
-
ConfigurationException
- thrown whenApiClient.Builder
cannot properly configure client with provided settings. (For example: creating client without base URL, private key file is not readable, etc.) -
SerializerNotSupportedException
- thrown when corresponding serializer is not registered for request and when deserializer for response content type cannot be found. -
ValidationException
- thrown when the request validation failed. Contains list of errors for every validation failure. -
KeystoreException
- thrown when the private key information is misconfigured in some way. -
RequestExecutionException
- wraps an internal exceptions if something went wrong during request execution.
Building new API methods
Can be done by simple extending of net.payrdr.integrations.sdk.apiclient(ApiRequest,ApiResponse)
classes.
Abstract methods of ApiRequest
:
- abstract List
validate();
- fillsValidationError
list if any validation fails - abstract String
getUrl();
- relative method reference - abstract HttpMethod
getMethod();
- HTTP method for request - abstract ContentType
getContentType()
; - content type used to determine serializer and sent via header - abstract
Class getResponseType();
- response DTO type to deserialize from HTTP response
Default methods of ApiRequest
:
- boolean
hasToBeSigned()
- determines if the API request has to be signed. Bypass configured request signer. Default:true
- boolean
hasToBeAuthenticated()
- determines if the API request has to be authenticated. Bypass configured authenticator. Default:true
-
Map<String, List<String>> getHeaders()
- additional HTTP headers that would be merged into the HTTP request before signing process. Default:null