Comments

mglaman created an issue. See original summary.

mglaman’s picture

Status: Active » Needs work
StatusFileSize
new24.15 KB

Proof of concept backport. Basics work with minor testing.

TynanFox’s picture

My site uses a payment processor that utilizes Gateway Emulation of Authorize.net. To make it work with this, I'm changing the variables noted in my settings file as noted here. Does modifying these variables still work when using this patch/using Accept.js?

mglaman’s picture

Does modifying these variables still work when using this patch/using Accept.js?

It is not modifying the existing payment method. It is adding a new one, so emulators need not worry.

drumm’s picture

Issue tags: +affects drupal.org

This seems to be working well so far.

I did add a bit of CSS to put all the credit card fields inline, but that’s easily handled in the theme:

#edit-commerce-payment-payment-details-acceptjs-cc .form-wrapper, #edit-commerce-payment-payment-details-acceptjs-cc .form-item {
  display: inline-block;
  margin-right: .25em;
}
drumm’s picture

Test cards seem to be declined, but record as a successful payment. Here is an example payload:

Array
(
    […] => {"transactionResponse":{"responseCode":"2","authCode":"","avsResultCode":"B","cvvResultCode":"","cavvResultCode":"","transId":"…","refTransID":"","transHash":"…","testRequest":"0","accountNumber":"XXXX1111","accountType":"Visa","errors":[{"errorCode":"2","errorText":"This transaction has been declined."}],"transHashSha2":""},"refId":"…","messages":{"resultCode":"Ok","message":[{"code":"I00001","text":"Successful."}]}}
)
drumm’s picture

The customer name & address are also not being populated in Authorize.net

ericchew’s picture

StatusFileSize
new27.68 KB
new6.25 KB

Here is a patch that fixes a few things (FYI I am only testing in the ADMIN area, someone else will need to test cart.)

  • Show authnet_acceptjs as the payment method instead of authnet_aim in the transaction entity
  • Add authnet_acceptjs to access checks so that views operation links work
  • Add authnet_acceptjs to form alter so that admins can choose auth or capture in payment terminal (select list)
  • Add remote_status to the transaction so that views operation links work
  • Add response message to the transaction
  • Correct the transaction remote_id...it was set to some crazy long string returned from the result...not sure if this was intentional

Card on file needs work, can't add them in admin UI or select them in payment terminal.

ericchew’s picture

StatusFileSize
new40.24 KB
new18.38 KB

This patch adds Card On File capabilities.

Notes:

  • In commerce_authnet.acceptjs.inc I had to rename form elements from $form['acceptjs'] to $form['credit_card'], otherwise card on file would not hide the credit card form when a card on file was selected in payment terminal.
  • As pointed out in #7, address, order, and user info is not sent when doing a transaction for cards that ARENT on file.
  • There is an issue for cards on file where the selected transaction type (Authorize Only or Authorize and Capture) is not considered...seems to always use the default for the payment rule. Should be easy fix, I just don't have time to look into it yet and wanted to get this patch up for others.
ericchew’s picture

StatusFileSize
new40.59 KB
new5.76 KB
  • Add billing/shipping info for non-cardonfile transactions
  • Form data for card is different than CIM, so had to add custom submit handler

One thing I notice is that if you create a card on file, then delete a card on file (so there are no more cards on file for the customer), then try to create a new card on file..you get "Error: Invalid OTS Token". I'm guessing this is because it is assuming there is a payment profile from a previous card.

ericchew’s picture

StatusFileSize
new51.84 KB
new12.78 KB

Should be working in the cart now with this patch. Had to create custom submit handler for new cards to be able to pass opaqueData instead of creditCard. You'll notice I didnt spend any time trying to make this code pretty, so feel free to refactor if you want!

The Error: Invalid OTS Token still remains if you delete all cards for a customer and try to add another. If you delete the customer profile altogether (via authorize.net site), it fixes the issue. Maybe when deleteing card we can check to see if it is the last card on file, and if so delete the customer profile?

ericchew’s picture

StatusFileSize
new51.87 KB
new573 bytes

Forgot to remove a variable I no longer used.

mglaman’s picture

mglaman’s picture

Assigned: mglaman » Unassigned

ericchew thanks so much. I'm going to tackle the "Invalid OTS Token" error.

mglaman’s picture

Status: Needs work » Needs review
StatusFileSize
new9.81 KB
new50.08 KB

This backports the profile creation logic from D8 to handle Accept.js and invalid tokens.

mglaman’s picture

+++ b/js/commerce_authnet.form.js
@@ -0,0 +1,48 @@
+      var $form = $('.acceptjs-form').closest('form');
+      $form.removeOnce('acceptjs-processed');
+      $form.off('submit.authnet');
+      debugger;

Debugging line, and invalid jQuery for what ships with core.

mglaman’s picture

StatusFileSize
new50.09 KB

Fixed jQuery

Interdiff:

diff --git a/js/commerce_authnet.form.js b/js/commerce_authnet.form.js
index fa91351..5b28c90 100644
--- a/js/commerce_authnet.form.js
+++ b/js/commerce_authnet.form.js
@@ -22,7 +22,7 @@
     detach: function (context, settings) {
       var $form = $('.acceptjs-form').closest('form');
       $form.removeOnce('acceptjs-processed');
-      $form.off('submit.authnet');
+      $form.unbind('submit.authnet');
       debugger;
     }
   };
mglaman’s picture

StatusFileSize
new58.07 KB

I also hit another quirk. If there is an error the submit button is still disabled and the loading gif keeps on spinning.

mglaman’s picture

StatusFileSize
new50.45 KB

Fixes unable to go back on error (or at all.)

diff --git a/js/commerce_authnet.form.js b/js/commerce_authnet.form.js
index 5b28c90..c0038c3 100644
--- a/js/commerce_authnet.form.js
+++ b/js/commerce_authnet.form.js
@@ -18,12 +18,19 @@
       // else if (authnetSettings.paymentMethodType === 'authnet_echeck') {
       //  Drupal.commerceAuthorizeNetEcheckForm($form, authnetSettings);
       // }
+
+      // AcceptJS hijacks all submit buttons for this form. Simulate the back
+      // button to make sure back submit still works.
+      $('.checkout-cancel, .checkout-back').bind('mousedown, click', function(e) {
+        debugger;
+        e.preventDefault();
+        window.history.back();
+      });
     },
     detach: function (context, settings) {
       var $form = $('.acceptjs-form').closest('form');
       $form.removeOnce('acceptjs-processed');
       $form.unbind('submit.authnet');
-      debugger;
     }
   };
   Drupal.commerceAuthorizeNet = {
mglaman’s picture

StatusFileSize
new49.19 KB
new12.98 KB

Here's an attempt to fix duplicates in card on file / admin terminal scenario.

mglaman’s picture

Status: Needs review » Needs work

When using the card 4111111111111111 with zip code 46282 the General bank decline workflow is triggered.

However checkout completes, and the order's payment transaction shows success even though:

{
  "transactionResponse": {
    "responseCode": "2",
    "authCode": "",
    "avsResultCode": "Y",
    "cvvResultCode": "P",
    "cavvResultCode": "2",
    "transId": "60103295060",
    "refTransID": "",
    "transHash": "AD657D03593ADA3A3A8702A6D0019126",
    "testRequest": "0",
    "accountNumber": "XXXX1111",
    "accountType": "Visa",
    "errors": [
      {
        "errorCode": "2",
        "errorText": "This transaction has been declined."
      }
    ],
    "transHashSha2": ""
  },
  "refId": "ref1526327925",
  "messages": {
    "resultCode": "Ok",
    "message": [
      {
        "code": "I00001",
        "text": "Successful."
      }
    ]
  }
}
mglaman’s picture

Status: Needs work » Needs review
StatusFileSize
new50 KB

Fix the handling.

Interdiff:

diff --git a/includes/commerce_authnet.acceptjs.inc b/includes/commerce_authnet.acceptjs.inc
index f04ef6d..49cbbd9 100644
--- a/includes/commerce_authnet.acceptjs.inc
+++ b/includes/commerce_authnet.acceptjs.inc
@@ -265,6 +265,24 @@ function commerce_authnet_acceptjs_submit_form_submit($payment_method, $pane_for
     commerce_payment_transaction_save($transaction);
     return FALSE;
   }
+  elseif (!empty($result['transactionResponse']['errors'])) {
+    $transaction->status = COMMERCE_PAYMENT_STATUS_FAILURE;
+    $transaction_message = array();
+    foreach ($result['transactionResponse']['errors'] as $message) {
+      $transaction_message[] = t('Authorize.net error: @code - @error', array(
+        '@code' => $message['errorCode'],
+        '@error' => $message['errorText'],
+      ));
+      watchdog('commerce_authnet', 'Authorize.net error: @code - @error', array(
+        '@code' => $message['errorCode'],
+        '@error' => $message['errorText'],
+      ), WATCHDOG_ERROR);
+      $transaction->message = implode('<br />', $transaction_message);
+      drupal_set_message(check_plain($message['errorText']), 'error');
+    }
+    commerce_payment_transaction_save($transaction);
+    return FALSE;
+  }
 
   // Set the transaction status based on the type of transaction this was.
   switch ($payment_method['settings']['txn_type']) {

mglaman’s picture

Clean up the files.

drumm’s picture

StatusFileSize
new49.93 KB

This is the same patch as #22, but without the debugger; statements.

drumm’s picture

I can confirm what I spotted in #6-7 looks all good now.

mglaman’s picture

+++ b/includes/commerce_authnet.acceptjs.inc
@@ -0,0 +1,736 @@
+  if (!empty($order)) {
+    if (isset($order->commerce_customer_billing)) {
+      $request['createTransactionRequest']['transactionRequest']['billTo'] = commerce_authnet_cim_billto_array($order);
+    }
+    if (isset($order->commerce_customer_shipping)) {
+      $request['createTransactionRequest']['transactionRequest']['shipTo'] = commerce_authnet_cim_shipto_array($order);
+    }
+  }

I think the only thing we are missing from the AIM gateway is:

* Invoice num
* Email
* Customer ID
* Customer IP

  // Add additional transaction invormation to the request array.
  $nvp += array(
    // Order Information
    'x_invoice_num' => $order->order_number,
    'x_description' => substr(implode(', ', $description), 0, 255),

    // Customer Information
    'x_email' => substr($order->mail, 0, 255),
    'x_cust_id' => substr($order->uid, 0, 20),
    'x_customer_ip' => substr(ip_address(), 0, 15),
  );
drumm’s picture

StatusFileSize
new51.25 KB
new2.14 KB

This patch adds the order number, line items, and customer ID, email, and IP.

drumm’s picture

The error handling may need to be improved. When testing with rejected API requests, there were the good commerce_authnet watchdog messages like

Authorize.net error: E00003 - The element 'lineItem' in namespace 'AnetApi/xml/v1/schema/AnetApiSchema.xsd' has invalid child element 'quantity' in namespace 'AnetApi/xml/v1/schema/AnetApiSchema.xsd'. List of possible elements expected: 'name' in namespace 'AnetApi/xml/v1/schema/AnetApiSchema.xsd'.

But also some noisy php watchdog messages:

Notice: Undefined index: transactionResponse in commerce_authnet_acceptjs_submit_form_submit() (line 267 of /var/www/dev/acceptjs-jobs.private.devdrupal.org/htdocs/sites/all/modules/commerce_authnet/includes/commerce_authnet.acceptjs.inc).

drumm’s picture

StatusFileSize
new51.62 KB
new3.33 KB

This version of the patch:

  • Adds the order description matching the old Authorize.net transactions. Keeps things consistent for accounting.
  • Downgrades some new array syntax.
  • Removes spaces in the card number to be friendlier.
mglaman’s picture

Status: Needs review » Reviewed & tested by the community

Let's commit this. I discussed with drumm, and this looks to be solid! Thanks a lot. We can handle any nits in follow ups.

  • mglaman committed d9d803b on 7.x-1.x authored by drumm
    Issue #2941743 by mglaman, ericchew, drumm: Backport Accept.js support...
mglaman’s picture

Status: Reviewed & tested by the community » Fixed

Yay! Glad to see this in.

Status: Fixed » Closed (fixed)

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

tonytheferg’s picture

Should we be able to Limit accepted credit cards to the following types: with accept.js? Should i open a new issue for this?

tonytheferg’s picture

Also, I noticed something in testing:
If there is a typo (wrong CVV for example) It will decline as it should, but when the typo is fixed, and the card resubmitted, the checkout screen is refreshed with no message, and there is this notice in the log:
Authorize.net error: E00027 - The transaction was unsuccessful.

According to this, it's a duplicate transaction error. It seems this resolves/refreshes after a couple of minutes. This seems to be common behavior for Authorize.net, (see here) So maybe the default "this transaction has been declined" message should include "please allow 3 minutes to prevent duplicate transactions" (or whatever)

jaimeah’s picture

Thank you for adding accept.js support for Drupal 7. Any plans for the acceptui.js hosted form variant?