Rest API - Credit Card info not being stored or updated (for existing ones) on clients account

Two weeks ago the credit card fields stopped being populated into the clients’ accounts for orders processed via the Rest API. The credit card input names are correct: cardNumber, expirationMonth, expirationYear.

Is anybody experiencing the same issue?
Did something change within the API?

Thanks in advance.

Good morning Dustin,

We lock down deployments around the holidays to prevent service interruptions during what is usually the busiest time of the year, so it’s generally unlikely that something changed, but it’s always possible. Could you provide the exact endpoint/verb you are using to make calls that aren’t getting the expected response? We have several methods that handle credit card information in various ways.

Hi Tom,

Thanks for the prompt response. Please see below the script we’re using to process the orders. I hope this serves the purpose of your question.

// Connect

require_once('isdk.php');
$app = new iSDK;
$app->cfgCon('cli',"on");

// Vars
$products = array();
$person = $app->findByEmail($_POST['Contact0Email'], array('Id'));

// Find or Create Person

foreach ($_POST as $key => $val) {
	if (preg_match("/Contact0/i", $key) && $val != "") {
		$con_data[substr($key, 8)] = $val;
	}
}

if (empty($person)) {
	$person = NULL;
		
	$app->addCon($con_data);
	$person = $app->findByEmail($_POST['Contact0Email'], array('Id'));
}
$cid = $person[0]['Id'];

usleep(500000);

$app->updateCon($cid, $con_data);

if (!empty($_POST['CardNumber'])) {
	switch (substr($_POST['CardNumber'], 0, 1)) {
		case 3:
			$cardType = 'American Express';
			break;
		case 4:
			$cardType = 'Visa';
			break;
		case 5:
			$cardType = 'Mastercard';
			break;
		default:
			$cardType = $_POST['CardType'];
	}
	
	$c_validation = array(
		'ContactId'			=> $cid,
		'CardNumber'			=> $_POST['CardNumber'],
		'ExpirationMonth'	=> $_POST['ExpirationMonth'],
		'ExpirationYear'	=> $_POST['ExpirationYear'],
		'CardType'			=> $cardType
	);
	
	$card_check = $app->validateCard($c_validation);
	
	if (in_array("false", $card_check)) {
		die("<div style=\"color: red; font-family: sans-serif;\"><h1>Your Credit Card Failed</h1>\n<p><strong>ERROR</strong>: ". $card_check["Message"] .". Click your browser's Back button to try again.</p></div>");
	}
	
	usleep(500000);
	
	$card = $app->locateCard($cid, substr($_POST['CardNumber'], -4));
	if (empty($card)) {
		$c_data = array(
			'ContactId'			=> $cid,
			'BillName'			=> $_POST['Contact0FirstName'] . ' '. $_POST['Contact0LastName'],
            'BillAddress1'      => $_POST['Contact0StreetAddress1'],
            'BillCity'          => $_POST['Contact0City'],
            'BillCountry'       => $_POST['Contact0Country'],
            'BillState'         => $_POST['Contact0State'],
            'BillZip'           => $_POST['Contact0PostalCode'],
			'NameOnCard'		=> $_POST['Contact0FirstName'] . ' '. $_POST['Contact0LastName'],
			'FirstName'			=> $_POST['Contact0FirstName'],
			'LastName'			=> $_POST['Contact0LastName'],
			'CardNumber'		=> $_POST['CardNumber'],
			'ExpirationMonth'	=> $_POST['ExpirationMonth'],
			'ExpirationYear'	=> $_POST['ExpirationYear'],
			'CardType'			=> $cardType
		);

		$app->dsAdd("CreditCard", $c_data);
		$card = $app->locateCard($cid, substr($_POST['CardNumber'], -4));
	}
} else {
	$cardQuery = $app->dsQueryOrderBy("CreditCard", 1, 0, array("ContactId" => $cid), array("Id"), "Id", false);
	$card = $cardQuery[0]['Id'];
}

// More Vars

$products = array();
$subscriptions = array();

if (array_key_exists('productId', $_POST)) {
	if (array_key_exists('qty', $_POST)) {
		$qty = $_POST['qty'];
		if (in_array(1843, $_POST['productId'])) {
			$qty += 1;
		}
		$products = array_pad($_POST['productId'], $qty, $_POST['productId'][0]);
	} else {
		$products = $_POST['productId'];
	}
}
if (array_key_exists('subscriptionId', $_POST)) {
	$subscriptions = $_POST['subscriptionId'];
}
$promoCode = "";
if (array_key_exists('promoCode', $_POST)) {
	$promoCode = $_POST['promoCode'];
}
if (array_key_exists('tag', $_POST)) {
	$tag = $_POST['tag'];
	if (array_key_exists('qty', $_POST)) {
		$tag .= " (". $_POST['qty'] .")";
	}
	$tagCatId = array_key_exists('tagCatId', $_POST) ? $_POST['tagCatId'] : 17;
	$tagQuery = array("GroupName" => $tag, "GroupCategoryId" => $tagCatId);
	$rsTag = $app->dsQuery("ContactGroup", 1, 0, $tagQuery, array("Id"));
	
	// Create if not and get tag Id
		
	if (empty($rsTag)) {
		$app->dsAdd("ContactGroup", $tagQuery);
		$rsTag = $app->dsQuery("ContactGroup", 1, 0, $tagQuery, array("Id"));
	}
	
	usleep(500000);
		
	// Assign Tag
	
	$app->grpAssign($cid, $rsTag[0]['Id']);
	
	usleep(500000);
}
if (array_key_exists('actions', $_POST)) { 
	$app->runAS($cid, $_POST['actions']);	
}
if (array_key_exists('tagID', $_POST)) { 
    if(is_array($_POST['tagID'])){
        foreach($_POST['tagID'] as $tag){
            $app->grpAssign($cid, $tag);
        }
        
    }else{
        $app->grpAssign($cid, $_POST['tagID']);	    
    }
    
	
}

$app->placeOrder($cid, $card, 0, $products, $subscriptions, true, array($promoCode));

$query_string = "";
foreach ($_POST as $key => $value) {
    if($key == 'CardType' || $key == 'ExpirationMonth' || $key == 'ExpirationYear' || $key == 'CardNumber'){
    
    }else{
        $query_string .= "&". $key ."=". $value;
    }
	
}
header("Location: ". $_POST['url'] ."?contactId=". $cid . $query_string);

Thanks in advance.

Dustin.

I’m trying to make sense of this; it appears that you are using an unsupported PHP SDK, and after some searching I do see repos with similar naming structure that I assume is where you sourced it, which is hitting the XMLRPC API, not the Rest API.

Looking at the source for the XMRPC OrderService the only change I see in the last year was to add an administrative lockout for misbehaving applications back in September, so it seems that there wasn’t any immediately visible change on our part.

For troubleshooting I would suggest adding additional logging of the complete request and response payloads on your end, then verify both that both conform to expected (current) documented behavior, as well as that your system objects are configured correctly (id’s match as expected, etc). Our development team doesn’t have access to production data for security purposes, so if you can’t get it sorted, I’d ask you to contact our Support team through our Developer Site so that they can look at it more in-depth and file a defect ticket if necessary.