Authorize.net and Custom Fields

  • Posts: 10
  • Thank you received: 0
10 years 5 months ago #160820

Hi guys,

I have a few questions about how to make the Authorize.net plugin work properly for my purposes.

QUESTION 1
I found out that I could add items to the Curl Request that goes to Authorize.net as follows:

In authrorize.php in function _loadStandardVars(&$order) I added the following line:

$vars["x_description"]='My description text';

That sends my description text through to Authorize.net and displays it on the customer receipt that Authorize.net sends out as well.

I need to know how I load variables into a payment plugin from custom fields, so that I can get data from the product, cart, etc. and use them in the payment plugin. I have custom fields in both the Order and the Item tables.

QUESTION 2

In function onBeforeOrderCreate(&$order,&$do) the CURL request is built and sent and the response is parsed.

I saw that the only the following information was being parsed from the data that Authorize.net sends back:
		$response_subcode     	= @$response_array[1];
		$response_reason_code 	= @$response_array[2];
		$response_reason_text 	= @$response_array[3];

Since there is other data in the Authorize.net response that I want to preserve I added the following lines:
		$response_auth_code 	= @$response_array[4]; // Authorization Code
		$response_trans_id 	= @$response_array[8]; // Transaction ID
		$response_account 	= @$response_array[52]; // Account Number (Last 4 digits of card)
		$response_card_type 	= @$response_array[53]; // Card Type

I also added corresponding custom fields in the Order table (_hikashop_order in the DB) and I need to know how to populate those fields with the data I get back from Authorize.net.

I want to be able to view the data under Orders in the admin and I want the customer to be able to view some of that information on their email receipt and on the order view.

In your sample code I have seen the following in the onPaymentNotification(&$statuses) function:
$this->modifyOrder($order_id, $this->payment_params->verified_status, true, true);

Is there some variation of that that I can use to get the custom fields and Authorize.net response data into the orders table in the DB?

I have also thought about just using a MySQL query to push the information from the Authorize.net response into the DB, but I'd rather use the functions that are already built into the extension if possible.

QUESTION 3

In order to generate an activation key that users will be purchasing through HikaShop I need to do the following:
1) Run a MySQL query on one of my other Joomla tables
2) Use the results from that to query a remote script
3) Take the response from the remote script and load it into the _hikashop_order table, attached to an item.
4) Display the Activation Key that the remote script generated on the Thank You page.

I purchased HikaSerial and tried unsuccessfully to create a HikaSerial plugin to perform this function. Nothing I tried would make my pack generator appear or work properly, so I have abandoned that for now.

I have viewed the information in the docs on writing a custom plugin, but the documentation doesn't really have enough information about how to get data into and out of a plugin from the main extension, from controllers or from other plugins. It would be really helpful if the documentation was a little clearer about this for those of us that need to make modifications. I also searched the forum, but there is vary little in here about this topic also.

I know you guys are great programmers and this is a great extension. I'm hoping you'll be able to assist me in finding the information I need. I will gladly update this post with the solution when I get it working.

Thanks in advance for your help.

Last edit: 10 years 5 months ago by convergent.

Please Log in or Create an account to join the conversation.

  • Posts: 82868
  • Thank you received: 13376
  • MODERATOR
10 years 5 months ago #160883

Hi,

1. All the custom fields data is available in the $order object there. So for example:
echo $order->field;
or:
echo $order->products[0]->field;

2. SQL is fine. It's not like we'll change the name of the table or the name of your custom fields in the future.
But if you really want you can do like that:
$class = hikashop_get('class.order');
$orderObj = new stdclass ();
$orderObj->order_id = $order_id;
$orderObj->field = $response_trans_id;
$class->save($orderObj);

However, If you're concerned about updates, I would recommend to rename the plugin to have your own version or you'll loose the changes each time you update HikaShop.

3. Jerome would be better suited to answer you regarding how to create a HikaSerial plugin. You should post on the HikaSerial forum about that.
Otherwise, if you want to do it all yourself, that would be quite easy to implement. Just have a hikashop plugin implementing the onAfterOrderUpdate and if the status changes in the $order passed to the function ($order->order_status!=$order->old->order_status) and that the new one is confirmed, then you can do your processing directly in the function. You could also add that directly in the onPaymentNotification function of the authorize.net plugin after the modifyOrder

Please Log in or Create an account to join the conversation.

  • Posts: 10
  • Thank you received: 0
10 years 5 months ago #161021

I have the following custom fields in my Orders table:

order_transaction_id
order_account
order_card_type
order_auth_code

All fields are published the field type is 'text' and none are set to 'core'.

These each correspond to a field in the Authorize.net response array.

This is the code I am trying in the function onPaymentNotification(&$statuses) function in authorize.php:

Right below this:

	 	if($vars['x_response_code']==1){
	 		$order_status = $this->payment_params->verified_status;
	 		$vars['payment_status']='Accepted';

I had this:
		$response_auth_code 	= @$response_array[4]; // Authorization Code
		$response_trans_id 	= @$response_array[8]; // Transaction ID
		$response_account 	= @$response_array[52]; // Account Number (Last 4 digits of card)
		$response_card_type 	= @$response_array[53]; // Card Type
		
		$class = hikashop_get('class.order');
		$orderObj = new stdclass ();
		$orderObj->order_id = $order_id;
		$orderObj->order_auth_code =$response_auth_code;
		$class->save($orderObj);

It does nothing at all.

I had previously placing these lines in function onBeforeOrderCreate(&$order,&$do) as follows:
		$response_array = explode("|",$post_response);
		$response_code        	= (int)@$response_array[0];
		$response_subcode     	= @$response_array[1];
		$response_reason_code 	= @$response_array[2];
		$response_reason_text 	= @$response_array[3];
		$response_auth_code 	= @$response_array[4]; // Authorization Code
		$response_trans_id 	= @$response_array[8]; // Transaction ID
		$response_account 	= @$response_array[52]; // Account Number (Last 4 digits of card)
		$response_card_type 	= @$response_array[53]; // Card Type

That also did not work.

When I set the fields to display on the front end and entered sample data into each field it wrote to the table properly.

I have also tried putting test data into my code instead of the variables in case it was not picking anything up...

Example:
		$orderObj->order_auth_code ='12345';

Nope. Nothing.

All I want to do is get data from the Authorize.net response into the orders table. I don't understand why this is so difficult.

Please let me know what I need to do. If you'd like I'll be happy to provide you with access to the demo site so you can take a look at what I have there. I have been working on this for days now without any progress. I need to know if it's time to abandon this extension and start over with something else or if the custom fields can be made to work.

Thanks in advance for your help.

Please Log in or Create an account to join the conversation.

  • Posts: 10
  • Thank you received: 0
10 years 5 months ago #161031

I tried the following in the checkout/after_end view and it wrote to the DB:

		$class = hikashop_get('class.order');
		$orderObj = new stdclass ();
		$orderObj->order_id = $order_id;
		$orderObj->order_auth_code ='Test Auth Code';
		$orderObj->order_card_type ='Test Card Type';
		$class->save($orderObj);

I also tried it inside the onAfterOrderConfirm(&$order,&$methods,$method_id) function, and it wrote to the orders table, but did not confirm the sale.

I could not, however, load any variables into it from the Authorize.net response. I tried var_dump and a bunch of other methods, but the data is hiding from me somewhere.

Every other shopping cart extension I have worked with has made it a lot simpler to view and retain the response data. I do not want to have to log into Authorize.net every time I need to look up information. The structure of the AIM response (as I'm sure you know) has more information in it than what HikaShop currently stores for each transaction.

See
http://www.authorize.net/support/AIM_guide.pdf
page 41 for more info.

Can you PLEASE just let me know what the secret is to the following:

A) How do I get the data from the custom fields into a plugin? (Can you give me a working example for the please for the custom field 'deviceserialnumber' that I have in the Item table?)

B) How do I store the response from Authorize.net (AIM) in the custom fields of my Orders table

C) How do I pull all of the response data from the order into the views? Here is an example of what I'm talking about:

In the checkout/after_end view I have this :
$order_id = $app->getUserState('com_hikashop.order_id');
Which gets the Order ID.

I had this:
$order_invoice_id = $app->getUserState('com_hikashop.order_invoice_id');
Which does nothing.

So this works:
echo 'Order ID: '.$order_id.'<br />';
Order ID: 114

And this does not.
echo 'Order Status: '.$order->order_status.'<br />';
Order Status: (Nothing here)

I have attached a text file of the authorize.php file from the plugin. I have tried to document what I have tried as well as adding comments where applicable.

File Attachment:

File Name: h57bfaab.txt
File Size:19 KB


Can you maybe take a look at this and just let me know what I need to do. Again, this should not be this difficult. Every time I have trouble with this extension I lose another day because it takes at least 24 hours for you to respond. I understand that you are far away, but please understand that I wouldn't be having this trouble with other extensions and I paid you in order to get support. You have given me a few answers, but your answers have not been very specific.

I feel that I have described what I need to know rather well. Please do your users the favor of providing specific answers on how this extension works.

Attachments:
Last edit: 10 years 5 months ago by convergent.

Please Log in or Create an account to join the conversation.

  • Posts: 82868
  • Thank you received: 13376
  • MODERATOR
10 years 5 months ago #161043

Hi,

A. I believe I already told you how to do that:

echo $order->products[0]->field;
So to be more clear with your example field and suppose that your are in one of the functions of the order API with the $order object provided, you can do either like that:
echo $order->products[0]->deviceserialnumber;
or like that:
echo $order->cart->products[0]->deviceserialnumber;
(it depends on the function where you are adding the change)

B. The code
$class = hikashop_get('class.order');
		$orderObj = new stdclass ();
		$orderObj->order_id = $order_id;
		$orderObj->order_auth_code =$response_auth_code;
		$class->save($orderObj);
is fine.
There is no reason it wouldn't work. Note that the authorize.net plugin supports both the AIM and the SIM mode. If you configured the payment method in AIM, the onPaymentNotification function won't be called at all, which would explain why you didn't get the code to work. In AIM, the code should be added in the onBeforeOrderCreate function. However, as the name of the function implies, this is before the order is created so you don't have the order_id yet. In that case, you want to add the order_auth_code directly in the $order object and it will be saved automatically by the system:
$order->order_auth_code =$response_auth_code;

C. The order_invoice_id is never stored in the session and the $order variable is not initialized before the after_end view call so it's normal that these snippets don't work.
Instead, you should do like that:
$order_id = $app->getUserState('com_hikashop.order_id');
$orderClass = hikashop_get('class.order');
$order = $orderClass->loadFullOrder($order_id, true, false);
An example of that code is provided on our developer documentation: www.hikashop.com/support/support/documen...umentation.html#code

D. Please understand that we answer as fast as possible as as best as we can to your questions. I believe I gave each time precise answers to your questions.

Please Log in or Create an account to join the conversation.

  • Posts: 10
  • Thank you received: 0
10 years 5 months ago #161180

I wanted to retain some of the response data from Authorize.net to my Orders table. It took a liitle figuring out, but this is what I came up with:

I placed the following code in the authorize.php file under the onBeforeOrderCreate function at about line 102, just below

$response_reason_text = @$response_array[3];
// ADDED RESPONSE FIELDS
		$response_auth_code 		= @$response_array[4]; // Authorization Code
		$response_transaction_id 	= @$response_array[6]; // Transaction ID
		$response_account 		= @$response_array[50]; // Account Number (Last 4 digits of card)
		$response_card_type 		= @$response_array[51]; // Card Type
		
		$order->order_auth_code 	=$response_auth_code;
		$order->order_transaction_id 	=$response_transaction_id;
		$order->order_account 		=substr($response_account,-4);
		$order->order_card_type 	=$response_card_type;
		$order->order_transaction_response 	=$post_response;

Now it stores the Authorization Code, Transaction ID, Last 4 of Card, Card Type and a copy of the entire response.

Next thing I need to do is use a custom field on each item to run a query on my DB, then use the results from that to query an outside script. If possible, I may do that in the view.

Please Log in or Create an account to join the conversation.

  • Posts: 82868
  • Thank you received: 13376
  • MODERATOR
10 years 5 months ago #161210

So from what I understand, you're using authorize.net in AIM mode. In that case, you'll want to modify the "end" view file (which is displayed at the end of the checkout) instead of the "after_end" view file (which is displayed after the customer has been redirected to the payment gateway form, paid, and is returning back to the website).

There, you'l be able to use the same code I gave on my last C answer to get the order details. You'll be able to save the order with the first snippet of code I put on my B answer. And trigger your outside script as needed by the outside script.

Please Log in or Create an account to join the conversation.

  • Posts: 10
  • Thank you received: 0
10 years 4 months ago #163567

Hi Guys,

In your previous response you mentioned using the following code to save order data...

$class = hikashop_get('class.order');
		$orderObj = new stdclass ();
		$orderObj->order_id = $order_id;
		$orderObj->order_auth_code =$response_auth_code;
		$class->save($orderObj);

Would I use a similar method to save custom field data for an individual product?

Currently I am using the following code in my after_end file to query my DB based on a custom field, then use an external script to generate an Activation Key, then writing that key along with other data to my DB in a custom table:
// GET ACTIVATION KEY 
function getActivationKey($product){
  	$app = JFactory::getApplication();
  	$order_id = $app->getUserState('com_hikashop.order_id');
  	$orderClass = hikashop_get('class.order');
	$order = $orderClass->loadFullOrder($order_id, true, false);
  	$serial = $product->deviceserialnumber;
	$db = JFactory::getDbo();
	$db->setQuery("SELECT `device_dna`,`key_index` FROM `#__[MY CUSTOM DEVICES TABLE]` WHERE `serial`='$serial' LIMIT 1");
	$result = $db->loadObject();
  	// PARSE RESULTS OF QUERY
  	$dna = $result->device_dna;
  	$key_seed = $result->key_index;
  	// GET INFO FROM PRODUCT
  	$feature = $product->order_product_code;
	$feature = substr($feature, 1);
  	$level = $product->order_product_level;
    $days = $product->order_product_quantity;
  	$key_date = date_create()->format('Y-m-d H:i:s');
    $model = $product->order_product_model;
    $price = $product->order_product_price;
  	$order_id = $product->order_id;
  // GET THE USER
  	$user = JFactory::getUser();
  	$key_user = $user->get('id');
  	
// BUILD AUTH SCRIPT REQUEST
  
  // RENTAL or PURCHASE
  if ($level == 'Rented'){
  	$authRequestString = $dna.' '.$feature.' '.$level.' '.$key_seed.' '.$days;
  }else{
    $authRequestString = $dna.' '.$feature.' '.$level;
    $days = 'Permanent';
  }
// TALK TO AUTH SCRIPT
	$outputB = shell_exec('env -i /[b][SOME PATH][/b]/tool_auth '.$authRequestString);
  
// WRITE KEY TO ACTIVATION KEYS TABLE  (This is working just fine)
	$query = $db->getQuery(true);
	$query
    	->insert($db->quoteName('#__[i][MY ACTIVATION KEYS TABLE][/i]'))
      ->columns('key_serial'.','.'key_model'.','.'key_feature'.','.'key_level'.','.'key_seed'.','.'key_days'.','.'key_string'.','.'key_date'.','.'key_user'.','.'key_trans')
    	->values($db->quote($serial).','.$db->quote($model).','.$db->quote($feature).','.$db->quote($level).','.$db->quote($key_seed).','.$db->quote($days).','.$db->quote($outputB).','.$db->quote($key_date).','.$db->quote($key_user).','.$db->quote($order_id));
	$db->setQuery($query);
	$db->query();

// UPDATE DEVICE RECORD
	$new_seed = $key_seed - 1;
	$updevice = $db->getQuery(true);

// RENTAL or PURCHASE
  if ($level == 'Rented'){
  	$outputB = '('.$days.' days) '.$outputB;
  }
	$fields = array(
    	$db->quoteName('key_index') . ' = ' . $db->quote($new_seed),
    	$db->quoteName($feature) . ' = ' . $db->quote($outputB)
);
	$conditions = array(
    	$db->quoteName('serial') . ' = ' . $db->quote($serial),
    	$db->quoteName('active') . ' != 0'
);
 
	$updevice->update($db->quoteName('#__[i][MY CUSTOM DEVICES TABLE][/i]'))->set($fields)->where($conditions);
	$db->setQuery($updevice);
 
	$updevice = $db->query();  
  
// RETURN KEY  (I have this set up for debugging to show me the Query, etc.)
  $outputAll = $outputB .'<br /><br /><div class="borderline">DEBUG<br /><strong>AUTH RESQUEST STRING:</strong> '.$authRequestString.'<br/><br/><strong>MySQL Query: </strong>'.$query.'</div>'; 
  return $outputAll; // This is for debugging
} // END FUNCTION
// END GET ACTIVATION KEY 

Then I am displaying the details (including the activation key I just generated on the page like this:
// LIST PRODUCTS IN ORDER
echo '<fieldset class="hikashop-trans-details">';
echo '<legend>Product List</legend>';
                              foreach($this->order->products as $product){
                                echo '<p class="nomarginall"><strong>Recording Option: </strong>'.$product->order_product_name.' - ('.$product->order_product_level.')</p>';
                                echo '<p class="nomarginall"><strong>Device: </strong>'.$product->order_product_model.' <strong>SN:</strong> '.$product->deviceserialnumber.'</p>';
                                $product_activation_key = getActivationKey($product);
                                //echo '<p class="nomarginall"><strong>Activation Key: </strong>'.getActivationKey($product).'</p>';
                                echo '<p class="nomarginall"><strong>Activation Key: </strong>'.$product_activation_key.'</p>';
							}

echo '</fieldset>';
// END LIST PRODUCTS

I was hoping to maybe move my function to a plugin, but I could not get that to work at all. Basically what I want to do is write all of the order data, including the custom field data from each product back to my DB and also be able to display the custom fields for each product in the Order Creation Notification emails, etc.

A few of the fields are populating in my #__order_product table, but I'm pretty sure that's because I'm feeding those fields with URL parameters when I add the product to the cart using URLs like this:
http://[MY DEMO SITE]/index.php?option=com_hikashop&ctrl=product&task=updatecart&quantity=1&checkout=1&product_id=1&data[item][deviceserialnumber]=76-00114&data[item][order_product_model]=CoolDevice&data[item][order_product_level]=Purchased

I don't want to run the script to generate the Activation Key until after I have confirmation that they have paid, but I do want to be able to send the key to them on their Order Notification email and save it to the proper tables in HikaShop as well as my own custom tables. I need all of the custom field data to display in the back end as well.

Currently the following fields in #_hikashop_order_product (the item table) are not being fed any data:

order_product_activationkey - Custom Field - Needs to be populated by the key that my external script generates. (I am able to save data to this field from the back end.)
order_product_feature - Custom Field - Needs to be populated by the key that my external script generates.

I feel like I'm almost there and don't have a whole lot more to do in order to make this all work, I just need to know how to get the data back into the proper tables and out to the customer on the notification emails.

I'm aware that my code is rather messy. I will be cleaning it up and making it secure and error-free before this goes live.

I'm on a deadline currently and your help is very much appreciated. As I mentioned, I will be happy to document and share my work when I get this project completed. I have built a number of customized views and emails which some users may find helpful.

Cheers,

Erich

Please Log in or Create an account to join the conversation.

  • Posts: 82868
  • Thank you received: 13376
  • MODERATOR
10 years 4 months ago #163579

Hi,

The best will simply be to run a MySQL to update the value of these fields with your data.
You can do like that:

$db->setQuery('UPDATE #__hikashop_order_product SET order_product_acivation_key = '.$db->Quote($serial).', order_product_feature = '.$db->Quote($outputB).' WHERE order_product_id = '(int)$product->order_product_id);
$db->query();
Once the data is in the fields, the data should be displayed automatically by HikaShop in the order notification emails.

Please Log in or Create an account to join the conversation.

  • Posts: 10
  • Thank you received: 0
10 years 4 months ago #163697

Where's the best place to put this type of query? In one of the views or in the payment plugin? Please let me know.

Thanks.

Please Log in or Create an account to join the conversation.

  • Posts: 13201
  • Thank you received: 2322
10 years 4 months ago #163702

Hi,

This code can be put in a view, it depend on when you need it to be executed.
Or you can be in the authorize_end view of the plugin.

Please Log in or Create an account to join the conversation.

Time to create page: 0.086 seconds
Powered by Kunena Forum