Pay with Amazon behaving async - c#

I have integrated Pay with Amazon with my web app, but I have determined that capturing funds only works when I step through the code debugging, and does not happen if I don't have a break-point. To me, this indicates that a pause is necessary. I am using recurring payments. The relevant section of code is below:
...
//make checkout object
AmazonAutomaticSimpleCheckout asc = new AmazonAutomaticSimpleCheckout(billingAgreeementId);
//capture
CaptureResponse cr = asc.Capture(authId, amount, 1);
//check if capture was successful
if (cr.CaptureResult.CaptureDetails.CaptureStatus.State == PaymentStatus.COMPLETED)
{
...
//give the user the things they paid for in the database
...
return "success";
}
...
So, if I have a break-point at the capture line under //capture, then the function returns success. If I do not have the break-point, I get a runtime exception System.NullReferenceException: Object reference not set to an instance of an object. regarding the following if statement.
To me, this implies that I should be able to await the capture method.
Also note, the capture(...) method is calling the CaptureAction(...) method, just as the C# sample does.
//Invoke the Capture method
public CaptureResponse Capture(string authId, string captureAmount, int indicator)
{
return CaptureAction(propertiesCollection, service, authId, captureAmount, billingAgreementId, indicator, null, null);
}
How can I await the capture call? Am I forgetting to pass a parameter to indicate that it should execute the operation immediately?

It seems after some experimentation, that a function that will essentially achieve the wait I was performing manually using a break-point is the function CheckAuthorizationStatus(), which is also in the C# sample provided with the documentation.
So the fixed code simply adds CheckAuthorizationStatus() before calling the capture() method. CheckAuthorizationStatus() apparently loops until the state of the authorization changes. This seems somewhat kludgey to me, but seems to be how the Pay with Amazon APIs are meant to be used, as best I can tell. Corrected code below:
//make checkout object
AmazonAutomaticSimpleCheckout asc = new AmazonAutomaticSimpleCheckout(billingAgreeementId);
//capture
CaptureResponse cr;
GetAuthorizationDetailsResponse gadr = asc.CheckAuthorizationStatus(authId);
cr = asc.Capture(authId, amount, 1);
//gadr = asc.CheckAuthorizationStatus(authId);
//check if capture was succeddful
if (cr.CaptureResult.CaptureDetails.CaptureStatus.State == PaymentStatus.COMPLETED)
{
...
return "success";
}

When using asynchronous mode you will typically rely on a couple of ways of handling it. The result of AuthorizeOnBillingAgreement will return a Amazon authorization Id (e.g. P01-1234567-1234567-A000001). Once you have the authorization Id you can:
Poll GetAuthorizationDetails - This will return the authorization details which will contain the "State" of the authorization. When the state is "Open" you can then make the Capture API call passing in the authorization Id.
Wait for the Instant Payment Notification (IPN). If you have a IPN handler you can watch for it and make the capture API call as described in step 1. The IPN is usually sent within 60 seconds and it will have the final processing status (Open or Declined).
You shouldn't add an arbitrary pause. You should always check the state of the authorization before making the capture. Even if the payment status is completed you still need to check the state.

Disclaimer:
I don't implement recurring payments, only a straightforward payment - though just reading the documentation it seems similar or at least there is a synchronous option.
Because it meets my requirements, I opt for the synchronous process. In essence treating it like a "payment gateway" - give me the result "now" and I'll deal with whatever result.
Additionally, AUTH and CAPTURE in one step - again, this is based on one's operational requirement/s.
The 2 related items are:
CaptureNow=true
TransactionTimeout=0
A value of zero always returns a synchronous Open or Declined
You'll get (synchronously):
AuthorizeResult.AuthorizationDetails which will have
AmazonAuthorizationId, AuthorizationAmount, etc
AuthorizeResult.AuthorizationDetails.IdList
null on failure
otherwise it will contain the capture id (if capture was successful)
AuthorizeResult.AuthorizationDetails.IdList.member - I've only seen this to contain 1 item (the CaptureId)
You can then use the CaptureId to call GetCaptureDetails and do what you need to do after parsing the GetCaptureDetailsResponse
Again, above is based on Payments API flow (not recurring Payments/Billing Agreement) so I hope it at least helps/gives you an avenue/idea for testing the synchronous option.

Related

ohLibspotify not calling any callback after login

I'm trying to create a project where I use the ohLibspotify .Net libspotify wrapper to login to spotify and stream playlists.
As far as I can see I've set everything up the same way like in the example. First create a session like so:
SpotifySessionConfig sp_config = new SpotifySessionConfig()
{
ApiVersion = 12,
CacheLocation = "cache",
SettingsLocation = "settings",
UserAgent = "player",
ApplicationKey = Properties.Resources.appkey,
Listener = new sp_Listener()
};
sp_session = SpotifySession.Create(sp_config);
Then I call relogin() if that fails than I show the login window to the user because no stored credentials have been found. When the user has supplied me with his account details I call login(username, password, true, null). After that I'm awaiting a call back to the sp_Listener class.
In the sp_Listener class I have overridden the following functions:
SpotifySessionListener.LoggedIn(SpotifySession session, SpotifyError error)
SpotifySessionListener.ConnectionError(SpotifySession session, SpotifyError error)
SpotifySessionListener.LogMessage(SpotifySession session, string data)
The only callback that gets called is the LogMessage callback. I've hooked it up to log4net to read all the output efficiently. This is all of the LogMessageoutput:
2015-02-22 20:58:38,636 [18] DEBUG Namespace.sp_Listener - 19:58:38.634 I [c:/Users/spotify-buildagent/BuildAgent/work/1e0ce8a77adfb2dc/client/core/session/offline_authorizer.cpp:297] Unable to login offline: no such user
2015-02-22 20:58:38,649 [18] DEBUG Namespace.sp_Listener - 19:58:38.649 I [c:/Users/spotify-buildagent/BuildAgent/work/1e0ce8a77adfb2dc/client/core/session/offline_authorizer.cpp:297] Unable to login offline: no such user
2015-02-22 20:58:38,651 [14] DEBUG Namespace.sp_Listener - 19:58:38.649 E [c:/Users/spotify-buildagent/BuildAgent/work/1e0ce8a77adfb2dc/client/core/network/proxy_resolver_win32.cpp:215] WinHttpGetProxyForUrl failed
2015-02-22 20:58:38,664 [19] DEBUG Namespace.sp_Listener - 19:58:38.661 I [ap:1752] Connecting to AP ap.gslb.spotify.com:4070
2015-02-22 20:58:38,713 [19] DEBUG Namespace.sp_Listener - 19:58:38.713 I [ap:1226] Connected to AP: 193.182.7.34:4070
It seems like I must have forgotten something. I've no idea what, maybe one of you guys knows a solution.
I'm the original author of the ohLibSpotify wrapper library. I think you possibly have overlooked the need to call ProcessEvents. ohLibSpotify tries as far as possible to provide only a thin layer over libspotify. Almost everything in the libspotify docs remains relevant when you are using ohLibSpotify, and you should consider those docs your first port-of-call. https://developer.spotify.com/docs/libspotify/12.1.51/index.html
In particular:
The library itself uses multiple threads internally. To allow for synchronization between these threads, you must implement the sp_session_callbacks::notify_main_thread callback. Whenever called (from some internal thread), the application must wake up the main loop so the sp_session_process_events() function can be run.
The API itself is not thread-safe. Thus, you must take care not to call the API functions from more than one of your own threads.
The names are slightly different, but the concepts are the same - you need to implement NotifyMainThread to get notifications that libspotify wants to communicate with you, then you need to make sure that your main thread calls sp_session.ProcessEvents. You also need to make sure that only one thread ever interacts with ohLibSpotify at a time, either by coordinating so that only one thread calls ohLibSpotify, or by using appropriate locks around calls into ohLibSpotify.
(I'm using libspotify names here: the following advice applies equally whether you're using libspotify directory or ohLibSpotify.)
With a few exceptions, libspotify only ever calls your callbacks from inside a call to sp_session_process_events. (The exceptions are notify_main_thread and the callbacks associated with music delivery.) So if you're not set up to call that regularly, you'll find that libspotify doesn't do very much. If your program has an event loop, you should arrange to send yourself events whenever you receive the notify_main_thread callback or when the time specified by your last call to sp_session_process_events has passed, and call sp_session_process_events in the event handler. If you have no event loop, you might want to spawn a thread for this purpose, and make sure to use appropriate locks to stop other threads from calling into libspotify at the same time.

C#: will there be a recursion limit issue with this approach borrowed from javascript

Wondering if an approach that's possible in javascript is OK to use in C#.
In a javascript application, when a large number of web requests have to be made one after the other, the UI can be kept responsive by eschewing a for-loop, and instead, using a stack (an array) and events. The next URL is popped from the array in the success eventhandler, which keeps making another request until the stack is empty. Can a similar approach be taken in C# with a Stack? Is the following legit?
urlStack .... // stack of urls
myRequestMaker = new WebRequestMaker(); // my custom object
myRequestMaker.ResponseReceived += (s,e) =>
{
// e contains info whether the request succeeded, failed, or timed out
url = pop another url from urlStack if it's not empty
(s as WebRequestMaker).MakeWebRequest(url);
}
url = pop first url from urlStack
myRequestMaker.MakeWebRequest(url);
(The ReponseReceived event is raised by the WebRequestMaker object also when the request times out, BTW)
In javascript, you can hit maximum recursion limits using this approach, and to get around that you can wrap the method invocation, made inside the success eventhandler, in a SetTimeout. Will invokving myRequestMaker's MakeWebRequest method inside the ResponseReceived eventhandler run into analogous issues?
Yes, your code will eventually hit StackOverflowException. You can simulate setTimeout behaviour using the System.Task class that runs code asynchronously:
myRequestMaker.ResponseReceived += (s,e) =>
{
// e contains info whether the request succeeded, failed, or timed out
url = pop another url from urlStack if it's not empty
Task.Run(() => (s as WebRequestMaker).MakeWebRequest(url));
}
(of course, your urlStack now should be a concurrent to avoid racing conditions)
Optimally, you would not use the code above, but implement a MakeWebRequestAsync method that gets your job done asynchronously. Most built-in long-running/blockin methods (such as reading and writing from/to streams) in .Net already implement such a method, so if your WebRequestMaker is actually using a System.Net.WebClient you can call the async version. More information about tasks and async/await can be found in MSDN.
Yes it will, every function call pushed to the call stack and poped when it finishes.
The error you mention is fired when the call stack is full, not in javascript, in most languages (in fact I don't know any that doesn't).
You should apply the same logic as you do in Javascript here.

What's the correct way of posting this data asynchronously, and canceling/queuing new requests?

I am attempting to improve the stability of the web dashboard I have created. I have noticed that the main cause of getting into a bad state is when the user moves too quickly and requests get cut short.
For instance, I have the following javascript:
//When a resize occurs a lot of handling needs to happen to convert the user's action into
//a visibly-pleasing result. In addition, the server has to be spoken with in order to save the controls.
function OnClientResizing(pane, eventArgs) {
eventArgs.set_cancel(true);
var parameters = new Array();
parameters.push("Resize");
parameters.push(pane.get_id());
parameters.push(eventArgs.get_delta());
__doPostBack(pane.get_splitter()._uniqueID, parameters);
}
This function passes the hard work back to the server, so that it can calculate the appropriate ways to resize the controls on the page during resizes. This takes X seconds. If the user then resizes the page again before X seconds has elapsed -- I enter into a bad state. Either the old request gets cut off prematurely, or the new one runs at the same time. Either way, controls become mishapen on the page.
As such, I would like to queue future resizes, or play around with canceling current requests. I read that the best way to do something like this is to simply set a flag outside the scope of this function. I can do that, but I am not sure how to detect the end of a doPostBack. Am I supposed to change the javascript variable from the server-side somehow in PageRequestManager - EndRequest?
Cheers
First off, don't let your server participate in UI resize algorithms. Do that entirely client side. You can send resulting data to the server at any time, but don't make a real-time UI positioning depend upon a server response. That should be handled client-side with CSS or javascript logic.
Second off, if your code can't handle two ajax calls in flight at the same time, then your options are as follows:
Fix your code so it can handle sequential ajax responses in flight at the same time.
Cancel/ignore the first ajax response the moment you send a second one so that you ignore the response from the first and wait for the response from the second.
Prevent a second ajax request until the first one completes. I wouldn't suggest queueing them because that's just going to lead to an even worse user experience.
The details of how to do 1, 2 or 3 depend upon how your code works which you have not yet shared.
The easiest is option 3). That can be done with just a global flag. Just define a global variable, set it to true when you start an ajax call and clear it when the ajax call completes (in a completion function):
var ajaxInFlight = false; // global declaration
function OnClientResizing(pane, eventArgs) {
if (ajaxInFlight) return; // do nothing if ajax call already in flight
ajaxInFlight = true;
eventArgs.set_cancel(true);
var parameters = new Array();
parameters.push("Resize");
parameters.push(pane.get_id());
parameters.push(eventArgs.get_delta());
__doPostBack(pane.get_splitter()._uniqueID, parameters);
}
function postBackCompletionHandler(id, parms) {
ajaxInFlight = false; // clear global flag, ajax call done
// ... rest of your function here
}
You will also have to make sure that error conditions are handled so that the global flag is reset if the ajax call fails for any reason.

Calling a webservice async

Long post.. sorry
I've been reading up on this and tried back and forth with different solutions for a couple of days now but I can't find the most obvious choice for my predicament.
About my situation; I am presenting to the user a page that will contain a couple of different repeaters showing some info based on the result from a couple of webservice calls. I'd like to have the data brought in with an updatepanel (that would be querying the result table once per every two or three seconds until it found results) so I'd actually like to render the page and then when the data is "ready" it gets shown.
The page asks a controller for the info to render and the controller checks in a result table to see if there's anything to be found. If the specific data is not found it calls a method GetData() in WebServiceName.cs. GetData does not return anything but is supposed to start an async operation that gets the data from the webservice. The controller returns null and UpdatePanel waits for the next query.
When that operation is complete it'll store the data in it's relevant place in the db where the controller will find it the next time the page asks for it.
The solution I have in place now is to fire up another thread. I will host the page on a shared webserver and I don't know if this will cause any problems..
So the current code which resides on page.aspx:
Thread t = new Thread(new ThreadStart(CreateService));
t.Start();
}
void CreateService()
{
ServiceName serviceName = new ServiceName(user, "12345", "MOVING", "Apartment", "5100", "0", "72", "Bill", "rate_total", "1", "103", "serviceHost", "password");
}
At first I thought the solution was to use Begin[Method] and End[Method] but these don't seem to have been generated. I thought this seemed like a good solution so I was a little frustrated when they didn't show up.. is there a chance I might have missed a checkbox or something when adding the web references?
I do not want to use the [Method]Async since this stops the page from rendering until [Method]AsyncCompleted gets called from what I've understood.
The call I'm going to do is not CPU-intensive, I'm just waiting on a webService sitting on a slow server, so what I understood from this article: http://msdn.microsoft.com/en-us/magazine/cc164128.aspx making the threadpool bigger is not a choice as this will actually impair the performance instead (since I can't throw in a mountain of hardware).
What do you think is the best solution for my current situation? I don't really like the current one (only by gut feeling but anyway)
Thanks for reading this awfully long post..
Interesting. Until your question, I wasn't aware that VS changed from using Begin/End to Async/Completed when adding web references. I assumed that they would also include Begin/End, but apparently they did not.
You state "GetData does not return anything but is supposed to start an async operation that gets the data from the webservice," so I'm assuming that GetData actually blocks until the "async operation" completes. Otherwise, you could just call it synchronously.
Anyway, there are easy ways to get this working (asynchronous delegates, etc), but they consume a thread for each async operation, which doesn't scale.
You are correct that Async/Completed will block an asynchronous page. (side note: I believe that they will not block a synchronous page - but I've never tried that - so if you're using a non-async page, then you could try that). The method by which they "block" the asynchronous page is wrapped up in SynchronizationContext; in particular, each asynchronous page has a pending operation count which is incremented by Async and decremented after Completed.
You should be able to fake out this count (note: I haven't tried this either ;) ). Just substitute the default SynchronizationContext, which ignores the count:
var oldSyncContext = SynchronizationContext.Current;
try
{
SynchronizationContext.SetSynchronizationContext(new SynchronizationContext());
var serviceName = new ServiceName(..);
// Note: MyMethodCompleted will be invoked in a ThreadPool thread
// but WITHOUT an associated ASP.NET page, so some global state
// might be missing. Be careful with what code goes in there...
serviceName.MethodCompleted += MyMethodCompleted;
serviceName.MethodAsync(..);
}
finally
{
SynchronizationContext.SetSynchronizationContext(oldSyncContext);
}
I wrote a class that handles the temporary replacement of SynchronizationContext.Current as part of the Nito.Async library. Using that class simplifies the code to:
using (new ScopedSynchronizationContext(new SynchronizationContext()))
{
var serviceName = new ServiceName(..);
// Note: MyMethodCompleted will be invoked in a ThreadPool thread
// but WITHOUT an associated ASP.NET page, so some global state
// might be missing. Be careful with what code goes in there...
serviceName.MethodCompleted += MyMethodCompleted;
serviceName.MethodAsync(..);
}
This solution does not consume a thread that just waits for the operation to complete. It just registers a callback and keeps the connection open until the response arrives.
You can do this:
var action = new Action(CreateService);
action.BeginInvoke(action.EndInvoke, action);
or use ThreadPool.QueueUserWorkItem.
If using a Thread, make sure to set IsBackground=true.
There's a great post about fire and forget threads at http://consultingblogs.emc.com/jonathangeorge/archive/2009/09/10/make-methods-fire-and-forget-with-postsharp.aspx
try using below settings
[WebMethod]
[SoapDocumentMethod(OneWay = true)]
void MyAsyncMethod(parameters)
{
}
in your web service
but be careful if you use impersonation, we had problems on our side.
I'd encourage a different approach - one that doesn't use update panels. Update panels require an entire page to be loaded, and transferred over the wire - you only want the contents for a single control.
Consider doing a slightly more customized & optimized approach, using the MVC platform. Your data flow could look like:
Have the original request to your web page spawn a thread that goes out and warms your data.
Have a "skeleton" page returned to your client
In said page, have a javascript thread that calls your server asking for the data.
Using MVC, have a controller action that returns a partial view, which is limited to just the control you're interested in.
This will reduce your server load (can have a backoff algorithm), reduce the amount of info sent over the wire, and still give a great experience to the client.

ASMX webservices with Silverlight Async confusion

I have a silverlight 4 web app that needs to communicate with a server by accessing the ASMX web service on the server.
I have a list(yes, the array), of objects that I need to send(one by one) as a parameter to the service. However looping through the list and running the method(objecttosend); will not work because I need to send then one after another and Silverlight seems to only support Async(presumably to not lockup interface - makes sense).
So I tried this:
public void SendNextPart()
{
if (partsToSend.Count > 0)
{
Part thisPart = partsToSend.Dequeue();
fuWS.createPartCompleted += new EventHandler<System.ComponentModel.AsyncCompletedEventArgs>(fuWS_createPartCompleted);
fuWS.createPartAsync(thisPart);
}
}
Queue<Part> partsToSend = new Queue<Part>();
void fuWS_createPartCompleted(object sender, System.ComponentModel.AsyncCompletedEventArgs e)
{
SendNextPart();
}
Which, as far as I can understand it, will check to see if the List has parts to send, then run the webservice(called fuWS) method and delete that part from the partsToSend List. Once it gets the completed event it should then run the SendNextPart method again and send the next part.
However what is happening(picked this up by watching HTTPwatch) is that it sends the first part, then after that is sends 2 parts at once and then after that more and more, all at once. Almost as if it is receiving the completed event before it has actually sent to the server and run the method successfully.
Please help, this is bugging the hell out of me, and it completely breaks what I need to do :'(
I don't see the SendNextBuffer method that you're calling in the web service callback event handler. But in any case, at best your code has a race condition. If the web service completes and returns before the partsToSend.RemoveAt line is executed (theoretically possible) then you could be making the next request before you've removed the one you just sent.
So first, you should check to make sure you've included all the code in your example unless you meant for SendNextBuffer to say SendNextPart.
Secondly, you should move the partsToSend.RemoveAt line before the web service call.
Finally, you should probably change the partsToSend list into a Queue<Part> (first in, first out) or Stack<Part> (last in, first out) instead since that is what you're using it as.
Ok, so after using Debug.WriteLine, I realized that I was being an idiot.
Check out this line:
fuWS.createPartCompleted += new EventHandler<System.ComponentModel.AsyncCompletedEventArgs>(fuWS_createPartCompleted);
What this was doing was adding a new event handler every time it had to send a new part. So the second part sending now had two callback then the third would have more and so on increasing exponentially.

Categories