Skip to content

Authorize.Net optional fields are not optional #181

@ghost

Description

Documentation labels the opts as optional but if you try to submit without them you get an error.

iex> amount = Money.new(20, :USD)
iex> card = %CreditCard{number: "5424000000000015", year: 2099, month: 12, verification_code: "999"}
iex> result = Gringotts.purchase(Gringotts.Gateways.AuthorizeNet, amount, card, [])

{:error,
 %{
   __struct__: Gringotts.Response,
   authorization: nil,
   avs_result: nil,
   cvc_result: nil,
   error_code: nil,
   fraud_review: nil,
   message: nil,
   params: nil,
   raw: %{
     "ErrorResponse" => %{
       "messages" => %{
         "message" => %{
           "code" => "E00003",
           "text" => "The 'AnetApi/xml/v1/schema/AnetApiSchema.xsd:itemId' element is invalid - The value '' is invalid according to its datatype 'String' - The actual length is less than the MinLength value." 
         },
         "resultCode" => "Error"
       }
     }
   },
   status_code: nil,
   success: false
 }}

When I look at the payload in Gateways.AuthorizeNet.commit/3 it looks like the opts are included as blanks anyway. I believe this is throwing a bug on Authorize.Net's end where when they see the "lineItems" node they expect a "lineItem" with a "itemId" with length greater than 0.

pry(2)> XmlToMap.naive_map(payload)
%{
  "createTransactionRequest" => %{
    "merchantAuthentication" => %{
      "name" => "6X3g9dVnZ",
      "transactionKey" => "8eP2Jc7SA7a3h3Gy"
    },
    "refId" => %{},
    "transactionRequest" => %{
      "amount" => "5",
      "billTo" => %{
        "address" => %{},
        "city" => %{},
        "company" => %{},
        "country" => %{},
        "firstName" => %{},
        "lastName" => %{},
        "state" => %{},
        "zip" => %{}
      },
      "customer" => %{"id" => %{}},
      "customerIP" => %{},
      "duty" => %{"amount" => "0", "description" => %{}, "name" => %{}},
      "lineItems" => %{
        "lineItem" => %{
          "description" => %{},
          "itemId" => %{},
          "name" => %{},
          "quantity" => %{},
          "unitPrice" => %{}
        }
      },
      "order" => %{"description" => %{}, "invoiceNumber" => %{}},
      "payment" => %{
        "creditCard" => %{
          "cardCode" => "999",
          "cardNumber" => "5424000000000015",
          "expirationDate" => "2020-12"
        }
      },
      "poNumber" => %{},
      "shipTo" => %{
        "address" => %{},
        "city" => %{},
        "company" => %{},
        "country" => %{},
        "firstName" => %{},
        "lastName" => %{},
        "state" => %{},
        "zip" => %{}
      },
      "shipping" => %{"amount" => "0", "description" => %{}, "name" => %{}},
      "tax" => %{"amount" => "0", "description" => %{}, "name" => %{}},
      "transactionType" => "authOnlyTransaction"
    }
  }
}

I tested this structure:

<createTransactionRequest xmlns="AnetApi/xml/v1/schema/AnetApiSchema.xsd">
  <merchantAuthentication>
    <name>78BZ5Xprry</name>
    <transactionKey>8s2F95Q7brhHd7Tn</transactionKey>
  </merchantAuthentication>
  <transactionRequest>
    <transactionType>authCaptureTransaction</transactionType>
    <amount>5</amount>
    <payment>
      <creditCard>
        <cardNumber>5424000000000015</cardNumber>
        <expirationDate>2020-12</expirationDate>
        <cardCode>999</cardCode>
      </creditCard>
    </payment>
    <order>
     <invoiceNumber>INV-12345</invoiceNumber>
     <description>Product Description</description>
    </order>
  </transactionRequest>
</createTransactionRequest>

on Authorize.Net's API reference and I got a successful response, so it doesn't seem necessary to include all the blank options in the request if there happen to be no options included. May I suggest only submitting opts that the user submits in the call to Gringotts.purchase as a solution to this problem?

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Type

    No type

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions