Omnipay with Paypal Express - php

I have an ecommerce website that redirects to a Paypal express checkout using Omnipay. It will correctly redirect the user to Paypal and return with a successful message with payerID and everything. However, it does not actually take any payment and it does not show up on our paypal account as any payment taken. I am not sure if this is a paypal issue or a configuration problem with Omnipay. I would imagine that Paypal handles this part of it but since it's not working (on our old site it works fine but we do not use Omnipay.)
$gateway = Omnipay::gateway('paypal');
//production
$gateway->setUsername('11111111');
$gateway->setPassword('1111111111');
$gateway->setSignature('111111111');
$cardInput = array(
'firstName' => $info['first_name_bill'],
'lastName' => $info['last_name_bill'],
'billingAddress1' => $info['street_address_1_bill'],
'billingAddress2' => $info['street_address_2_bill'],
'billingPhone' => $info['phone_bill'],
'billingCity' => $info['city_bill'],
'billingState' => $info['state_bill'],
'billingPostCode' => $info['zip_bill'],
'shippingAddress1' => $info['street_address_1_ship'],
'shippingAddress2' => $info['street_address_2_ship'],
'shippingPhone' => $info['phone_ship'],
'shippingCity' => $info['city_ship'],
'shippingState' => $info['state_ship'],
'shippingPostCode' => $info['zip_ship'],
);
$card = Omnipay::creditCard($cardInput);
//live
$response = Omnipay::purchase(
array(
'cancelUrl' => 'http://store.site.com/cart/cancel-payment',
'returnUrl' => 'http://store.site.com/cart/successful-payment',
'amount' => Input::get('total'),
'currency' => 'USD',
'card' => $card,
'description' => 'Stuff'
)
)->send();
if ($response->isSuccessful()) {
return Redirect('cart/successful-payment');
} elseif ($response->isRedirect()) {
$response->redirect(); // this will automatically forward the customer
} else {
return Redirect::back()->with('error', 'There was a problem. Please try again.');
}
} else {
return Redirect::to('cart/successful-payment');
}
So basically what this will do is redirect them to Paypal to make a payment then redirect back to our store. That all works fine. They can input their card number and then come back to our store after submitting it. The issue is after it gets return nothing happens through paypal. No orders or payment are exchanged.

In your return function, the function that gets called when this URL is executed: http://store.site.com/cart/successful-payment you need to call completePurchase. Something like this:
$gateway = Omnipay::gateway('paypal');
//production
$gateway->setUsername('11111111');
$gateway->setPassword('1111111111');
$gateway->setSignature('111111111');
$purchaseId = $_GET['PayerID'];
$response = $gateway->completePurchase([
'transactionReference' => $purchaseId
])->send();
// .. check $response here.

Related

PayPal Sandbox "Sorry, we can’t complete your purchase at this time "

I have set up PayPal Sandbox to test my PayPal Express integration, but whenever I log in to the sandbox from the payment page, I get greeted by the following error message;
I am using laravel-omnipay and omnipay-paypal with the PayPal_Express gateway.
I think this is likely to be a configuration issue (or a bug..? Although I'm hoping it's not.) in PayPal, but this is the piece of code I am using to initiate the payment:
public function checkout ()
{
$cart = Cart::forSession ();
$response = Omnipay::purchase
(
[
'amount' => $cart->getPrice (),
'currency' => preferred_currency ()->name,
'description' => (string) $cart,
'returnUrl' => URL::action ('OrderController#checkoutReturn'),
'cancelUrl' => URL::action ('OrderController#checkoutCancel')
]
)->send ();
if ($response->isSuccessful ())
dd ('successful', $response);
else if ($response->isRedirect ())
return $response->getRedirectResponse ();
else
return Redirect::to ('/cart')->with ('alerts', [new Alert ('An error occurred while attempting to process your order: ' . $response->getMessage (), Alert::TYPE_ALERT)]);
}
And the omnipay.php configuration file:
return array(
'gateway' => 'PayPal_Express',
'defaults' => array(
'testMode' => true,
),
'gateways' => array(
'PayPal_Express' => array(
'username' => '<>',
'password' => '<>',
'signature' => '<>',
'landingPage' => array('billing', 'login'),
),
),
);
The username, password and signature I am using are the ones I created in the PayPal Sandbox for my account.
The sandbox account I am using to test this is a "personal"/buyer account, with funding sources and "Payment Review" disabled. The Sandbox Accounts overview on the PayPal Developer website indicates the sandbox account's status as "complete".
I'm hoping I didn't miss something obvious. I checked out some of the other answers on Stack Overflow but none of those seemed to offer a solution for this exact problem.
Contact PayPal support, as there is something wrong on their end.

Does the creditCard function exist in Omnipay PayPal Express? Or only in PayPal Pro?

This question is maybe similar to THIS and THIS but I'm not entirely sure.
I've made a shopping cart that sends the product details and quantity/total amount to Paypal on checking out. I'm using Laravel 4 and the Omnipay Paypal plugin (Paypal_Express). I can send product details fine using the 'setItems' function and am now looking to pre-populate the credit card field on the Paypal summary page with my User's details.
I have seen in other SO threads such as THIS that other people use the creditCard function to pass details to the Paypal summary credit card info page.
My question: 1) Do you need to be using Paypal_Pro for the creditCard function to worK?
I get this error when I try (call_user_func_array() expects parameter 1 to be a valid callback, class 'Omnipay\Common\GatewayFactory' does not have a method 'creditCard').
I don't want to enter all the credit card details - Just speed the process up by entering the User's Name, Adress etc...
Also I tried changing to Paypal_Pro and it didn't work. (same error as above) I changed config plus gateways in my payment controller.
2)How do you change PayPal_Express to PayPay_Pro?
My code:
public function postPayment() {
$cart = Session::get('cart');
$allProducts = [];
foreach($cart->aContents as $productID=>$quantity){
$product = Product::find($productID);
// get the product id
// load the product from the id
// store data in the allProduct array
$allProducts[] = array('name' => $product->name, 'quantity' => $quantity, 'price'=> $product->price);
}
$cardInput = array(
'first_name' => Input::get('first_name'),
'last_name' => Input::get('last_name'),
'address1' => Input::get('address1'),
'city' => Input::get('city'),
'zip' => Input::get('zip'),
'email' => Input::get('email')
);
$card = Omnipay::creditCard($cardInput);
$params = array(
'cancelUrl' => \URL::to('cancel_order'),
'returnUrl' => \URL::to('payment_success'),
'amount' => Input::get('price'),
'currency' => Input::get('currency'),
'card' => $card,
);
Session::put('params', $params);
Session::save();
$gateway = Omnipay::create('PayPal_Express');
$gateway->setUsername('tjmusicmanagement-facilitator_api1.gmail.com');
$gateway->setPassword('K2LWQVP2L8472BPY');
$gateway->setSignature('AwTOuAJWzCkdc5PldYeiz.l3iy5UAwOucYW6EFLLA9zUQqXaWyEGbebq');
$gateway->setTestMode(true);
$gateway->setLogoImageUrl(URL::to('images/logoSmall.png'));
$response = $gateway->purchase($params)->setItems($allProducts)->send();
if ($response->isSuccessful()) {
// payment was successful: update database
print_r($response);
} elseif ($response->isRedirect()) {
// redirect to offsite payment gateway
$response->redirect();
} else {
// payment failed: display message to customer
echo $response->getMessage();
}
}
And also the ignited\laravel-omnipay\config.php is unchanged (though I did try changing the driver)
return array(
// The default gateway to use
'default' => 'paypal',
// Add in each gateway here
'gateways' => array(
'paypal' => array(
'driver' => 'PayPal_Express',
'options' => array(
'solutionType' => '',
'landingPage' => '',
'headerImageUrl' => ''
)
)
)
);
Thanks for your tinme!!
EDIT: Here is my getSuccessPayment function where I can hopefully get the users paypal details (just name and address etc) from paypal. But how and where do I specify this?
public function getSuccessPayment()
{
$gateway = Omnipay::create('PayPal_Express');
$gateway->setUsername('lillyloverofwar-facilitator_api1.gmail.com');
$gateway->setPassword('U6LM3SG2MNCA3QE2');
$gateway->setSignature('AJVP9tUtdotIeVt82RpcG7n9ld-tAdCG1Ramb1u8yZECHhSpiXc0BO04');
$gateway->setTestMode(true);
$params = Session::get('params');
$response = $gateway->completePurchase($params)->send();
$paypalResponse = $response->getData(); // this is the raw response object
if(isset($paypalResponse['PAYMENTINFO_0_ACK']) && $paypalResponse['PAYMENTINFO_0_ACK'] === 'Success') {
// return View::make('successfulPayment')->with($params);
// Session::flush();
// Response
// print_r($paypalResponse);
} else {
//Failed transaction
}
// FLUSHING SESSION HERE GETS AN ERROR
// Session::flush();
return View::make('successfulPayment');
}
1) I get this error when I try (call_user_func_array() expects parameter 1 to be a valid callback, class 'Omnipay\Common\GatewayFactory' does not have a method 'creditCard').
You can't use credit cards on the PayPal Express gateway, only on Pro or REST. I recommend that you use the REST gateway not the Pro gateway (REST supersedes Pro and has more features).
I don't want to enter all the credit card details - Just speed the process up by entering the User's Name, Adress etc...
There is no need to do that if you are using PayPal Express anyway, because PayPal will provide you the necessary details after the user has gone through the PayPal login process and authorized the transaction.
Also I tried changing to Paypal_Pro and it didn't work. (same error as above) I changed config plus gateways in my payment controller.
2)How do you change PayPal_Express to PayPay_Pro?
I suggest you have a look at my fork of the omnipay-paypal gateway, https://github.com/delatbabel/omnipay-paypal -- on the accept-paypal-payments branch there are additional commits (sent as a PR to the main repository but not merged yet) with additional features such as using the REST gateway for either Credit Card or PayPal purchases, and additional API documentation including code examples on how to use the REST gateway.
Here is the code example for using the Rest gateway for a purchase transaction with a credit card:
// Create a gateway for the PayPal RestGateway
// (routes to GatewayFactory::create)
$gateway = Omnipay::create('RestGateway');
// Initialise the gateway
$gateway->initialize(array(
'clientId' => 'MyPayPalClientId',
'secret' => 'MyPayPalSecret',
'testMode' => true, // Or false when you are ready for live transactions
));
// Create a credit card object
// DO NOT USE THESE CARD VALUES -- substitute your own
// see the documentation in the class header.
$card = new CreditCard(array(
'firstName' => 'Example',
'lastName' => 'User',
'number' => '4111111111111111',
'expiryMonth' => '01',
'expiryYear' => '2020',
'cvv' => '123',
'billingAddress1' => '1 Scrubby Creek Road',
'billingCountry' => 'AU',
'billingCity' => 'Scrubby Creek',
'billingPostcode' => '4999',
'billingState' => 'QLD',
));
// Do a purchase transaction on the gateway
$transaction = $gateway->purchase(array(
'amount' => '10.00',
'currency' => 'AUD',
'description' => 'This is a test purchase transaction.',
'card' => $card,
));
$response = $transaction->send();
if ($response->isSuccessful()) {
echo "Purchase transaction was successful!\n";
$sale_id = $response->getTransactionReference();
echo "Transaction reference = " . $sale_id . "\n";
}

Use Paypal Pro instead of Paypal Express - Omnipay for Laravel

I have a shopping cart that currently is redirecting users to paypal directly to make their payment. I am wanting to allow customers to input their credit card on the site and paypal to process it. I have Paypal Pro account but I am having trouble using it. I am not sure how I can use the Paypal Pro package via Omnipay. In my vendors folder I have a ExpressGateway.php and a Progateway.php but not sure how to call the Progateway.php page. The only way I can see to set it is by using Omnipay::getway('paypal') which I currently do for express. What is the process i need to use in order to use Paypal Pro?
$gateway = Omnipay::gateway('paypal');
if(Auth::user() != NULL && Auth::user()->super_user == 1) {
//sandbox
$gateway->setUsername('#######');
$gateway->setPassword('#######');
$gateway->setSignature('#######');
$gateway->setTestMode('true');
} else {
//production
$gateway->setUsername('#######');
$gateway->setPassword('#######');
$gateway->setSignature('######');
}
$cardInput = array(
'firstName' => $info['first_name_bill'],
'lastName' => $info['last_name_bill'],
'billingAddress1' => $info['street_address_1_bill'],
'billingAddress2' => $info['street_address_2_bill'],
'billingPhone' => $info['phone_bill'],
'billingCity' => $info['city_bill'],
'billingState' => $info['state_bill'],
'billingPostCode' => $info['zip_bill'],
'shippingAddress1' => $info['street_address_1_ship'],
'shippingAddress2' => $info['street_address_2_ship'],
'shippingPhone' => $info['phone_ship'],
'shippingCity' => $info['city_ship'],
'shippingState' => $info['state_ship'],
'shippingPostCode' => $info['zip_ship'],
);
$card = Omnipay::creditCard($cardInput);
$response = Omnipay::purchase(
array(
'cancelUrl' => URL::to('cart'),
'returnUrl' => URL::action('CartController#getSuccessPayment', array('id' =>$invoice->id)),
'amount' => Input::get('total'),
'currency' => 'USD',
'card' => $card,
'description' => '#####'
)
)->send();`
Set the gateway this way:
$gateway = Omnipay::gateway('Paypal_Pro');

Omnipay 3Dsecure redirect

I am using Omnipay to allow users to pay using Cardsave.
I have the following:
\Omnipay::setTestMode(true);
$transactionId = date('YmdHis').$booking->space->id.$booking->user->id;
$response = $gateway->purchase([
'amount' => $booking->price,
'currency' => 'GBP',
'card' => $card,
'transactionId' => $transactionId,
'cancelUrl' => \base_url('cardsave/cancel/'.$booking->id),
'returnUrl' => \base_url('cardsave/confirm/'.$booking->id)
])->send();
if ($response->isSuccessful()) {
$transactionReference = $response->getTransactionReference();
//save the transaction reference in case of refund
return ['status' => 'success', 'message' => 'Reservation process complete'];
} elseif ($response->isRedirect()) {
\Log::info('3DSecure redirect');
$booking->addAdditional(['3dsecure_transaction_id' => $transactionId]);
return [
'status' => 'redirect',
'form_html' => $response->getRedirectResponse()->getContent()
];
}
throw new PaymentException ($response->getMessage());
and my confirm url goes to the following method:
$transactionId = $booking->getAdditional('3dsecure_transaction_id');
$response = $gateway->completePurchase([
'amount' => $amount,
'transactionId' => $transactionId,
'currency' => 'GBP',
])->send();
if ($response->isSuccessful()) {
$transactionReference = $response->getTransactionReference();
return $this->finalise($booking, $transactionReference);
} else {
$this->cancel($booking);
}
But looking through the code for league/omnipay-cardsave, I see the following:
$md = $this->httpRequest->request->get('MD');
$paRes = $this->httpRequest->request->get('PaRes');
if (empty($md) || empty($paRes)) {
throw new InvalidResponseException;
}
So my question is (and I realise it is probably dumb, but I can't seem to grok this, for some reason), where is that request coming from, if I just instantiated the gateway?
I think I am doing this wrong.
EDIT:
I have discovered that the return call from the 3DSecure thing comes with the MD and PaRes values as POST parameters. This allows me to set them on the gateway. How do I do that? Is it done automatically when I instantiate the gateway?
I was right, the question was dumb.
After reading the code, and trying it out, I found out that the AbstractGateway uses Symfony's request class to automatically pickup POST variables, amongst which are in this case, 'MD' and 'PaRes'.
In fact, it says so in the CompletePurchase class:
$md = $this->httpRequest->request->get('MD');
$paRes = $this->httpRequest->request->get('PaRes');
httpRequest is setup in AbstractGateway.
Basically, it just works.

Show billing and shipping information in Paypal Express using Omnipay

I am using Laravel with Omnipay for our ecommerce application. We direct the customers to Paypal to make their purchase. We require shipping and billing information prior to placing an order and we would like that information to continue to Paypal to make it easier for them. However, only the first name and last name are crossing over to Paypal correctly. We can also use email with no issues.
public function postPayment() {
//var_dump(Session::get('shipping_info')); die;
$info = Session::get('shipping_info');
$gateway = Omnipay::gateway('paypal');
//sandbox
$gateway->setUsername('xxxx');
$gateway->setPassword('xxxx');
$gateway->setSignature('xxx');
$gateway->setTestMode('true');
//production
// $gateway->setUsername('xxxx');
// $gateway->setPassword('xxxx');
// $gateway->setSignature('xxxx');
$cardInput = array(
'firstName' => $info['first_name_bill'],
'lastName' => $info['last_name_bill'],
'billingAddress1' => $info['street_address_1_bill'],
'billingAddress2' => $info['street_address_2_bill'],
'billingPhone' => $info['phone_bill'],
'billingCity' => $info['city_bill'],
'billingState' => $info['state_bill'],
'billingPostCode' => $info['zip_bill'],
'shippingAddress1' => $info['street_address_1_ship'],
'shippingAddress2' => $info['street_address_2_ship'],
'shippingPhone' => $info['phone_ship'],
'shippingCity' => $info['city_ship'],
'shippingState' => $info['state_ship'],
'shippingPostCode' => $info['zip_ship'],
);
$card = Omnipay::creditCard($cardInput);
// var_dump($card); die;
$response = Omnipay::purchase(
array(
'cancelUrl' => 'http://localhost/public/',
'returnUrl' => 'http://localhost/public/',
'amount' => Input::get('total'),
'currency' => 'USD',
'card' => $card,
'description' => 'Stuff'
)
)->send();
$response->redirect();
}
According to the docs https://github.com/omnipay/omnipay it should work with no issues. dumping the sessions reveals the correct billing and shipping parameters.
It was just needing a cache refresh.

Categories