How to run Python Sample Code for MLE

Highlighted
Visa Employee

How to run Python Sample Code for MLE

In this “How-to” guide, we will show you how to test MLE (Message Level Encryption) enabled APIs using Python.

 

Important Links:

 

Enable MLE for the API(s) you are interested in.

 

Login to your Visa Developer Dashboard and go to your project, you should see something like this:

 

2020-11-11_09-45-12.png

 

Enable the APIs for which MLE needs to be active in VDP by toggling the API for which MLE needs to be enforced.

 

In this example, we will enable MLE for Funds Transfer API And Query API as below:

 

2020-11-11_09-46-41.png

 

 

How to get credentials

 

You can obtain your project credentials by browsing the left side navigation menu of your project and click on “Credentials”.

 

2020-11-11_11-25-10.png

 

Next step we will create a Key-ID by clicking on the Generate Key-ID button.

 

2020-11-11_11-29-02.png

 

After you have clicked the button, you will get Key-ID. Copy the Key-ID for your reference.

The Key-ID will look like this: 41d9f2a1-xxxx-4xxx-b40c-a0480c2xxxxx

 

2020-11-11_11-30-49.png

 

The next step is to add a CSR (Certificate Signing Request). Click on the link "Add CSR" .   

 

You will be prompt to submit a Certificate Signing Request. 

 

2020-11-11_11-32-46.png

 

We have option to Generate a CSR for me (default) or submit your own. In this example we will use the Generate a CSR for me (default) and Click Confirm button.

 

After submitting the request, you will be prompt to download the Certificate/Copy Private Key. 

 

2020-11-11_11-34-26.png

 

After you have downloaded the private key, check the box "I confirm that I've downloaded my certificate key" and click continue. You will see the Status change to "Active".

 

 

Expand the Key-ID and you will see the Server Encryption Certificate and Client Encryption Certificate.

Download both certificates and save it.

 

2020-11-11_11-36-33.png

To be able to make an API call with MLE, you need to have the following

  • Server Encryption Certificate
  • Key-ID
  • Certificate Private Key

 

How to run Python Sample Code for MLE

 

 

Step 1 - Create a new project on PyCharm

 

  • Launch PyCharm, on the PyCharm Welcome Screen, click Create New Project.
  • In the New Project wizard, select Pure Python from the list on the left, provide the project Location and click Create. Please make sure to specify your “Project Interpreter” as Python2
  • Create a new file and named it “mle_oct.py

 

Refer to How to run Python Sample Code using the Hello World API and Mutual SSL for how to create a project with PyCharm and testing VISA APIs using Mutual SSL.

 

Step 2 - Copy the below sample code to the “mle_oct.py” file

 

  • Install all the required dependencies when prompt by PyCharm, alternatively you can use pip to install the dependencies
  • Set the below parameters:

//For Basic Auth and Mutual SSL

user_id  = 'YOUR_USER_ID'

password = 'YOUR_PASSWORD'

 

cert = 'ABSOLUTE_PATH_TO_CERTIFICATE'

key  = 'ABSOLUTE_PATH_TO_PRIVATE_KEY'

 

//For MLE

myKey_ID  = 'YOUR_KEY_ID'

server_cert = 'YOUR_SERVER_CERT'

private_key = 'YOUR_PRIVATE_KEY'

 

 

 

# -*- coding: utf-8 -*-
# !/usr/bin/python


'''
© Copyright 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.

'''

import requests
import logging
import unittest
import base64
import json
import sys
import os
import datetime
import random 
from ast import literal_eval
import os
import sys

import time

# where python
# D:\Python27\python.exe
# C:\Users\user\AppData\Local\Microsoft\WindowsApps\python.exe

# D:\Python27\Scripts
# pip install jwcrypto
from jwcrypto import jwk, jwe

__author__ = 'Visa Inc.'

DEBUG = False
#DEBUG = True

if DEBUG: print ("Python Path", os.path.dirname(sys.executable))

print("\n\n")
print ("####################################################################################")
print ("######################################### MLE ######################################")
print ("####################################################################################\n\n")


# THIS IS EXAMPLE ONLY how will user_id and password look like
# user_id = '1WM2TT4IHPXC8DQ5I3CH21n1rEBGK-Eyv_oLdzE2VZpDqRn_U'
# password = '19JRVdej9'

user_id  = 'YOUR_USER_ID'
password = 'YOUR_PASSWORD'


# THIS IS EXAMPLE ONLY how will cert and key look like
# cert = 'cert.pem'
# key = 'key_83d11ea6-a22d-4e52-b310-e0558816727d.pem'

cert = 'ABSOLUTE_PATH_TO_CERTIFICATE'
key  = 'ABSOLUTE_PATH_TO_PRIVATE_KEY'


# MLE KEY
#########
# THIS IS EXAMPLE ONLY how will myKey_ID, server_cert and private_key look like
# myKey_ID = '7f591161-6b5f-4136-80b8-2ae8a44ad9eb'
# server_cert = 'server_cert_7f591161-6b5f-4136-80b8-2ae8a44ad9eb.pem'
# private_key = 'key_7f591161-6b5f-4136-80b8-2ae8a44ad9eb.pem'

myKey_ID  = 'YOUR_KEY_ID'
server_cert = 'YOUR_SERVER_CERT'
private_key = 'YOUR_PRIVATE_KEY'


if DEBUG: print ("Key_ID", myKey_ID)
if DEBUG: print ("server_cert", server_cert)
if DEBUG: print ("private_key", private_key)

#def encrypt(self, payload):
def encrypt(payload, server_cert, myKey_ID):
    #config = Configuration()
    payload = json.dumps(payload)
    protected_header = {
            "alg": "RSA-OAEP-256",
            "enc": "A128GCM",
            #"kid": config.api_key['keyId'],
            "kid": myKey_ID,
            "iat": int(round(time.time() * 1000))
        }
    jwetoken = jwe.JWE(payload.encode('utf-8'),
                            #recipient=loadPem('server_cert_7f591161-6b5f-4136-80b8-2ae8a44ad9eb.pem'),
                            recipient=loadPem(server_cert),
                            #recipient=self.loadPem(config.encryption_public_key_path),
                            protected=protected_header)
    encryptedPayload = jwetoken.serialize(compact=True)
    return {"encData": encryptedPayload}   


#def decrypt(self, encPayload):
def decrypt(encPayload, private_key):
    print(encPayload);
    if type(encPayload) is str:
        payload = json.loads(encPayload)
    if encPayload.get('encData', True):
        #config = Configuration()
        jwetoken = jwe.JWE()
        #jwetoken.deserialize(payload["encData"], key=self.loadPem(config.decryption_private_key_path))
        #jwetoken.deserialize(encPayload["encData"], key=loadPem('key_7f591161-6b5f-4136-80b8-2ae8a44ad9eb.pem'))
        jwetoken.deserialize(encPayload["encData"], key=loadPem(private_key))
        return jwetoken.payload
    return encPayload

#def loadPem(self, filePath):
def loadPem(filePath):
    with open(filePath, "rb") as pemfile:
        return jwk.JWK.from_pem(pemfile.read())

print("\n\n")
print ("####################################################################################")
print ("##################################### END MLE ######################################")
print ("####################################################################################\n\n")

# These two lines enable debugging at httplib level (requests->urllib3->http.client)
# You will see the REQUEST, including HEADERS and DATA, and RESPONSE with HEADERS but without DATA.
# The only thing missing will be the response.body which is not logged.
try:
    import http.client as http_client
except ImportError:
    # Python 2
    import httplib as http_client
http_client.HTTPConnection.debuglevel = 1

# You must initialize logging, otherwise you'll not see debug output.
logging.basicConfig()
logging.getLogger().setLevel(logging.DEBUG)
requests_log = logging.getLogger("requests.packages.urllib3")
requests_log.setLevel(logging.DEBUG)
requests_log.propagate = True


print ("START Sample Code for Running a simple transaction using Two-Way (Mutual) SSL")

headers = { "content-type": "application/json",
            'accept': 'application/json',
            'keyId': myKey_ID
            }

timeout = 10

recipientPrimaryAccountNumber = "4957030420210496"


def datestdtojd (stddate):
    fmt='%Y-%m-%d'
    sdtdate = datetime.datetime.strptime(stddate, fmt)
    sdtdate = sdtdate.timetuple()
    jdate = str(sdtdate.tm_yday)
    if len (jdate) == 1:
        jdate = "00" + jdate
    if len (jdate) == 2:
        jdate = "0" + jdate        
    return(jdate)


date = datetime.datetime.now().strftime("%Y-%m-%dT%H:%M:%S")
if DEBUG: print(date)

systemsTraceAuditNumber = str(random.randint(100000,999999))
if DEBUG: print ("systemsTraceAuditNumber", systemsTraceAuditNumber)

def generateRetrievalReferenceNumber (date, systemsTraceAuditNumber):
    
    stddate = date.split('T')[0]
    #print(stddate)
    lastYearDigit = stddate.split('-')[0][-1]
    #print(lastYearDigit)
    jdate = datestdtojd(stddate)
    #print(jdate)
    hour = date.split('T')[1].split(':')[0]
    #print(hour)
    
    retrievalReferenceNumber = lastYearDigit + jdate + hour + systemsTraceAuditNumber
    return(retrievalReferenceNumber)

retrievalReferenceNumber = generateRetrievalReferenceNumber (date, systemsTraceAuditNumber)
if DEBUG: print (retrievalReferenceNumber)


# we will add new variable
acquiringBin = "408999"

print("\n\n")
print ("####################################################################################")
print ("######################## PUSH (OCT)  Transaction ###################################")
print ("####################################################################################\n\n")


url = 'https://sandbox.api.visa.com/visadirect/fundstransfer/v1/pushfundstransactions'

payload = json.loads('''
{
"acquirerCountryCode": "840",
"acquiringBin": "''' + acquiringBin + '''",
"amount": "124.05",
"businessApplicationId": "AA",
"cardAcceptor": {
"address": {
"country": "USA",
"county": "San Mateo",
"state": "CA",
"zipCode": "94404"
},
"idCode": "CA-IDCode-77765",
"name": "Visa Inc. USA-Foster City",
"terminalId": "TID-9999"
},
"localTransactionDateTime": "''' + date + '''",
"merchantCategoryCode": "6012",
"pointOfServiceData": {
"motoECIIndicator": "0",
"panEntryMode": "90",
"posConditionCode": "00"
},
"recipientName": "rohan",
"recipientPrimaryAccountNumber": "''' + recipientPrimaryAccountNumber + '''",
"retrievalReferenceNumber": "''' + retrievalReferenceNumber + '''",
"senderAccountNumber": "4653459515756154",
"senderAddress": "901 Metro Center Blvd",
"senderCity": "Foster City",
"senderCountryCode": "124",
"senderName": "Mohammed Qasim",
"senderReference": "",
"senderStateCode": "CA",
"sourceOfFundsCode": "05",
"systemsTraceAuditNumber": "''' + systemsTraceAuditNumber + '''",
"transactionCurrencyCode": "USD",
"settlementServiceIndicator": "9",
"colombiaNationalServiceData": {
"countryCodeNationalService": "170",
"nationalReimbursementFee": "20.00",
"nationalNetMiscAmountType": "A",
"nationalNetReimbursementFeeBaseAmount": "20.00",
"nationalNetMiscAmount": "10.00",
"addValueTaxReturn": "10.00",
"taxAmountConsumption": "10.00",
"addValueTaxAmount": "10.00",
"costTransactionIndicator": "0",
"emvTransactionIndicator": "1",
"nationalChargebackReason": "11"
}
}
''')

# we have to encrypt payload
encryptedPayload = encrypt(payload, server_cert, myKey_ID)

try:
    response = requests.post(url,
                          cert = (cert, key),
                          headers = headers,
                          auth = (user_id, password),
                          #json = payload,
                          json = encryptedPayload,
                          timeout=timeout
                          #if DEBUG: print (response.text)
 )
except Exception as e:
    print (e)


if DEBUG: print (response.json())
#decryptedPayload = decrypt(r.json())
decryptedPayload = decrypt(response.json(), private_key)

#print('hello')
data = literal_eval(decryptedPayload.decode('utf8'))
#print('hello1', )
print("Decrypted payload",data)

# It might be great to capture transactionIdentifier 
transactionIdentifier = data['transactionIdentifier']
if DEBUG: print("transactionIdentifier", transactionIdentifier)

# Capture X-CORRELATION-ID
correlation_id = response.headers.get("X-CORRELATION-ID")
print("correlation_id", correlation_id)

var1 = str(response.status_code)
if DEBUG: print("var1", var1)
var2 = '200'
msg = " PUSH (OCT) transaction failed"
assert var1 == var2, msg

print ("END Sample Code for Running a simple transaction using Two-Way (Mutual) SSL\n\n")

print("\n\n")
print ("####################################################################################")
print ("################################### QUERY API ######################################")
print ("####################################################################################\n\n")


print ("START Sample Code for Running a QUERY API\n\n")


url = 'https://sandbox.api.visa.com/visadirect/v1/transactionquery?acquiringBIN=' + str(acquiringBin) + '&transactionIdentifier=' + str(transactionIdentifier)

try:
    r = requests.get(url,
                    cert = (cert, key),
                    headers = headers,
                    auth = (user_id, password),
                    #json = payload,
                    timeout=timeout
 )
except Exception as e:
    print (e)


if DEBUG: print (r.json())

decryptedPayload_Query_API = decrypt(r.json(), private_key)

data_Query_API = literal_eval(decryptedPayload_Query_API.decode('utf8'))
print("Decrypted payload",data_Query_API)


print ("END Sample Code for Running a QUERY API\n\n")

###############################
# END second webinar changes

print("\n\n")
print ("####################################################################################")
print ("####################################### END ########################################")
print ("####################################################################################\n\n")

 

 

 

Step 4 - Compile Your Code 

 

  • Simply right click and run “mle_oct”

 

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.