One of my clients needed me to add First Data Merchant account processing to Gravity Forms in WordPress. I had gotten the First Data Merchant account working and explained how I did that in this post. I’m not going to change much of the First Data code from that post. I will just be discussing WHERE to put that code so that it will work in Gravity Forms and WordPress.
I love Gravity Forms because it has so many hooks and filters which makes just about anything possible. There are so many hooks that it often makes it difficult to figure out exactly where the code should go – which hook to hang it on. The form I’m using also uses the Gravity Forms User Registration add-on. Someone else may have a better solution for this problem. If so, please leave me a message in the comments. I’m always looking for ways to improve. I just usually take the lazy way out, which in programming is sometimes the best way.
Gravity Forms handles the credit card validation pretty well as far as making sure there is a valid number, valid expiration date, etc. But, it can’t know about whether the card will go through until you actually try to charge the card.
I thought about adding the credit card processing to the validation hooks in Gravity Forms, but decided against it. I didn’t want to have to refund the card or cancel the payment or deal with authorizations if the rest of the form had a problem… Or if the user couldn’t be registered… Or if there was some other problem in the form processing since I had so many things happening during registration.
I decided that I would let Gravity Forms handle the user registration and form processing and once the form processing had finished, I would charge the card. If there is a problem with the payment, then it could either delete the user or put a hold on their account or block them from any paid services until they get the payment to go through.
I added the following code to the functions.php file:
define('FD_URL','https://api.globalgatewaye4.firstdata.com/transaction/v11'); define('FD_ID','Axxxxx-xx'); define('FD_PASSWORD','xxxxxxxx'); add_action('gform_after_submission_1', 'process_cc', 10, 2); function process_cc($entry, $form) { // send an email to myself for debugging and to know when someone registers/makes a payment $body = "$form = nn"; foreach ($_POST as $key=>$data) { $body .= $key.' = '.$data."nn"; if ($key == 'input_9_2') { foreach ($data as $key2=>$data2) { $body .= $key2.' = '.$data2."nn"; } } } //save the fields from the form $amount = $_POST['input_8']; $type = $_POST['input_7']; $username = $_POST['input_6']; $user = get_userdatabylogin($username); $name = $_POST['input_9_5']; $card_number = $_POST['input_9_1']; $cc_expiry_month = str_pad($_POST['input_9_2']['0'], 2, '0', STR_PAD_LEFT); $cc_expiry_year = substr($_POST['input_9_2']['1'], -2); $cvv_code = $_POST['input_9_3']; //send another email to myself with more debug information $body .= 'Username = '.$username."nnAmount = $".$amount."nnType = ".$type."nnCert = ".$cert."nnName=".$name."nnCard Number = ".$card_number."nnExpires = ".$cc_expiry_month.$cc_expiry_year."nn"; $body .= print_r($entry); $body .= print_r($_POST); mail('email@example.com','gform after sub', $body, "From: email@example.com"); //Add First Data info here - make the payment $data = array("gateway_id" => FD_ID, "password" => FD_PASSWORD, "transaction_type" => "00", "amount" => $amount, "cardholder_name" => $name, "cc_number" => $card_number, "cc_expiry" => $cc_expiry_month.$cc_expiry_year); $data_string= json_encode($data); $ch = curl_init( FD_URL ); curl_setopt($ch, CURLOPT_CUSTOMREQUEST, "POST"); curl_setopt($ch, CURLOPT_POSTFIELDS, $data_string); curl_setopt($ch, CURLOPT_RETURNTRANSFER, true); curl_setopt($ch, CURLOPT_HTTPHEADER, array('Content-Type: application/json; charset=UTF-8;')); $result = curl_exec($ch); // Getting jSON result string //Another email - I like to see exactly what's going on for debug purposes and to make sure it's working correctly mail('email@example.com','results from api',$result); //put the xml results into simplexml and check results $xml = @simplexml_load_string($result); if ($xml) { if ($xml->Bank_Resp_Code == '100') { // credit card charged successfully $valid = true; } else { // error with credit card charge - send myself an error message $body = $xml->Bank_Message; mail ('email@example.com','error with transaction',$body,"From: email@example.com"); $valid=false; } } else { // The simple xml failed - send a message to myself to let me know what went wrong mail ('email@example.com','error with transaction','nothing in xml',"From: email@example.com"); } if ($valid) { // If the credit card was successful // Save how many lessons they have bought - I have options to buy the whole course or one lesson at a time. if ($type == 'Full') { $lessons = 10; $product_name = 'Full Course'; } if ($type == 'Lesson') { $lessons = 1; $product_name = 'Lesson 1'; } // Send receipt $message = "Thank you for your purchase!nn"; $message .= "[Course Name]: ".$product_name."nn"; $message .= "Amount: $".money_format('%2n',$amount)."nn"; $message .= "Thank You,nnDr. Menn"; mail($user->user_email, '[Course Name] receipt', $message, "From: info@jerilavigne.com"); $payment = "SUCCESS"; } else { // the credit card wasn't successful, send an email to the user. I also set a user meta field $payment so I could display an error on the user's membership page. // Save lesson bought as 0 - show introduction only with buy now button $lessons = 0; $message = "I'm sorry, your payment did not go through.nnError: $xml->Bank_MessagennPlease try again.nnThank you, Dr. Me"; mail($user->user_email, '[Course Name] payment failed', $message, "From: email@example.com"); $payment = "FAILED"; } // save the user meta fields to indicate the status of the user and their payment $user_id = $user->ID; update_user_meta($user_id, 'paid_lessons', $lessons, 0); add_user_meta($user_id, 'payment', $payment, true); }
A few things you should notice:
- I like to add emails to myself for debugging purposes and so that I can see exactly what’s going on during the processing. If it fails, or if there is a problem with my code, I want to know exactly where it went wrong. I often leave those emails in so that I can see when someone purchases and make sure that everything is being processed as expected. When the emails become annoying, I’ll go in and take out the email code.
- I obviously changed some of the code for security purposes. You will have to put in your own app ID and password, email address and course or product information as well as email text.
- I am using the URL for the production First Data processing. You will want to use the First Data test site URL, ID, and Password until you have it working on your site.
Please let me know if you have any question, comments or feedback.
Hello,
I too am having issues with g-forms payment processing. I need the CC info to be pulled without being censored because as soon as they hit submit they are redirected to a secured backend but every time I send the CC info to my payment it’s always blocked. Anyway to remove that XXXX XXXX XXXX from gravity forms?
Are you putting the code in the after_submission hook? You may want to check the hook to make sure the $_POST is still in tact when you send the payment info.
Hi Cindy, and thanks for the script.
Im trying to incorporate in my site but i get nothing in xml.
I dont think it is processing properly.
Any suggestions, Thanks.
AJ
AJ, you will need to post your code for us to see it.
Hi Cindy, thanks for getting back to me.
Below is the code, all i did is copy you script and put it in the functions.php.
Once there i added the demo site url, changed the post fields name for mine, updated the email to my email for debug, i did take out the username field since in my form you dont need to be registered (took it out of the body as well) and lastly put my first data login id and password.
thanks for your help
$data) {
$body .= $key.’ = ‘.$data.”nn”;
if ($key == ‘input_9_2′) {
foreach ($data as $key2=>$data2) {
$body .= $key2.’ = ‘.$data2.”nn”;
}
}
}
//save the fields from the form
$amount = $_POST[‘input_44’];
$type = $_POST[‘input_30’];
$name = $_POST[‘input_50’];
$card_number = $_POST[‘input_47’];
$cc_expiry_month = str_pad($_POST[‘input_52’][‘0’], 2, ‘0’, STR_PAD_LEFT);
$cc_expiry_year = substr($_POST[‘input_53’][‘1’], -2);
$cvv_code = $_POST[‘input_49’];
//send another email to myself with more debug information
$body .= “nnAmount = $”.$amount.”nnType = “.$type.”nnCert = “.$cert.”nnName=”.$name.”nnCard Number = “.$card_number.”nnExpires = “.$cc_expiry_month.$cc_expiry_year.”nn”;
$body .= print_r($entry);
$body .= print_r($_POST);
mail(‘myemail@mydomain.com’,’gform after sub’, $body, “From: myemail@mydomain.com“);
//Add First Data info here – make the payment
$data = array(“gateway_id” => FD_ID, “password” => FD_PASSWORD, “transaction_type” => “00”, “amount” => $amount, “cardholder_name” => $name, “cc_number” => $card_number, “cc_expiry” => $cc_expiry_month.$cc_expiry_year);
$data_string= json_encode($data);
$ch = curl_init( FD_URL );
curl_setopt($ch, CURLOPT_CUSTOMREQUEST, “POST”);
curl_setopt($ch, CURLOPT_POSTFIELDS, $data_string);
curl_setopt($ch, CURLOPT_RETURNTRANSFER, true);
curl_setopt($ch, CURLOPT_HTTPHEADER, array(‘Content-Type: application/json; charset=UTF-8;’));
$result = curl_exec($ch); // Getting jSON result string
//Another email – I like to see exactly what’s going on for debug purposes and to make sure it’s working correctly
mail(‘myemail@mydomain.com’,’results from api’,$result);
//put the xml results into simplexml and check results
$xml = @simplexml_load_string($result);
if ($xml) {
if ($xml->Bank_Resp_Code == ‘100’) { // credit card charged successfully
$valid = true;
} else { // error with credit card charge – send myself an error message
$body = $xml->Bank_Message;
mail (‘myemail@mydomain.com’,’error with transaction’,$body,”From: myemail@mydomain.com“);
$valid=false;
}
} else { // The simple xml failed – send a message to myself to let me know what went wrong
mail (‘myemail@mydomain.com’,’error with transaction’,’nothing in xml’,”From: myemail@mydomain.com“);
}
if ($valid) { // If the credit card was successful
// Save how many lessons they have bought – I have options to buy the whole course or one lesson at a time.
if ($type == ‘Full’) {
$lessons = 10;
$product_name = ‘Full Course’;
}
if ($type == ‘Lesson’) {
$lessons = 1;
$product_name = ‘Lesson 1’;
}
// Send receipt
$message = “Thank you for your purchase!nn”;
$message .= “[Course Name]: “.$product_name.”nn”;
$message .= “Amount: $”.money_format(‘%2n’,$amount).”nn”;
$message .= “Thank You,nnDr. Menn”;
mail($user->user_email, ‘[Course Name] receipt’, $message, “From: info@jerilavigne.com“);
$payment = “SUCCESS”;
} else { // the credit card wasn’t successful, send an email to the user. I also set a user meta field $payment so I could display an error on the user’s membership page.
// Save lesson bought as 0 – show introduction only with buy now button
$lessons = 0;
$message = “I’m sorry, your payment did not go through.nnError: $xml->Bank_MessagennPlease try again.nnThank you, Dr. Me”;
mail($user->user_email, ‘[Course Name] payment failed’, $message, “From: myemail@mydomain.com“);
$payment = “FAILED”;
}
// save the user meta fields to indicate the status of the user and their payment
$user_id = $user->ID;
update_user_meta($user_id, ‘paid_lessons’, $lessons, 0);
add_user_meta($user_id, ‘payment’, $payment, true);
}
Dont think the code displayed right, here goes again.
//define('FD_URL','https://api.globalgatewaye4.firstdata.com/transaction/v11');//PRODUCTION
define('FD_URL','https://demo.globalgatewaye4.firstdata.com/');//DEMO
define('FD_ID','xxxx-xx');
define('FD_PASSWORD','xxxxxxx');
//add_action("gform_pre_submission_5", "pre_submission_cc_processing", 10, 2);
//function pre_submission_cc_processing($entry, $form){
add_action('gform_after_submission_5', 'process_cc', 10, 2);
function process_cc($entry, $form) {
// send an email to myself for debugging and to know when someone registers/makes a payment
$body = "$form = nn";
foreach ($_POST as $key=>$data) {
$body .= $key.' = '.$data."nn";
if ($key == 'input_9_2') {
foreach ($data as $key2=>$data2) {
$body .= $key2.' = '.$data2."nn";
}
}
}
//save the fields from the form
$amount = $_POST['input_44'];
$type = $_POST['input_30'];
$name = $_POST['input_50'];
$card_number = $_POST['input_47'];
$cc_expiry_month = str_pad($_POST['input_52']['0'], 2, '0', STR_PAD_LEFT);
$cc_expiry_year = substr($_POST['input_53']['1'], -2);
$cvv_code = $_POST['input_49'];
//send another email to myself with more debug information
$body .= "nnAmount = $".$amount."nnType = ".$type."nnCert = ".$cert."nnName=".$name."nnCard Number = ".$card_number."nnExpires = ".$cc_expiry_month.$cc_expiry_year."nn";
$body .= print_r($entry);
$body .= print_r($_POST);
mail('myemail@mydomain.com','gform after sub', $body, "From: myemail@mydomain.com");
//Add First Data info here - make the payment
$data = array("gateway_id" => FD_ID, "password" => FD_PASSWORD, "transaction_type" => "00", "amount" => $amount, "cardholder_name" => $name, "cc_number" => $card_number, "cc_expiry" => $cc_expiry_month.$cc_expiry_year);
$data_string= json_encode($data);
$ch = curl_init( FD_URL );
curl_setopt($ch, CURLOPT_CUSTOMREQUEST, "POST");
curl_setopt($ch, CURLOPT_POSTFIELDS, $data_string);
curl_setopt($ch, CURLOPT_RETURNTRANSFER, true);
curl_setopt($ch, CURLOPT_HTTPHEADER, array('Content-Type: application/json; charset=UTF-8;'));
$result = curl_exec($ch); // Getting jSON result string
//Another email - I like to see exactly what's going on for debug purposes and to make sure it's working correctly
mail('myemail@mydomain.com','results from api',$result);
//put the xml results into simplexml and check results
$xml = @simplexml_load_string($result);
if ($xml) {
if ($xml->Bank_Resp_Code == '100') { // credit card charged successfully
$valid = true;
} else { // error with credit card charge - send myself an error message
$body = $xml->Bank_Message;
mail ('myemail@mydomain.com','error with transaction',$body,"From: myemail@mydomain.com");
$valid=false;
}
} else { // The simple xml failed - send a message to myself to let me know what went wrong
mail ('myemail@mydomain.com','error with transaction','nothing in xml',"From: myemail@mydomain.com");
}
if ($valid) { // If the credit card was successful
// Save how many lessons they have bought - I have options to buy the whole course or one lesson at a time.
if ($type == 'Full') {
$lessons = 10;
$product_name = 'Full Course';
}
if ($type == 'Lesson') {
$lessons = 1;
$product_name = 'Lesson 1';
}
// Send receipt
$message = "Thank you for your purchase!nn";
$message .= "[Course Name]: ".$product_name."nn";
$message .= "Amount: $".money_format('%2n',$amount)."nn";
$message .= "Thank You,nnDr. Menn";
mail($user->user_email, '[Course Name] receipt', $message, "From: info@jerilavigne.com");
$payment = "SUCCESS";
} else { // the credit card wasn't successful, send an email to the user. I also set a user meta field $payment so I could display an error on the user's membership page.
// Save lesson bought as 0 - show introduction only with buy now button
$lessons = 0;
$message = "I'm sorry, your payment did not go through.nnError: $xml->Bank_MessagennPlease try again.nnThank you, Dr. Me";
mail($user->user_email, '[Course Name] payment failed', $message, "From: myemail@mydomain.com");
$payment = "FAILED";
}
// save the user meta fields to indicate the status of the user and their payment
$user_id = $user->ID;
update_user_meta($user_id, 'paid_lessons', $lessons, 0);
add_user_meta($user_id, 'payment', $payment, true);
}
AJ, It looks like you may be getting JSON results instead of XML. Try reading it as a JSON string like this:
$result = curl_exec($ch); // Getting jSON result string
//$xml = @simplexml_load_string($result);
$json = json_decode($result);
if ($json) {
if ($json->Bank_Resp_Code == ‘100’) {
$valid = true;
} else {
You’ll have to change all the following variables named $xml to $json.