How do I resolve a 400 bad request error using the paypal rest api? - paypal

I am currently testing credit card payments using the PayPal payments pro Rest API.
I keep getting the following error:
Exception in HttpConnection Execute: Invalid HTTP response The remote server returned an error: (400) Bad Request. --->
I created and activated my PayPal test account and as following:
Credit card
Credit card number:
ccnumber here
Credit card type:
Visa
Expiration date:
3/2019
When I enter the above information in my payment form and submit I keep getting the 400 bad request error.
I have gotton this to work before with the PayPAl joe shopper account but lost the test cc number.
I am 100% sure I have authenticated with the oauth2 credentials
What is the likely cause of this error?:
I am entering a random payer first name and last name .
Does the name have to exsist?
What could be causing the error

If anything goes wrong in the data given, paypal api will return a 400 - Bad request error.
When I got the error(PHP SDK), I caught the exception and $ex->getData() returned a json which contains the details about the bad request, in my case the currency code I given was wrong.
try {
$payment->create($apiContext);
} catch (PayPal\Exception\PPConnectionException $ex) {
var_dump(json_decode($ex->getData()));
exit(1);
}

Like others here have said, there are several things that can cause the (HTTP 400 - Bad Request).
In my case it was due to using the same invoice number. For temporary testing I just used the ShoppingCartID that I generated with a guid. You could also use a Random number generator as well. Ultimately you will need to generate an invoice number to the clients specifications.
-Good luck

I just had the same problem (HTTP 400 - Bad Request). The cause is a REST API request with "errors". In my case I had two causes:
I passed amount details to an Amount object but the sum of subtotal, shipping an tax was not equal to the amount total.
I passed amount currency values including a fracture, but passed not exactly two decimals but only one. Obviously the REST API is a bit touchy and accepts only either no or two decimals.
I passed an item_list in the Transaction object but the sum of the prices in the Item object was not equal to the subtotal given in the amount details.
I don't know a way of finding the actual cause of the error (if there is one).
In your case it could be the name of the payer that you add. Try without.
Edit:
I just tried out: It is indeed the payer info. I passed a payer_info with first and lastname and got HTTP 400 (without everything worked). I assume that payer_info must not be set by us but is set by PayPal when returning a Payment object.
Payer payer = new Payer { payment_method = "paypal", payer_info = new PayerInfo {
first_name = "Zaphod", last_name = "Beeblebrox"} }; // => HTTP 400 - Bad Request

firstly find out what exactly what Your error is
payment = PayPal::SDK::REST::DataTypes::Payment.new(...)
payment.create
# got Response[400]: Bad Request here
payment.error
# got {"name"=>"VALIDATION_ERROR", "details"=>[{"field"=>"transactions", "issue"=>"
then find out what Your issue here to get more info
https://developer.paypal.com/webapps/developer/docs/api/#validation-issues

I had the same issue. In my case it was Credit Card issue which might be over used. So I have taken new Credit card Number from this site Testing Credit card and replaced with the old one.
Here is Credit Card Information that I used
credit_card = new CreditCard()
{
billing_address = new Address()
{
city = "Johnstown",
country_code = "US",
line1 = "52 N Main ST",
postal_code = "43210",
state = "OH"
},
cvv2 = "874",
expire_month = 11,
expire_year = 2018,
first_name = "Joe",
last_name = "Shopper",
number = "4024007185826731", //New Credit card Number, Only Card type should match other details does not matter
type = "visa"
}
Note: All the Credit Card mentioned in PayPal site are not working, giving same issue for me. If it working for you then it's good otherwise use new testing Credit Card Number. Hope this will help someone.
Thank you! Enjoy Coding!

I too got struck with this issue, there might be many other possible root cause for this failure but then in my case all my passing argument is correct, but then it failed in sandbox environment, I just changed Payment option from PayPal Balance to Visa then it started working.

I recently had a 400 bad request error as well. In my case, I was processing a refund using RefundRequest, and it appears that PayPal recently changed the constraints on the "reason" field (although it isn't documented that I can find) so my lengthy descriptions of what was being returned were no longer acceptable. I found the error only because I saw another field where PayPal was now requiring that it be only single-byte alphanumeric characters. What actually helped though, was shortening the data I was putting through as a reason to simply "Returned items".
Obviously this is an old thread, and I'm sure the original problem was solved long ago, but if using some of the above methods to determine more information about an error don't yield results I would suggest submitting a request with the bare minimum of information until you can get it to go through. Then, start adding additional fields/information back to see if you can identify which field contains the information causing the bad request. That would have worked for my issue, at least.

Understand your errors
PayPal returns detailed data on every exception (except 500 INTERNAL_SERVER_ERROR), explaining what was the exact error you are seeing. You can retrieve that as follows:
Update your exception handling to catch PayPalConnectionException and print $ex->getData() as shown below:
try {
$payment->create($apiContext);
} catch (PayPal\Exception\PayPalConnectionException $ex) {
echo $ex->getCode(); // Prints the Error Code
echo $ex->getData(); // Prints the detailed error message
die($ex);
} catch (Exception $ex) {
die($ex);
}

It is due to the wrong currency or amount you have given.
I faced the issue in React JS
I was doing this. in the createOrder method.
purchase_units: [{
amount: {
currency_code: 'PHP',
value: totalAmount
}
}],
that was the issue. If i gave any currency other than USD i will get the 400 Error. So i removed the currency_code from here
And I moved the currency declaration into my component declaration.
like this.
options={{
clientId: " Your_ID " ,
currency: "PHP"
}}
Here you can give any currency you want. This solves my 400 Error

If you use Paypal Sandbox for testing Driver and on first try with buggy code it shows the client a 400 Bad request error.
Reason:- Paypal sent JWT auth and it was stored in the client's local storage.
Suggestion:- Try to clear the client's local storage cache (You only need to clear the Paypal Token).
This works for me, I hope it works for you :)

Related

Paypal smart buttons credit card error management

I'm using paypal smart buttons sdk to fullfill paypal payment by credit card or paypal balance. the problem is for sandbox negative testing i was unable to test bad credit card cases because of lack of documentation (or may be it's me who didn't search enough).
so i decided to test in a production like environment with my production paypal business account and intentionally put a bad credit card secret .
The problem is when calling order.capture() function paypal raises a lot of errors but i'm unable to catch them and manage them correctly
here is my calling code :
onApprove: async (data: any, actions: any) => {
const order = await actions.order;
this.logger.log(order);
try {
order.capture().then((details: any) => {
this.logger.log('[PAYPAL onApprove : ]' + details);
const payPalCreateOrderResponse: PayPalCreateOrderResponse = new PayPalCreateOrderResponse();
payPalCreateOrderResponse.details = details;
this.checkOutEventsStore.paymentDetails = payPalCreateOrderResponse;
});
} catch (e) {
this.managePaypalError(params, e);
this.logger.error('====> Paypal Order Capture ERROR ' + e);
}
}
the errors i see in console :
POST https://www.paypal.com/smart/api/order/order_id_replaced/capture 500
(anonyme) # buttons?
(anonyme) # js?client-id=xxxxxxxxxxxxxxxxxxx&currency=EUR&locale=fr_FR&debug=true:4841
ZalgoPromise.try # js?client-id=xxxxxxxxxxxxxx&currency=EUR&locale=fr_FR&debug=true:770
(anonyme) # js?client-id=xxxxxxxxxxxxxx&currency=EUR&locale=fr_FR&debug=true:4834
(anonyme) # js?client-id=xxxxxxxxxxxxx&currency=EUR&locale=fr_FR&debug=true:4851
######## a lot of stack ommited
Error: Api: /smart/api/order/order_id_replaced/capture returned status code: 500 (Corr ID: f2967533987cc)
{"ack":"error","message":"Unhandled api error","meta":{"calc":"f2967533987cc","rlog":"rZJvnqaaQhLn%2FnmWT8cSUueWscmrtUHe5Y1Bd%2FeqyvyOTq66rSXAcgw%2BjwUfLWoirTjSF3Dcz2NbXl4NQOgVH84XX3DSygFN_17c9d7d88e6"},"server":"HR8xYFSZUP13jAt-X87VBJ7lq_LqwktwVsmzzP_zQqInVub3-ylXm8UuExvdz-SWJ0NH49XoaSL2hE_9LzQo_5B-X0COwFFVi2Z4c-cTCQBGoBSZtkefMbHWojX3rQ4-qLZIYQefq6OE7funNI8ZnGZUi9YpufYlG9X1qx89zj0l4LERQ9wesnqMpT59y3GbjqsfOGbGf7uasTCGOz6f58ZNMbdNVYrz1h5gc3sZbk-LhH5ks1k1DqJV7UPsxus1QBII26hjpRQbnFr6VLiyCW"}
and the most important , in the network api calls i can see clearly for :
https://www.paypal.com/smart/api/order/order_id_replaced/capture api call
a good json result for the error :
{"name":"UNPROCESSABLE_ENTITY","details":[{"issue":"INSTRUMENT_DECLINED","description":"The instrument presented was either declined by the processor or bank, or it can't be used for this payment."}],"message":"The requested action could not be performed, semantically incorrect, or failed business validation.","debug_id":"f569254a2e9c8","links":[{"href":"https://developer.paypal.com/docs/api/orders/v2/#error-INSTRUMENT_DECLINED","rel":"information_link","method":"GET"},{"href":"https://www.paypal.com/checkoutnow?token=token_replaced","rel":"redirect","method":"GET"}]}
So the question is how to manage this error correctly by using the js api.
Thank you for your Help .
Ryan
when calling order.capture() function paypal raises a lot of errors but I'm unable to catch them and manage them correctly
When capturing on the client side with .capture() , if the capture is declined PayPal will automatically offer the payer the ability to try again, likely falling back to a modal window. No error handling by you is necessary, required, nor possible.
If you were capturing on the server side (which you are not doing), there is sample error handling code in this demo.

PayPal Smart Button transaction not charging after 'approval'

After spending a full day on this dangerous thing, I can't understand how a transaction show APPROVED, I get an order ID, but there is no charge (not for buyer or receiver).
I am on live environment after tested on sandbox successfully.
So the code is long but basically on the server side we first create the transaction:
const request = new paypal.orders.OrdersCreateRequest();
request.prefer("return=representation");
request.requestBody({
intent: 'CAPTURE', //CAPTURE
purchase_units: [{
amount: {
currency_code: currency,
value: finalPrice
},
payee: {
email_address: payee
},
shipping: shipObj
}]
});
and later we approve the order with PayPal :
let request = new paypal.orders.OrdersGetRequest(orderID);
let order;
try {
order = await client.execute(request);
}
catch (err) {
console.error("error",err);
return res.sendStatus(500);
}
At this point i get order.result.status = APPROVED .
This is a live environment (the client and secret keys).
How can you send APPROVED to developer, and give an orderID but not charge ?
This is such a dangerous thing to do and can literally ruin businesses.
So then i found out there is a link to your order ID :
https://api.paypal.com/v2/checkout/orders/4PE63643WC652674S
If you look in this page you get this :
"message":"Authentication failed due to invalid authentication credentials or a missing Authorization header."
Now, only god knows what this means, and this is a failur message on an order ID page, which mean the orderID means nothing ??
So i also check the paypal link with my client-ID (should be identical to my client id in sdk right?) :
https://www.paypal.com/sdk/js?client-id=xxxxxxxxx&merchant-id=xxx#yyyy.com&disable-funding=credit,card&currency=USD
Which seems ok and contains the right email.
Seems like you may have solved the issue and that you were missing the capture step, which is a required step to commit the transaction and must always occur after approval.
Just to review the best ways to integrate, if you are doing so with API calls from a server, you'll want to set make two routes on your server, one for 'Set up Transaction' and one for 'Capture Transaction', documented here: https://developer.paypal.com/docs/checkout/reference/server-integration/
Then, the best JS customer approval flow to pair with those server-side routes is this: https://developer.paypal.com/demo/checkout/#/pattern/server

Paypal shopping cart AMOUNT_ERROR

I am having a issue with a paypal cart since the update around march (bit late but the site is not used yet and we just discovered it now).
I already checked this question but it did not solve the issue for a shopping cart (Paypal : hosted button payments fail with code=AMOUNT_ERROR)
We send a object that contains the request data through a plugin called neo.js, this works fine as far as we know.
This is our data we send to paypal as a js object.
{
amount_1: 10.01,
business: "noreply#domain.com",
cancel_return: "https://dev.domain.com",
charset: "utf-8",
cmd: "_cart",
currency_code: "US",
custom: "username",
item_name_1: "$10 item",
item_number_1: "1",
no_shipping: 1,
notify_url: "https://dev.domain.com/callback/paypal.php",
quantity_1: 1,
return: "https://dev.domain.com",
upload: 1
}
It has to do something with the amount, but using a , instead of . but that only gives a normal error message on screen that the format is incorrect.
We have tried multiple things including the dollar sign and making it a string but nothing seem to be working.
I reproduced the error and it is due to the wrong currency code passed.
You are passing "US" but the currency code (that is a parameter that refers to the AMOUNT as in the error returned) must be of 3 characters as you can see on PayPal guide: https://developer.paypal.com/webapps/developer/docs/classic/api/currency_codes/
Change it to "USD" instead and you will have a working checkout.

PayPal API charging card but returning error

Please excuse me if this is a newbie question but I have never worked with any sort of credit card API before and I am, well, pretty much a newbie...
I have a script with "PayPal integrated" heh, and its not working.
When I run a card on the PayPal Sandbox, the transaction seems to go through, my sandbox account gets credited the amount but the script returns this error:
TIMESTAMP: 2011-04-25T14:03:42Z
CORRELATIONID: 5e727288789fb
ACK: SuccessWithWarning
L_LONGMESSAGE0: This transaction has been completed, but the total of items in the cart did not match the total of all items.
AMT: 25.00
CURRENCYCODE: EUR
AVSCODE: X
TRANSACTIONID: 4MM79765A4836914N
I understand the error message, but I am not sure where to begin looking in order to try and rectify it.
Sorry if this question is blurry, I am pretty lost and hoping that someone could just help get me pointed in the right direction here?
Thanks in advance!
"In your request string you may have use &L_COST0=18.00& for amount".
which may create problem for transaction, The variable for line item is L_AMTn so in this case it should be &L_AMT0=18.00&.
Just try this if needed. otherwise send the request string you had pass for more detail view.
Thanks.
you are suppose to called this function-
$httpParsedResponseAr = PPHttpPost('DoDirectPayment', $nvpStr);
where
$nvpStr = &PAYMENTACTION=$paymentType&AMT=$amount&CREDITCARDTYPE=$creditCardType&ACCT=$creditCardNumber".
"&EXPDATE=$padDateMonth$expDateYear&CVV2=$cvv2Number&FIRSTNAME=$firstName&LASTNAME=$lastName".
"&STREET=$address1&CITY=$city&STATE=$state&ZIP=$zip&COUNTRYCODE=$country&CURRENCYCODE=$currencyID";
Some parameters may diff for your payment process,
so you can try this.
Thanks.

Paypal sandbox IPN return INVALID

I am trying IPN callback, using servlet. The code I am using is provided by paypal for verifying the ipn data. But every time i getting a INVALID response.
Here is the code:
Enumeration en = req.getParameterNames();
String str = "cmd=_notify-validate";
while (en.hasMoreElements()) {
String paramName = (String) en.nextElement();
String paramValue = req.getParameter(paramName);
//str = str + "&" + paramName + "=" + URLEncoder.encode(paramValue,"UTF-8"); // for UTF-8 i set the encode format in my account as UTF-8
//str = str + "&" + paramName + "=" + URLEncoder.encode(paramValue,"ISO-8859-1");// for ISO-8859-1 i set the encode format in my account as ISO-8859-1
str = str + "&" + paramName + "=" + URLEncoder.encode(paramValue); //default as provided by paypal
}
URL u = new URL("http://www.sandbox.paypal.com/cgi-bin/webscr");
URLConnection uc = u.openConnection();
uc.setDoOutput(true);
uc.setRequestProperty("Content-Type", "application/x-www-form-urlencoded");
PrintWriter pw = new PrintWriter(uc.getOutputStream());
pw.println(str);
pw.close();
BufferedReader in = new BufferedReader(new InputStreamReader(uc.getInputStream()));
String res = in.readLine();
in.close();
if (res.equals("VERIFIED") || !res.equals("VERIFIED")) {
//Update database...
} else if (res.equals("INVALID")) {
//INVALID
}
I have checked all three possibilities provided by paypal in case paypal return INVALID as follow:
1) Missing Parameters - As I am send all the parameters no issue of missing parameters
2) Invalid URL. - I am using sandbox so URL is : http://www.sandbox.paypal.com/cgi-bin/webscr
3) Character encoding. - Tried with character encoding same as paypal account setting parameter encoding.
the request I am sending back to paypal using following parameters:
cmd=_notify-validate&last_name=User&test_ipn=1&address_name=Test+User&txn_type=web_accept&receiver_email=sellr1_1252495907_biz%40gmail.com&residence_country=US&address_city=San+Jose&payment_gross=&payment_date=01%3A55%3A04+Sep+26%2C+2009+PDT&address_zip=95131&payment_status=Completed&address_street=1+Main+St&first_name=Test&payer_email=buyer1_1252495751_per%40gmail.com&protection_eligibility=Eligible&payer_id=BXBKS22JQCUWL&verify_sign=AOMkeg7ofCL7FJfioyWA19uCxD4XAgZirsjiGh8cUy1fd2YAqBwOkkst&payment_type=instant&business=sellr1_1252495907_biz%40gmail.com&address_country_code=US&mc_fee=0.64&address_status=confirmed&transaction_subject=True+Up&quantity=1&notify_version=2.8&mc_currency=EUR&custom=&address_state=CA&payment_fee=&handling_amount=0.00&payer_status=verified&shipping=0.00&item_name=True+Up&tax=0.00&username=hannonj&charset=windows-1252&item_number=567&mc_gross=10.00&txn_id=7F456350BS7942738&receiver_id=MASSU6BSR9SC2&address_country=United+States
Please , can any one direct me to proper direction? I am not getting what is wrong the code or the URL or anything else. I tried all the possibilities. Please help me.
An “INVALID” message is due to the following reasons:
Check that your are posting your response to the correct URL, which is https://www.sandbox.paypal.com/cgi-bin/webscr or https://www.paypal.com/cgi-bin/webscr, depending on whether you are testing in the Sandbox or you are live, respectively.
Verify that your response to the test IPN message contains exactly the same variables and values as the test message and that they are in the same order as in the test message. Finally, verify that the original variables are preceded by a cmd=_notify-validate variable.
Ensure that you are encoding your response string and are using the same character encoding as used by the test IPN message. (for example, I can see that he is using letters with umlaut and other symbols like “/”, etc).
With regard to the last point, the merchant can try to change the encoding language in use in his PayPal account, following the steps below:
Login on you PayPal account
Click on Profile
Click on “My Selling Preferences” tab
Click on “PayPal Button Language Encoding” (at the end of the page)
Click on "Other Options"
Select from the drop down menu: UTF-8
Choose the same charset also for the second option, which is related to IPN
Click “Save”
If the issue persists, we recommend to review the script in use, PayPal has some IPN code samples available at: https://github.com/paypal/ipn-code-samples
For additional information I include the link: https://developer.paypal.com/webapps/developer/docs/classic/ipn/integration-guide/IPNTesting/#id091GFE00WY4
I'm pretty sure the URL to send to is just "www.sandbox.paypal.com", see chapter 4 of Sandbox User Guide, and well, this is what I put for my own code (incidentally, for live, it is also just "www.paypal.com", for their sample code)
Thank you guys for your reply.
ohhh I solved it at last.
Actually in notify URL I also added a username parameter. Paypal want the parameter values for IPN same as it return to the servlet.(You can get it as req.getParameterNames()). As I have username parameter extra, which is not known to paypal. Paypal was returning INVALID.
Remember paypal's sandbox has completely different credentials. You must have development account and be logged into development panel to use sandbox.
If you're testing Paypal IPN over SSL, you will have to use ssl://www.sandbox.paypal.com on the port 443
I ran into multiple problems layered on top of each other before I could get Paypal IPN working - it kept returning INVALID but was not specific about which part I was getting wrong, unfortunately.
Things I got wrong:
Sandbox - if you use the Sandbox you need to use the entire Sandbox environment. It requires creating a new, separate account on the Paypal Sandbox website. The Sandbox API credentials it sets up under your regular account are not enough. You then use that separate Paypal account to file fake transactions on the Paypal Sandbox website, and watch them come across IPN on the Sandbox endpoint. The need for this second account is not obvious or clear at all in setting up API access. Also, switching between Sandbox and Live requires more than switching the URL, you need to switch the credentials. So a simple compile flag alternating a string isn't going to cut it.
Live - if you use the Live environment a number of things will get in your way. For us, it took a long time for Paypal to open up "Business" access to us. It wouldn't provide us anything over the API until that was enabled. When we initially applied we were flatly denied with no explanation or timeline to resolve it. A month later ish of taking payments (with no API to keep us up to date with those payments) it seemed to just magically start working.
Code example - the code example provided by Paypal is outdated, and has some clear issues. Here's an example that uses modern TPL/async:
// Send the verification back to Paypal in the format Paypal requested
var verif = (HttpWebRequest)WebRequest.Create(ipnVerifyUrl);
verif.Method = "POST";
verif.ContentType = "application/x-www-form-urlencoded";
var param = req.BinaryRead(req.TotalBytes);
var sRequest = Encoding.ASCII.GetString(param);
sRequest = "cmd=_notify-validate&" + sRequest;
verif.ContentLength = sRequest.Length;
using (var streamOut = new StreamWriter(verif.GetRequestStream(), Encoding.ASCII))
{
await streamOut.WriteAsync(sRequest);
}
// Send it
using (var re = await verif.GetResponseAsync())
{
var s = await HttpWebRequestAsync.GetFullResponseStringAsync((HttpWebResponse)re);
// Log the response (s)
}
Besides this code actually working (This is exactly what we have in Production, with some of our logging library calls stripped out), this code won't freeze a thread while waiting on network.
The awaits allow the thread to step away while the network does its thing, both in writing the verification request to Paypal, and in receiving the response back, both of which could be a long time.