3

Read
https://support.magento.com/hc/en-us/articles/360024368392
Issue :

Magento implements the Authorize.Net Direct Post payment method, using Authorize.Net's AIM (Advanced Integration Method) and DPM (Direct Post method) APIs, which use MD5 based hash.

Authorize.net will stop supporting MD5 based hash usage on March 14, 2019. Starting from this date, Magento Open Source, Magento Commerce and Magento Cloud merchants will not be able to process payments using Authorize.Net Direct Post payment method. To be able to continue successfully process payments using these methods, merchants need to apply the patch provided by Magento and replace the existing MD5 hash with a Signature Key in the Magento Admin configuration settings.

3 Answers 3

3

Now Apply Patch directly in vendor folder
This patch is applicable on all Magento 2.x and 1.x versions.

Alternatively you can use patched files from following address and replace them in your vendor folder.

https://github.com/MeetanshiInc/Magento-Authorize-Net-Direct-Post-Patch-for-M1-M2

If Need Run php bin/magento setup:upgrade; php bin/magento setup:static-content:deploy -f;

After apply patch you will see Signature Key enter image description here

2
  • You don't need to run upgrade script and re-deploy static content.
    – joni jones
    Mar 7, 2019 at 21:43
  • I needed to flush cache after that changes were reflected. Apr 5, 2019 at 14:54
0

I found this from github which explains the detail; https://gist.github.com/robolmos/7a3bf336516b18f8e0bd48a13d93e1ef

Basically, you have to change from the original patch file here;

Index: vendor/magento/module-authorizenet/Model/Directpost.php

+++ vendor/magento/module-authorizenet/Model/Directpost.php    (revision a0dade4d8bc15b651d8b1ea0e7e4e3580fb1d3ae)
--- vendor/magento/module-authorizenet/Model/Directpost.php    (revision 01fbfeba9bd743266199e30260376a9c1b95fbf5)

and they become this;

Index: Model/Directpost.php
+++ Model/Directpost.php   (revision a0dade4d8bc15b651d8b1ea0e7e4e3580fb1d3ae)
--- Model/Directpost.php   (revision 01fbfeba9bd743266199e30260376a9c1b95fbf5)

after the text replacement.

0
0

You just can install Cweagans Composer Patches using this command below:

composer require cweagans/composer-patches

then add this snippet in your composer.json file inside the extra node:

"extra": {
        ...
        "patches": {
            "magento/module-authorizenet": {
                "Authorizenet-MD5": "m2-hotfixes/Auth.net.md5.composer-2019-02-27-11-51-12.patch"
            }
        }
    }

And create this patch file in a folder m2-hotfixes, it will be like this:

m2-hotfixes/Auth.net.md5.composer-2019-02-27-11-51-12.patch

The content of this file will be:

Index: vendor/magento/module-authorizenet/Model/Directpost.php
<+>UTF-8
===================================================================
--- a/vendor/magento/module-authorizenet/Model/Directpost.php   (revision 01fbfeba9bd743266199e30260376a9c1b95fbf5)
+++ b/vendor/magento/module-authorizenet/Model/Directpost.php   (revision a0dade4d8bc15b651d8b1ea0e7e4e3580fb1d3ae)
@@ -531,15 +531,16 @@
     public function validateResponse()
     {
         $response = $this->getResponse();
-        //md5 check
-        if (!$this->getConfigData('trans_md5')
-            || !$this->getConfigData('login')
-            || !$response->isValidHash($this->getConfigData('trans_md5'), $this->getConfigData('login'))
+        $hashConfigKey = !empty($response->getData('x_SHA2_Hash')) ? 'signature_key' : 'trans_md5';
+
+        //hash check
+        if (!$response->isValidHash($this->getConfigData($hashConfigKey), $this->getConfigData('login'))
         ) {
             throw new \Magento\Framework\Exception\LocalizedException(
                 __('The transaction was declined because the response hash validation failed.')
             );
         }
+
         return true;
     }

Index: vendor/magento/module-authorizenet/Model/Directpost/Request.php
<+>UTF-8
===================================================================
--- a/vendor/magento/module-authorizenet/Model/Directpost/Request.php   (revision 01fbfeba9bd743266199e30260376a9c1b95fbf5)
+++ b/vendor/magento/module-authorizenet/Model/Directpost/Request.php   (revision a0dade4d8bc15b651d8b1ea0e7e4e3580fb1d3ae)
@@ -7,6 +7,7 @@
 namespace Magento\Authorizenet\Model\Directpost;

 use Magento\Authorizenet\Model\Request as AuthorizenetRequest;
+use Magento\Framework\Intl\DateTimeFactory;

 /**
  * Authorize.net request model for DirectPost model
@@ -18,9 +19,33 @@
      */
     protected $_transKey = null;

+    /**
+     * Hexadecimal signature key.
+     *
+     * @var string
+     */
+    private $signatureKey = '';
+
+    /**
+     * @var DateTimeFactory
+     */
+    private $dateTimeFactory;
+
+    /**
+     * @param DateTimeFactory $dateTimeFactory
+     * @param array $data
+     */
+    public function __construct(
+        DateTimeFactory $dateTimeFactory,
+        array $data = []
+    ) {
+        $this->dateTimeFactory = $dateTimeFactory;
+        parent::__construct($data);
+    }
+
     /**
      * Return merchant transaction key.
-     * Needed to generate sign.
+     * Needed to generate MD5 sign.
      *
      * @return string
      */
@@ -31,7 +56,7 @@

     /**
      * Set merchant transaction key.
-     * Needed to generate sign.
+     * Needed to generate MD5 sign.
      *
      * @param string $transKey
      * @return $this
@@ -43,7 +68,7 @@
     }

     /**
-     * Generates the fingerprint for request.
+     * Generates the MD5 fingerprint for request.
      *
      * @param string $merchantApiLoginId
      * @param string $merchantTransactionKey
@@ -63,7 +88,7 @@
     ) {
         return hash_hmac(
             "md5",
-            $merchantApiLoginId . "^" . $fpSequence . "^" . $fpTimestamp . "^" . $amount . "^" . $currencyCode,
+            $merchantApiLoginId . '^' . $fpSequence . '^' . $fpTimestamp . '^' . $amount . '^' . $currencyCode,
             $merchantTransactionKey
         );
     }
@@ -85,6 +110,7 @@
             ->setXRelayUrl($paymentMethod->getRelayUrl());

         $this->_setTransactionKey($paymentMethod->getConfigData('trans_key'));
+        $this->setSignatureKey($paymentMethod->getConfigData('signature_key'));
         return $this;
     }

@@ -168,17 +194,81 @@
      */
     public function signRequestData()
     {
-        $fpTimestamp = time();
-        $hash = $this->generateRequestSign(
-            $this->getXLogin(),
-            $this->_getTransactionKey(),
-            $this->getXAmount(),
-            $this->getXCurrencyCode(),
-            $this->getXFpSequence(),
-            $fpTimestamp
-        );
+        $fpDate = $this->dateTimeFactory->create('now', new \DateTimeZone('UTC'));
+        $fpTimestamp = $fpDate->getTimestamp();
+
+        if (!empty($this->getSignatureKey())) {
+            $hash = $this->generateSha2RequestSign(
+                $this->getXLogin(),
+                $this->getSignatureKey(),
+                $this->getXAmount(),
+                $this->getXCurrencyCode(),
+                $this->getXFpSequence(),
+                $fpTimestamp
+            );
+        } else {
+            $hash = $this->generateRequestSign(
+                $this->getXLogin(),
+                $this->_getTransactionKey(),
+                $this->getXAmount(),
+                $this->getXCurrencyCode(),
+                $this->getXFpSequence(),
+                $fpTimestamp
+            );
+        }
+
         $this->setXFpTimestamp($fpTimestamp);
         $this->setXFpHash($hash);
+
         return $this;
     }
+
+    /**
+     * Generates the SHA2 fingerprint for request.
+     *
+     * @param string $merchantApiLoginId
+     * @param string $merchantSignatureKey
+     * @param string $amount
+     * @param string $currencyCode
+     * @param string $fpSequence An invoice number or random number.
+     * @param string $fpTimestamp
+     * @return string The fingerprint.
+     */
+    private function generateSha2RequestSign(
+        $merchantApiLoginId,
+        $merchantSignatureKey,
+        $amount,
+        $currencyCode,
+        $fpSequence,
+        $fpTimestamp
+    ): string {
+        $message = $merchantApiLoginId . '^' . $fpSequence . '^' . $fpTimestamp . '^' . $amount . '^' . $currencyCode;
+
+        return strtoupper(hash_hmac('sha512', $message, pack('H*', $merchantSignatureKey)));
+    }
+
+    /**
+     * Return merchant hexadecimal signature key.
+     *
+     * Needed to generate SHA2 sign.
+     *
+     * @return string
+     */
+    private function getSignatureKey(): string
+    {
+        return $this->signatureKey;
+    }
+
+    /**
+     * Set merchant hexadecimal signature key.
+     *
+     * Needed to generate SHA2 sign.
+     *
+     * @param string $signatureKey
+     * @return void
+     */
+    private function setSignatureKey(string $signatureKey)
+    {
+        $this->signatureKey = $signatureKey;
+    }
 }
Index: vendor/magento/module-authorizenet/Model/Directpost/Response.php
IDEA additional info:
Subsystem: com.intellij.openapi.diff.impl.patch.CharsetEP
<+>UTF-8
===================================================================
--- a/vendor/magento/module-authorizenet/Model/Directpost/Response.php  (revision 01fbfeba9bd743266199e30260376a9c1b95fbf5)
+++ b/vendor/magento/module-authorizenet/Model/Directpost/Response.php  (revision a0dade4d8bc15b651d8b1ea0e7e4e3580fb1d3ae)
@@ -24,27 +24,33 @@
      */
     public function generateHash($merchantMd5, $merchantApiLogin, $amount, $transactionId)
     {
-        if (!$amount) {
-            $amount = '0.00';
-        }
-
         return strtoupper(md5($merchantMd5 . $merchantApiLogin . $transactionId . $amount));
     }

     /**
      * Return if is valid order id.
      *
-     * @param string $merchantMd5
+     * @param string $storedHash
      * @param string $merchantApiLogin
      * @return bool
      */
-    public function isValidHash($merchantMd5, $merchantApiLogin)
+    public function isValidHash($storedHash, $merchantApiLogin)
     {
-        $hash = $this->generateHash($merchantMd5, $merchantApiLogin, $this->getXAmount(), $this->getXTransId());
+        if (empty($this->getData('x_amount'))) {
+            $this->setData('x_amount', '0.00');
+        }

-        return Security::compareStrings($hash, $this->getData('x_MD5_Hash'));
-    }
+        if (!empty($this->getData('x_SHA2_Hash'))) {
+            $hash = $this->generateSha2Hash($storedHash);
+            return Security::compareStrings($hash, $this->getData('x_SHA2_Hash'));
+        } elseif (!empty($this->getData('x_MD5_Hash'))) {
+            $hash = $this->generateHash($storedHash, $merchantApiLogin, $this->getXAmount(), $this->getXTransId());
+            return Security::compareStrings($hash, $this->getData('x_MD5_Hash'));
+        }

+        return false;
+    }
+
     /**
      * Return if this is approved response from Authorize.net auth request.
      *
@@ -54,4 +60,54 @@
     {
         return $this->getXResponseCode() == \Magento\Authorizenet\Model\Directpost::RESPONSE_CODE_APPROVED;
     }
+
+    /**
+     * Generates an SHA2 hash to compare against AuthNet's.
+     *
+     * @param string $signatureKey
+     * @return string
+     * @see https://support.authorize.net/s/article/MD5-Hash-End-of-Life-Signature-Key-Replacement
+     */
+    private function generateSha2Hash(string $signatureKey): string
+    {
+        $hashFields = [
+            'x_trans_id',
+            'x_test_request',
+            'x_response_code',
+            'x_auth_code',
+            'x_cvv2_resp_code',
+            'x_cavv_response',
+            'x_avs_code',
+            'x_method',
+            'x_account_number',
+            'x_amount',
+            'x_company',
+            'x_first_name',
+            'x_last_name',
+            'x_address',
+            'x_city',
+            'x_state',
+            'x_zip',
+            'x_country',
+            'x_phone',
+            'x_fax',
+            'x_email',
+            'x_ship_to_company',
+            'x_ship_to_first_name',
+            'x_ship_to_last_name',
+            'x_ship_to_address',
+            'x_ship_to_city',
+            'x_ship_to_state',
+            'x_ship_to_zip',
+            'x_ship_to_country',
+            'x_invoice_num',
+        ];
+
+        $message = '^';
+        foreach ($hashFields as $field) {
+            $message .= ($this->getData($field) ?? '') . '^';
+        }
+
+        return strtoupper(hash_hmac('sha512', $message, pack('H*', $signatureKey)));
+    }
 }
Index: vendor/magento/module-authorizenet/etc/adminhtml/system.xml
IDEA additional info:
Subsystem: com.intellij.openapi.diff.impl.patch.CharsetEP
<+>UTF-8
===================================================================
--- a/vendor/magento/module-authorizenet/etc/adminhtml/system.xml   (revision 01fbfeba9bd743266199e30260376a9c1b95fbf5)
+++ b/vendor/magento/module-authorizenet/etc/adminhtml/system.xml   (revision a0dade4d8bc15b651d8b1ea0e7e4e3580fb1d3ae)
@@ -29,6 +29,10 @@
                     <label>Transaction Key</label>
                     <backend_model>Magento\Config\Model\Config\Backend\Encrypted</backend_model>
                 </field>
+                <field id="signature_key" translate="label" type="obscure" sortOrder="55" showInDefault="1" showInWebsite="1" showInStore="0">
+                    <label>Signature Key</label>
+                    <backend_model>Magento\Config\Model\Config\Backend\Encrypted</backend_model>
+                </field>
                 <field id="trans_md5" translate="label" type="obscure" sortOrder="60" showInDefault="1" showInWebsite="1" showInStore="0">
                     <label>Merchant MD5</label>
                     <backend_model>Magento\Config\Model\Config\Backend\Encrypted</backend_model>
Index: vendor/magento/module-authorizenet/etc/config.xml
IDEA additional info:
Subsystem: com.intellij.openapi.diff.impl.patch.CharsetEP
<+>UTF-8
===================================================================
--- a/vendor/magento/module-authorizenet/etc/config.xml (revision 01fbfeba9bd743266199e30260376a9c1b95fbf5)
+++ b/vendor/magento/module-authorizenet/etc/config.xml (revision a0dade4d8bc15b651d8b1ea0e7e4e3580fb1d3ae)
@@ -22,6 +22,7 @@
                 <title>Credit Card Direct Post (Authorize.net)</title>
                 <trans_key backend_model="Magento\Config\Model\Config\Backend\Encrypted" />
                 <trans_md5 backend_model="Magento\Config\Model\Config\Backend\Encrypted" />
+                <signature_key backend_model="Magento\Config\Model\Config\Backend\Encrypted" />
                 <allowspecific>0</allowspecific>
                 <currency>USD</currency>
                 <create_order_before>1</create_order_before>

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge that you have read and understand our privacy policy and code of conduct.

Not the answer you're looking for? Browse other questions tagged or ask your own question.