Skip to content

Instantly share code, notes, and snippets.

Embed
What would you like to do?
Gravity/Authorize.net/PayPal
<?php
# use at your own risk :)
/**
* E-COMM -- Custom Authorize.Net AIM api call for GravityForms
*
* GravityForms AuthorizeNet Add-on does NOT handle eChecks (or two Authorize.net accounts), so we bypass the add-on entirely for the API call, but keep it installed and activated, just to use it's Credit Card field on the form. We bypass it by enabling the Authorize.net Condition (in the GF Authorizet.net Feed settings), and creating a condition that should never happen (like: if Email = "disable-me@xyz.com").
* Of course, modify the input/field/form IDs based on YOUR form.
* This setup assumes your form has a field to allow the user to select a Payment Method: either "Credit Card" or "eCheck".
*/
add_action("gform_validation_10", "my_anet_aim", 10, 2); // Form-ID 10 only
function my_anet_aim($validation_result) { // already has $form
# get Form object // only since hook is for Validation
$form = $validation_result["form"];
define("AUTHORIZENET_API_LOGIN_ID", "XXXXXXXXXX"); // enter YOURS
define("AUTHORIZENET_TRANSACTION_KEY", "XXXXXXXXXXXXXXXXXX"); // enter YOURS
define("AUTHORIZENET_SANDBOX", true); //dev: true
define("TEST_REQUEST", "FALSE"); // You may want to set to true if testing against production
$current_page = rgpost('gform_source_page_number_' . $form['id']) ? rgpost('gform_source_page_number_' . $form['id']) : 1;
if ($current_page == 3) {
$payment_method = rgpost('input_37');
if($payment_method == "Paypal"){ //paypal handling
} else { //credit cards or echecks (Authorize.net stuff)
#AUTH-NET PHP SDK
require ('anet_php_sdk/AuthorizeNet.php');
// This is ALREADY included by GravityForms AuthNet Add-on, just be activated (which we do for the nice credit-card field-group), even if the feed Condition blocks GF from sending the transaction. So we don't want to re-require it here.
$frequency = rgpost('input_2');
if ($frequency == 'Monthly') { //Automated Recurring Billing (ARB)
//VERIFY CARD USING AIM, THEN CREATE SUBSCRIPTION USING ARB
$verify = new AuthorizeNetAIM;
$verify->amount = str_replace('$','',rgpost("input_12"));
//$verify->cust_id = rgpost("input_14"); // my Customer Account Number
//$verify->invoice_num = rgpost("input_7"); // my Invoice Number
$verify->email = rgpost('input_2');
# UNIQUE ID -- GF puts a Unique ID in the AuthNet Invoice field. But we use that field for the my Invoice. But it's nice to have the Unique ID somewhere in AuthNet, so let's add it to the Description field.
$web_submission_id = uniqid();
$verify->description =
"Web-Form: ".$form["title"] .", ".
"Web-Submission-ID: ".$web_submission_id;
# ADDRESS
$form_data["address1"] = rgpost('input_28_1');
$form_data["address2"] = rgpost('input_28_2'); // not required
$form_data["address"] = trim($form_data["address1"] . " " . $form_data["address2"]);
$verify->address = $form_data["address"];
$verify->city = rgpost('input_28_3');
$verify->state = rgpost('input_28_4');
$verify->zip = rgpost('input_28_5');
$verify->country = rgpost('input_28_6');
# PAYMENT METHOD: CREDIT CARD
if($payment_method == "Credit Card") {
//echo 'CC payment';
# EXP DATE
$exp_date = rgpost("input_10_2"); // array of two dropdowns
$form_data['exp_date'] = str_pad($exp_date[0], 2, "0", STR_PAD_LEFT) ."-". $exp_date[1];
# NAME ON CARD
$form_data["card_name"] = rgpost("input_10_5"); // single field
$names = explode(" ", $form_data["card_name"]); // explode to array
$form_data["first_name"] = rgar($names,0); // first-name
$form_data["last_name"] = ""; // last-name
if(count($names) > 0){
unset($names[0]);
$form_data["last_name"] = implode(" ", $names);
}
# CC FIELDS
$verify->card_num = rgpost("input_10_1");
$verify->exp_date = $form_data["exp_date"];
$verify->card_code = rgpost("input_10_3"); //ccv
$verify->first_name = $form_data["first_name"]; //api needs separate fields
$verify->last_name = $form_data["last_name"]; //api needs separate fields
} //credit cards
else {
// # PAYMENT METHOD: E-CHECK
// # NAME - Credit-card has a single "name on card" field, exploded to First-name and Last-name. E-checks doesn't have access to that field, so we use the normal FName/LName fields here. Then the "name on bank acct" field is used for "bank_acct_name" api-field.
// $verify->first_name = rgpost("input_1_3");
// $verify->last_name = rgpost("input_1_6");
// # BANK INFO
// $verify->bank_aba_code = rgpost("input_9");
// $verify->bank_acct_num = rgpost("input_10");
// $verify->bank_acct_type = 'CHECKING';
// $verify->bank_name = rgpost("input_11");
// $verify->bank_acct_name = rgpost("input_12"); //name on bank account
// $verify->echeck_type = 'WEB';
// NOT using AuthNet PHP-SDK's setECheck() here. But.. it has wrong var. Should be bank_acct_name, but uses bank_acct_type, so AuthNet Merch-Interface shows "CHECKING" instead of the person's name. For this my site, we fixed the bug in the php-sdk (plugins/gravityformsauthorizenet/api/lib/AuthorizeNetAIM.php). If the wp-addon is ever updated, this fix will be lost, and must be re-implemented.
} //eChecks
# API RESPONSE
$response = $verify->authorizeOnly();
if($response->approved != 1){
// NOT APPROVED!
$validation_result["is_valid"] = false;
$message = $response->response_reason_text;
$code = $response->response_reason_code;
$my_payment_error = $code; // error! Used for generic validation message, in change_message
# Validation Messages for each field
foreach($form["fields"] as &$field){
if($payment_method == "Credit Card"){
# credit-card field group
if($field["id"] == "10"){
$field["failed_validation"] = true;
$field["validation_message"] = $message;
break;
}
}//cc
else { //eChecks
// # aba/routing number
// if($code == "9"){
// if($field["id"] == "9"){ //bank-aba field
// $field["failed_validation"] = true;
// $field["validation_message"] = $message;
// break;
// }
// }
// # bank acct number
// if($code == "10"){
// if($field["id"] == "10"){ //bank-acct field
// $field["failed_validation"] = true;
// $field["validation_message"] = $message;
// break;
// }
// }
}//echecks
} //foreach($form["fields"]
} else { //if($response->approved != 1)
//APPROVED!!!
//if payment info approved, setup the ARB
$subscription = new AuthorizeNet_Subscription;
$subscription->name = "Monthly Donation to Americas Fund";
$subscription->amount = str_replace('$','',rgpost("input_12"));
//$subscription->cust_id = rgpost("input_14"); // my Customer Account Number
//$subscription->invoice_num = rgpost("input_7"); // my Invoice Number
$subscription->customerEmail = rgpost('input_30');
# UNIQUE ID -- GF puts a Unique ID in the AuthNet Invoice field. But we use that field for the my Invoice. But it's nice to have the Unique ID somewhere in AuthNet, so let's add it to the Description field.
$web_submission_id = uniqid();
$subscription->orderDescription =
"Web-Form: ".$form["title"] .", ".
"Web-Submission-ID: ".$web_submission_id;
# ADDRESS
$form_data["address1"] = rgpost('input_28_1');
$form_data["address2"] = rgpost('input_28_2'); // not required
$form_data["address"] = trim($form_data["address1"] . " " . $form_data["address2"]);
$subscription->billToAddress = $form_data["address"];
$subscription->billToCity = rgpost('input_28_3');
$subscription->billToState = rgpost('input_28_4');
$subscription->billToZip = rgpost('input_28_5');
$subscription->billToCountry = rgpost('input_28_6');
//NOT SETTABLE THROUGH THE FORM
$subscription->intervalLength = "1";
$subscription->intervalUnit = "months";
$subscription->startDate = date('Y-m-d');
$subscription->totalOccurrences = "9999";
# PAYMENT METHOD: CREDIT CARD
$payment_method = rgpost('input_37');
if($payment_method == "Credit Card"){
//echo 'CC payment';
# EXP DATE
$exp_date = rgpost("input_10_2"); // array of two dropdowns
$form_data['exp_date'] = str_pad($exp_date[0], 2, "0", STR_PAD_LEFT) ."-". $exp_date[1];
# NAME ON CARD
$form_data["card_name"] = rgpost("input_10_5"); // single field
$names = explode(" ", $form_data["card_name"]); // explode to array
$form_data["first_name"] = rgar($names,0); // first-name
$form_data["last_name"] = ""; // last-name
if(count($names) > 0){
unset($names[0]);
$form_data["last_name"] = implode(" ", $names);
}
# CC FIELDS
$subscription->creditCardCardNumber = rgpost("input_10_1");
$subscription->creditCardExpirationDate = $form_data["exp_date"];
$subscription->creditCardCardCode = rgpost("input_10_3"); //ccv
$subscription->billToFirstName = $form_data["first_name"]; //api needs separate fields
$subscription->billToLastName = $form_data["last_name"]; //api needs separate fields
} //credit cards
else {
// # PAYMENT METHOD: E-CHECK
// # NAME - Credit-card has a single "name on card" field, exploded to First-name and Last-name. E-checks doesn't have access to that field, so we use the normal FName/LName fields here. Then the "name on bank acct" field is used for "bank_acct_name" api-field.
// $subscription->first_name = rgpost("input_1_3");
// $subscription->last_name = rgpost("input_1_6");
// # BANK INFO
// $subscription->bank_aba_code = rgpost("input_9");
// $subscription->bank_acct_num = rgpost("input_10");
// $subscription->bank_acct_type = 'CHECKING';
// $subscription->bank_name = rgpost("input_11");
// $subscription->bank_acct_name = rgpost("input_12"); //name on bank account
// $subscription->echeck_type = 'WEB';
// NOT using AuthNet PHP-SDK's setECheck() here. But.. it has wrong var. Should be bank_acct_name, but uses bank_acct_type, so AuthNet Merch-Interface shows "CHECKING" instead of the person's name. For this my site, we fixed the bug in the php-sdk (plugins/gravityformsauthorizenet/api/lib/AuthorizeNetAIM.php). If the wp-addon is ever updated, this fix will be lost, and must be re-implemented.
} //eChecks
//reference
$refId = "ref" . time();
// Create the request and send it.
$request = new AuthorizeNetARB;
$request->setRefId($refId);
$response = $request->createSubscription($subscription);
global $my_payment_error;
$my_payment_error = 0; //default= 0 (ok, no error)
if ($response->getMessageCode() !== 'I00001') { //if subscription not successful
//error!
//$validation_result["is_valid"] = false;
//echo 'ERROR: ' . $response->getMessageCode();
//$errormessage = $response->getMessageCode() . ' || ' . $response->getMessageText().' RefId: '.$response->getRefId();
//$code = $response->getMessageCode();
//$my_payment_error = $code; // error! Used for generic validation message, in change_message
$myerror = '<pre>'.$response->getMessageCode().'</pre>';
error_log($myerror);
$validation_result["is_valid"] = false;
$message = $response->getMessageText();
$code = $response->getMessageCode();
$my_payment_error = $message . ' &&& ' . $code; // error! Used for generic validation message, in change_message
# Validation Messages for each field
foreach($form["fields"] as &$field){
if($payment_method == "Credit Card"){
# credit-card field group
if($field["id"] == "10"){
$field["failed_validation"] = true;
$field["validation_message"] = $message;
break;
}
}//cc
}
}
}
} elseif ($frequency == 'One-time') { // Single transaction
$sale = new AuthorizeNetAIM;
# BASIC FIELDS
$sale->amount = str_replace('$','',rgpost("input_12"));
//$sale->cust_id = rgpost("input_14"); // my Customer Account Number
//$sale->invoice_num = rgpost("input_7"); // my Invoice Number
$sale->email = rgpost('input_2');
# UNIQUE ID -- GF puts a Unique ID in the AuthNet Invoice field. But we use that field for the my Invoice. But it's nice to have the Unique ID somewhere in AuthNet, so let's add it to the Description field.
$web_submission_id = uniqid();
$sale->description =
"Web-Form: ".$form["title"] .", ".
"Web-Submission-ID: ".$web_submission_id;
# ADDRESS
$form_data["address1"] = rgpost('input_28_1');
$form_data["address2"] = rgpost('input_28_2'); // not required
$form_data["address"] = trim($form_data["address1"] . " " . $form_data["address2"]);
$sale->address = $form_data["address"];
$sale->city = rgpost('input_28_3');
$sale->state = rgpost('input_28_4');
$sale->zip = rgpost('input_28_5');
$sale->country = rgpost('input_28_6');
# PAYMENT METHOD: CREDIT CARD
$payment_method = rgpost('input_37');
if($payment_method == "Credit Card"){
//echo 'CC payment';
# EXP DATE
$exp_date = rgpost("input_10_2"); // array of two dropdowns
$form_data['exp_date'] = str_pad($exp_date[0], 2, "0", STR_PAD_LEFT) ."-". $exp_date[1];
# NAME ON CARD
$form_data["card_name"] = rgpost("input_10_5"); // single field
$names = explode(" ", $form_data["card_name"]); // explode to array
$form_data["first_name"] = rgar($names,0); // first-name
$form_data["last_name"] = ""; // last-name
if(count($names) > 0){
unset($names[0]);
$form_data["last_name"] = implode(" ", $names);
}
# CC FIELDS
$sale->card_num = rgpost("input_10_1");
$sale->exp_date = $form_data["exp_date"];
$sale->card_code = rgpost("input_10_3"); //ccv
$sale->first_name = $form_data["first_name"]; //api needs separate fields
$sale->last_name = $form_data["last_name"]; //api needs separate fields
} //credit cards
else {
echo 'not credit card';
# PAYMENT METHOD: E-CHECK
// # NAME - Credit-card has a single "name on card" field, exploded to First-name and Last-name. E-checks doesn't have access to that field, so we use the normal FName/LName fields here. Then the "name on bank acct" field is used for "bank_acct_name" api-field.
// $sale->first_name = rgpost("input_1_3");
// $sale->last_name = rgpost("input_1_6");
// # BANK INFO
// $sale->bank_aba_code = rgpost("input_9");
// $sale->bank_acct_num = rgpost("input_10");
// $sale->bank_acct_type = 'CHECKING';
// $sale->bank_name = rgpost("input_11");
// $sale->bank_acct_name = rgpost("input_12"); //name on bank account
// $sale->echeck_type = 'WEB';
// NOT using AuthNet PHP-SDK's setECheck() here. But.. it has wrong var. Should be bank_acct_name, but uses bank_acct_type, so AuthNet Merch-Interface shows "CHECKING" instead of the person's name. For this my site, we fixed the bug in the php-sdk (plugins/gravityformsauthorizenet/api/lib/AuthorizeNetAIM.php). If the wp-addon is ever updated, this fix will be lost, and must be re-implemented.
} //eChecks
# API RESPONSE
$response = $sale->authorizeAndCapture();
# DEBUG
// echo "<h1>response</h1> <pre>"; print_r($response); echo "</pre> <hr />";
// echo "<h1>sale</h1> <pre>"; print_r($sale); echo "</pre> <hr /> ";
// echo "<h1>form</h1> <pre>"; print_r($form); echo "</pre> <hr />";
// //echo "<h1>entry</h1> <pre>"; print_r($entry); echo "</pre> <hr />"; //not available on "gform_validation" hook.
# VALIDATION based on AuthNet Response
// if card was declined, show message, and dont do Entry.
global $my_payment_error;
$my_payment_error = 0; //default= 0 (ok, no error)
if($response->approved != 1){ // NOT Approved
$validation_result["is_valid"] = false;
$message = $response->response_reason_text;
$code = $response->response_reason_code;
$my_payment_error = $code; // error! Used for generic validation message, in change_message
# Validation Messages for each field
foreach($form["fields"] as &$field){
if($payment_method == "Credit Card"){
# credit-card field group
if($field["id"] == "10"){
$field["failed_validation"] = true;
$field["validation_message"] = $message;
break;
}
}//cc
else { //eChecks
// # aba/routing number
// if($code == "9"){
// if($field["id"] == "9"){ //bank-aba field
// $field["failed_validation"] = true;
// $field["validation_message"] = $message;
// break;
// }
// }
// # bank acct number
// if($code == "10"){
// if($field["id"] == "10"){ //bank-acct field
// $field["failed_validation"] = true;
// $field["validation_message"] = $message;
// break;
// }
// }
}//echecks
} //foreach($form["fields"]
} //if($response->approved != 1)
# ADD SYSTEM DATA
# Since we're bypassing the GF AuthNet Add-on, we don't get the benefit of the special payment fields it creates and populates. So instead, we created hidden fields in the form, to contain data from the AuthNet Response (the Transaction ID), and any other data generated by our api call (the Web Submission ID).
$_POST['input_38'] = $response->transaction_id;
$_POST['input_39'] = $web_submission_id;
}
}// end credit cards or echecks
# WRAP UP VALIDATION
// Ref: http://www.gravityhelp.com/documentation/page/Using_the_Gravity_Forms_%22gform_validation%22_Hook
$validation_result['form'] = $form;
return $validation_result;
} else {
//echo 'not page 3';
return $validation_result;
}
} //function my_anet_aim_echeck
/**
* E-COMM -- VALIDATION MESSAGE (for GravityForms)
*
* The general message at the top of the page. If the error is from AuthNet Response (a decline or error), then use this message (with the Error Code), instead of the default.
*/
add_filter("gform_validation_message_10", "change_message", 10, 2);
function change_message($message, $form){
global $my_payment_error;
//global $errormessage;
if($my_payment_error !== 0){
//$message = "<div class='validation_payment_error'><strong>Sorry!</strong> There was a problem with your payment. Please check your information below. If you need assistance, please contact us and mention ERROR ".$my_payment_error.".".date('Y-m-d')."</div> ";
//$message = $errormessage;
$message = $my_payment_error.'<--error';
}
return $message;
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment