Paypal error message "Capture amount exceeds allowable limit" - paypal

We wrote the below function in sandbox environment
function captureTransactions(access_token, d) {
try {
var req = http.request("POST", _config.host + "/v1/payments/authorization/" + d.authorization_id + "/capture", JSON.stringify({
"amount": {
"currency": "USD",
"total": d.total
},
"is_final_capture": true
}), {
"Content-Type": "application/json",
"Authorization": "Bearer " + access_token
});
var r = JSON.parse(req.readAll().toString());
} catch (e) {
console.error(e.stack);
console.error(r);
}
console.warn("[captureTransactions]", r);
return r;
};
and receive the below error
{
"name": "CAPTURE_AMOUNT_LIMIT_EXCEEDED",
"message": "Capture amount exceeds allowable limit.",
"information_link": "https://developer.paypal.com/webapps/developer/docs/api/#CAPTURE_AMOUNT_LIMIT_EXCEEDED",
"debug_id": "2fc79fc7df623"
}
Can anyone tell me what is the reason for receiving this msg and how to fix it? Note that we only test $5 payments so it shouldn't be due to transaction size. We did do multiple authorizations on the same card before, but not sure if that could be the reason for this error?
Appreciate your help!

I have had this problem on the live site with PayFlow today. It appears that you cannot use a "Credit Card" that is "Attached" to that "Gateway" account with "PayPal".
I supposed that is a method to stop "Customers" (PayPal payment service users) from "Paying" themselves as a Paypal employee explained to me on another separate issue. That is where we were testing a Billing Software with the gateway and refunding the money back to our account after the transaction. We were told that we could put our own money into our account(s) that way. At the time "I ask how we were to pay the $60.00 monthly fee if the business (PayPal account) hasn't collected/processed any money yet if we can't put money in there? This was resolved by the 1st part of this Answer.

Related

I don't understand how to get a token to make API calls

I'm using the Payouts API and to do so I have to specify an access token when calling https://api-m.sandbox.paypal.com/v1/payments/payouts
To get an access token, as specified here I have to send a POST request with Postman to https://developer.paypal.com/docs/api/overview/#get-an-access-token and it returns in the response the token
My problem is that this token has an expiration time, which is an issue because I can't go in my app every 15 minutes to change the token in the Authorization header. How can I get a "permanent" or rather an "auto refreshed" token ?
I tried to make a call from my app instead of Postman but it doesn't seem to work, it says my credentials are invalid
This is my code in case it can be useful (I'm managing everything from the front-end):
window.paypal
.Buttons({
createOrder: (data, actions) => {
return actions.order.create({
purchase_units: [
{
description: this.product.description,
amount: {
value: this.product.price
}
}
]
});
},
onApprove: (data, actions) => {
const timestamp = new Date().getUTCMilliseconds();
const id = timestamp;
return actions.order.capture().then(details => {
axios
.post(
"https://api-m.sandbox.paypal.com/v1/payments/payouts",
{
sender_batch_header: {
sender_batch_id: id,
email_subject: "You have a payout!",
email_message:
"You have received a payout! Thanks for using our service!",
recipient_type: "EMAIL"
},
items: [
{
amount: {
value: this.product.price,
currency: "USD"
},
note: "congrats someone bought your stuff",
sender_item_id: id,
receiver: "john#doe.com"
}
]
},
{
headers: {
Authorization:
"Bearer <my token that I get from postman>"
}
}
)
.then(() => {
alert(
"Transaction completed by " + details.payer.name.given_name
);
})
.catch(err => console.log(err));
});
}
})
.render(".paypal");
}
},
Update
Reading the code a second time and noticing how your Payout is for the same this.product.price as the original payment, that makes no sense. Don't use payouts at all for this use case. The full amount will go to your account normally, but if you want the full amount to go somewhere else instead, set the payee variable for this checkout: https://developer.paypal.com/docs/checkout/integration-features/pay-another-account/
(original answer below)
Using Payouts from the client side is an absolutely terrible idea, anyone with your client credentials will be able to send money from your account to wherever they want
The payouts API must be used from your server only. Your server needs to do an API call to get an access token, similar to what you mention about postman -- except using whatever backend environment you have. You can integrate direct HTTPS calls, or there are also Payouts SDKs available which will handle getting the access token automatically.
As for how to trigger that backend action when capturing a payment, use a proper server integration:
Create two routes, one for 'Create Order' and one for 'Capture Order', documented here. These routes should return JSON data. Before returning JSON data, that last route (the capture one) should record the successful transaction in your database and trigger any Payout logic you want.
Pair those two routes with the following approval flow: https://developer.paypal.com/demo/checkout/#/pattern/server

Stripe Charge Card via HTTP Rest API

I am attempting to charge a card via Stripe but am getting:
{ error:
{ type: 'invalid_request_error',
message: 'You must supply either a card or a customer id' } }
Below is in the body (assume api key is correctly in header, content type is application/x-www-form-urlencoded, it is a post request to https://api.stripe.com/v1/charges)
data = {
"amount": 400,
"currency": "usd",
"card": {
"number": "4242424242424242",
"exp_month": "12",
"exp_year": "2019",
"cvc": "442"
},
"description": "Charge for test#example.com"
}
Any idea why this isn't working? Is it formatted incorrectly? Can't find an example of doing it this way in Stripe Documentation. Can charging a card be done directly like this, or is a token required? If so, how can this be done via HTTP and not stripe.js?

paypal subscription with immediate first payment

I'm trying to set up recurring payment with immediate first payment.
For example you buy some monthly subscription on my website for $10. I take first $10 immediately and then I continue charge $10 monthly.
My problem is that I can't set up first immediate payment.
I use REST API:
https://developer.paypal.com/docs/api/#create-a-plan
Here is my JSON
{
name = Caption,
description = "Some Description"
type = "INFINITE",
payment_definitions =
[
{
name = "Some Name"
type ="REGULAR",
frequency = "DAY",
frequency_interval = 1,
amount = new
{
value = 10,
currency = "USD"
},
cycles = "0"
}
],
merchant_preferences
{
setup_fee = new
{
value = 10,
currency = "USD"
},
cancel_url = CancelUrl,
return_url = ReturnUrl,
max_fail_attempts = "5"
}
};
What should I add to my json, to make paypal take first payment immediately.
Thanks.
Edited:
I could find out some strange behavior:
My timezone is (UTC+04:00) Tbilisi. If I set up a transaction before 14:00 it processes immediately, but if I do it after, I have to wait until next day.
If the $10 is a one time payment then you should have it as the setup fee. The setup fee should be immediately processed.
Is only in sandbox is didn't work?
I've try a +1day (made the 24, and in the client, the first payment is for the 25) and nothing is transfered...

Paypal REST API Bug - Fee Charged By PayPal NOT SET in Response

UPDATE: Issue applies to both TEST and LIVE API Requests
At first I thought this was a Test Environment bug but I've confirms it applies to production as well. It's critical to know Fees Charged By PayPal.
Is there a way to get the Paypal Test environment (developer.paypal.com) to respond with fees charged by PayPal? Neither a Sale or a Sale Lookup seem to return the Paypal Fee seen in live transactions. Are we forced to test with live transactions (not a best practice)? Without the same fee values you see in the live environment, its hard to unit test our accounting system in development.
Request - Credit Card Charge ($43) with Stored Card
$cardToken = new CreditCardToken();
$cardToken->setCredit_card_id( $cc->getRefid() );
$fi = new FundingInstrument();
$fi->setCredit_card_token( $cardToken );
$payer = new Payer();
$payer->setPayment_method('credit_card');
$payer->setFunding_instruments(array($fi));
$amount = new Amount();
$amount->setCurrency('USD');
$amount->setTotal('43.00');
$transaction = new Transaction();
$transaction->setAmount($amount);
$transaction->setDescription($note);
$payment = new Payment();
$payment->setIntent('sale');
$payment->setPayer($payer);
$payment->setTransactions(array($transaction));
$response = $payment->create();
Response - Approved (full response)
PayPal\Api\Transaction Object
(
[_propMap:PPModel:private] => Array
(
[amount] => PayPal\Api\Amount Object
(
[_propMap:PPModel:private] => Array
(
[total] => 43.00
[currency] => USD
[details] => PayPal\Api\AmountDetails Object
(
[_propMap:PPModel:private] => Array
(
[subtotal] => 43.00
)
)
)
)
Documentation - Fee Charged By PayPal
(Below Image) - details object from the documentation showing a (string) fee charged by PayPal - Which doesn't seem to expose itself in the test environment.
Use the NVP API (GetTransactionDetails request) to return more accurate details in place of or along side the standard REST Responses. If you're interested I can post a PHP Example.
The REST API allows you to do things like manage a Credit Card vault.. so you can store a card and charge a card with the REST .. but when I charge it, I return the NVP API GetTransactionDetails response which includes Fees Charged By Paypal and everything else you need to know about the transaction that was charged via REST. It maybe be a hack and involve an extra API call but it works really well.
This is now available on the REST api. Specifically, via the transaction_fee on the sale object.
You can also access transaction_fee from a payment object by drilling down. Here's a (slightly redacted) example response:
{
"id": "PAY-5YK922393D847794YKER7MUI",
"state": "approved",
"intent": "sale",
"payer": {...},
"transactions": [
{
"related_resources": [
{
"sale": {
"id": "36C38912MN9658832",
"state": "completed",
"amount": {
"total": "7.47",
"currency": "USD"
},
"transaction_fee": {
"value": "1.75",
"currency": "USD"
}
}
}
]
}
]
}
For those following along at home, you can get the value of the transaction fee on this payment with the following simple and intuitive line of code:
payment.transactions[0].related_resources[0].sale.transaction_fee.value
See? Easy. Oh, but just remember - the sale object will not exist until after the payment has been executed.
Here's a massive ticket on the Ruby SDK about how this feature was added, if you want some light reading.
Looks like it's known bug that will be fixed. Don't have the date yet.

Pay with Paypal through Paypal REST API does not show up payment description on Paypal Sandbox or live sites

I am implementing Paypal's new REST API Pay with Paypal method that can be referenced here:
https://developer.paypal.com/webapps/developer/docs/integration/web/accept-paypal-payment/
The payment executes fine, exactly the way it should be. The user chooses to pay with Paypal and is then redirected to the Paypal site where he is expected to log in and approve the payment. The JSON data that I am sending Paypal is pretty much what is specified in the above link and mine looks like this:
{
"intent":"sale",
"redirect_urls":{
"return_url":"http://<return URL here>",
"cancel_url":"http://<cancel URL here>"
},
"payer":{
"payment_method":"paypal"
},
"transactions":[
{
"amount":{
"total":"7.47",
"currency":"USD"
},
"description":"This is the payment description."
}
]
}
As it redirects the user to the paypal website, the description and total amount column is shown blank
I am not sure if this is a mistake on Paypal's REST API but I believe I am providing the necessary description + amount payment to be reflected on this page. If this information is not shown, it is typically a deterrent to the user since they would definitely like to see the amount they are paying on the Paypal site even though this amount is listed on my website.
This is what it looks like:
For those who would like to indicate that the user has not logged in, well, even after logging in, the description and the current purchase column remain blank.
Am I missing any parameters that need to be sent to Paypal in order to indicate this description data?
Note: This issue persists for both the live and sandbox servers.
The left hand pan in above page displays:
1. Item details from order. You can include item list as part of the transaction details in payment resource. The same will be displayed here.
2. Components of the transaction amount e.g. shipping amount, tax, etc. if you include them in request.
Try this request to see example:
{
"intent": "sale",
"payer": {
"payment_method": "paypal"
},
"redirect_urls": {
"return_url": "http://<return url>",
"cancel_url": "http://<cancle url>"
},
"transactions": [
{
"amount": {
"total": "8.00",
"currency": "USD",
"details": {
"subtotal": "6.00",
"tax": "1.00",
"shipping": "1.00"
}
},
"description": "This is payment description.",
"item_list": {
"items":[
{
"quantity":"3",
"name":"Hat",
"price":"2.00",
"sku":"product12345",
"currency":"USD"
}
]
}
}
]
}
Thank you. Madhu remember to use the rest-api library!
Details amountDetails = new Details();
amountDetails.setSubtotal(autoregistro.getPedido().getItems().get(0).getTotal().toPlainString());
amountDetails.setTax("0");
amountDetails.setShipping("0");
Amount amount = new Amount();
amount.setCurrency("USD");
amount.setTotal(autoregistro.getPedido().getItems().get(0).getTotal().toPlainString());
// amount.setTotal("7.47"); // Los decimales deben ser con punto
amount.setDetails(amountDetails);
Item item = new Item();
item.setCurrency("USD");
item.setQuantity("1");
item.setName(autoregistro.getPedido().getItems().get(0).getDescripcion());
item.setPrice(amountDetails.getSubtotal());
List<Item> items = new ArrayList<Item>();
items.add(item);
ItemList itemList = new ItemList();
itemList.setItems(items);
Transaction transaction = new Transaction();
transaction.setDescription(item.getName());
transaction.setAmount(amount);
transaction.setItemList(itemList);
List<Transaction> transactions = new ArrayList<Transaction>();
transactions.add(transaction);
Payer payer = new Payer();
payer.setPaymentMethod("paypal");
// payer.setPaymentMethod("credit_card");
Payment payment = new Payment();
payment.setIntent("sale");
payment.setPayer(payer);
payment.setTransactions(transactions);
RedirectUrls redirectUrls = new RedirectUrls();
redirectUrls.setCancelUrl(this.configParameters.getAutoregistroURL() + "/pay_paypal?cancel=true");
redirectUrls.setReturnUrl(this.configParameters.getAutoregistroURL() + "/pay_paypal?success=true");
payment.setRedirectUrls(redirectUrls);
Payment createdPayment = payment.create(apiContext);