Hi,
Trying to implement Alias Directory Service: alias-directory-service
Below 2 endpoint requests:
1) Get All Payment Credentials
2) Update Alias Status
First one, executing successfully:
{
"errorCode": "LDS-30002",
"errorMessages": [
"Alias not found"
]
}
But second one failing:
{
"responseStatus": {
"status": 401,
"code": "9159",
"severity": "ERROR",
"message": "Token Validation Failed",
"info": ""
}
}
Here is the full working C# code:
internal class Program
{
private const string KeyId = "5a2d00d1-fdbf-45da-b1d4-b2875706002d";
private const string PrivateKeyDir = @"C:\Private\Projects\Visa Alias\Creds\MLE\Generated by Visa\mle_private_key.pem";
private const string VisaPublicKeyDir = @"C:\Private\Projects\Visa Alias\Creds\MLE\Generated by Visa\server_cert.pem";
private const string SharedSecret = "kGx@3Y4gc+XN4Y7Oc+ht+USm0rNUerxeHWsBx2s@";
private const string QueryString = "apikey=ZYY182UVZ18Q348BMGXK21xm_qLMrP01vxVbTnovsmCWI-NJc";
private const string BaseUrl = "https://sandbox.api.visa.com/aliasdirectory";
private static RSA _rsa = null!;
public static async Task Main()
{
var cert = await File.ReadAllTextAsync(PrivateKeyDir);
_rsa = RSA.Create();
_rsa.ImportFromPem(cert);
await GetAllPaymentCredentials();
Console.WriteLine("\n-------------------------------------------------------------------------------------------------------------------------------\n");
await UpdateAliasStatus();
}
private static string GetXPayToken(string resourcePath, string? payload = null)
{
var timestamp = DateTimeOffset.Now.ToUnixTimeSeconds();
var message = timestamp + resourcePath + QueryString + payload;
using var hmac = new HMACSHA256(Encoding.UTF8.GetBytes(SharedSecret));
var hashBytes = hmac.ComputeHash(Encoding.UTF8.GetBytes(message));
var hash = Convert.ToHexString(hashBytes).ToLowerInvariant();
var token = "xv2:" + timestamp + ":" + hash;
Console.WriteLine($"\nx-pay-token:\n{token}");
return token.Trim();
}
private static async Task GetAllPaymentCredentials()
{
var resourcePath = "v1/aliases/e336c8c8-2945-4be3-af3e-951ec2d01219/paymentCredentials";
var token = GetXPayToken(resourcePath);
using var client = new HttpClient();
client.DefaultRequestHeaders.Add("x-pay-token", token);
client.DefaultRequestHeaders.Add("keyId", KeyId);
var bar = await client.GetAsync($"{BaseUrl}/{resourcePath}?{QueryString}");
var contentString = await bar.Content.ReadAsStringAsync();
Console.WriteLine($"\nencoded-response:\n{contentString}");
var content = JsonSerializer.Deserialize<Root>(contentString);
var decoded = JWT.Decode(content.EncData, _rsa, JweAlgorithm.RSA_OAEP_256, JweEncryption.A128GCM);
Console.WriteLine($"\ndecoded-response:\n{decoded}");
}
private static async Task UpdateAliasStatus()
{
const string body = "{\"status\":\"ACTIVE\"}";
var cert = X509CertificateLoader.LoadCertificateFromFile(VisaPublicKeyDir);
long timeStamp = DateTimeOffset.Now.ToUnixTimeSeconds();
var header = new Dictionary<string, object>
{
{ "kid", KeyId },
{ "iat", timeStamp }
};
var encoded = JWT.Encode(body, cert.GetRSAPublicKey(), JweAlgorithm.RSA_OAEP_256, JweEncryption.A128GCM, null, header);
Console.WriteLine($"encoded-request:\n{encoded}");
var resourcePath = "v1/aliases/e336c8c8-2945-4be3-af3e-951ec2d01219/status";
var token = GetXPayToken(resourcePath, body);
using var client = new HttpClient();
client.DefaultRequestHeaders.Add("x-pay-token", token);
client.DefaultRequestHeaders.Add("keyId", KeyId);
var bodyJson = JsonSerializer.Serialize(new Root { EncData = encoded });
var stringContent = new StringContent(bodyJson, Encoding.UTF8, "application/json");
var bar = await client.PutAsync($"{BaseUrl}/{resourcePath}?{QueryString}", stringContent);
var foo = await bar.Content.ReadAsStringAsync();
Console.WriteLine($"\nencoded-response:\n{foo}");
var content = await bar.Content.ReadFromJsonAsync<Root>();
if (content?.EncData is not null)
{
var decoded = JWT.Decode(content.EncData, _rsa, JweAlgorithm.RSA_OAEP_256, JweEncryption.A128GCM);
Console.WriteLine($"\ndecoded-response:\n{decoded}");
}
}
}
public class Root
{
[JsonPropertyName("encData")]
public string EncData { get; set; } = null!;
}
Here are the usings
using System.Net.Http.Json;
using System.Security.Cryptography;
using System.Security.Cryptography.X509Certificates;
using System.Text;
using System.Text.Json;
using System.Text.Json.Serialization;
using Jose;
And packages
<ItemGroup>
<PackageReference Include="Microsoft.IdentityModel.Tokens" Version="8.0.1" />
<PackageReference Include="System.IdentityModel.Tokens.Jwt" Version="8.0.1" />
<PackageReference Include="System.Security.Cryptography.ProtectedData" Version="9.0.0"/>
<PackageReference Include="jose-jwt" Version="5.0.0"/>
</ItemGroup>
Hi @obank, Thank you for reaching out. An agent will get back to you as soon as possible. Until then, if any community member has information that may be helpful, feel free to reply in this thread.
Hey @obank,
Please refer to the Visa Developer Error Codes page for tips on how to fix the error.