rolinger
rolinger

Reputation: 3058

Authroize.Net Missing or invalid token for Accept Hosted iFrame page

Going nuts here with Authorize.Net extremely POOR documentation and error reporting. I am trying to implement an Accept Hosted page to process credit cards. I am able to generate the token but when I pass the token into the form (in the iFrame) I am getting an error MISSING OR INVALID TOKEN

The token is getting created without issue, but when trying to use it is when things go sideways.

And in the chrome inespector console I am getting two javascript errors returned:

ERROR TypeError: Cannot read property 'billTo' of null
ERROR TypeError: Cannot read property 'offsetHeight' of null

So, printing out my $request json I am able to validate my json object that is being passed to create the token is correct:

{
  "merchantAuthentication": {"name":"xxxxxxxx","transactionKey":"yyyyyyyyyyyy"},
  "clientId":"sdk-php-2.0.0-ALPHA",
  "refId":"ref1608564012",
  "transactionRequest": {
    "transactionType":"authCaptureTransaction",
    "amount":"360.00",
    "order":  {"invoiceNumber":"11373-0","description":"2020-11-01 bill for All Regions\/All Sites"},
    "customer":{"type":"business","id":"1002","email":"[email protected]"},
    "billTo":{"firstName":"Preston","lastName":"Johnson","company":"Backyard Grill","address":"123 Main St","city":"Tampa","state":"FL","zip":"33611","country":"USA"},
    "shipTo":{"firstName":"Preston","lastName":"Johnson","company":"Backyard Grill","address":"123 Main St","city":"Tampa","state":"FL","zip":"33611","country":"USA"}
  },
  "hostedPaymentSettings":
    {"setting":[
      {"settingName":"hostedPaymentReturnOptions","settingValue":"{ \"url\": \"https:\/\/portal.attendago.com\/adminInvoicePaid.html\", \"cancelUrl\": \"https:\/\/portal.attendago.com\/adminInvoicePay.html?invID=11373-0\", \"showReceipt\":true }"},
      {"settingName":"hostedPaymentButtonOptions","settingValue":"{ \"text\": \"Submit Payment\" }"},
      {"settingName":"hostedPaymentStyleOptions","settingValue":"{ \"bgColor\": \"#192a67\" }"},
      {"settingName":"hostedPaymentPaymentOptions","settingValue":"{ \"cardCodeRequired\":true, \"showCreditCard\":true, \"showBankAccount\":true }"},
      {"settingName":"hostedPaymentShippingAddressOptions","settingValue":"{ \"show\":false, \"required\":true }"},
      {"settingName":"hostedPaymentBillingAddressOptions","settingValue":"{ \"show\":true, \"required\":true }"},
      {"settingName":"hostedPaymentCustomerOptions","settingValue":"{ \"showEmail\":true, \"requiredEmail\":true, \"addPaymentProfile\":false }"},
      {"settingName":"hostedPaymentOrderOptions","settingValue":"{ \"show\":false }"},
      {"settingName":"hostedPaymentIFrameCommunicatorUrl","settingValue":"{ \"url\": \"https:\/\/portal.attendago.com\/adminInvoiceFrame.html\" }"}
  ]}
}

Here is my function to create the token:

function getCustomerToken($ss) {
    $ii = $ss['invoiceData'] ;
    if (isSet($ss['payMethods'])) {
      $pp = $ss['payMethods'] ;
    }
    
    ////////////////////////////////////////////////
    /// global objects needed for all transactions
    ////////////////////////////////////////////////
    
    // Create a merchantAuthenticationType, pulled from constants file
    $merchantAuthentication = new AnetAPI\MerchantAuthenticationType();
    $merchantAuthentication->setName(\AuthorizeConstants::sandboxID);  // loginID / sandboxID
    $merchantAuthentication->setTransactionKey(\AuthorizeConstants::sandboxKey);  // loginKey / sandboxKey
    
    // Set the transaction's refId
    $refId = 'ref' . time();
    
    // Set order information
    $order = new AnetAPI\OrderType();
    $order->setInvoiceNumber($ss['invoiceID']);
    if (strpos($ii['invName'], "S") !== false) {
      $invDesc = $ii['servMonth']. " bill for Site " .$ii['venue'] ;
    } else if (strpos($ii['invName'], "R") !== false) {
      $invDesc = $ii['servMonth']. " bill for Region " .$ii['venue'] ;
    } else {
      $invDesc = $ii['servMonth']. " bill for " .$ii['venue'] ;
    }
    $order->setDescription($invDesc);    
    
    // Set the customer's identifying information
    $customerData = new AnetAPI\CustomerDataType();
    $customerData->setType("business");
    $customerData->setId($ii['cID']);
    $customerData->setEmail($ii['cEmail']);
    
    // Set the Bill To info for new payment type
    $billTo = new AnetAPI\CustomerAddressType();
    $billTo->setFirstName($ii['cFirstName']);
    $billTo->setLastName($ii['cLastName']);
    $billTo->setCompany($ii['cName']);
    $billTo->setAddress($ii['cAddress']. " " .$ii['cAddress1']);
    $billTo->setCity($ii['cCity']);
    $billTo->setState($ii['cState']);
    $billTo->setZip($ii['cZip']);
    $billTo->setCountry("USA");
    //$billTo->setFaxNumber('8005551212') ;
    //$billTo->setPhoneNumber($ii['cPhone']);
    
    // set shipping profile
    $shippingProfiles[] = $billTo ;
    
    //create a transaction
    $transactionRequestType = new AnetAPI\TransactionRequestType();
    $transactionRequestType->setTransactionType("authCaptureTransaction");
    $transactionRequestType->setAmount($ss['balance']);
    $transactionRequestType->setCustomer($customerData) ;
    $transactionRequestType->setOrder($order) ;
    if (isSet($ss['authMerchID'])) {
      $profileType = new AnetAPI\CustomerProfilePaymentType();
      $profileType->setCustomerProfileId($ss['authMerchID']) ;
      $transactionRequestType->setProfile($profileType) ;
    } else {
      $transactionRequestType->setBillTo($billTo) ;
      $transactionRequestType->setShipTo($billTo) ;
    }

    // Set Hosted Form options
    $setting0 = new AnetAPI\SettingType();
    $setting0->setSettingName("hostedPaymentReturnOptions");
    $setting0->setSettingValue( "{ \"url\": \"https://portal.mysdomain.com/adminInvoicePaid.html\", \"cancelUrl\": \"https://portal.mydomain.com/adminInvoicePay.html?invID=" .$ss['invoiceID']. "\", \"showReceipt\":true }" );
    
    $setting1 = new AnetAPI\SettingType();
    $setting1->setSettingName("hostedPaymentButtonOptions");
    $setting1->setSettingValue("{ \"text\": \"Submit Payment\" }");

    $setting2 = new AnetAPI\SettingType();
    $setting2->setSettingName("hostedPaymentStyleOptions");
    $setting2->setSettingValue("{ \"bgColor\": \"#192a67\" }");

    $setting3 = new AnetAPI\SettingType();
    $setting3->setSettingName("hostedPaymentPaymentOptions");
    $setting3->setSettingValue("{ \"cardCodeRequired\":true, \"showCreditCard\":true, \"showBankAccount\":true }");
    
    $setting4 = new AnetAPI\SettingType();
    $setting4->setSettingName("hostedPaymentShippingAddressOptions");
    $setting4->setSettingValue("{ \"show\":false, \"required\":true }");
    
    $setting5 = new AnetAPI\SettingType();
    $setting5->setSettingName("hostedPaymentBillingAddressOptions");
    $setting5->setSettingValue("{ \"show\":true, \"required\":true }");
    
    $setting6 = new AnetAPI\SettingType();
    $setting6->setSettingName("hostedPaymentCustomerOptions");
    $setting6->setSettingValue("{ \"showEmail\":true, \"requiredEmail\":true, \"addPaymentProfile\":false }");
    
    $setting7 = new AnetAPI\SettingType();
    $setting7->setSettingName("hostedPaymentOrderOptions");
    $setting7->setSettingValue("{ \"show\":false }");
    
    $setting8 = new AnetAPI\SettingType();
    $setting8->setSettingName("hostedPaymentIFrameCommunicatorUrl");
    $setting8->setSettingValue("{ \"url\": \"https://portal.mydomain.com/adminInvoiceFrame.html\" }");

    // Build transaction request
    $request = new AnetAPI\GetHostedPaymentPageRequest();
    $request->setMerchantAuthentication($merchantAuthentication);
    $request->setRefId($refId);
    $request->setTransactionRequest($transactionRequestType);

    $request->addToHostedPaymentSettings($setting0);
    $request->addToHostedPaymentSettings($setting1);
    $request->addToHostedPaymentSettings($setting2);
    $request->addToHostedPaymentSettings($setting3);
    $request->addToHostedPaymentSettings($setting4);
    $request->addToHostedPaymentSettings($setting5);
    $request->addToHostedPaymentSettings($setting6);
    $request->addToHostedPaymentSettings($setting7);
    $request->addToHostedPaymentSettings($setting8);

    //execute request
    $controller = new AnetController\GetHostedPaymentPageController($request);
    $response = $controller->executeWithApiResponse(\net\authorize\api\constants\ANetEnvironment::SANDBOX);
    
    $gToken=[] ;
    if (($response != null) && ($response->getMessages()->getResultCode() == "Ok")) {
        //echo $response->getToken()."\n";
        $gToken["Error"]  = 0 ;
        $gToken["Token"] = $response->getToken() ;
    } else {
        //echo "ERROR :  Failed to get hosted payment page token\n";
        $errorMessages = $response->getMessages()->getMessage();
        //echo "RESPONSE : " . $errorMessages[0]->getCode() . "  " .$errorMessages[0]->getText() . "\n";
        $gToken["Error"]  = 1 ;
        $gToken["errMsg"] = $errorMessages[0]->getCode() . ":  " .$errorMessages[0]->getText() ;
    }
    return array($gToken,$request);
}

*** UPDATE***

Looking at the network console logs, there is a request going out to https://test.authorize.net/payment/payment - but the key token is empty, which would appear to be the reason for the error Missing or Invalid Token. In my form, I can validate the TOKEN is there. But when I click the trigger popup iFrame button, I can visually see the token being deleted from the hidden form field.

Upvotes: 0

Views: 1750

Answers (1)

rolinger
rolinger

Reputation: 3058

The code to open the popup iframe, copied verbatim from the Authorize.net code sample had this bit of code $("#popupToken").val($("#inputtoken").val()); - this is erasing/deleting the token value before it was being submitted to payment gateway - what the heck?! Why would their own example code do that? Commenting this out fixed it.

AuthorizeNetPopup.openPopup = function () {
  var popup = document.getElementById("divAuthorizeNetPopup");
  var popupScreen = document.getElementById("divAuthorizeNetPopupScreen");
  var ifrm = document.getElementById("iframeAuthorizeNet");
  var form = document.forms["formAuthorizeNetPopup"];
  //$("#popupToken").val($("#inputtoken").val());   // WTH authorize????
  form.action = "https://test.authorize.net/payment/payment";
  ifrm.style.width = "442px";
  ifrm.style.height = "578px";

  form.submit();

  popup.style.display = "";
  popupScreen.style.display = "";
  centerPopup();
  };

Upvotes: 1

Related Questions