Reputation: 1071
I'm integrating Amazon pay with my website, using the v2 c# SDK from amazon (MVC App), in the sandbox. Setup is all good, I created the keys, return urls, etc.
In my checkout process, I create the CheckoutSession, which is successful. I click on the Amazon Pay button, log in using my test buyer account, and "pay" for the item using their valid test credit card.
Amazon redirects to my return URL with the checkout session id as expected.
When I try to CompleteCheckoutSession, the result is an error back from the Amazon API
error: InvalidCheckoutSessionStatus
message: You tried to call an operation on a Checkout Session that is in a state where that operation is not allowed
I put in a test line of code to retrieve the CheckoutSession to look at it before I try to complete it, and it shows that the current status is "Open", which is the correct status when trying to complete it, so I'm at a loss at why the checkout session status is invalid.
EDIT:
Note I'm using this flow for my transaction, so there is no "review" of the transaction. Buyer chooses his items on my site.
Also note, I'm creating the payload dynamically according to this:
So when the amazonpay button is clicked, it calls a method on my site which builds the payload which begins the CheckoutSession. I then have the Amazon Session ID in my cache which I save it, and save the total. The payload is returned to the Amazon pay script which then takes me to the Amazon Site. I choose the payment type and click "continue to checkout", which sends me back to my site with the SessionId to do the "complete" step.
My request to CompleteCheckoutSession(sessionId)
{"chargeAmount":{"amount":99,"currencyCode":"USD"}}
result.RawResponse from the client.CompleteCheckoutSession(sessionId) method:
{
"reasonCode":"InvalidCheckoutSessionStatus",
"message":"You tried to call an operation on a Checkout Session that is in a state where that operation is not allowed"
}
EDIT SAMPLE CODE:
I created a brand new test MVC app with basic functionality:
public ActionResult Index()
{
var client = InitiateClient(); //hidden for security
// prepare the request
var request = new CreateCheckoutSessionRequest
(
checkoutReviewReturnUrl: "http://localhost:44300/home/completecheckout",
storeId: "amzn1.application-oa2-client.mystoreid"
);
request.PaymentDetails.PaymentIntent = Amazon.Pay.API.WebStore.Types.PaymentIntent.AuthorizeWithCapture;
request.PaymentDetails.ChargeAmount.Amount = 99;
request.PaymentDetails.ChargeAmount.CurrencyCode = Currency.USD;
// generate the signature and payload string that is passed back to the frontend
ViewBag.Signature = client.GenerateButtonSignature(request);
ViewBag.Payload = request.ToJson();
return View();
}
In the Index.cshtml file:
<div id="AmazonPayButton"></div>
<script src="https://static-na.payments-amazon.com/checkout.js"></script>
<script type="text/javascript" charset="utf-8">
amazon.Pay.renderButton('#AmazonPayButton', {
merchantId: 'mymerchantid',
ledgerCurrency: 'USD',
sandbox: true,
checkoutLanguage: 'en_US',
productType: 'PayOnly',
placement: 'Checkout',
buttonColor: 'Gold',
createCheckoutSessionConfig: {
payloadJSON: '@Html.Raw(ViewBag.Payload)', // string generated in step 2
signature: '@Html.Raw(ViewBag.Signature)', // signature generated in step 3
publicKeyId: 'AGPTYXGL5VH6PSYLJUSHTKW6'
}
});
</script>
And finally, the completecheckout code, which is unsuccessful:
public ActionResult CompleteCheckout(string amazonCheckoutSessionId)
{
var client = InitiateClient(); //hidden for security
var request = new CompleteCheckoutSessionRequest(99.00M, Currency.USD);
// send the request
var result = client.CompleteCheckoutSession(amazonCheckoutSessionId, request);
// check if API call was successful
if (!result.Success)
{
throw new Exception("API Call unsuccessful");
}
return View();
}
NOTE: certain keys obfuscated, but actual keys are in the sample code.
Upvotes: 2
Views: 2943
Reputation: 31
I had a similar issue and it takes me a very long time to figure it out. This is what happened to me.
I was not intent to create production code. I just want to create a test page with only Amazon Pay button. I used several node js script to getCheckoutSession/updateCheckoutSession
. However, when I tried completeCheckoutSession
, I got "InvalidCheckoutSessionStatus".
In the end, I found, after I setup all the required parameter and remove all constraint, the updateCheckoutSession
gives me a "amazonPayRedirectUrl
" in API return. That URL is really important. You need to go that URL in order to complete the review...
This is from Amazon official website:
"Once there are no constraints, the response will return a unique amazonPayRedirectUrl. Redirect the buyer to that URL to complete checkout."
The other way to solve this issue is mentioned by "Daniel Lemke". In that way, shoppers don't need to confirm the session. However, you need to make sure to provide all useful information in webCheckoutDetails
(paymentDetails, addressDetails). If you only give checkoutMode
, you will get "MissingParameterValue".
This is from Amazon official website:
"paymentDetails is required when using 'ProcessOrder'. addressDetails is also required if you use 'ProcessOrder' with productType set to 'PayAndShip'"
Upvotes: 3
Reputation: 2459
Manually creating the CheckoutSession doesn't work with the "no review page" flow that you are following. If you want to integrate this flow, you'll have to let Amazon Pay create the CheckoutSession for you using the createCheckoutSessionConfig parameter in the button code, see here: https://amazonpaycheckoutintegrationguide.s3.amazonaws.com/amazon-pay-apb-checkout/add-the-amazon-pay-button.html#4-render-the-button
EDIT:
The code sample below shows how to construct the payload and signature for the 'no order review' payment flow. Please note the CheckoutMode parameter, that instructs Amazon Pay to immediately process the payment, and the checkoutResultReturnUrl, that defines the URL where the buyer is sent to for completing the checkout. When the user arrives at that URL, you will have to call Complete CheckoutSession, which should now succeed.
public ActionResult Index()
{
var client = InitiateClient(); //hidden for security
// prepare the request
var request = new CreateCheckoutSessionRequest
(
checkoutReviewReturnUrl: null,
storeId: "amzn1.application-oa2-client.mystoreid"
);
// instructs Amazon Pay to immediately process the payment
request.WebCheckoutDetails.CheckoutMode = CheckoutMode.ProcessOrder;
request.WebCheckoutDetails.CheckoutResultReturnUrl = "http://localhost:44300/home/completecheckout";
// payment details
request.PaymentDetails.PaymentIntent = Amazon.Pay.API.WebStore.Types.PaymentIntent.AuthorizeWithCapture;
request.PaymentDetails.ChargeAmount.Amount = 99;
request.PaymentDetails.ChargeAmount.CurrencyCode = Currency.USD;
// generate the signature and payload string that is passed back to the frontend
ViewBag.Signature = client.GenerateButtonSignature(request);
ViewBag.Payload = request.ToJson();
return View();
}
Upvotes: 3