I'm developing a site for a client, and he wants people to be able to buy licenses/support contracts via PayPal. What I'm stumped on is how I can make the payments secure. My current idea is to generate a random string using MD5 or whatever, plug this into a database, and send it along with the rest of the PayPal button code. When the payment is completed, the user is redirected to a PHP page where there is code to update their information in the database. The only thing stopping a hacker giving themselves a license/whatever without paying is the random hash, which can be found out using a sniffer of some sort, and plugged into the POST data returned by the PayPal code.
So. My question is this: How do I execute custom PHP code only on a successful PayPal payment, without leaving any loopholes open for the more evil users of the interwebs?
I think you should use a Payment Gateway such as PayFlow
if you're on the website ready to pay, there maybe a session already with your user logged in?
in this scenario, when the user returns back to the website, you can check you have a particular session variable and if it exists, you do the following
1) check your session, do you have a user logged in? should still be logged in if you just visited paypal a few minutes ago.
2) does the session contain your sale_id?
3) if no, dump the user on the home page, remember to header("Location..."); die("DEAD"). the die() part is important
4) if yes, check the sale_id was paid, the notify url should have caught the POSTED payment data, if valid, allow them to update the data
5) if yes, but not valid, allow them to repay using another method, this means to redirect them to another page to attempt to pay again, but don't let them access the "change details" page, the only way you get there, is by strictly validating the payment was successful.
how does that work for you ?
Related
I've never used PayPal before, it's not really popular here, and I'm confused by how the order and payment works. Can anyone explain it to me? I've read the documentation and I'm still confused.
To complete payer approval, use the approve link to redirect the
payer. The API caller has 3 hours (default setting, this which can be
changed by your account manager to 24/48/72 hours to accommodate your
use case) from the time the order is created, to redirect your payer.
Once redirected, the API caller has 3 hours for the payer to approve
the order and either authorize or capture the order.
I have created a working PHP curl call for this API in sandbox env according to the sample
https://developer.paypal.com/docs/api/orders/v2/#orders_create
The APIs I created before work like this:
Send a request to 3rd party payment
Get a response containing a checkout link
Redirect customer to link
Customer complete payment
3rd party send a request containing order and payment detail to a file/path on my server
My server receives the request and updates the order status/payment in my database
3rd party redirect the customer to my webpage
With PayPal, what I got so far is:
Send request containing order detail to /v2/checkout/orders
Get a response containing various links
Redirect my customer to the rel:approve checkout link
Log in to my sandbox customer account and pay using PayPal balance, click Continue
A popup message is shown: We're sending you back to xxx's Test Store to complete this purchase
The popup message is closed and I'm still at the same payment page with the Continue button as seen in the image
Send request containing order detail to /v2/checkout/orders
Get a response containing links
Redirect my customer to approve link
Step (3) is an old integration method, for websites using an old redirect-based flow. The preferred way to integrate PayPal uses no redirects. At all. Your website remains loaded in the background. Do the following:
Follow the Set up standard payments guide and make 2 routes on your server, one for 'Create Order' and one for 'Capture Order', documented here. Both routes should return only JSON data (no HTML or text). Inside the 2nd route, when the capture API is successful you should store its resulting payment details in your database (particularly purchase_units[0].payments.captures[0].id, which is the PayPal transaction ID) and perform any necessary business logic (such as sending confirmation emails or reserving product) immediately before forwarding your return JSON to the frontend caller.
Pair those 2 routes with the frontend approval flow: https://developer.paypal.com/demo/checkout/#/pattern/server
If, for some odd and inexplicable reason, you insist on using the legacy flow with a full page redirect instead of what I just described above, you must include a redirect_url in your orders creation request, so that PayPal has somewhere to return to after the order is approved. Immediately when the return happens, capture the order with an API call and show the success/failure result to the customer. If you want an intervening order review step before capture, you can do this, but you must also edit your initial order creation request to change the verbiage of the last button at PayPal from "Pay Now" to "Continue" so that the user is clicking on something that corresponds to what the next step will be. application_context.user_action needs to be continue for this change.
Capturing an order will return a v2/payments object which is the completed transaction with its own ID for accounting and refund purposes. (The order ID is only used during payer approval, and unimportant otherwise)
I had this issue too, and I eventually got a solution from the documentation.
You have to add application_context.return_url to your request.
Attached is an example in PHP:
$postData = [
"intent" => "CAPTURE",
"purchase_units" => $purchase_units,
"application_context" => [
"return_url" => "",
"cancel_url" => "",
],
];
You can make a whole lot of customisations to the PayPal Payment page by adding the Application Context option, For a full list of the possible customisations, you can check up the official documentation Application Context Documentation
I apologize in advance for this question, as its probably rather silly, but I really can not find any answers elsewhere.
My current goal is to integrate a subscription to my website, that allows for a user to have access to certain parts of the site.
I've watched a few videos on it, but it leaves me open ended with some questions.
PayPal allows you to manually create a subscription plan at https://www.paypal.com/billing/plans. When you create a plan here, it gives you the code you need to get the pay pal sub buttons to display on the page. Users can then use them to create the subscription. This is great. However, I have found now way to validate the results of the transaction. My goal would be that if the user was successful, I would be able to retrieve data via the API, that says it was successful, and I could then store than information in my database, and grant them access. Does anyone know how to get the data from the manually created facebook plans?
I did watch a video that had you do everything from your website (you create it all within your own code), the end result however sent everything through $_GET variables in the url. I feel like having this data exposed could result in the manipulation of the subscription, and grant it to users who were unsuccessful in creating a subscription.
I have no problem doing all of the coding to make this work, but I really want to make sure I do it the best possible way.
There is a few way to do it. By setting up a webhook and listen to paypal success notification and react to it. By using the Paypal Subscription API. Or a combination of both.
As you are using the paypal button you will have the onApprove function which will trigger upon user confirming the subscription. You can query the subscription data with:
onApprove={async (data: any, actions: any) => {
const detailedSubscriptionData = await actions.subscription.get()
// activate subscription on your side by sending it to your backend
...
// etc.
}}
Inside the data you have queried above, there will be a paypal transaction id (I-....) that is unique for each transaction, as well as your product id (plan_id). You can now do the following for verification on your backend:
Check if there is already a subscription (from another customer) on your side with that paypal transaction id
Check for the plan_id
Queried the API Subscription Details with the paypal transaction id and check for status, etc. as well as matching of plan_id
Keep in mind that for using the API you will have to queried for an access-token which in turn required you to have Developer App Setup following these steps.
I have a digital download page. The page is loaded on successful PayPal payment. Can I prevent direct user access to the download page if the user simply types the URL in their browser address bar?
This scenario is similar to showing pages to a user if he is authenticated. The implementation details will depend on the tech that you are using. For something like showing download page for successful payment, let's assume that you have an order and assume it tracks whether payment was successful (maybe as a boolean) .e.g. id: 1234, paymentSuccessful: false. What you can do, at the router, when a request to view order/1234/download is done, check if the paymentSuccessful is true. I hope this gives you an idea of how to go about it.
I have just created my first PayPal button and it is working correctly within sand box. I would like to know the best way (if possible) to issue a unique activation code on my return url ensuring that the user has definitely paid before they receive the code. I could manually email the code but wondered if the was any way of automating this using some sort of return value? Possibly returning to an aspx page which then reads from my database to get the next activation key and displays it?
Thanks
Garry
As you already know that PayPal doesn't provide such facility for delivering activation instantly but it does offer the Instant Payment Notification API (PayPal IPN) which can be used to build such a platform.
Here is a great article for that purpose only. https://www.codeproject.com/Articles/383207/Selling-software-using-PayPal-IPN-as-an-eCommerceenter link description here
The best way to handle that would be to use Instant Payment Notification (IPN).
Any time a transaction happens on your site (whether it's a payment, refund, cleared pending payment, dispute, etc.) the PayPal server will POST details about that transaction to a script you have sitting on your server.
This script can receive the data and process it accordingly allowing you to automate things like updating a database, generating email notifications, hitting 3rd party web services, delivering e-goods, etc.
If you want the activation code to be visible on the return URL you can look at Payment Data Transfer (PDT), which is just like IPN except that it's made for use with the return URL. It is not recommended to use this, though, for post-transaction processing because there is no guarantee the user will make it back to the return URL, for one, and also it wouldn't handle things like e-checks correctly.
I have confusion, that I have integrated recurring payment system.
It was working well before, 3 days.
Form 2 days I am getting error
Sorry — your last action could not be completed
When I am trying to login.
It login successfully but now shows the payment confirmation page.
What should be the issue?
I am using sandbox for now.
Let me know if you want more details.
please check or do the following
Use a separate browser page for logging into sandbox.paypal.com as you stated you are trying to 'login'
I have noticed periodically that sandbox.paypal.com loads my live credentials when a previous paypal.com session was activated; an apparent cookie issue
If you have a password / user id client like fast pass, etc; make sure to verify the password that's injected into the fields in your options of the pw/user ID client
Please take note as I am replying to:
Sorry — your last action could not be completed When I am trying to login <-- Not to recurring payments system not working as it appears that these are 2 different issues. If not, please clarify for me