PART 4 of my Code //It took me 5 days to figure out everything above, then another 5 days to figure out this sectioin below
//The PayPal docs for v2 are so messed up with regard to the onApprove, onCancel, and onError
//I figured the following out after reading the pain and suffering from dozens of other developers
//trying to accomplish this for the last 2 years.
//Point of note: The onError suggestion in the docs seems useless. I have a feeling there is more to it
//than what is documented, but the docs are limited. Why would we, as developers, want to simply show an error
//message to the buyer instead of an actual error code that we can interpret and make look pretty?
//I also found that there seemed to be no way to grab the orderID from within the onError function, which
//make the entire onError function seem pointless because you then have now way to even track the attempted payment.
//Therefore, I am using the onAuthorize to capture both the successfule and unsuccessful payment attempts
onApprove: function(data, actions) {
return actions.order.capture().then(function (details) {
//All of the alerts you see are for testing purposes only. When your website is fully functional, you
//should not rely on these alerts. A better user experience is to grab the results and have your website react accordingly
//This alert is just here to show me were I am in the capture process
alert('Transaction completed by ' + details.payer.name.given_name);
//I create a variable for the URL I'm using to save the transaction results
var EXECUTE_URL = '[paypalsave]?mycart=[mycart]&hash=[hash]&sd=[numseed]';
//Initially I didn't like the idea of fetch, I preferred to either redirect directly like we could in v1 of checkout.js
//but that ability to redirect and capture the JSON result seems to be gone now. IMHO that is stupid and sad.
//Now we have to grab the JSON and save it before redirecting the buyer to the final page of the site.
fetch(EXECUTE_URL, {
method: 'post',
headers: {
'content-type': 'application/json'
},
body: JSON.stringify({
orderID: data.orderID, //This variable is suggested in the docs
payerID: data.payerID, //This variable is also suggested in the docs
//I also tried to grab data.status and save that, but 'status' is a reserved word and therefore it can't be easily grabbed from the JSON
amtpaid: details.purchase_units[0].amount.value, //I'm grabbing this to speed up the processing steps on my end
invoice_id: details.purchase_units[0].invoice_id, //I'm grabbing this to cross refrence my own shopping cart variable "mycart" to the invoice_id. They should be the same
finalstate: details.purchase_units[0].payments.captures[0].final_capture //This will be set to "true" if the payment was successful. I'm using this in place of my attempt to grab data.status as mentioned above
})
//Here's where things get interesting. I now do a test to make sure the fetch actually worked.
//This is where I test if the network error broke the fetch.
}).then (response => {
//If the fetch response if NOT ok, then I am goint to try doing a redirect to my next screen with URL variables that will pass along the state
//as well as a "fetcherror" variable to tell me the fetch broke
//I thought about skipping the fetch all together and just redirecting to the next page with the URL and the GET, but then I
//realized that more information could be sent in the fetch, and since it's a POST, there's a little more security.
//I'm also planning for future expansion when I can grab more information from the PayPal results and fetch them over to safety
if (!response.ok) {
//I'm building me redirect URL here
var uri = "[paypalreturn]&fetcherror=T&orderid="+data.orderID+"&payerID="+data.payerID+"&finalstate="+details.purchase_units[0].payments.captures[0].final_capture;
//Since the redirect is a GET, the URL needs to be encoded
var res = encodeURI(uri);
//The console message is used in testing. I had the location.href commented out during testing so I could see the console errors in DevTools of my browser
console.log('res',res);
//When redirecting at this point I already know that the payment was successful and teh rest of the script below doesn't matter to me any more
//I'm actually redirecting the buyer to the thank you page right here, but the extra added URL variables will tell my thank you page that there
//was something wrong with the fetch to save the JSON, and it will process the results differently
location.href=res;
}
});
//If the script gets to this point I know that the fetch above was successful. If the fetch wasn't successful I would have already been redirected away from this page
//I'm showing myself messages in the colsole only for testing. In production I comment the colsole lines out or just delete them
console.log('given_name'); console.log(details.payer.name.given_name);
console.log('return to [paypalreturn]');
//This is where I would notmally redirect the buyer to the thank you page
//Under normal conditions I do not have to send any GET variables to the thank you page. The fetch saved JSON will be waiting for me over there
location.href = '[paypalreturn]';
})
//And now we handle the errors. This is how I capture errors and display usable mesages that I could not get from onError as suggested in the docs.
//This catch will recognize when the return actions.order.capture() above fails
.catch(error => {
//The alert is just for my own testing. It is commented out or deleted in production mode
alert('error inside approve ');
//These console messages are also for testing. They are commented out or deleted in production mode
console.log ('error inside approve');
console.log ('orderID',data.orderID);
console.log ('payerID',data.payerID);
//Similar to what I did above, this is just prepwork for my fetch URL
var EXECUTE_URL = '[paypalsave]?mycart=[mycart]&hash=[hash]&sd=[numseed]';
fetch(EXECUTE_URL, {
method: 'post',
headers: {
'content-type': 'application/json'
},
//As I studied the PayPal v2 SDK docs I could not figure out how to grab any usable results from the onError.
//specifically, I needed to orderID so I could track the failed order and help a buyer.
//I saw several other people on this forum request a way to get order details and at least one PayPal Emploee tell them to use the onError function
//I really felt like someone was singing "there's a hole in the bucket, dear Liza, dear Liza" and no one was paying attention
//By including the error capture within the onAuthorize I found that the order variable are still available
//That's exactly why this is here, and you'll notice that I removed the onError from my script
body: JSON.stringify({
orderID: data.orderID,
payerID: data.payerID,
capturestatus:'ERROR' //This is my identifier that there's a problem. I can use the orderID on the next screen to lookup the order and figure out what went wrong
})
//Similar to above, this next part is protection against a potential network error during the fetch.
}).then (response => {
//Same as before, if the fetch result is NOT ok, then we will prepare a GET and redirect to the next page
if (!response.ok) {
//Prepping my next URL, it has the same info as the fetch.
var uri = "[paypalreturn]&fetcherror=T&orderid="+data.orderID+"&payerID="+data.payerID+"&capturestatus=ERROR";
//Once again, since this is a URL I need to encode the URI or spacing and other characters might break it
var res = encodeURI(uri);
//The console message is only for testing. I had the location.href commented out for testing.
//The consol line will be deleted or commented out for production
console.log('res',res);
location.href=res;
}
});
//If the fetch worked correctly, then this is where I expect to be.
//The console line is only for testing. It iw commented out or deleted for production
console.log('return to [paypalreturn]');
//The location.href was commented out for testing. This is where I jumpt the buyer to the next page
//My next page is actually my thank you page, but when I get there I'll find the fetch JSON telling me that there was an error
//Instead of showing the thank you I will use the data.orderID that I was able to save then ping PayPal to find out what the error was
//I built an error table on my website to translate the PayPal errors into something understadable by the buyer.
//I also built an email notification feature into my error routine that tells the seller that there is a purchase error along with all the details from PayPal
location.href = '[paypalreturn]';
});
},
//The onCancel works as expected. Perhaps the only part of this entire v2 SDK that worked without a single problem
onCancel: function(data) {
location.href='[paypalcancel]';
},
}).render('#paypal-button-container');
</script>
... View more