Both of the above answers are correct. However, PayPal tech support provided a more thorough set of instructions which I've provided below. Hopefully they'll help someone else.
Modify your SetExpressCheckout calls so that the RETURNURL and CANCELURL parameters point to a special return page that will handle closing the pop-up window for you and continuing the normal checkout process (more on this later).
Next, modify the script that redirects the buyer over to the PayPal website. Normally, this script would return a “302 Found” (or similar) response to the browser, telling the browser that it should follow a redirect to some other page. (In PHP, this is usually accomplished with the “header” function – e.g., header(“Location: https://www.paypal.com/cgi-bin/webscr?cmd=_express-checkout&token=$token”);
.) Instead, this script should emit the following HTML/JavaScript code (replacing “TOKEN” with the token you received from PayPal). This will open a pop-up window where the buyer can continue the checkout process on PayPal. You can insert additional text, as you like, to indicate to the buyer that they should be using the pop-up window to complete their checkout. To avoid issues with pop-up blockers, you can create a link or button on your page, indicating to the buyer that they should click the link/button to continue, and use this code for the object’s “onClick” handler.
<script type="text/javascript">
window.open("https://www.paypal.com/cgi-bin/webscr?cmd=_express-checkout&token=TOKEN","_blank","width=1024,height=768,location=1,resizable=1,scrollbars=1,status=1",true);
</script>
Now, create a new page that executes the following code (or similar – this code is based on PHP, adjust as necessary for whatever language you are using). This code will close the pop-up window and continue the checkout process in your existing iframe. The RETURNURL parameter of your SetExpressCheckout call should point to this page. Replace “paypalreturn.php” with the script you currently use to handle buyers returning to your shopping cart from PayPal.
<html>
<body>
<script type="text/javascript">
window.opener.location="http://www.regattacentral.com/paypalreturn.php?token=<? echo $_REQUEST["token"]; ?>&PayerID=<? echo $_REQUEST["PayerID"]; ?>";
window.close();
</script>
</body>
</html>
Lastly, repeat this step for your CANCELURL handler.
• The purchase completes inside of the iframe, and the transaction ID for the purchase is shown.