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