Exemplo n.º 1
0
$settings = unserialize($method->settings);
$payment_currency = $okay->money->get_currency(intval($method->currency_id));
// Проверяем получателя платежа
if ($_POST['ok_reciever'] != $settings['okpay_receiver']) {
    my_exit("bad reciever");
}
// Проверяем валюту
if ($_POST['ok_txn_currency'] != $payment_currency->code) {
    my_exit("bad currency");
}
// Нельзя оплатить уже оплаченный заказ
if ($order->paid) {
    my_exit('Этот заказ уже оплачен');
}
if ($_POST['ok_item_1_price'] != round($okay->money->convert($order->total_price, $method->currency_id, false), 2) || $_POST['ok_item_1_price'] <= 0) {
    my_exit("incorrect price");
}
// Установим статус оплачен
$okay->orders->update_order(intval($order->id), array('paid' => 1));
// Отправим уведомление на email
$okay->notify->email_order_user(intval($order->id));
$okay->notify->email_order_admin(intval($order->id));
// Спишем товары
$okay->orders->close(intval($order->id));
// Перенаправим пользователя на страницу заказа
header('Location: ' . $okay->config->root_url . '/order/' . $order->url);
exit;
function my_exit($text)
{
    header('Location: ' . $okay->request->root_url . '/order/');
    exit;
Exemplo n.º 2
0
 /**
  * Handle IPN's. The function may produce output, which would be returned to the Payment Gateway. The function may do transaction verification.
  *
  * @return array	A long tuple of collected data.
  */
 function handle_transaction()
 {
     /*$myfile=fopen(get_file_base().'/data_custom/ecommerce.log','at');
     		fwrite($myfile,serialize($_POST));
     		fclose($myfile);*/
     $txn_id = post_param('trans_id');
     if (substr($txn_id, 0, 7) == 'subscr_') {
         $subscription = true;
         $txn_id = substr($txn_id, 7);
     } else {
         $subscription = false;
     }
     $transaction_rows = $GLOBALS['SITE_DB']->query_select('trans_expecting', array('*'), array('id' => $txn_id), '', 1);
     if (!array_key_exists(0, $transaction_rows)) {
         warn_exit(do_lang_tempcode('MISSING_RESOURCE'));
     }
     $transaction_row = $transaction_rows[0];
     $member_id = $transaction_row['e_member_id'];
     $item_name = $subscription ? '' : $transaction_row['e_item_name'];
     $purchase_id = $transaction_row['e_purchase_id'];
     $code = post_param('code');
     $success = $code == 'A';
     $message = post_param('message');
     if ($message == '') {
         switch ($code) {
             case 'P:A':
                 $message = do_lang('PGE_A');
                 break;
             case 'P:X':
                 $message = do_lang('PGE_X');
                 break;
             case 'P:P':
                 $message = do_lang('PGE_P');
                 break;
             case 'P:S':
                 $message = do_lang('PGE_S');
                 break;
             case 'P:E':
                 $message = do_lang('PGE_E');
                 break;
             case 'P:I':
                 $message = do_lang('PGE_I');
                 break;
             case 'P:C':
                 $message = do_lang('PGE_C');
                 break;
             case 'P:T':
                 $message = do_lang('PGE_T');
                 break;
             case 'P:N':
                 $message = do_lang('PGE_N');
                 break;
             case 'P:M':
                 $message = do_lang('PGE_M');
                 break;
             case 'P:B':
                 $message = do_lang('PGE_B');
                 break;
             case 'P:D':
                 $message = do_lang('PGE_D');
                 break;
             case 'P:V':
                 $message = do_lang('PGE_V');
                 break;
             case 'P:R':
                 $message = do_lang('PGE_R');
                 break;
             case 'P:#':
                 $message = do_lang('PGE_HASH');
                 break;
             case 'C':
                 $message = do_lang('PGE_COMM');
                 break;
             default:
                 $message = do_lang('UNKNOWN');
         }
     }
     $payment_status = $success ? 'Completed' : 'Failed';
     $reason_code = '';
     $pending_reason = '';
     $memo = '';
     $mc_gross = post_param('amount');
     $mc_currency = post_param('currency', '');
     // May be blank for subscription
     $email = $GLOBALS['FORUM_DRIVER']->get_member_email_address($member_id);
     // Validate
     $hash = post_param('hash');
     if ($subscription) {
         $my_hash = md5('trans_id=' . $txn_id . '&' . 'req_cv2=true' . '&' . get_option('ipn_digest'));
     } else {
         $repeat = $this->_translate_subscription_details($transaction_row['e_length'], $transaction_row['e_length_units']);
         $my_hash = md5('trans_id=' . $txn_id . '&' . 'req_cv2=true' . '&' . 'repeat=' . $repeat . '&' . get_option('ipn_digest'));
     }
     if ($hash != $my_hash) {
         my_exit(do_lang('IPN_UNVERIFIED'));
     }
     if ($success) {
         require_code('notifications');
         dispatch_notification('payment_received', NULL, do_lang('PAYMENT_RECEIVED_SUBJECT', $txn_id, NULL, NULL, get_lang($member_id)), do_lang('PAYMENT_RECEIVED_BODY', float_format(floatval($mc_gross)), $mc_currency, get_site_name(), get_lang($member_id)), array($member_id), A_FROM_SYSTEM_PRIVILEGED);
     }
     // Subscription stuff
     if (get_param_integer('subc', 0) == 1) {
         if (!$success) {
             $payment_status = 'SCancelled';
         }
     }
     if ($success) {
         $_url = build_url(array('page' => 'purchase', 'type' => 'finish', 'product' => get_param('product', NULL)), get_module_zone('purchase'));
     } else {
         $_url = build_url(array('page' => 'purchase', 'type' => 'finish', 'cancel' => 1, 'message' => do_lang_tempcode('DECLINED_MESSAGE', $message)), get_module_zone('purchase'));
     }
     $url = $_url->evaluate();
     echo http_download_file($url);
     if (addon_installed('shopping')) {
         $this->store_shipping_address($purchase_id);
     }
     return array($purchase_id, $item_name, $payment_status, $reason_code, $pending_reason, $memo, $mc_gross, $mc_currency, $txn_id, '');
 }
Exemplo n.º 3
0
$query .= ',';
$query .= 'INET6_NTOA(UNHEX(ip)) AS ip';
$query .= ' FROM ';
$query .= ' hostnames ';
$query .= ' WHERE ';
$query .= "isResolved='0'";
$query .= ' ORDER BY id ASC';
$result = db_select($link, $query);
while ($row = db_fetch_array($link, $result)) {
    $timestampNow = time();
    debug('Now timestamp is: ' . $timestampNow . '. Script start was at: ' . $startTime, 40, __FILE__, __LINE__);
    debug('Checking if run time exceeded ' . $maxRunTime . ' seconds...', 40, __FILE__, __LINE__);
    if ($timestampNow - $startTime > $maxRunTime) {
        debug('YES', 40);
        debug('Exceeded run time', 30, __FILE__, __LINE__);
        my_exit($link, 0);
    }
    debug('NO', 40);
    $hostname = gethostbyaddr($row['ip']);
    $query = 'UPDATE ';
    $query .= 'hostnames';
    $query .= ' SET ';
    $query .= "hostname='" . $hostname . "'";
    $query .= ',';
    $query .= "isResolved='1'";
    $query .= ' WHERE ';
    $query .= "id='" . $row['id'] . "'";
    db_update($link, $query, 1);
    debug('.', 30);
}
debug('Updating last resolver timestamp...', 40, __FILE__, __LINE__);
Exemplo n.º 4
0
 /**
  * Handle IPN's. The function may produce output, which would be returned to the Payment Gateway. The function may do transaction verification.
  *
  * @return array	A long tuple of collected data.
  */
 function handle_transaction()
 {
     //$myfile=fopen(get_file_base().'/data_custom/ecommerce.log','wt');
     //fwrite($myfile,serialize($_POST)."\n".serialize($_GET));
     //fclose($myfile);
     //$_POST=unserialize('a:36:{s:8:"testMode";s:3:"100";s:8:"authCost";s:4:"15.0";s:8:"currency";s:3:"GBP";s:7:"address";s:1:"a";s:13:"countryString";s:11:"South Korea";s:10:"callbackPW";s:10:"s35645dxr4";s:12:"installation";s:5:"84259";s:3:"fax";s:1:"a";s:12:"countryMatch";s:1:"B";s:7:"transId";s:9:"222873126";s:3:"AVS";s:4:"0000";s:12:"amountString";s:11:"&#163;15.00";s:8:"postcode";s:1:"a";s:7:"msgType";s:10:"authResult";s:4:"name";s:1:"a";s:3:"tel";s:1:"a";s:11:"transStatus";s:1:"Y";s:4:"desc";s:15:"Property Advert";s:8:"cardType";s:10:"Mastercard";s:4:"lang";s:2:"en";s:9:"transTime";s:13:"1171243476007";s:16:"authAmountString";s:11:"&#163;15.00";s:10:"authAmount";s:4:"15.0";s:9:"ipAddress";s:12:"84.9.162.135";s:4:"cost";s:4:"15.0";s:6:"instId";s:5:"84259";s:6:"amount";s:4:"15.0";s:8:"compName";s:32:"The Accessible Property Register";s:7:"country";s:2:"KR";s:11:"MC_callback";s:63:"www.kivi.co.uk/ClientFiles/APR/data/ecommerce.php?from=worldpay";s:14:"rawAuthMessage";s:22:"cardbe.msg.testSuccess";s:5:"email";s:16:"*****@*****.**";s:12:"authCurrency";s:3:"GBP";s:11:"rawAuthCode";s:1:"A";s:6:"cartId";s:32:"3ecd645f632f0304067fb565e71b4dcd";s:8:"authMode";s:1:"A";}');
     //$_GET=unserialize('a:3:{s:4:"from";s:8:"worldpay";s:7:"msgType";s:10:"authResult";s:12:"installation";s:5:"84259";}');
     $code = post_param('transStatus');
     if ($code == 'C') {
         exit;
     }
     // Cancellation signal, won't process
     $txn_id = post_param('transId');
     $cart_id = post_param('cartId');
     if (post_param('futurePayType', '') == 'regular') {
         $subscription = true;
     } else {
         $subscription = false;
     }
     $transaction_rows = $GLOBALS['SITE_DB']->query_select('trans_expecting', array('*'), array('id' => $cart_id), '', 1);
     if (!array_key_exists(0, $transaction_rows)) {
         warn_exit(do_lang_tempcode('MISSING_RESOURCE'));
     }
     $transaction_row = $transaction_rows[0];
     $member_id = $transaction_row['e_member_id'];
     $item_name = $subscription ? '' : $transaction_row['e_item_name'];
     $purchase_id = $transaction_row['e_purchase_id'];
     $success = $code == 'Y';
     $message = post_param('rawAuthMessage');
     $payment_status = $success ? 'Completed' : 'Failed';
     $reason_code = '';
     $pending_reason = '';
     $memo = '';
     $mc_gross = post_param('authAmount');
     $mc_currency = post_param('authCurrency');
     $email = $GLOBALS['FORUM_DRIVER']->get_member_email_address($member_id);
     if (post_param('callbackPW') != get_option('callback_password')) {
         my_exit(do_lang('IPN_UNVERIFIED'));
     }
     if ($success) {
         require_code('notifications');
         dispatch_notification('payment_received', NULL, do_lang('PAYMENT_RECEIVED_SUBJECT', $txn_id, NULL, NULL, get_lang($member_id)), do_lang('PAYMENT_RECEIVED_BODY', float_format(floatval($mc_gross)), $mc_currency, get_site_name(), get_lang($member_id)), array($member_id), A_FROM_SYSTEM_PRIVILEGED);
     }
     if ($success) {
         $_url = build_url(array('page' => 'purchase', 'type' => 'finish', 'product' => get_param('product', NULL), 'message' => '<WPDISPLAY ITEM=banner>'), get_module_zone('purchase'));
     } else {
         $_url = build_url(array('page' => 'purchase', 'type' => 'finish', 'cancel' => 1, 'message' => do_lang_tempcode('DECLINED_MESSAGE', $message)), get_module_zone('purchase'));
     }
     $url = $_url->evaluate();
     echo http_download_file($url);
     if (addon_installed('shopping')) {
         $this->store_shipping_address($purchase_id);
     }
     return array($purchase_id, $item_name, $payment_status, $reason_code, $pending_reason, $memo, $mc_gross, $mc_currency, $txn_id, '');
 }
Exemplo n.º 5
0
 /**
  * Handle IPN's. The function may produce output, which would be returned to the Payment Gateway. The function may do transaction verification.
  *
  * @return array	A long tuple of collected data.
  */
 function handle_transaction()
 {
     if (file_exists(get_file_base() . '/data_custom/ecommerce.log') && is_writable_wrap(get_file_base() . '/data_custom/ecommerce.log')) {
         $myfile = fopen(get_file_base() . '/data_custom/ecommerce.log', 'at');
         fwrite($myfile, serialize($_POST) . chr(10));
         fclose($myfile);
     }
     // assign posted variables to local variables
     $purchase_id = post_param_integer('custom', '-1');
     $txn_type = post_param('txn_type', NULL);
     if ($txn_type == 'cart') {
         require_lang('shopping');
         $item_name = do_lang('CART_ORDER', $purchase_id);
     } else {
         $item_name = substr(post_param('txn_type', ''), 0, 6) == 'subscr' ? '' : post_param('item_name', '');
     }
     $payment_status = post_param('payment_status', '');
     // May be blank for subscription
     $reason_code = post_param('reason_code', '');
     $pending_reason = post_param('pending_reason', '');
     $memo = post_param('memo', '');
     $mc_gross = post_param('mc_gross', '');
     // May be blank for subscription
     $tax = post_param('tax', '');
     if ($tax != '' && intval($tax) > 0 && $mc_gross != '') {
         $mc_gross = float_to_raw_string(floatval($mc_gross) - floatval($tax));
     }
     $mc_currency = post_param('mc_currency', '');
     // May be blank for subscription
     $txn_id = post_param('txn_id', '');
     // May be blank for subscription
     $parent_txn_id = post_param('parent_txn_id', '-1');
     $receiver_email = post_param('receiver_email');
     // post back to PayPal system to validate
     if (!ecommerce_test_mode()) {
         require_code('files');
         $pure_post = isset($GLOBALS['PURE_POST']) ? $GLOBALS['PURE_POST'] : $_POST;
         $x = 0;
         $res = mixed();
         do {
             $res = http_download_file('http://' . (ecommerce_test_mode() ? 'www.sandbox.paypal.com' : 'www.paypal.com') . '/cgi-bin/webscr', NULL, false, false, 'ocPortal', $pure_post + array('cmd' => '_notify-validate'));
             $x++;
         } while (is_null($res) && $x < 3);
         if (is_null($res)) {
             my_exit(do_lang('IPN_SOCKET_ERROR'));
         }
         if (!(strcmp($res, 'VERIFIED') == 0)) {
             if (post_param('txn_type', '') == 'send_money') {
                 exit('Unexpected');
             }
             // PayPal has been seen to mess up on send_money transactions, making the IPN unverifiable
             my_exit(do_lang('IPN_UNVERIFIED') . ' - ' . $res . ' - ' . flatten_slashed_array($pure_post), strpos($res, '<html') !== false);
         }
     }
     $txn_type = str_replace('-', '_', post_param('txn_type'));
     if ($txn_type == 'subscr-modify') {
         $payment_status = 'SModified';
         $txn_id = post_param('subscr_id') . '-m';
     } elseif ($txn_type == 'subscr_signup') {
         $payment_status = 'Completed';
         $mc_gross = post_param('mc_amount3');
         if (post_param_integer('recurring') != 1) {
             my_exit(do_lang('IPN_SUB_RECURRING_WRONG'));
         }
         $txn_id = post_param('subscr_id');
     } elseif ($txn_type == 'subscr_eot' || $txn_type == 'recurring_payment_suspended_due_to_max_failed_payment') {
         $payment_status = 'SCancelled';
         $txn_id = post_param('subscr_id') . '-c';
     } elseif ($txn_type == 'subscr_payment' || $txn_type == 'subscr_failed' || $txn_type == 'subscr_cancel') {
         exit;
     }
     $primary_paypal_email = get_value('primary_paypal_email');
     if (!is_null($primary_paypal_email)) {
         if ($receiver_email != $primary_paypal_email) {
             my_exit(do_lang('IPN_EMAIL_ERROR'));
         }
     } else {
         if ($receiver_email != $this->_get_payment_address()) {
             my_exit(do_lang('IPN_EMAIL_ERROR'));
         }
     }
     if (addon_installed('shopping')) {
         $this->store_shipping_address($purchase_id);
     }
     return array($purchase_id, $item_name, $payment_status, $reason_code, $pending_reason, $memo, $mc_gross, $mc_currency, $txn_id, $parent_txn_id);
 }
Exemplo n.º 6
0
myinitenv();
if (!key_exists("HOME", $MYENV)) {
    echo "There is no env.\nMicroshell can't work properly.\n";
    echo "Try again.\n";
    return 0;
}
$fd = fopen("php://stdin", "r");
if ($fd !== FALSE) {
    $pwd = "PWD";
    echo "<{$MYENV[$pwd]}>\$ ";
    while (($line = fgets($fd)) !== FALSE) {
        $command = parse($line);
        $command = checkalias($command[1][0]);
        $ptr = "func_" . $command;
        if ($ptr == "func_exit" || !isset($MYENV)) {
            my_exit($ptr);
        } else {
            if (isredir($line) == 1) {
                func_redir($line);
            } else {
                if (function_exists($ptr)) {
                    $ptr($line, $fd);
                } else {
                    if ($command != "") {
                        echo "{$command}: command not found\n";
                    }
                }
            }
        }
        echo "<{$MYENV[$pwd]}>\$ ";
    }
Exemplo n.º 7
0
function new_expense()
{
    create_expense($_POST['pot_id'], $_POST['amount'], $_POST['description']);
    my_exit("success", "expense created");
}
Exemplo n.º 8
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);
    }
}