Hello,

When performing an order, using Paypal or Check method, the module acts as if the order was complete. So when the user goes to his account, in the Product Keys section, a Key is associated to the product and so visible.
The e-mail containing the key is not sent because the order is pending but the user can see his key in My Account.
I used Paypal and when the status is "PayPal pending" the Key is visible an associated to the user.
With the Check method, after confirming the order (so the check is not received by the store) the Key is also visible.

It looks like the "COD payment" issue but its status is "won't fix" so I posted here.

Could anyone help me or explain me if I'm wrong please ?

Comments

freixas’s picture

Assigned: Unassigned » freixas

Yes, I agree this sounds like the "COD payment" issue.

Perhaps there is a way to fix this. The question is: when do you give the user the product key? My answer so far has been: when the order is completed. This is because I've been thinking of the order process mostly in terms of checkout.

In another bug report, someone pointed out that admin-created orders never issued a product key. Again, this was because I was just thinking of checkout, rather than thinking of the entire life-cycle of the order.

I fixed the admin orders by issuing keys to any product order where the order state transitions from anything to 'completed' AND the order currently has no product keys associated with it.

So I've removed the hook_order_complete() function and now handle everything with hook_order(). Product keys are issued IF the order is transitioning to payment_received OR completed AND the order has no associated product keys.

In theory, this should fix your problem and even the COD problem. Could you test out the dev release dated 3/5/10 or later and see if your problem is fixed (and no new ones cropped up)? Let me know what you find.

freixas’s picture

Status: Active » Needs review
nicolasb_cdip’s picture

Assigned: freixas » Unassigned
Status: Needs review » Active

Hello and thanks for your answer !

I have just installed the last dev release and things are a little different. So here is what happen in the two payment method I tested :

Check :
Pending -> nothing (OK)
Payment received -> Key visible in My account (OK)
Completed -> nothing new (should be sending an e-mail with the key)

Paypal :
Paypal Pending -> Key visible in My account (should not be visible)
Payment received -> nothing new (key should be visible now)
Completed -> nothing new (should be sending an e-mail with the key)

So with the Check method it's almost okay (I didn't change the conditionnal action associated). But with the Paypal method, the user shouldn't be able to see his key before the payment is defined as received.

Hope this can help.

freixas’s picture

Assigned: Unassigned » freixas

Thanks for taking the time to check this out. Your diagnostics are puzzling.

When a key is generated, the email should be sent out. So for the Check method, the key should go out when the payment is received. One question is whether you've ever got the email for any payment method. I use uc_free_payment for testing and I have a test product key with a $0.00 price. I wonder if you could install this module and see if you get the email (unless you have some other way of verifying that the email works). Perhaps you haven't set up the conditional action properly?

The PayPal method reveals some sort of problem—it could be on my side or in the PayPal payment code. It's a pain to test since I have to go set up a sandbox account. I'll check this out when I get some free time. I'm assuming you're not a programmer, but if you are, it should be easy to find the code where the order states are checked and add some debug code to find out why the PayPal payment system is prematurely assigning a product key.

nicolasb_cdip’s picture

I'm gonna perform the following tests to let you have significant results : using the beta version and the dev release and for each one Paypal method, Check and Cybermut (payment module).
I'm a programmer but I'm just starting to learn about Drupal module. I had a look on your .module file and I see where the test concerning the order status has been done. So according to your code, there is no reason it's not working well.

Does the conditionnal action need to be configured ? Because I see there is no predicate and I'm a bit confused about that. I was expecting something like "order status updated : new status = completed" as a predicate for the action "send an e-mail"
EDIT : The conditionnal action just needed to be reset, that was why after re-installing your module in dev release the e-mail action didn't work. So now when the product key appears in My Account, the e-mail is sent. Those two actions are linked as expected.

Test results are coming... ;)
---------------------------------------------------------------------------------------------------------------------

Beta version

Check :
Pending -> Key visible in My account & e-mail sent (BAD)
Payment received -> nothing new
Completed -> nothing new (key should be visible & an e-mail should be sent now)

Paypal :
Paypal Pending -> Key visible in My account & e-mail sent (BAD)
Payment received -> nothing new
Completed -> nothing new (key should be visible & an e-mail should be sent now)

Cybermut :
Pending -> can't be seen
Payment received -> Key visible in My account & e-mail sent (OK)
Completed -> nothing new
---------------------------------------------------------

Dev release

Check :
Pending -> nothing (OK)
Payment received -> Key visible in My account & e-mail sent (OK)
Completed -> nothing new (OK)

Paypal :
Paypal Pending -> Key visible in My account & e-mail sent (should not be visible & should not send e-mail)
Payment received -> nothing new (key should be visible & an e-mail should be sent now)
Completed -> nothing new

Cybermut :
Pending -> can't be seen
Payment received -> Key visible in My account & e-mail sent (OK)
Completed -> nothing new
---------------------------------------------------------------------------------------------------------------------

So as you said there might be a problem with the Paypal Payment, maybe the order status moves like "In Checkout" -> "Payment Received" -> "Paypal Pending" -> "Payment Received" ... or something like that.
I'm gonna try and see if I can fix that.

freixas’s picture

Progress!

In regards to the conditional action, here's the relevant code:

    // Pull the conditional action trigger and send the email to the user with the newly assigned keys.

    if(count($all_keys) > 0) {
      $status = ca_pull_trigger('uc_product_keys_assigned', $all_keys, $user, $order);
    }

In other words, the email is sent only if some product keys are assigned.

In regards to PayPal, what I would do is go to uc_product_keys_order() and add the following debug code:

    $old_state = uc_order_status_data($order->order_status, 'state');
    $new_state = uc_order_status_data($arg2, 'state');
    var_dump($old_state, $new_state);

The var_dump() may screw up the checkout process, so you may want to enable it only right before you submit the order. An alternative is to use something like:

file_put_contents('somefile.txt', "$old_state $new_state\n", FILE_APPEND);

This should reveal whatever may be causing the problem. Before making any changes to the PayPal payment code, you may want to do some research to find out why they do whatever they do. One of the problems with using hook_order is that there are a lot of payment modules and they don't all use the state settings in a consistent manner. It's sometimes impossible to write code that will work with all the payment methods.

nicolasb_cdip’s picture

Thanks for your help !
I used this instruction :
file_put_contents('****/trace.log', "at ".date('i:s')." -> $old_state $new_state\n", FILE_APPEND);
to see when your function is called and what are the states and here is the result :

at 04:43 -> in_checkout post_checkout
at 04:47 -> post_checkout payment_received
at 06:09 -> payment_received payment_received

As I was expecting, the Paypal module (or just the Sandbox mode) is changing the order state twice in a normal transaction.

After submitting the form which appears after the visiting the Paypal website, the state change from in_checkout to post_checkout which is normal. Without doing anything and after a few seconds, it changed to payment_received (on the order pane : in_checkout -> Paypal pending).
I think the problem is here, the new state should be Paypal pending (the same as on the order pane).
And the last change is because in Sandbox mode we need to validate a payment, and so the state change without effect.

So I'm thinking about having a look over the "uc_order_status_data" function or maybe the Paypal module, but it seems like your module doesn't need to be fixed :)

freixas’s picture

Status: Active » Fixed

Since you're new to Drupal/Ubercart, let me point you to a discussion of order states vs. order statuses: http://www.ubercart.org/docs/developer/920/order_states_and_statuses.

I looked at the PayPal payment module code and I see it adds a status of "paypal_pending" and matches it to state "payment_received". It also (in _uc_paypal_pending_message()) lists a number of reasons way a payment may be pending. In some cases, the payment has actually been received from the customer but requires some additional action before you can received the funds.

So why don't I just check for the "completed" state? Some payment modules don't place the order into the completed state.

To get this right, I would have to code the correct condition check for each payment method. This is not possible, but what I've done is added a hook so that people can customize the condition based on whatever payment system they have. Check the revised README.txt file for hook_uc_product_keys_order_ready(). I only did enough testing to make sure that, if no one implements the hook, the code still issued the keys the same as before.

If you've never extended a hook before, you will need to read about creating a module. The module should be pretty simple. You will need an info file and a module file. The module file will include a function called [module name]_uc_product_keys_order_ready($order, $status). I think you can get the payment system from the $order object. Since you know the payment system, you can use the order statuses added by the PayPal module in addition to looking at the states.

Let me know if you have any success using the hook to resolve your problem.

nicolasb_cdip’s picture

Before trying to extend the hook you provide, I have made some other tests to sumarize the 3 payment method I use and their calls to your function because I wanted to "see" the difference between states and status myself. So, adding these two instructions :

file_put_contents('****/trace.log', "at ".date('i:s')." -> order->order_status=".$order->order_status." et arg2=$arg2\n", FILE_APPEND);
file_put_contents('****/trace.log', "at ".date('i:s')." -> old state:$old_state new state:$new_state\n", FILE_APPEND);

I got for Cybermut :

at 59:02 -> order->order_status=in_checkout et arg2=payment_received
at 59:02 -> old state:in_checkout new state:payment_received

for Check :

at 59:57 -> order->order_status=in_checkout et arg2=pending
at 59:57 -> old state:in_checkout new state:post_checkout
at 00:38 -> order->order_status=pending et arg2=payment_received
at 00:38 -> old state:post_checkout new state:payment_received

and for Paypal :

at 03:07 -> order->order_status=in_checkout et arg2=pending
at 03:07 -> old state:in_checkout new state:post_checkout
at 03:10 -> order->order_status=pending et arg2=paypal_pending
at 03:10 -> old state:post_checkout new state:payment_received
at 03:29 -> order->order_status=paypal_pending et arg2=payment_received
at 03:29 -> old state:payment_received new state:payment_received

And it seems like if your were testing arg2 instead of $new_state, if think it should work with the Paypal module as well. Don't you think.
I understood why you didn't use a test against a "completed" state or status. But here, using the arg2 value, your test would be the same and it should take care of the Paypal situation.

What do you think about that ?

EDIT : I tried to make this change and it seems to be okay, so if you agree to add it to your dev release, I think it should handle the Paypal Payment ;)

freixas’s picture

The reason I don't look at statuses is because of the way they are specified (see http://www.ubercart.org/docs/api/uc_order_status_list):

Statuses may be renamed and reordered, ...

There is no guarantee that any particular status exists in any instance of Ubercart. Your code may work with your system, but I can't incorporate it.

nicolasb_cdip’s picture

Okay I understand.

I used the solution you provided and it's okay. So I wrote a module extending the hook and it's well handled. I don't know if I should publish this module because it's very specific to my use. Maybe it should be linked to your module... What do you think ?

Anyway thanks a lot for your help, and now I know more about debugging Drupal and extending modules.

freixas’s picture

The PayPal module is used by a lot of people, so your code would probably be a nice little extension to have. Why don't you attach your module here and I'll add it as a sub-module that people can enable if they are using the PayPal payment system. I will credit you as the author, although I will make modifications if needed.

Ideally, the module should check if the payment system is PayPal. If not, it should return NULL for the hook. If it is PayPal, then test for the right conditions under which to issue the keys and return TRUE or FALSE. If it's written properly, it shouldn't be specific to your system, just to PayPal. The real trick is that there are several ways PayPal can be used. I forget the names—I know one is called PayPal Standard. The module should work (and be tested) with all these modes. Since you probably just use one type of payment, you'll need to tell me which type you've tested.

If you want to make a more significant contribution, you'll see if you can make your module work for all the ways in which the PayPal module can be set up.

Thanks for testing my changes!

nicolasb_cdip’s picture

StatusFileSize
new595 bytes

I see two ways in which the PayPal module can be set up (PayPal Express Checkout [paypal_ec] and PayPal Website Payments Standard [paypal_wps]) so I adapted my module to handle these two ones.
I have tested both ways and it seems to be okay.
If anyone notice an other one (maybe 'credit'), let me know.
My module is attached, it's my first one so let me know for any mistakes.

Cheers

freixas’s picture

Hi,

I finally had time to check out your module. I made a few minor changes in the formatting and such, but it still uses the exact same algorithm you created. I checked it out as far as making sure that I hadn't introduced any typos and that I could place an order with your module enabled. I didn't actually try to set up the PayPal code.

I've created an RC1 release. If you download this, you will see the changes I made to your code. Also, the RC1 should continue to work for you—holler if I screwed up something.

Be sure to disable your module, remove it from the sites/all/modules folder, install the update and then re-enable my version of your module.

Status: Fixed » Closed (fixed)

Automatically closed -- issue fixed for 2 weeks with no activity.