Example #1
0
 /**
  * Standard modular run function for realtime-rain hooks.
  *
  * @param  TIME			Start of time range.
  * @param  TIME			End of time range.
  * @return array			A list of template parameter sets for rendering a 'drop'.
  */
 function run($from, $to)
 {
     $drops = array();
     if (has_actual_page_access(get_member(), 'admin_ecommerce')) {
         $rows = $GLOBALS['SITE_DB']->query('SELECT amount,item,t_time AS timestamp FROM ' . $GLOBALS['SITE_DB']->get_table_prefix() . 'transactions WHERE t_time BETWEEN ' . strval($from) . ' AND ' . strval($to));
         foreach ($rows as $row) {
             require_code('ecommerce');
             list($product, ) = find_product_row($row['item']);
             if (!is_null($product)) {
                 $title = $product[4];
             } else {
                 require_lang('ecommerce');
                 $title = do_lang('SALE_MADE');
             }
             $timestamp = $row['timestamp'];
             $ticker_text = do_lang('KA_CHING', ecommerce_get_currency_symbol(), $row['amount']);
             $drops[] = rain_get_special_icons(NULL, $timestamp, NULL, $ticker_text) + array('TYPE' => 'ecommerce', 'FROM_MEMBER_ID' => NULL, 'TO_MEMBER_ID' => NULL, 'TITLE' => $title, 'IMAGE' => find_theme_image('bigicons/ecommerce'), 'TIMESTAMP' => strval($timestamp), 'RELATIVE_TIMESTAMP' => strval($timestamp - $from), 'TICKER_TEXT' => $ticker_text, 'URL' => NULL, 'IS_POSITIVE' => true, 'IS_NEGATIVE' => false, 'FROM_ID' => NULL, 'TO_ID' => NULL, 'GROUP_ID' => 'product_' . $row['item']);
         }
     }
     return $drops;
 }
Example #2
0
/**
 * Handle IPN's that have been confirmed as backed up by real money.
 *
 * @param  ID_TEXT		The ID of the purchase-type (meaning depends on item_name)
 * @param  SHORT_TEXT	The item being purchased (aka the product) (blank: subscription, so we need to look it up). One might wonder why we use $item_name instead of $product. This is because we pass human-readable-names (hopefully unique!!!) through payment gateways because they are visually shown to the user. (blank: it's a subscription, so look up via a key map across the subscriptions table)
 * @param  SHORT_TEXT	The status this transaction is telling of
 * @set    SModified SCancelled Completed Pending Failed
 * @param  SHORT_TEXT	The code that gives reason to the status
 * @param  SHORT_TEXT	The reason it is in pending status (if it is)
 * @param  SHORT_TEXT	A note attached to the transaction
 * @param  SHORT_TEXT	The amount of money
 * @param  SHORT_TEXT	The currency the amount is in
 * @param  SHORT_TEXT	The transaction ID
 * @param  SHORT_TEXT	The ID of the parent transaction
 * @param  ID_TEXT		The ID of a special source for the transaction
 * @param  string			The subscription period (blank: N/A)
 */
function handle_confirmed_transaction($purchase_id, $item_name, $payment_status, $reason_code, $pending_reason, $memo, $mc_gross, $mc_currency, $txn_id, $parent_txn_id, $source = '', $period = '')
{
    /*#####################################################################################*/
    //Temporary setting - force payment setting to "completed" for test mode transactions
    if (get_option('ecommerce_test_mode') == "1") {
        $payment_status = 'Completed';
    }
    /*#####################################################################################*/
    // Try and locate the product
    if ($item_name == '') {
        $product = $GLOBALS['SITE_DB']->query_value_null_ok('subscriptions', 's_type_code', array('id' => intval($purchase_id)));
        // Note that s_type_code is not numeric, it is a $product
        if (is_null($product)) {
            warn_exit(do_lang_tempcode('NO_SUCH_SUBSCRIPTION', strval($purchase_id)));
        }
        $item_name = '_' . $product;
        // Check what we sold
        list($found, ) = find_product_row($product, true, false);
        if (!is_null($found)) {
            $item_name = $found[4];
        }
    } else {
        // Check what we sold
        list($found, $product) = find_product_row($item_name, true, true);
    }
    if (is_null($found)) {
        my_exit(do_lang('PRODUCT_NO_SUCH') . ' - ' . $item_name);
    }
    // Check price
    if ($mc_gross != $found[1] && $found[1] != '?') {
        if ($payment_status == 'SModified') {
            $GLOBALS['SITE_DB']->query_update('subscriptions', array('s_state' => 'new'), array('id' => intval($purchase_id)), '', 1);
        }
        if ($payment_status != 'SCancelled' && substr($txn_id, 0, 6) != 'manual') {
            my_exit(do_lang('PURCHASE_WRONG_PRICE', $item_name));
        }
    }
    if ($period != '') {
        $length = array_key_exists('length', $found[3]) ? strval($found[3]['length']) : '1';
        $length_units = array_key_exists('length_units', $found[3]) ? $found[3]['length_units'] : 'm';
        if (strtolower($period) != strtolower($length . ' ' . $length_units)) {
            my_exit(do_lang('IPN_SUB_PERIOD_WRONG'));
        }
    }
    // Store
    $GLOBALS['SITE_DB']->query_insert('transactions', array('id' => $txn_id, 't_memo' => $memo, 'purchase_id' => $purchase_id, 'status' => $payment_status, 'pending_reason' => $pending_reason, 'reason' => $reason_code, 'amount' => $mc_gross, 't_currency' => $mc_currency, 'linked' => $parent_txn_id, 't_time' => time(), 'item' => $product, 't_via' => $source));
    $found['txn_id'] = $txn_id;
    // Check currency
    if ($mc_currency != get_option('currency')) {
        if ($payment_status == 'SModified') {
            $GLOBALS['SITE_DB']->query_update('subscriptions', array('s_state' => 'new'), array('id' => intval($purchase_id)), '', 1);
        }
        if ($payment_status != 'SCancelled' && substr($txn_id, 0, 6) != 'manual') {
            my_exit(do_lang('PURCHASE_WRONG_CURRENCY'));
        }
    }
    // Pending
    if ($payment_status == 'Pending' && $found[0] == PRODUCT_INVOICE) {
        $GLOBALS['SITE_DB']->query_update('invoices', array('i_state' => 'pending'), array('id' => intval($purchase_id)), '', 1);
    } elseif ($payment_status == 'Pending' && $found[0] == PRODUCT_SUBSCRIPTION) {
        $GLOBALS['SITE_DB']->query_update('subscriptions', array('s_state' => 'pending'), array('id' => intval($purchase_id)), '', 1);
        if ($found[2] != '') {
            call_user_func_array($found[2], array($purchase_id, $found, $product, true));
        }
        // Run cancel code
    } elseif ($payment_status == 'Pending' && $item_name == do_lang('CART_ORDER', $purchase_id)) {
        $found['ORDER_STATUS'] = 'ORDER_STATUS_awaiting_payment';
        if ($found[2] != '') {
            call_user_func_array($found[2], array($purchase_id, $found, $product, true));
        }
        // Set order status
    } elseif ($payment_status == 'SCancelled' && $found[0] == PRODUCT_SUBSCRIPTION) {
        $GLOBALS['SITE_DB']->query_update('subscriptions', array('s_auto_fund_source' => $source, 's_auto_fund_key' => $txn_id, 's_state' => 'cancelled'), array('id' => intval($purchase_id)), '', 1);
    } elseif ($found[0] == PRODUCT_SUBSCRIPTION) {
        $GLOBALS['SITE_DB']->query_update('subscriptions', array('s_auto_fund_source' => $source, 's_auto_fund_key' => $txn_id, 's_state' => 'active'), array('id' => intval($purchase_id)), '', 1);
    } elseif ($payment_status != 'Completed' && $payment_status != 'SCancelled' && get_option('ecommerce_test_mode') != '1') {
        my_exit(do_lang('TRANSACTION_NOT_COMPLETE', $product . ':' . strval($purchase_id), $payment_status), true);
    }
    // Invoice: Check price
    if ($found[0] == PRODUCT_INVOICE) {
        $price = $GLOBALS['SITE_DB']->query_value('invoices', 'i_amount', array('id' => intval($purchase_id)));
        if ($price != $mc_gross) {
            if (substr($txn_id, 0, 6) != 'manual') {
                my_exit(do_lang('PURCHASE_WRONG_PRICE', $item_name));
            }
        }
    }
    /* At this point we know our order (or subscription cancellation) is good */
    // Dispatch
    if ($payment_status == 'Completed' || $payment_status == 'SCancelled') {
        //Find product hooks of this order to check dispatch type
        $object = find_product($product, true);
        if (is_object($object) && !method_exists($object, 'get_product_dispatch_type')) {
            //If hook does not have dispatch method setting take dispatch method as automatic
            $found['ORDER_STATUS'] = 'ORDER_STATUS_dispatched';
        } elseif (is_object($object) && $object->get_product_dispatch_type($purchase_id) == 'automatic') {
            $found['ORDER_STATUS'] = 'ORDER_STATUS_dispatched';
        } else {
            $found['ORDER_STATUS'] = 'ORDER_STATUS_payment_received';
        }
        if ($found[2] != '') {
            call_user_func_array($found[2], array($purchase_id, $found, $product));
        }
        // Send out notification to staff
        if ($found[0] == PRODUCT_SUBSCRIPTION) {
            require_code('notifications');
            $member_id = $GLOBALS['SITE_DB']->query_value_null_ok('subscriptions', 's_member_id', array('id' => intval($purchase_id)));
            if (!is_null($member_id)) {
                $username = $GLOBALS['FORUM_DRIVER']->get_username($member_id);
                if (is_null($username)) {
                    $username = do_lang('GUEST');
                }
                if ($payment_status == 'Completed') {
                    $subject = do_lang('SERVICE_PAID_FOR', $item_name, $username, get_site_name(), get_site_default_lang());
                    $body = do_lang('_SERVICE_PAID_FOR', $item_name, $username, get_site_name(), get_site_default_lang());
                    dispatch_notification('service_paid_for_staff', NULL, $subject, $body);
                } else {
                    $subject = do_lang('SERVICE_CANCELLED', $item_name, $username, get_site_name(), get_site_default_lang());
                    $body = do_lang('_SERVICE_CANCELLED', $item_name, $username, get_site_name(), get_site_default_lang());
                    dispatch_notification('service_cancelled_staff', NULL, $subject, $body);
                }
            }
        }
    }
    // Invoice handling
    if ($found[0] == PRODUCT_INVOICE) {
        $GLOBALS['SITE_DB']->query_update('invoices', array('i_state' => 'paid'), array('id' => intval($purchase_id)), '', 1);
    }
    // Subscription: Delete if cancelled
    if ($payment_status == 'SCancelled' && $found[0] == PRODUCT_SUBSCRIPTION) {
        $GLOBALS['SITE_DB']->query_delete('subscriptions', array('id' => intval($purchase_id)), '', 1);
    }
}
Example #3
0
 /**
  * View an overview of the members adverts on the system.
  *
  * @return tempcode		The UI
  */
 function adverts()
 {
     require_lang('classifieds');
     require_code('catalogues');
     require_code('ecommerce');
     $member_id = get_param_integer('member_id', get_member());
     $title = get_page_title($member_id == get_member() ? 'CLASSIFIED_ADVERTS' : '_CLASSIFIED_ADVERTS', true, array($GLOBALS['FORUM_DRIVER']->get_username($member_id)));
     if (is_guest()) {
         access_denied('NOT_AS_GUEST');
     }
     enforce_personal_access($member_id);
     $start = get_param_integer('start', 0);
     $max = get_param_integer('max', 30);
     require_code('templates_results_browser');
     $max_rows = $GLOBALS['SITE_DB']->query_value('catalogue_entries e JOIN ' . get_table_prefix() . 'classifieds_prices c ON c.c_catalogue_name=e.c_name', 'COUNT(*)', array('ce_submitter' => $member_id));
     $rows = $GLOBALS['SITE_DB']->query_select('catalogue_entries e JOIN ' . get_table_prefix() . 'classifieds_prices c ON c.c_catalogue_name=e.c_name', array('e.*'), array('ce_submitter' => $member_id), 'GROUP BY e.id ORDER BY ce_add_date DESC');
     if (count($rows) == 0) {
         inform_exit(do_lang_tempcode('NO_ENTRIES'));
     }
     $ads = array();
     foreach ($rows as $row) {
         $root = get_param_integer('root', NULL);
         $data_map = get_catalogue_entry_map($row, NULL, 'CATEGORY', 'DEFAULT', $root, NULL, array(0));
         $ad_title = $data_map['FIELD_0'];
         $purchase_url = build_url(array('page' => 'purchase', 'type' => 'misc', 'filter' => 'CLASSIFIEDS_ADVERT', 'id' => $row['id']), get_module_zone('purchase'));
         // We'll show all transactions against this ad
         $transaction_details = $GLOBALS['SITE_DB']->query('SELECT * FROM ' . get_table_prefix() . 'transactions WHERE purchase_id=' . strval($row['id']) . ' AND item LIKE \'' . db_encode_like('CLASSIFIEDS\\_ADVERT\\_%') . '\'');
         $_transaction_details = array();
         foreach ($transaction_details as $t) {
             list($found, ) = find_product_row($t['item']);
             if (!is_null($found)) {
                 $item_title = $found[4];
             } else {
                 $item_title = $t['item'];
             }
             $_transaction_details[] = array('T_ID' => strval($t['id']), 'PURCHASE_ID' => strval($t['purchase_id']), 'STATUS' => $t['status'], 'REASON' => $t['reason'], 'AMOUNT' => float_format($t['amount']), 'T_CURRENCY' => $t['t_currency'], 'LINKED' => $t['linked'], 'T_TIME' => strval($t['t_time']), 'ITEM' => $t['item'], 'ITEM_TITLE' => $item_title, 'PENDING_REASON' => $t['pending_reason'], 'T_MEMO' => $t['t_memo'], 'T_VIA' => $t['t_via']);
         }
         $url_map = array('page' => 'catalogues', 'type' => 'entry', 'id' => $row['id'], 'root' => $root);
         $url = build_url($url_map, '_SELF');
         // No known expiry status: put on free, or let expire
         if ($row['ce_last_moved'] == $row['ce_add_date']) {
             require_code('classifieds');
             initialise_classified_listing($row);
         }
         $ads[] = array('AD_TITLE' => $ad_title, 'TRANSACTION_DETAILS' => $_transaction_details, 'DATE' => get_timezoned_date($row['ce_add_date']), 'DATE_RAW' => strval($row['ce_add_date']), 'EXPIRES_DATE' => get_timezoned_date($row['ce_last_moved']), 'EXPIRES_DATE_RAW' => strval($row['ce_last_moved']), 'ACTIVE' => $row['ce_validated'] == 1, 'PURCHASE_URL' => $purchase_url, 'ID' => strval($row['id']), 'URL' => $url, 'NUM_VIEWS' => integer_format($row['ce_views']));
     }
     $results_browser = results_browser(do_lang('_CLASSIFIED_ADVERTS'), NULL, $start, 'start', $max, 'max', $max_rows, NULL, NULL, true);
     return do_template('CLASSIFIED_ADVERTS_SCREEN', array('TITLE' => $title, 'RESULTS_BROWSER' => $results_browser, 'ADS' => $ads));
 }