CVV code not being passed to Authorize.net for validation using Accept.js

Created on 3 May 2019, about 5 years ago
Updated 20 May 2024, about 1 month ago

ISSUE:

CVV code entered into payment information form during checkout is not being sent to authorize.net. We are using Accept.js and are not using Cardinal Cruise.

STEPS TO REPRODUCE

  • Enable and configure Authorize.net (Accept.js)
  • Enter an invalid CVV code during checkout
  • The order goes through with invalid code

MORE INFORMATION

If you make the CVV security "required" in authorize.net (as is recommended) then ALL payments will fail. I assume that this is because the CVV value is not actually being passed to auth.net. Since the value is now required and no CVV value is sent all payments are declined.

If we turn the 'required' setting back off for the CVV field then any CVV value entered is accepted. Again, it appears that this is because the CVV value is not actually being sent to auth.net.

The CVV field appears to be part of the auth.net module and not the Commerce Payment module itself. Is there a disconnect somewhere in the way the CVV field is added by the auth.net module?

EDIT: More Information

After a lot more testing and speaking at length with a support rep at Authorize.net they confirmed that the CVV data is, in fact, not being sent from Commerce Authorize.net Module to Authorize.net for processing. On all of our tests the auth.net data shows:

Card Code Status: Not Applicable

Which the rep says means that no CVV data was received for the transactions.

EDIT: More Information

In /js/commerce_authnet.accept.form.js, I put some debug code to output what I think is being sent to auth.net and it does appear that the secureData object contains the cardCode value that was enetered as expected. I thought maybe there was a typo in the variable name but it appears to match the auth.net documentation exactly.

For some reason though the cardCode value is not actually being received by auth.net. This has been confirmed in multiple ways.

🐛 Bug report
Status

Needs work

Version

1.0

Component

Code

Created by

🇺🇸United States 3CWebDev

Live updates comments and jobs are added and updated live.
Sign in to follow issues

Comments & Activities

Not all content is available!

It's likely this issue predates Contrib.social: some issue and comment data are missing.

  • 🇮🇳India Suresh Prabhu Parkala Bangalore

    A re-rolled #28 patch against the latest 8.x-1.x. Please review.

  • Status changed to Needs work over 1 year ago
  • 🇮🇱Israel jsacksick

    Why is the card type now hardcoded? Also, the diff kinda looks wrong which makes me wonder if some changes didn't get lost between the patch iterations...

  • 🇺🇦Ukraine tBKoT

    I tried adding the latest patch or a couple and everything seems to be working as it should. However, this only works for newly added cards and doesn't work every time I want to reuse existing payment methods. Another problem I encountered is that it is not possible to delete saved payment methods. I've decided to resolve this issue in a bit different way and let users enter the CVV code every time when the payment method is reused.

  • Status changed to Needs review over 1 year ago
  • 🇺🇦Ukraine tBKoT

    Add missing changes for tests

  • Status changed to Needs work about 1 year ago
  • 🇮🇱Israel jsacksick

    @tBKoT: had a quick look at your patch and realized you're testing the checkout step ID. We can't assume that the payment information pane is on the order information pane for example.

    Also, the order should be retrieved using the route match, like the following:

      /** @var \Drupal\commerce_order\Entity\OrderInterface $order */
      $order = \Drupal::routeMatch()->getParameter('commerce_order');
    

    Haven't really reviewed the rest.

  • 🇺🇦Ukraine tBKoT

    @jsacksick I've added the proposed changes. This patch tracks if we have the payment information panel

  • Open in Jenkins → Open on Drupal.org →
    Core: 9.5.x + Environment: PHP 7.3 & MySQL 5.7
    last update 8 months ago
    12 pass
  • Status changed to Needs review 8 months ago
  • Status changed to Needs work 5 months ago
  • 🇺🇸United States rszrama

    I'm not sure I understand the proposed solution here, as it appears we're now storing the CVV, which is not something we should be doing. (We also wouldn't use a patch that just comments things out like in the JS file here.)

    Why is the CVV not being transmitted directly to the server?

  • 🇨🇦Canada lindsay.wils

    Hi everyone. After weeks of debugging, testing and back and forth with not to helpful ANET support I FINALLY have found this thread which is clearly what I am encountering.

    What is the suggested solution here right now? It is suggested the latest patch works, but isn't recommended?

    Also, for us, everything worked in testmode with a sandbox account. Assuming because in my sandbox account the require CVV setting was disabled. This seems like a temp solution to get it working, but not secure for long term.

    Any suggestions would be very much appreciated as our project is delayed weeks now trying to resolve this issue.

    Thanks in advance

  • 🇺🇸United States ben.hamelin Adirondack Mountains, NY

    Hi @lindsay.wils!
    Please try the patch in #37 or #39. We're using 37 on our affected project.

    Longer term we need to open a MR, get review and approval from the maintainers on this fix. It's been a while since I originally dug into this, but at that time I outlined the problem as best I could in comments #14 and #20. But I haven't revisited it since so don't know the current status of the Auth API.

  • 🇨🇦Canada lindsay.wils

    Thanks very much @ben.hamelin.

    I have applied the patched and the issue is resolved. Wish I found this thread 2 weeks again.

    Another flag then is that the error code and message logged in Drupal does not give all the information.

    The extra information coming from the errorCode and errorText are not logged.

    errorCode -> string (2) "33"
    errorText -> string (22) "Card Code is required."

    Once I sifted through the module code and outputted the full error message myself, I was able to get this info, which is what led me to this thread.

    I believe this extra info should also be logged.

    Thanks for everyone's work on this patch.

  • 🇨🇦Canada lindsay.wils

    Hi @tBKoT,

    Could you please provide some details on what this latest patch is doing and how it differs from the previous? Ive just tested it and it failed to apply.

    I also have an update on the issue. The previous patch works when a user is paying with a card that already exists on their account in DC. When a new user adds a new card during the checkout process, the order fails and takes them back to the payment page, the added card is preselected and the CVV field shows. Enter the CVV into the field, process the payment again, and it works fine.

    We need a way that the CVV is passed to ANET with the new card details.

  • 🇨🇦Canada lindsay.wils

    For anyone else that has experienced this bug, are you able to confirm that you also see my issue mentioned above?

    If a user adds a CC during checkout for the first time, or adds a new CC during checkout, the payment fails.

    If anyone could please confirm that would be great to know if this is something wrong with my setup, or related to the same bug the patch fixed.

    Thanks

  • 🇺🇦Ukraine tBKoT

    @lindsaywils
    Could you try the latest patch from #45? I've made some changes to the form_alter because custom submit from there also was triggered when the user added a new card which should not happen. As a result, the stored CVV code is overridden to NULL.

  • 🇨🇦Canada lindsay.wils

    Thanks for the response @tBKoT.

    I did try applying that patch earlier yesterday and it failed to apply. I removed my composer patch for the first one and added this the new one, but it failed. I can try again and let you know.

  • 🇨🇦Canada lindsay.wils

    Just tried again and can confirm it failed to apply. any ideas? Thanks again for the continued work on this issue.

          "patches": {
                "drupal/commerce_authnet": {
                    "Deprecated function: strstr()": "https://www.drupal.org/files/issues/2022-11-07/commerce_authnet-deprecated-function-strstr-3319388-2.patch",
                    "CVV code not being passed to Authorize.net for validation using Accept.js": "https://www.drupal.org/files/issues/2024-04-01/3052498-45.patch"
                }
            }

    error message

      - Applying patches for drupal/commerce_authnet
        https://www.drupal.org/files/issues/2022-11-07/commerce_authnet-deprecated-function-strstr-3319388-2.patch (Deprecated function: strstr())
        https://www.drupal.org/files/issues/2024-04-01/3052498-45.patch (CVV code not being passed to Authorize.net for validation using Accept.js)
       Could not apply patch! Skipping. The error was: Cannot apply patch https://www.drupal.org/files/issues/2024-04-01/3052498-45.patch
    
  • 🇺🇦Ukraine tBKoT

    Updated patch from #45 and removed changes related to deprecation fix as it was resolved in #3319388

  • Open in Jenkins → Open on Drupal.org →
    Core: 9.5.x + Environment: PHP 7.3 & MySQL 5.7
    last update 3 months ago
    PHPLint Failed
  • 🇨🇦Canada lindsay.wils

    Thank you so much!! Ive just applied the patch, tested with making a purchase and adding a card during the checkout process, and the payment was successful!

    I cannot explain how grateful I am to you for providing this fix, and literally at the last hour before we were about to go live with some hack in place to warn users about the error and having to enter their CVV a second time, which was really not great.

    THANK YOU SO MUCH! We go live in 45mins with a working checkout and no hack!!

  • Status changed to Needs review 3 months ago
  • 🇺🇸United States ben.hamelin Adirondack Mountains, NY

    @tBKoT @rszrama I reviewed the patch in #51. It looks good to me, including the removal of the card_code from privateTempStore once it is no longer needed. I believe the need for this approach has been outlined throughout the comments, albeit these are dated and I'm not up to date on the latest Authorize.net API and documentation.

  • Status changed to RTBC 2 months ago
  • 🇯🇴Jordan Qusai Taha Amman

    The patch is working very well!
    Thank you so much!

  • 🇮🇱Israel jsacksick

    Storing the CVV is strictly prohibited... We can't really commit this patch as it is...

    From the Recurly documentation:

    Upon the creation of a new subscription or the update of a credit card number, Recurly submits both the card number and the CVV (Card Code Verification) to Authorize.net. In compliance with PCI regulations, storing CVV values is strictly prohibited, regardless of encryption measures. As such, the CVV can only be utilized for the initial request. Submitting the CVV along with the first request enhances the likelihood of transaction approval and serves as a robust deterrent against fraudulent activities. Banks generally permit subsequent transactions to process smoothly if previous transactions by the same merchant have been conducted without issues.

  • Status changed to Needs work about 2 months ago
  • 🇮🇳India vipin.j

    The documentation provided by Authorize.net for Accept.js implementation prefers & recommend to perform a createTransactionRequest with the one-time-use token, or payment nonce received in exchange of payment data submitted.

    We have referred a sample code for Drupal to implement Accept.js with createTransactionRequest, from the Sample Application on GitHub provided by Authorize.net and, experienced that when we build a transaction request with createTransactionRequest from the payment nonce received, we had no error/failure with the transaction, even when the Card Code(CVV) field was set to required or not with the Authorize.net merchant account. in both cases our transaction request executed successfully.

    But when we preferred to create Customer Profiles first over transaction request i.e. Customer Profile and Payment profile to charge the customer credit card, which Commerce Authnet's Accept.js plugin doing currently, we face the error message as "Card Code Required", when we set the Card Code field to required with Authorize.net merchant account's "Payment Form - Fields" settings.

    We can achieve security of the payment transaction while setting up the "Card Code" field to required, when we update the Accept.js plugin to perform a createTransactionRequest first over the creation of Customer Profile and Payment Profile.

    Though we can fetch Customer ID and Payment Profile ID from the transId reference with a new request createCustomerProfileFromTransactionRequest and this transId returned as a response of createTransactionRequest.

    But we need to accept that, whether we create profiles from Payment Nonce received or from the transId, The transaction request with reference to Profiles will always end-up with "Card Code is required." when Card Code field is set to required.

  • 🇺🇦Ukraine tBKoT

    tBKoT changed the visibility of the branch 8.x-1.x to hidden.

Production build 0.69.0 2024