Google OAuth from Windows Phone invalid signature - c#

I've spent the past couple nights on this, and it's driving me mad. Hopefully someone can shed some light on this.
I'm trying to write a Windows Phone 7 app to connect to Google. The OAuth routine is really giving me trouble.
I've seen quite a few twitter examples, but nothing specific to Google. The code is below - every time I make the request, Google says 'invalid signature.' The base URLs match, everything seems kosher - but it refuses to take it.
string baseReqUrl = "https://www.google.com/accounts/OAuthGetRequestToken";
string oauth_consumer_key = "CONSUMER_KEY";
string oauth_consumer_secret = "CONSUMER_SECRET";
string oauth_nonce = OAuthLibrary.OAuth.CreateNonce();
string oauth_signature_method = "HMAC-SHA1";
long oauth_timestamp = OAuthLibrary.OAuth.CreateTimestamp();
//string scope = "https%3A%2F%2Fwww.google.com%2Fanalytics%2Ffeeds%2F";
string scope = "https://www.google.com/analytics/feeds/";
string oauth_callback = "oob";
List<string> sig = new List<string>();
sig.Add(baseReqUrl);
sig.Add("oauth_callback=" + oauth_callback);
sig.Add("oauth_conusmer_key=" + oauth_consumer_key);
sig.Add("oauth_nonce=" + oauth_nonce);
sig.Add("oauth_signature_method=" + oauth_signature_method);
sig.Add("oauth_timestamp=" + oauth_timestamp.ToString());
sig.Add("scope=" + scope);
string baseReq = "GET";
int i = 0;
foreach (string s in sig)
{
if (i == 1)
{
baseReq = baseReq + "?" + s;
}
else
{
baseReq = baseReq + "&" + s;
}
i++;
}
HMACSHA1 h = new HMACSHA1(Encoding.UTF8.GetBytes(oauth_consumer_secret));
OAuth.OAuthBase b = new OAuth.OAuthBase();
string normalizedUrl = string.Empty;
string normalizedRequestParameters = string.Empty;
string sigBase = b.GenerateSignatureBase(new Uri(baseReq.Substring(4)), oauth_consumer_key, null, null, "GET", oauth_timestamp.ToString(), oauth_nonce, "HMAC-SHA1", out normalizedUrl, out normalizedRequestParameters);
string signature = b.GenerateSignatureUsingHash(sigBase, h);
string reqUrl = normalizedUrl + "?" + normalizedRequestParameters + "&oauth_signature=" + signature;
GetUrl(reqUrl); //this line just makes the request

Related

AWS business Api Call - Working in Postman but not working in restsharp c#

We are trying to get all products by ASINS number. It´s working in Postman but not working in .net using restsharp.
public static string url = "https://na.business-api.amazon.com/products/2020-08-26/products/getProductsByAsins";
public static string accessKey = "xxxxxxxxxxxxxxxxxxxxxxxxxx";
public static string secretkey = "xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx";
public static string awsRegion = "us-east-1";
public static string awsServiceName = "execute-api";
string host = string.Join("/", url.Split('/').Select(Uri.EscapeDataString)) + "\n";
Uri endpoint = new Uri(url);
string s = endpoint.AbsoluteUri;
// Get and save dates ready for further use.
DateTimeOffset utcNowSaved = DateTimeOffset.UtcNow;
string amzLongDate = utcNowSaved.ToString("yyyyMMddTHHmmssZ");
string amzShortDate = utcNowSaved.ToString("yyyyMMdd");
string sha56key = "xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx";
Dictionary < string, string > parameters = new Dictionary < string, string > ();
parameters.Add("Content-Type", "application/json");
parameters.Add("x-amz-access-token", accesstoken);
parameters.Add("x-amz-user-email", "example#gmail.com");
parameters.Add("X-Amz-Content-Sha256", sha56key);
parameters.Add("X-Amz-Date", amzLongDate);
parameters.Add("host", url);
// 1. Create Canonical Request
var canonicalRequest = new StringBuilder();
canonicalRequest.Append("POST" + "\n");
var headersToBeSigned = new List < string > ();
foreach(KeyValuePair < string, string > keyValuePair in parameters) {
canonicalRequest.Append(keyValuePair.Key.ToLowerInvariant());
canonicalRequest.Append(":");
canonicalRequest.Append(string.Join(",", keyValuePair.Value.Trim()));
canonicalRequest.Append("\n");
headersToBeSigned.Add(keyValuePair.Key.ToLowerInvariant());
}
canonicalRequest.Append("\n");
var signedHeaders = string.Join(";", headersToBeSigned);
canonicalRequest.Append(signedHeaders + "\n");
canonicalRequest.Append(sha56key);
// 2. String to sign.
string stringToSign = "AWS4-HMAC-SHA256" + "\n" + amzLongDate + "\n" + amzShortDate + "/" + awsRegion + "/" + awsServiceName + "/aws4_request" + "\n" + Hash(Encoding.UTF8.GetBytes(canonicalRequest.ToString()));
// 3. Signature with compounded elements.
var dateKey = HmacSha256(Encoding.UTF8.GetBytes("AWS4" + secretkey), `enter code here`
amzShortDate);
var dateRegionKey = HmacSha256(dateKey, awsRegion);
var dateRegionServiceKey = HmacSha256(dateRegionKey, awsServiceName);
var signingKey = HmacSha256(dateRegionServiceKey, "aws4_request");
var signature = ToHexString(HmacSha256(signingKey, stringToSign.ToString()));
// **************************************************** END SIGNING PORTION ****************************************************
// Add the Header to the request.
var credentialScope = amzShortDate + "/" + awsRegion + "/" + awsServiceName + "/aws4_request";
parameters.Add("Authorization", "AWS4-HMAC-SHA256 Credential=" + accessKey + "/" + credentialScope + ", SignedHeaders=" + signedHeaders + ", Signature=" + signature);
var client = new RestClient();
var request = new RestRequest(url, Method.Post);
foreach(KeyValuePair < string, string > keyValuePair in parameters) {
request.AddHeader(keyValuePair.Key, keyValuePair.Value);
}
var body = new AmazonASINSRequestDto();
body.productIds = new List < string > (new string[] {
"B087Z733CM",
"B0012YVGOW",
"B000YDJIYW",
"B07XQHYC95",
"B004MDLZ96",
"B07KSRFJ9Y",
"B00YH2JT9U",
"B002OB49KA",
"B00FU6PDLU"
});
body.productRegion = "US";
body.locale = "en_US";
body.facets = new List < string > (new string[] {
"OFFERS",
"IMAGES"
});
var jsonval = JsonConvert.SerializeObject(body);
//request.AddParameter("application/json", jsonval, ParameterType.RequestBody);
request.AddJsonBody(jsonval);
RestResponse response = await client.ExecuteAsync(request);

Binance API bad request with C# in Fiddler

I have an outgoing POST from another application, and with the help of Fiddler I want to send another order opening request. I managed to take the necessary data from the original request, sign the request using HMAC256 and send it to Binance, but I get a "bad request" in the response and I don't understand what's wrong here. I would appreciate any help.
public static void OnBeforeResponse(Session oSession)
{
if (oSession.HTTPMethodIs("POST") && oSession.uriContains("order"))
{
String strBody = oSession.GetRequestBodyAsString();
//Price
int PriceStart = strBody.IndexOf("price=") + 6;
int PriceEND = strBody.IndexOf("&", PriceStart);
string priceStr = strBody.Substring(PriceStart, PriceEND - PriceStart);
float priceF = float.Parse(priceStr, System.Globalization.CultureInfo.InvariantCulture);
// SYMBOL
int symbolStart = strBody.IndexOf("symbol=") + 7;
int symbolend = strBody.IndexOf("BTC", symbolStart);
string symbol = strBody.Substring(symbolStart, symbolend - symbolStart);
// Quantity
int quantStart = strBody.IndexOf("quantity=") + 9;
int quantend = strBody.IndexOf("&price", quantStart);
string quant = strBody.Substring(quantStart, quantend - quantStart);
float quantity = float.Parse(quant, System.Globalization.CultureInfo.InvariantCulture) * 2;
// timestamp
decimal timestamp = Math.Round(Convert.ToDecimal(DateTime.UtcNow.Subtract(new DateTime(1970, 1, 1, 0, 0, 0, DateTimeKind.Utc)).TotalMilliseconds), 0);
//Sign
Encoding ascii = Encoding.ASCII;
string secretKey = "lfaeGkjitNwvyG2lqDueMhSAOzRFlzL73w5pKRCAvSy7YrxyTkvwKCcHBHj...";
HMACSHA256 hmac = new HMACSHA256(ascii.GetBytes(secretKey));
// string query_string_LIMIT = "symbol="+symbol+"USDT&side=BUY&type=LIMIT&timeInForce=GTC&quantity="+quantity+"&price="+priceF+"&recvWindow=5000&timestamp="+timestamp+"&signature=";
string result = "symbol=" + symbol + "USDT&side=BUY&type=MARKET&quantity=" + quantity + "&recvWindow=5000&timestamp=" + timestamp + "&signature=";
String signature = BitConverter.ToString(hmac.ComputeHash(ascii.GetBytes(result))).Replace("-", "");
oSession.host = "fapi.binance.com";
string resultRequest = "symbol=" + symbol + "USDT&side=BUY&type=MARKET&quantity=" + quantity + "&recvWindow=5000&timestamp=" + timestamp + "&signature=" + signature;
byte[] resulByte = System.Text.Encoding.ASCII.GetBytes(resultRequest);
//oSession.utilReplaceInRequest("api/v3/order","fapi/v1/order?"+resultFin);
oSession.url = oSession.url.Replace("api/v3/order", "fapi/v1/order?" + resultRequest);
FiddlerApplication.oProxy.SendRequest(oSession.RequestHeaders, resulByte, null);
}
}

Twitter home_timeline Windows 8 C# call returns Could not authenticate you

I'm trying to pull the timeline of an authenticated user in a Windows 8.1/Windows Phone 8.1 Universal app. I believe I have everything set up correctly, but I keep getting a response of "code=32, message=Could not authenticate you" in Fiddler.
I think I'm just using the headers in the TwitterGetRequest function wrong, but I can't figure out the exact issue.
This is all based off the WebAuthentication Sample code from MSDN.
Here's the main function
private async Task GetTwitterUserNameAsync(string webAuthResultResponseData)
{
//
// Acquiring a access_token first
//
string responseData = webAuthResultResponseData.Substring(webAuthResultResponseData.IndexOf("oauth_token"));
string request_token = null;
string oauth_verifier = null;
String[] keyValPairs = responseData.Split('&');
for (int i = 0; i < keyValPairs.Length; i++)
{
String[] splits = keyValPairs[i].Split('=');
switch (splits[0])
{
case "oauth_token":
request_token = splits[1];
break;
case "oauth_verifier":
oauth_verifier = splits[1];
break;
}
}
String TwitterUrl = "https://api.twitter.com/oauth/access_token";
string response = await TwitterPostRequest(request_token, oauth_verifier, TwitterUrl);
String[] Tokens = response.Split('&');
string oauth_token_secret = null;
string access_token = null;
string screen_name = null;
for (int i = 0; i < Tokens.Length; i++)
{
String[] splits = Tokens[i].Split('=');
switch (splits[0])
{
case "screen_name":
screen_name = splits[1];
break;
case "oauth_token":
access_token = splits[1];
break;
case "oauth_token_secret":
oauth_token_secret = splits[1];
break;
}
}
//you can store access_token and oauth_token_secret for further use. See Scenario5(Account Management).
if (access_token != null)
{
DebugPrint("access_token = " + access_token);
}
if (oauth_token_secret != null)
{
DebugPrint("oauth_token_secret = " + oauth_token_secret);
}
if (screen_name != null)
{
//rootPage.NotifyUser(screen_name + " is connected!!", NotifyType.StatusMessage);
}
string timeline = await TwitterGetRequest(access_token, oauth_token_secret, oauth_verifier, "https://api.twitter.com/1.1/statuses/home_timeline.json");
List<SocialItem> tweets = new List<SocialItem>();
if (timeline.Length > 0)
{
JArray tweetArray = JArray.Parse(timeline);
for(int i=0;i<tweetArray.Count();i++)
{
JObject tweet = JObject.Parse(tweetArray[i].ToString());
JObject tweetAuthor = JObject.Parse(tweet["user"].ToString());
string imgUrl = tweetAuthor["profile_image_url"].ToString();
string message = tweet["text"].ToString();
string userName = tweetAuthor["screen_name"].ToString();
string displayName = tweetAuthor["name"].ToString();
string createdAtString = tweet["created_at"].ToString();
DateTime created;
if(!DateTime.TryParse(createdAtString, out created))
{
created = DateTime.MinValue;
}
tweets.Add(new SocialItem
{
ImageUrl = imgUrl,
MessageBody = message,
UserName = userName,
DisplayName = displayName,
MessageDate = created,
ProfileUrl = ("http://twitter.com/" + userName)
});
}
this.DataContext = tweets;
}
}
Here's the supporting functions:
private async Task<string> TwitterPostRequest(string request_token, string oauth_verifier, String TwitterUrl)
{
string timeStamp = GetTimeStamp();
string nonce = GetNonce();
String SigBaseStringParams = "oauth_consumer_key=" + Twitter.CLIENT_ID;
SigBaseStringParams += "&" + "oauth_nonce=" + nonce;
SigBaseStringParams += "&" + "oauth_signature_method=HMAC-SHA1";
SigBaseStringParams += "&" + "oauth_timestamp=" + timeStamp;
SigBaseStringParams += "&" + "oauth_token=" + request_token;
SigBaseStringParams += "&" + "oauth_version=1.0";
String SigBaseString = "POST&";
SigBaseString += Uri.EscapeDataString(TwitterUrl) + "&" + Uri.EscapeDataString(SigBaseStringParams);
String Signature = GetSignature(SigBaseString, Twitter.CLIENT_SECRET);
HttpStringContent httpContent = new HttpStringContent("oauth_verifier=" + oauth_verifier, Windows.Storage.Streams.UnicodeEncoding.Utf8);
httpContent.Headers.ContentType = HttpMediaTypeHeaderValue.Parse("application/x-www-form-urlencoded");
string authorizationHeaderParams = "oauth_consumer_key=\"" + Twitter.CLIENT_ID + "\", oauth_nonce=\"" + nonce + "\", oauth_signature_method=\"HMAC-SHA1\", oauth_signature=\"" + Uri.EscapeDataString(Signature) + "\", oauth_timestamp=\"" + timeStamp + "\", oauth_token=\"" + Uri.EscapeDataString(request_token) + "\", oauth_version=\"1.0\"";
HttpClient httpClient = new HttpClient();
httpClient.DefaultRequestHeaders.Authorization = new HttpCredentialsHeaderValue("OAuth", authorizationHeaderParams);
var httpResponseMessage = await httpClient.PostAsync(new Uri(TwitterUrl), httpContent);
string response = await httpResponseMessage.Content.ReadAsStringAsync();
return response;
}
private async Task<string> TwitterGetRequest(string request_token, string oauth_token_secret, string oauth_verifier, String TwitterUrl)
{
string timeStamp = GetTimeStamp();
string nonce = GetNonce();
String SigBaseStringParams = "oauth_consumer_key=" + Twitter.CLIENT_ID;
SigBaseStringParams += "&" + "oauth_nonce=" + nonce;
SigBaseStringParams += "&" + "oauth_signature_method=HMAC-SHA1";
SigBaseStringParams += "&" + "oauth_timestamp=" + timeStamp;
SigBaseStringParams += "&" + "oauth_token=" + request_token;
SigBaseStringParams += "&" + "oauth_version=1.0";
String SigBaseString = "GET&";
SigBaseString += Uri.EscapeDataString(TwitterUrl) + "&" + Uri.EscapeDataString(SigBaseStringParams);
String Signature = GetSignature(SigBaseString, oauth_token_secret);
//HttpStringContent httpContent = new HttpStringContent("oauth_verifier=" + oauth_verifier, Windows.Storage.Streams.UnicodeEncoding.Utf8);
//httpContent.Headers.ContentType = HttpMediaTypeHeaderValue.Parse("application/x-www-form-urlencoded");
string authorizationHeaderParams = "oauth_consumer_key=\"" + Twitter.CLIENT_ID +
"\", oauth_nonce=\"" + nonce +
"\", oauth_signature_method=\"HMAC-SHA1\", oauth_signature=\"" + Uri.EscapeDataString(Signature) +
"\", oauth_timestamp=\"" + timeStamp +
"\", oauth_token=\"" + Uri.EscapeDataString(request_token) +
"\", oauth_version=\"1.0\"";
HttpClient httpClient = new HttpClient();
httpClient.DefaultRequestHeaders.Authorization = new HttpCredentialsHeaderValue("OAuth", authorizationHeaderParams);
string response="";
try
{
response = await httpClient.GetStringAsync(new Uri(TwitterUrl));//httpClient.PostAsync(new Uri(TwitterUrl), httpContent);
}
catch (Exception ex)
{
DebugPrint(ex.Message);
}
//string response = await httpResponseMessage.Content.ReadAsStringAsync();
return response;
}
string GetNonce()
{
Random rand = new Random();
int nonce = rand.Next(1000000000);
return nonce.ToString();
}
string GetTimeStamp()
{
TimeSpan SinceEpoch = DateTime.UtcNow - new DateTime(1970, 1, 1);
return Math.Round(SinceEpoch.TotalSeconds).ToString();
}
string GetSignature(string sigBaseString, string consumerSecretKey)
{
IBuffer KeyMaterial = CryptographicBuffer.ConvertStringToBinary(consumerSecretKey + "&", BinaryStringEncoding.Utf8);
MacAlgorithmProvider HmacSha1Provider = MacAlgorithmProvider.OpenAlgorithm("HMAC_SHA1");
CryptographicKey MacKey = HmacSha1Provider.CreateKey(KeyMaterial);
IBuffer DataToBeSigned = CryptographicBuffer.ConvertStringToBinary(sigBaseString, BinaryStringEncoding.Utf8);
IBuffer SignatureBuffer = CryptographicEngine.Sign(MacKey, DataToBeSigned);
string Signature = CryptographicBuffer.EncodeToBase64String(SignatureBuffer);
return Signature;
}
I have never received this kind of error but I have been developing with Tweetinvi and it is very easy to retrieve the timeline of the authenticated user.
Just do the following:
TwitterCredentials.SetCredentials("ACCESS_TOKEN", "ACCESS_TOKEN_SECRET", "CONSUMER_KEY", "CONSUMER_SECRET");
var tweets = Timeline.GetHomeTimeline();
Hope this helps.

401 Error when trying to get Request Token

resp = (HttpWebResponse)request.GetResponse();Right I know this is probably some stupid mistake or just me not being well versed in Oauth stuff but I have come to a grinding halt and have no idea where to go from here, after many searches and attempts I humbly ask for some help.
I am attempting to get a request token from Twitter to try and get a users twitter feeds, I cannot use a library for other business reasons...
Here is the code so far:
Dictionary<string, string> parameters = new Dictionary<string, string>();
parameters.Add("oauth_callback", "www.url.com/redirect.aspx");
parameters.Add("oauth_consumer_key", <Consumer_KEY>);
parameters.Add("oauth_nonce", generateNonce());
parameters.Add("oauth_signature_method", "HMAC-SHA1");
parameters.Add("oauth_timestamp", CurrentUNIXTimestamp.Get());
parameters.Add("oauth_version", "1.0");
parameters = parameters.OrderBy(x => x.Key).ToDictionary(v => v.Key, v => v.Value);
string concat = "";
string OAuthHeader = "OAuth ";
foreach (string k in parameters.Keys)
{
if (k == "oauth_callback")
{
concat += k + "%3D" + EncodeToUpper(parameters[k]) + "%26";
OAuthHeader += k + "=" + "\"" + EncodeToUpper(parameters[k]) + "\", ";
}
else
{
concat += k + "%3D" + parameters[k] + "%26";
OAuthHeader += k + "=" + "\"" + parameters[k] + "\", ";
}
}
concat = concat.Remove(concat.Length - 3, 3);
concat = "POST&" + EncodeToUpper("https://api.twitter.com/oauth/request_token" ) + "&" + concat;
//byte[] content = Encoding.UTF8.GetBytes(concat);
HMACSHA1 hmacsha1 = new HMACSHA1();
hmacsha1.Key = Encoding.ASCII.GetBytes(string.Format("{0}&{1}", EncodeToUpper(<CONSUMER SECRET>, ""));
byte[] dataBuffer = System.Text.Encoding.ASCII.GetBytes(concat);
byte[] hashBytes = hmacsha1.ComputeHash(dataBuffer);
string hash = Convert.ToBase64String(hashBytes);
OAuthHeader += "oauth_signature=\"" + EncodeToUpper(hash) + "\"";
HttpWebRequest request = (HttpWebRequest)WebRequest.Create("https://api.twitter.com/oauth/request_token");
request.Method = "POST";
request.Headers["Authorization"] = OAuthHeader;
StringBuilder responding = new StringBuilder();
HttpWebResponse resp = null;
try
{
resp = (HttpWebResponse)request.GetResponse();
}
catch (WebException exc)
{
lblError.Text = "Error Connecting to Social Network " + exc.Message;
}
if (resp != null)
{
using (StreamReader reader = new StreamReader(resp.GetResponseStream()))
{
responding.Append(reader.ReadToEnd());
}
}
An Example of the Nonce is "ne8ehvVr0pW2EUxNHdxdyqbi8Fwphatt3SW1yerTyXH" and the CurrentUNIXTimestamp is generated by
public static class CurrentUNIXTimestamp
{
public static string Get()
{
return Convert.ToString((int)(DateTime.UtcNow - new DateTime(1970, 1, 1, 0, 0, 0)).TotalSeconds);
}
}
I have tried as many things as I can think of, there is no longer a client/browser issue (which was many other answers), the server time is correct to British Summer Time (I don't know whether that would be an issue but I tried adding an hour to the unix time stamp still a 401.), and i have defined the callback url on the twitter app page
I have got the same app working with facebook (I know its different oauth but may help)
The actual error comes at resp = (HttpWebResponse)request.GetResponse();, which comes up with a 401 error. I couldn't get any further details from the exc.response object, could anyone say how to get something useful out of the error in VS2008?
Thanks for any answers
The hardest problem I had implementing OAuth was dealing with character encoding. It's very particular.
Here is the code I ended up writing for it.
private static string UrlEncode(IEnumerable<KeyValuePair<string, object>> parameters)
{
StringBuilder parameterString = new StringBuilder();
var paramsSorted = from p in parameters
orderby p.Key, p.Value
select p;
foreach (var item in paramsSorted)
{
if (parameterString.Length > 0)
{
parameterString.Append("&");
}
if(item.Value.GetType() == typeof(string) )
parameterString.Append(
string.Format(
CultureInfo.InvariantCulture,
"{0}={1}",
UrlEncode(item.Key),
UrlEncode(item.Value as string)));
}
return UrlEncode(parameterString.ToString());
}
public static string UrlEncode(string value)
{
if (string.IsNullOrEmpty(value))
{
return string.Empty;
}
value = Uri.EscapeDataString(value);
// UrlEncode escapes with lowercase characters (e.g. %2f) but oAuth needs %2F
value = Regex.Replace(value, "(%[0-9a-f][0-9a-f])", c => c.Value.ToUpper());
// these characters are not escaped by UrlEncode() but needed to be escaped
value = value
.Replace("(", "%28")
.Replace(")", "%29")
.Replace("$", "%24")
.Replace("!", "%21")
.Replace("*", "%2A")
.Replace("'", "%27");
// these characters are escaped by UrlEncode() but will fail if unescaped!
value = value.Replace("%7E", "~");
return value;
}
If you really get fed up, you can use the WebRequestBuilder class from my library to do all the OAuth stuff for you: http://www.twitterizer.net/

Payment succeeds, and our data matches querystring data, but falls thru to INVALID anyway!

Why does my ipn script I wrote always fail? It always goes to INVALID even though it matches everything in the query string that paypal sends to me?
notification.cshtml?tx=b78v54b5b55rby92S&st=Completed&amt=3.04&cc=USD&cm=&item_number=&merchant_return_link=Return+to+web+site+name&form_charset=UTF-8
And the part that checks it is:
string LiveURL = "https://www.paypal.com/cgi-bin/webscr";
HttpWebRequest request = (HttpWebRequest)WebRequest.Create(LiveURL);
// Set request back values.
request.Method = "POST";
request.ContentType = "application/x-www-form-urlencoded";
byte[] parameters = Request.BinaryRead(HttpContext.Current.Request.ContentLength);
string RequestString = System.Text.Encoding.ASCII.GetString(parameters);
RequestString += "&cmd=_notify-validate";
request.ContentLength = RequestString.Length;
// Send request to PP and get response.
StreamWriter Sout = new StreamWriter(request.GetRequestStream(), System.Text.Encoding.ASCII);
Sout.Write(RequestString);
Sout.Close();
StreamReader Sin = new StreamReader(request.GetResponse().GetResponseStream());
string response = Sin.ReadToEnd();
Sin.Close();
if(result != null && result.OrderStatus == "Confirmed")
{
switch(response)
{
case "VERIFIED":
if(Request["st"] == "Completed")
{
var PPQuery = "SELECT TransactionId, OrderTotal FROM Orders WHERE OrderId = '" + Session["OSFOID"] + "' AND UserId = '" + WebSecurity.CurrentUserId + "'";
var ppQueryResult = database.Query(PPQuery);
foreach(var item in ppQueryResult)
{
decimal fff = 3.04M;
if(item["TransactionId"] != Request["tx"])
{
if(item["OrderTotal"] == TotalPrice)
{
// Payment was a success. Convey that to the user.
output = "Thanks. Order complete.";
}
else
{
// Possible fraud. Log it.
}
}
else
{
// This is a duplicate transaction. Log it and Redirect to homepage.
}
}
}
break;
case "INVALID":
output = "Invalid was returned. Investigate further.";
break;
default:
output = "Other exception has occured. Investigate further and log.";
break;
}
}
The code looks fine. The problem must be with response not matching "VERIFIED".
You're not in Turkey by chance, and changing response to uppercase prior to the comparison? *
*) If the locale is Turkey, uppercasing a string turns i into İ, not I (just one of the many traps with string manipulation)
Within the "VERIFIED" block, check:
if (Request.Params["payment_status"] == "Completed")
{
...
}
Request["st"] is incorrect.
Be sure to set IPN URL in one place in PayPal admin and do not use the other form of return URL checking (can't remember the name of it offhand) and IPN at the same time.
There is no "merchant_return_link" parameter; I think it should be "notify_url"... the URL string and the list of params doesn't look right to me; for example: &cm=&item_number
I know your list of params will be unique for your situation, but here's some sample code where I construct the URL to be passed to PayPal:
protected string GetPayPalURL(string SERVER_URL, string business, string[] itemNames,
int[] quantities, decimal[] amounts, double[] weight, string invoiceID, string transID, string NOTIFY_URL)
{
// Customer will be required to specify delivery address to PayPal - VERY IMPORTANT
const string NO_SHIPPING = "2";
StringBuilder url = new StringBuilder();
url.Append(SERVER_URL + "?cmd=_cart&upload=1");
url.Append("&business=" + HttpUtility.UrlEncode(business));
for (int i = 0; i < itemNames.Length; i++)
{
url.Append("&item_name" + "_" + (i + 1).ToString() + "=" + HttpUtility.UrlEncode(itemNames[i]));
url.Append("&quantity" + "_" + (i + 1).ToString() + "=" + quantities[i].ToString().Replace(",", "."));
url.Append("&amount" + "_" + (i + 1).ToString() + "=" + amounts[i].ToString().Replace(",", "."));
url.Append("&weight" + "_" + (i + 1).ToString() + "=" + weight[i].ToString().Replace(",", "."));
}
url.Append("&no_shipping=" + HttpUtility.UrlEncode(NO_SHIPPING));
url.Append("&custom=" + HttpUtility.UrlEncode(invoiceID));
url.Append("&txn_id=" + HttpUtility.UrlEncode(transID));
url.Append("&notify_url=" + HttpUtility.UrlEncode(NOTIFY_URL));
return url.ToString();
}
I think the Paypal method you are trying to do is as follows on code project
and if you get payment_status = INVALID, then check the reason in payment_reason
i dont see in the code where you are defining result which is checked in the if, also in the switch you are checking against request, surely this should be against response?

Categories

Resources