SparkDevNetwork / Rock

An open source CMS, Relationship Management System (RMS) and Church Management System (ChMS) all rolled into one.
http://www.rockrms.com
572 stars 347 forks source link

Obsidian Registration Block Charges Duplicate Payments #5377

Closed thejasonharvey closed 1 year ago

thejasonharvey commented 1 year ago

Please go through all the tasks below

Please provide a brief description of the problem. Please do not forget to attach the relevant screenshots from your side.

When submitting a registration, if the page has an abnormally long load time, long enough that a gateway request is submitted more than once, Rock does not recognize it has submitted more than one request and therefore multiple charges are applied to the registrar. Rock will not have a record of the double charge (it will only record one), but the payment processor will log two charges.

Expected Behavior

When submitting a registration, regardless of the load time, if registration was successful only one payment would be made.

Actual Behavior

When submitting a registration at a time when the website page is under a heavy load (in our case we had about 60 registrations in 15 minutes which was causing longer load times) Rock was unable to realize it had already made the charge and then charged the registrar again.Below is the reply of the analysis from our payment processor:Both transactions originated from Rock RMS directly and did not have any order id submitted with the payment request. It doesn't look like the Rock RMS event registration includes an order id on the transaction processing request. When an order id is present in the processing request, the gateway will reject any secondary transaction charge requests if an existing transaction with the order id is already present in the gateway system. We would recommend asking Rock RMS to include an order id in the NMI merchant processing request, as that will prevent duplicates at the gateway level. Included below is the NMI gateway documentation to the direct post-transaction variables section. Under that section is a variable named "orderid". Adding the additional "orderid" variable to the charge POST request. As long as that "orderid" is unique for the checkout session then duplicates will be blocked. This works as once a transaction is approved with an order id, then NMI will decline any additional charge requests with the same order number as an approved order already exists. Using this should a user fire off two rapid charge requests, the first request would approve and the second will decline, etc. Integration Documentation: https://secure.process4changegateway.com/merchants/resources/integration/integration_portal.php#transaction_variables Directions: Please see Transaction Variables > "orderid"

Steps to Reproduce

Admittedly this might be difficult to reproduce. You would have to have a registration page that is experiencing a heavy load that causes the page to load slowly enough that the request to the payment gateway occurs more than once. However, based on the documentation received from our payment processor the issue is well understood and limited to the lack of orderid. So, I suppose if you analyzed a successful payment and noticed that no orderid was present then you could expect the issue to be plausible under the circumstances that would cause a registration to make multiple payment gateway requests.

Rock Version

14.2

Client Culture Setting

en-US

ethan-sparkdevnetwork commented 1 year ago

Hello @thejasonharvey. I am looking into this but I do not see any info in NMI's API documentation about the orderid field except that it exists. I have submitted a support request to them. In the meantime can you let me know where you got your information? I didn't see anything on the interwebs.

thejasonharvey commented 1 year ago

Hello @ethan-sparkdevnetwork. Thank you for the follow-up. When we encountered this issue we reached out to our payment processor OnlineGiving for more insights. They did all the technical checking and responded with what was included in the "Actual Behavior" Section above (more or less).

ethan-sparkdevnetwork commented 1 year ago

@thejasonharvey I got a response back from NMI. I asked them about duplicate payments in general, and the "orderid" field in particular. Their response is below. NMI says that the orderid field is not and cannot be used to prevent a duplicate payment. They also say that in order to get a duplicate it has to actually be submitted twice. I will keep looking into Rock to find what could be happening, slow load times should not be creating additional requests to NMI or any processor.

The good new is NMI has internal controls that can be configured to prevent duplicate payments. Essentially you can setup the system to not allow the same amount to be charged on the same card more than once in a set time limit in seconds. They give instructions for that below.


How to prevent duplicate payments caused by (I think) the retry logic in collect.js. Collect.js payment tokens are for one-time use so when a transaction comes in with a particular payment token and it gets processed that payment token becomes invalidated and cannot be used anymore. To send in another transaction that would get charged again the customer would have to enter in information again and collect.js would create another different token which would then be sent in. That being said there is a feature built into the gateway that allows for duplicate checking you can enable if it isn't already. If you log into your affiliate partner account and go to list accounts and select the relevant merchant you will be brought to a configuration page for that merchant.

If you scroll down a bit you should find something that's called processor configuration. This contains all the processors that are boarded onto the merchant account. Find the one that is having the transactions sent to it and then click on edit. This will allow you to edit the processor configuration. Within the processor configuration section, there should be a subsection called 'Duplicate Velocity Controls'. These contain options for duplicate checking which include enabling/disabling it, setting the minimum time for duplicate checks, and merchant override. The minimum time is in seconds and simply means how long from an initial transaction the system will check for duplicates and the default value is 20 minutes [1200 seconds]. That means that when a transaction comes in for the next 20 minutes it will check to see if any duplicates come in and if they do it will block that transaction from coming through. The two relevant fields that it will check are the card number and the amount sent in. This will also work with an integration that is using collect.js as well. Merchant override allows the option for a merchant to manually allow a duplicate transaction but this only applies to virtual terminal transactions so not super relevant for this case.

I would also advise just having the development team check their integration to make sure that it's not accidentally doing anything wrong. Also, I can investigate some cases of these duplicates if you provide the transaction IDs associated with them.

Info about the orderid field, what it does, how/why to use it. orderid is a field that can be assigned to a transaction. We usually see this when a company has some kind of internal system to keep track of orders and they populate this field so that the transactions/transaction report matches up with what they have in their system and they can better account for goods sold. It is also required for Level 3 transactions which require more information but give you a much better interchange rate in return.

thejasonharvey commented 1 year ago

Hey @ethan-sparkdevnetwork, I forwarded this to the OnlineGiving support team. I will be following up with them and will touch base again afterward. Sorry for my delayed reply.

Have you tested what happens if you multi-click the "Submit" button on a registration? There are several places in Rock where we have noticed if someone clicks the equivalent of a "Submit" button multiple times before the page responds then duplicated entries can be submitted. We have never observed this in relation to registration payment, just to be clear, and I recognize that if duplicate protection is working properly on the merchant side it shouldn't matter but since I have observed it in other button behavior it makes me wonder if it is possible.

deboorn commented 1 year ago

Some important items you may want to consider with respect to using NMI's Order ID

Some important items you may want to consider in respect to using NMI duplicate second feature vs Order ID

nairdo commented 1 year ago

@thejasonharvey I hope you were able to find a resolution with your payment gateway provider, OnlineGiving.

From: NMI ... Info about the orderid field, what it does, how/why to use it. orderid is a field that can be assigned to a transaction. We usually see this when a company has some kind of internal system to keep track of orders and they populate this field so that the transactions/transaction report matches up with what they have in their system and they can better account for goods sold. It is also required for Level 3 transactions which require more information but give you a much better interchange rate in return.

Taking into account the details of this issue and the information from NMI (seen above), we will not be making any additional changes to the core gateway code. Since Rock does not currently have a need for the orderid field nor does the NMI payment gateway (currently supported core gateway).

thejasonharvey commented 5 months ago

@nairdo I wanted to bring this to your attention as we encountered the issue again last week in a specific registration that was hit pretty hard all at once. This time around it occurred to two different people as they were registering. Rock only logged one payment, however, our gateway registered two. Neither of the individuals was aware they had been double charged until we reached out to them and asked them to verify they had been double charged.

I recognize this may not be considered a Rock-specific issue, but as the issue is recurring under specific circumstances and related to registrations that are experiencing a sudden and heavy load I thought it would be worthwhile noting it again. The scenario from last year is very similar and this particular piece of information from our gateway provider support team I believe is relevant:

Previously, we had focused on the way payment occurs, but now that we have confirmed our settings should have stopped a quick double click, and the duplicate transactions occurred more than a minute apart, maybe there is something else that would be beneficial to look into?

deboorn commented 5 months ago

Hey there @thejasonharvey! Technically speaking, it looks like there's a bit of an issue with the way Rock is implementing NMI. Currently, Rock isn't taking advantage of the NMI Order ID field for duplicate prevention, which is causing some trouble.

But don't worry, the solution is pretty simple! All Rock needs to do is make sure that the Order ID field is populated with a unique ID for each event registration. This will make sure that NMI rejects any secondary charge requests if there's already an approved transaction with the same NMI Order ID in the gateway. Easy peasy!

This isn't a processor vendor issue but an NMI gateway issue by not taking advantage of the NMI Order ID field IMO.

Hope this helps!

chead4 commented 5 months ago

@thejasonharvey Hi Jason - We're sorry to hear that you experienced this issue last week with a registration. It would be greatly appreciated if you could provide some more details so that we can investigate further. First, please navigate to System Settings/Financial Gateways and paste a screenshot of the payment gateway that you are using. Second, please run this SQL query and paste the results.
SELECT * FROM [EntityType] WHERE [FriendlyName] LIKE '%NMI%'

thejasonharvey commented 5 months ago

image

image

sparkdevnetwork-service commented 5 months ago

@deboorn Based on the information in this issue, it seems clear that there is a plugin (Online Giving Integration) involved here with the payments. We would like to recommend that you contact Spark (info @ sparkdevnetwork.org) to consider working with them for further assistance and enhancements/changes to Rock core.