We currently use both Payflow Pro recurrning billing for credit cards, and use Paypal Subscriptions for paypal processing in a custom site, but are moving to Drupal. I have been researching for the last week to try find a way to get the 2 to play nice, and the only way I can see is if this module is fixed to either accept paypal express checkout as well, or drop the currently implimented express checkout code that is conflicting with the normal paypal module.

Obviously, from a management standpoint, it seems that if this module managed both types of subscriptions, it would be easier to administer. The API's for Payflow pro, and paypal are somewhat similar, as are the return values (NVP).

Thoughts? I have a lot of experience with Payflow Pro, and Paypal subscriptions, just not a lot with PHP/Drupal module development. I would be happy to try assist as much as I can.

Comments

kwinters’s picture

I suspect the current Express Checkout code in this module is close to right, so that's where I would concentrate if it would meet your needs.

Eventually I also want to move the EC code out to its own submodule, which would avoid the conflict issues.

Does that answer your question?

jantoine’s picture

I too am after this functionality. I will submit a patch in the next hour or so that will separate the PayPal Express code out into its own sub-module. Once that initial patch is committed, I will proceed to submit bug-fix and code-cleanup (per http://drupal.org/coding-standards) patches.

Kwinters, I would be happy to join this project as a co-maintainer if you're interested as I have several clients using this service.

Cheers,

Antoine

noloco’s picture

Sounds great. I have been going through a bit of the code for the express checkout section. First thing I noticed is that its not asking for any kind of email address / paypal creditials to setup a payment.

kwinters’s picture

Antoine: Sure, I could use the help (busy busy). Check out the 6.x-2.x branch for my ideas on how to split it up. Send me a contact re: CVS access and we can work out the details.

Noloco: I think Express Checkout is supposed to tie directly into your PFP account and deposit the money there. I'm not entirely sure about it though.

noloco’s picture

Kwinters: Actually no, Express Checkout ties in directly to Website Payment Standard (WPS) and Website Payment Pro (WPP). Payflow pro is a totally separate interface/system.

In order for Express checkout to work correctly, it would require its own set of API credentials, API url, sandbox, etc. The name value pairs are similar to Payflow Pro, but not the same. As a submodule, this should be a good route to go, since the products/profiles/schedules section of the Payflow Pro Recurring Settings would completely apply to Paypal subscriptions the same as they would for Payflow pro. It would just require a different set of variables to get pass/collect the correct data.

noloco’s picture

Unless they recently added support for Express Checkout into Payflow, I will do some research...

Edit: OK, it looks like they do allow you to process Express Checkout via Payflow Pro now, been too long since I have worked on the code ;)

Here is the documentation, in case anyone needs it: https://cms.paypal.com/cms_content/US/en_US/files/developer/PFP_ExpressC...

jantoine’s picture

Status: Active » Needs review

Attached is a patch that moves the Express Checkout code into its own sub-module. This patch is a direct backport from the 2.x branch. I did not add an update hook to automatically enable the new sub-module because it is my understanding that this code has never been used because it doesn't work. Please correct me if I am wrong and point me to what I can use to detect if the user is currently using this portion of the code. I will then re-roll the patch with an update hook.

Cheers,

Antoine

jantoine’s picture

StatusFileSize
new50.1 KB

And here is the patch!

Cheers,

Antoine

noloco’s picture

AntoineSolutions: Nice work, I will begin testing this right away.

Going back to Payflow/Express Checkout intergration, it appears that payflow does accept it, however I am not sure how the management works, etc.

In either case, it does not help me, as I have many clients setup in a separate paypal account for Express Checkout. So hopefully we can modify the code to support both integrated into payflow, and separate Paypal profiles.

kwinters: You have been talking about the 6.x-2.x branch as using the uc_recurring module. So in this branch, does the uc_recurring module handle the setup of terms, price, start date, end date, etc. instead of uc_payflowpro? If this is the case, wouldn't pulling the express checkout out of the payflowpro module allow for using the paypal module to manage express checkout, and payflowpro module to manage PFP charges?

Thanks.

noloco’s picture

Antoine: The patch appears to work flawlessly, however, if you go to Store Admin > Configuration > Payment Settings > Edit > Payment gateways >PayflowPro Settings, I still have Express Checkout settings at the bottom. Are you seeing the same thing?

Thanks.

jantoine’s picture

StatusFileSize
new52.13 KB

noloco,

Looks like I missed the form settings. Attached is a new patch that also removes the Express Checkout form settings from the uc_payflowpro module. Also, if you could update the status after you test a patch, it would help the module maintainers ;)

kwinters,

In the 6.x-2.x branch there are also some recurring form settings removed from the main module and put into the Express Checkout module. I'm not sure if those were specific to trying to use the uc_recurring project and should still be moved over to the new Express Checkout sub-module. Your input would be appreciated.

Cheers,

Antoine

noloco’s picture

Status: Needs review » Reviewed & tested by the community

Antoine: The new patch appears to work perfectly.

kwinters’s picture

Oh boy, lots of stuff going on here.

Re: upgrade path - The Express checkout may have worked in D5, but I'm pretty certain it has never worked in D6. I wouldn't write an upgrade path unless someone actually needs it. There are only a handful of D5 installs in the wild anyway.

2.x branch - The uc_recurring module mainly just acts as a bridge between the PFP recurring API code (not PayPal) with ubercart core, eliminating some code from the module and allowing better integration with other recurring logic via standardization and hooks. The uc_recurring code is in a separate submodule in 2.x, so using any other module for recurring would be possible. As for Express Checkout and recurring, any of that would be specific to the PFP EC sub-module or potentially the PayPal module (but I think yours is an unusual case).

2.x settings - which settings are you talking about, specifically? Anything that ended up in the EC submodule could have been an accident, since I was basically just getting that code out of the way. I don't remember *adding* any settings for uc_recurring, but that was a while ago and I could be mistaken.

jantoine’s picture

kwinters,

This code is found in the uc_payflowpro_settings_form() function in the uc_payflowpro.module file.

  $form['payflowpro_settings']['recurring'] = array(
    '#type' => 'fieldset',
    '#title' => t('Recurring Settings'),
    '#description' => t('Settings specific to recurring profiles.'),
    '#collapsible' => TRUE,
    '#collapsied' => TRUE,
  );
  $form['payflowpro_settings']['recurring']['uc_payflowpro_enable_recurring'] = array(
    '#type' => 'checkbox',
    '#title' => t('Enable recurring products'),
    '#default_value' => variable_get('uc_payflowpro_enable_recurring', FALSE),
    '#description' => t('Checking this box will enabled recurring profiles on
                        products that have an expiration.'),
  );
  $form['payflowpro_settings']['recurring']['uc_payflowpro_recurring_create_order'] = array(
    '#type' => 'checkbox',
    '#title' => t('Successful recurring payments should create a duplicate order'),
    '#default_value' => variable_get('uc_payflowpro_recurring_create_order', FALSE),
    '#description' => t('If this box is unchecked, the original order will be updated instead.'),
  );
  $form['payflowpro_settings']['recurring']['uc_payflowpro_recurring_site_key'] = array(
    '#type' => 'textfield',
    '#title' => t('Site key'),
    '#description' => t('The site key is used to namespace your site from other
                        sites. This should be short, all letters or numbers or both,
                        e.g. mysite, or prodsite, etc.'),
    '#default_value' => variable_get('uc_payflowpro_recurring_site_key', ''),
  );

The above code no longer exists in the uc_payflowpro module in the 2.x branch. However, this code is found in the uc_payflowpro_ec_form_uc_payment_gateways_form_alter() function in the uc_payflowpro_ec.module file in the 2.x branch (it is commented out as if it was still under heavy development).

  /*$fields = array(
    '#type' => 'fieldset',
    '#title' => t('Recurring Settings'),
    '#description' => t('Settings specific to recurring profiles.'),
    '#collapsible' => TRUE,
    '#collapsied' => TRUE,
  );
  // TODO: remove this option? also change in uninstall / update hooks
  $fields['uc_payflowpro_recurring_create_order'] = array(
    '#type' => 'checkbox',
    '#title' => t('Successful recurring payments should create a duplicate order'),
    '#default_value' => variable_get('uc_payflowpro_recurring_create_order', FALSE),
    '#description' => t('If this box is unchecked, the original order will be updated instead.'),
  );
  $fields['uc_payflowpro_recurring_site_key'] = array(
    '#type' => 'textfield',
    '#title' => t('Site key'),
    '#description' => t('The site key is used to namespace your site from other
                        sites. This should be short, all letters or numbers or both,
                        e.g. mysite, or prodsite, etc.'),
    '#default_value' => variable_get('uc_payflowpro_recurring_site_key', ''),
  );

  $form['gateways']['payflowpro']['payflowpro_settings']['recurring'] = $fields;*/

I wasn't sure if this code was accidentally copied over, if it was necessary for integrating with the uc_recurring module, or if it is required for recurring to work at all? Any insight is helpful. If you are unsure, I'll begin digging deeper tomorrow.

Cheers,

Antoine

kwinters’s picture

uc_payflowpro_recurring_create_order and uc_payflowpro_recurring_site_key were moved to the _recurring submodule (function uc_payflowpro_recurring_form_uc_payment_gateways_form_alter). uc_payflowpro_enable_recurring was no longer needed, as it's implied by the module being enabled.

None of them should be in the EC module. Even if EC ends up with its own recurring logic, the setting keys should probably still be changed.

jantoine’s picture

kwinters,

OK... So #14 is a non-issue since the patch leaves the original code in the main module and does not add it to the new PFP EC sub-module. Please let me know if there are any other concerns with the patch of if you think this is RTCB.

Cheers,

Antoine

noloco’s picture

Kwinters:

I just wanted to clarify a bit as to where you are heading with the 2.x branch. The new branch would integrate with this module http://drupal.org/project/uc_recurring, correct? Basically, defining the recurring schedule, payment, etc would be done in the recurring module, not in the uc_payflowpro module. Or am I misunderstanding?

kwinters’s picture

re: #17 - That is the correct recurring module, which provides the interface for adding recurring features to products, etc. All of the credit card actions still pass through the PFP recurring API though: initial setup, the periodic charges, recurring cancellation, etc.

The uc_recurring module doesn't really add any new features, just offloads things that the module already did. However, this should make it more useful with uc_roles, etc. since it's a standard.

re: #16 - The patch looks mostly fine. I want to follow up on a few things in detail, mostly uninstall related.

kwinters’s picture

Title: Play nice with Paypal subscriptions » Express Checkout Feature Addition
Status: Reviewed & tested by the community » Needs work

I renamed the issue, since it became more about EC than anything.

This seems like an accident (it was copied to the new location as-is):

$order->billing_street1 = $response->PayPalResult->EMail;
jantoine’s picture

Status: Needs work » Needs review
StatusFileSize
new67.86 KB

The original Express Checkout code was copied from either the 5.x-1.x or the 6.x-1.x uc_paypal module and is greatly outdated. I have completely rewritten the Express Checkout code copying the latest code from the uc_paypal module and making the necessary changes to work with the PayFlow Pro gateway per the developers documentation linked comment #6. Patch attached.

Note: This patch was generated from the GIT repository below because trying to generate patches that include adding new folders/files is near impossible with CVS.

Cheers,

Antoine

kwinters’s picture

Assigned: Unassigned » jantoine

AntoineSolutions, please run through all the changes and check for XSS issues, then commit. It will need a CHANGELOG entry, too.

This is the section I noticed, but there may be others: $order->billing_street1 = $response['STREET'];

jantoine’s picture

StatusFileSize
new68.33 KB

Hey kwinters,

I have attached a new patch.

After reviewing the documentation listed below, I believe I have been incorrectly using check_plain(). The check_plain() function should only be used on user submitted data when outputting, not when saving, and only in circumstances where Drupal is not already performing the check for us. Please review the documentation listed below and my changes to the patch and let me know if you concur with my findings.

http://drupal.org/writing-secure-code
http://drupal.org/node/101495
http://drupal.org/node/28984

Cheers,

Antoine

blg@bgreenaway.com’s picture

subscribing - intending to deploy PayPal Express and Pay Flow Pro with no recurring (for now...) and will be testing last patch

Nate_P’s picture

Just tested this with Paypal Sandbox accounts using PayPal Express and Pay Flow Pro (no recurring).

Seems to work fine until confirming the purchase on Paypal. I get a white screen upon redirection.

Warning: call_user_func_array() [<a href='function.call-user-func-array'>function.call-user-func-array</a>]: First argument is expected to be a valid callback, 'uc_payflowpro_ec_review_redirect' was given in menu_execute_active_handler() (line 348 of /htdocs/includes/menu.inc).

Probably due to chunks failing during install - From the .rej file:

***************
*** 25,63 ****
   * Implementation of hook_menu()
   */
  function uc_payflowpro_menu() {
- 
-   // Callback functions for Express Checkout
-   $items['cart/echeckout/selected'] = array(
-     'title' => 'Review order',
-     'page callback' => 'uc_payflowpro_ec_review_redirect',
-     'access arguments' => array('access content'),
-     'type' => MENU_CALLBACK,
-   );
-   $items['cart/echeckout/review'] = array(
-     'title' => 'Review payment',
-     'page callback' => 'uc_payflowpro_ec_review',
-     'access arguments' => array('access content'),
-     'type' => MENU_CALLBACK,
-   );
-   $items['cart/echeckout/submit'] = array(
-     'title' => 'Submit order',
-     'page callback' => 'uc_payflowpro_ec_submit',
-     'access arguments' => array('access content'),
-     'type' => MENU_CALLBACK,
-   );
-   $items['cart/echeckout/complete'] = array(
-     'title' => 'Order complete',
-     'page callback' => 'uc_payflowpro_ec_complete',
-     'access arguments' => array('access content'),
-     'type' => MENU_CALLBACK,
-   );
-   $items['cart/echeckout/cancel'] = array(
-     'title' => 'PayPal payment cancelled',
-     'page callback' => 'uc_payflowpro_ec_cancel',
-     'access arguments' => array('access content'),
-     'type' => MENU_CALLBACK,
-   );
- 
    // Recurring Billing administration
    $items['admin/store/settings/uc_recurring'] = array(
      'title' => 'Payflow Pro Recurring Settings',
--- 25,30 ----
   * Implementation of hook_menu()
   */
  function uc_payflowpro_menu() {
    // Recurring Billing administration
    $items['admin/store/settings/uc_recurring'] = array(
      'title' => 'Payflow Pro Recurring Settings',

torgospizza’s picture

Any follow-up to this? The patch in #22 allows us to use Express Checkout (the module did not work previously) however I have not yet been able to test all the way through. We need to get this working... any updates would be appreciated, otherwise I will try to work on it myself now.

damienmckenna’s picture

@bbqsauced: you have to apply the patch to the -dev version, then it'll apply correctly.

damienmckenna’s picture

+1 for the patch in #22.

I don't know about anyone else, but I suggest asking AntoineSolutions if he'd be willing to co-maintain the module and add all of his patches so this module can finally work correctly.

damienmckenna’s picture

Status: Needs review » Reviewed & tested by the community

The only way this could be improved would be to have an update script in uc_payflowpro.install to automatically enable the module if the checkout pane was enabled.

damienmckenna’s picture

FYI if you're using my patch from #1661716: Code in uc_payflowpro_form_alter() causes checkout to fail you have to first revert that patch (easy way: download uc_payflowpro-6.x-1.x-dev again) and then apply this patch.

reinvented’s picture

Note that if you're using the patch from #22 -- which substantially works -- you will find that the Paypal checkout page's left-hand-column order summary doesn't contain the details of the customer's order if any of the following are applied to the order in Ubercart:

  • Shipping
  • Taxes
  • Coupon Discounts
  • Multiple quantities of any product in the cart

The module still works, and customers can still check out, but they won't see a summary of their order (and thus not the total amount they are signing in to pay for) in most circumstances.

Paypal's Payflow Pro Express Checkout API will only display the order summary if the order total (the AMT parameter) equals the sum of the item total (ITEMAMT), taxes (TAXAMT) and shipping (FREIGHTAMT).

Shipping and Tax

This module does not pass shipping or tax information to Paypal at all, so unless you have a tax-free order with no shipping you will not see the order summary.

We added the passing of shipping and tax in the uc_payflowpro_ec_checkout() function of uc_payflowpro_ec.module with:

$tax = 0;
$shipping = 0;

if (is_array($order->line_items)) {
  foreach ($order->line_items as $item) {
    if ($item['type'] == 'shipping') {
      $shipping += $item['amount'];
    }
  }
}

if (module_exists('uc_taxes')) {
  foreach (uc_taxes_calculate($order) as $tax_item) {
    $tax += $tax_item->amount;
  }
}

and then adding these to the $request array:

    'TAXAMT' => substr(uc_price($tax, $context, $options), 0, 10),
    'FREIGHTAMT' => substr(uc_price($shipping, $context, $options), 0, 10),

Coupon Discounts

Also, this module does not add a line item for coupon discounts (applied, for example, by the uc_coupon module). Note that if you plan to modify the module to handle coupons, if you pass the DISCOUNT parameter this will appear in the Paypal order summary as "Shipping Discount" and note also that the ADJUSTMENTAMT parameter appears to be only for Paypal internal use. Our solution was to add a line item with a negative amount, like this (where $discount is the amount of the discount, a negative number, and $discountlabel is the label to show with the discount in the Paypal order summary), in the uc_payflowpro_ec_checkout() function in uc_payflowpro_ec.module:

if ($discount < 0) {
  $maxnum = 0;
  foreach($request as $k => $v) {
    if (substr($k,0,6) == 'L_NAME') {
      $num = str_replace('L_NAME','',$k);
      if ($num > $maxnum) {
        $maxnum = $num;
      }
    }
  } 
  $newnum = $maxnum + 1;

  $request['L_NAME' . $newnum] = 'Discounts';
  $request['L_DESC' . $newnum] = substr(check_plain($discountlabel), 0, 35);
  $request['L_COST' . $newnum] = substr(uc_price($discount, $ec_context, $ec_options), 0, 10);
  $request['L_QTY' . $newnum] = 1;

  $subtotal += $discount;

  // Set the updated item subtotal amount now that we've applied discounts
  $request['ITEMAMT'] = substr(uc_price($subtotal, $ec_context, $ec_options), 0, 10);
}

Multiple quantities of any product in the cart

Paypal's Payflow Pro Express Checkout API expects the L_COSTn parameter passed to be the unit cost of the product; as it stands the module passes the aggregate cost (qty * price). This means that if the quantity is more than one Paypal will not display the order summary.

We fixed this by modifying the uc_payflowpro_ec_request_products() function in uc_payflowpro_ex.inc so that the the line:

$request['L_COST' . $i] = substr(uc_price($price_info, $ec_context, $ec_options), 0, 10);

passes $priceinfo with a 'qty' key of '1'.

With all of the above added to the module, we are now successfully getting the Paypal order summary on all orders:

torgospizza’s picture

That's some excellent work. Any chance you could get this in a patch as well? We suffer from the same issue, and I'd love to test a proper patch. I would also be able to modify this to work with UC Gift Certificates, as using them for partial payment is essentially the same as including a coupon discount, and requires its own negative line item in the order.

Thanks!