Zen Cart update database with Post affiliate pro id - php

We are in the process of creating a specialty cart where our when a client makes a purchase it logs the Affiliate id in the database at time of purchase. I have created the following code to get the affiliate id/name using the Post Affiliate Pro API.
include ("affiliate/api/PapApi.class.php");
$session = new Gpf_Api_Session("https://www.elitespecialtymeats.com/affiliate/scripts/server.php");
if(!$session->login("user", "password")){ die("Cannot login. Message: ".$session->getMessage()); }
$clickTracker = new Pap_Api_ClickTracker($session);
try {
$clickTracker->track();
$clickTracker->saveCookies();
if ($clickTracker->getAffiliate() != null){ $affid=$clickTracker->getAffiliate()->getValue('username'); }
else{ $affid=''; }
}catch (Exception $e){
$affid='';
}
I am trying to figure out the best way of adding that id into the purchase. I think it may be best to add it in tpl_checkout_success_default.php where they log the purchase into PAP. My issue is that I dont know enough about the system to implement the code.
My best guess is
$db->Execute("UPDATE ".TABLE_ORDERS_TOTAL." SET affid='$affid' where orders_id = '".(int)$orders->fields['orders_id']."' AND class in ('ot_coupon', 'ot_gv', 'ot_subtotal', 'ot_group_pricing', 'ot_quantity_discount')");
Will this work or will i mess something up?

First of all, using the API you are loading affiliate username ( ...getValue('username') ), not affiliate ID as you stated in the first paragraph. You should use getValue('userid'); (for affiliate ID) or getValue('refid'); (for referral ID).
The database command you are trying to use will only work in case the the table TABLE_ORDERS_TOTAL has a column called 'affid'. You can add it manually to the table...
I am wondering why are you doing something like this... It seems like you want to use the ID for some special purpose later. Do you want to give a commission to the original referring person even the customer removed all the cookies or clicked another affiliate's banner meanwhile? If so, you should use Lifetime commissions instead:
http://support.qualityunit.com/541587-Lifetime-commissions
In case you need any other help, feel free to contact our online support.

You might want to look at the way JROX does it - they are an affiliate marketing system that is popular with Zen Cart. It's described here: http://jam.jrox.com/docs/index.php?article=111
Basically they just piggyback onto the checkout success page and stick their logic in the footer.

Related

No traces of a user's shopping website until user reopens shop?

I have a friend that found one more problem with the shopping website, her StackOverflow account (Displayed ID name is Ruth) has been used to ask a question for something else today and could not ask another one until two days later. So I have decided to ask the question for my friend.
She is creating a shopping website that allows users to create an account and open a website. If they choose to close down the shop, there is a button for it. So far on the database table, there is a disabled field for the shop, so that the user can reopen the shop again, so she's not completely deleting the shop from the table. But she wants the users not be able to find the information and items of that closed website. So basically no traces of the website is there until the shop owner opens it back up again.
How to make it so that others are not able to find any traces of the website and its items all at once?
It's simple, you add a flag in the database table for example Enabled (boolean) and depending on the condition you fetch the data accordingly.
In your php file, you can fetch the result of the shop from MySQL and if the shop enabled is false, you display a page saying that it's not reachable otherwise you display the shop.
Depends on your application's logic.
Do you have the "disabled" field on a user or shop table? I think it would be easier to implement it on a shop table, that way your shop is set to disabled more clearly.
In this case, I do not think having no traces of the shopping website is even accurate to put. Are you fetching data from a get variable to show the items of that shop? Okay, maybe the ID of that item still exists, because you need it to exist if you still have the table and all the shop items not deleted. What you can do is set up an if statement when the page receives the get variable to display that item. This statement tests whether the item's shop is disabled or not, and this you would need MySQL to help. So when it is disabled, just redirect them to a 404 page or an error page of your customization.
Now, when you do go looking for that shop's website, that should also redirect to a page saying that the shop is not existing. Although this practice is not entirely the best (in terms of security), it may very much be what you are looking for.

Get notified on stock unavailability

I am trying to create a "Notify me" feature if the stock is unavailable.
On search on admin panel, I could find only that a user should sign up / log in to get notified about the stock availability.
But I just want to let the user (a guest) enter only his/her email address to get notified.
How should I do this?
Please give suggestions..
EDIT:
I have got this link, which gives me a way to start.
Till now what I did is added the following code in my template file which is creating a url for redirect (thinking to do it in ajax way, to stop page refreshing).
<?php
$actual_link = "http://$_SERVER[HTTP_HOST]$_SERVER[REQUEST_URI]";
$base64 = strtr(base64_encode($actual_link), '+/=', '-_,');
$postUrl = "http://$_SERVER[HTTP_HOST]/efk/productalert/add/stock/product_id/" . $simpleProduct->getId() . "/uenc/". $base64;
?>
In the above code, efk is my project folder name.
After this, I have gone to productalert/add/stock controller method i.e stockAction() which is calling sign up / login form (I think so) using $model->save();.
How should I disable this save calling and add my own small overlay which holds a textbox to enter a email address?
Magento has "Notify me when product is back in stock" feature out of the box. It can be configured in admin panel: system / configuration / catalog / product alerts and product alerts run settings.
You're right, it works only for registred customers. To make it working for guest users some coding is required. I'd say you need to do the following steps:
Add email column to product_alert_stock table
Create new controller and action (believe me, it's better than you override existing one via config.xml) which extends Mage_ProductAlert_AddController::stockAction(). Your method will have to set guest's email to productalert/stock model.
Create subscription form and make sure it submits data to your new controller/action.
Update (override) Mage_ProductAlert_Model_Observer::_processStock() method to make it respect situations when "customer" has no ID but has email.
When you'll be testing, I suggest you to install SMTP Pro Email extension and mailcatcher to ease the testing process.
We have done this (http://www.alfresia.co.uk/sorrento-side-table.html/). Here we ended up creating a custom module as when we did this magento did not support any product alert system for the guest users (i do not know if this is supported now).
We first created a text box which would appear on product page where the product is out of stock. We were saving this info in one of our custom tables where we the schema was {id, email, product_sku, status} (status had three values Awaiting Stock, In Stock, and Already Notified).
We then wrote an observer which was hooked to cataloginventory_stock_item_save_after event, this helped us get the product sku which has been back in stock, and update all entries in our custom table with status In Stock and send a mail to the user.
This is how we did it, surely there will be a much cleaner way doing this.
You could have work with plugins. MagentoCommerce has loads of plugins/extensions which does the same
Free Version - http://www.magentocommerce.com/magento-connect/product-out-of-stock-subscription-1350.html
I too had similar requirement, and have installed 'http://www.magentocommerce.com/magento-connect/product-out-of-stock-subscription-1350.html' this plugin.
Well this plugin does the job, But they have override complete product view page template instead of simply adding a new block. By this your custom development on product view page development might get reflected on frontend.
Or else this plugin definitely does the job.
This http://www.magentocommerce.com/magento-connect/product-out-of-stock-subscription-1350.html plugin is really good but it breaks for configurable product types and it completely overrides the product controller which makes your system vulnerable to future upgrades. I think observers should be hooked to events where the product is back in stock and should update the users.

Creating new hosted buttons versus updating existing ones?

I need to dynamically generate the price of the full aggregate cart on my website - I've already built my own shopping cart. Only when the user is going to check out do I want to generate a button with the aggregate cart price.
What's a better approach? Should I create a hosted button through PayPal's interface and just update it whenever the user gets to the checkout stage? Or should I create a new button for every user checkout? Is either approach going to be more expensive than the other?
I'd suggest creating a saved hosted button for each item you sell. Because this way users can't tamper with the prices of the items.
If you use the "customized" button and change the form variables yourself without saving it on paypal, you'll have to verify the price of each order because frankly it is VERY easy to change them through DOM. (Especially true for anyone on this site)
If you have thousands of items, you might want to look into third-party merchant solutions that allows you to update items easier.

Magento - Single Coupon marked as used when payment pending

I have got a problem with Magento single coupon code that is marked as having been used at the time the customer clicks on the Place Order button. If the Paypal payment fails or the client leaves the page before the order is complete, he won't able to go back and re-order with this coupon which is set to be only used once, and has been marked already been used.
I have found a piece of code that decreases the number of times the coupons has been used by the user and allows him to reuse the coupon. Unfortunately, he gets an error when trying to connect the Paypal page when clicking the place order button. In order to be able to use the coupon another time and access the Paypal page, I have to delete the lines in SQL database in tables salesrule_coupon_usage and salesrule_customer with this customer's ID.
Here is the code I need to change to automatically delete coupon usage information for a customer ID:
public function cancel($observer)
{
$order = $observer->getEvent()->getPayment()->getOrder();
if ($order->canCancel()) {
if ($code = $order->getCouponCode()) {
$coupon = Mage::getModel('salesrule/coupon')->load($code, 'code');
if ($coupon->getTimesUsed() > 0) {
$coupon->setTimesUsed($coupon->getTimesUsed() - 1);
$coupon->save();
}
$rule = Mage::getModel('salesrule/rule')->load($coupon->getRuleId());
error_log("\nrule times used=" . $rule->getTimesUsed(), 3, "var/log/debug.log");
if ($rule->getTimesUsed() > 0) {
$rule->setTimesUsed($rule->getTimesUsed()-1);
$rule->save();
}
if ($customerId = $order->getCustomerId()) {
if ($customerCoupon = Mage::getModel('salesrule/rule_customer')->loadByCustomerRule($customerId, $rule->getId())) {
$couponUsage = new Varien_Object();
Mage::getResourceModel('salesrule/coupon_usage')->loadByCustomerCoupon($couponUsage, $customerId, $coupon->getId());
if ($couponUsage->getTimesUsed() > 0) {
/* I can't find any ##$!#$ interface to do anything but increment a coupon_usage record */
$resource = Mage::getSingleton('core/resource');
$writeConnection = $resource->getConnection('core_write');
$tableName = $resource->getTableName('salesrule_coupon_usage');
$query = "UPDATE {$tableName} SET times_used = times_used-1 "
. "WHERE coupon_id = {$coupon->getId()} AND customer_id = {$customerId} AND times_used > 0";
$writeConnection->query($query);
}
if ($customerCoupon->getTimesUsed() > 0) {
$customerCoupon->setTimesUsed($customerCoupon->getTimesUsed()-1);
$customerCoupon->save();
}
}
}
}
}
}
I believe this was an old bug from around 1.4 to maybe 1.6. But whether you've got an old version or not, this can fairly easily be fixed in place if you know your way around Magento.
The problem is, you have code that is updating the salesrule_coupon_usage table right when they click the pay button. This isn't really what you want at all. You want this to be wrapped into the payment transaction. I don't know if this bug is happening because you have custom code or are using a older version of Magento, but I'll tell you how I would fix the problem. Then I'll give you a fix similar to what you proposed:
Magento already has an abstraction called a "transaction". A transaction is used to put and group of objects together that need to either all succeed or all fail, no half-measures. Magento will go through the transaction and attempt to save each of the objects you have placed in it. If any of them fail (for example, payment doesn't go through), all the events that have been already saved are "rolled back".
Luckily, Magento already creates a transaction object to handle payment for the various things that need to update together on successful payment. You can tap into that transaction and use it to update the coupon usage correctly.
Here is the 10,000 foot view of what you need to do.
Find whatever is updating the salesrule_coupon_usage table too early and kill it. We are going to add in our own transaction-safe version, so we don't want it being saved anywhere else. Easiest way to do this is to figure out what model connects to that table and search for the creation of that model. For 1.7 and 1.8, that is the rule/customer model.
Create an observer to catch the start of a payment transaction. In most modern versions of magento this event is called sales_order_payment_place_start and can be witnessed in app/code/core/Mage/Sales/Model/Order/Payment.php
Pull the order out of the event and pull the coupon code out of the event.
Pull the actual model you want to update. It looks like someone couldn't find it in your code, but there should be some model that uses the salesrule_coupon_usage table hiding somewhere. Search though the .xml files for "salesrule_coupon_usage" and see which model using that table. Again, for me, on 1.7, that is the rule/customer model.
Load that model up, with the customer change the value where your coupon code is concerned to indicate that the customer has used the coupon, but don't save yet.
Get the transaction out of the event and register your updated coupon object with the addObject method.
And your done. The transaction will automatically try to save all of the objects that have been added to it. If any part fails (including a failed payment), it'll rollback the whole process and your coupon won't be used. Yay!
Now, in my opinion, the above is the best way to handle the issue, but if you are having issues for some reason, here is an alternative based on catching an unsuccessful payment and then using your code.
Again, here is the 10,000 foot view:
Create an observer to catch the failed payment event. In most versions the event you want is sales_order_payment_cancel.
Run the code you've got... it should do it. But to clarify for others:
Pull the order out of the event, pull the coupon code and customer id out of that.
Update the customer, rule and salesrule_coupon_usage table. (Although there really should be a model for that, I'm sure you can find it)
Now when a sale fails, you go back through and unwind everything manually. This isn't as clean as my first solution, but might be easier for you depending on your familiarity with Magento.
I'm fairly sure that new, clean versions of Magento don't have this issue, so let me offer a fairly obvious suggestion as a third solution.
Update Magento
If Magento is up to date, test disabling any custom modules, because something broke it. I've noticed that Amasty coupon plugins are particularly buggy.
If you've made custom changes to Magento core... good luck with that.
Good luck!

Magento! A Call to a DAL Server on or before or around OnePageController or Success.php

Ok so I have customized the Mage_Checkout_OnepageController
I need to be able to connect to a DAL server and save certain things there. I got everything correct. It's RESTful, so I am sending a POST request. It's works all just fine. But I need to send one more thing aside from quoteData, item details etc. that one more thing is the magento orderId.
I understand that Magento hasn't created the order Id on Mage_Checkout_OnepageController yet, it generates it on Mage_Checkout_Block_Onepage_Success. I have my own X_Request_Block_Checkout_Success. Within this file the following code;
$order = Mage::getModel('sales/order')->loadByIncrementId(Mage::getSingleton('checkout/session')->getLastRealOrderId());
$orderInfo['orderId'] = $order->getIncrementId();
But in this Success.php, this time I can't get the data I get in Mage_Checkout_OnepageController, namely the followings; (any quoteData, shipping address etc)
$jobSiteAddress = Mage::getSingleton('checkout/session')->getQuote()->getShippingAddress()->toArray();
$quote = Mage::getSingleton('checkout/session')->getQuote();
$cartItems = $quote->getAllVisibleItems();
and some other things, I hope you get the idea.
Big Question
So my question; Is there a way to get magento orderId and all cart data either in Mage_Checkout_Block_Onepage_Success or in my Mage_Checkout_OnepageController
I tried
In My OnePageController I have;
$this->getOnepage()->getQuote()->save();
I tried getting the magento order id after this line but no luck
do let me know If I didn't explain clearly
SO, to be clear, you need to have an orderId before magento really generates it ?
Can you explain more why it's needed ? Why don't you do this call after the order is really generated (magento sales/order events can clearly do this)
Anyways, it seems hard to me to get the next orderId (you can't be sure of the next increment_id if 10 customers orders simultaneously, and i don't think you want to create an order if the user haven't pay already) but you should be able to determine the next OrderIncrementId as it's linked to customer history...

Categories