Im integrating Paypal Adaptive Payment API for a mobile website.
But when Im submitting payment to
https://www.paypal.com/webscr?cmd=_ap-payment&paykey=value
( For Sandbox : https://www.sandbox.paypal.com/cgi-bin/webscr )
Its always redirecting to Paypal Main Web. Not to Paypal Mobile website.
How to redirect client to paypal mobile web?
Try redirecting your site to
https://www.sandbox.paypal.com/webapps/adaptivepayment/flow/pay?paykey=AP-XYZ&expType=mini
Fill your pay key in place of AP-XYZ
Let me know if it works.
The best approach I found was mini browser experience. But I had a variety of different issues on mobile devices implementing it (which is what it was meant for in the first place). You will see many similar questions about adaptive payments and all sorts of issues with using lightbox and mini browser experience.
But FINALLY... I have figured it out after hours upon hours, days upon days! This should solve everyone's problems of all different varieties when it comes to issues with PayPal Adaptive Payments and the issues with:
The default redirected paypal page is NOT mobile responsive and looks horrible on mobile devices.
The lightbox gets "hung up" and does not close on some mobile devices.
The mini browser doesn't close after completing payment or cancelling.
The mini browser doesn't redirect to the callBackFunction from paypal apdg.js script.
Not redirecting to returnUrl and cancelUrl after payment completion (or when cancelling)
Chrome for ios (iphones) doesn't initiate the callbackfunction and therefore after payment completion or cancellation, it just keeps you at the page you launched the paypal payment page from which prevents you from validating success or failure of payment.
Drum roll please.... here it is!! This replaces any need for PayPal javascript files etc. All you need is what is below along with your own method of obtaining the PayKey to add to the redirect url. My live website, with adaptive payments working correctly using below code, is https://www.trackabill.com.
<div>
<?php $payUrl = 'https://www.paypal.com/webapps/adaptivepayment/flow/pay?expType=mini&paykey=' . $payKey ?>
<button onclick="loadPayPalPage('<?php echo $payUrl; ?>')" title="Pay online with PayPal">PayPal</button>
</div>
<script>
function loadPayPalPage(paypalURL)
{
var ua = navigator.userAgent;
var pollingInterval = 0;
var win;
// mobile device
if (ua.match(/iPhone|iPod|Android|Blackberry.*WebKit/i)) {
//VERY IMPORTANT - You must use '_blank' and NOT name the window if you want it to work with chrome ios on iphone
//See this bug report from google explaining the issue: https://code.google.com/p/chromium/issues/detail?id=136610
win = window.open(paypalURL,'_blank');
pollingInterval = setInterval(function() {
if (win && win.closed) {
clearInterval(pollingInterval);
returnFromPayPal();
}
} , 1000);
}
else
{
//Desktop device
var width = 400,
height = 550,
left,
top;
if (window.outerWidth) {
left = Math.round((window.outerWidth - width) / 2) + window.screenX;
top = Math.round((window.outerHeight - height) / 2) + window.screenY;
} else if (window.screen.width) {
left = Math.round((window.screen.width - width) / 2);
top = Math.round((window.screen.height - height) / 2);
}
//VERY IMPORTANT - You must use '_blank' and NOT name the window if you want it to work with chrome ios on iphone
//See this bug report from google explaining the issue: https://code.google.com/p/chromium/issues/detail?id=136610
win = window.open(paypalURL,'_blank','top=' + top + ', left=' + left + ', width=' + width + ', height=' + height + ', location=0, status=0, toolbar=0, menubar=0, resizable=0, scrollbars=1');
pollingInterval = setInterval(function() {
if (win && win.closed) {
clearInterval(pollingInterval);
returnFromPayPal();
}
} , 1000);
}
}
var returnFromPayPal = function()
{
location.replace("www.yourdomain.com/paypalStatusCheck.php");
// Here you would need to pass on the payKey to your server side handle (use session variable) to call the PaymentDetails API to make sure Payment has been successful
// based on the payment status- redirect to your success or cancel/failed page
}
</script>
There is actually a simple solution to this that isn't documented anywhere. We were in discussion with PayPal about adding it a while back so I am wondering if it eventually got implemented.
Anyway, simply just redirect the user to the following URL and they will be redirected back to your site on completion:
https://www.sandbox.paypal.com/webapps/adaptivepayment/flow/preapproval?preapprovalKey=PA-XXXXX&expType=redirect
The difference here is using expType=redirect rather that expType=mini. I'm not sure when this was added but after a bit of reverse engineering and some experimenting we have a surprisingly simple solution.
that's right - the Adaptive Payments UI is not Mobile optimized. But the closest to that it offers is what we call the MiniBrowser experience. You can try and see if that serves your needs. You can find the how-to guide here on X.com: Implementing the Mini-Browser Option
Related
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.
I've implemented Website Payments Pro Hosted on my website. I can pay using the PayPal log in and it gives me the link to return to my store which is fine as I then display my order confirmation page to the user.
When the user decides to pay via credit card:
They are then redirected to a confirmation page I don't seem to have any control over:
What I've tried:
Setting auto return on in my preferences and setting a return url (both via the Profile and in my initial API call when generating the button.
Changing the Web Payments Pro confirmation page setting to On my sites confirmation page.
When the payment is taken via credit card, I'd like to redirect the user to my actual payment confirmation page. Is this possible?
It turns out that showHostedThankyouPage=true was causing this issue.
I am using the .NET button API to generate the request for the iFrame like so:
var service = new PayPalAPIInterfaceServiceService(GetConfig(request));
var createButtonResponse = service.BMCreateButton(new BMCreateButtonReq
{
BMCreateButtonRequest = new BMCreateButtonRequestType
{
ButtonType = ButtonTypeType.PAYMENT,
ButtonCode = ButtonCodeType.TOKEN,
ButtonCountry = countryCodeType,
ButtonVar = new List<string>
{
String.Format("subtotal={0}", _salesOrderPriceService.GetGrossTotal(request.Order)),
String.Format("notify_url={0}", request.NotifyUrl),
String.Format("return={0}", request.ReturnUrl),
String.Format("invoice={0}", request.Order.Id),
String.Format("currency_code={0}", request.Order.Currency.Code),
String.Format("cancel_return={0}", request.CancelReturnUrl),
"billing_first_name=test",
"billing_last_name=tset",
"billing_address1=test",
"billing_city=test",
"billing_state=tes",
"billing_zip=test",
"billing_country=GB",
"template=templateD",
"paymentaction=sale",
"business=tset"
}
}
});
I had showHostedThankyouPage=true included in the name value pairs which was causing the issue. Removing it sorted it out.
I'm trying to get PayPal's chained payments working in their sandbox env. but whenever I click on "Pay" at the very last stage after signing in I always get redirected to a page with the generic error message "Your payment can't be completed. Please return to the participating website and try again."
I've tried doing both chained and parallel payments with the same results.
I've also followed a few suggestions from around the web which inc tweaking the merchant account settings making sure certain fields were unchecked under the "blocked" options. As well checking currency and country code. Initially country code was en_GB and currency GBP, that didn't work I tried doing en_US with USD but in all cases I get the same message.
I've also tried adding an IPN url on the off chance PayPal would post some error code/message to it but got nadda! If you click "Return to test store" it goes to the cancel URL without any POST/GET parameters.
I'm using their PHP SDK from http://paypal.github.io/#adaptive-payments-tab-php-5-3
So the question, does anyone have any suggestion as to how I can find out what exactly is going wrong or other things I can try to fix it?
I had this problem in the sandbox environment because I was not including an application ID. I used APP-80W284485P519543T which one of examples indicated as the Sandbox Application ID, and then it worked.
Mobile Payments Library Developer Guide and Reference
–
Android OS
Edition
Oct 2016
5
Preface
**Important:
The Mobile Payments Library is based on the PayPal Adaptive Payments API.
As of October 6, 2016, Adaptive Payments is now a limited releas
e product. It is restricted to
select partners for approved use cases and should not be used for new integrations without guidance from PayPal**
=============================================
first implement method
private void initLibrary() {
PayPal pp = PayPal.getInstance();
if(pp == null) {
pp = PayPal.initWithAppID(this, PAYPAL_APP_ID, PayPal.ENV_SANDBOX);
pp.setLanguage("en_US"); // Sets the language for the library.
pp.setFeesPayer(PayPal.FEEPAYER_EACHRECEIVER);
// pp.setShippingEnabled(true);
pp.setDynamicAmountCalculationEnabled(false);
}
}
**paypal button click event code**
double secondary_payment = 0;
double primary_payment = 0;
PayPalAdvancedPayment advPayment = makeChainedPayment(secondary_payment,primary_payment,"primary_email","secondary_email");
Intent checkoutIntent = PayPal.getInstance().checkout(advPayment, your_current_activity);
startActivityForResult(checkoutIntent, 1);
=============================================
private PayPalAdvancedPayment makeChainedPayment(double priceSecondary, double pricePrimary, String primary_email, String secondary_email) {
PayPalAdvancedPayment payment = new PayPalAdvancedPayment();
payment.setCurrencyType("USD");
// payment.setMerchantName("PushND");
BigDecimal bigDecimalPrimary=new BigDecimal(pricePrimary);
PayPalReceiverDetails receiverPrimary = new PayPalReceiverDetails();
receiverPrimary.setRecipient(primary_email);
//receiverPrimary.setRecipient("adaptive_receiver_1#pushnd.com");
receiverPrimary.setSubtotal(bigDecimalPrimary);
receiverPrimary.setIsPrimary(true);
payment.getReceivers().add(receiverPrimary);
PayPalReceiverDetails receiverSecondary= new PayPalReceiverDetails();
receiverSecondary.setRecipient(secondary_email);
BigDecimal bigDecimalSecond=new BigDecimal(priceSecondary);
receiverSecondary.setSubtotal(bigDecimalSecond);
payment.getReceivers().add(receiverSecondary);
return payment;
}
Is it possible to launch the payflow entirely inline (a la Express Checkout)? How?
We're using chained payments and everything works on non-iOS-mobile devices (and in Chrome for iOS), but we're making a web app, so we need this to work on phones. Testing on the iPhone, we have this problem with PayPal's code that I've already asked about, as well as the fact that when I get around that bug by doing a location.replace with the URL to PayPal (or loading it in a lightbox of my own design), iOS and mobile Safari kill the "Log In" popup (without giving the user an opportunity to view it if they so choose).
In short, is there any way I can use Adaptive Payments without ridiculous 1990s-era popups???
Here's what I'm doing to use PayPal's mobile web flow. I'm testing on Android and it's working well. The only hang up is the callbackFunction is not firing in mobile browsers and works fine in desktop browsers. (I'm still working on this part. Let me know if you solve it.) Here's an example on how to do it using expType=mini to launch the PayPal mini browser experience.
First include the Javascript for the Mini flow:
<script src="http://www.paypalobjects.com/js/external/apdg.js"></script>
Then a link to launch the redirect:
<a id="payPalRedirect" href="https://www.sandbox.paypal.com/webapps/adaptivepayment/flow/pay?paykey={paykey}&expType=mini" target="_blank">Complete PayPal Payment</a>
<br /><br />
<div id="resultDiv"></div>
And some Javascript to initiate the Mini Flow process and the callbackFunction:
var returnFromPayPal = function () {
alert("Returned from PayPal");
var div = document.getElementById('resultDiv');
div.innerHTML = "Returned from PayPal!";
// Here you would need to pass on the payKey to your server side handle to call the PaymentDetails API to make sure Payment has been successful or not
// based on the payment status- redirect to your success or cancel/failed urls
}
var dgFlowMini = new PAYPAL.apps.DGFlowMini({ trigger: 'payPalRedirect', expType: 'mini', callbackFunction: 'returnFromPayPal' });
More insights and solution options to this issue can be found here:
Paypal Embedded Flow not using returnUrl or cancelUrl
I'm using Paypal Digital Goods, it is good until now. When user click on button, it open a floating box with paypal iframe.
The problem is I don't want using floating box anymore. I stop using paypal javascript. After call a request to paypal
$nvps["METHOD"] = "SetExpressCheckout";
$nvps["RETURNURL"] = $this->configs['return_url'];
$nvps["CANCELURL"] = $this->configs['cancel_url'];
$nvps["PAYMENTREQUEST_0_PAYMENTACTION"] = "Sale";
$nvps["PAYMENTREQUEST_0_NOTIFYURL"] = $this->configs['listener_url'];
$nvps["PAYMENTREQUEST_0_AMT"] = $item['price'];
$nvps["PAYMENTREQUEST_0_CURRENCYCODE"] = $item['currency'];
$nvps["PAYMENTREQUEST_0_ITEMAMT"] = $item['price'];
$nvps["L_PAYMENTREQUEST_0_NAME0"] = $item['desc'];
$nvps["L_PAYMENTREQUEST_0_NUMBER0"] = $item_number;
$nvps["L_PAYMENTREQUEST_0_AMT0"] = $item['price'];
$nvps["L_PAYMENTREQUEST_0_QTY0"] = "1";
$nvps["L_PAYMENTREQUEST_0_ITEMCATEGORY0"] = "Digital";
I redirect to "https://www.sandbox.paypal.com/incontext?token=" with a token from request above. The style of page is still like a floating box. If user click on login button, it still open a mini browser (popup) and I don't want like this. Any suggestion?
Simply stop loading the dg.js fil and change the PayPal redirection URL from https://www.paypal.com/incontext?token= to https://www.paypal.com/cgi-bin/webscr?cmd=_express-checkout&token=
This will make it the regular Express Checkout checkout experience.
I suspect you are still including the Paypal dg.js file. Remove the following line from your page and the Paypal iFrame will no longer appear.
<script src='https://www.paypalobjects.com/js/external/dg.js' type='text/javascript'></script>