Closed viktoria-zh closed 4 years ago
@viktoria-zh, thanks for having opened this issue.
I wouldn't use DefaultRequestHeaders
, because your Authorization
header will be different for every new request you send.
Here are 3 ways of calling the Enhanced Currency Conversion Calculator (in order of preference).
Here is a .NET solution with the same tests you can run: ViktoriaZh.zip
[TestMethod]
public void TestConversionRateSummaryApi_WithOpenApiGeneratedClient()
{
// Configure the generated ApiClient to sign requests
var signingKey = AuthenticationUtils.LoadSigningKey(SigningKeyPkcs12FilePath, SigningKeyAlias, SigningKeyPassword, X509KeyStorageFlags.MachineKeySet | X509KeyStorageFlags.Exportable);
var config = Configuration.Default;
config.BasePath = BaseServicePath;
config.ApiClient.RestClient.Authenticator = new RestSharpOAuth1Authenticator(ConsumerKey, signingKey, new Uri(config.BasePath));
// Call the service
var conversionRateSummaryApi = new ConversionRateSummaryApi(Configuration.Default);
var response = conversionRateSummaryApi.GetEnhancedConversionDetailsUsingGET(
rateDate: "2020-08-07",
transCurr: "GBP",
transAmt: "100",
crdhldBillCurr: "EUR"
);
}
internal class RequestSignerHandler : HttpClientHandler
{
private readonly NetHttpClientSigner signer;
public RequestSignerHandler(string consumerKey, RSA signingKey)
{
signer = new NetHttpClientSigner(consumerKey, signingKey);
}
protected override async Task<HttpResponseMessage> SendAsync(HttpRequestMessage request, CancellationToken cancellationToken)
{
await signer.SignAsync(request);
return await base.SendAsync(request, cancellationToken);
}
}
[TestMethod]
public async Task TestConversionRateSummaryApi_WithNetHttpClientAndNetHttpClientSigner()
{
// Configure the HttpClient to sign requests
var signingKey = AuthenticationUtils.LoadSigningKey(SigningKeyPkcs12FilePath, SigningKeyAlias, SigningKeyPassword, X509KeyStorageFlags.MachineKeySet | X509KeyStorageFlags.Exportable);
var httpClient = new HttpClient(new RequestSignerHandler(ConsumerKey, signingKey)) { BaseAddress = new Uri(BaseServicePath) };
// Call the service
var uri = "summary-rates?rate_date=2020-08-07&trans_curr=GBP&trans_amt=100&crdhld_bill_curr=EUR";
var response = await httpClient.GetAsync(uri);
string responseBody = await response.Content.ReadAsStringAsync();
}
[TestMethod]
public async Task TestConversionRateSummaryApi_WithNetHttpClientAndGetAuthorizationHeader()
{
// Compute the Authorization header
var signingKey = AuthenticationUtils.LoadSigningKey(SigningKeyPkcs12FilePath, SigningKeyAlias, SigningKeyPassword, X509KeyStorageFlags.MachineKeySet | X509KeyStorageFlags.Exportable);
var uri = BaseServicePath + "summary-rates?rate_date=2020-08-07&trans_curr=GBP&trans_amt=100&crdhld_bill_curr=EUR";
var authorizationString = OAuth.GetAuthorizationHeader(uri, "GET", string.Empty, Encoding.UTF8, ConsumerKey, signingKey);
// Manually add the Authorization header
var httpClient = new HttpClient();
httpClient.DefaultRequestHeaders.Authorization = new AuthenticationHeaderValue("OAuth", authorizationString.Replace("OAuth ", string.Empty));
// Call the service
var response = await httpClient.GetAsync(uri);
string responseBody = await response.Content.ReadAsStringAsync();
}
Don't forget to update those before running the tests in ViktoriaZh.zip!
private const string ConsumerKey = "000000000000000000000000000000000000000000000000!000000000000000000000000000000000000000000000000";
private const string SigningKeyAlias = "replace-me!";
private const string SigningKeyPassword = "replace-me!";
private const string SigningKeyPkcs12FilePath = "./sandbox_key.p12";
private const string BaseServicePath = "https://sandbox.api.mastercard.com/enhanced/settlement/currencyrate/subscribed/";
I hope this helps.
Also, we have plans to review the set of Mastercard authentication libraries and fix small differences in encoding like the one you reported.
Hello,
I am trying to call Enhanced Currency Conversion Calculator API.
My code:
var uri = "https://sandbox.api.mastercard.com/enhanced/settlement/currencyrate/subscribed/summary-rates?rate_date=2020-08-07&trans_curr=GBP&trans_amt=100&crdhld_bill_curr=EUR"; var authHeader= OAuth.GetAuthorizationHeader(uri, "GET", string.Empty,, Encoding.UTF8, consumerKey, signingKey); var httpClient = new HttpClient(); httpClient.DefaultRequestHeaders.Authorization = AuthenticationHeaderValue.Parse(authHeader);
My generated base string: GET&https%3A%2F%2Fsandbox.api.mastercard.com%2Fenhanced%2Fsettlement%2Fcurrencyrate%2Fsubscribed%2Fsummary-rates&crdhld_bill_curr%3DEUR%26oauth_body_hash%3D47DEQpj8HBSa%2B%2FTImW%2B5JCeuQeRkm5NMpJWZG3hSuFU%3D%26oauth_consumer_key%3DzFlC3IqZ-f7lNmfFyVsC8xDGdE1zIPcMMWPbCqGy50ba7ea4%21499f2d41e5d540aaa8ae8ddf6bef610e0000000000000000%26oauth_nonce%3D5ee0d0cf9d5f710c%26oauth_signature_method%3DRSA-SHA256%26oauth_timestamp%3D1596795752%26oauth_version%3D1.0%26rate_date%3D2020-08-07%26trans_amt%3D100%26trans_curr%3DGBP
Acceptable signature base string from server error response: GET&https%3A%2F%2Fsandbox.api.mastercard.com%2Fenhanced%2Fsettlement%2Fcurrencyrate%2Fsubscribed%2Fsummary-rates&crdhld_bill_curr%3DEUR%26oauth_body_hash%3D47DEQpj8HBSa%252B%252FTImW%252B5JCeuQeRkm5NMpJWZG3hSuFU%253D%26oauth_consumer_key%3DzFlC3IqZ-f7lNmfFyVsC8xDGdE1zIPcMMWPbCqGy50ba7ea4%2521499f2d41e5d540aaa8ae8ddf6bef610e0000000000000000%26oauth_nonce%3D5ee0d0cf9d5f710c%26oauth_signature_method%3DRSA-SHA256%26oauth_timestamp%3D1596795752%26oauth_version%3D1.0%26rate_date%3D2020-08-07%26trans_amt%3D100%26trans_curr%3DGBP
Body hash of empty string is 47DEQpj8HBSa+/TImW+5JCeuQeRkm5NMpJWZG3hSuFU=. In my generated base string +/ encoded as %2B%2F, when in acceptable string from server it is %252B%252F. It seems that body hash should be encoded twice to be accepted. The same for the customer key.
How could I update my code to match accepted signature?