So I was messing around with my cart and discovered something interesting. We could end up with orders of negative value. For fun I proceeded to the Moneris HPP to see what it would do. The HPP indicated that the transaction was for a negative value and successfully posted the transaction back to the site. Because HPP is not designed to process negative transactions, it produced a response code of "Null" and HPP accepted that response code as a successful payment, which it should not have.

My immediate solution to fix this on my own site is to implement a minimum transaction amount for the Commerce Moneris HPP rule. This is a temporary solution and won't necessarily prevent Null response codes in the future.

EDIT: Another way of producing a "Null" Moneris Response Code is to click the browsers back button after the payment has been accepted. The browser goes back to the last step Moneris' payment process (where it posts values back to the website) and then returns the Null value to the site and associates it with the same order. There is no apparent way to prevent this.

Support from Acquia helps fund testing for Drupal Acquia logo

Comments

rbrownell’s picture

Issue summary: View changes

corrected grammer

rbrownell’s picture

It appears that the function looking for the null value is case sensitive (it searches for 'null'). When Moneris HPP posts back to Drupal it does so with a 'Null'. I am going to create a patch to remedy this using a case insensitive comparison.

The HPP component of the Commerce Moneris module didn't have a function coded that handled 'null' response codes. I am currently working on a patch for this.

rbrownell’s picture

Version: 7.x-1.x-dev » 7.x-1.3
Component: Code » Miscellaneous
Assigned: rbrownell » Unassigned
Issue tags: -Needs tests

So here is my somewhat extensive patch...

Upon working on this I discovered that null values occur for a number of reasons:

  • The payment was already processed. This creates a null response_code and a message indicating that the submitted order id was already processed. This can occur when one presses the back button of their browser after the payment was completed. This also puts the order state back into the checkout state, which if the payment was already successfully completed is undesirable.
  • The payment value is negative. Creating a null response_code and a message indicating that the amount submitted is invalid.

The attached patch changes functions related HPP only.

Patch Changes:

  1. It modifies some existing comments to make them more useful by indicating if the function is related to HPP.
  2. Implements Moneris Canada's "Enhanced Cancel Feature".
  3. Improves the handling of transactions that are cancelled.
  4. Removes the "Payment successfully." message from the order completion so that users can define messages via rules.
  5. Verifies that the order state is in the checkout state before attempting to process the transaction.
    1. If the order is in completed or pending states it simply goes back to the completed page, does not add any more transactions, and prints a status message indicating that payment was already submitted.
    2. If the order is in any other state it prints an error message and returns the user to the home page.
    3. This is handled before a null response_code is handeled.
  6. Improves the handling of transactions with a null response_code.
    1. Posts payment with status of failure.
    2. Returns verbose error messages from Moneris indicating the problem.

Notes:

  • Change #2 The "Enhanced Cancel" feature returns a full response to the decline url with a response code of '914' to indicate that the cardholder cancelled the transaction.
  • Change #3 Cancel does not seem to work in Canada without Enhanced Cancel enabled on Moneris' end. Moneris seems to send cancelTXN through a GET function instead of a POST function thus breaking it.
  • Change #3 Using COMMERCE_PAYMENT_STATUS_CANCELED does not produce a valid Payment status.
  • Change #5 Tests the STATE and not the STATUS to avoid conflicts with rules and other modules that can create custom statues.
  • Change #5-1 Moneris HPP in Canada automatically prevents duplicate transactions based on the Order ID, so recording transactions if the checkout is already complete is unnecessary. This will need to be confirmed in the US.
  • Change #5-2 returns to the home page to prevent orders with the states shopping_cart and cancelled from being unintentionally put into the checkout process.
  • I could only test Change #6-2 in Canada. I am unsure if Moneris HPP in the United States contains a returned 'message' value, though I did call for it in the HPP US variable selection section.

Everything here has been tested for production HPP in Canada. I would appreciate someone testing it for production HPP in the United States... I couldn't find an American integration guide for Moneris HPP.

rbrownell’s picture

Assigned: rbrownell » Unassigned
Issue tags: -Needs tests
FileSize
6.19 KB

Attaching the patch here... (Had to re-roll it against the latest dev.)

rbrownell’s picture

Version: 7.x-1.3 » 7.x-1.x-dev
Assigned: Unassigned » rbrownell
Status: Active » Needs review
rbrownell’s picture

Issue tags: +Needs tests
rbrownell’s picture

Component: Miscellaneous » Code
Assigned: Unassigned » rbrownell
Issue tags: +Needs tests
rbrownell’s picture

FileSize
6.13 KB

Just realized my initial patch included a drupal_set_message that I used for developmental purposes... This one does not have that message.

rbrownell’s picture

FileSize
6.42 KB

Yet another revision of my patch... Upon further reflection, for accounting purposes, every post to Drupal whether a successful transaction or a failed one should probably be attached to the order's history. This patch causes Changes #5-1 and #5-2 (listed above in previous comments) to write the transaction results anyways.

rbrownell’s picture

Version: 7.x-1.3 » 7.x-1.x-dev
Component: Miscellaneous » Code
Assigned: Unassigned » rbrownell
Issue tags: +Needs tests

So I was thinking about this this morning and I came to realize that probably the best way to prevent the problems associated with the back button is to use the Transaction Verification feature in HPP #2068601: Implement HPP Transaction Verification so that each and every transaction is properly verified.

Another layer of fool proofing is to setup HPP to load within an iFrame #2050527: HPP in Frame that way the back button will take the user to a page that is generated by Drupal and any code used to display the iFrame could validate that the cart is in the Checkout: Payment status before doing so. (I will look into this sometime soonthis week.)

Other thoughts about the logic I built into the patch that need to be improved are:

  1. For successful transaction processing, the processor should be looking for the Checkout: Payment status instead of the Checkout state.
  2. If the order is in the Checkout State AND does not have the Checkout: Payment status I think the transaction should be recorded and an error given.
  3. If a successful transaction was posted erroneously for whatever reason (example: double payment) it needs to be indicated as a successful transaction. There also needs to be some sort of notification to the site administrator of the problem.

Notes:

  • #2 After reading http://www.drupalcommerce.org/developer-guide/utilizing-core-apis/writing-payment-method-module it seems that the status of the cart is set by the checkout and not the payment module this means that the Checkout: Payment (which locks carts from modification) is automatically set when for us when we proceed to the HPP. In which case I think the error handling should probably be the same for the "Canceled" and "Pending" order states.
  • #3 I am not quite sure how to handle something like this. I almost think a new variable should be indicated to indicate potential trouble with the transaction... Perhaps a new order status under the pending state? Something like 'Payment Review Required' or 'Payment Transaction Verification'. This way the order is marked complete and the person fulfilling the orders can then double check the payments for problems and make any necessary corrections.

I will work on a new patch for this today.

rbrownell’s picture

FileSize
6.08 KB

Wow. What a ride! Fix one thing, break another, fix that, discover other unrelated problems... Who knew contributing to modules would be so much fun!? (Believe me, I have a whole new respect for maintainers now.)

I have implemented all of the changes mentioned above and after running a 32 scenario test suite, have thoroughly tested it for HPP in Canada.

Additional Changes:

  1. Added Payment Transaction Verification to the list as per comment #9 item 3. If the order is in any state other than checkout_payment when it is processed and if it is approved will mark it with this new status.

Notes

  • The only thing that is pending testing for the US is the verbose messages (See comment #2 item 6-2), everything else should be sound in terms of logic because there are no special functions unique to the US other than setting the initial variables. Though I am confident that it is fine because I managed to hunt down a copy of the US Merchant Integration Guide and the message returned value uses the same key.
  • Caches need to be cleared in order for the Payment Transaction Verification status to show up in the statuses list.
  • #1This method does not test the order balance but rather relies on the order status to determine if a duplicate payment occurred... As far as I see it, the only way this could happen is if an order with the Pending or Completed states is somehow put back into the checkout state (which would more than likely only involve an administrator... Or a rule, but anyone who makes a rule like that would also be creating a feedback loop in their checkout process). I think that Drupal Commerce should almost have a verification step when switching between the Complete and Pending states and the rest of the states.
rbrownell’s picture

Title: Commerce Moneris HPP reports successful payment on Moneris Response Code Null » Moneris HPP improve handling of null response codes
rbrownell’s picture

Component: Code » Moneris Hosted Pay Page: Code
rbrownell’s picture

Component: Moneris Hosted Pay Page: Code » Hosted Pay Page: Code
rbrownell’s picture

Status: Needs review » Fixed

Committed to 7.x-1.x-dev.

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

Anonymous’s picture

Issue summary: View changes

Added new way of producing Null values.