Need PayPal PDT Sample Code in Client JavaScript - javascript

I'm new to PayPal and its PDT. I've searched through many posts but they require Node.js or PHP to implement it. I don't have both, but I just want a simple return from PayPal PDT, telling my download.html that the purchase was successful so that I can safely display the product key to my customers and allow them to download my digital product, otherwise I will do something like this in my JavaScript:
If (purchaseFailed) {
window.location.replace('/404.html');
}
The reason that I do that is to prevent direct access to my download.html and reveal the product key without making a payment through PayPal.
I've enabled my PayPal PDT and specified the return URL, but I just do not know how to write the JavaScript to get the return the status from PayPal. I do not need to display any transaction detail to my customers except a 'thank you' message, the product key, and the download link (but if you can show some sample on getting the transaction details, e.g. product code and customer email address, that would help too). Can somebody help me with some simple JavaScript that my Google Blogger HTML can execute it? Thanks a lot!

PDT is completely unreliable, because returns are never guaranteed to happen, due to browser/network crashes or the customer not waiting for the auto-return (there is a timer) or not clicking through to return (typically guests w/o an account must be shown a receipt and click to return). So PDT is suitable for informational purposes only (e.g. showing buyers a thank you message when they do return.).
Absolutely no business logic such as downloads should depend on a PDT return actually occurring.
Instead, if you need a dependable notification from PayPal of payment completion, an asynchronous IPN or one of the newer webhooks should be listened for -- or alternatively, the integration should be changed to a more robust synchronous server-side one such as this pattern: https://developer.paypal.com/demo/checkout/#/pattern/server , where there is always an immediate API response on payment capture for notification purposes.
Blogger's HTML/JS does not provide any of the necessary listening or API capabilities, of course.

Related

Stripe collect payment later workflow Node/Express/EJS

I am working on the payment portion of an app using Stripe and having trouble trying to figure out the best way to route customers. Essentially, the way the app is supposed to work is:
Customer goes to site to enters payment details.
Payment is broken into two parts the Fee and the Deposit.
Customer submits payment details.
If the funds are validated they are brought to a success page.
If the funds are not validated they get an error page.
Later, the funds are captured either with or without the deposit amount.
I have Stripe set up where I am creating the payment intent with capture_method: 'manual' set so I can capture the funds later. I am passing the client secret to the front via EJS, and using stripe.confirmCardPayment() to 'run' the card. All of that seems to be working fine and they are correctly showing up in my Stripe dashboard as uncaptured payments. So, from here what is the best way to route the user to the correct page after the card is 'run'. In other words, if the funds are there then route to success pages, otherwise route to an error page. There needs to be some validation on the server side otherwise the customer could just directly visit the success page route without paying. Thanks for any help and ideas!
stripe.confirmCardPayment returns a Promise that resolves with result.error if there were errors (like the charge declined) or with result.paymentIntent if the PaymentIntent confirmation succeeds: https://stripe.com/docs/js/payment_intents/confirm_card_payment
Once your confirmCardPayment() Promise resolves, you can look at result.paymentIntent.status (which in your case would be requires_capture).
During this, you can make any arbitrary calls to your server (like pass the PaymentIntent/Customer ID and update your database) and then redirect your customer to the success/failure page accordingly.

Paypal Smart Checkout – Multiple merchant ids throw error

On a checkout page, loading the PayPal Javascript SDK, I provide multiple merchant-ids like this (where [my_client_id] is replaced with my id, of course), the email addresses shown have been modified for privacy reasons:
<script src="https://www.paypal.com/sdk/js?client-id=[my_client_id]&currency=EUR&locale=de_DE&merchant-id=*"
data-merchant-id="lobo***#gmail.com,suic***#squar***.de,einkauf#***-games.de,paypal#***.events,***#kst***.at"></script>
I then create a separate Paypal Smart button for each of the merchants. But although I provide the multiple merchant-ids, I will get the following error as soon as a payment button is clicked:
Error: Payee(s) passed in transaction does not match expected merchant
id. Please ensure you are passing merchant-id=****55TUNG or
merchant-id=lobo***#gmail.com to the sdk url.
But that merchant-id is provided in the URL as you can see above. If I press another merchant's pay button, I get the same error message but with that merchant's id listed in the error message.
The payee passed by the PHP script using createOrder is the corresponding email address of the merchant 100 percent correctly.
Is this a bug in the PayPal SDK or am I listing the merchant-ids maybe in the wrong way in the SDK-URL (though it is the way PayPal has described it a discussion on github)?
IMPORTANT SIDE NOTE: If I totally omit providing the merchant-ids in the SDK-URL, I get Javascript warnings about the missing merchant-id, but the payment buttons work just fine (which makes me sure that the PHP backend script is working 100 percent correctly), the payments are being processed.
What interesting, too: If I omit the merchant-ids in the SDK-URL, PayPal will render four different payment options, if I include the merchant-ids in the URL, then only two are shown (and both of them will throw the error).
All of this is referring to production mode.
Only pass a single merchant-id, and have it correspond to the payee that you are going to use.
Alternatively, pass no merchant-id at all, for transaction types that don't require it.

How to block the link from malicious bot visitors?

I'm producing an event registration website. When someone click on a link:
Reserve id=10 event
The system is doing a "lock" on this event for ten minutes for this visitor. In that case no one else can reserve this event in next ten minutes. If the payment is done in that time, everything is OK, else the event is unlocked again. I hope the idea is clear.
PROBLEM: When bot (google bot, malicious bot, or angry customer script :P) visits this page, he see this link. Then he enters the page. Then the lock is done...
Also if someone visit recursive: /reserve/1, /reserve/2, /reserve/3, ... He can lock all the events.
I thought about creating a random md5 string for each event. In that case, every event has (next to id) unique code, for example: 1987fjskdfh938hfsdvpowefjosidjf8243
Next, I can translate libraries, to work like this:
<a href="/reserve/1987fjskdfh938hfsdvpowefjosidjf8243" rel="nofollow">
Reserve
</a>
In that case I can prevent the "bruteforce" lock. But the link is still visible for bots.
Then I thought about entering the captcha. And that is the solution. But captchas are... not so great in case of usability and user experience.
I saw few websites with reservation engine working like this. Are they protected? Maybe there is a simple ajax / javascript solution to prevent the bots from reading this as a pure text? I thought about:
Reserve
<script type="text/javascript">
$('#reserve').click(function(e) {
e.preventDefault();
var address = ...;
// something not so obvious to follow?
// for example: md5(ajaxget(some_php_file.php?salt=1029301))
window.location('/reserve/' + address);
});
</script>
But I'm not sure what shall I do there to prevent bots form calculating it. I mean stupid bots will not be able even to follow javascript or jquery stuff, but sometimes, someone wants to destroy something, and if the source is obvious, it can be broken in few lines of code. And whole database of events will be locked down with no reservation option for noone.
CRFS + AJAX POST + EVENT TOKEN generated on each load.
Summary: don't rely on GET requests especially through a elements.
And better if you add some event block rate limits (by IP for instance).
EDIT: (this is a basic sketch)
replace all the href="..." with data-reservation-id=ID
delegate click on the parent element for a[data-reservation-id]
in the callback, simply make a POST ajax call to the API
in the API's endpoint check rate limits using IP for instance
if OK, block the event and return OK, if not return error.
IP-Specific maximum simultaneous reservations
Summary: Depend on the fact that many simple bots operate from one host. Limit the number of simultaneous reservations for a host.
Basic scetch:
Store the requesting IP alongside the reservation
On reservation request count the IP's which have a non-completed reservation.
SELECT Count(ip) FROM reservations WHERE ip=:request_ip AND status=open;
If the number is above a certain threshold, block the reservation.
(this is mostly an expansion of point 4 given in avetist's excellent answer)

How to check failed recurring subscription Stripe

How should I design an on-login middleware that checks if the recurring subscription has failed ? I know that Stripe fires events when things happen, and that the best practice is webhooks. The problem is, I can't use webhooks in the current implementation, so I have to check when the user logs in.
The Right Answer:
As you're already aware, webhooks.
I'm not sure what you're doing that webhooks aren't an option in the current implementation: they're just a POST to a publicly-available URL, the same as any end-user request. If you can implement anything else in Node, you can implement webhook support.
Implementing webhooks is not an all-or-nothing proposition; if you only want to track delinquent payments, you only have to implement processing for one webhook event.
The This Has To Work Right Now, Customer Experience Be Damned Answer:
A retrieved Stripe Customer object contains a delinquent field. This field will be set to true if the latest invoice charge has failed.
N.B. This call may take several seconds—sometimes into the double digits—to complete, during which time your site will appear to have ceased functioning to your users. If you have a large userbase or short login sessions, you may also exceed your Stripe API rate limit.
I actually wrote the Stripe support team an email complaining about this issue (the need to loop through every invoice or customer if you're trying to pull out delinquent entries) and it appears that you can actually do this without webhooks or wasteful loops... it's just that the filtering functionality is undocumented. The current documentation shows that you can only modify queries of customers or invoices by count, created (date), and offset... but if you pass in other parameters the Stripe API will actually try to understand the query, so the cURL request:
https://api.stripe.com/v1/invoices?closed=false&count=100&offset=0
will look for only open invoices.... you can also pass a delinquent=true parameter in when looking for delinquent customers. I've only tested this in PHP, so returning delinquent customers looks like this:
Stripe_Customer::all(array(
"delinquent" => true
));
But I believe this should work in Node.js:
stripe.customers.list(
{delinquent:true},
function(err, customers) {
// asynchronously called
});
The big caveat here is that because this filtering is undocumented it could be changed without notice... but given how obvious the approach is, I'd guess that it's pretty safe.

Implementing digital goods express checkout without javascript

Is it possible to implement express checkout for digital goods without having to use javascript? I want my website not to depend on clients having javascript enabled and can live with customers being redirected to PayPal's pages to authorize payment. Can I simply redirect the user to https://www.paypal.com/cgi-bin/webscr?cmd=_express-checkout &token=APIToken instead of https://www.paypal.com/incontext?token=APIToken after the call to setexpresscheckout if I mark the transaction as a digital goods one (noshipping=1, etc.)?
The answer to your question is: yes.
Don't change anything about your initial API call
Like you mentioned, after you get your API token from paypal redirect the user to: https://www.paypal.com/cgi-bin/webscr?cmd=_express-checkout&token=APIToken
If you are transitioning from js, remember to remove the paypal script tag and the code that converts your link into a popup:
new PAYPAL.apps.DGFlow({ trigger: "link_id" })

Categories

Resources