Paypal API Express Checkout in PHP Payment error code 13113 - php

We have tried and tested our site with Paypal sandbox and it works fully deducting the amount.
We switched the API details to Paypal and the links. We have tried with several paypal accounts to see if it works (all of them have enough funds for the transaction).
We recieve this back through the API on our returnUrl page -
The API Call Failed
Array ( [TIMESTAMP] => 2012%2d07%2d15T19%3a31%3a43Z [CORRELATIONID] => 927a89205e54a
[ACK] => Failure [VERSION] => 65%2e1 [BUILD] => 3300093 [L_ERRORCODE0] => 13113
[L_SHORTMESSAGE0] => Buyer%20Cannot%20Pay%2e [L_LONGMESSAGE0] =>
The%20Buyer%20cannot%20pay%20with%20PayPal%20for%20this%20Transaction%2e [L_SEVERITYCODE0] => Error )
Php to make the final API call -
$APIUSERNAME="*****";
$APIPASSWORD="***";
$APISIGNATURE="*****";
$ENDPOINT = "https://api-3t.paypal.com/nvp";
//$ENDPOINT = "https://api-3t.sandbox.paypal.com/nvp";
$VERSION = "64";
//Build the Credential String:
$cred_str = "USER=" . $APIUSERNAME . "&PWD=" . $APIPASSWORD . "&SIGNATURE=" .
$APISIGNATURE . "&VERSION=" . $VERSION;
//Build NVP String for GetExpressCheckoutDetails
$nvp_str = "&METHOD=GetExpressCheckoutDetails&TOKEN=" . urldecode($token);
//Lets combine both strings then make the API call
$req_str = $cred_str . $nvp_str; $response = PPHttpPost($ENDPOINT, $req_str);
The above array comes from when i recieve my final acknowledgment from paypal.
//check Response
if($doresponse['ACK'] == "Success" || $doresponse['ACK'] == "SuccessWithWarning") {
echo "completed"; //just put to test
include "finishtransaction.php"; //cancels my cart sessions
} else{
echo "The API Call Failed"; print_r($doresponse);
}
There is not much on google about this error, not even in the API error codes. Has anyone come accross this before?

The PayPal API Error Codes are admittedly not very helpful.
Error code 13113, or "The Buyer cannot pay with PayPal for this Transaction" means that PayPal has taken a security measure by refusing to process the transaction. This can happen for one of the following reasons (there are more, but here are a few):
The buyer does not have enough money in their account
The buyer does not have enough money in their account, and there is a problem charging their credit card (if they have that set in their settings)
The buyer has asked for a refund on another item from the seller, and PayPal has therefore blocked the buyer's account from transferring money to the seller until the situation has been resolved.
The buyer is suspected of fraudulent activity, so there is a freeze on their accounts.
The buyer's account is restricted to sending money to the specific seller for some other reason
The buyer's account is entirely frozen for some specific reason
Unfortunately, there isn't much anyone can tell you without thoroughly looking through your code. I would check my code and make sure all appropriate flags and what-not are set. If you wait a few hours and are still getting the error (especially on multiple/new accounts), then you will need to contact PayPal.
I know it sucks, but only PayPal will be able to tell you why exactly the transaction is failing.

Related

Verify stripe payment amount

For my shopping site I have a fairy simple stripe implementation on the frontend where user hits "pay through stripe" button fills in CC details in a popup and hits proceed. If all goes well I get a token as $_POST['stripeToken'] which I process like below (for web payments)
try
{
$stripe = new Stripe();
$stripe = Stripe::make();
$customer = $stripe->customers()->create([
'email' => $_POST['email_id'],
'source' => $_POST['stripeToken']
]);
$charge = $stripe->charges()->create([
'customer' => $customer['id'],
'amount' => $total_amount, // note this is calculated again on server to prevent fraud
'currency' => 'sgd'
]);
}
catch (\Cartalyst\Stripe\Exception\CardErrorException $e)
{
return view('front.payment_error')->with('message', $e->getMessage());
}
Thing is we cannot rely on $total_amount coming from frontend form submission as user can easily spoof this amount and pay just $1 in stripe and get a token and spoof $total_amount to 1 thus getting products at whatever price he wants ,that's why I need to calculate his `$total_amount again on the server (from his cart) and use that to process stripe on the server.If that amount doesn't match what the token stands for , stripe would automatically raise an exception and prevent fraud.
So far good.. but the problem comes when dealing with API , mobile app will process stripe using their own libs. on the client side they would just send the final (for recording in db) but obviously I cannot use it to charge since that is already done on the mobile.Since these days it's very easy to change app behaviour (by patching apks) or craft custom HTTP request (postman) , server check is a must in case of payments.
So my question is how can I verify from the token the actual amount user paid
ie. reverse convert stripeToken => actual paid amount
Update:
This is what I am looking in case of Stripe
https://developer.paypal.com/docs/integration/mobile/verify-mobile-payment/

How to retrieve information about a transaction just performed?

This is my code:
$gateway = GatewayFactory::create('PayPal_Express');
$gateway->setUsername('name');
$gateway->setPassword('pass');
$gateway->setSignature('sig');
$gateway->setTestMode(true);
$resp = $gateway->purchase(
array(
'cancelUrl' => 'mysite/',
'returnUrl' => 'mysite/success',
'description' => "mysite item",
'amount' => $amount, //final amount
'currency' => 'EUR'
)
)->send();
if ($resp->isSuccessful()) {
// payment was successful: update database
// never reached
$a = new database('database');
$a->write database;
$dbp = null; die;
print_r($resp);
} elseif ($resp->isRedirect()) {
// redirect to offsite payment gateway
$resp->redirect();
} else {
echo $resp->getMessage();
header('Location: mysite/error');
exit;
}
How can I retrive informations about the transaction after the redirect?
How to adapt this code for credit card on paypal?
From your comments, I would assume that you're not getting to the successful payment stage.
With this in mind, let's take a look at the express checkout flow and compare it to a DoDirectPayment api call
===============
SetExpressCheckout API Call - the Shopping Cart announces the checkout details and gets back an "Express Checkout Token". The token identifies the checkout session that the shop has requested from PayPal
The buyer is redirected to the Express Checkout URL and the token gets appended to the redirect URL - https://www.sandbox.paypal.com/cgi-bin/webscr?cmd=_express-checkout&token=EC-6C677292NP7377708
(if you skip step 5, you have to add a useraction=commit parameter to the redirect URL)
The buyer logs in and approves the payment
The buyer is redirected back to the Return URL announced in the SetExpressCheckout API call with the PayerID and the Token added to the return URL as HTTP GET Parameters
5. The integration initiates a GetExpressCheckoutDetails API call, retrieves the shipping info and displays one last overview and the added shipping charges to the buyer
Once the buyer decides to complete the payment, he initiates the payment through your integration on your website. The website then calls the DoExpressCheckoutPayment API
===============
For Credit Card Payments via the DoDirectPayment API, the API NVP Request and Response would look like this - it should be pretty straight forward.
Request:
VERSION = 109.0
METHOD = DoDirectPayment
PAYMENTACTION = Sale
IPADDRESS = 192.168.0.1
AMT = 0.01
CREDITCARDTYPE = Visa
ACCT = xxxxxxxx6840
EXPDATE = 102020
CVV2 = 123
FIRSTNAME = John
LASTNAME = Test
STREET = 12312 Port Grace Blvd
CITY = La Vista
STATE = NE
COUNTRYCODE = US
ZIP = 68128
CURRENCYCODE = USD
Response:
TIMESTAMP=2015-01-20T16:00:27Z
CORRELATIONID=180513f33ad52
ACK=Success
VERSION=109.0
BUILD=14726230
AMT=0.01
CURRENCYCODE=USD
AVSCODE=X
CVV2MATCH=M
TRANSACTIONID=0PA61839GE498951M}
===============
Judging by your comments in the code, you're assuming that the transaction completes once step 4 is complete.
As I do not see any code to initiate a DoExpressCheckoutPayment API call, you will need to make sure at least step 6 is being done.
https://devtools-paypal.com/integrationwizard/ has standalone sample code that might help.
However, using an SDK based integration will relieve much of the pain:
https://devtools-paypal.com/guide/expresscheckout/php?interactive=ON&env=sandbox
...
If you want to retrieve Payment Details at a later stage, you can run a GetTransactionDetails API call against the Transaction ID returned in the DoDirectPayment API call or the DoExpressCheckoutPayment calls.
See: https://developer.paypal.com/webapps/developer/docs/classic/api/merchant/GetTransactionDetails_API_Operation_NVP/
You can use Instant Payment Notification to receive notifications about the just completed transaction. IPN is the recommended way to go.

Integrating PayPal REST API into Laravel using Omnipay - The card parameter is required

I'm using L5 and want to integrate my PayPal purchases into that system. The sandbox is already set up and I can do all my payments using the real PayPal API package, but as I want to try to do it with Omnipay I'm struggling a bit:
When I execute this code:
Route::get('test', function()
{
$gateway = Omnipay::create('PayPal_Rest');
$gateway->setClientId('{my id}');
$gateway->setSecret('{my secret}');
$gateway->setTestMode(true);
$params = array(
'cancelUrl' => 'http://webshop.app',
'returnUrl' => 'http://webshop.app/testresp',
'name' => 'Your Purchase',
'description' => 'Your Description',
'amount' => '15.99',
'currency' => 'EUR'
);
Session::put('params', $params);
Session::save();
$resp = $gateway->purchase($params)->send();
if ($resp->isSuccessful()) {
// payment was successful: update database
print_r($resp);
} elseif ($resp->isRedirect()) {
// redirect to offsite payment gateway
$resp->redirect();
} else {
// payment failed: display message to customer echo
$resp->getMessage();
}
});
I get this:
InvalidRequestException in AbstractRequest.php line 122:
The card parameter is required
Seems like I would have to initiate that purchase with credit card information of the client, which I do not want to gather (hence using PayPal in the first place). Is there any way to use that API without usage of a credit card?
I don't like the usage of the Express API as I don't want my PayPal username and password within my code. For several reasons.
The Card array field is required. it's not required to insert credit card number, but you will need to provide some information.
From the official docs:
Even off-site gateways make use of the CreditCard object, because often you need to pass customer billing or shipping details through to the gateway.
Check out the following branch of my fork of the omnipay-paypal gateway code: https://github.com/delatbabel/omnipay-paypal/tree/accept-paypal-payments
That includes code that allows you not to pass through a credit card and have PayPal do the payment processing.
I have submitted a PR but it hasn't been merged into the main omnipay-paypal repository yet.

How do I use omnipay to check if it's a pending payment or not

I'm using Omnipay 2.1 and CodeIgniter 2.1.4 to receive Paypal payments.
I use this line to complete the purchase and check if the payment was sent:
$bool = $gateway->completePurchase(array('amount' => $total, 'currency' => 'EUR'))
->send()
->isSuccessful();
But I noticed that the method isSuccessful() will also return true if the payment is on pending.
How can I use omnipay to check if it's a pending payment or not?
Looking at your raw response data, the important lines are:
[ACK] => Success
[PAYMENTINFO_0_CURRENCYCODE] => EUR
[PAYMENTINFO_0_PAYMENTSTATUS] => Pending
[PAYMENTINFO_0_PENDINGREASON] => multicurrency
So the payment was processed successfully, but is in a Pending state. Omnipay doesn't explicitly check for this, but I'm not sure that would be sensible anyway. From the customer's point of view, the payment was successful, and money has left their account.
Looking at the PayPal API documentation for PAYMENTINFO_0_PENDINGREASON:
multi-currency – You do not have a balance in the currency sent, and you do not have your Payment Receiving Preferences set to automatically convert and accept this payment. You must manually accept or deny this payment.
So basically the payment was successful, the only reason it is pending is that you are charging customers in a currency (EUR) that you haven't explicitly enabled in your PayPal account.
I believe you shouldn't be chaining isSuccessful() fn. Try just send() then checking the response from gateway:
$response = $gateway->purchase(['amount' => '10.00', 'currency' => 'USD')->send();
if ($response->isSuccessful()) {
// payment was successful: update database
print_r($response);
} else {
// debug etc;
print_r($response);
}
Otherwise you might be getting a bool for send() etc;
Recent versions of OmniPay have an isPending method in the Response class that you can use to check if a payment is pending.
If you see the possible reasons for a payment status being pending, some of these may lead to an unsuccessful payment.
E.g.
paymentreview
regulatory_review
echeck.
I would suggest its not a good idea to ship or confirm an order before checking this would not rely on the response isSuccessful method returning true by itself.

Paypal Express checkout not working? [duplicate]

We have tried and tested our site with Paypal sandbox and it works fully deducting the amount.
We switched the API details to Paypal and the links. We have tried with several paypal accounts to see if it works (all of them have enough funds for the transaction).
We recieve this back through the API on our returnUrl page -
The API Call Failed
Array ( [TIMESTAMP] => 2012%2d07%2d15T19%3a31%3a43Z [CORRELATIONID] => 927a89205e54a
[ACK] => Failure [VERSION] => 65%2e1 [BUILD] => 3300093 [L_ERRORCODE0] => 13113
[L_SHORTMESSAGE0] => Buyer%20Cannot%20Pay%2e [L_LONGMESSAGE0] =>
The%20Buyer%20cannot%20pay%20with%20PayPal%20for%20this%20Transaction%2e [L_SEVERITYCODE0] => Error )
Php to make the final API call -
$APIUSERNAME="*****";
$APIPASSWORD="***";
$APISIGNATURE="*****";
$ENDPOINT = "https://api-3t.paypal.com/nvp";
//$ENDPOINT = "https://api-3t.sandbox.paypal.com/nvp";
$VERSION = "64";
//Build the Credential String:
$cred_str = "USER=" . $APIUSERNAME . "&PWD=" . $APIPASSWORD . "&SIGNATURE=" .
$APISIGNATURE . "&VERSION=" . $VERSION;
//Build NVP String for GetExpressCheckoutDetails
$nvp_str = "&METHOD=GetExpressCheckoutDetails&TOKEN=" . urldecode($token);
//Lets combine both strings then make the API call
$req_str = $cred_str . $nvp_str; $response = PPHttpPost($ENDPOINT, $req_str);
The above array comes from when i recieve my final acknowledgment from paypal.
//check Response
if($doresponse['ACK'] == "Success" || $doresponse['ACK'] == "SuccessWithWarning") {
echo "completed"; //just put to test
include "finishtransaction.php"; //cancels my cart sessions
} else{
echo "The API Call Failed"; print_r($doresponse);
}
There is not much on google about this error, not even in the API error codes. Has anyone come accross this before?
The PayPal API Error Codes are admittedly not very helpful.
Error code 13113, or "The Buyer cannot pay with PayPal for this Transaction" means that PayPal has taken a security measure by refusing to process the transaction. This can happen for one of the following reasons (there are more, but here are a few):
The buyer does not have enough money in their account
The buyer does not have enough money in their account, and there is a problem charging their credit card (if they have that set in their settings)
The buyer has asked for a refund on another item from the seller, and PayPal has therefore blocked the buyer's account from transferring money to the seller until the situation has been resolved.
The buyer is suspected of fraudulent activity, so there is a freeze on their accounts.
The buyer's account is restricted to sending money to the specific seller for some other reason
The buyer's account is entirely frozen for some specific reason
Unfortunately, there isn't much anyone can tell you without thoroughly looking through your code. I would check my code and make sure all appropriate flags and what-not are set. If you wait a few hours and are still getting the error (especially on multiple/new accounts), then you will need to contact PayPal.
I know it sucks, but only PayPal will be able to tell you why exactly the transaction is failing.

Categories