How to prevent duplicate PayPal payments? - paypal

I have a simple Pay Now button, the code created through the button maker, with a "custom" hidden field added to identify it.
I wonder if there is some additional hidden field I can add to tell PayPal that "This transaction should not be made twice".
<form action="https://www.sandbox.paypal.com/cgi-bin/webscr" method="post">
<input type="hidden" name="cmd" value="_s-xclick">
<input type="hidden" name="custom" value="{MYUNIQUEID}">
<input type="hidden" name="hosted_button_id" value="{MYHOSTEDBUTTONID}">
<input type="image" src="https://www.sandbox.paypal.com/en_US/i/btn/btn_paynowCC_LG.gif"
border="0" name="submit" alt="PayPal - The safer, easier way to pay online!">
<img alt="" border="0" src="https://www.sandbox.paypal.com/en_US/i/scr/pixel.gif" width="1" height="1">
</form>
As it is now it's unlikely that the customer should be able to pay twice, but I noticed that when the Sandbox had a glitch I succeeded in paying the same transaction twice. Something that I absolutely want to avoid. Not just for the customer, that could get refunded, sure, but also since I don't want my database messed up and I would like to avoid extensive coding to catch duplicate payments...

You would want to add a unique identifier to the "invoice" parameter; <input type="hidden" name="invoice" value="your unique invoice ID"> and enable "Block duplicate payments" within the 'Profile' > 'My selling tools' section on your account at www.paypal.com

Thanks Robert! (above post)
I actually went so far that I was going to ask PayPal Merchant Technical Support about it and just before submitting my question there found a page with the answer -
Avoiding duplicate payments:
https://ppmts.custhelp.com/app/answers/detail/a_id/165
Not sure if you have to log in to see above page so I'm quoting the page here for convenience:
You can avoid duplicate transactions by passing an invoice number to
the PayPal system. This feature is available for Website Payments
Standard, and Website Payments Pro (SOAP and NVP). The PayPal system
will check to make sure the invoice number you pass has not already
been paid in your account, as long as you have configured your profile
to block duplicate invoice numbers.
Example: Invoice 001 has been paid, therefore if 001 is passed to the
PayPal account a second time, it will be denied.
To block this in your profile:
Block accidental payments: You may prevent accidental payments by
blocking duplicate invoice IDs
Login at https://www.paypal.com
Click the 'Profile' subtab
Under 'Selling Preferences' click 'Payment Receiving Preferences'
Choose 'Yes, block multiple payments per invoice ID' if you wish to utilize this feature while passing the "invoice" variable
Scroll to the bottom and click the 'Save' button
To pass the invoice number for Website Payments Standard, you will
need to add a line of code to your existing button code. You cannot
add this code to a button originally created as encrypted. Example
below:
For Website Payments Pro, the parameter you pass depends on the type
of API calls you are making.
For SOAP: InvoiceID
For NVP: INVNUM
When using Pro, if a duplicate invoice number is detected the error
10412 will be returned. For a complete list of the API error codes,
and details regarding the 10412 error Click Here

Related

Weird return values to IPN since about a week ago

We use fields called "item_name" and "item_number" in integration with PayPal to convey the details of the ordered product.
Recently I've been seeing PayPal transactions return "Shopping cart" in item_name, rather than the string that was posted to PayPal in that field.
This behavior is inconsistent, I have logs that show 5 transactions with 1, 4 and 5 having the missing item_name, and 2 and 3 having the old item_name without any issues whatsoever.
I've tried to find out whether item_name was deprecated but it appears to be still active, as per https://developer.paypal.com/docs/classic/ipn/integration-guide/IPNandPDTVariables/
We are not using shopping cart, we're using PayPal Payments Standard. Our PayPal send code is:
<form action="https://www.paypal.com/cgi-bin/webscr" method="post" name="PayPal">
<input type="hidden" name="item_name" value="<?=$item_name; ?>">
<input type="hidden" name="item_number" value="<?=$item_number; ?>">
The item_name and item_number can be seen at the top of the PayPal pages the user sees next.
Could someone from PayPal please explain why is there this inconsistency in the behavior, and whether it's a problem with PayPal or a forerunner of change I wasn't aware of?
Thank you in advance for your help!
Maciek
We also starting experiencing this problem on 8/19/2017. Item_name = "Shopping Cart" Here are others reporting this problem:
https://www.paypal-community.com/t5/About-Payments/item-name-changed-to-quot-Shopping-Cart-quot-in-IPN/td-p/1290682

How to use IPN/PDT to display receipt and digital and/or downloadable products after purchase and redirection with PayPal

I have a webshop: energyshop.se which I have successfully managed to setup a Sandbox account at PayPal and to create a Buyer and a Seller account, created a button which I implemented to my site (from the Seller account) and I manage to make a payment through my Buyer account and got redirection to work too, to energyshop.se/tack.
So far so good, now I wonder how do I reach the "product ID" that IPN/PDT sends when the user is redirected? How do I use that holder to display files for download or just for play/listening? And what are the holders/variable that holds the receipt information? I would like to say for example when returned to /tack to display the receipt and then the downloadable item.
Any help is very welcome I have worked n this site for ages now and just want it done, it is for a customer too.
I tried to do something like this (i use wordpress at my thankyoupage):
<div id="receiptform">
<form method=post action="https://www.paypal.com/cgi-bin/webscr">
<input type="hidden" name="cmd" value="_notify-synch">
<input type="hidden" name="tx" value="TransactionID">
<input type="hidden" name="at" value="P0d7_HmQSAuXh9r-7hG1Rzf_npI2LaFgYHQJyWUsjQHg7WhZARqs3sq6IW4">
<input type="submit" value="PDT">
</form>
</div>
But that just displays a button PDT that when clicked displyas FAIL ERROR: 4002
How do I edit this to just display the content nicely in tx?
Also, I can tell that "its" working because in the address field, when redirected to thank-you-page this reads: http://energyshop.se/tack/?tx=9LJ24270G46097059&st=Completed&amt=10.00&cc=USD&cm=&item_number=1 which leads me to think its A) completed and B) got the info I need. Now is the question how i present this data? What am I supposed to do? A php-script that I...? I cant seem to find any examples on it, just the defnition of the variables for IPN/PDT but that doesnt help me if I dont know where to put or do with it...
You would want to use PDT as you are. When you receive the tx variable and etc back, you have to do a post back to PayPal to verify all of the inforamtion. Then once you have varified the post, PayPal will then send all of the variables back to your script. You can find a bit more on how PDT works at https://www.x.com/developers/paypal/documentation-tools/ipn/integration-guide/IPNPDTAnAlternativetoIPN. There are also some sample scripts on that site as well at https://www.x.com/developers/PayPal/documentation-tools/code-sample/216627 and https://paypaltech.com/PDTGen/

PayPal PDT is not Returning a tx value in the Query String

I've gone through the (not so helpful) PayPal docs and can't find an easy answer to this problem. When the user returns from PayPal, the URL does not contain a query string and thus I do not receive the 'tx' value (or any other value for that matter).
This is an example of what I'm sending to PayPal:
<form accept-charset="utf-8" action="https://www.sandbox.paypal.com/au/cgi-bin/webscr" id="paypal-form" method="post">
<input type="hidden" name="business" value="dallas_bus#dallasjclark.com">
<input type="hidden" name="cancel_return" value="http://localhost/checkout">
<input type="hidden" name="cmd" value="_xclick">
<input type="hidden" name="charset" value="utf-8">
<input type="hidden" name="currency_code" value="AUD">
<input type="hidden" name="custom" value="155">
<input type="hidden" name="lc" value="AU">
<input type="hidden" name="notify_url" value="http://localhost/paypal-ipn">
<input type="hidden" name="return" value="http://localhost/checkout">
<input type="hidden" name="item_name" value="ABC Company - Order #155">
<input type="hidden" name="item_number" value="155">
<input type="hidden" name="amount" value="8.95">
<input type="hidden" name="discount_amount" value="0.00">
<input type="hidden" name="shipping" value="25.00">
<input type="image" src="https://www.paypal.com/en_AU/i/btn/btn_buynowCC_LG.gif" name="submit" alt="Buy Now">
</form>
Thanks in advance !
You should check the settings at https://www.sandbox.paypal.com/us/cgi-bin/webscr?cmd=_profile-website-payments and make sure
Auto Return is set to ON
You have specified a Return URL
Payment Data Transfer is set to ON
There's another much less obvious thing I had to learn through experimentation: your form must not contain a "return" value, otherwise that will override the Return URL in your settings and prevent the Auto Return from working and you'll wind up without the necessary tx parameter. This is a relatively recent development (bug?) at Paypal, because it used to work.
I've just been struggling with this for some time, and another thing that seemingly causes no tx value to be returned is if you have a free trial.
So, if the cost of your service is free for the first 20 days then 4.99 thereafter you won't get a tx value back for the first free payment. If you charge one penny (or whatever your relevant currency is) for the initial 'free' period then you will get a tx value returned.
We actually logged a ticket with PayPal Merchant Technical Services to get to the bottom of this.
We found that over time, some paypal merchant accounts would appear to forget their AutoReturn/PDT settings.
Even though you could go into the Website Preferences and AutoReturn and PDT were both enabled; the account would behave as if they were not enabled.
Follow this procedure to reset the settings ....
Click on Profile.
Click on "My Selling Preferences">
Click on "Website Preferences"
(*) Direct link to this section, in case you can't found it -> https://www.paypal.com/cgi-bin/customerprofileweb?cmd=_profile-website-payments
Disable both Auto Return and Payment Data Transfer.
Save your changes.
Access to Website Preferences again.
Enable Auto Return and Payment Data Transfer again.
Save your changes.
I've got the same problem with sandbox during testing. To fix it I had to verify test accounts in sandbox environment. To verify them use the build-in testing e-mail service. After verifying, paypal sandbox started to sent TX parameter.
A few other reasons why you might not get a tx parameter:
For PDT to work, you must confirm the email address used as the value of business in your button code. If this email address is not confirmed, PDT will not work. If your email address is not confirmed, you will not see the PDT query string appended to your return URL.
When you enable PDT, the URL you are using as the default Auto Return URL must be a valid hostname or IP address or the user will not be auto-returned back to that URL. Make sure you use a valid URL as the URL of where you want the user to go back to or you will not see the intended result.
From: https://ppmts.custhelp.com/app/answers/detail/a_id/469
i have found a method, that worked for me - try to insert this field into your generated form code:
<input type='hidden' name='rm' value='2'>
rm means return method;
2 means post with variables
Than after the user purchases and returns to your site url, then that url gets the POST parameters as well
p.s. if using php, try to insert var_dump($_POST); in your return url(script), then make a test purchase, and when you return back to your site you will see what variables are got on your url.
I had a similar problem - where working from a local server,
i used to get instead of the 'tx' variable, i got a 'auth' variable.
After playing around with it for a while, found that (for some wired reason) if i change my vitrual host and host file, to the real domain, i get the 'tx' variable, where as in my local environment domain i get the 'auth' variable.
That fixed it for me.
Hope this helps anyone.
I also opened a PayPal Merchant Technical Services ticket for this.
For transactions initiated by a PayPal Button. The PayPal back end sometimes loses the monetary values of the pricing structure (even though it shows you, and you can edit the pricing, the back-backend will lose the values and not accept updates).
Symptoms: In Sandbox, the PayPal process will fail after login but before it can show you the screen for choosing the funding source (i.e. which back account or credit card to use). You get the "We're sorry; Things are not working" message.
Create the Button anew and hopefully the pricing is saved this time.

How do I pass session variables to paypal with buy now button

When my users are logged in with their username and userid saved in the session variable they can donate using paypal. With the simple buy now button that you can simply generate at paypal.
<form action="https://www.paypal.com/cgi-bin/webscr" method="post">
<input type="hidden" name="cmd" value="_s-xclick">
<input type="hidden" name="hosted_button_id" value="XXX">
<input type="image" src="https://www.paypal.com/en_US/i/btn/btn_buynowCC_LG.gif" border="0" name="submit" alt="PayPal - The safer, easier way to pay online!">
<img alt="" border="0" src="https://www.paypal.com/en_US/i/scr/pixel.gif" width="1" height="1">
</form>
When they payment is successful they are sent to my confirm_payment.php with all the _POST data. I can use the mail they paid with and compare this with my user database to find the correct user, but I can't be sure that they use the same email for paypal and my site.
I need to pass the $_SESSION['username'] to paypal so I can use this information to give my users donator status automatically. Can I add something like:
<input type="hidden" name="custom" value="custom variable">
to my button code? Here is more info on the variables avaliable paypal info
I found the documentation confusing but after a lot of web browsing I discovered that the custom variables do not allow you to create your own hidden fields but there are 3 variables that may be useful:
"custom" Optional Pass-through variable for your own tracking purposes, which buyers do not see.
Default – No variable is passed back to you. 256 characters
"item_number" See description. Pass-through variable for you to track product or service purchased or the contribution made. The value you specify is passed back to you upon payment completion. This variable is required if you want PayPal to track inventory or track profit and loss for the item the button sells.
"invoice" Optional Pass-through variable you can use to identify your invoice number for this purchase.
Default – No variable is passed back to you. 127characters.
So if you save your data prior to allowing the buy now button to fire (I do this by having a summary screen which shows the choices made and saves them to a database) you can then put a value (e.g. primary key of the saved data) as the custom value.
Note that the data will be posted to the instant payment notification page that you designate.
From
https://www.x.com/developers/paypal/documentation-tools/paypal-payments-standard/integration-guide/Appx_websitestandard_htmlvariables#id08A6HF00TZS
yes you can add like this, this is the correct way, and when paypal pings you back on IPNHandler then you'll get the value of this custom hidden field in querystring with the same name.

Can I send a variable to paypal, and have it post it back to me when payment completes?

Ive been using express checkout API to convert people's accounts on my site to premium accounts after paying. The only problem with it is that it doesn't send the user back to the site until they click the button to return, and it updates their permission when that happens. About 40% of the users don't seem to do that.... so their accounts never get credited after payment.
Although paypal does an instant post-back upon the successful payment, I was never able to make it actually update the user's account right away, since I cant get it to send back some sort of informational that would identify the user that just completed the payment. I could only do that when you are sent back to the site, which sends the transaction ID, that I logged with a post-back. It searches for it, and grants permission if it was found int he DB.
Is there a way to submit some sort of a variable to paypal, that it will then post back to me? Something like &user_id=123, which would make it very handly to update the user's permission.
Iten_number hidden variable don't work in my application. But i found that custom hidden field works fine. Just add this field to the form, generated by paypal: <input type="hidden" name="custom" value="YOUR VALUE FROM DB"/>. After, you can read this value to identify, for example, what product have been purchased. (Java code): String custom = request.getParameter("custom");
Yes, if you send item_number, the IPN notification will include that when it posts back to you. I record a unique ID in the database when the user starts the payment process, and include that when sending them to PayPal. When the IPN comes in, that unique ID matches up with the record in the database, giving me all the info I need.
Edit Re your comment:
I expect there's a code example somewhere on the site linked above, but basically in my case I'm using a form that I POST to https://www.paypal.com/cgi-bin/webscr. Within that form are various hidden fields documented in the IPN stuff (cmd for what command to perform, business to specify your business ID, item_name for a nice description in the PayPal UI, item_number for the item number I mentioned above, etc., etc.). When IPN posts back to your IPN address, it includes various fields (such as payment_status — kind of important! &mdash and the item_number you fed in when posting to them).
Just to add to this old question...
There are option parameters that are commonly used for custom data sending through paypal.
These option tags are on0, on1, or on2 for the custom field names and os0, os1, and os2 for the custom field values.
I would send on0 with a value of "UserID" and os0 the actual ID.
These values will be represented in the IPN as follows:
os0 is represented as option_selection1
os1 is represented as option_selection2
os2 is represented as option_selection3
on0 is represented as option_name1
on1 is represented as option_name2
on2 is represented as option_name3
Here's the info on PayPal's HTML parameters
According to HTML Variables for PayPal Payments Standard you can send all the "Pass-through" variables:
item_number Pass-through variable for you to track product or service
purchased or the contribution made. The value you specify is passed
back to you upon payment completion. This variable is required if you
want PayPal to track inventory or track profit and loss for the item
the button sells.
custom Pass-through variable for your own tracking purposes, which buyers do not see. Default – No variable is passed back to you.
and
invoice Pass-through variable you can use to identify your invoice number for this purchase. Default – No variable is passed back to
you.
All these pass-through variables are sent back by the IPN in the payment response info.
You just have to render your HTML template server-side and write the fields back in the HTML code like
<input type="hidden" name="item_number" value="{{ productID }}">
<input type="hidden" name="invoice_id" value="{{ invoiceID }}">
<input type="hidden" name="custom" value="{{ jsonInfo }}">
Technically the field "custom" can be a JSON encoded string if you want to handle more data like
myItemObject = {
"customerEmail" : "john#doe.com
"customerID: "AAFF324"
}
jsonInfo = json.dumps( myItemObject )
return render_template(tmpl_name, jsonInfo=jsonInfo, productID=productID, invoiceID=invoiceID)
I finally get this answer, I want to share with all of you look:
on your HTML form put this code (this is Paypal sandbox):
form action="https://www.sandbox.paypal.com/cgi-bin/webscr?custom=YOUR_VAR" method="post"
On your PHP after the Paypal redirect to your page success: use the cm GET variable:
$example = $_GET["cm"];
I hope this URL solves your issue. As it solved mine as well. Add a custom variable to your form and then retrieve it on your success payment page.
Example :
<input type='hidden' name='custom' value='<?php echo $email; ?>'/>
and then retrieve it as :
$_POST['custom']
<input type="hidden" name="on0" value="Ajay Gadhavana">
<input type="hidden" name="on1" value="my_phone_number">
<input type="hidden" name="on2" value="my_third_extra_field">
Response from paypal would be
[option_name1] => Ajay Gadhavana
[option_name1] => my_phone_number
[option_name1] => my_third_extra_field
What worked for me in 2021 is passing "custom_id" (inside the "purchase_units" array) to PayPal in my client app and checking "custom" on my backend.
Yes, it looks like PayPal renames the parameter for some reason.