I'm trying to reach https://sandbox.api.visa.com/vcpe/v2/pan/enrollment but I'm getting a 400 error with the message "Expected input credential was not present". I'm able to reach the helloworld endpoint so my certs should be correct. I'm also using MLE for my payload.
Here is the response:
DEBUG:urllib3.connectionpool:Starting new HTTPS connection (1): sandbox.api.visa.com:443
DEBUG:urllib3.connectionpool:https://sandbox.api.visa.com:443 "POST /vcpe/v2/pan/enrollment HTTP/1.1" 400 130
HEADERS: {'Server': 'nginx', 'Date': 'Fri, 17 Nov 2023 18:26:43 GMT', 'Content-Type': 'application/json;charset=UTF-8', 'Content-Length': '130', 'Connection': 'keep-alive', 'X-SERVED-BY': '-54d479d6g9', 'X-CORRELATION-ID': '1700245603_779_1751905695_-54d479d6g9_VDP_WS', 'X-ERROR-ORIGIN': '9200', 'X-APP-STATUS': '400', 'X-Frame-Options': 'SAMEORIGIN', 'X-XSS-Protection': '0', 'X-Content-Type-Options': 'nosniff', 'Strict-Transport-Security': 'max-age=31536000;includeSubdomains', 'Cache-Control': 'no-cache, no-store, must-revalidate', 'Pragma': 'no-cache', 'Expires': '-1', 'Content-Security-Policy-Report-Only': "default-src 'self' https://*.v.me https://*.visa.com;script-src 'self' 'unsafe-inline' 'unsafe-eval' https://*.visa.com https://*.v.me;img-src 'self' https://*.v.me https://*.visa.com https://*.unica.com https://ad.doubleclick.net;style-src 'self' 'unsafe-inline' https://*.visa.com;object-src https://*.v.me https://*.visa.com data:;report-uri /logging/logCSPReport;", 'X-Content-Security-Policy-Report-Only': "default-src 'self' https://*.v.me https://*.visa.com;script-src 'self' 'unsafe-inline' 'unsafe-eval' https://*.visa.com https://*.v.me;img-src 'self' https://*.v.me https://*.visa.com https://*.unica.com https://ad.doubleclick.net;style-src 'self' 'unsafe-inline' https://*.visa.com;object-src https://*.v.me https://*.visa.com data:;report-uri /logging/logCSPReport;", 'X-WebKit-CSP-Report-Only': "default-src 'self' https://*.v.me https://*.visa.com;script-src 'self' 'unsafe-inline' 'unsafe-eval' https://*.visa.com https://*.v.me;img-src 'self' https://*.v.me https://*.visa.com https://*.unica.com https://ad.doubleclick.net;style-src 'self' 'unsafe-inline' https://*.visa.com;object-src https://*.v.me https://*.visa.com data:;report-uri /logging/logCSPReport;"}
{'responseStatus': {'status': 400, 'code': '9125', 'severity': 'ERROR', 'message': 'Expected input credential was not present', 'info': ''}}
And this is my code for reference:
import requests
import logging
import json
import datetime
from ast import literal_eval
import time
from jwcrypto import jwk, jwe
DEBUG = True
print(datetime.datetime.now())
date = datetime.datetime.now().strftime("%Y-%m-%dT%H:%M:%S")
user_id = 'QI*****************************'
password = 'A0R***************************'
cert = './cert.pem'
key = './key_b9fdfea0-d7cc-426a-83af-d14961390672.pem'
# MLE KEY
myKey_ID = 'c7d2524f-2771-4ec6-843a-feb7a35e474e'
server_cert = './MLE_keys/server_cert_c7d2524f-2771-4ec6-843a-feb7a35e474e.pem'
private_key = './MLE_keys/key_c7d2524f-2771-4ec6-843a-feb7a35e474e.pem'
timeout = 10
def encrypt(payload, server_cert, myKey_ID):
payload = json.dumps(payload)
protected_header = {
"alg": "RSA-OAEP-256",
"enc": "A128GCM",
"kid": myKey_ID,
"iat": int(round(time.time() * 1000))
}
jwetoken = jwe.JWE(payload.encode('utf-8'),
recipient=loadPem(server_cert),
protected=protected_header)
encryptedPayload = jwetoken.serialize(compact=True)
return {"encData": encryptedPayload}
def decrypt(encPayload, private_key):
print(encPayload)
if type(encPayload) is str:
payload = json.loads(encPayload)
if encPayload.get('encData', True):
jwetoken = jwe.JWE()
jwetoken.deserialize(encPayload["encData"], key=loadPem(private_key))
return jwetoken.payload
return encPayload
def loadPem(filePath):
with open(filePath, "rb") as pemfile:
return jwk.JWK.from_pem(pemfile.read())
url = 'https://sandbox.api.visa.com/vcpe/v2/pan/enrollment'
headers = {
"Accept": "application/json",
"Content-Type": "application/json",
"X-Request-ID": "00000000000",
"key_ID": myKey_ID
}
payload = json.loads('''{
"operationType": "UPDATE",
"updateReferenceID": "00000000000"
}''')
encryptedPayload = encrypt(payload, server_cert, myKey_ID)
try:
import http.client as http_client
except ImportError:
# Python 2
import httplib as http_client
http_client.HTTPSConnection.debuglevel = 1
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 Two-Way (Mutual) SSL")
try:
response = requests.post(url,
verify = ('./DigiCertGlobalRootCA.pem'), # CA certificate pem file path
cert=(cert, key),
headers = headers,
auth=(user_id, password),
json=encryptedPayload,
timeout=timeout
)
except Exception as e:
print(e)
if DEBUG: print(response.headers)
decryptedPayload = decrypt(response.json(), private_key)
if DEBUG: print(literal_eval(decryptedPayload.decode('utf8')))
var1 = str(response.status_code)
var2 = '200'
msg = " Two-Way (Mutual) SSL test failed"
assert var1 == var2, msg
print("END Sample Code for Two-Way (Mutual) SSL\n\n")
If anyone could please let me know which input credential I'm missing, I'd greatly appreciate it!
I was using the wrong format for keyid in my header, I used "keyid" instead of "key_id" and it fixed my 400 error. However, I am now getting an internal error:
{'Server': 'nginx', 'Date': 'Fri, 17 Nov 2023 18:54:31 GMT', 'Content-Type': 'application/json;charset=UTF-8', 'Content-Length': '86', 'Connection': 'keep-alive', 'X-SERVED-BY': '-54d479d6n7', 'X-CORRELATION-ID': '1700247271_734_1291039736_-54d479d6n7_VDP_WS', 'X-APP-STATUS': '500', 'X-ERROR-ORIGIN': '9300', 'Cache-Control': 'no-cache, no-store, must-revalidate', 'X-Frame-Options': 'SAMEORIGIN', 'X-XSS-Protection': '0', 'X-Content-Type-Options': 'nosniff', 'Strict-Transport-Security': 'max-age=31536000;includeSubdomains', 'Pragma': 'no-cache', 'Expires': '-1', 'Content-Security-Policy-Report-Only': "default-src 'self' https://*.v.me https://*.visa.com;script-src 'self' 'unsafe-inline' 'unsafe-eval' https://*.visa.com https://*.v.me;img-src 'self' https://*.v.me https://*.visa.com https://*.unica.com https://ad.doubleclick.net;style-src 'self' 'unsafe-inline' https://*.visa.com;object-src https://*.v.me https://*.visa.com data:;report-uri /logging/logCSPReport;", 'X-Content-Security-Policy-Report-Only': "default-src 'self' https://*.v.me https://*.visa.com;script-src 'self' 'unsafe-inline' 'unsafe-eval' https://*.visa.com https://*.v.me;img-src 'self' https://*.v.me https://*.visa.com https://*.unica.com https://ad.doubleclick.net;style-src 'self' 'unsafe-inline' https://*.visa.com;object-src https://*.v.me https://*.visa.com data:;report-uri /logging/logCSPReport;", 'X-WebKit-CSP-Report-Only': "default-src 'self' https://*.v.me https://*.visa.com;script-src 'self' 'unsafe-inline' 'unsafe-eval' https://*.visa.com https://*.v.me;img-src 'self' https://*.v.me https://*.visa.com https://*.unica.com https://ad.doubleclick.net;style-src 'self' 'unsafe-inline' https://*.visa.com;object-src https://*.v.me https://*.visa.com data:;report-uri /logging/logCSPReport;"}
{'status': 'INTERNAL_SERVER_ERROR', 'code': 'NPPS003', 'message': 'Internal error occured'}
.Can anyone help with why I am getting this error? I don't see the code on the error codes page.
Also for reference, this is my request header:
{'User-Agent': 'python-requests/2.31.0', 'Accept-Encoding': 'gzip, deflate', 'Accept': 'application/json', 'Connection': 'keep-alive', 'Content-Type': 'application/json', 'X-Request-ID': '00000000000', 'KeyId': 'c7d2524f-2771-4ec6-843a-feb7a35e474e', 'Content-Length': '621', 'Authorization': 'Basic UUk1Q0dEVzQ5MTlQVlI2Tzk5SjYyMXNrS3FGZkpoRHdPdm1oNTZjZmlyZUJVcTFvbzpBMFJrczZnMTdBVTEybDFLMDhyMldVWlBFQWtleTY='}
Hi, @kaitlynlew. Thank you for reaching out! One of our agents is looking into this and will get back to you as soon as possible. Until then, if any community member knows a solution, please feel free to reply here.
Hi @kaitlynlew,
To investigate the error, please provide the information requested below.
1. End Point
2. Request Header
3. Request Body
4. Response Header (include the x-correlation-id)
5. Response Body
You can find the x-correlation-id in the response header.
Hi @kaitlynlew,
If you're still experiencing an error and need help, please provide the information that I requested in my previous post.
Hi @kaitlynlew,
I haven't received a reply from you so I'll take you off my contact list. Feel free to reach out if you have questions.