SetExpressCheckout token received but Sandbox claims transaction has expired - c#

I've been attempting to process a very simple express checkout Sandbox transaction using the C# Paypal API, but keep getting a session timeout error on the Paypal website after the redirect.
I should emphasize that I get a successful ACK response from SetExpressCheckout along with a Token string.
Here is an example of the checkout URL I've been trying to redirect to:
https://www.sandbox.paypal.com/cgi-bin/webscr?cmd=_express-checkout&token=EC-9RY2628262462061J
My return address is localhost, but I couldn't see anywhere that this would be a problem in Sandbox.
On trying to redirect to the Sandbox I arrive not at the checkout URL but at this address:
https://www.sandbox.paypal.com/cgi-bin/webscr?cmd=_flow&SESSION=CzvBHQErPEHw5gOt51FV88G_4L9HUCLypeGkwVZLW6mkWsZOofIpFR2K6Aa&dispatch=50a222a57771920b6a3d7b606239e4d529b525e0b7e69bf0224adecfb0124e9b61f737ba21b081984719ecfa9a8ffe80733a1a700ced90ae
And see the following error message:
"This transaction has expired. Please return to the recipient's website to complete your transaction using their regular checkout flow."
How can the transaction be timing out when [1] I have a successful API response along with a token and [2] I literally redirect there immediately after getting the token.
Does anyone have any idea what's going on here?
If it helps here is the C# I wrote to access the API. As noted, I get a success ACK response plus a token.
try
{
var details = ToPaymentDetails(data);
var request = new SetExpressCheckoutReq();
request.SetExpressCheckoutRequest = new SetExpressCheckoutRequestType
{
SetExpressCheckoutRequestDetails = details,
Version = Version
};
var result = await client.SetExpressCheckoutAsync(credentials, request);
var response = result.SetExpressCheckoutResponse1;
FailOnError(response);
return Result.Success(response.Token);
}
catch (Exception ex)
{
return Result.Error<string>("Received an error from Paypal.SetExpressCheckout.", exception: ex);
}

The EC token only last for 3 hours. You will have to recall the SetEC API to get a new EC token and proceed with the checkout flow.

I am not closer to understanding why the SOAP API call generates a token that is rejected by Paypal, but I found that I was able to reach the Sandbox payment page if I used the SDK to generate a payment.
This hasn't exactly been an enlightening or educational experience ...

Related

SnipCart API Authorization returns 401 Unauthorized

I want to use the V3 SnipCart API to get data about specific orders on my thank you page. I am using C# to do this. I keep getting this error when trying to use the API
System.Net.WebException:'The remote server returned an error: (401)
Unauthorized.'
I have tried to follow their documentation by using only the API key with no password as shown here. Below is my code that I wrote that is giving me the error. I wrote this inside my controller. I get the error as soon as the breakpoint hits this line responseObjGet = (HttpWebResponse)requestObjGet.GetResponse();
//Testing API get data begin
string strurltest = String.Format("https://app.snipcart.com/api/orders/c5541254-r8541-8501-0024-juy85vv002154");
WebRequest requestObjGet = WebRequest.Create(strurltest);
requestObjGet.Credentials = new NetworkCredential("HihiukoJOUBVCTYIiijiGiiYTd6tOiUyTYo", "");
requestObjGet.Method = "GET";
HttpWebResponse responseObjGet = null;
responseObjGet = (HttpWebResponse)requestObjGet.GetResponse(); //401 is triggered here
string strresulttest = null;
using (Stream stream = responseObjGet.GetResponseStream())
{
StreamReader sr = new StreamReader(stream);
strresulttest = sr.ReadToEnd();
sr.Close();
}
Concerns that I have as well are the following:
1.The API key that I entered here is my public api key since I am still in the development and testing phase. I am not sure if this api call will work with the test api key or if I have to use the real secret production key. Any thoughts?
2.I am debugging this off my local machine (localhost:) for now before I deploy these API calls to production to test these changes in prod still with the test api key, could that be a reason for the 401? Since the URL that is trying to get the info is my localhost: url and not my actual domain that I added to SnipCart Dashboard. I was thinking maybe I have to try and hit this from prod environment instead? Any thought?
These are the 2 possibilities that come to mind for me. I am not too savvy on APi's yet so I don't know if my call is missing something.
Summary: All I am trying to do is be able to use the API so that I can load the data I want for an order when users reach my custom thank you page with their token.
Our 401 "Unauthorized" status code is returned when the authentication failed to our API with your Authorization header's value.
Here's the documentation about the auth to our APIs. Make sure to return us a base64 value of your secret API key and the trailing single colon character at the end to respect the Basic Authentication Scheme.
And if you are trying to get data for an order that was placed in live mode then you would need to use the live secret API key.

How do I authenticate my server based app with Zoho SDK?

I hope this makes sense. I am using the Zoho C# SDK examples to write records to the CRM Leads. While calling recordOperations.CreateRecords(); it fails after trying to GetToken from the Token Store.
Here is the token I am saving
Token token = new OAuthToken(
"xxxx.clientid.goes.here.xxxxx",
"xxxx.clientsecret.goes.here.xxxx",
"REFRESH/GRANT token",
TokenType.GRANT,
string.Empty);
TokenStore tokenStore = new CustomTokenStore();
tokenStore.SaveToken(user, token);
And I am sending this token into the SDKInitilizer.Initialize. No errors at this point. Next I try and create a lead. When it gets inside of recordOperations.CreateRecords(); it tries GetToken and I've hard coded it to return exactly what was in the token object above. CreateRecords throws an error for "invalid_code". Here is what is in the log file
21-09-07 16:49:34 [INFO]: Initialization successful for Email Id : myemail#email.com in Environment : https://www.zohoapis.com.
21-09-07 16:49:47 [INFO]: Access Token has expired. Hence refreshing.
21-09-07 16:49:50 [ERROR]: Exception in authenticating current request : {"Code":"INVALID CLIENT ERROR","Message":"invalid_code","Cause":null,"Details":null,"StackTrace":" at Com.Zoho.API.Authenticator.OAuthToken.ParseResponse(String response)\r\n at Com.Zoho.API.Authenticator.OAuthToken.RefreshAccessToken(UserSignature user, TokenStore store)\r\n at Com.Zoho.API.Authenticator.OAuthToken.Authenticate(APIHTTPConnector urlConnection)\r\n at Com.Zoho.Crm.API.Util.CommonAPIHandler.APICall[T](Type className, String encodeType)","Data":{},"InnerException":null,"HelpLink":null,"Source":"ZCRMSDK","HResult":-2146233088}
It appears to be failing when it tries to refresh the token so I assume I am not sending in the right info in the token object?
*** Edit for #sucasa ***
This is what I am sending into the Initialize method.
What I have figured out since my first post is, I'm not getting the initial token from Initialize and its not calling the custom TokenStore.SaveToken() I created and it should, right? If I save it, all I have is what is above, not an actual token. So I think when I go to create the lead, I don't actually have the initial token to refresh. I hope that's clearer.
Access Tokens expire and must be refreshed using a refresh token. The error message indicates this. Can you log the value of token and report back here?

Unable to sign in to login.microsoftonline.com oauth 2 authorize endpoint

I've tried different ways to connect the Microsoft sign in function which open a webpage so you can use things like sign in with MFA. I manage to get this to work in Postman and now im trying it in C# particularly in .NET MVC 5.
HomeController:
public ActionResult TestAuth()
{
HttpClient client = new HttpClient();
var bodyParams = new Dictionary<string, string>();
bodyParams.Add("client_id", "{my_client_id}");
bodyParams.Add("client_secret", "{my_client_secret}");
bodyParams.Add("scope", "openid");
bodyParams.Add("redirect_uri", "https://localhost");
bodyParams.Add("grant_type", "authorization_code");
var response = client.PostAsync("https://login.microsoftonline.com/{my_tenant_id}/oauth2/v2.0/authorize", new FormUrlEncodedContent(bodyParams)).Result;
return View("TestAuth", new { response.Content.ReadAsStringAsync().Result });
}
View TestAuth.cshtml:
#model dynamic
#Html.Raw(Model)
If i sign in with my email on that domain, or any text at all really, i get this message. I cannot see why this issue occurs it gives me zero information what to do next more than just trying until you make it basically :). I've looked at tons of different Microsoft documentations, Stack posts, forums etc but with no success.
The postman call example:
Is it possible I'm doing something wrong in the request in the c# code or am i missing something important like configurations in Azure AD etc?
I'm up for anything that will work that i can sign into a Microsoft account that use MFA, then i can use their login to fetch data from Microsoft Graph based on their permissions basically.
P.S. I also can fetch data with the access token generated from postman so it's working as expected. I only need to "convert the postman call to c#" to make it work esentially. Any help is appreciated :)
You’re trying to do an oauth2 request from the controller. The request you’re sending is incorrect.
Microsoft made a great sample on how to use the Microsoft identity platform in a dotnet application https://github.com/Azure-Samples/active-directory-aspnetcore-webapp-openidconnect-v2/tree/master/1-WebApp-OIDC
In a nutshell you redirect the user to the endpoint (so not a get/post from the controller, but actually a redirect 302 response to the token url).
The user then has to login and is redirected to the webapplication.
Your webapplication will get an authorization code that is has to exchange for an access token by a post request.
Postman does this for you, but in order to do it in dotnet core, just follow the sample.
I didn't find a soultion to this specific problem what i did find was another guide which led me to this github project https://github.com/Azure-Samples/ms-identity-aspnet-webapp-openidconnect
Which had similar code in the Startup.cs file but actually had some examples like SendMail and ReadMail etc which was fetched from ms graph api. This gave me some idea of how this project was structured compared to mine. So one thing that was missing was this part I couldnt figure out:
IConfidentialClientApplication app = await MsalAppBuilder.BuildConfidentialClientApplication();
var account = await app.GetAccountAsync(ClaimsPrincipal.Current.GetAccountId());
So the Msal app builder which is a custom made thingy i needed to get the current user etc which i needed. This works fine and after that i can start doing requests to the graph api like adding scopes etc and make http request.
Example see groups:
[Authorize]
[HttpGet]
public async Task<ActionResult> GetGroups()
{
IConfidentialClientApplication app = await MsalAppBuilder.BuildConfidentialClientApplication();
var account = await app.GetAccountAsync(ClaimsPrincipal.Current.GetAccountId());
string[] scopes = { "GroupMember.Read.All", "Group.Read.All", "Group.ReadWrite.All", "Directory.Read.All", "Directory.AccessAsUser.All", "Directory.ReadWrite.All" };
AuthenticationResult result = null;
HttpClient client = new HttpClient();
HttpRequestMessage request = new HttpRequestMessage(HttpMethod.Get, "https://graph.microsoft.com/v1.0/groups");
try
{
//Get acccess token before sending request
result = await app.AcquireTokenSilent(scopes, account).ExecuteAsync().ConfigureAwait(false);
if (result != null)
{
request.Headers.Authorization = new AuthenticationHeaderValue("Bearer", result.AccessToken);
//Request to get groups
HttpResponseMessage response = await client.SendAsync(request);
if (response.IsSuccessStatusCode)
{
ViewBag.Groups= response.Content.ReadAsStringAsync().Result;
return View("MyView");
}
}
}
catch (Exception ex)
{
Response.Write($"Error occured:{System.Environment.NewLine}{ex}");
}
return View();
}

How to validate QuickBooks's connection?

I have been integrating QuickBooks's API to my web application. I made requests to get tokens (both request token and secret token), I stored them to database. So, how can I validate connection at second time or more, I mean because I had tokens in database, so I don't want to re-authorize to get other new tokens. I tried to find solutions to resolve it, but there's no anything. Please give me some methods or advices to get it done. Thank you very much!
So, how can I validate connection at second time or more,
You can validate tokens by doing a query against a v3 service, and checking to see if you get a 200 OK or a 401 Unauthorized response back.
Pseudo-code should look something like this:
function am_i_connected_to_quickbooks()
{
if (you have tokens stored in your database)
{
results = do_qb_query("SELECT * FROM Customer MAXRESULTS 1")
if (you got a 200 OK back from Intuit)
{
// You are connected, and the tokens are still valid/have not been revoked
return true
}
}
// You don't have tokens, or your tokens are invalid (revoked, expired, incorrect, etc.)
return false
}

Validating PayPal Webhook calls with PayPal .NET SDK in Sandbox

I've been trying to set up PayPal Webhooks (in Sandbox mode) to receive notifications about declined and successful payments. My problem is that I can't get validation working. Some details about my attempts:
The app is an OWIN self-hosted Web API 2.
Hosted as an Azure Web App, tested on Azure as well.
I set the Paypal Webhook receiver URL in the Paypal dashboard to the URL of my endpoint on Azure.
I used the Paypal Webhooks simulator from the Paypal dashboard to send a message to the Azure endpoint.
I tried listening for Webhook calls two ways:
ASP.NET Webhook Receivers (http://blogs.msdn.com/b/webdev/archive/2015/09/04/introducing-microsoft-asp-net-webhooks-preview.aspx), which didn't work. I get the error message "WebHook validation failed: "
Tried creating a Web API endpoint to receive and validate the request, didn't work either. Code here:
[HttpPost]
public async Task<IHttpActionResult> PaymentCaptureCompleted()
{
// Get the received request's headers
NameValueCollection nvc = new NameValueCollection();
foreach (var item in Request.Headers)
{
nvc.Add(item.Key, string.Join(",", item.Value));
}
// Get the received request's body
var requestBody = await Request.Content.ReadAsStringAsync();
var isValid = WebhookEvent.ValidateReceivedEvent(Api, nvc, requestBody, ConfigurationManager.AppSettings["paypal.webhook.id"]);
if (isValid)
{
return Ok();
}
else
{
return BadRequest("Could not validate request");
}
}
There are a lot more details to this of course, but I'm not sure how much information is required to answer my question. Just let me know what you need and I'll edit this question.
Please refer PayPal Dot Net SDK for code samples. https://github.com/paypal/PayPal-NET-SDK
Also if your simulator is not working, to rule out if there is something wrong with the configuration of webhook or the azure, you may want to use Runscope. Ypu can configure a Runscope bucket as a webhook endpoint and If you are getting a webhook notification there, you may need to make changes in the Azure config.
Really don`t go to the documentation. It is old but objects is still good.
You can use WebhookEvent class for it.
Just use this action in your controller.
public JsonResult Index(WebhookEvent event)
{
// event has all the data
return Json(new { success = true });
}
Validation does not work for either IPN sandbox nor Webhook events from the mock. It's stated in the PayPal documentation. Validation only works on the production environment of PayPal.
Wrap WebhookEvent.ValidateReceivedEvent in a try catch. If the call fails, it can just hang without that. The exception will show you the error.
try
{
var isValid = WebhookEvent.ValidateReceivedEvent(apiContext, nv, requestBody, hookId);
}
catch(Exception e)
{
}
In my case the exception said "Unable to load trusted certificate"

Categories

Resources