Since I have implemented the Accept.js in our payment terminal we have been getting up to 33% error rate from our clients using it - some have tried a couple times with no success and others have had periodic success. I can't seem to track any pattern but the error response I am getting is: 'The element 'opaqueData' in namespace 'AnetApi/xml/v1/schema/AnetApiSchema.xsd' has incomplete content. List of possible elements expected: 'dataDescriptor' in namespace 'AnetApi/xml/v1/schema/AnetApiSchema.xsd'
I thought maybe if I posted the code someone could point out the obvious. I have tried to trim it down to the minimum necessary to follow the flow:
client side javascript
/*
* Once the form fields are confirmed to be correct during the submit event,
* this function is called.
*/
function sendPaymentDataToAnet() {
var secureData = {}, authData = {}, cardData = {};
data = formData(Billing.flags.sensitive);
cardData.cardNumber = data.card_number;
cardData.month = data.exp_month;
cardData.year = data.exp_year;
cardData.cardCode = data.card_code;
cardData.zip = Billing.changes.hasOwnProperty('zip') ? Billing.changes.zip : Billing.fields.zip;
var name = [(Billing.changes.hasOwnProperty('first_name') ? Billing.changes.first_name : Billing.fields.first_name),
(Billing.changes.hasOwnProperty('last_name') ? Billing.changes.last_name : Billing.fields.last_name)];
var fullname = name.join(' ');
cardData.fullname = fullname.trim();
secureData.cardData = cardData;
authData.clientKey = BDP.clientKey;
authData.apiLoginID = BDP.apiLoginID;
secureData.authData = authData;
Accept.dispatchData(secureData, 'creditCardHandler');
}
function creditCardHandler(response) {
var data = formData();
delete data.card_number;
delete data.card_code;
if (response.messages.resultCode === 'Error') {
var errorMsg = '';
for (var i = 0; i < response.messages.message.length; i++) {
errorMsg = errorMsg + response.messages.message[i].code + ':' + response.messages.message[i].text + ' ';
}
data.error = errorMsg;
}
else if ( response.hasOwnProperty('opaqueData') )
{
var opaqueData = response.opaqueData;
data.dataDescriptor = opaqueData.hasOwnProperty('dataDescriptor') ? opaqueData.dataDescriptor : 'COMMON.ACCEPT.INAPP.PAYMENT';
data.dataValue = opaqueData.hasOwnProperty('dataValue') ? opaqueData.dataValue : null;
if ( data.dataValue === null || data.dataValue.length < 1 )
{
data.error = "Payment gateway returned an invalid response: dataValue is empty.";
}
}
$.post("/billing/terminal.php",data)
.always(function(data) {
$('#confirm').hide();
$('#entry-form').hide();
$('#response .contents').empty().append(data);
$('#response').show();
$("body").css("cursor", "default");
});
}server-side php
$pdo = new PDO("mysql:host=".$DB['host'].";dbname=".$DB['schema'], $DB['user'], $DB['pwd']);
if ($_SERVER['REQUEST_METHOD'] === 'POST') {
$merchantAuthentication = new AnetAPI\MerchantAuthenticationType();
$merchantAuthentication->setName(\Billing\Constants::MERCHANT_LOGIN_ID);
$merchantAuthentication->setTransactionKey(\Billing\Constants::MERCHANT_TRANSACTION_KEY);
// $base: information specific to the account being charged along with the dollar amount
// $address: billing address
// $group := we have several product lines and this holds information about
// which line holds the account being charged.
$data = array_merge($base, $address,['dataDescriptor'=>$_POST['dataDescriptor'],
'dataValue'=>$_POST['dataValue']],$group);
$response = cc_transaction($merchantAuthentication, $data, $pdo);
}
function cc_transaction($merchantAuthentication, $data, $pdo)
{
global $anetUrl;
$refId = 'ref' . time();
$op = new AnetAPI\OpaqueDataType();
$op->setDataDescriptor($data['dataDescriptor']);
$op->setDataValue($data['dataValue']);
$paymentOne = new AnetAPI\PaymentType();
$paymentOne->setOpaqueData($op);
$billTo = new AnetAPI\CustomerAddressType();
$billTo->setFirstName($data['first_name'])
->setLastName($data['last_name'])
->setAddress($data['address'])
->setCity($data['city'])
->setState($data['state'])
->setZip($data['zip']);
$customer = new AnetAPI\CustomerDataType();
$customer->setId($data['customer_id']);
$customer->setEmail($data['email']);
$orderType = new AnetAPI\OrderType();
$invoiceNumber = substr($data['customer_id'] . '_' . date('ymdHis'),0,20);
$orderType->setInvoiceNumber($invoiceNumber);
$orderType->setDescription($data['description'] . ' payment terminal');
$transactionRequestType = new AnetAPI\TransactionRequestType();
$transactionRequestType->setAmount($data['amount']);
$transactionRequestType->setBillTo($billTo);
$transactionRequestType->setCustomer($customer);
$transactionRequestType->setOrder($orderType);
$transactionRequestType->setPayment($paymentOne);
$transactionRequestType->setTransactionType( "authCaptureTransaction");
$request = new AnetAPI\CreateTransactionRequest();
$request->setMerchantAuthentication($merchantAuthentication);
$request->setRefId( $refId);
$request->setTransactionRequest( $transactionRequestType);
$controller = new AnetController\CreateTransactionController($request);
$response = $controller->executeWithApiResponse($anetUrl);
if (($response != null) && ($response->getMessages()->getResultCode() == "Ok") ) {
$tresponse = $response->getTransactionResponse();
if ($tresponse != null && $tresponse->getMessages() != null) { // success
$respData = array(
'amount'=>$data['amount'],
'response_description'=>$tresponse->getMessages()[0]->getDescription(),
'auth_code'=>$tresponse->getAuthCode(),
'transaction_id'=>$tresponse->getTransId(),
'payment_method'=>$tresponse->getAccountType() . ' ' . $tresponse->getAccountNumber(),
'memo'=> '(' . $tresponse->getAccountType() . ') ' . $tresponse->getAccountNumber()
. ' - AUTH: ' . $tresponse->getAuthCode()
);
$avsResultCode = $tresponse->getAvsResultCode();
if ( isset(\Billing\Lists::$AvsResponse[$avsResultCode]) )
$respData['avs_response'] = \Billing\Lists::$AvsResponse[$avsResultCode];
$lead_in = response_page_lead(false);
$payment_information = payment_information($respData);
$billing_information = billing_information($data);
$action_buttons = action_buttons(false);
$infoResponse = join('',[$lead_in,$payment_information,$billing_information,$action_buttons,'</div>']);
}
else { // error
if($tresponse->getErrors() != null) {
$errorMessage = $tresponse->getErrors()[0]->getErrorCode() . " " . $tresponse->getErrors()[0]->getErrorText();
$error_code = $tresponse->getErrors()[0]->getErrorCode();
$error_text = $tresponse->getErrors()[0]->getErrorText();
$account_type = $tresponse->getAccountType();
$account_number = $tresponse->getAccountNumber();
$codes = join('|',array($tresponse->getErrors()[0]->getErrorCode(),
$tresponse->getAvsResultCode(),
$tresponse->getCvvResultCode(),
$tresponse->getCavvResultCode()));
$error = "CC Failure (" . $account_type . ") " . $account_number . ": " . $codes . ' ' . $error_text;
$logMessage = date('D, d M Y h:i:s O') . " ERROR : (" . __FILE__ . ' : ' . __LINE__ . ") - " . $errorMessage;
if (AUTHORIZENET_LOG_FILE)
file_put_contents(AUTHORIZENET_LOG_FILE, $logMessage, FILE_APPEND);
$payment_information = billing_information($data);
$action_buttons = action_buttons(true);
}
else {
$error = "General payment error.";
}
$amountStr = 'Amount: $' . $data['amount'] . '<br />';
$lead_in = response_page_lead($amountStr . $error);
$billing_information = billing_information($data);
$action_buttons = action_buttons(true);
$infoResponse = join('',[$lead_in,$billing_information,$action_buttons,'</div>']);
}
}
else { // error
$errorMessages = $response->getMessages()->getMessage();
$error_code = $errorMessages[0]->getCode();
$error_text = $errorMessages[0]->getText();
$account_type = $data['card_type'];
$account_number = $data['safe_number'];
$error = "CC Failure (" . $account_type . ") " . $account_number . ": " . $error_text;
$errorMessage = $error_code . " " . $error_text;
$logMessage = date('D, d M Y h:i:s O') . " ERROR : (" . __FILE__ . ' : ' . __LINE__ . ") - " . $errorMessage;
if (AUTHORIZENET_LOG_FILE)
file_put_contents(AUTHORIZENET_LOG_FILE, $logMessage, FILE_APPEND);
$amountStr = 'Amount: $' . $data['amount'] . '<br />';
$lead_in = response_page_lead($amountStr . $error);
$billing_information = billing_information($data);
$action_buttons = action_buttons(true);
$infoResponse = join('',[$lead_in,$billing_information,$action_buttons,'</div>']);
}
return $infoResponse;
}
08-03-2017 04:13 PM