1

I'm in the process of implementing Netbanx as a payment gateway using the Omnipay PHP library, but I'm having an issues with errors relating to "Node: state" and "Node: country" strings being less than the minLength facet.

Note: I'm using the test credentials provided to me when registering for a developer account at Netbanx, and test CC details listed in their documentation here: docs.

Here is a code snippet from my Payment class:

class NetbanxPayment
{
    /**
     * Initialize payment gateway.
     *
     * @param string $accountNumber
     * @param string $storeId
     * @param string $storePassword
     * @param bool   $testMode
     */
    public function __construct($accountNumber, $storeId, $storePassword, $testMode = false)
    {
        $omnipay = new Omnipay;

        $this->gateway = $omnipay->create('NetBanx');

        $this->gateway->setAccountNumber($accountNumber);
        $this->gateway->setStoreId($storeId);
        $this->gateway->setStorePassword($storePassword);
        $this->gateway->setTestMode($testMode);
    }

    /**
     * Handle making the purchase
     *
     * @param       $amount
     * @param array $data
     *
     * @return \AwardForce\Modules\Payments\Contracts\Response
     */
    public function purchase($amount, $data = [])
    {
        $card = new CreditCard();

        $card->setNumber(array_get($data, 'cardNumber', ''));
        $card->setExpiryMonth(array_get($data, 'expiryMonth', ''));
        $card->setExpiryYear(array_get($data, 'expiryYear', ''));
        $card->setCvv(array_get($data, 'cvv', null));
        $card->setBillingAddress1(array_get($data, 'street', ''));
        $card->setBillingCity(array_get($data, 'city', ''));
        $card->setBillingPostcode(array_get($data, 'postcode', ''));
        if (array_get($data, 'country', '') == 'US') {
            $card->setBillingState(array_get($data, 'region', ''));
        }
        $card->setBillingCountry(array_get($data, 'country', ''));

        $response = $this->gateway->purchase([
            'amount'   => $amount,
            'currency' => $this->getCurrency(),
            'card'     => $card
        ])->send();

        dd($response);
     }
}

Here is the dumped response with the errors I'm seeing:

Response {#1404 ▼
  #data: SimpleXMLElement {#1405 ▼
    +"confirmationNumber": "329008300"
    +"decision": "ERROR"
    +"code": "5023"
    +"actionCode": "M"
    +"description": "You submitted a request that is not parseable."
    +"detail": array:4 [▼
      0 => SimpleXMLElement {#1400 ▼
        +"tag": "InternalResponseCode"
        +"value": "24"
      }
      1 => SimpleXMLElement {#1399 ▶}
      2 => SimpleXMLElement {#1398 ▶}
      3 => SimpleXMLElement {#1395 ▼
        +"tag": "ErrorDetail"
        +"value": """
          \n
          Errors: \n
            Node: state, Detail: string length (0) is less than minLength facet (2) for StateV1 in namespace http://www.optimalpayments.com/creditcard/xmlschema/v1\n
            Node: state, Detail: string length (0) is less than minLength facet (2) for StateV1 in namespace http://www.optimalpayments.com/creditcard/xmlschema/v1\n
            Node: country, Detail: string length (0) is less than minLength facet (2) for CountryV1 in namespace http://www.optimalpayments.com/creditcard/xmlschema/v1\n
          """
      }
    ]
    +"txnTime": "2015-10-12T21:20:59.661-04:00"
    +"duplicateFound": "false"
  }
}

Here's the formatted XML data being sent to Netbanx:

<?xml version="1.0" encoding="UTF-8"?>
<ccAuthRequestV1 xmlns="http://www.optimalpayments.com/creditcard/xmlschema/v1" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://www.optimalpayments.com/creditcard/xmlschema/v1">
    <merchantAccount>
        <accountNum>********</accountNum>
        <storeID>********</storeID>
        <storePwd />
    </merchantAccount>
    <merchantRefNum>********</merchantRefNum>
    <amount>1.10</amount>
    <card>
        <cardNum>4111111111111111</cardNum>
        <cardExpiry>
            <month>11</month>
            <year>2019</year>
        </cardExpiry>
        <cardType>VI</cardType>
        <cvdIndicator>1</cvdIndicator>
        <cvd>123</cvd>
    </card>
    <billingDetails>
        <cardPayMethod>WEB</cardPayMethod>
        <firstName />
        <lastName />
        <street>123 Some St</street>
        <street2 />
        <city>City</city>
        <state />
        <country>GB</country>
        <zip>1234</zip>
        <phone />
        <email />
    </billingDetails>
</ccAuthRequestV1>

Any help, advice or pointers in the right direction as to what might be causing these issues would be greatly appreciated :)

JasonMortonNZ
  • 3,752
  • 8
  • 34
  • 56
  • Have you verified that state and country are actually being passed through correctly? The error means empty strings are being passed through to the payment gateway, array_get defaults to an empty string if it can't find the key you specify so that may be it. – Tim Sheehan Oct 13 '15 at 01:46
  • G'day Tim, I thought I recognised the 'Dontfeedthecode' handle :) I just ran a test and hard coded the values in for state & country, and now I only getting 2 of the 3 original error messages - one for state and one for country. – JasonMortonNZ Oct 13 '15 at 01:53
  • Small world mate haha, hang on I'll write what I've found up in an answer for you. – Tim Sheehan Oct 13 '15 at 02:02
  • Sweet, cheers mate :) – JasonMortonNZ Oct 13 '15 at 02:03
  • Just to add to my answer, if that does end up being the issue you may need to fix the rest of the card object such as it expecting the expiry date to be within a cardExpiry object and the properties being named differently etc. – Tim Sheehan Oct 13 '15 at 02:12

1 Answers1

1

So after having a look at the developer docs for Netbanx it seems it's not expecting the billing state and country to be part of the card object.

    "card" => CreditCard {#1094 ▼
      #parameters: ParameterBag {#1342 ▼
        #parameters: array:7 [▼
          "number" => "4530910000012345"
          "expiryMonth" => 11
          "expiryYear" => 2019
          "cvv" => "123"
          "billingPostcode" => "1234"
          "billingState" => "London"
          "billingCountry" => "GB"
        ]
      }

https://developer.optimalpayments.com/en/documentation/card-payments-api/card-object/

The API is expecting a request like this:

     "merchantRefNum" : "demo-1",
     "amount" : 10098,
     "settleWithAuth":true,
     "card" : {
       "cardNum" : "4111111111111111",
       "cardExpiry":{
         "month":2,
         "year":2017
        },
        "cvv":123
      },
      "billingDetails":{
         "street":"100 Queen Street West",
         "city":"Toronto",
         "state":"ON",              
         "country":"CA",
         "zip":"M5H 2N2"
      }
    } '

It's probably a problem with the Omnipay plugin, but you're going to have to modify it so that the billing details are sent in the correct object.

Tim Sheehan
  • 3,994
  • 1
  • 15
  • 18
  • It's turns out the dump of the Response class I added to the question may have been a bit misleading. The params array was just a dump of the Card object (not representative of the formatted data being passed to Netbanx). The actual formatted XML that's send across to Netbanx is now added to the question description. – JasonMortonNZ Oct 13 '15 at 02:42
  • State seems to be missing from the XML? – Tim Sheehan Oct 13 '15 at 02:54
  • Yeah that's because Great Britain doesn't have states represented by 2 letter codes. I believe the state should only be required if the country is US (https://developer.optimalpayments.com/en/documentation/card-payments-api/billingdetails-object/) – JasonMortonNZ Oct 13 '15 at 02:57
  • Have you tried processing a test transaction using a US state and country code? – Tim Sheehan Oct 13 '15 at 03:04
  • For countries other than Canada and US the state is considered a Region. This not as restrictive as using the 2 letter code for the state. It is a free form paraemter. – Corporate One Jan 03 '17 at 20:48