How to find response after payment process complete in joomla virtuemart? - redirect

I am using virtuemart in joomla for ecommerce purpose. It's working fine. But after checkout from cart it redirect to paypal ( or other payment system). After completion of payment process, paypal again redirects to my website. It's working all stuff smoothly. But problem is that how to know that payment process is complete successfully or not from my website? Is virtuemart automatic does this or not ? if yes then, which file is responsible for this ?

It's not automatic, but it's also not hard (aside from VM's terrible documentation), here's a skeleton of the plugin you want to write:
<?php
defined('_JEXEC') or die('Restricted access');
if (!class_exists('vmCustomPlugin')){
require(JPATH_VM_PLUGINS . '/vmcustomplugin.php');
}
class plgVmcustomAfterOrderConfirmedHook extends vmCustomPlugin {
function plgVmConfirmedOrder($cart, $order){
$db = JFactory::getDBO();
$db->setQuery($db->getQuery(true)
->select('order_status')
->from('#__virtuemart_orders')
->where('virtuemart_order_id = '.intval($order['details']['BT']->virtuemart_order_id)));
if($db->loadResult() === 'C'){
blah();
}
}
}
?>

Related

PayPal Smart Payment Buttons integration with server-side REST API

I know there are a few questions regarding PayPal Integration but I'm trying to implement PayPal Express Checkout with Smart Buttons and REST API and no success.
What I want to do is:
Create a Payment Authorization (with payidand orderid)
Send this payid to the client (javascript) to be approved.
Redirect after payment to a confirmation page.
I have already created a Payment Authorization with the code bellow:
<?php
// 1. Autoload the SDK Package. This will include all the files and classes to your autoloader
// Used for composer based installation
require __DIR__ . '/PayPal-PHP-SDK/autoload.php';
// Use below for direct download installation
// require __DIR__ . '/PayPal-PHP-SDK/autoload.php';
// After Step 1
$apiContext = new \PayPal\Rest\ApiContext(
new \PayPal\Auth\OAuthTokenCredential(
'client id', // ClientID
'cliente secret' // ClientSecret
)
);
// After Step 2
$payer = new \PayPal\Api\Payer();
$payer->setPaymentMethod('paypal');
$amount = new \PayPal\Api\Amount();
$amount->setTotal('1.00');
$amount->setCurrency('USD');
$transaction = new \PayPal\Api\Transaction();
$transaction->setAmount($amount);
$redirectUrls = new \PayPal\Api\RedirectUrls();
$redirectUrls->setReturnUrl("https://example.com/your_redirect_url.html")
->setCancelUrl("https://example.com/your_cancel_url.html");
$payment = new \PayPal\Api\Payment();
$payment->setIntent('sale')
->setPayer($payer)
->setTransactions(array($transaction))
->setRedirectUrls($redirectUrls);
// After Step 3
try {
$payment->create($apiContext);
echo $payment;
echo "\n\nRedirect user to approval_url: " . $payment->getApprovalLink() . "\n";
echo $data= json_encode($payment->id, JSON_PRETTY_PRINT), "\n";
echo "</br>";echo "</br>";
echo $data= $payment->id;
}
catch (\PayPal\Exception\PayPalConnectionException $ex) {
// This will print the detailed information on the exception.
//REALLY HELPFUL FOR DEBUGGING
echo json_encode($ex->getData()->id, JSON_PRETTY_PRINT), "\n";
echo "</br>";echo "</br>";
echo $ex->getData()->id;
}
?>
My setup is as following (Please, correct if it's wrong):
User chooses the item and submits the form.
User is redirected to a new page with a new form and then fills the form with his name and other personal informations and then submits the form to be saved in the database and generate the Payment Authorization.
User should be redirected to a final page with Smart Buttons to complete the payment.
User should be redirected to a confirmation page, confirming his payment was successfully made.
The problem is that I'm stuck in the step 2 because once I generate the Payment Authorization, I don't know how to pass this id (and other required parameters) to the client, in this new page that is supposed to show the Smart Payment Buttons to complete the transaction.
I'm following along with the tutorial in PayPal documentation but I'm not able to understand.
The JavaScript makes calls to my server to get the payid, it works, but it generates a new payid and a new Payment Order, i want to use the one that was previously created when the user submitted the form and then, somehow, pass it to the final page with the Smart Buttons to complete the transaction and redirect to a confirmation page.
My Javascript:
<script>
paypal.Button.render({
onApprove: function(data) {
return fetch('/my-server/get-paypal-transaction', {
headers: {
'content-type': 'application/json'
},
body: JSON.stringify({
orderID: data.orderID
})
}).then(function(res) {
return res.json();
}).then(function(details) {
alert('Transaction approved by ' + details.payer_given_name);
}, '#paypal-button');
</script>
The problem is that it generates a new orderID, a new transaction, and I want to retrieve the transaction that was generated when the user submitted the form in the step 2 but I don't know what I should do.
Ultimately what I need is:
Get the Payment Authorization and pass it to the Client (final page with the buttons)
Redirect the users after payment complete.
You are looking for this front-end: https://developer.paypal.com/demo/checkout/#/pattern/server
For your backend, you should use the latest v2/orders SDK: https://github.com/paypal/Checkout-PHP-SDK
(Your v1/payments backend will work, but that SDK is deprecated and there is no reason to use it for a new integration)

Codenameone browser issues with paypal checkout express

So I've been trying to find an API to integrate PayPal Payment into my Codename One App, except that I didn't find enough documentation to use the Purchase builtin feature. So I tried to use a WebView of a page hosted on my server and implemented using the paypal "checkout.js" Api.
When I load the page into Chrome, it works perfectly and the transaction is complete. But when I load it using the codename one BrowserComponent it gets stuck (See screenshot). What is the root of this problem ? Is it the fact that the browser does not support popus ? and Is there a way to fix it ?
Button payButton = new Button("Checkout");
payButton.addActionListener((ActionEvent evt) -> {
Form payForm = new Form("Payment", new BorderLayout());
WebBrowser webBrowser = new WebBrowser("http://localhost/paymentserver/web/app_dev.php/payerParticipation/5");
payForm.add(BorderLayout.CENTER, webBrowser);
payForm.show();
});
Screenshot
Try embedding firebug into the of your page to see if it reports any errors:
<script>
if (!document.getElementById('FirebugLite')){E = document['createElement' + 'NS'] && document.documentElement.namespaceURI;E = E ? document'createElement' + 'NS' : document'createElement';E'setAttribute';E'setAttribute';E'setAttribute';(document'getElementsByTagName'[0] || document'getElementsByTagName'[0]).appendChild(E);E = new Image;E'setAttribute';}
</script>
Thanks for the help everybody,
I finally found a turnaround and implemented this feature on a PHP server using PayPal PHP SDK. I used the browser Navigation Callback in order to check when the payment was successful/failed.
browser.setNavigationCallback((url)->{
if (url.indexOf("success=true")!=-1){
System.out.println("Payment complete");
}
else if (url.indexOf("success=false")!=-1){
System.out.println("Payment failed");
}
return true;
});
I don't have an answer for that but I did implement Braintree support for Codename One which is the official PayPal mobile API. I have a cn1lib for it implemented but I didn't get around to publishing it because of the bootcamp. Keep an eye on the blog I'll probably publish it in the next couple of weeks.

PayPal SDK: No Server Response when Paying with PayPal Account

I have scoured the docs and this tutorial about 100 times but can't figure out how to go through the payment process using a PayPal account as opposed to a credit card. I have gotten the credit card payment to go through just fine.
In the aforementioned tutorial, it is stated that I am supposed to expect a JSON response from the server after making an OAuth credential:
$sdkConfig = array(
"mode" => "sandbox"
);
$cred = new OAuthTokenCredential("clientID","clientSecret", $sdkConfig);
I get absolutely no server response despite geting a '200 OK' status from the server.
Initially I had my code set up like a bunch of other tutorials:
$apiContext = new ApiContext(
new OAuthTokenCredential(
'clientID', // ClientID
'clientSecret' // ClientSecret
)
);
$payer = new Payer();
$payer->setPaymentMethod('paypal');
$item1 = new Item();
$item1->setName("Donation squares.");
$item1->setCurrency('USD');
$item1->setQuantity(1);
$item1->setPrice(1);
$itemList = new ItemList();
$itemList->setItems(array($item1));
$amountDetails = new Details();
$amountDetails->setSubtotal('7.41');
$amountDetails->setTax('0.03');
$amountDetails->setShipping('0.03');
$amount = new Amount();
$amount->setCurrency('USD');
$amount->setTotal('7.47');
$amount->setDetails($amountDetails);
$transaction = new Transaction();
$transaction->setAmount($amount);
$transaction->setDescription('This is the payment transaction description.');
$redirectUrls = new RedirectUrls();
$redirectUrls->setReturnUrl("https://devtools-paypal.com/guide/pay_paypal/php?success=true");
$redirectUrls->setCancelUrl("https://devtools-paypal.com/guide/pay_paypal/php?cancel=true");
$payment = new Payment();
$payment->setIntent('sale');
$payment->setPayer($payer);
$payment->setRedirectUrls($redirectUrls);
$payment->setTransactions(array($transaction));
try{
$payment->create($apiContext);
} catch(Exception $e){
echo $e
exit(1);
}
None of this works either - no response from the server whatsoever.
ANSWER / COMMENT
You're not supposed to be looking for a JSON response after all. If the payment is successfully created, an approval URL should be generated by running
$payment->getApprovalLink();
The user then follows this link to finalize his/her payment.
You might be interested in following a very simple instruction here at PayPal-PHP-SDK, that explains how to make calls using PayPal PHP SDK. I know you have already gone through that, and are looking for how to create a payment using PayPal.
I am not sure you are aware of this, but PayPal-PHP-SDK comes along with a lot of samples, that you could run by just one simple command (if you have PHP 5.4 or higher). One of the first sample have the instructions and code to make PayPal Call.
There are two steps involved in that.
Create a Payment. Receive a approval_url link to be used to ask the user to complete Paypal flow over any browser.
Once the user accepts the payment on paypal website, it will be redirected back to your website, where you execute the payment.
Both the code samples are provided here and here.
Let me know if this helps, and you have any more questions. I would be more than happy to help.

PayPal Adaptive Payments: two payments from one sender in two browser tabs

I use PayPal Adaptive Payments (parallel) on my website and I've encountered a strange problem with two payments in two different browser tabs from the same sender. The similar question was asked before, but nobody answered there.
The scenario which reproduces the problem
The user opens the first browser tab of the website and starts a payment process to the first seller.
PayPal's lightbox with Login button appears.
The user opens the second browser tab of the website and starts a payment process to the second seller.
Again, PyaPal's lightbox with Login button appears.
The user returns to the first browser tab and login to PayPal.
After login to PayPal in the first browser tab the user sees payment details to the second seller.
After login to PayPal in the second browser tab the user sees payment details to the second seller.
It seems that PayPal Adaptive Payments support only one transaction from one sender.
How it works
The website works with Ruby on Rails and I use paypal_adaptive gem for payments with PayPal. The payment flow is quite simple:
The user clicks on Buy button on the website. The client makes AJAX request which handled by payment controller in Ruby on Rails.
In the controller the app makes Pay request to PayPal API using paypal_adaptive gem and receives a PayKey (see the code below).
The server responds to the client with the PayKey and the client uses it in PayPal form to start payment process through PayPal's lightbox (see the code below).
That's it. After that I do not control anything (the payment process goes through PayPal's external webpage).
Additional notes
I'm sure that the data for Pay request is different on the server side in the test scenario listed above.
I've tried different PayPal's dialog options besides PayPal's lightbox: mini-browser and popup. These options doesn't affect on this bug and it is still reproducable.
The client code
<script src="https://www.paypalobjects.com/js/external/dg.js" type="text/javascript"></script>
<form action="https://www.sandbox.paypal.com/webapps/adaptivepayment/flow/pay" class="paypal-hidden-form" target="PPDGFrame">
<button id="paypal-submit"></button>
<input id="type" type="hidden" name="expType" value="light">
<!-- Insert PayKey here and click on the form's submit button using jQuery after server's response. -->
<input id="paypal-key" type="hidden" name="paykey" value="">
</form>
<!-- Paypal -->
<script type="text/javascript" charset="utf-8">
var dgFlow = new PAYPAL.apps.DGFlow({ trigger: "paypal-submit", expType: "light" });
function MyEmbeddedFlow(embeddedFlow) {
this.embeddedPPObj = embeddedFlow;
this.paymentSuccess = function(paymentStatus) {
this.embeddedPPObj.closeFlow();
// More UI code here...
};
this.paymentCanceled = function() {
this.embeddedPPObj.closeFlow();
// More UI code here...
};
}
var myEmbeddedPaymentFlow = new MyEmbeddedFlow(dgFlow);
</script>
The server code
# Make a Pay request to PayPal API.
paypal_payment_thread = Thread.new do
# Some preparation code goes here...
pay_request = PaypalAdaptive::Request.new
process_guid = SecureRandom.uuid
# Construct Pay API request data.
data = {
:returnUrl => "#{PAYPAL_RETURN_URL}?process_guid=#{process_guid}",
:cancelUrl => "#{PAYPAL_CANCEL_URL}?process_guid=#{process_guid}",
:requestEnvelope => {
:errorLanguage => "en_US"
},
:currencyCode => "USD",
:receiverList => {
:receiver => [{
# seller_paypal value is different for two payments.
# But in fact we do the last payment for both payments.
:email => seller_paypal,
:amount => ORDER_SELLER_AMOUNT,
:paymentType => "DIGITALGOODS"
}, {
:email => PAYPAL_MARKETPLACE_EMAIL,
:amount => ORDER_MARKETPLACE_AMOUNT,
:paymentType => "DIGITALGOODS"
}]
},
:actionType => "PAY",
:ipnNotificationUrl => PAYPAL_NOTIFY_URL,
:reverseAllParallelPaymentsOnError => "true",
:trackingId => process_guid
}
# Make a Pay API request.
pay_response = pay_request.pay(data)
if pay_response.success?
# Everything is ok. Update database here...
else
raise Exceptions::PaypalPaymentError
end
end
I've removed some unimportant code just to be clear, how it really works.
Thanks in advance for the help!
Looks like it is by design. I've tried the same test here on the website of one of PayPal's employees and it is reproducible there.
PayPal's support answered me that the problem in using Lightbox. However I've tried Mini-Browser and Popup options as I described in my post without no effect.
Also, PayPal's support answered me that this is by design and adviced me to contact with Technical Support. Maybe it will be useful for someone else.
Hi Michael, Thanks, yes I was able to reproduce it as well. However
it’s important to understand that PayPal is not made for handling 2
payment flows at the same time. If you want to get further on that,
you can contact our Technical Support : https://ppmts.custhelp.com/
They have other tools to debug and may be able to give you a better
understanding of the technical problem.
Finally I've blocked simultaneous payments using a special flag in HTML5 Local Storage and dgFlow.isOpen() method of PAYPAL.apps.DGFlow object to detect PayPal window. On window close I reset this flag using onunload and onbeforeunload events of window.
I close this question. Thanks.

Paypal IPN listener issue

I currently have a problem with my Paypal IPN listener and have been receiving the following email from paypal each day:
"Please check your server that handles PayPal Instant Payment Notifications (IPN). IPNs sent to the following URL(s) are failing:
http://www.mysales.ie/create_promo_listener.php"
I have a demo site which enables users to create ads and works perfectly (no problems with IPN), however the proper site that I am developing has this issue (It is on a different host).
I have contacted the host provider and they have said it is not an issue on their side. I have tried php error logs but cant find any issues. I have the exact same code on both sites so I cant understand what the problem is.
<?php include 'ipn_handler.class.php';
/**
* Logs IPN messages to a file.
*/
class Logging_Ipn_Handler extends IPN_Handler
{
public function process(array $post_data)
{
$data = parent::process($post_data);
if($data === FALSE)
{
header('HTTP/1.0 400 Bad Request', true, 400);
exit;
}
$random_number = $_POST['custom'];
file_put_contents( 'logs/listenerTest.txt', "listener = " . $random_number, FILE_APPEND);
header("location:create_promo_creator.php?random_number=" . $random_number);
}
}
date_default_timezone_set('Europe/Oslo');
$handler = new Logging_Ipn_Handler();
$handler->process($_POST);
I have been trying to find the root of the problem for a long time but cant figure it out.
Seems that your $data = parent::process($post_data);
method is returning FALSE.
Do you have any logging instrumentation in your code to verify this?
The easy workaround is to return a 200 response to keep PayPal's IPN system happy, and to log the error for further review.