HelloWorld.java - How to run Java Sample Code using the Hello World API and Mutual SSL

shameem
Visa Employee

In this "How-to" guide we will show you how to run the “Hello World” project using Visa Hello World API and Two-Way SSL (Mutual Authentication). The Hello World API is a simple API for testing the connectivity with the Visa Network.

 

Important Links:

 

 

How to Create a Visa Developer Project

 

Before you are able to run the “Hello World” Project, you must create a Visa Developer Portal (VDP) project and get credentials. If you haven't registered yet just click on register here, fill out the account information, agree to the terms and conditions and click on receive emails. Once you have successfully activated your account, you will see your dashboard and you are ready to go.

 

java1.png

 

Once you are there, click on create your first project if this is your first project.  On the next page, you will be asked for details, such as project name, description and a list of APIs to choose from.

 

Java2.png

 

For this tutorial, we're going to select “Visa Direct” and click create project.

 

 

Java3.png

 

How to get Credentials

 

After creating your project, you will be redirected to the project summary page. You can obtain your project credentials by browsing the left side navigation menu of your project and click on “Credentials”.

 

Java4.png

 

What is required for the Two-Way SSL (Mutual Authentication)?

 

To be able to make an API call with 2-way SSL authentication, you need to have the following:

 

  1. User ID
  2. Password
  3. Your client cert
  4. Your private key previously downloaded
  5. Visa Development Platform Certificate

Java5.png

 

 

Download the project certificate as well as the common certificates - Visa Developer Platform certificate and DigiCert Certificate. 

visa_common_certs.png

 

 

Import an existing SSL certificate and private key to a keystore:

 

a) Convert the certificate and private key to PKCS 12

 

Place your private key file (for example: privateKey.pem and your certificate file from VDP (for example: cert.pem in the same directory. Generate a keystore (for example: myProject_keyAndCertBundle.p12) file as shown below. 
Note: The myProject_keyAndCertBundle.p12 is only a placeholder file name. You may choose to name it anything else.

 

 

> openssl pkcs12 -export -in cert.pem -inkey "privateKey.pem" -certfile cert.pem -out myProject_keyAndCertBundle.p12

 

 

 

b) Run the following Java keytool command to convert your P12 file into a JKS file..

 

 

> keytool -importkeystore -srckeystore myProject_keyAndCertBundle.p12 -srcstoretype PKCS12 -destkeystore myProject_keyAndCertBundle.jks -deststoretype PKCS12

 

 

 

c) Run the following Java keytool command to validate the contents of your new JKS file.

 

 

> keytool -list -v -keystore myProject_keyAndCertBundle.jks

 

 

 

d) Run the following command to add the root certificate to your JKS file.

 

 

> keytool -import -alias ejbca -keystore myProject_keyAndCertBundle.jks -file VDPCA-SBX.pem -storepass <password>

 

 

 

e) Run the following command to add digicert to your JKS file.

 

 

> keytool -import -alias digicert -keystore myProject_keyAndCertBundle.jks -file DigiCertGlobalRootCA.crt -storepass <password>

 

 

How to run the Java Sample codes of the “Hello World API” using IntelliJ

 

Next, we'll show you how to run the Java sample code of the “Hello World API” using IntelliJ. IntelliJ IDEA is a cross-platform IDE that provides consistent experience on Windows, macOS, and Linux, and can be downloaded here. In IntelliJ IDEA, a project helps you organize your source code, tests, libraries that you use, build instructions, and your personal settings in a single unit.

 

Step 1: Launch IntelliJ IDEA

 

  • If the Welcome screen opens, click Create New Project. Otherwise, from the main menu, select File | New | Project.

java6.png

 

Step 2 - In the New Project wizard, select Java from the list on the left.

 

To develop Java applications in IntelliJ IDEA, you need the Java SDK (JDK).

 

  • If the necessary JDK is already defined in IntelliJ IDEA, select it from the Project SDK list.
  • If the JDK is installed on your computer, but not defined in the IDE, select Add JDK and specify the path to the JDK home directory.
  • If you don't have the necessary JDK on your computer, select Download JDK.

 

We're not going to use any additional libraries or frameworks for this tutorial, so click Next. Don't create a project from the template. In this tutorial, we're going to do everything from scratch, so click Next.

 

Step 3 - Name the project

 

  • For example: HelloWorld. If necessary, change the default project location and click Finish.

java7.png

 

Step 4 - Upload the HelloWorld.java in the “src” folder

 

java8.png

 

Double click on the file Helloworld.java (if it is not already open) and set the below parameters. 

 

String keystorePath = "<YOUR JAVA KEYSTORE PATH>";

String keystorePassword = "<YOUR KEYSTORE PASSWORD>";

String userId = "<YOUR USER ID>";

String password = "<YOUR PASSWORD>";

 

 

 

 

 

 

 

 

 

/*
 * (c) Copyright 2018 - 2020 Visa. All Rights Reserved.**
 *
 * NOTICE: The software and accompanying information and documentation (together, the “Software”) remain the property of and are proprietary to Visa and its suppliers and affiliates. The Software remains protected by intellectual property rights and may be covered by U.S. and foreign patents or patent applications. The Software is licensed and not sold.*
 *
 *  By accessing the Software you are agreeing to Visa's terms of use (developer.visa.com/terms) and privacy policy (developer.visa.com/privacy).In addition, all permissible uses of the Software must be in support of Visa products, programs and services provided through the Visa Developer Program (VDP) platform only (developer.visa.com). **THE SOFTWARE AND ANY ASSOCIATED INFORMATION OR DOCUMENTATION IS PROVIDED ON AN “AS IS,” “AS AVAILABLE,” “WITH ALL FAULTS” BASIS WITHOUT WARRANTY OR  CONDITION OF ANY KIND. YOUR USE IS AT YOUR OWN RISK.** All brand names are the property of their respective owners, used for identification purposes only, and do not imply product endorsement or affiliation with Visa. Any links to third party sites are for your information only and equally  do not constitute a Visa endorsement. Visa has no insight into and control over third party content and code and disclaims all liability for any such components, including continued availability and functionality. Benefits depend on implementation details and business factors and coding steps shown are exemplary only and do not reflect all necessary elements for the described capabilities. Capabilities and features are subject to Visa’s terms and conditions and may require development,implementation and resources by you based on your business and operational details. Please refer to the specific API documentation for details on the requirements, eligibility and geographic availability.*
 *
 * This Software includes programs, concepts and details under continuing development by Visa. Any Visa features,functionality, implementation, branding, and schedules may be amended, updated or canceled at Visa’s discretion.The timing of widespread availability of programs and functionality is also subject to a number of factors outside Visa’s control,including but not limited to deployment of necessary infrastructure by issuers, acquirers, merchants and mobile device manufacturers.*
 *
 */

import javax.net.ssl.HttpsURLConnection;
import javax.net.ssl.KeyManagerFactory;
import javax.net.ssl.SSLContext;
import java.io.BufferedReader;
import java.io.FileInputStream;
import java.io.InputStreamReader;
import java.net.HttpURLConnection;
import java.net.URL;
import java.nio.charset.StandardCharsets;
import java.security.KeyStore;
import java.util.Base64;

public class Helloworld {

    public static void main(String[] args) throws Exception {

        System.out.println("START Sample Code for Two-Way (Mutual) SSL");
        URL url = new URL("https://sandbox.api.visa.com/vdp/helloworld");

        HttpURLConnection con = (HttpURLConnection) url.openConnection();

        // THIS IS EXAMPLE ONLY how will cert and key look like
        // keystorePath = "visa.jks"
        // keystorePassword = "password"

        String keystorePath = "<YOUR JAVA KEYSTORE PATH>";
        String keystorePassword = "<YOUR KEYSTORE PASSWORD>";
        // Make a KeyStore from the PKCS-12 file
        KeyStore ks = KeyStore.getInstance("PKCS12");
        try (FileInputStream fis = new FileInputStream(keystorePath)) {
            ks.load(fis, keystorePassword.toCharArray());
        }

        // Make a KeyManagerFactory from the KeyStore
        KeyManagerFactory kmf = KeyManagerFactory.getInstance("SunX509");
        kmf.init(ks, keystorePassword.toCharArray());

        // Now make an SSL Context with our Key Manager and the default Trust Manager
        SSLContext sslContext = SSLContext.getInstance("TLS");
        sslContext.init(kmf.getKeyManagers(), null, null);
        if (con instanceof HttpsURLConnection) {
            ((HttpsURLConnection) con).setSSLSocketFactory(sslContext.getSocketFactory());
        }

        con.setRequestMethod("GET");
        con.setRequestProperty("Content-Type", "application/json");
        con.setRequestProperty("Accept", "application/json");

        // THIS IS EXAMPLE ONLY how will user_id and password look like
        // userId = "1WM2TT4IHPXC8DQ5I3CH21n1rEBGK-Eyv_oLdzE2VZpDqRn_U";
        // password = "19JRVdej9";
        String userId = "<YOUR USER ID>";
        String password = "<YOUR PASSWORD>";

        String auth = userId + ":" + password;
        byte[] encodedAuth = Base64.getEncoder().encode(auth.getBytes(StandardCharsets.UTF_8));
        String authHeaderValue = "Basic " + new String(encodedAuth);
        con.setRequestProperty("Authorization", authHeaderValue);

        int status = con.getResponseCode();
        System.out.println("Http Status: " + status);

        BufferedReader in;
        if (status == 200) {
            in = new BufferedReader(new InputStreamReader(con.getInputStream()));
        } else {
            in = new BufferedReader(new InputStreamReader(con.getErrorStream()));
            System.out.println("Two-Way (Mutual) SSL test failed");
        }
        String response;
        StringBuffer content = new StringBuffer();
        while ((response = in.readLine()) != null) {
            content.append(response);
        }
        in.close();
        con.disconnect();

        System.out.println(content.toString());
        System.out.println("END Sample Code for Two-Way (Mutual) SSL");
    }
}

 

 

 

 

 

 

 

 

 

Step 5 - Compile Your Code 

 

  • Click the Run the Remove button in the gutter and select Run 'Helloworld.main()' in the popup. The IDE starts compiling your code.  When the compilation is complete, the Run tool window opens at the bottom of the screen.

java9.png

 

 

Want more? Join the Visa Developer Community to get alerts on the latest tutorials, guides and new developer resources. Stay tuned for more in the series. 

 

Written by: @shameem@jmedlen, & @mprsic 

 

Comments
agent_techhub
Helper

Hello @shameem, thank you for the great tutorial, first of all! For me, in particular, it was really helpful.

However, in my case, I had to do one more operation, "f)", during the keystore preparation. I had to explicitly convert it to PKCS12, as was recommended by Java's keytool utility. On the operation "e)" you've mention to list the content on newly created .jks. The listing ends with the following message:

Warning:
The JKS keystore uses a proprietary format. It is recommended to migrate to PKCS12 which is an industry standard format using "keytool -importkeystore -srckeystore visaAPI_keyAndCertBundle.jks -destkeystore visaAPI_keyAndCertBundle.jks -deststoretype pkcs12"

Screen Shot 2021-10-27 at 19.36.49.png

I didn't pay attention to that at first and proceed with the next steps. And when I tried to do my first request, I get the following exception:

DerInputStream.getLength(): lengthTag=109, too big.

and here is a begin of the stacktrace:

19:24:47,436 INFO VisaService:215 [pool-4-thread-3] - VISA API request thrown the exception
java.io.IOException: DerInputStream.getLength(): lengthTag=109, too big.
at sun.security.util.DerInputStream.getLength(DerInputStream.java:599) ~[na:1.8.0_181]
at sun.security.util.DerValue.init(DerValue.java:391) ~[na:1.8.0_181]
at sun.security.util.DerValue.<init>(DerValue.java:332) ~[na:1.8.0_181]
at sun.security.util.DerValue.<init>(DerValue.java:345) ~[na:1.8.0_181]
at sun.security.pkcs12.PKCS12KeyStore.engineLoad(PKCS12KeyStore.java:1938) ~[na:1.8.0_181]
at java.security.KeyStore.load(KeyStore.java:1445) ~[na:1.8.0_181]

After some tries and thoughts, I've run the command, recommended by keytool and - voila, it started to work!

Could you, please, explain it somehow?

I have installed Java 1.8 and working under macOS 10.13

Thank you in advance!

shameem
Visa Employee

Hi @agent_techhub ,

 

Thank you for trying out the "How to run Java Sample Code using the Hello World API and Mutual SSL".

We are glad to hear that the tutorial was helpful to get started.

 

I can see that you are using Java version 1.8.0 and this created the Java Keystore in the Java Proprietary format by default as compare to the newest version.

 

We have updated the article accordingly to ensure the Keystore is created in PKCS12 format (which is the industry standard format).

 

Let us know if you have any further question.

Thank you.