简体   繁体   中英

Pay with Amazon behaving async

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 (eg P01-1234567-1234567-A000001). Once you have the authorization Id you can:

  1. 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.

  2. 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.

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM