# Customer Onboarding Guide
source: https://developer.mastercard.com/india-online-dispute-resolution/documentation/onboarding-guide/index.md
This tutorial will explain how to create a simple API client.
## Environment setup {#environment-setup}
1. Create a Maven project.
* In the IDE, create a new Maven project (for example, **IndiaOnlineDisputeResolutionTutorial**) which sets your directory structure automatically.
* Provide an **ArtifactId** and a project name as per your choice.
2. Add resources.
* Add the IODR [API specification](https://developer.mastercard.com/india-online-dispute-resolution/documentation/api-reference/index.md#apis) to your resources folder of Maven project.
* Add the generated sandbox key, Mastercard encryption key, and encryption certificate to your Maven project resources folder. This is generated while creating the project on Mastercard Developers.
* Your Maven project directory structure appears:

3. Update the pom.xml file.
```XML
org.openapitools
openapi-generator-maven-plugin
5.2.1
IODR API REST Client
generate
${project.basedir}/src/main/resources/india-online-dispute-resolution-api-swagger.yaml
java
false
false
src/gen/java/main
true
java8
Date=LocalDate
```
* Add the following dependencies to your pom.xml file to generate the API client library and the Mastercard OAuth1 Signer library.
The Mastercard OAuth1 Signer library provides code helpers for HTTP clients used for various OpenAPI Generator Library templates.
**Dependencies**
```XML
17
2.5.3
1.18.16
4.9.1
3.11
1.3.2
1.5.1
1.8.2
4.13.1
2.8.6
1.8.5
1.6.2
1.3.2
UTF-8
com.mastercard.developers.iodr
0.2.1
17
17
org.springframework.boot
spring-boot-starter-web
${spring.boot.version}
org.springframework.boot
spring-boot-devtools
${spring.boot.version}
runtime
true
org.springframework.data
spring-data-commons
2.5.0
com.squareup.okhttp3
okhttp
${okhttp-version}
com.squareup.okhttp3
logging-interceptor
${okhttp-version}
com.google.code.gson
gson
${gson-version}
io.gsonfire
gson-fire
${gson-fire-version}
org.apache.commons
commons-lang3
${commons-lang3-version}
javax.annotation
javax.annotation-api
${javax-annotation-version}
com.mastercard.developer
oauth1-signer
${oauth1-signer-version}
com.mastercard.developer
client-encryption
${client-encryption-version}
io.swagger
swagger-annotations
${swagger-core-version}
com.google.code.findbugs
jsr305
3.0.2
org.openapitools
jackson-databind-nullable
${jackson-databind-nullable-version}
commons-io
commons-io
2.6
log4j
log4j
1.2.14
runtime
junit
junit
4.13.2
test
org.springframework.boot
spring-boot-starter-test
test
com.vaadin.external.google
android-json
org.junit.jupiter
junit-jupiter-engine
org.mockito
mockito-junit-jupiter
org.mockito
mockito-inline
3.0.0
test
```
For more information, refer [Generating and Configuring a Mastercard API Client](https://developer.mastercard.com/platform/documentation/security-and-authentication/generating-and-configuring-a-mastercard-api-client/#overview).
## Setting up the project {#setting-up-the-project}
1. Navigate to the root directory of the project within a terminal window and run `mvn clean install`.  A folder named **target** is created within your root directory, which contains classes generated for the schemas and API calls defined within the OpenAPI Specification. 
2. Following are the steps to create a sample project with an open API generator.
a. Create a Java file **IODRApiClient.java** at src/main/java/.
b. To make the API call, add the following OAuth credentials in **IODRApiClient.java** .
c. Create a java test file **IODRApiTest.java** at src/test/java/.
**OAuth**
```java
String consumerKey = "";
String signingKeyFilePath = "./src/main/resources/client p12 file name downloaded on project creation>.p12";
String encryptionCertPath = "./src/main/resources/.pem";
String mcKeyFilePath = "./src/main/resources/.p12";
String signingKeyAlias = "";
String mcKeyAlias = "";
String mcKeyPassword = "";
PrivateKey signingKey = AuthenticationUtils.loadSigningKey(signingKeyFilePath, signingKeyAlias,
signingKeyPassword);
```
**Content of IODRApiClient.java**
```java
package com.mastercard.odr;
import java.security.PrivateKey;
import java.security.cert.Certificate;
import com.mastercard.developer.interceptors.OkHttpJweInterceptor;
import com.mastercard.developer.interceptors.OkHttpOAuth1Interceptor;
import com.mastercard.developer.utils.AuthenticationUtils;
import com.mastercard.developer.utils.EncryptionUtils;
import com.mastercard.developer.encryption.JweConfig;
import com.mastercard.developer.encryption.JweConfigBuilder;
import org.springframework.stereotype.Service;
@Service
public class IODRApiClient {
public ApiClient getApiClient(boolean enableEncryption) throws Exception {
ApiClient client = new ApiClient();
String consumerKey = "";
String signingKeyFilePath = "./src/main/resources/client p12 file name downloaded on project creation>.p12";
String encryptionCertPath = "./src/main/resources/.pem";
String mcKeyFilePath = "./src/main/resources/.p12";
String signingKeyAlias = "";
String signingKeyPassword = "";
String mcKeyAlias = "";
String mcKeyPassword = "";
PrivateKey signingKey = AuthenticationUtils.loadSigningKey(signingKeyFilePath, signingKeyAlias,
signingKeyPassword);
client.setBasePath("https://mtf.api.mastercard.co.in/iodr");
client.setDebugging(true);
if (enableEncryption) {
client.setHttpClient(client.getHttpClient().newBuilder()
.addInterceptor(new OkHttpJweInterceptor(getEncryptionDecryptionConfig(encryptionCertPath,mcKeyFilePath, mcKeyAlias, mcKeyPassword)))
.addInterceptor(new OkHttpOAuth1Interceptor(consumerKey, signingKey)).build());
} else {
client.setHttpClient(client.getHttpClient().newBuilder()
.addInterceptor(new OkHttpOAuth1Interceptor(consumerKey, signingKey)).build());
}
return client;
}
private JweConfig getEncryptionDecryptionConfig(String encryptionCertPath, String keyFile, String keyAlias, String password) {
JweConfig config = null;
try {
Certificate encryptionCertificate = EncryptionUtils.loadEncryptionCertificate(encryptionCertPath);
PrivateKey key = EncryptionUtils.loadDecryptionKey(keyFile, keyAlias, password);
config = JweConfigBuilder.aJweEncryptionConfig().withEncryptionCertificate(encryptionCertificate)
.withEncryptionPath("$", "$").withEncryptedValueFieldName("encryptedValue")
.withDecryptionKey(key).withDecryptionPath("$.encryptedValue", "$")
.build();
} catch (Exception e) {
System.out.println(e);
}
return config;
}
}
```
**Content of IODRApiTest.java**
```java
package com.mastercard.odr;
import org.junit.Assert;
import org.junit.Before;
import org.junit.Test;
import org.junit.runner.RunWith;
import org.openapitools.client.api.IodrApi;
import org.openapitools.client.model.*;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.test.context.ContextConfiguration;
import org.springframework.test.context.junit4.SpringJUnit4ClassRunner;
import java.util.UUID;
@RunWith(SpringJUnit4ClassRunner.class)
@ContextConfiguration(classes = { IODRApiClient.class })
public class IODRApiTest {
@Autowired
IODRApiClient iodrApiClient;
IodrApi iodrApi;
IodrApi iodrApiClientForEncryptionDecryption;
@Before
public void setUp() throws Exception {
iodrApi = new IodrApi(iodrApiClient.getApiClient(false));
iodrApiClientForEncryptionDecryption = new IodrApi(iodrApiClient.getApiClient(true));
}
@Test
public void testCreateComplaintsAPIWithPositiveScenario() throws Exception {
try {
String requestId = UUID.randomUUID().toString();
CreateComplaint createComplaintRequestPayload = getCreateComplaintRequest();
System.out.println("Calling create a new complaint API Positive Scenario with requestID "+requestId +" and request payload "+ createComplaintRequestPayload);
Complaint createComplaintResponse = iodrApiClientForEncryptionDecryption.createComplaint(requestId, createComplaintRequestPayload);
Assert.assertEquals("Complaint created successfully.", createComplaintResponse.getDescription());
System.out.println("Calling create a new complaint API response : "+ createComplaintResponse);
} catch (Exception e) {
System.out.println("Create a new complaint API Call failed with error msg : "+ e.getMessage());
Assert.assertNotNull(e.getMessage());
}
}
@Test
public void testCreateComplaintsAPIWithNegativeScenario() throws Exception {
try {
String requestId = UUID.randomUUID().toString();
CreateComplaint createComplaintRequestPayload = getCreateComplaintRequest();
createComplaintRequestPayload.setCardNumber("");
System.out.println("Calling create a new complaint API with Negative Scenario requestID : "+requestId+ " and request payload : {}"+ createComplaintRequestPayload.toString());
Complaint createComplaintResponse = iodrApiClientForEncryptionDecryption.createComplaint(requestId, createComplaintRequestPayload);
System.out.println("Calling create a new complaint API response with Negative Scenario : " + createComplaintResponse.toString());
} catch (Exception e) {
System.out.println("Create a new complaint API Call failed with error msg with Negative Scenario: " + e);
Assert.assertNotNull(e.getMessage());
}
}
@Test
public void testValidateTransactionStatusWithPositiveScenario() {
try {
String requestId = UUID.randomUUID().toString();
IODRTransactionValidation iodrTransactionValidationRequestPayload = getValidateTransactionRequest();
System.out.println("Calling validate transaction details API with requestID : " + requestId + " and request payload : " + iodrTransactionValidationRequestPayload.toString());
Detail validateTransactionDetails = iodrApiClientForEncryptionDecryption.validateTransaction(requestId, iodrTransactionValidationRequestPayload);
System.out.println("Calling validate transaction details API response : " + validateTransactionDetails.toString());
} catch (Exception e) {
System.out.println("Validate transaction details API Call failed with error msg " + e);
Assert.assertNotNull(e);
}
}
@Test
public void testValidateTransactionStatusWithNegativeScenario() {
try {
String requestId = UUID.randomUUID().toString();
IODRTransactionValidation iodrTransactionValidationRequestPayload = getValidateTransactionRequest();
iodrTransactionValidationRequestPayload.setAcquirerICA("");
System.out.println("Calling validate transaction details API with requestID : " + requestId + " and request payload : " + iodrTransactionValidationRequestPayload.toString());
Detail validateTransactionDetails = iodrApiClientForEncryptionDecryption.validateTransaction(requestId, iodrTransactionValidationRequestPayload);
System.out.println("Calling validate transaction details API response : " + validateTransactionDetails.toString());
} catch (Exception e) {
System.out.println("Validate transaction details API Call failed with error msg " + e);
Assert.assertNotNull(e);
}
}
@Test
public void testGetTransactionStatusWithPositiveScenario() {
try {
String trackingNumber = "OUD0AT0UAKDO";
System.out.println("Calling get transaction status API with trackingNumber : " + trackingNumber);
Status transactionDetailStatus = iodrApiClientForEncryptionDecryption.getTransactionStatus(trackingNumber);
System.out.println("Calling get transaction status API response : " + transactionDetailStatus.toString());
} catch (Exception e) {
System.out.println("Get transaction status API Call failed with error msg "+e);
Assert.assertNotNull(e);
}
}
@Test
public void testGetTransactionStatusWithNegativeScenario() {
try {
String trackingNumber = "OUD0AT0UAKDP";
System.out.println("Calling get transaction status API with trackingNumber : " + trackingNumber);
Status transactionDetailStatus = iodrApiClientForEncryptionDecryption.getTransactionStatus(trackingNumber);
System.out.println("Calling get transaction status API response : " + transactionDetailStatus.toString());
} catch (Exception e) {
System.out.println("Get transaction status API Call failed with error msg "+e);
Assert.assertNotNull(e);
}
}
@Test
public void testUpdateComplaintsByUserAPIWithPositiveScenario() {
try {
String requestId = UUID.randomUUID().toString();
UpdateComplaintByUser updateComplaintByUser = getUpdateComplaintByUserRequest();
System.out.println("Calling update a complaint by issuer API with requestID : "+ requestId+" and request payload :"+ updateComplaintByUser.toString());
Complaint complaintUpdateByIssuer = iodrApi.updateComplaint(requestId, updateComplaintByUser);
System.out.println("Calling update a complaint by issuer API response :"+ complaintUpdateByIssuer.toString());
} catch (Exception e) {
System.out.println(e);
Assert.assertNotNull(e);
}
}
@Test
public void testUpdateComplaintsByUserAPIWithNegativeScenario() {
try {
String requestId = UUID.randomUUID().toString();
UpdateComplaintByUser updateComplaintByUser = getUpdateComplaintByUserRequest();
updateComplaintByUser.setTrackingNumber("ABX");
System.out.println("Calling update a complaint by issuer API with requestID "+ requestId+" and request payload "+updateComplaintByUser);
Complaint complaintUpdateByIssuer = iodrApi.updateComplaint(requestId, updateComplaintByUser);
System.out.println("Calling update a complaint by issuer API response :" + complaintUpdateByIssuer.toString());
} catch (Exception e) {
System.out.println(e);
Assert.assertNotNull(e);
}
}
@Test
public void testFetchComplaintBySerachCriteriaAPIWithPositiveScenario() {
try {
String requestId = UUID.randomUUID().toString();
FetchComplaintsBySearchCriteria fetchComplaintsBySearchCriteria = getComplaintsBySeachParamRequest();
System.out.println("Calling get a complaint Details API with requestID : " + requestId + " and request payload : " + fetchComplaintsBySearchCriteria.toString());
Search complaintSearchResponse = iodrApiClientForEncryptionDecryption.getComplaintsBySearchParam(requestId, fetchComplaintsBySearchCriteria);
System.out.println("Calling get a complaint Details API response : " + complaintSearchResponse.toString());
} catch (Exception e) {
System.out.println(e);
Assert.assertNotNull(e);
}
}
@Test
public void testFetchComplaintBySerachCriteriaAPIWithNegativeScenario() {
try {
String requestId = UUID.randomUUID().toString();
FetchComplaintsBySearchCriteria fetchComplaintsBySearchCriteria = getComplaintsBySeachParamRequest();
fetchComplaintsBySearchCriteria.setSearchValue("");
System.out.println("Calling get a complaint Details API with requestID : " + requestId + " and request payload : " + fetchComplaintsBySearchCriteria.toString());
Search complaintSearchResponse = iodrApiClientForEncryptionDecryption.getComplaintsBySearchParam(requestId, fetchComplaintsBySearchCriteria);
System.out.println("Calling get a complaint Details API response : " + complaintSearchResponse.toString());
} catch (Exception e) {
System.out.println(e);
Assert.assertNotNull(e);
}
}
private CreateComplaint getCreateComplaintRequest() {
CreateComplaint createComplaint = new CreateComplaint();
createComplaint.setComplaintType(CreateComplaint.ComplaintTypeEnum.ATM);
createComplaint.setTransactionDate("2025-03-06");
createComplaint.setCardNumber("530837881010");
createComplaint.setTransactionAmount("9999.98");
return createComplaint;
}
// Validate Transaction Details API by Issuer Request payload
private IODRTransactionValidation getValidateTransactionRequest() {
IODRTransactionValidation iodrTransactionValidation = new IODRTransactionValidation();
iodrTransactionValidation.setTrackingNumber("OUD0AT0UAKDO");
iodrTransactionValidation.setRetrievalReferenceNumber("435465768995");
iodrTransactionValidation.setBanknetReferenceNumber("234354739");
iodrTransactionValidation.setApprovalCode("A1R4D8");
iodrTransactionValidation.setAcquirerICA("00000023162");
return iodrTransactionValidation;
}
// Update Complaint By Issuer or Acquirer API Request payload
private UpdateComplaintByUser getUpdateComplaintByUserRequest() {
UpdateComplaintByUser updateComplaintByIssuer = new UpdateComplaintByUser();
updateComplaintByIssuer.setComments("Complaint status updated");
updateComplaintByIssuer.setComplaintStatus(UpdateComplaintByUser.ComplaintStatusEnum.UNDER_INVESTIGATION);
updateComplaintByIssuer.setTrackingNumber("OUD0AT0UAKDO");
return updateComplaintByIssuer;
}
// Get Complaint Details by Search criteria by Issuer or Acquirer
private FetchComplaintsBySearchCriteria getComplaintsBySeachParamRequest() {
FetchComplaintsBySearchCriteria fetchComplaintsBySearchCriteria = new FetchComplaintsBySearchCriteria();
fetchComplaintsBySearchCriteria.searchType(FetchComplaintsBySearchCriteria.SearchTypeEnum.DEFAULT);
return fetchComplaintsBySearchCriteria;
}
}
```
3. Once the project setup is completed, compile and run the project.
Note: You have successfully completed the tutorial on how to generate the SDK and connect to the IODR API in Sandbox using the SDK.
## Encryption and decryption {#encryption-and-decryption}
If the endpoint you are calling requires [encryption or decryption](https://developer.mastercard.com/platform/documentation/security-and-authentication/securing-sensitive-data-using-payload-encryption/), you need to configure an interceptor to encrypt the request payload or decrypt the response body.
To configure the interceptor, load the certificate:
* create the configuration object for encryption and decryption.
```java
private JweConfig getEncryptionDecryptionConfig(String encryptionCertPath, String keyFile, String keyAlias, String password)
{
JweConfig config = null;
try {
Certificate encryptionCertificate = EncryptionUtils.loadEncryptionCertificate(encryptionCertPath);
PrivateKey key = EncryptionUtils.loadDecryptionKey(keyFile, keyAlias, password);
config = JweConfigBuilder.aJweEncryptionConfig().withEncryptionCertificate(encryptionCertificate)
.withEncryptionPath("$", "$").withEncryptedValueFieldName("encryptedValue")
.withDecryptionKey(key).withDecryptionPath("$.encryptedValue", "$")
.build();
} catch (Exception e) {
System.out.println(e);
}
return config;
}
```
* Instantiate `IodrApi` with `getApiClient` with `enabledEncryptionDecryption` as true.
```Java
IodrApi iodrApiClientForEncryptionDecryption = new IodrApi(getApiClient(true));
```
* Use the following method to get the `ApiClient`.
```Java
public ApiClient getApiClient(boolean enableEncryption) throws Exception
{
ApiClient client = new ApiClient();
String consumerKey = "";
String signingKeyFilePath = "./src/main/resources/client p12 file name downloaded on project creation>.p12";
String encryptionCertPath = "./src/main/resources/.pem";
String mcKeyFilePath = "./src/main/resources/.p12";
String signingKeyAlias = "";
String signingKeyPassword = "";
String mcKeyAlias = "";
String mcKeyPassword = "";
PrivateKey signingKey = AuthenticationUtils.loadSigningKey(signingKeyFilePath, signingKeyAlias,
signingKeyPassword);
client.setBasePath("https://mtf.api.mastercard.co.in/iodr");
client.setDebugging(true);
if (enableEncryption) {
client.setHttpClient(client.getHttpClient().newBuilder()
.addInterceptor(new OkHttpJweInterceptor(getEncryptionDecryptionConfig(encryptionCertPath,mcKeyFilePath, mcKeyAlias, mcKeyPassword)))
.addInterceptor(new OkHttpOAuth1Interceptor(consumerKey, signingKey)).build());
} else {
client.setHttpClient(client.getHttpClient().newBuilder()
.addInterceptor(new OkHttpOAuth1Interceptor(consumerKey, signingKey)).build());
}
return client;
}
```
### Generate a unique Request-ID {#generate-a-unique-request-id}
The Request-ID header identifies each API request. This helps in tracking and logging failed requests, debug, and trace issues.
Use the UUID class in Java to generate a random UUID.
```java
import java.util.UUID;
public class RequestIdGenerator {
public static String generateRequestId() {
return UUID.randomUUID().toString();
}
}
```
Note: For a walkthrough of the first Sandbox call, see [Make your first Sandbox request](https://developer.mastercard.com/india-online-dispute-resolution/documentation/quick-start-guide/index.md#step-3-make-your-first-sandbox-request).