PayPal - Updating Redirect Urls - c#

I have initiated a Paypal Payment, got a token back. PayPal has redirected back to my site using the URL I set in the Payment. From here I get the users shipping address, update the shipping costs and wait for the user to confirm payment. However, at the same time (but in a separate function) I want to update the redirect urls (actually only the return_url if that's possible). I have the following code:
RedirectUrls redirUrls = new RedirectUrls()
{
cancel_url = ppmodel.CancelUrl + "&cancel=true",
return_url = ppmodel.ReturnUrl + "?guid=" + basket.OrderGuid
};
PatchRequest pRequest = new PatchRequest();
Patch pUrls = new Patch
{
op = "replace",
path = "/redirect_urls",
value = redirUrls
};
pRequest.Add(pUrls);
payment.Update(_apiContext, pRequest); --Error here
I am getting a server error 400 Bad Request. Can anyone tell me what I am doing wrong?

Related

Post message from Website to Facebook wall

I have a website made with ASP.NET webform .NET 4.5 C#. This site contains a forum(homemade by me), parts of this forum needs to be posted to the specific facebook wall(made for this webpage). What I need :
Post just created thread(message) from specific part of the forum to the corsponding facebook wall.
Optional : Sync the forum thread on webpage with message/comments on the specific facebook page
I have looked at these guides :
http://www.codeproject.com/Articles/569920/Publish-a-post-on-Facebook-wall-using-Graph-API
http://www.c-sharpcorner.com/UploadFile/raj1979/post-on-facebook-users-wall-using-Asp-Net-C-Sharp/
But im not sure that this is really the solution for me? I have tried to follow the guide but it does not look the same.
Edit :
dynamic result;
//https://developers.facebook.com/tools/explorer/
//https://developers.facebook.com/tools/access_token/
FacebookClient client = new FacebookClient(ConfigurationManager.AppSettings["FacebookAppToken"]);
//result = client.Get("debug_token", new
//{
// input_token = ConfigurationManager.AppSettings["FacebookAppToken"],
// access_token = ConfigurationManager.AppSettings["FacebookAppToken"]
//});
//result = client.Get("oauth/access_token", new
// {
// client_id = ConfigurationManager.AppSettings["FacebookAppId"],
// client_secret = ConfigurationManager.AppSettings["FacebookAppSecret"],
// grant_type = "client_credentials",
// //redirect_uri = "http://www.MyDomain.net/",
// //code = ""
// });
result = client.Get("oauth/access_token", new
{
client_id = ConfigurationManager.AppSettings["FacebookAppId"],
client_secret = ConfigurationManager.AppSettings["FacebookAppSecret"],
grant_type = "client_credentials"
});
client.AccessToken = result.access_token;
result = client.Post("[IdOfFacebookPage]/feed", new { message = "Test Message from app" });
//result.id;
result = client.Get("[IdOfFacebookPage]");
return false;
Approach to post to a facebook wall:
You need to register in facebook developer tools.
Create a app (fill a form).
Download FGT 5.0.480 (Facebook graph toolkit)
Reference FGT dlls in your web application.
FGT has methods to post to facebook wall but needs appId.
Use the app id of your app created in step 2.
To post to an user's wall through facebook, it is only possible through an app.
Try this asp .net app, which will allow you to post in your wall:
https://apps.facebook.com/aspdotnetsample/?fb_source=search&ref=br_tf
This will allow you to envision what you need.
Your app gets an appId with which you need to generate auth token.
Limitation: The user's wall where you want to post should have added the app created at step 2, this is compulsory and there is no work around.
When the user accesses the app for the first time, it automatically asks for permission to post to wall--> the user needs to accept it.
Hope this gives you an idea on how to go about doing this.
You can then post into the user's wall.
For Banshee's below request using Facebook SDK for .NET:
userId - facebook user id, wall to post the message
This user should have added the app created by you in step 1 else it will say unauthorized access.
dynamic messagePost = new ExpandoObject();
messagePost.picture = "http://www.stackoverflow.com/test.png";
messagePost.link = "http://www.stackoverflow.com";
messagePost.name = "This is a test name";
messagePost.caption = "CAPTION 1";
messagePost.description = "Test desc";
messagePost.message = "message"
var fb = new FacebookClient();
dynamic result = fb.Get("oauth/access_token", new {
client_id = "app_id",
client_secret = "app_secret",
grant_type = "client_credentials"
});
fb.AccessToken = result.access_token;
try
{
var postId = fb.Post(userId + "/feed", messagePost);
}
catch (FacebookOAuthException ex)
{
//handle oauth exception
}
catch (FacebookApiException ex)
{
//handle facebook exception
}
You will need an extended token to publish to a wall.. Steps to get extended token is explained well by Banshee..
Edit: How to get extended token by Banshee:
Please follow this post
By creating a extended page token and use it to make the post everything works just fine. See this : How to get Page Access Token by code?
Im surprised that this simple task was so hard to get running and that there was vary little help to get.

Error in transaction processing when using SetPaymentsOptionsRequest

I'm working on integrating PayPal into a client's ecommerce site. Using the sandbox, we got everything working fine. I now need to add in SetPaymentOptionsRequest to prevent the user from changing his shipping address (they enter it on our site, so they can't change it at PayPal due to different shipping costs calculated on our site). It appears to work fine, but I get a 3005 error when logging into the PayPal sandbox site to confirm the transaction. Below is the relevant code (C#):
public string MakeChainedPayment(params params) {
var request = new PayRequest {
requestEnvelope = new RequestEnvelope("en_us"),
actionType = "CREATE",
cancelUrl = this._cancelUrl,
currencyCode = this._currencyCode,
returnUrl = this._returnUrl,
ipnNotificationUrl = this._ipnNotificationUrl
};
// Some code to generate receivers, not important for this problem, I don't think
var response = this._paymentService.Pay(request);
switch (response.paymentExecStatus) {
// This always returns "CREATED", as I'd want, so good up to here.
case "CREATED":
// If I leave this code out, PayPal works fine, but I need
// this part to do the shipping address verification.
var p = new SetPaymentOptionsRequest();
p.senderOptions = new SenderOptions();
p.senderOptions.addressOverride = false;
p.senderOptions.shippingAddress = new ShippingAddressInfo {
// Setting from params: city, country, zip, state, street1, street2
};
p.payKey = response.payKey;
p.requestEnvelope = request.requestEnvelope;
SetPaymentOptionsResponse r = _paymentService.SetPaymentOptions(payOptsReq);
break;
// This always retuns r.error.Count = 0, r.responseEnvelope.ack = "SUCCESS",
// so I think I'm good to go.
}
if (this._useSandbox) {
return string.Concat("https://www.sandbox.paypal.com/cgi-bin/webscr?cmd=_ap-payment&paykey=", response.payKey);
}
return string.Concat("https://www.paypal.com/cgi-bin/webscr?cmd=_ap-payment&paykey=", response.payKey);
}
Paypal returns this message when your Paypal account's email address has not been verified. To verify your Paypal Email account, please follow the following steps:
Log into your Paypal Account. You should be in the “Overview” tab.
Click on your Email address, under “Business account overview”, you will be taken to a Web page listing your Paypal Email addresses.
Select your Primary Adress.
Click on the “Confirm” button.
Follow the rest of the Paypal instructions.
The problem was what I was passing in for the country; I was sending in "USA", and it should be "US".

Google Analytics throws 403 error

I am attempting to download metric data from Google Analytics using C# and am performing user authentication with OAuth 2.0. I'm using the Installed Application authorisation flow, which requires logging into Google and copy-and-pasting a code into the application. I'm following the code taken from google-api-dotnet-client:
private void DownloadData()
{
Service = new AnalyticsService(new BaseClientService.Initializer() {
Authenticator = CreateAuthenticator(),
});
var request = service.Data.Ga.Get(AccountID, StartDate, EndDate, Metrics);
request.Dimensions = Dimensions;
request.StartIndex = 1;
request.MaxResults = 10000;
var response = request.Execute(); // throws Google.GoogleApiException
}
private IAuthenticator CreateAuthenticator()
{
var provider = new NativeApplicationClient(GoogleAuthenticationServer.Description) {
ClientIdentifier = "123456789012.apps.googleusercontent.com",
ClientSecret = "xxxxxxxxxxxxxxxxxxxxxxxx",
};
return new OAuth2Authenticator<NativeApplicationClient>(provider, Login);
}
private static IAuthorizationState Login(NativeApplicationClient arg)
{
// Generate the authorization URL.
IAuthorizationState state = new AuthorizationState(new[] { AnalyticsService.Scopes.AnalyticsReadonly.GetStringValue() });
state.Callback = new Uri(NativeApplicationClient.OutOfBandCallbackUrl);
Uri authUri = arg.RequestUserAuthorization(state);
// Request authorization from the user by opening a browser window.
Process.Start(authUri.ToString());
Console.Write("Google Authorization Code: ");
string authCode = Console.ReadLine();
// Retrieve the access token by using the authorization code.
state = arg.ProcessUserAuthorization(authCode, state);
return state;
}
The Google account xxxxxx#gmail.com registered the Client ID and secret. The same account has full administration rights in Google Analytics. When I try to pull data from Google Analytics, it goes through the authorisation process, which appears to work properly. Then it fails with:
Google.GoogleApiException
Google.Apis.Requests.RequestError
User does not have sufficient permissions for this profile. [403]
Errors [
Message[User does not have sufficient permissions for this profile.] Location[ - ] Reason [insufficientPermissions] Domain[global]
]
I've been struggling with this for a few hours. I've double checked that the correct user is being used, and is authorised on Google Analytics. I'm at a loss as to what is misconfigured. Any ideas as to what requires configuring or changing?
If auth seems to be working working then my suggestion is that you make sure you're providing the correct ID because based on your code snippet:
var request = service.Data.Ga.Get(AccountID, StartDate, EndDate, Metrics);
one can only assume that you're using the Account ID. If so, that is incorrect and you'd receive the error you've encountered. You need to query with the Profile ID.
If you login to Google Analytics using the web interface you'll see the following pattern in URL of the browser's address bar:
/a12345w654321p9876543/
The number following the p is the profile ID, so 9876543 in the example above. Make sure you're using that and actually you should be using the table id which would be ga:9876543.
If it isn't an ID issue then instead query the Management API to list accounts and see what you have access to and to verify auth is working correctly.
This can help : https://developers.google.com/analytics/devguides/reporting/core/v3/coreErrors, look error 403.
//Thanks for this post. The required profile id can be read from the account summaries.
Dictionary profiles = new Dictionary();
var accounts = service.Management.AccountSummaries.List().Execute();
foreach (var account in accounts.Items)
{
var profileId = account.WebProperties[0].Profiles[0].Id;
profiles.Add("ga:" + profileId, account.Name);
}

Refreshing a Google Token using Google REST API in C#

I'm wondering if anyone has solved managing the expiration of Google OAuth2 tokens?
The example below is a REST call to get a list of calendars with a valid token. If the token is expired, I will get a 401 response and need to refresh the token using the 'refresh token' stored in my database. I'm wondering if anyone has a strategy around this for their web application?
var httpContent = new HttpRequestMessage(HttpMethod.Get, "https://www.googleapis.com/calendar/v3/users/me/calendarList");
httpContent.Headers.Add("Authorization", "OAuth " + token);
responseBody = client.SendAsync(httpContent).Result.EnsureSuccessStatusCode().Content.ReadAsStringAsync().Result;
I've thought about refreshing automatically upon user logging in and saving the refresh token encrypted in session, but not sure if there are any better strategies.
//Notes
Strategy Options:
1 - Upon Logging a user in, refresh all OAuth tokens for user. This works assuming that a session will never last longer than a token timeout period. (may not be reliable for all OAuth servers).
2 - When refreshing, use token expiration to record expiration date/time in database. Before calling any API, check if token needs to be refreshed. (still need to account for edge case where token expires unexpectedly outside of normal expiration schedule)
3 - Catch the response status of the call and check for 401s. If receive a 401, refresh the token and try again. This could be a fail-over for both Options 1/2. Code for this example would be here:
var restClient = new RestClient();
var request = new RestRequest("https://www.googleapis.com/calendar/v3/users/me/calendarList", Method.GET);
request.AddHeader("Authorization", "OAuth " + token);
// execute the request
var response = restClient.Execute(request);
if (response.StatusCode == HttpStatusCode.Unauthorized)
{
var newToken = RefreshGoogleToken(token);
request = new RestRequest("https://www.googleapis.com/calendar/v3/users/me/calendarList", Method.GET);
request.AddHeader("Authorization", "OAuth " + newToken);
// execute the request
response = restClient.Execute(request);
}
var content = response.Content; // raw content as string
dynamic responseJson = JsonValue.Parse(content);
var calendarList = new List<GoogleCalendar>();
foreach (var item in responseJson.items)
{
var calendar = new GoogleCalendar { Kind = item.kind, Etag = item.etag, Id = item.id, Title = item.summary, Description = item.description, Location = item.location, Timezone = item.timeZone, SummaryOverride = item.summaryOverride, ColorId = item.colorId, AccessRole = item.accessRole };
if (item.defaultReminders != null)
{
calendar.DefaultReminders = new List<GoogleCalendarReminder>();
foreach (var reminder in item.defaultReminders)
{
var rem = new GoogleCalendarReminder { Method = reminder.method, Minutes = reminder.minutes };
calendar.DefaultReminders.Add(rem);
}
}
calendarList.Add(calendar);
}
return calendarList;
}
If the expiration time is known you can keep track of your token's expiration time and anticipate that it has already expired, then just do the refresh at that time.
I would imagine you could also simply respond to the 401 errors with a refresh as well, and even as a fail safe if the expiration tracking happens to fail (just be sure to add code to avoid getting stuck in a loop).

C#: Get a user access token

I'm developing a desktop application in C#.
After visiting https://www.facebook.com/dialog/oauth?client_id=123 the user logs in and the user access token is attached to the redirect uri. Its no problem, when the loginpage is displayed in a webbrowser control in my form, so i can extract the token from the url.
But this is not the way i want to get the token. My question is, is there a way to obtain the freshly created token via an Graph API call?
Because i want to display the login page in the user's standard browser and not in this embedded webbrowser. All my efforts to get the user access token have been resulted in getting the app access token, which is useless in this case.
Any hints are appreciated.
// This is very raw, And Note it is a MVC3 solution, but it is in C# and I hope it helps.
// It is basically a C# version of the PHP example on FB for 'Server Side Flow'
// I have been at it for a while and had to go through some pain
// Please note the bug I read about that states the redirect_uri must be the same for both //requests
// Also read that someone had an issue if the redirect_uri did not end in '/'
// Post back if you hae any ?s as I am just starting this project and am going to try and //incorporate the C# FaceBook SDK
public class AccountController : Controller
{
// LoginWithFaceBook
// First Contact with FB - oauth?client_id ... redirect_uri = /Account/FacebookLinker
// according to a bug files on FB redirect_uri MUST BE SAME FOR both trips ( to get the 'code' then exchange the code for 'access_token'
public ActionResult ConnectFaceBookAccount()
{
string APP_ID = HttpContext.Application["FacebookAppId"].ToString();
string redirect_uri = HttpContext.Application["FacebookOAuthRedirect"].ToString();
string state = HttpContext.Application["state_guid"].ToString();
// in this View I simply link to this URL
ViewBag.FaceBookOAuthUrl = "https://www.facebook.com/dialog/oauth?client_id=" + APP_ID + "&redirect_uri="+redirect_uri+"&state=" + state+"&display=popup";
return View();
}
// Account/FacebookLinker
// redirect_uri for both getting 'code' and exchanging for 'access_token'
public ActionResult FacebookLinker()
{
if (!Request.IsAuthenticated)
{
Response.Redirect("/Account/LogOn");
}
// Per FB DOC, Make sure 'state' var returned is same one you sent to reduce chance of Cross Site Forgery
if (Request.QueryString["state"].ToString() == HttpContext.Application["state_guid"].ToString())
{
try
{
string FBcode = Request.QueryString["code"].ToString();
string APP_ID = HttpContext.Application["FacebookAppId"].ToString();
string APP_SECRET = HttpContext.Application["FacebookAppSecret"].ToString();
string redirect_uri = HttpContext.Application["FacebookOAuthRedirect"].ToString();
string FBAccessUrl = "https://graph.facebook.com/oauth/access_token?client_id=" + APP_ID + "&redirect_uri=" + redirect_uri + "&client_secret=" + APP_SECRET + "&code=" + FBcode;
string accessToken = null;
// Send the request to exchange the code for access_token
var accessTokenRequest = System.Net.HttpWebRequest.Create(FBAccessUrl);
HttpWebResponse response = (HttpWebResponse) accessTokenRequest.GetResponse();
// handle response from FB
// this will not be a url with params like the first request to get the 'code'
Encoding rEncoding = Encoding.GetEncoding(response.CharacterSet);
using(StreamReader sr = new StreamReader(response.GetResponseStream(),rEncoding))
{
// parse the response to get the value of the 'access_token'
accessToken = HttpUtility.ParseQueryString(sr.ReadToEnd()).Get("access_token");
}
//TODO
// Add to the accessToken for the Logged in User.Identity to a FBUSERS Model
// WHen someone Logs in Check to see if they are also in FB
// ON Login Page add option to login with FaceBook
return View();
}
catch (Exception exp)
{
// try to get token failed
}
}
else
{
// state var form FB did not match state var sent
}
return View();
}
I think this is achievable via URL protocol handlers;
Create a custom URL protocol handler (MSDN: Registering an Application to a URL Protocol)
Create a facebook page that passes user access token to your url handler (ex. myfbapp://accesstoken/{token})
Set oauth redirect_uri to your facebook page
Parse access token in your application

Categories

Resources