Authorize.net has a fraud detection suite. Its filters can perform certain checks (e.g. billing address check, CVV check etc) on the transaction. The authorize.net UI allows selecting one of 4 possibilities on how to react in case the filter detects fraud. These are:

  1. Process as normal and report filter(s) triggered
  2. Authorize and hold for review.
  3. Do not authorize, but hold for review.
  4. Declined

In case 1. the drupal payment should be authorized (and captured, if the payment gateway setting says so). The response message code is 1.
In case 2. the drupal payment should be only authorized, no matter what the payment gateway setting is. The response message code is 253.
In case 3. the drupal payment should stay in status 'new'. The response message code is 252.
In case 4. no payment should be created on the drupal side. The response message code is 251.

Comments

czigor created an issue. See original summary.

czigor’s picture

Status: Active » Needs review
StatusFileSize
new1.38 KB
mglaman’s picture

+++ b/src/Plugin/Commerce/PaymentGateway/AcceptJs.php
@@ -327,7 +327,17 @@ class AcceptJs extends OnsiteBase implements SupportsRefundsInterface, SupportsU
+    // 252 means "Do not authorize, but hold for review" if the fraud detection
+    // result is positive.
+    elseif ($code == 252) {
+      $next_state = 'new';
+    }

We're going to need a "hold" state in Commerce itself. It's not a new transaction but in a transitionary status.

It's also a non-Authnet problem, as Braintree has Kount integration for fruad.

bojanz’s picture

StatusFileSize
new4.4 KB

Uploading patch provided by mglaman. Review to follow.

bojanz’s picture

Status: Needs review » Needs work
+payment_fraud:
+  id: payment_fraud

The name of the workflow is too generic, it would conflict with a similarly-intentioned workflow in a different module.
When the payment type and workflow are custom for a payment gateway, we should name them after the gateway.
In this case, payment_acceptjs, or payment_authnet (if usable on multiple authnet gateway plugins).

+    review:
+      label: 'Unauthorized (Needs Review)'
+    authorization:
+      label: 'Authorization'
+    authorization_voided:
+      label: 'Authorization (Voided)'
+    authorization_expired:
+      label: 'Authorization (Expired)'
+    authorization_review:
+      label: 'Authorization (Needs Review)'
+    completed:
+      label: 'Completed'

So, we have "review" meaning "results in authorization" and "authorization_review" meaning "results in a completed payment".
I was initially confused by this, but have no better alternative. "Unauthorized but flagged for review" still feels like an unnatural state to have on the remote side.

  needs_review:
      label: 'Needs review'
      from: [new]
      to: review
    authorization_needs_review:
      label: 'Authorization needs review'
      from: [new, authorization]
      to: authorization_review
    void:
      label: 'Void payment'
      from: [authorization, authorization_review, review]
      to: authorization_voided

We have no success transitions.

+  public function buildPaymentOperations(PaymentInterface $payment) {
+    // @todo Support handling review states.
+    return parent::buildPaymentOperations($payment);
+  }

We need to allow "void" for in-review payments, and to add a custom "approve" operation which calls the matching gateway method.

bojanz’s picture

I see that our initial spec called for:

review_unauthorized: this will need a transition to Authorized (and perform authorization) if the merchant decides it is OK, otherwise a "void" which just cancels the transaction
review_authorized: this will need a transition to "authorize_capture", which is like the normal flow. Or otherwise the normal "void" flow which cancels the transaction.

Maybe this makes more sense? Worth bikeshedding

bojanz’s picture

Bikeshedding results:
We agreed that the workflow should be "payment_acceptjs", the payment type should be "acceptjs". The "review" state should become "unauthorized_review" to match its label.

czigor’s picture

StatusFileSize
new11.28 KB

A patch updating the void and adding the approve payment operation. It's untested, don't know how to achieve these states with cardinal and authnet, since their test credit card numbers do not overlap. Naming has not been fixed.

bojanz’s picture

Status: Needs work » Needs review
StatusFileSize
new11.41 KB

This patch adds the renames mentioned in #7.

  • bojanz committed 919397e on 8.x-1.x
    Issue #2985568 by bojanz, czigor: Fraud handling
    
bojanz’s picture

Status: Needs review » Fixed

Rebuilt the patch, committed.

Status: Fixed » Closed (fixed)

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