Alter authorize.net transaction key dynamically? - php

I am currently building an ecommerce website that is used for 5 separate companies using woocommerce and authorize.net for the payment.
So far the authorization is working great for a single vendor, the issue comes in that once I have selected the vendor by location, I need to change the api_transaction_key and api_login_id to the correct vendor before payment is processed.
I have been searching the files for hours now and cannot find where the key and id are set.
Can someone help me find where I can overwrite the key and id values to what I need?
or would it be better to create a new payment gateway for each of the vendors and copy all of the authorize.net gateway information except the key and id?

This answer is here for if anyone is curious on how I was able to make this work.in the Authorize.net woocommerce payment gateway you'll find a file called
class-wc-authorize-net-cim-api.php
and it is in this file's contruct function that your hook needs to be placed.
public function __construct( $api_user_id, $api_transaction_key, $environment ) {
// File default code
}
This needs the follow three lines of code to be placed BEFORE the default file code
$custom_auth_info = apply_filters('get_custom_auth', $custom_auth_info );
$api_user_id = $custom_auth_info['api_user_id'];
$api_transaction_key = $custom_auth_info['api_transaction_key'];
The apply_filters refers to the following function that is placed in my plugin
add_filter('get_custom_auth', 'select_distributor_by_state');
function select_distributor_by_state($custom_auth_info = []) {
global $wpdb;
//Your Query is here to select the proper distributor from the DB
//and retrieve their custom Authorize.net ID and Transaction Key
$custom_auth_info['api_user_id'] = $your_query[0]['api_loginid'];
$custom_auth_info['api_transaction_key'] = $your_query[0]['api_transactionkey'];
$_SESSION['dealer'] = $vendor[0]['id'];
return $custom_auth_info;
}
This filter allows you to hook in, grab the data you need, then return it and apply it directly into the code before the payment is processed.

Related

Add custom fields to Stripe checkout information and send via webhook

I am using wordpress to build a website that uses Stripe as its payment gateway.
Through the Paid Membership Pro plugin I have configured my Stripe connection.
The issue I am faced with is that I need to append a custom field, in this case a unique identifier for the customer, to the payment information for it to be available to send via my webhook to my server for processing.
I have come across a load of answers but none seem to be doing exactly what I am looking for.
I noticed in the PMPro plugin it allows you to add User Fields which I presumed would be a way to add custom data to the information but after checking the JSON payloads in Stripe none of the user field information is available.
I then tried adding the code from this answer to my functions.php file in word press just using a test meta key but again this information was not available in the payloads.
I am not using woocommerce.
How can I achieve this?
So I was able to crack this using a php script that intercepts the Stripe checkout event.
I added this as a snippet to my Wordpress site and to read in a custom field from the post submit.
Stripe allows you to add custom filed data to the metadata block and once populated this was successfully sent to my webhook.
function my_pmpro_stripe_params_send_user_id( $params, $order = null ) {
global $my_pmpro_checkout_order;
if ( empty( $params['metadata'] ) ) {
$params['metadata'] = array();
}
if ( empty ( $order ) ) {
// Save order while creating payment intent.
$order = $my_pmpro_checkout_order;
} else {
// Use saved order while creating subscription.
$my_pmpro_checkout_order = $order;
}
$params['metadata']['my_custom_field'] = $_POST['my_custom_value'];
return $params;
}
add_filter( 'pmpro_stripe_payment_intent_params', 'my_pmpro_stripe_params_send_user_id', 10, 2 );
add_filter( 'pmpro_stripe_create_subscription_array', 'my_pmpro_stripe_params_send_user_id', 10, 1 );

Edit WC shipping method on orders

I want to simply change the shipping method of an order on Woocommerce.
I have seen a few posts on editing shipping methods on orders but I'm not 100% clear on the exact protocol of how it works, I have a rough idea but no success yet! If you can help me to get the order to update its shipping method that would be awesome! (this is the middle of a large project so I can't share the whole plugin, let me know if you need anymore details happy to provide anything that's necessary!)
I have this small bit of code that returns me a list of orders that need shipping method updated and the new shipping method rateID that it has to be changed to, that all works fine but i have included it so you can see where it comes from.
Once the array of orders to be updated has been constructed, it then needs to be processed using the set_shipping() method. One at a time working through the array items and updating the shipping method of each, from the original to the new one provided in the toUpdate array
UPDATED: i have tried using the WC_API_Orders() class as set_shipping is a method of that. still coming up with the unrecognised error.
'Class 'Inc\Api\Callbacks\WC_API_Orders' not found'
private function updateRound()
{
if (! empty($_POST['update'])) {
$updateorderID= $_POST['orderID']; //get list of orderID to change
$updateRound= $_POST['newRound']; //list of rounds new orders want swapped to
$updateList= $_POST['update']; //uses a check box to confirm user wants to update row (stops accidentally updating the whole list)
// print_r($_POST['update']); //shows an output to check results.
$toUpdate = []; //this is the array for all the shippingmmethods to update on set order etc.
//make list of order ID's to update and their new shipping method
foreach ($updateList as $key => $value) {
$toUpdate[] = [
'orderID' => $key,
'newRound' => $updateRound[$key]
];
}
}
$absOrder = new WC_API_Orders();
foreach ($toUpdate as $updateOrder) {
//echo "</br>OrderID: ".$updateOrder['orderID']." Round updated to ".$updateOrder['newRound'];
echo "order ".$updateOrder['orderID']."updating";
$absOrder->wc_get_order($updateOrder['orderID']);
echo " order retreived";
$absOrder->set_shipping($order, $updateOrder['newRound'], 'update' );
echo "updated </br>";
}
}
This is for a very local veg delivery scheme, people can only place an order if their postcode is in the set group, so that's not so important, this shipping method we use to change from 'wed round' to 'thurs round' etc. Simple really no concern for delivery companies etc, its all in house. Tax etc. doesn't matter, it's all done elsewhere, this is simply meant to be a way of editing orders onto delivery rounds.

Magento - Store Views and multiple currencies - Checkout using base currency always

I have a magento website
We have a store
In a store we have multiple store views (US, EU and UK)
Each store view has it's own currency, etc.
The base currency is GBP at the default config (main)
My problem is that the display currencies work well. Each store view has it's own individual price (no automatic conversion). Everything seems to be working and in order. However, on the final payment emails and actual connection with payment providers (PayPal/Sage). The base currency is always used. Although the display appears in the currency for each store view.
My question is why are the store view currencies not used with PayPal, emails, etc. Although the amounts, display currency, etc work fine?
It turns out that Base Currency can be set on each Store View. However, this option was not presented on the admin side. I had to change the system.xml
app/code/core/Mage/Directory/etc/system.xml
<label>Base Currency</label>
I have to set the appropriate to change from 0 to 1
<show_in_store>1</show_in_store>
Once this was done, I could see Base Currency under "Currency Options" even within a store view. This now works well and everything seems to be working fine.
No PHP code changes or any additional plugins required.
When I had run into this issue with a rather large Magento store, this quick fix worked pretty well for me: Magento knowledge-base paypal base currency tweak
Just note that, that fix probably won't work out of the box but it'll take some tweaking
Here it is some solutions.
You might custom some codes
If you are using Paypal Express,
\app\code\core\Mage\Paypal\Model\Express.php
protected function _placeOrder(Mage_Sales_Model_Order_Payment $payment, $amount)
{
$order = $payment->getOrder();
// prepare api call
$token = $payment->getAdditionalInformation(Mage_Paypal_Model_Express_Checkout::PAYMENT_INFO_TRANSPORT_TOKEN);
$api = $this->_pro->getApi()
->setToken($token)
->setPayerId($payment->
getAdditionalInformation(Mage_Paypal_Model_Express_Checkout::PAYMENT_INFO_TRANSPORT_PAYER_ID))
->setAmount($amount)
->setPaymentAction($this->_pro->getConfig()->paymentAction)
->setNotifyUrl(Mage::getUrl('paypal/ipn/'))
->setInvNum($order->getIncrementId())
**->setCurrencyCode($order->getOrderCurrencyCode())** // should be used getOrderCurrencyCode();
->setPaypalCart(Mage::getModel('paypal/cart', array($order)))
->setIsLineItemsEnabled($this->_pro->getConfig()->lineItemsEnabled)
;
if ($order->getIsVirtual()) {
$api->setAddress($order->getBillingAddress())->setSuppressShipping(true);
} else {
$api->setAddress($order->getShippingAddress());
$api->setBillingAddress($order->getBillingAddress());
}
// call api and get details from it
$api->callDoExpressCheckoutPayment();
$this->_importToPayment($api, $payment);
return $this;
}
\app\code\core\Mage\Paypal\Model\Standard.php
public function getStandardCheckoutFormFields()
{
$orderIncrementId = $this->getCheckout()->getLastRealOrderId();
$order = Mage::getModel('sales/order')->loadByIncrementId($orderIncrementId);
/* #var $api Mage_Paypal_Model_Api_Standard */
$api = Mage::getModel('paypal/api_standard')->setConfigObject($this->getConfig());
$api->setOrderId($orderIncrementId)
**->setCurrencyCode($order->getOrderCurrencyCode())** // should be used getOrderCurrencyCode();
//->setPaymentAction()
->setOrder($order)
->setNotifyUrl(Mage::getUrl('paypal/ipn/'))
->setReturnUrl(Mage::getUrl('paypal/standard/success'))
->setCancelUrl(Mage::getUrl('paypal/standard/cancel'));
// export address
$isOrderVirtual = $order->getIsVirtual();
$address = $isOrderVirtual ? $order->getBillingAddress() : $order->getShippingAddress();
if ($isOrderVirtual) {
$api->setNoShipping(true);
} elseif ($address->validate()) {
$api->setAddress($address);
}
// add cart totals and line items
$api->setPaypalCart(Mage::getModel('paypal/cart', array($order)))
->setIsLineItemsEnabled($this->_config->lineItemsEnabled)
;
$api->setCartSummary($this->_getAggregatedCartSummary());
$api->setLocale($api->getLocaleCode());
$result = $api->getStandardCheckoutRequest();
return $result;
}

Magento - Insufficient Stock Notification on Product Page

I am using Magento 1.7.0.2. Whilst on the product page, if a customer attempts to add a quantity greater than we have in stock they receive a message stating ".. the requested quantity is not available".
Is there any way for magento to either email or log when this occurs? I.e. I receive an automatic email stating a customer has attempted to add X number of item X? This would allow me to identify lost sales due to us not having enough stock of a particular item?
Has anyone come across anything like this before or is this even possible?
Thank you in advance
Mike Prentice
yes this is possible
You have to code for this.
I came across this problem one time and what i have do like this below.
I have make one observer event to check if customer is requesting quantity more then available if so i sent email to admin.
What you can do is create one observer for chekout_cart_add_before event in this event you can put your logic.
Or otherwise you can use magento feature Backorders you can find this in inventory tab,if you enable this then customer can order even requested quantity > available quantity, customer can see one message in cart page about backorder.
There is no standart functionality to notify about low quantity products by email.
But there is RSS notification http://www.magentocommerce.com/wiki/modules_reference/english/mage_adminhtml/system_config/edit/cataloginventory
Extend this functionality to match your needs.
You could write some script which would parse RSS, and send email etc.
EDIT
Here is some extension you may like http://www.magentocommerce.com/magento-connect/low-stock-email-notification.html
But is is not free.
Here's how I've done it so that it sends a google analytics tracking event whenever a customer tries to order more than the available stock level.
First copy: app/code/core/Mage/CatalogInventory/Model/Stock/Item.php
To: app/code/local/Mage/CatalogInventory/Model/Stock/Item.php
so that you're not modifying a core file.
In app/code/local/Mage/CatalogInventory/Model/Stock/Item.php add this function
public function notifyOutOfStock($productId){
$session = Mage::getSingleton('checkout/session');
//Initialise as empty array, or use existing session data
$outOfStockItems = array();
if ($session->getOutOfStock()){
$outOfStockItems = $session->getOutOfStock();
}
try {
$product = Mage::getModel('catalog/product')->load($productId);
$sku = $product->getSKu();
if($sku){
//Add the current sku to our out of stock items (if not already there)
if(! isset($outOfStockItems[$sku]) ) {
$outOfStockItems[$sku] = 0;
}
}
} catch (Exception $e){
//Log your error
}
Mage::getSingleton('checkout/session')->setOutOfStock($outOfStockItems);
}
In that same file is another function called checkQuoteItemQty.
Inside that function you need to call your new function using $this->notifyOutOfStock($this->getProductId()); right after it sets each of the error messages and before the return statement.
So:
public function checkQuoteItemQty($qty, $summaryQty, $origQty = 0)
{
....
if ($this->getMinSaleQty() && ($qty) < $this->getMinSaleQty()) {
$result->setHasError(true)
->setMessage(
$_helper->__('The minimum quantity allowed for purchase is %s.', $this->getMinSaleQty() * 1)
)
->setQuoteMessage($_helper->__('Some of the products cannot be ordered in requested quantity.'))
->setQuoteMessageIndex('qty');
//** Call to new function **
$this->notifyOutOfStock($this->getProductId());
return $result;
}
.....
->setQuoteMessageIndex('qty');
//** Call to new function **
$this->notifyOutOfStock($this->getProductId());
return $result;
.....
What this does is add your product sku to an array in the checkout session.
This means you will have access to that info in the template file right after your page loads displaying the "Insufficient stock" notification.
So in one of your template files you can add some code to render the necessary JavaScript.
I've chosen header.phtml since it loads on every page. (Users can add quantities of items to the cart in the cart page as well as the product view page).
app/design/frontend/CUSTOMNAME/default/template/page/html/header.phtml
Somewhere down the bottom of the code add this:
<!-- GA tracking for out of stock items -->
<script>
try {
<?php
$session = Mage::getSingleton('checkout/session');
if ($session->getOutOfStock()){
$outOfStockItems = $session->getOutOfStock();
foreach($outOfStockItems as $sku=>$value) {
if($value==0){
//Render the GA tracking code
echo "_gaq.push(['_trackEvent', 'AddToCart', 'ProductQtyNotAvailable', '".$sku."']); \r\n";
//Set it to 1 so we know not to track it again this session
$outOfStockItems[$sku] = 1;
}
}
//Update the main session
Mage::getSingleton('checkout/session')->setOutOfStock($outOfStockItems);
}
?>
}
catch(err) {
//console.log(err.message);
}
</script>
Can confirm this works well and in my opinion is better than an email or RSS feed as you can analyse it along with the rest of your analytics.

Set subscriber status in Magento programmatically

I am trying to write a module that syncs my newsletter subscribers in Magento with a external database. I need to be able to update the subscription status in Magento programmatically but I am having diffuculty getting the "setStatus" method in Magento to work. It does not throw any errors but the code does not seem to have any effect. Below is the code where I call the method:
$collection = Mage::getResourceModel('newsletter/subscriber_collection')->showStoreInfo()->showCustomerInfo();
foreach ($collection as $cust) {
$cust->setStatus(1);
}
In theory, this should set the status of all of my subscribers to "subscribed". I could optionally change the argument sent to "setStatus" to any of the below ints for a different status.
1: Subscribed
2: Status Not Active
3: Unsubscribed
How to best change the subscriber status or get this code working?
Here an import script:
<?php
require_once("./app/Mage.php");
Mage::app();
$subscribers = array('email1#server1.com', 'email2#server2.com');
foreach ($subscribers as $email) {
# create new subscriber without send an confirmation email
Mage::getModel('newsletter/subscriber')->setImportMode(true)->subscribe($email);
# get just generated subscriber
$subscriber = Mage::getModel('newsletter/subscriber')->loadByEmail($email);
# change status to "subscribed" and save
$subscriber->setStatus(Mage_Newsletter_Model_Subscriber::STATUS_SUBSCRIBED);
$subscriber->save();
}
?>
It seems that newsletter subscribers are also stored elsewhere. What you are setting is just a check in the customer base for some other use.
You need to do the following for each customer as well.
Mage::getModel('newsletter/subscriber')->subscribe($email);
See this link for a complete reference.
Thanks to the link #Ozair shared I was able to figure out what I needed to do.
I was successfully setting the status of the subscriber in the Magento subscriber object but I was not saving the object. I needed to call Magento's save method so it would call the ORM and write it to the database. All I need to do was add
$cust->save();
in the for loop. Below is the whole code snippet.
$collection = Mage::getResourceModel('newsletter/subscriber_collection')->showStoreInfo()->showCustomerInfo();
foreach ($collection as $cust) {
$cust->setStatus(1);
$cust->save();
}
I Hope this helps someone in the future. I needed it for a Constant Contact - Magento Synchronization extension I was making: http://www.freelunchlabs.com/store/constant-contact-and-magento-sync.html

Categories