Re: helloworld.py - How to run Python Sample Code using the Hello World API and X-Pay-Token

Solved! Go to solution
shameem
Visa Employee

helloworld.py - How to run Python Sample Code using the Hello World API and X-Pay-Token

In this "How-to" guide we will show you how to run the “Hello World” project using Visa Hello World API and and API Key - Shared Secret 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 CyberSource Payments and click create project.

 

 

CyberSourcePaymentMethod.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 X-Pay-Token Authentication?

 

To be able to make an API call with X-Pay-Token Authentication, you need to have the following:

  1. Api Key
  2. Secret Key

CredentialsForXPayToken.png

 

How to run the Python Sample code of the “Hello World API” using PyCharm

 

 

Next, we'll show you how to run the Python sample code of the “Hello World API” using PyCharm. PyCharm is a dedicated Python Integrated Development Environment (IDE) providing a wide range of essential tools for Python developers and can be downloaded using below link:

 

https://www.jetbrains.com/pycharm/download

 

In PyCharm, 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 PyCharm

 

  • On the PyCharm Welcome Screen, click Create New Project.

2020-11-12_17-17-13.png

 

Otherwise, from the main menu, select File | New | Project

 

Step 2 - 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”

 

2020-11-12_17-18-05.png

 

 

Step 3 - Create a new file and named it “helloworld.py

 

2020-11-12_17-22-08.png

 

 

Step 4 - Copy the below sample code to the “helloworld.py” file

 

  • Install all the required dependencies when prompt.
  • Set the below parameters:

api_key = '<YOUR API KEY>'

shared_secret = '<YOUR SHARED SECRET KEY>'

 

 

 

#  *(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 datetime
import hashlib
import hmac
import json
import logging
from calendar import timegm

import requests

# DEBUG = False
DEBUG = True


# helloworld
# Sample Code for API Key- Shared Secret (X-Pay-Token)

# 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.HTTPSConnection.debuglevel = 0

# 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 API Key- Shared Secret (X-Pay-Token)")

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

url = 'https://sandbox.api.visa.com/vdp/helloworld'
headers = {}
body = {}

payload = json.loads('''{}
''')

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

api_key = '<YOUR API KEY>'
shared_secret = '<YOUR SHARED SECRET KEY>'

timeout = 10

query_string = "apiKey=" + api_key
resource_path = "helloworld"
body = ""

secret = bytes(shared_secret, 'utf-8')
timestamp = str(timegm(datetime.datetime.utcnow().timetuple()))
pre_hash_string = bytes(timestamp + resource_path + query_string + body, 'utf-8')
print(pre_hash_string)
hash_string = hmac.new(secret, pre_hash_string, digestmod=hashlib.sha256).hexdigest()
x_pay_token = 'xv2:' + timestamp + ':' + hash_string
print(x_pay_token)
headers = {'x-pay-token': x_pay_token}

try:
    response = requests.get(url + '?' + query_string,
                            headers=headers,
                            timeout=timeout
                            # if DEBUG: print (response.text)
                            )
except Exception as e:
    print(e)

if DEBUG: print(response.headers)
if DEBUG: print(response.content)

var1 = str(response.status_code)
var2 = '200'
msg = " API Key- Shared Secret (X-Pay-Token) test failed"
assert var1 == var2, msg
print("END Sample Code for API Key- Shared Secret (X-Pay-Token)\n\n")

 

 

 

 

Step 5 - Compile Your Code 

 

  • Simply right click and run “helloworld”

Screen Shot 2020-11-12 at 5.23.31 PM.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 

3 REPLIES 3
kathrynchen
Helper

Re: helloworld.py - How to run Python Sample Code using the Hello World API and X-Pay-Token

Is there Python examples of using X-Pay-Token with POST method and payload?

shameem
Visa Employee

Re: helloworld.py - How to run Python Sample Code using the Hello World API and X-Pay-Token

Hi @kathrynchen ,

 

Thank you for reaching out. You can reuse the same code for POST method. For post method, we are appending the payload. Ensure the payload formatting is the same as being sent in the request, otherwise authentication will fail.

Hope this helps.

import hashlib
import hmac
import json
from datetime import datetime

//function for creating the x-pay-token
def generate_x_pay_token(uri, query_string, secret_key, unix_timestamp, payload=None):
    pre_hash = unix_timestamp + uri + query_string
    if payload is not None:
        //if not required, simply append the payload as string
        payload = json.loads(payload)
        pre_hash += json.dump(payload)

    signature = hmac.new(secret_key.encode("utf-8"), msg=pre_hash.encode("utf-8"), digestmod=hashlib.sha256).hexdigest()
    return 'xv2:' + unix_timestamp + ':' + signature

 

Thank you

Shameem

kathrynchen
Helper

Re: helloworld.py - How to run Python Sample Code using the Hello World API and X-Pay-Token

Hi @shameem:

 

Thank you for the reply! I figured out how to query Full Bin List API using Post method. 

 

Just that for the Python 3.0, it needs some modifications from your sample script. Here is the working gen_x_pay_token() method modified from your script. The difference in Python 3.0 is that hmac constructor only takes keys that are bytes type:

 

def gen_x_pay_token(shared_secret, resource_path, utcnow, payload = None):

    timestamp = str(timegm(utcnow.timetuple()))
    
    x_pay_str = timestamp + resource_path + query_string
    
    if payload != None:    
        payload_json = json.loads(payload)
        x_pay_str += json.dumps(payload_json)
    
    # Hash
    secret = bytes(shared_secret, 'utf-8')
    pre_hash_string = bytes(x_pay_str, 'utf-8')
    hash_string = hmac.new(secret, pre_hash_string, digestmod=hashlib.sha256).hexdigest()
    x_pay_token = 'xv2:' + timestamp + ':' + hash_string
    
    return x_pay_token

 

 

The above generator is tested to work for HelloWorld example:

 

api_url = "https://sandbox.api.visa.com/vdp/helloworld"
api_key = '<masked>'
shared_secret = '<masked>'
resource_path = "helloworld"
query_string = "apikey="+api_key

x_pay_token = gen_x_pay_token(shared_secret, resource_path, datetime.datetime.utcnow(), payload=None)
headers = {'x-pay-token': x_pay_token}

try:
    response = requests.get(api_url + '?' + query_string,
                            headers=headers,
                            timeout=timeout,
                            proxies=proxies
    )
except Exception as e:
    print(e)

print(response.text)

 

 

will return 

 

'{"timestamp":"2022-10-31T17:29:56","message":"helloworld"}'

 

 

 

Full Bin List example:

 

From the API reference, Full Bin List requires the following to be included in payload and header. I assume the "requestTS" value has to be matched to the timestamp used in x-pay-token but in string format:

 

{
    "requestHeader": {
        "requestTS": "<from current utc timestamp>",
        "requestMessageID": "test123"},
    "requestData": {
        "binRangeSearchIndex": 0,
        "binRangeCount": 100}
}

 

 

The following is my API call to Full Bin List by POST method:

 

 

api_url = "https://sandbox.api.visa.com/v2/binRangeDetails"
api_key = '<masked>'
shared_secret = '<masked>'
resource_path = "binRangeDetails"
query_string = "apikey="+api_key

timestamp = datetime.datetime.utcnow()
payload = {"requestHeader": {"requestTS": timestamp.strftime("%Y-%m-%dT%H:%M:%S.%f")[:-3], "requestMessageID": "full_bin_list"}, "requestData": {"binRangeSearchIndex": 0, "binRangeCount": 100}}

x_pay_token = gen_x_pay_token(shared_secret, resource_path, timestamp, payload=json.dumps(payload))
headers['x-pay-token'] = x_pay_token

try:
    response = requests.post(api_url + '?' + query_string,
                            headers=headers,
                            timeout=timeout,
                            proxies=proxies,
                            json=payload
                            )
except Exception as e:
    print(e)


print(response.text)

 

 

 

Hope this helps anyone who runs into this.