Sending transaction-specific emails with PayPal IPN - paypal

I am running an audio processing service in which users upload their raw audio tracks and then purchase them after completion. After purchase, I would like an email to be sent to them a unique Dropbox link to download the respective files.
Given that each transaction on my website will contain different pricing information and will require a unique link, I do not know what to do.
Currently, I allow the users to select (via checkboxes) the files they would like to purchase. I then use some server-side logic to calculate the appropriate price, and then run it through a PayPal Express Checkout button.
payment: function(data, actions) {
return actions.payment.create({
payment: {
transactions: [{
amount: { total: "<?php echo $totalPrice ?>", currency: 'USD' }
}]
}
});
},
The problem is that I have no way to manually send them their unique download links after purchase. Is this possible with PayPal IPN? Thank you

You should create a local order record in your database that contains the details about what they bought and any unique data for that order. Then you can pass that order ID in your payment request to PayPal, and it would come back in the IPN data. You could pull your unique data back out of your system using the order ID so that you can then include it in your custom emails.

Related

Retrieve paypal subscription data after approval

Afternoon
I am a bit of a PayPal integration newbie and having been working on a project where customers use a subscription button to purchase goods. Everything works well however I need to retrieve subscription data after approval for further use. Initially I need the email address so we can send a customised automated email thanking the customer for their purchase but going forward would like the majority of the data so it can be placed in an SQL database.
The onApprove: function(data, actions) seems to be the place to enter code but not overly sure where to start. The subscriptionID seems to be pulled and used within the default code, but when I try and pull another piece of data nothing happens.
onApprove: function(data, actions) { //alert('You have successfully created subscription ' + data.subscriptionID); alert('Here is the email address ' + data.subscriber.email_address); }
Is my reference to the email address wrong or does paypal only give you access to the subscriptionID which can then be passed to another PHP page and I can use do a REST API request for the subscription data??
Many thanks chris
console.log(data) in the onApprove will show you the data that is available on the client side.
To log information to a server, you should not depend on approval notifications from the client, since they may fail for any number of reasons. Instead, (using the correct clientid) subscribe to webhooks related to subscriptions, particularly the PAYMENT.SALE.COMPLETED event so you receive an update every time a subscription is successfully renewed.
For reconciliation (so you know what payment is for what), you can pass your own arbitrary custom_id when the subscription is first created. This will be returned in the webhook.

PayPal Subscriptions and Smart Payment Buttons -- adding a description/metadata

createSubscription: function(data, actions) {
console.log($('#donation-details').val());
return actions.subscription.create({
'plan_id': window.VUE_DONATION_MODULE.getPlanId(),
// I want to add meta data about the subscription
'description': $('#donation-details').val(),
'application_context':{brand_name:$('#donation-details').val()}
});
},
onApprove: function(data, actions) {
$('#step-7').removeClass('active').fadeOut();
$('#step-9').addClass('active').fadeIn();
}
I am using PayPal Smart Buttons to make a subscription, and want to add metadata. For a one-time payments I used the 'description' field to enter this metadata. Please help me find a way to record metadata for subscriptions; I want it to display it under transaction details after loging into PayPal, in both merchant account and customer account.
Plans have a description field you can use at original plan creation time: https://developer.paypal.com/docs/api/subscriptions/v1/#plans-create-request-body
If you need per-user metadata to be part of the plan description, you must create a new plan per user.
If you just need to associate additional metadata with a user's subscription, you must do this in your own database. Associate the subscription ID object with the user the moment it is created by your site/application, and so all additional metadata can be stored by your site/application, and be looked up by either the user or the subscription ID.

How to set up custom PayPal payments on a web application

I am currently working on a project that needs to include some functionality to allow me to set an amount and a recipient for a PayPal payment, and then display a button to a user who can then complete the payment. I will also need to confirm that the payment was successful.
I am building it as an MVC application using the ASP.net framework.
Since you want to be able to confirm the payment is successful, you need a server-side integration. Here is a demo pattern of the UI: https://developer.paypal.com/demo/checkout/#/pattern/server
Note that it does fetch() XHR calls to two server endpoint of yours, which will need to implement v2/orders API calls to initially set up the payment, and then later capture it --- which provides confirmation of success/failure. More information on the server-side portion can be found here: https://developer.paypal.com/docs/checkout/reference/server-integration/ ; there is a .NET v2 Checkout SDK available.
Normally you need the ClientID and Secret of each receiver's REST APP (this is preferred, since PayPal account emails can change) -- but alternatively, you can use your own REST APP and specify the receiver's PayPal email address in the payee field:
purchase_units: [{
payee: {
email_address: 'replacewithrealemail#somewhere.com'
},
amount: {
value: '1.00'
}
}]

How to add custom user id in subscriptions paypal api

I need integrate paypal subscriptions to my project.
I use new paypal subscriptions api https://developer.paypal.com/docs/api/subscriptions/v1/#subscriptions and need to know how i can identify payer and my own db user.
Here is scenario in my mind:
I create my own db user with signup form.
I set my own user id to paypal api call
After user confirm subscription paypal return me subscriptions id, then i call paypal api to get details of returned subscription and see my own db user id
But looks like paypal cant provide it.
here is my smart checkout button code
paypal.Buttons({
style: {
layout: 'horizontal',
size: 'small',
color: 'blue',
label: 'pay',
height: 55,
tagline: 'false'
},
createSubscription: function(data, actions) {
return actions.subscription.create({
'plan_id': 'P-5GS67390M7258253CLUHXAHQ',
'metadata' : {
'user_id' : 'myuserid'
}
});
},
onApprove: function(data, actions) {
console.log(data);
alert('You have successfully created subscription ' + data.subscriptionID);
}
}).render('#paypal-button-container');
</script>
I found only one way how i can do it
User insert all data to signup form and then click on paypal button
After success paypal payment on
onApprove: function(data, actions) {
$('#myform').append('<input name="subscriptions_id" value="data.subscriptionID"')
$('#myform').submit()
alert('You have successfully created subscription ' + data.subscriptionID);
}
What is the best way to add subscriptions id for mysql db user?
The solution in the question is one possible way. The problem with it is that if the client goes down before sending the data to the server, the association between user_id and subscription_id is lost.
The way around it is to send the user_id to paypal as custom_id. That custom_id is then a part of the subscription data, retained on the payapl server, shown in the paypal billing UI for the subscriptiion details. I do not yet know it for sure, but strongly suspect it is also sent to the webhook.
see PayPal API documentation for creating a subscription
So ideally combine both. Have a webhook to associate the custom_id (your user_id) with the subscription. Have the API call (form post) like you do. If either way fails, you have the fallback.
UPDATE 2021-09-02: I myself use that approach in our web billing solution. One thing I noticed, statistically, it is a very rare event that the web client goes down before getting a response back. I know it because webhook calls come from hours to days after the event. After several hundreds of subscriptions that I analyzed, I have seen not a single case where the webhook came to patch up a missing transaction.
I do not know why it is so. It certainly exceeded my expectations.
My guesses are 1. PayPal server replies fast 2. my PWA is written well enough to warn user to wait a bit not close the browser window until the confirmation screen.
Still I recommend to implement webhook. It would be needed for all the other cases where user cancels subscription directly on the paypal, or such other events.
The solution in the question is correct, the subscription-id should be stored and associated with the internal user-id at creation time, which for subscriptions occurs right after approval (in the onApprove function)
The fetch API can be used instead of a form post to communicate this subscription-id to the server, along with the user-id to associate it with -- similar to the examples in https://developer.paypal.com/demo/checkout/#/pattern/server

How can a server know a payment was truly made via PayPal client side REST API?

I was looking the PayPal interactive integration demo link.
At some point after the user complete the payment flow, the client reach the code:
// onAuthorize() is called when the buyer approves the payment
onAuthorize: function(data, actions) {
// Make a call to the REST api to execute the payment
return actions.payment.execute().then(function() {
window.alert('Payment Complete!');
});
}
In a real scenario, instead of an alert, I would probably like to send the server a instruction to ship a product or update the user plan. And it would probably be done via an HTTP POST request.
How can the server know that indeed a payment was made and it was not a result of an hacker sending an http post request manually?
After actions.payment.execute() you can call your server and have it make a GET call to verify the payment has been completed: https://developer.paypal.com/docs/integration/direct/express-checkout/integration-jsv4/advanced-payments-api/show-payment-details/
Your idea is correct, the server cannot know if the payment was really made. This client API is intended for things like donations, where no request to any servers is necessary. The client callback can then be used to display a "thank you" note or similar to the user.
For most cases (like online shops etc.) you will want to use the server API. That way, the PayPal server will send a request to your server, so you can validate that it really is a genuine payment confirmation.
1) generate a unique reference server side in your database that includes the payment details. For example:
My paypal references table
| Amount: $1.00 | Reference: ECHI5786786 |
2) Pass the payment reference in your transaction object before excuting the payment.
"transactions": [
{
"amount": {
"total": "1.99",
"currency": "USD"
},
"soft_descriptor": "ECHI5786786" //this is your unique reference
]
3) In your PayPal app configuration, on the developers site, set a webhook to your server for "payment sale completed". PayPal will call your url with the transaction details including the unique reference. Record the details in your database. For example
My paypal confirmed completed payments table
| Amount paid: $1.00 | Reference: ECHI5786786 |
4) When PayPal confirms the payment is complete client side, send a request to your server to confirm payment details
// Make a call to the REST api to execute the payment
return actions.payment.execute().then(function() {
//ajax to your server here with "soft_descriptor"
//if ajax success, then all good
});
Serverside confirmation
Confirm that the reference is in both tables and that the amount matches