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

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;
}

Related

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 multiple currencies on a single domain with no subdirectories

I am trying to set up a website that allows about 6 different currencies. I originally was able to achieve this quite well using the currency exchange rates built into Magento and the customer could select which currency they prefered and all prices were displayed in that currency. However I recently discovered that despite the prices being in that currency Magento will still process the transactions in the base currency, in this case GBP. In fact it doesn't tell the customer this is what will happen until right at the end of the order which in my opinion is a very bad thing, some customers might also be charged more by their banks for the currency conversion.
As PayPal has been configured to allow payments in the 6 currencies I would like the customers to be able to pay in those currencies.
I have since found out that due to the way Magento has been built that this is no easy task and instead you should set up a new 'website' for each of the currencies, then I can set a base currency for each website. This sounds easy enough, however the tutorials about this all seem to force each website to have its own unique url - such as either us.website.com or website.com/us - but in this case that will not do and we need everything to use only the one base url website.com.
Does anyone know if this is possible?
I have been able to change the store by manually adding the following to index.php and I was thinking one possible solution would be to remember the users selection in the session and then load the correct store here. Would this be efficient or is there a better way to do this that I have overlooked?
/* Override store code */
if (isset($_GET['code']))
{
$mageRunCode = $_GET['code'];
$mageRunType = 'website';
}
Mage::run($mageRunCode, $mageRunType);
The website is running Magento Community Edition v1.7.0.2.
I have been able to achieve this using something similar to the following in index.php
if (isset($_GET["currency"]) || !isset($_COOKIE["basewebsite"]))
{
// List of available stores
$stores = array('usd','aud','eur');
$website = 'base'; // Default store ID
if (isset($_GET['currency']) && in_array($_GET['currency'], $stores))
{
$website = $_GET['currency'];
}
// Set cookie to remember selection
setcookie("basewebsite", $website);
$_COOKIE['basewebsite'] = $website;
}
else
{
$website = $_COOKIE['basewebsite'];
}
/* Store or website code */
$mageRunCode = isset($_SERVER['MAGE_RUN_CODE']) ? $_SERVER['MAGE_RUN_CODE'] : $website;
/* Run store or run website */
$mageRunType = isset($_SERVER['MAGE_RUN_TYPE']) ? $_SERVER['MAGE_RUN_TYPE'] : 'website';
Mage::run($mageRunCode, $mageRunType);
With this I can then change the website by simply adding ?currency=usd to the end of any Magento url. The selection is then remembered by the cookie and the correct website is loaded with any further requests.
This question hasn't received many views but if anyone does spot a better solution then please do let me know!

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.

Creating a single random Magento coupon

I'm having some trouble. What I want to do is automatically generate a single random coupon code in Magento each time someone subscribes to our newsletter. The coupon is 10 dollars off anything and will have an exp. date of two weeks after subscription.
So, I'm trying to write a simple script that trips when the "subscribe to our newsletter" form is submitted that will talk to Magento, ask Magento for a single random coupon code, set a few basic price rules (10 bucks off anything, one use per customer, one use per coupon, expires two weeks from generation) and then return a random coupon code (ex:WELCOME5798) which can be stored in a variable that will be passed, along w/ first+last name and e-mail to MailChimp via the MailChimp API. I have all this figured out EXCEPT for how to get Mage to generate such a code via a PHP script and then return said code (i.e. I have my form and I know how to pass values to MailChimp).
I'm new to Magento, so I'm having a tough time. I've seen the code in Mage/SalesRule/Model/Coupon and I've seen some examples of people solving somewhat similar questions, such as here: Magento - Create Unique Coupon Codes through code and mail it to the customer
But I'm really at a loss for where to start making this work for my own purposes. Could use some help/setting straight. :( Thanks folks.
So, what is your question? How to generate coupon for your requirements? Or how to arrange it in module?
You can use event newsletter_subscriber_save_after to inject your custom actions to the subscribe process.
Here is an example of coupon creation according to your needs
<?php
/**
* Create coupon for fixed price discount
*
* #param int $customer_id
* #param float $discount
*/
public function createCoupon($customer_id, $discount)
{
$customer = Mage::getModel('customer/customer')->load($customer_id);
$customerGroupIds = Mage::getModel('customer/group')->getCollection()->getAllIds();
$websitesId = Mage::getModel('core/website')->getCollection()->getAllIds();
$customer_name = $customer->getName();
$couponCode = Mage::helper('core')->getRandomString(9);
$model = Mage::getModel('salesrule/rule');
$model->setName('Discount for ' . $customer_name);
$model->setDescription('Discount for ' . $customer_name);
$model->setFromDate(date('Y-m-d'));
$model->setToDate(date('Y-m-d', strtotime('+2 days')));
$model->setCouponType(2);
$model->setCouponCode($couponCode);
$model->setUsesPerCoupon(1);
$model->setUsesPerCustomer(1);
$model->setCustomerGroupIds($customerGroupIds);
$model->setIsActive(1);
$model->setConditionsSerialized('a:6:{s:4:\"type\";s:32:\"salesrule/rule_condition_combine\";s:9:\"attribute\";N;s:8:\"operator\";N;s:5:\"value\";s:1:\"1\";s:18:\"is_value_processed\";N;s:10:\"aggregator\";s:3:\"all\";}');
$model->setActionsSerialized('a:6:{s:4:\"type\";s:40:\"salesrule/rule_condition_product_combine\";s:9:\"attribute\";N;s:8:\"operator\";N;s:5:\"value\";s:1:\"1\";s:18:\"is_value_processed\";N;s:10:\"aggregator\";s:3:\"all\";}');
$model->setStopRulesProcessing(0);
$model->setIsAdvanced(1);
$model->setProductIds('');
$model->setSortOrder(1);
$model->setSimpleAction('by_fixed');
$model->setDiscountAmount($discount);
$model->setDiscountStep(0);
$model->setSimpleFreeShipping(0);
$model->setTimesUsed(0);
$model->setIsRss(0);
$model->setWebsiteIds($websitesId);
try {
$model->save();
} catch (Exception $e) {
Mage::log($e->getMessage());
}
}

Opencart Paypal unsupported currency

Im trying to support the checkout of ZAR (South African Rand).
So far i have enabled $, this enables the paypal module however the conversion isn't being completed.
The site simply checkout to the value. Eg: R1500.00 = $1500.00 when checking out through paypal.
What is the correct way to do the currency conversion using the built in convertor?
Ok found the solution:
Taken from Opencart Forum by user Qphoria
Q: How can I use paypal if my currency isn't supported?
Q: How can I use a payment gateway that doesn't support my currency?
Q: Paypal doesn't support my currency?
A:
You are limited to what the payment gateway supports. However, you can add code to auto-convert your currency to the current exchange rate of a supported currency fairly easy.
(v1.5.x)
1. EDIT: catalog/controller/payment/.php
FIND (FIRST INSTANCE ONLY):
Code: Select all
$order_info = $this->model_checkout_order->getOrder
AFTER, ADD (Replace USD with your choice of valid currency):
Code: Select all
$order_info['currency_code'] = 'USD';
Whatever currency you choose to use, be sure you have it in your list of currencies on your store in the Admin->System->Localisation->Currency page. It doesn't need to be enabled, just has to exist so that the conversion calculation can be done.
This will then auto convert the amount before it is sent to the gateway. The customer won't likely notice this.
They will see, for example, 1000 AED on the checkout page
But you will see $272.25 USD (based on the current conversion rate) in your paypal account.
Up til 1.5.1.3, Paypal Standard did this automatically
In 1.5.2, it was changed (not for the better) to simply disable itself from the list of payments if using an unsupported currency. So that will need special instruction and maybe should be changed back in the core.
For now:
1. EDIT: catalog/model/payment/pp_standard.php
FIND AND REMOVE:
Code: Select all
if (!in_array(strtoupper($this->currency->getCode()), $currencies)) {
$status = false;
}
EDIT: catalog/controller/payment/pp_standard.php
FIND (THE FIRST INSTANCE ONLY):
Code: Select all
$order_info = $this->model_checkout_order->getOrder
AFTER, ADD:
Code: Select all
$currencies = array('AUD','CAD','EUR','GBP','JPY','USD','NZD','CHF','HKD','SGD','SEK','DKK','PLN','NOK','HUF','CZK','ILS','MXN','MYR','BRL','PHP','TWD','THB','TRY');
if (!in_array(strtoupper($this->currency->getCode()), $currencies)) {
$order_info['currency_code'] = 'USD';
}
Change "USD" with your choice of supported currency.
for opencart 2 or 3
the first step is the same
EDIT: catalog/model/extension/payment/pp_standard.php
FIND AND REMOVE:
if (!in_array(strtoupper($this->currency->getCode()), $currencies)) { $status = false; }
the second step is
at catalog/controller/extension/payment/pp_standard.php
find
$order_info = $this->model_checkout_order->getOrder($this->session->data['order_id']);
after it ,and
$order_info['currency_code'] = 'USD';
this solution will exchange all currencies to USD and then go to paypal.com to pay

Categories