I have been exploring payeezy api from last three days. I am just making a simple http web request from a C# application. I have followed all the steps mentions and correctly verified each and everything. Below is the detail per item.
API Key :- I have verified my api key its correct.
API Secret :- It is also correct.
merchant token :- It is also verified.
Nonce :- I have created cryptographically strong random number as following.
RandomNumberGenerator rng = new RNGCryptoServiceProvider();
byte[] nonceData = new byte[18];
rng.GetBytes(nonceData);
string nonce = BitConverter.ToUInt64(nonceData,0).ToString();
Timestamp :-
string timestamp = Convert.ToInt64(ts.TotalMilliseconds).ToString();
Payload :-
{"merchant_ref":"Astonishing-Sale","transaction_type":"authorize","method":"credit_card","amount":"1299","currency_code":"USD","credit_card":{"type":"visa","cardholder_name":"John Smith","card_number":"4788250000028291","exp_date":"1020","cvv":"123"}}
Then I have created HMAC as following.
private string CreateAuthorization(string data, string secret)
{
// data is in following format.
// data = apiKey + nonce + timestamp + token + payload;
secret = secret ?? "";
using (var hmacsha256 = new HMACSHA256(Encoding.UTF8.GetBytes(secret)))
{
byte[] hashdata = hmacsha256.ComputeHash(Encoding.UTF32.GetBytes(data));
return Convert.ToBase64String(hashdata);
}
}
Now I am getting hmac validation error. My generated hmac string is 64 bit while on your website under docs and sandbox its 86 bit.
Can you please assist me in this as I am stuck on this issue from last three days.
Thanks
These are the common causes for “HMAC validation Failure”:
API key and/or API secret are incorrect.
Leading or trailing spaces in the API key, API secret, merchant token.
Timestamp in the HTTP header is not in milliseconds.
Timestamp in the HTTP header does not represent EPOCH time.
Timestamp in the HTTP header is not within 5 minutes of our server time.
System time is not accurate.
Here is a sample c# code to generate HMAC:
public byte[] CalculateHMAC(string data, string secret)
{
HMAC hmacSha256 = new HMACSHA256(Encoding.UTF8.GetBytes(secret));
byte[] dataBytes = Encoding.UTF8.GetBytes(data);
byte[] hmac2Hex = hmacSha256.ComputeHash(Encoding.UTF8.GetBytes(data));
string hex = BitConverter.ToString(hmac2Hex);
hex = hex.Replace("-","").ToLower();
byte[] hexArray = Encoding.UTF8.GetBytes(hex);
return hexArray;
}
protected void Button1_Click(object sender, EventArgs e)
{
string jsonString = "{ \"merchant_ref\": \"MVC Test\", \"transaction_type\": \"authorize\", \"method\": \"credit_card\", \"amount\": \"1299\", \"currency_code\": \"USD\", \"credit_card\": { \"type\": \"visa\", \"cardholder_name\": \"Test Name\", \"card_number\": \"4005519200000004\", \"exp_date\": \"1020\", \"cvv\": \"123\" } }";
Random random = new Random();
string nonce = (random.Next(0, 1000000)).ToString();
DateTime date = DateTime.UtcNow;
DateTime epoch = new DateTime(1970, 1, 1, 0, 0, 0, 0);
TimeSpan span = (date - epoch);
string time = span.TotalSeconds.ToString();
string token = Request.Form["token"];//Merchant token
string apiKey = Request.Form["apikey"];//apikey
string apiSecret = Request.Form["apisecret"];//API secret
string hashData = apiKey+nonce+time+token+jsonString;
string base64Hash = Convert.ToBase64String(CalculateHMAC(hashData, apiSecret));
string url = "https://api-cert.payeezy.com/v1/transactions";
//begin HttpWebRequest
HttpWebRequest webRequest = (HttpWebRequest)WebRequest.Create(url);
webRequest.Method = "POST";
webRequest.Accept = "*/*";
webRequest.Headers.Add("timestamp", time);
webRequest.Headers.Add("nonce", nonce);
webRequest.Headers.Add("token", token);
webRequest.Headers.Add("apikey", apiKey);
webRequest.Headers.Add("Authorization", base64Hash );
webRequest.ContentLength = jsonString.Length;
webRequest.ContentType = "application/json";
StreamWriter writer = null;
writer = new StreamWriter(webRequest.GetRequestStream());
writer.Write(jsonString);
writer.Close();
string responseString;
try
{
using(HttpWebResponse webResponse = (HttpWebResponse)webRequest.GetResponse())
{
using (StreamReader responseStream = new StreamReader(webResponse.GetResponseStream()))
{
responseString = responseStream.ReadToEnd();
request_label.Text = "<h3>Request</h3><br />" + webRequest.Headers.ToString() + System.Web.HttpUtility.HtmlEncode(jsonString);
response_label.Text = "<h3>Response</h3><br />" + webResponse.Headers.ToString() + System.Web.HttpUtility.HtmlEncode(responseString);
}
}
}
catch (WebException ex)
{
if (ex.Response != null)
{
using (HttpWebResponse errorResponse = (HttpWebResponse)ex.Response)
{
using (StreamReader reader = new StreamReader(errorResponse.GetResponseStream()))
{
string remoteEx = reader.ReadToEnd();
error.Text = remoteEx;
}
}
}
}
}
I've been working on an integration and it's working great; maybe you can take a peek
https://github.com/clifton-io/Clifton.Payment
Specifically you'll want to look here:
https://github.com/clifton-io/Clifton.Payment/blob/cc4053b0bfe05f2453dc508e96a649fc138b973c/Clifton.Payment/Gateway/Payeezy/PayeezyGateway.cs#L66
Best of luck :)
Related
I am trying to make a call to 2checkout API. According to their documentation first I need to authenticate. All example code on their website is written in PHP.
When I try the same using C# I am getting "Hash signature could not be authenticated" message from the server.
Here is code-snipped from my code:
Encoding encoding = Encoding.UTF8;
string vendorCode = //My vendor code
string secretKey = //My secret key
byte[] secretBytes = encoding.GetBytes(secretKey);
date = DateTime.Now.ToString("yyyy-MM-dd HH:mm:ss");
string input = vendorCode.Length.ToString() + vendorCode + date.Length.ToString() + date;
using (HMACMD5 keyedHash = new HMACMD5(secretBytes))
{
byte[] hashedBytes = keyedHash.ComputeHash(encoding.GetBytes(input));
string hash = Convert.ToBase64String(hashedBytes);
using (HttpRequestMessage request = new HttpRequestMessage(HttpMethod.Get, apiUrl +
requestString))
{
request.Headers.Add("accept", "application/json");
string headerValue = "code=\"" + vendorCode + "\" date=\"" + date + "\" hash=\"" + hash + "\"";
request.Headers.Add("X-Avangate-Authentication", headerValue);
HttpResponseMessage httpResponse = await httpClient.SendAsync(request);
}
}
I am not sure what I am doing wrong. Is it the hash algorithm that I use or it is the text encoding?
I tried several variants but without any success.
I will be very grateful if someone helps me with this.
The below code block works for me. Code slightly modified as per needs on basis of the documentation https://verifone.cloud/docs/2checkout/API-Integration/Webhooks/06Instant_Payment_Notification_%2528IPN%2529/IPN-code-samples#c__0023__00a0
string secretKey = "MYSECRETKEY";
string VendorCode = "MYVENDORCODE";
string requestDateTime = DateTime.UtcNow.ToString("yyyy-MM-dd HH:mm:ss");
string plaintext = VendorCode.Length + VendorCode + requestDateTime.Length + requestDateTime;
using(HMACMD5 hmac = new HMACMD5(Encoding.ASCII.GetBytes(secretKey)))
{
byte[] hashBytes = hmac.ComputeHash(Encoding.ASCII.GetBytes(plaintext));
string signatureHash = BitConverter.ToString(hashBytes).Replace("-", "").ToLower();
using (var httpClient = new HttpClient { BaseAddress = new Uri("https://api.avangate.com/rest/6.0/") })
{
httpClient.DefaultRequestHeaders.TryAddWithoutValidation("accept", "application/json");
httpClient.DefaultRequestHeaders.TryAddWithoutValidation("X-Avangate-Authentication", $"code='{VendorCode}' date='{requestDateTime}' hash='{signatureHash}'");
// Make your requests to desired Api
}
}
I'm trying to connect to Apple's News API. When generating the signature the results all appear the same from each of the different examples. However, I keep getting this error:
{"errors":[{"code":"WRONG_SIGNATURE"}]}
Here is my c# code to generate the auth header.
public class Security
{
public static string AuthHeader(string method, string url, object content=null)
{
var apiKeyId = "<YOUR KEY HERE...>"; //we get this value from our settings file.
var apiKeySecret = "<YOUR SECRET HERE...>"; //we get this value from our settings file.
if ( string.IsNullOrEmpty(apiKeyId) || string.IsNullOrEmpty(apiKeySecret)) return string.Empty;
var encoding = new ASCIIEncoding();
var dt = DateTime.Now.ToString(Constants.DateFormat);
var canonicalRequest = string.Format("{0}{1}{2}", method, url, dt);
var key = Convert.FromBase64String(apiKeySecret);
var hmac = new HMACSHA256(key);
var hashed = hmac.ComputeHash(encoding.GetBytes(canonicalRequest));
var signature = Convert.ToBase64String(hashed);
var authorizaton = string.Format(#"HHMAC; key={0}; signature={1}; date={2}", apiKeyId, signature, dt);
return authorizaton;
}
}
Short version of Constants class
public static class Constants
{
public static readonly string ChannelId = "<YOUR CHANNEL ID HERE...>"; //again from our settings file
public static readonly string BaseUrl = "https://news-api.apple.com";
public static readonly string DateFormat = "yyyy-MM-ddTHH:mm:ssK";
}
Short version of Actions class (SendCommand is the method that performs the request)
public class Actions
{
public static string SendCommand(string action, string method)
{
var url = $"{Constants.BaseUrl}{action}";
var authheader = Security.AuthHeader(method, url, null);
var request = (HttpWebRequest)WebRequest.Create(url);
request.Method = method;
request.Timeout = 1000;
request.Headers.Add("Authorization", authheader);
request.Accept = "application/json";
request.ContentType = "application/json";
var output = string.Empty;
try
{
using (var response = request.GetResponse())
{
using (var reader = new StreamReader(response.GetResponseStream()))
output = reader.ReadToEnd();
}
}
catch (WebException e)
{
using (var reader = new StreamReader(e.Response.GetResponseStream()))
{
output = reader.ReadToEnd();
}
}
return output;
}
public static string ReadChannel()
{
var action = $"/channels/{Constants.ChannelId}";
const string method = "GET";
return SendCommand(action, method);
}
}
I'm using the ReadChannel method for testing.
I've also tried examples in php and ruby with no luck.
Any ideas how to do this correctly?
Pasted the authorization string generated from the original code on this post into fiddler and I was able to get a successful response from the Apple News API. It seems like HttpWebRequest isn't including the Authorization header correctly and submitting the same request with the property PreAuthenticate = true corrects this issue (HttpWebRequest.PreAuthenticate). Also, with a GET request the ContentType needs to be omitted so I've added a conditional statement to account for this too.
public class Actions
{
public static string SendCommand(string action, string method)
{
var url = $"{Constants.BaseUrl}{action}";
var authheader = Security.AuthHeader(method, url, null);
var request = (HttpWebRequest)WebRequest.Create(url);
request.Method = method;
request.Timeout = 1000;
request.PreAuthenticate = true;
request.Headers.Add("Authorization", authheader);
request.Accept = "application/json";
if(method.Equals("post", StringComparison.InvariantCultureIgnoreCase))
request.ContentType = "application/json";
var output = string.Empty;
try
{
using (var response = request.GetResponse())
{
using (var reader = new StreamReader(response.GetResponseStream()))
output = reader.ReadToEnd();
}
}
catch (WebException e)
{
using (var reader = new StreamReader(e.Response.GetResponseStream()))
{
output = reader.ReadToEnd();
}
}
return output;
}
public static string ReadChannel()
{
var action = $"/channels/{Constants.ChannelId}";
const string method = "GET";
return SendCommand(action, method);
}
}
The error complains something is wrong in how we compute the signature. Let's take a look at the Apple's example code to produces a correct signature, which is here:
https://developer.apple.com/documentation/apple_news/apple_news_api/about_the_news_security_model
Unfortunately I only found Python code. I don't know Python, either, but I can figure out enough to adapt it to just show the signature. We'll also need to know exactly what date value was used.
import base64
from hashlib import sha256
import hmac
from datetime import datetime
channel_id = 'cdb737aa-FFFF-FFFF-FFFF-FFFFFFFFFFFF'
api_key_id = '240ab880-FFFF-FFFF-FFFF-FFFFFFFFFFFF'
api_key_secret = 'HgyfMPjFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF='
url = 'https://news-api.apple.com/channels/%s' % channel_id
date = str(datetime.utcnow().strftime("%Y-%m-%dT%H:%M:%SZ"))
canonical_request = 'GET' + url + date
key = base64.b64decode(api_key_secret)
hashed = hmac.new(key, canonical_request, sha256)
signature = hashed.digest().encode("base64").rstrip('\n')
print date
print signature
You can see the result here (the short link points to tutorialspoint.com, which was the first online python interpreter I found in Google):
http://tpcg.io/e1W4p1
If you don't trust the link, just know I was able to use it to figure out the following known-correct signature based on these known inputs:
Method: GET
URL: https://news-api.apple.com/channels/cdb737aa-FFFF-FFFF-FFFF-FFFFFFFFFFFF
DateTime: 2018-06-12T18:15:45Z
API Secret: HgyfMPjFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF=
Signature: f3cOzwH7HGYPg481noBFwKgVOGAhH3jy7LQ75jVignA=
Now we can write C# code we can verity. When we can use those same inputs to produce the same signature result, we will have correct code.
Based on that, I was able to write this C# code:
public static void Main()
{
string method = "GET";
string url = "https://news-api.apple.com/channels/cdb737aa-FFFF-FFFF-FFFF-FFFFFFFFFFFF";
string dateString = "2018-06-12T18:15:45Z";
string apiKeySecret = "HgyfMPjFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF=";
var MyResult = GetSignature(method, url, dateString, apiKeySecret);
var DocumentedResult = "f3cOzwH7HGYPg481noBFwKgVOGAhH3jy7LQ75jVignA=";
Console.WriteLine(MyResult);
Console.WriteLine(MyResult == DocumentedResult);
}
public static string GetSignature(string method, string url, string dt, string APISecret)
{
var hmac = new HMACSHA256(Convert.FromBase64String(APISecret));
var hashed = hmac.ComputeHash(Encoding.ASCII.GetBytes(method + url + dt));
return Convert.ToBase64String(hashed);
}
Which you can see in action here:
https://dotnetfiddle.net/PQ73Zv
I don't have my own Apple API key to test with, so that's as far as I can take you.
One thing I did notice from the question is Apple's example has a "Z" at the end of the date string which is missing with original code here.
I am trying to access Adobe's Datawarehouse reporting using their API. The way it works is by first forming the JSON using the metrics available and the dimensions you want it to be brojen down by. That all works fine. However where I do have the issue comes down to this. Whenever I request more than 3 to 4 dimensions, the report takes longer to generate. I would need the HttpWebResponse to wait until it has been completed before moving to the next line. Below is my sample code that I have built based on an example from github.
class Program
{
protected static string JSONFolder = System.Configuration.ConfigurationManager.AppSettings["JSONFolder"];
protected static string USERNAME = System.Configuration.ConfigurationManager.AppSettings["Username"];
protected static string SECRET = System.Configuration.ConfigurationManager.AppSettings["Secret"];
protected static string ReportSuiteID = System.Configuration.ConfigurationManager.AppSettings["ReportSuiteID"];
private static string ENDPOINT = "https://api5.omniture.com/admin/1.4/rest/";
protected static string environment = "dev";
static void Main(string[] args)
{
DateTime previousDay = DateTime.Today.AddDays(-1);
string json = RequestJsonBuilder(previousDay, previousDay, ReportSuiteID);
string response = callMethod("Report.Queue", json, 15);
var jss = new JavaScriptSerializer();
var requestDetails = jss.Deserialize<Dictionary<string, string>>(response);
}
/*Build the json for the methods Report.GetStatus and Report.Get*/
public static string RequestJsonBuilderStatus(string id)
{
ReportID json = new ReportID() { reportID = id };
var serializer = new JavaScriptSerializer();
var serializedResult = serializer.Serialize(json);
return serializedResult;
}
/*Build the json for the method Report.Queue*/
static string RequestJsonBuilder(DateTime StartDate, DateTime EndDate, string ReportSuiteID)
{
//Build the list of metrics to send with the request
var listMetrics = new List<Metrics>();
listMetrics.Add(new Metrics() { id = "visits" });
//Build the list of elements to send with the request
var listElements = new List<Elements>();
listElements.Add(new Elements() { id = "page" , top = "25"});
var serializer2 = new JavaScriptSerializer();
Dictionary<string, RankedRequest> dic = new Dictionary<string, RankedRequest>();
dic.Add("reportDescription", new RankedRequest()
{
reportSuiteID = ReportSuiteID,
dateFrom = StartDate.ToString("yyyy-MM-dd"),
dateTo = EndDate.ToString("yyyy-MM-dd"),
metrics = listMetrics,
elements = listElements,
source = "warehouse"
});
var serializedResult2 = serializer2.Serialize(dic);
return serializedResult2;
}
/*Build the rest call to the Adobe Analytics REST APII 1.4*/
public static String callMethod(String method, String data, int secs)
{
Program prog = new Program();
HttpWebResponse statusResponse = null;
string responseXml = "";
StringBuilder sbUrl = new StringBuilder(ENDPOINT + "?method=" + method);
HttpWebRequest omniRequest = (HttpWebRequest)WebRequest.Create(sbUrl.ToString());
string timecreated = generateTimestamp();
string nonce = generateNonce();
string digest = getBase64Digest(nonce + timecreated + SECRET);
nonce = base64Encode(nonce);
omniRequest.Headers.Add("X-WSSE: UsernameToken Username=\"" + USERNAME + "\", PasswordDigest=\"" + digest + "\", Nonce=\"" + nonce + "\", Created=\"" + timecreated + "\"");
omniRequest.Method = "POST";
omniRequest.ContentType = "text/json";
//Write the json details to the request
using (var streamWriter = new StreamWriter(omniRequest.GetRequestStream()))
{
string json = data;
Console.WriteLine("\n 2.0 ############## Json request : \n\n " + json + "\n\n");
streamWriter.Write(json);
}
//Get the response of the request
try
{
Console.WriteLine("\n 2.0 ############## Sleeping thread for " + secs + "\n");
using (HttpWebResponse statusResponse = (HttpWebResponse) omniRequest.GetResponse())
{
using (Stream receiveStream = statusResponse.GetResponseStream())
{
using (StreamReader readStream = new StreamReader(receiveStream, Encoding.UTF8))
{
responseXml = readStream.ReadToEnd();
return responseXml;
}
}
}
}
catch (Exception ex) { throw ex; }
}
// other methods defined below
// private static string getBase64Digest(string input)
// private static string generateNonce()
// public static string base64Encode(string data)
// etc.
}
How do I make HttpWebResponse wait until a HTTP 200 response is actually received. This might take minutes to sometimes an hour depending on the number of metrics and dimensions I add.
Things I have tried also include changing line 88 to something like this:
How to process WebResponse when .NET throws WebException ((400) Bad Request)?
how to wait until a web request with HttpWebRequest is finished?
Sincerely appreciate all help here.
Thanks
Did you try setting the timeout? I was looking recently for the similar question and found that one:
HttpWebRequest.GetResponse() keeps getting timed out
I have a perl script that hashes and hexes parameters for authenticating a post message. I have to write the same procedure in C#, but have had no luck so far. Here is the perl code:
my $sha1_user_pwd = sha1_base64($user_pwd);
$sha1_user_pwd .= '=' x (4 - (length($sha1_user_pwd) % 4));
my $sha1_ws_pwd = sha1_base64($ws_pwd);
$sha1_ws_pwd .= '=' x (4 - (length($sha1_ws_pwd) % 4)); # Padding; if neccesary.
my $utc_time = time;
my ($utc_time, $kontekst, $projekt, $userid, $sha1_user_pwd) = #_;
my $auth = calc_hmac($sha1_ws_pwd, $sha1_user_pwd, $utc_time, $kontekst, $projekt, $userid);
sub calc_hmac {
my ($sha1_ws_pwd, $sha1_user_pwd, $utc_time, $kontekst, $projekt, $userid) = #_;
my $hmac = Digest::HMAC_SHA1->new($sha1_ws_pwd . $sha1_user_pwd);
$hmac->add($utc_time . $kontekst . $projekt . $userid);
return $hmac->hex digest;
}
$kontekst, $projekt, $userid and $ws_userid are all original string values.
Final post message (i have inserted line breaks for readability)
wsBrugerid=$ws_userid
&UTCtime=$utc_time
&kontekst=$kontekst
&projekt=$projekt
&BrugerId=$userid
&Auth=$auth
I have tried to copy the procedure in C#:
const string APP_KEY = "APP_KEY";
Encoding enc = Encoding.ASCII;
HMACSHA1 hmac = new HMACSHA1(enc.GetBytes(APP_KEY));
hmac.Initialize();
string ws_user = "ws_usr";
string ws_password = "ws_pwd";
DateTime epochStart = new System.DateTime(1970, 1, 1, 8, 0, 0, System.DateTimeKind.Utc);
int time = (int) (System.DateTime.UtcNow - epochStart).TotalSeconds;
string context = "context";
string project = "project";
string user_id = "user_id";
string user_pwd = "user_pwd";
string sha1_ws_pwd = System.Convert.ToBase64String(hmac.ComputeHash(enc.GetBytes(ws_password)));
sha1_ws_pwd += '=';
string sha1_user_pwd = System.Convert.ToBase64String(hmac.ComputeHash(enc.GetBytes(user_pwd)));
sha1_user_pwd += '=';
string k0 = sha1_ws_pwd + sha1_user_pwd;
string m0 = time + context + project + user_id;
byte[] _auth = hmac.ComputeHash(enc.GetBytes(k0 + m0));
string auth = BitConverter.ToString(_auth).Replace("-", string.Empty);
string url = "https://auth.emu.dk/mauth?wsBrugerid="+ws_user+
"&UTCtime="+time+
"&kontekst="+context+
"&projekt="+project+
"&BrugerId="+user_id+
"&Auth="+auth;
print("AuthenticationManager, url: " + url);
HttpWebRequest request = (HttpWebRequest)WebRequest.Create(url);
request.Method = "POST";
Encoding encoding = System.Text.Encoding.GetEncoding("utf-8");
String responseString = "";
HttpWebResponse response = (HttpWebResponse) request.GetResponse();
using (Stream stream = response.GetResponseStream()){
StreamReader reader = new StreamReader(stream, encoding);
responseString = reader.ReadToEnd();
}
JSONNode json = JSON.Parse(responseString);
print("AuthenticationManager, response: " + json[0] + " - " + json[1]);
I have no access to the server or application, which gives the response. The real values has of course been swapped. For example, APP_KEY is not "APP_KEY", but instead an actual string used for authentication. I know the data is correct as it passes in the perl script.
I appreciate any help I can get very much.
I figured it out!
It was not the time, but instead it was the hmac key. I was using APP_KEY as key, but the perl script is using sha1_ws_pwd + sha1_user_pwd. (so that was a stupid mistake...)
my $hmac = Digest::HMAC_SHA1->new($sha1_ws_pwd . $sha1_user_pwd);
Finally i also had to lower case the auth in C#. So the change in C# was:
// sha1 hash the passwords
string sha1_ws_pwd = System.Convert.ToBase64String(sha1.ComputeHash(enc.GetBytes(ws_password)));
string sha1_user_pwd = System.Convert.ToBase64String(sha1.ComputeHash(enc.GetBytes(user_pwd)));
…
string k0 = sha1_ws_pwd + sha1_user_pwd;
HMACSHA1 hmac = new HMACSHA1(enc.GetBytes(k0));
…
string auth = BitConverter.ToString(_auth).Replace("-", string.Empty).ToLower();
Thank you for your time and answers.
I am using Omniture api to download a report. The report is completed when I checked the status with DataWarehouseCheckRequest method. Now when I try to fetch the report using DataWarehouseGetReportData method, I get
CommunicationException Error in deserializing body of reply message for operation 'DataWarehouseGetReportData
Inner exception says
The specified type was not recognized: name='data_warehouse_report_row', namespace='http://www.omniture.com/', at <rows xmlns=''>
I am new with C# and the API both. Got no idea how to resolve this. Please help.
Thanks
When you want to download a DW report the best option is to do it over http. This the standard way and is much more efficient.
The response to CheckRequest contains a DataURL. Use that to download the data.
Here is some c# sample code I am using for an almost identical API (Partner vs you Enterprise API) (note I'm no c# expert either, so you will need to do a code review on this).
HttpWebResponse statusResponse = null;
string response = "";
StringBuilder sbUrl = new StringBuilder(dwrq.data_url); // hardcode to variable "rest_url" for testing.
HttpWebRequest omniRequest = (HttpWebRequest)WebRequest.Create(sbUrl.ToString());
string timecreated = generateTimestamp();
string nonce = generateNonce();
string digest = getBase64Digest(nonce + timecreated + secret);
nonce = base64Encode(nonce);
omniRequest.Headers.Add("X-WSSE: UsernameToken Username=\"" + username + "\", PasswordDigest=\"" + digest + "\", Nonce=\"" + nonce + "\", Created=\"" + timecreated + "\"");
omniRequest.Method = "GET"; // Switched from POST as GET is the right HTTP verb in this case
try
{
statusResponse = (HttpWebResponse)omniRequest.GetResponse();
using (Stream receiveStream = statusResponse.GetResponseStream())
{
using (StreamReader readStream = new StreamReader(receiveStream, Encoding.UTF8))
{
response = readStream.ReadToEnd();
}
}
}
catch (Exception ex)
{
throw new Exception(ex.Message);
}
Console.WriteLine("Response is a TAB delimeted CSV structure. Printing to screen.");
Console.WriteLine(response);
Console.WriteLine("Ending REST...");
Console.WriteLine("Ending ExportRequestSegmentedData...");
and the supporting methods
/*** Here are the private functions ***/
// Encrypting passwords with SHA1 in .NET and Java
// http://authors.aspalliance.com/thycotic/articles/view.aspx?id=2
private static string getBase64Digest(string input)
{
SHA1 sha = new SHA1Managed();
ASCIIEncoding ae = new ASCIIEncoding();
byte[] data = ae.GetBytes(input);
byte[] digest = sha.ComputeHash(data);
return Convert.ToBase64String(digest);
}
// generate random nonce
private static string generateNonce()
{
Random random = new Random();
int len = 24;
string chars = "0123456789abcdef";
string nonce = "";
for (int i = 0; i < len; i++)
{
nonce += chars.Substring(Convert.ToInt32(Math.Floor(random.NextDouble() * chars.Length)), 1);
}
return nonce;
}
// Time stamp in UTC string
private static string generateTimestamp()
{
return DateTime.UtcNow.ToString("yyyy-MM-ddTHH:mm:ssZ");
}
// C#-Base64 Encoding
// http://www.vbforums.com/showthread.php?t=287324
public static string base64Encode(string data)
{
byte[] encData_byte = new byte[data.Length];
encData_byte = System.Text.Encoding.UTF8.GetBytes(data);
string encodedData = Convert.ToBase64String(encData_byte);
return encodedData;
}
Best of Luck! C.