# Build an end-to-end application
source: https://developer.mastercard.com/mastercard-processing-debit/documentation/tutorials-and-guides/build-end-to-end-app-tutorial/index.md

This tutorial helps you to create a simple Java application that makes an API call to the Mastercard Processing API in the Sandbox environment.

**What you will learn**

* How to set up the environment to develop a simple Java application
* How to perform [payload encryption](https://developer.mastercard.com/platform/documentation/security-and-authentication/securing-sensitive-data-using-payload-encryption/)
* How to make an API call

Note: The tutorial does not cover an additional level of encryption or decryption of the PIN block. For more information, refer to [PIN Block Formation and Encryption Process](https://developer.mastercard.com/mastercard-processing-debit/documentation/tutorials-and-guides/build-end-to-end-app-tutorial/index.md) tutorials.

## Step 1 - Set up the environment {#step-1---set-up-the-environment}

### 1. Pre-requisites {#1-pre-requisites}

To complete this tutorial, you will need:

* [JDK 1.8.0](https://www.java.com/en/) or later
* [Maven 3.6](https://maven.apache.org/) or later
* [IntelliJ IDEA](https://www.jetbrains.com/idea/) (or any other IDE of your choice)
* Mastercard Developers account with access to the Mastercard Processing Core APIs

### 2. Create a Maven project {#2-create-a-maven-project}

For this tutorial, IntelliJ IDEA is used as the IDE.
In IntelliJ IDEA, create a new Maven project that automatically sets your directory structure.
Provide an ArtifactId and a project name as per your choice.

![](https://static.developer.mastercard.com/content/mastercard-processing-debit/uploads/create-a-maven-project.png)

### 3. Add resources {#3-add-resources}

Add the Mastercard Processing Core API specification to your Maven project folder. For API description, refer to the API Reference.

Add the generated Sandbox signing key (`.p12` file), payload decryption key (`.p12` file), and payload encryption cert (`.pem` file) to your Maven project resources folder. Those files are generated by creating a Sandbox project in the Mastercard Developers.

Keeping a separate resource folder for these files is suggested. Your Maven project directory structure should appear as follows:

![](https://static.developer.mastercard.com/content/mastercard-processing-debit/uploads/add-resources1.png)
Note: This tutorial uses the specification for Mastercard Processing Core API, but you can easily adapt it to use any API specification file.

### 4. Update pom.xml file {#4-update-pomxml-file}

In your IDE, add the [OpenAPI Generator maven plugin](https://github.com/OpenAPITools/openapi-generator/tree/master/modules/openapi-generator-maven-plugin) to your project pom.xml file. Use the Plugin config as shown here:
Note: [OpenAPI Generator](https://openapi-generator.tech/) generates API client libraries using OpenAPI Specification. It provides multiple generators and library templates to support multiple languages and frameworks. We will use the Java generator for this project.

```XML
<build>
    <plugins>
        <plugin>
            <groupId>org.openapitools</groupId>
            <artifactId>openapi-generator-maven-plugin</artifactId>
            <version>6.3.0</version>
            <executions>
                <execution>
                    <goals>
                        <goal>generate</goal>
                    </goals>
                    <configuration>
                        <inputSpec>${project.basedir}/src/main/resources/mastercard-processing-core-api-swagger.yaml</inputSpec>
                        <generatorName>java</generatorName>
                        <library>okhttp-gson</library>
                        <generateApiTests>false</generateApiTests>
                        <generateModelTests>false</generateModelTests>

                       <apiPackage>com.mastercard.mpe.generated.apis</apiPackage>
                       <modelPackage>com.mastercard.mpe.generated.models</modelPackage>
                       <invokerPackage>com.mastercard.mpe.generated.invokers</invokerPackage>

                        <configOptions>
                            <sourceFolder>src/gen/main/java</sourceFolder>
                            <dateLibrary>java8</dateLibrary>
                        </configOptions>
                    </configuration>
                </execution>
            </executions>
        </plugin>
        <plugin>
            <groupId>org.apache.maven.plugins</groupId>
            <artifactId>maven-compiler-plugin</artifactId>
            <version>3.11.0</version>
            <configuration>
                <source>1.8</source>
                <target>1.8</target>
            </configuration>
        </plugin>
    </plugins>
</build>
```

Add the following dependencies to your pom.xml file to add dependencies for the API client library generation and the Mastercard OAuth1 Signer library.
Note: Mastercard offers Oauth1 Signer Libraries, which offer code helpers targeting the HTTP clients used by the different OpenAPI Generator Library templates. The libraries are hosted on [GitHub](https://github.com/Mastercard?utf8=%E2%9C%93&q=client-encryption&type=&language=).

Mastercard offers Client Encryption Libraries, which offer code helpers for payload encryption. The libraries are hosted on [GitHub](https://github.com/Mastercard?utf8=%E2%9C%93&q=client-encryption&type=&language=).

```XML
<dependencies>
    <dependency>
        <groupId>org.openapitools</groupId>
        <artifactId>openapi-generator-cli</artifactId>
        <version>6.6.0</version>
    </dependency>
    <dependency>
        <groupId>io.swagger.core.v3</groupId>
        <artifactId>swagger-annotations</artifactId>
        <version>2.2.14</version>
    </dependency>
    <dependency>
        <groupId>io.swagger.parser.v3</groupId>
        <artifactId>swagger-parser</artifactId>
        <version>2.1.16</version>
    </dependency>
    <dependency>
        <groupId>com.squareup.okhttp3</groupId>
        <artifactId>okhttp</artifactId>
        <version>4.11.0</version>
    </dependency>
    <dependency>
        <groupId>com.squareup.okhttp3</groupId>
        <artifactId>logging-interceptor</artifactId>
        <version>4.11.0</version>
    </dependency>
    <dependency>
        <groupId>com.google.code.gson</groupId>
        <artifactId>gson</artifactId>
        <version>2.10.1</version>
    </dependency>
    <dependency>
        <groupId>io.gsonfire</groupId>
        <artifactId>gson-fire</artifactId>
        <version>1.8.5</version>
    </dependency>
    <dependency>
        <groupId>javax.annotation</groupId>
        <artifactId>javax.annotation-api</artifactId>
        <version>1.3.2</version>
    </dependency>
    <dependency>
        <groupId>javax.ws.rs</groupId>
        <artifactId>javax.ws.rs-api</artifactId>
        <version>2.1.1</version>
    </dependency>

    <!--
    Mastercard open source library for generating a Mastercard API compliant Oauth signature --
    https://github.com/Mastercard/oauth1-signer-java
    ->
    <dependency>
        <groupId>com.mastercard.developer</groupId>
        <artifactId>oauth1-signer</artifactId>
        <version>1.5.2</version>
    </dependency>
    <!--
    Mastercard open source library for Mastercard API compliant payload encryption/decryption --
     https://github.com/Mastercard/client-encryption-java
    ->
    <dependency>
        <groupId>com.mastercard.developer</groupId>
        <artifactId>client-encryption</artifactId>
        <version>1.7.9</version>
    </dependency>
</dependencies>
```

For more information, refer to the [Generating and Configuring a Mastercard API Client](https://developer.mastercard.com/platform/documentation/security-and-authentication/generating-and-configuring-a-mastercard-api-client/#overview) page.

## Step 2 -- Generate the API Client {#step-2--generate-the-api-client}

Now you have all the dependencies; you can generate the source code. You can navigate to the project root directory within a terminal window and run `mvn clean compile`.

A new folder named **target** is created within the root directory, which contains classes generated for the schemas and API calls defined within the OpenAPI Specification. The generated classes can be found in the target folder as shown below:

![](https://static.developer.mastercard.com/content/mastercard-processing-debit/uploads/generating-api-client.png)

## Step 3 -- Authentication and encryption {#step-3--authentication-and-encryption}

Once the classes are generated, you can create a new `Main` class and method. All the following code snippets can be added to said method. An example of the file can be found at the [end of this tutorial](https://developer.mastercard.com/mastercard-processing-debit/documentation/tutorials-and-guides/build-end-to-end-app-tutorial/index.md).

### Authentication {#authentication}

The authentication for each call is done using classes defined by the Mastercard OAuth1 signer library. Instantiating one interceptor for authentication (`OkHttpOAuth1Interceptor`) ensures that the client has the correct privileges to access the server.

```JAVA
// change these values accordingly
String signingKeyFilePath = "#PATH AND NAME OF YOUR P12 FILE HERE#";
String signingKeyAlias = "#YOUR KEY ALIAS HERE#";
String signingKeyPass = "#YOUR KEY PASSWORD HERE#";
String consumerKey = "#YOUR 97 CHARACTER CONSUMER KEY HERE#";

// Step 1.1- Load the signing key - Provided by the OAuth1 Signer lib
PrivateKey signingKey = AuthenticationUtils.loadSigningKey(signingKeyFilePath, signingKeyAlias, signingKeyPass);

// Step 1.2 -- Inject OAuth signing key and consumer key to interceptor
OkHttpOAuth1Interceptor authInterceptor = new OkHttpOAuth1Interceptor(consumerKey, signingKey);
```

### Encryption {#encryption}

The encryption and decryption of the payload for each call are done using classes defined by the Mastercard Client Encryption library. With the instantiation of a second interceptor (`OkHttpEncryptionInterceptor`), the data sent can be adequately protected.

The request body of the service calls is encrypted and put in JSON Web Encryption (JWE) format. The details of what kind of keys to use, how to request and manage keys, and the algorithms used to encrypt or decrypt are present on the [API Basics](https://developer.mastercard.com/mastercard-processing-debit/documentation/api-basics-section/index.md) page.

The `OkHttpEncryptionInterceptor` constructor receives a JweConfig parameter that should be configured as such.

```JAVA
// change these values accordingly
String clientEncryptionCertPath = "#PATH AND NAME OF YOUR PEM FILE HERE#";
String mastercardEncryptionKeyFilePath = "#PATH AND NAME OF YOUR P12 FILE HERE#";
String mastercardEncryptionAlias = "#YOUR KEY ALIAS HERE#";
String mastercardEncryptionPass = "#YOUR KEY PASSWORD HERE#";

// Step 2.1 - This will be the certificate used to encrypt the payload before sending
Certificate encryptionCertificate = EncryptionUtils.loadEncryptionCertificate(clientEncryptionCertPath);

// Step 2.2 - The response received from the call will need to be decrypted using this key
PrivateKey decryptionKey = EncryptionUtils.loadDecryptionKey(
        mastercardEncryptionKeyFilePath,
        mastercardEncryptionAlias,
        mastercardEncryptionPass);

// Step 2.3 -- Prepare JweConfig 
JweConfig config = JweConfigBuilder.aJweEncryptionConfig()
        .withEncryptionCertificate(encryptionCertificate)
        .withDecryptionKey(decryptionKey)
        .withEncryptionPath("$", "$")
        .withDecryptionPath("$.encryptedValue", "$")
        .withEncryptedValueFieldName("encryptedValue")
        .build();

// Step 2.4 -- Inject JweConfig to interceptor 

OkHttpEncryptionInterceptor encryptionInterceptor = OkHttpEncryptionInterceptor.from(config);
```

An instance of the `ApiClient` class can be created, adding both interceptors that were instantiated.

```JAVA
// Step 3 -- Create ApiClient
ApiClient apiClient = new ApiClient();

// Step 3.1 -- Configure the Mastercard service URL
apiClient.setBasePath("https://sandbox.api.mastercard.com/global-processing/core");

// Step 3.2 -- Add the interceptors responsible for signing, encrypting, and decrypting HTTP requests//responses 
apiClient.setHttpClient(
        apiClient.getHttpClient()
                .newBuilder()
                .addInterceptor(encryptionInterceptor)
                .addInterceptor(authInterceptor)
                .build()
);

// Step 3.3 - Enable or disable OK Http debugging - disable on UAT/PROD env.
apiClient.setDebugging(true);
```

## Step 4 -- Make an API call {#step-4--make-an-api-call}

Now an API call is ready to get started. In this tutorial, we are using `getCard` and `activateCard`. For further information on other APIs, refer to the [API Reference](https://developer.mastercard.com/mastercard-processing-debit/documentation/api-reference/index.md) section.

```JAVA
// Example 1: get Card Contract information

// The resulting CardContractWithEncryptedCardContractNumber object will contain the response information already decrypted and ready to use

CardContractWithEncryptedCardContractNumber response = null;
try {
  CardContractApi clientApi = new CardContractApi(apiClient);
  Long contractId = 70001L;
  // Make an API Call
  response = clientApi.getCardContract(contractId, null, null);

} catch (Exception exception) {
  exception.printStackTrace();
}


// Example 2: Update Card Status to activate it
try {
  // Object with the information that will be sent
  CardContractActivation request = new CardContractActivation();
  request.activated(true);
  Long contractId = 70001L;
  CardPlasticApi clientApi = new CardPlasticApi(apiClient);
  // Make an API Call
  clientApi.activateCard(contractId, request);

} catch (Exception exception) {
  exception.printStackTrace();
}
```

## Step 5 -- Sample code {#step-5--sample-code}

By the end of this tutorial, your `Main.java` file should look something like this:

```JAVA
package org.example; // change accordingly

import com.mastercard.developer.encryption.JweConfig;
import com.mastercard.developer.encryption.JweConfigBuilder;
import com.mastercard.developer.interceptors.OkHttpEncryptionInterceptor;
import com.mastercard.developer.interceptors.OkHttpOAuth1Interceptor;
import com.mastercard.developer.utils.AuthenticationUtils;
import com.mastercard.developer.utils.EncryptionUtils;
import java.security.*;
import java.security.cert.Certificate;
import org.openapitools.client.ApiClient;
import org.openapitools.client.api.CardContractApi;
import org.openapitools.client.api.CardPlasticApi;
import org.openapitools.client.model.CardContractActivation;
import org.openapitools.client.model.CardContractWithEncryptedCardContractNumber;

public class Main {

  public static void main(String[] args) throws Exception {
    // change these values accordingly
    String consumerKey =
        "J8nQPn_Ovh1BQQTR_zKSKev2HmEHGCwdJmzDaRTOdb00fa6c!8f2d9d40a22b4869bc57161daaeed7e00000000000000000";
    String signingKeyFilePath =
        "src/main/resources/core-prod-sandbox-oauth-signing-certificate.p12";
    String signingKeyAlias = "keyalias";
    String signingKeyPass = "keystorepassword";
    String clientEncryptionCertPath =
        "src/main/resources/core-prod-sandbox-request-encryption-public-key.pem";
    String mastercardEncryptionKeyFilePath =
        "src/main/resources/core-prod-sandbox-response-decryption-private-key.p12";
    String mastercardEncryptionAlias = "sandbox-key";
    String mastercardEncryptionPass = "Sandbox@123";

    // Create generic apiClient with required configurations
    ApiClient apiClient =
        getApiClient(
            consumerKey,
            signingKeyFilePath,
            signingKeyAlias,
            signingKeyPass,
            clientEncryptionCertPath,
            mastercardEncryptionKeyFilePath,
            mastercardEncryptionAlias,
            mastercardEncryptionPass);

    // Example 1 - Get Card Contract details
    CardContractWithEncryptedCardContractNumber response = getCardContract(apiClient);

    if (response != null) {
      System.out.println(response.toJson().toString());
    }
    // Example 2 - Activate Card
    activateCard(apiClient);

    System.exit(0);
  }

  public static ApiClient getApiClient(
      String consumerKey,
      String signingKeyFilePath,
      String signingKeyAlias,
      String signingKeyPass,
      String clientEncryptionCertPath,
      String mastercardEncryptionKeyFilePath,
      String mastercardEncryptionAlias,
      String mastercardEncryptionPass)
      throws Exception {

    // Step 1.1 - Load the signing key - Provided by the OAuth1 Signer lib
    PrivateKey signingKey =
        AuthenticationUtils.loadSigningKey(signingKeyFilePath, signingKeyAlias, signingKeyPass);

    // Step 1.2 -- Inject OAuth signing key and consumer key to interceptor
    OkHttpOAuth1Interceptor authInterceptor = new OkHttpOAuth1Interceptor(consumerKey, signingKey);

    // Step 2.1 - This will be the certificate used to encrypt the payload before sending
    Certificate encryptionCertificate =
        EncryptionUtils.loadEncryptionCertificate(clientEncryptionCertPath);

    // Step 2.2 - The response received from the call will need to be decrypted using this key
    PrivateKey decryptionKey =
        EncryptionUtils.loadDecryptionKey(
            mastercardEncryptionKeyFilePath, mastercardEncryptionAlias, mastercardEncryptionPass);

    // Step 2.3 -- Prepare JweConfig
    JweConfig config =
        JweConfigBuilder.aJweEncryptionConfig()
            .withEncryptionCertificate(encryptionCertificate)
            .withDecryptionKey(decryptionKey)
            .withEncryptionPath("$", "$")
            .withDecryptionPath("$.encryptedValue", "$")
            .withEncryptedValueFieldName("encryptedValue")
            .build();

    // Step 2.4 -- Inject JweConfig to interceptor
    OkHttpEncryptionInterceptor encryptionInterceptor = OkHttpEncryptionInterceptor.from(config);

    // Step 3 -- Create ApiClient
    ApiClient client = new ApiClient();

    // Step 3.1 -- Configure the Mastercard service URL
    client.setBasePath("https://sandbox.api.mastercard.com/global-processing/core");

    // Step 3.2 -- Add the interceptors responsible for signing, encrypting, and decrypting HTTP
    // requests/responses
    client.setHttpClient(
        client
            .getHttpClient()
            .newBuilder()
            .addInterceptor(encryptionInterceptor)
            .addInterceptor(authInterceptor)
            .build());

    // Step 3.3 - Enable or disable OK Http debugging - disable on UAT/PROD env.
    client.setDebugging(true);

    return client;
  }

  private static CardContractWithEncryptedCardContractNumber getCardContract(ApiClient apiClient) {
    // Example 1: get Card Contract information

    // The resulting CardContractWithEncryptedCardContractNumber object will contain the response
    // information already decrypted and ready to use
    CardContractWithEncryptedCardContractNumber response = null;
    try {
      CardContractApi clientApi = new CardContractApi(apiClient);
      Long contractId = 70001L;
      // Make an API Call
      response = clientApi.getCardContract(contractId, null, null);

    } catch (Exception exception) {
      exception.printStackTrace();
    }

    return response;
  }

  private static void activateCard(ApiClient apiClient) {
    // Example 2: Update Card Status to activate it
    try {
      // Object with the information that will be sent
      CardContractActivation request = new CardContractActivation();
      request.activated(true);
      Long contractId = 70001L;
      CardPlasticApi clientApi = new CardPlasticApi(apiClient);
      // Make an API Call
      clientApi.activateCard(contractId, request);

    } catch (Exception exception) {
      exception.printStackTrace();
    }
  }
}
```

Once the code is written, it can be executed using the `mvn exec:java -Dexec.mainClass="package.of.Main"` command.
Tip: To ensure you always execute the latest code and correct dependencies, use the following one-liner `mvn clean compile exec:java -Dexec.mainClass="package.of.Main"`
