I found a library that paypal themselves have written for node, they wrote a great library on how to pay. Im still in the confused state on how to receive payment and Im running out of time right now.
The use case is very simple, User A click add an item to his cart , then he has a choice, its either to pay using Credit/debit card or paypal(express checkout)
My goal still at the credit/debit card, where user decided to use credit/debit card to receive payments, and im using paypal-rest-api sdk to do this. But looking at the code samples Im super confused on which sample to choose, from
https://github.com/paypal/PayPal-node-SDK/tree/master/samples
var card_data = {
"type": "visa",
"number": "4417119669820331",
"expire_month": "11",
"expire_year": "2018",
"cvv2": "123",
"first_name": "Joe",
"last_name": "Shopper"
};
paypal.creditCard.create(card_data, function(error, credit_card){
if (error) {
console.log(error);
throw error;
} else {
console.log("Create Credit-Card Response");
console.log(credit_card);
}
})
In the card_data, there is no amount, and im really confused.
Again the use case
User could buy the item on website, and he pays using credit/debit card and it will automatically send the money from his bank account to my paypal business account.
You're looking at not the right method. You need payment.create
Here's the code snippet from payment documentation
var create_payment_json = {
"intent": "sale",
"payer": {
"payment_method": "credit_card",
"funding_instruments": [{
"credit_card": {
"type": "visa",
"number": "4417119669820331",
"expire_month": "11",
"expire_year": "2018",
"cvv2": "874",
"first_name": "Joe",
"last_name": "Shopper",
"billing_address": {
"line1": "52 N Main ST",
"city": "Johnstown",
"state": "OH",
"postal_code": "43210",
"country_code": "US"
}
}
}]
},
"transactions": [{
"amount": {
"total": "7",
"currency": "USD",
"details": {
"subtotal": "5",
"tax": "1",
"shipping": "1"
}
},
"description": "This is the payment transaction description."
}]
};
paypal.payment.create(create_payment_json, function (error, payment) {
if (error) {
throw error;
} else {
console.log("Create Payment Response");
console.log(payment);
}
});
Related
I was wondering how do I send shipment info to Paypal so that when the user gets redirected to Paypal for payment, the user doesn't have to fill out Shipping information again. The user already filled out shipping information and the data is stored in my database. The issue is that the shipping info stored in the database will more than likely not be the same address as the person making the order. The user will more than likely be using another shipping address, not their own. Now I can operate just fine this way but I was thinking: If I dont have the correct shipping address stored on Paypal's records, the customer could easily say I never shipped their product and demand a refund. At this point, I would only have the tracking # to the address stored on my database, not on Paypal's records, thus making me vulnerable to these kind of paypal scams. Correct me if Im wrong anybody.
Below is Paypals example on what data is sent to them during ordering process:
https://github.com/paypal/PayPal-node-SDK/blob/master/samples/order/create.js
var create_payment_json = {
"intent": "order",
"payer": {
"payment_method": "paypal"
},
"redirect_urls": {
"return_url": "http://return.url",
"cancel_url": "http://cancel.url"
},
"transactions": [{
"item_list": {
"items": [{
"name": "item",
"sku": "item",
"price": "1.00",
"currency": "USD",
"quantity": 1
}]
},
"amount": {
"currency": "USD",
"total": "1.00"
},
"description": "This is the payment description."
}]
};
I added a shipping object, see the sample below.
var create_payment_json = {
"intent": "sale",
"payer": {
"payment_method": "paypal"
},
"redirect_urls": {
"return_url": "https://website.com/thankyou",
"cancel_url": "https://website.com"
},
"transactions": [{
"item_list": {
"items": [{
"name": name,
"sku": "item",
"price": total_price,
"currency": "USD",
"quantity": 1
}]
},
"shipping_address": {
"recipient_name":recipient_name,
"line1":line_1,
"city": city,
"state":state,
"postal_code":zipcode,
"country_code":"US"
},
"amount": {
"currency": "USD",
"total": total_price
},
"description": description
}]
};
But I get this error:
"response": {
"name":"MALFORMED REQUEST",
"message":"Incoming JSON request",
"information_link":"https://developer.paypal.com/webapps/developer/docs/api/#MALFORMED_REQUEST",
"debug_id":"cb2ecc213218b",
"httpStatusCode":400
},
"httpStatusCode":400
}
I didn't just make this up the shipping object. On a successful Paypal payment, PayPal returns a transaction object that includes the shipping address object. I copied exactly the way I saw it, assuming I could send the shipping info to Paypal.
How can I send shipping info to Paypal via REST API / node.js when creating a Paypal order. Remember, when you checkout at any store and login to Paypal, the shipping address is automatically your shipping address that you set with Paypal. How do I change it via API? If you cant, how do stores typically handle these kinds of situations? For example, buy a gift for a friend. Thanks for your time, your help is much appreciated.
You have the right approach. The shipping_address object belongs inside the item_list next to the items array.
An example here:
var create_payment_json = {
"intent": "sale",
"payer": {
"payment_method": "paypal"
},
"redirect_urls": {
"return_url": "https://website.com/thankyou",
"cancel_url": "https://website.com"
},
"transactions": [{
"item_list": {
"shipping_address": {
"recipient_name":recipient_name,
"line1":line_1,
"city": city,
"state":state,
"postal_code":zipcode,
"country_code":"US"
},
"items": [{
"name": name,
"sku": "item",
"price": total_price,
"currency": "USD",
"quantity": 1
}]
},
"amount": {
"currency": "USD",
"total": total_price
},
"description": description
}]
};
I do not have a website and I would like to just send a link to the user and get the appropriate response whether they paid or not on the PayPal website and handle the rest.
Basically I dont want to redirect the user anywhere.
After configuring my PayPal credentials I have the following
var create_payment_json = {
"intent": "sale",
"payer": {
"payment_method": "paypal"
},
// I WANT TO REMOVE THAT BUT IF I DO I GET AN ERROR IN RESPONSE
"redirect_urls": {
"return_url": "http://return.url",
"cancel_url": "http://cancel.url"
},
"transactions": [{
"item_list": {
"items": [{
"name": "item",
"sku": "item",
"price": "1.00",
"currency": "USD",
"quantity": 1
}]
},
"amount": {
"currency": "USD",
"total": "1.00"
},
"description": "This is the payment description."
}]
};
paypal.payment.create(create_payment_json, function (error, payment) {
if (error) {
throw error;
} else {
console.log("Create Payment Response");
console.log(payment);
}
});
var paymentId = 'PAYMENT id created in previous step';
//check if user payed or not
paypal.payment.execute(paymentId, execute_payment_json, function (error, payment) {
if (error) {
console.log(error.response);
throw error;
} else {
console.log("Get Payment Response");
console.log(JSON.stringify(payment));
}
});
I was getting this error when building my little toy payment gateway form, but now I realized I can't even properly run the sample code after cloning the repository here.
I have entered my client ID and secret into configure.js. I'm in sandbox mode.
The file I'm running:
var create_payment_json = {
"intent": "sale",
"payer": {
"payment_method": "credit_card",
"funding_instruments": [{
"credit_card": {
"type": "visa",
"number": "4417119669820331",
"expire_month": "11",
"expire_year": "2018",
"cvv2": "874",
"first_name": "Joe",
"last_name": "Shopper",
"billing_address": {
"line1": "52 N Main ST",
"city": "Johnstown",
"state": "OH",
"postal_code": "43210",
"country_code": "US"
}
}
}]
},
"transactions": [{
"amount": {
"total": "7.00",
"currency": "USD",
"details": {
"subtotal": "5.00",
"tax": "1.00",
"shipping": "1.00"
}
},
"description": "This is the payment transaction description."
}]
};
paypal.payment.create(create_payment_json, function (error, payment) {
if (error) {
console.log(error);
throw error;
} else {
console.log("Create Payment Response");
console.log(payment);
}
});
When running, I get
> node create_with_credit_card.js
{ [Error: Response Status : 400]
response:
{ name: 'UNKNOWN_ERROR',
message: 'An unknown error has occurred',
information_link: 'https://developer.paypal.com/webapps/developer/docs/api/#UNKNOWN_ERROR',
debug_id: '599dd3222e6fb',
httpStatusCode: 400 },
httpStatusCode: 400 }
C:\cygwin64\home\Ryan\PayPal-node-SDK\samples\payment\create_with_credit_card.js:47
throw error;
^
Error: Response Status : 400
at IncomingMessage.<anonymous> (C:\cygwin64\home\Ryan\PayPal-node-SDK\lib\client.js:136:23)
at IncomingMessage.emit (events.js:117:20)
at _stream_readable.js:944:16
at process._tickCallback (node.js:442:13)
I'm desperate to find out where I am going wrong here.
The card you use (4417119669820331) is not unique. When testing a payment in REST API especially for Credit Card number, try not to use the default credit card number such 4417119669820331. Try with some other number like example 4532371704016199.
Alternatively, use this site (http://www.fakenamegenerator.com/) to generate the fake credit card for testing.
I am trying to create a batch payout with a test sandbox account.
The 'create payment' function is working absolutely fine with correct response:
var paypal_sdk = require('paypal-rest-sdk');
var config_opts = {
'host': host, //host defined
'port':'',
'mode':'sandbox',
'client_id': client_id, //clientID defined
'client_secret': client_secret, //clientSecret defined
};
var makePayment = function (req, res, next) {
var create_payment_json = {
"intent": "sale",
"payer": {
"payment_method": "paypal"
},
"redirect_urls": {
"return_url": "http://mystore.in",
"cancel_url": "http://mystore.in/contact"
},
"transactions": [
{
"amount": {
"currency": "USD",
"total": "1.00"
},
"description": "This is the payment description."
}
]
};
paypal_sdk.payment.create(create_payment_json,config_opts, function (err, data) {
if (err) console.log("ERRRRR", err);
console.log("Create Payment Response");
console.log(data);
//res.send('201');
});
}
makePayment(); //CALLING THE FUNCTION
But, when I am trying to create a new payout, by editing create_payment_json as:
var create_payment_json = {
"sender_batch_header": {
"email_subject": "You have a Payout!",
"recipient_type": "EMAIL"
},
"items": [
{
"recipient_type": "EMAIL",
"amount": {
"value": "1.0",
"currency": "USD"
},
"note": "Thanks for your patronage!",
"sender_item_id": "201403140001",
"receiver": "shirt-supplier-one#mail.com"
}
]
};
And main function as:
paypal_sdk.payout.create(create_payment_json,config_opts, function (err, data) {
if (err) console.log("ERRRRR", err);
console.log("Create Payment Response");
console.log(data);
//res.send('201');
});
I am receiving an error as follows:
{ [Error: Response Status : 401]
response:
{ error: 'invalid_client',
error_description: 'Client Authentication failed',
httpStatusCode: 401 },
httpStatusCode: 401 }
However, I am sure that credentials passed are correct and they are working perfectly in case of payment creation.
I am doing all this for the testing first. Also, the payout feature is enabled for this respective test paypal developer account.
Is there any possible solution?
I just got the solution. Well, to add, I must say paypal should provide proper error handling to let the developers know the reason behind each error.
The error was because of the currency that I had set in the configuration. The testing developer account was of some other country and the currency code was set as "USD".
Just make a new account and set currency code in config according to the country you had selected during the creation of that test developer account.
I test payout , as below code, it works fine. You can compare your code with my sample, you can add'sender_batch_id' parameter to have a try.
curl -v https://api.sandbox.paypal.com/v1/payments/payouts/ \
-H "Content-Type:application/json" \
-H "Authorization: *****" \
-d '{
"sender_batch_header": {
"sender_batch_id": "batch_25",
"email_subject": "You have a payment"
},
"items": [
{
"recipient_type": "EMAIL",
"amount": {
"value": 0.99,
"currency": "USD"
},
"receiver": "aaabbb#email.com",
"note": "Thank you.",
"sender_item_id": "item_1"
},
{
"recipient_type": "EMAIL",
"amount": {
"value": 0.90,
"currency": "USD"
},
"receiver": "bbbb#gmail.com",
"note": "Thank you.",
"sender_item_id": "item_2"
},
{
"recipient_type": "EMAIL",
"amount": {
"value": 2.00,
"currency": "USD"
},
"receiver": "cccc#gmail.com",
"note": "Thank you.",
"sender_item_id": "item_3"
}
]
}'
This is how I create Paypal payment from my webapp :
paypal.configure(paypal_config.api);
var payment = {
"intent": "sale",
"payer": {
"payment_method": "paypal"
},
//"receiver_email": "business#place.fr",
"redirect_urls": {
"return_url": "http://yoururl.com/execute",
"cancel_url": "http://yoururl.com/cancel"
},
"transactions": [{
"item_list": {
"items": [{
"name": "item",
"sku": "item",
"price": "1.00",
"currency": "USD",
"quantity": 1
}]
},
"amount": {
"currency": "USD",
"total": "1.06",
"details": {
"subtotal": "1.00",
"tax": "0.03",
"shipping": "0.03"
}
},
"description": "This is the payment description."
}]
};
paypal.payment.create(payment, function (error, payment) {
if (error) {
console.log(error);
} else {
if(payment.payer.payment_method === 'paypal') {
req.session.paymentId = payment.id;
var redirectUrl;
for(var i=0; i < payment.links.length; i++) {
var link = payment.links[i];
if (link.method === 'REDIRECT') {
redirectUrl = link.href;
}
}
res.redirect(redirectUrl);
}
}
});
It works perfectly but I have 2 problems, I need to set the receiver email, and the request is said to be malformed when I add the key "receiver_email".
My second problem is more a question in fact, with this method I know directly if the payment is validated or not, but what happened when a payment need more time to be validated (bank transfer etc..), there's no ipn url to give ?
Thank you !
Currently with PayPal rest payments, you cannot configure the receiver, so the payee has to be the one with the client_id/client_secret pair.
To your second question, currently ipn support is not there for REST payments but the "http post to your server when payment status changes" feature will be coming for REST payments soon. Currently the best option is to fetch the payment with the PAY-XXX id by doing a GET to check change of status.
I don't think setting receiver to be different from the client_id is supported at the moment.