Bonjour, je suis bloquer depuis des jours, sa ne passe pas, qu'es ce qui ne vas pas selon vous ?
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
/*
VisaAPIClient
*/
using System.IO;
using System.Net;
using System.Configuration;
using System.Security.Cryptography.X509Certificates;
using System.Security.Cryptography;
using System.Diagnostics;
using Jose;
using Newtonsoft.Json;
using Org.BouncyCastle.OpenSsl;
using Org.BouncyCastle.Security;
using Org.BouncyCastle.Crypto;
using Org.BouncyCastle.Crypto.Parameters;
using Org.BouncyCastle.X509;
namespace Visa1
{
internal class Program
{
static void Main(string[] args)
{
VisaAPIClient vsc = new VisaAPIClient();
vsc.visaUrl = "https://sandbox.api.visa.com/";
vsc.userId = "";
vsc.pwd = "";
vsc.cert = "C:\\Users\\HP\\Documents\\Visa developer\\1\\myProject_keyAndCertBundle.p12";
vsc.certpwd = "2e404b1b-8285-4933-975c-47b0d327f5ab";
vsc.mlePublicCertificate = "C:\\Users\\HP\\Documents\\Visa developer\\cert.pem";
vsc.mleKey = "9b1b532e-34c3-4886-916b-9ba4d42ff718";
vsc.mlePrivateKey = "";
vsc.apiKey = "";
vsc.sharedSecret = "NMBZQG8GVQQGZ133F01321gwjQBrfQ6zQj_hZvys6gKekH89I";
Console.WriteLine(vsc.mlePublicCertificate);
PushFundsRequest fr = new PushFundsRequest();
VisaService vs =new VisaService(vsc);
Console.WriteLine(vs.pushTransferCall(fr));
}
}
}
//--------------------------------------------------------------------
//--------------------------------------------------------------------
//--------------------------------------------------------------------
public class VisaService
{
public VisaAPIClient visaAPIClient;
public VisaService(VisaAPIClient visaApiClient)
{
this.visaAPIClient = visaApiClient;
}
private string GetFormatUTC()
{
return DateTime.UtcNow.ToString("yyyy-MM-ddTHH:mm:ss");
}
public string pushTransferCall(PushFundsRequest Corps)
{
Console.WriteLine("Executing Push fund");
String pushFundsRequest = Corps.GetSampleRequest(this.GetFormatUTC());
string baseUri = "visadirect/";
string resourcePath = "fundstransfer/v1/pushfundstransactions";
string status = this.visaAPIClient.DoMutualAuthCall(baseUri + resourcePath, "POST", "Push Funds Transaction Test", pushFundsRequest);
return status;
}
}
//--------------------------------------------------------------------
//--------------------------------------------------------------------
public class VisaAPIClient
{
public string visaUrl = "<visaURL>";
public string userId = "<user_id>";
public string pwd = "<pwd>";
public string cert = "<Certificate_path>";
public string certpwd = "<Certificate_pwd>";
public string mlePublicCertificate = "<MLE_Public_Certificate>";
public string mleKey = "<MLE_KeyId>";
public string mlePrivateKey = "<MLE_Private_Key>";
public string apiKey = "<API_KEY>";
public string sharedSecret = "<Shared_Secret>";
public string identifier = "";
private void LogRequest(string url, string requestBody)
{
Debug.WriteLine(url);
Debug.WriteLine(requestBody);
}
private void LogResponse(string info, HttpWebResponse response)
{
string responseBody;
Debug.WriteLine(info);
Console.WriteLine("Response Status: \n" + response.StatusCode);
Debug.WriteLine("Response Headers: \n" + response.Headers.ToString());
int status = (int)response.StatusCode;
using (var reader = new StreamReader(response.GetResponseStream(), ASCIIEncoding.ASCII))
{
try
{
responseBody = reader.ReadToEnd();
Debug.WriteLine("Response Body: \n" + responseBody);
}
catch (Exception e)
{
Debug.WriteLine("Some Error occurred" + e.Message);
}
}
}
private string GetBasicAuthHeader(string userId, string pwd)
{
string authString = userId + ":" + pwd;
var authStringBytes = Encoding.UTF8.GetBytes(authString);
string authHeaderString = Convert.ToBase64String(authStringBytes);
pwd = null;
return "Basic " + authHeaderString;
}
private string GetResponseBody(HttpWebResponse response)
{
string responseBody = "";
using (var reader = new StreamReader(response.GetResponseStream(), ASCIIEncoding.ASCII))
{
try
{
responseBody = reader.ReadToEnd();
Debug.WriteLine("Response Body: \n" + responseBody);
}
catch (Exception e)
{
Debug.WriteLine("Some Error occurred" + e.Message);
}
}
return responseBody;
}
public string DoMutualAuthCall(string path, string method, string testInfo, string requestBodyString, Dictionary<string, string> headers = null)
{
string requestURL = visaUrl + path;
string statusCode = "";
string responseBody = "";
int status = 200;
LogRequest(requestURL, requestBodyString);
requestBodyString = getEncryptedPayload(requestBodyString);
// Create the POST request object
HttpWebRequest request = WebRequest.Create(requestURL) as HttpWebRequest;
request.Method = method;
if (method.Equals("POST") || method.Equals("PUT"))
{
request.ContentType = "application/json";
request.Accept = "application/json";
// Load the body for the post request
var requestStringBytes = Encoding.UTF8.GetBytes(requestBodyString);
request.GetRequestStream().Write(requestStringBytes, 0, requestStringBytes.Length);
}
if (headers != null)
{
foreach (KeyValuePair<string, string> header in headers)
{
request.Headers[header.Key] = header.Value;
}
}
// Add headers
request.Headers["Authorization"] = GetBasicAuthHeader(userId, pwd);
//request.Headers["ex-correlation-id"] = GetCorrelationId();
request.Headers["keyId"] = mleKey;
// Add certificate
var certificate = new X509Certificate2(cert, certpwd, X509KeyStorageFlags.MachineKeySet);
request.ClientCertificates.Add(certificate);
Console.WriteLine("ici 1");
// en production debut
//ServicePointManager.ServerCertificateValidationCallback = delegate { return true; };
// ServicePointManager.SecurityProtocol = SecurityProtocolType.Tls12; // TLS 1.2
//ServicePointManager.ServerCertificateValidationCallback = delegate { return true; };
// en production fin
// Make the call
using (HttpWebResponse response = request.GetResponse() as HttpWebResponse)
{
responseBody = GetResponseBody(response);
LogResponse(testInfo, response);
status = (int)response.StatusCode;
statusCode = response.StatusCode.ToString();
}
Console.WriteLine("ici 2");
responseBody = getDecryptedPayload(responseBody);
Console.WriteLine("ici 3");
if (status == 202)
{
identifier = responseBody;
}
return statusCode;
}
private string GetXPayToken(string apiNameURI, string queryString, string requestBody)
{
string timestamp = GetTimestamp();
string sourceString = timestamp + apiNameURI + queryString + requestBody;
string hash = GetHash(sourceString);
string token = "xv2:" + timestamp + ":" + hash;
return token;
}
private static string GetTimestamp()
{
long timeStamp = ((long)DateTime.UtcNow.Subtract(new DateTime(1970, 1, 1, 0, 0, 0, DateTimeKind.Utc)).TotalMilliseconds) / 1000;
return timeStamp.ToString();
}
private String getEncryptedPayload(String requestBody)
{
// Assurez-vous que le chemin vers le certificat est correct
if (string.IsNullOrEmpty(mlePublicCertificate) || !File.Exists(mlePublicCertificate))
{
throw new FileNotFoundException("Le fichier de certificat n'a pas été trouvé.");
}
// Lecture du certificat
byte[] certBytes = File.ReadAllBytes(mlePublicCertificate);
Org.BouncyCastle.X509.X509Certificate cert = new X509CertificateParser().ReadCertificate(certBytes);
if (cert == null)
{
throw new InvalidOperationException("Le certificat n'a pas pu être chargé.");
}
// Récupération de la clé publique
AsymmetricKeyParameter publicKey = cert.GetPublicKey();
if (publicKey == null)
{
throw new InvalidOperationException("La clé publique n'a pas pu être extraite du certificat.");
}
// Conversion de la clé publique en paramètres RSA
RSAParameters rsaParams = DotNetUtilities.ToRSAParameters((RsaKeyParameters)publicKey);
// Création du RSA et importation des paramètres
RSA clientCertificate = RSA.Create();
clientCertificate.ImportParameters(rsaParams);
/*
Alternative (en haut)
RSA clientCertificate = new X509Certificate2(mlePublicCertificate).GetRSAPublicKey();
*/
DateTime now = DateTime.UtcNow;
DateTimeOffset dateTimeOffset = new DateTimeOffset(now);
long unixTimeMilliseconds = (long)(dateTimeOffset - new DateTime(1970, 1, 1)).TotalMilliseconds;
/*
Alternative (en haut)
long unixTimeMilliseconds = new DateTimeOffset(now).ToUnixTimeMilliseconds();
*/
IDictionary<string, object> extraHeaders = new Dictionary<string, object>{
{"kid", mleKey},{"iat",unixTimeMilliseconds}
};
string token = Jose.JWT.Encode(requestBody, clientCertificate, JweAlgorithm.RSA_OAEP_256, JweEncryption.A128GCM, null, extraHeaders);
return "{\"encData\":\"" + token + "\"}";
}
private String getDecryptedPayload(String encryptedPayload)
{
// Vérifiez si le payload est null ou vide avant de tenter la désérialisation
if (string.IsNullOrEmpty(encryptedPayload))
{
throw new ArgumentNullException("encryptedPayload", "Le payload crypté ne peut pas être null ou vide.");
}
// Désérialiser le JSON en un objet EncryptedPayload
var jsonPayload = JsonConvert.DeserializeObject<EncryptedPayload>(encryptedPayload);
if (jsonPayload == null)
{
throw new InvalidOperationException("La désérialisation du payload a échoué.");
}
// Vérifiez si encData est null ou vide avant de le décoder
if (string.IsNullOrEmpty(jsonPayload.encData))
{
throw new ArgumentNullException("encData", "Le champ 'encData' est null ou vide.");
}
// Assurez-vous que la fonction ImportPrivateKey retourne une clé valide
var privateKey = ImportPrivateKey(mlePrivateKey);
if (privateKey == null)
{
throw new InvalidOperationException("La clé privée importée est null.");
}
// Décoder le payload crypté avec la clé privée
string decryptedPayload = JWT.Decode(jsonPayload.encData, privateKey);
Console.WriteLine("Decrypted Response\n" + decryptedPayload);
return decryptedPayload;
}
private static RSA ImportPrivateKey(string privateKeyFile)
{
var pemValue = "";
try
{
pemValue = System.Text.Encoding.Default.GetString(File.ReadAllBytes(privateKeyFile));
}
catch (Exception e)
{
Console.WriteLine("Error while reading " + e.Message);
return null;
}
var pr = new PemReader(new StringReader(pemValue));
var keyPair = (AsymmetricCipherKeyPair)pr.ReadObject();
var rsaParams = DotNetUtilities.ToRSAParameters((RsaPrivateCrtKeyParameters)keyPair.Private);
var rsa = RSA.Create();
rsa.ImportParameters(rsaParams);
return rsa;
}
private string GetHash(string data)
{
// string sharedSecret = sharedSecret;
var hashString = new HMACSHA256(Encoding.ASCII.GetBytes(sharedSecret));
var hashbytes = hashString.ComputeHash(Encoding.ASCII.GetBytes(data));
string digest = String.Empty;
foreach (byte b in hashbytes)
{
digest += b.ToString("x2");
}
return digest;
}
}
public class EncryptedPayload
{
public string encData { get; set; }
}
//-----------------------------------------------------
//-----------------------------------------------------
//-----------------------------------------------------
public class PushFundsRequest
{
// Propriétés avec leurs valeurs par défaut
public string AcquirerCountryCode { get; set; } = "840";
public string AcquiringBin { get; set; } = "408999";
public string Amount { get; set; } = "124.05";
public string BusinessApplicationId { get; set; } = "AA";
public string LocalTransactionDateTime { get; set; } = "";
public string MerchantCategoryCode { get; set; } = "6012";
public string RecipientName { get; set; } = "rohan";
public string RecipientPrimaryAccountNumber { get; set; } = "4957030420210496";
public string RetrievalReferenceNumber { get; set; } = "412770451018";
public string SenderAccountNumber { get; set; } = "4653459515756154";
public string SenderAddress { get; set; } = "901 Metro Center Blvd";
public string SenderCity { get; set; } = "Foster City";
public string SenderCountryCode { get; set; } = "124";
public string SenderName { get; set; } = "Mohammed Qasim";
public string SenderReference { get; set; } = "";
public string SenderStateCode { get; set; } = "CA";
public string SourceOfFundsCode { get; set; } = "05";
public string SystemsTraceAuditNumber { get; set; } = "451018";
public string TransactionCurrencyCode { get; set; } = "USD";
public string TransactionIdentifier { get; set; } = "381228649430015";
public string SettlementServiceIndicator { get; set; } = "9";
// Propriétés supplémentaires
public string CardAcceptorAddressCountry { get; set; } = "USA";
public string CardAcceptorAddressCounty { get; set; } = "San Mateo";
public string CardAcceptorAddressState { get; set; } = "CA";
public string CardAcceptorAddressZipCode { get; set; } = "94404";
public string CardAcceptorIdCode { get; set; } = "CA-IDCode-77765";
public string CardAcceptorName { get; set; } = "Visa Inc. USA-Foster City";
public string CardAcceptorTerminalId { get; set; } = "TID-9999";
public string PointOfServiceMotoECIIndicator { get; set; } = "0";
public string PointOfServicePanEntryMode { get; set; } = "90";
public string PointOfServicePosConditionCode { get; set; } = "00";
public string ColombiaNationalServiceCountryCodeNationalService { get; set; } = "170";
public string ColombiaNationalServiceNationalReimbursementFee { get; set; } = "20.00";
public string ColombiaNationalServiceNationalNetMiscAmountType { get; set; } = "A";
public string ColombiaNationalServiceNationalNetReimbursementFeeBaseAmount { get; set; } = "20.00";
public string ColombiaNationalServiceNationalNetMiscAmount { get; set; } = "10.00";
public string ColombiaNationalServiceAddValueTaxReturn { get; set; } = "10.00";
public string ColombiaNationalServiceTaxAmountConsumption { get; set; } = "10.00";
public string ColombiaNationalServiceAddValueTaxAmount { get; set; } = "10.00";
public string ColombiaNationalServiceCostTransactionIndicator { get; set; } = "0";
public string ColombiaNationalServiceEmvTransactionIndicator { get; set; } = "1";
public string ColombiaNationalServiceNationalChargebackReason { get; set; } = "11";
// Méthode pour obtenir la chaîne JSON avec les valeurs des propriétés
public string GetSampleRequest(string strDate)
{
return "{" +
"\"acquirerCountryCode\": \"" + AcquirerCountryCode + "\"," +
"\"acquiringBin\": \"" + AcquiringBin + "\"," +
"\"amount\": \"" + Amount + "\"," +
"\"businessApplicationId\": \"" + BusinessApplicationId + "\"," +
"\"cardAcceptor\": {" +
"\"address\": {" +
"\"country\": \"" + CardAcceptorAddressCountry + "\"," +
"\"county\": \"" + CardAcceptorAddressCounty + "\"," +
"\"state\": \"" + CardAcceptorAddressState + "\"," +
"\"zipCode\": \"" + CardAcceptorAddressZipCode + "\"" +
"}," +
"\"idCode\": \"" + CardAcceptorIdCode + "\"," +
"\"name\": \"" + CardAcceptorName + "\"," +
"\"terminalId\": \"" + CardAcceptorTerminalId + "\"" +
"}," +
"\"localTransactionDateTime\": \"" + strDate + "\"," +
"\"merchantCategoryCode\": \"" + MerchantCategoryCode + "\"," +
"\"pointOfServiceData\": {" +
"\"motoECIIndicator\": \"" + PointOfServiceMotoECIIndicator + "\"," +
"\"panEntryMode\": \"" + PointOfServicePanEntryMode + "\"," +
"\"posConditionCode\": \"" + PointOfServicePosConditionCode + "\"" +
"}," +
"\"recipientName\": \"" + RecipientName + "\"," +
"\"recipientPrimaryAccountNumber\": \"" + RecipientPrimaryAccountNumber + "\"," +
"\"retrievalReferenceNumber\": \"" + RetrievalReferenceNumber + "\"," +
"\"senderAccountNumber\": \"" + SenderAccountNumber + "\"," +
"\"senderAddress\": \"" + SenderAddress + "\"," +
"\"senderCity\": \"" + SenderCity + "\"," +
"\"senderCountryCode\": \"" + SenderCountryCode + "\"," +
"\"senderName\": \"" + SenderName + "\"," +
"\"senderReference\": \"" + SenderReference + "\"," +
"\"senderStateCode\": \"" + SenderStateCode + "\"," +
"\"sourceOfFundsCode\": \"" + SourceOfFundsCode + "\"," +
"\"systemsTraceAuditNumber\": \"" + SystemsTraceAuditNumber + "\"," +
"\"transactionCurrencyCode\": \"" + TransactionCurrencyCode + "\"," +
"\"transactionIdentifier\": \"" + TransactionIdentifier + "\"," +
"\"settlementServiceIndicator\": \"" + SettlementServiceIndicator + "\"," +
"\"colombiaNationalServiceData\": {" +
"\"countryCodeNationalService\": \"" + ColombiaNationalServiceCountryCodeNationalService + "\"," +
"\"nationalReimbursementFee\": \"" + ColombiaNationalServiceNationalReimbursementFee + "\"," +
"\"nationalNetMiscAmountType\": \"" + ColombiaNationalServiceNationalNetMiscAmountType + "\"," +
"\"nationalNetReimbursementFeeBaseAmount\": \"" + ColombiaNationalServiceNationalNetReimbursementFeeBaseAmount + "\"," +
"\"nationalNetMiscAmount\": \"" + ColombiaNationalServiceNationalNetMiscAmount + "\"," +
"\"addValueTaxReturn\": \"" + ColombiaNationalServiceAddValueTaxReturn + "\"," +
"\"taxAmountConsumption\": \"" + ColombiaNationalServiceTaxAmountConsumption + "\"," +
"\"addValueTaxAmount\": \"" + ColombiaNationalServiceAddValueTaxAmount + "\"," +
"\"costTransactionIndicator\": \"" + ColombiaNationalServiceCostTransactionIndicator + "\"," +
"\"emvTransactionIndicator\": \"" + ColombiaNationalServiceEmvTransactionIndicator + "\"," +
"\"nationalChargebackReason\": \"" + ColombiaNationalServiceNationalChargebackReason + "\"" +
"}" +
"}";
}
}
//-----------------------------------------------------
//-----------------------------------------------------
//-----------------------------------------------------
Hi @Joel2, Thank you for reaching out. An agent will get back to you as soon as possible. Until then, if any community member knows a solution, feel free to reply in this thread.
Hey @Joel2,
I understand you're encountering difficulties with your Visa API integration and have been stuck for several days. Let's work through this together to identify and resolve the issues.
1. Certificate and Key Management:
- Certificate Path: Ensure that the path to your certificate (`myProject_keyAndCertBundle.p12`) is correct and accessible.
- Certificate Password: Verify that the certificate password (`certpwd`) is accurate.
2. API Credentials:
- User ID and Password: Confirm that your `userId` and `pwd` are correctly set with your Visa Developer credentials.
- API Key and Shared Secret: Ensure that `apiKey` and `sharedSecret` are correctly assigned. These should match the credentials provided in your Visa Developer project.
3. Mutual SSL Authentication:
- Certificate Loading: Make sure your application correctly loads the client certificate for mutual SSL authentication.
- TLS Version: Ensure that your application uses TLS 1.2 or higher for secure communication.
4. Endpoint Configuration:
- Visa URL: Verify that `visaUrl` is set to the correct endpoint. For sandbox testing, it should be `https://sandbox.api.visa.com/`.
- Resource Path: Ensure that the resource path (`visadirect/fundstransfer/v1/pushfundstransactions`) is correct and matches the API documentation.
5. Logging and Error Handling:
- Detailed Logging: Implement detailed logging to capture request and response details. This will help in identifying specific points of failure.
- Error Messages: Pay close attention to error messages returned by the API, as they can provide insights into what might be going wrong.
6. Sample Code Reference:
Refer to the Visa Developer Community’s guide on running the Hello World API with X-Pay-Token using Postman for a step-by-step example.
7. Community Support:
If issues persist, consider reaching out to the Visa Developer Community forums or support channels with specific error messages and logs. This will enable community members and support staff to provide more targeted assistance. Here's a link to our Visa Developer Cause/Resolution page.
By systematically verifying each of these areas, you should be able to identify and resolve the issues you're facing. If you need further assistance, please provide specific error messages or logs, and I’ll be happy to help.
Thank you for your responses. I will take the time to list all the issues I am encountering.
I am using the **Visa Direct C# SDK**, but my main problem is configuring the necessary elements to make the API work. Here are the required parameters:
public string visaUrl = "<visaURL>";
public string userId = "<user_id>";
public string pwd = "<pwd>";
public string cert = "<Certificate_path>";
public string certpwd = "<Certificate_pwd>";
public string mlePublicCertificate = "<MLE_Public_Certificate>";
public string mleKey = "<MLE_KeyId>";
public string mlePrivateKey = "<MLE_Private_Key>";
public string apiKey = "<API_KEY>";
public string sharedSecret = "<Shared_Secret>";
public string identifier = "";
### Issues encountered:
1️⃣ **Obtaining `userId` and `pwd`**
I can't find these details in the Visa Developer console. I have the impression that business authentication is required before accessing them. Can you confirm this?
2️⃣ **Setting up the certificate (`cert` and `certpwd`)**
I don't clearly understand how to obtain these elements. It seems that some command-line operations are required on a downloaded certificate, but the process is unclear to me. Which files should be used exactly?
3️⃣ **Retrieving `apiKey` and `sharedSecret`**
I have searched everywhere in the Visa Developer console, but I can’t find my `API_KEY`. Where is it supposed to appear? Is there an additional step to activate it?
Thanks in advance for your help!
Hey @Joel2,
Let's address each of the issues you are encountering with configuring the necessary elements for the Visa Direct C# SDK:
Issue 1: Obtaining `userId` and `pwd`
The `userId` and `pwd` are credentials used for mutual SSL authentication. These are typically your Visa Developer project credentials.
- userId: This is usually the username or ID provided when you registered your project on the Visa Developer platform.
- pwd: This is the password associated with the `userId`.
To obtain these details:
1. Log in to your Visa Developer account.
2. Navigate to your project.
3. Under the "Credentials" tab, you should find the `userId` and `pwd`.
If these details are not visible, ensure that your project has been properly set up and that you have the necessary permissions. Business authentication might be required for access to certain APIs.
Issue 2: Setting up the certificate (`cert` and `certpwd`)
The certificate (`cert`) and the certificate password (`certpwd`) are part of the mutual SSL authentication process. Here’s how you can obtain and set them up:
1. Download the Certificate:
- Go to your Visa Developer project.
- Under the "Credentials" tab, there should be an option to download your certificate. This file is usually in `.p12` or `.pem` format.
2. Convert the Certificate (if necessary):
- If you have a `.p12` file, you may need to convert it to `.pem` format using OpenSSL.
- Example command to convert `.p12` to `.pem`:
```sh
openssl pkcs12 -in your-certificate-file.p12 -out cert.pem -nodes
```
3. Set the Certificate Path and Password:
- The `cert` should be the path to your `.pem` file.
- The `certpwd` is the password you set when you downloaded or converted the certificate.
Issue 3: Retrieving `apiKey` and `sharedSecret`
The `apiKey` and `sharedSecret` are essential for generating the `X-Pay-Token`. Here’s how to find them:
1. API Key:
- Log in to your Visa Developer account.
- Navigate to your project.
- Under the "Credentials" tab, you should see the `apiKey`.
2. Shared Secret:
- The `sharedSecret` is also found in the "Credentials" tab, typically alongside the `apiKey`.
If you cannot find these, ensure that your project is fully set up and that you have the necessary permissions to view these credentials.
Here is an example of how you might configure these parameters in your C# application:
```csharp
// START
public class VisaConfig
{
public string VisaUrl { get; set; } = "<visaURL>";
public string UserId { get; set; } = "<user_id>";
public string Pwd { get; set; } = "<pwd>";
public string Cert { get; set; } = "<Certificate_path>";
public string CertPwd { get; set; } = "<Certificate_pwd>";
public string MlePublicCertificate { get; set; } = "<MLE_Public_Certificate>";
public string MleKey { get; set; } = "<MLE_KeyId>";
public string MlePrivateKey { get; set; } = "<MLE_Private_Key>";
public string ApiKey { get; set; } = "<API_KEY>";
public string SharedSecret { get; set; } = "<Shared_Secret>";
public string Identifier { get; set; } = "";
}
// END
```