function do_buy_subscription($subId, $userId, $complete = FALSE)
 {
     global $ym_sys;
     // assumes complete
     @ym_log_transaction(YM_IPN, $_REQUEST, $userId);
     if ($complete) {
         @ym_log_transaction(YM_PACKAGE_PURCHASED, $subId, $userId);
         $pack = ym_get_pack_by_id($subId);
         if (!$pack) {
             // unknown pack
             $complete = 'FALSE';
         } else {
             $user = new YourMember_User($userId);
             // get current
             $current = $user->pack_id;
             $extend = FALSE;
             // extend
             // ONLY extend if same package type (ie better pack for the same type)
             //   SO different Pack IDs
             // - like a switch from a monthly sub to a yearly sub
             // and current status is active
             // if been set inactivate then new sub
             if ($user->account_type == $pack['account_type'] && $user->pack_id != $subId && ($user->status == YM_STATUS_ACTIVE || $user->status == YM_STATUS_GRACE)) {
                 $extend = $user->expire_date;
             }
             // check for pack ID's the same
             // and extend allow
             // make sure expire date in the future
             if ($user->pack_id == $subId && $ym_sys->allow_upgrade_to_same && $user->expire_date > time()) {
                 $extend = $user->expire_date;
             }
             // patch :-P
             $pack['amount'] = $pack['cost'];
             // use magic
             // use an array so can pass to update
             // other wise direct calls to object....
             $data = array();
             // this is crap
             // TODO: takes the whole pack and stores it in the user object.....
             foreach ($user as $key => $value) {
                 if (isset($pack[$key])) {
                     $data[$key] = $pack[$key];
                 }
             }
             // end crap
             // additonal
             $data['pack_id'] = $subId;
             $data['status'] = YM_STATUS_ACTIVE;
             $data['reminder_email_sent'] = FALSE;
             if ($this->code == 'ym_gift') {
                 $data['status_str'] = __('Gift Giving was Successful', 'ym');
             } else {
                 if ($this->code == 'ym_dropdown') {
                     $data['status_str'] = __('DropDown was Successful', 'ym');
                 } else {
                     if ($extend) {
                         $data['status_str'] = __('Subscription Extension Successful', 'ym');
                     } else {
                         $data['status_str'] = __('Last payment was successful', 'ym');
                     }
                 }
             }
             $data['account_type'] = ucwords($pack['account_type']);
             $data['reminder_email_sent'] = FALSE;
             $data['gateway_used'] = $this->code;
             if (!$extend) {
                 $data['account_type_join_date'] = time();
             }
             $data['last_pay_date'] = time();
             // log
             @ym_log_transaction(YM_ACCOUNT_TYPE_ASSIGNATION, $data['account_type'], $userId);
             @ym_log_transaction(YM_USER_STATUS_UPDATE, YM_STATUS_ACTIVE . ' - ' . $data['status_str'], $userId);
             // apply trial?
             $apply = FALSE;
             // if trial enabled and user not taken
             if ($pack['trial_on'] && $user->trial_taken != $subId) {
                 // trial not taken yet then apply trial
                 // does the Gateway Used Support a Trial?
                 if (method_exists($this, 'enable_trial')) {
                     $apply = TRUE;
                 }
             }
             if ($apply) {
                 $data['trial_on'] = TRUE;
                 $data['expire_date'] = $user->expiry_time($data['trial_duration'], $data['trial_duration_type']);
                 $data['trial_taken'] = $subId;
             } else {
                 $data['trial_on'] = FALSE;
                 // most important
                 $data['expire_date'] = $user->expiry_time($data['duration'], $data['duration_type'], $extend);
             }
             @ym_log_transaction(YM_ACCESS_EXTENSION, $data['expire_date'], $userId);
             // check for force end
             if (isset($pack['force_end_date'])) {
                 $force_end_date = $pack['force_end_date'];
                 if ($force_end_date > time()) {
                     // greater than now
                     @ym_log_transaction(YM_ACCESS_EXTENSION, 'Adjustment (Force End Date): ' . $force_end_date, $userId);
                     $data['expire_date'] = $force_end_date;
                 }
             }
             // group membership
             $data['child_accounts_allowed'] = $pack['child_accounts_allowed'];
             $data['child_accounts_package_types'] = $pack['child_accounts_package_types'];
             $data['child_accounts_packages'] = $pack['child_accounts_packages'];
             // admin bar control
             $data['hide_admin_bar'] = $pack['hide_admin_bar'];
             $user->update($data);
             $user->save();
             $user->updaterole($pack['role']);
         }
     }
     if (!$complete) {
         $data = array('new_status' => FALSE);
         if (method_exists($this, 'fail_process')) {
             $data = $this->fail_process();
         } else {
             $new_status = YM_STATUS_ERROR;
             $status_str = sprintf(__('Last Payment Errored and No Handler Found for the Payment Gateway Response', 'ym'));
             $data = array('new_status' => $new_status, 'status_str' => $status_str);
         }
         if (isset($data['new_status']) && $data['new_status']) {
             @ym_log_transaction(YM_USER_STATUS_UPDATE, $data['new_status'] . ' - ' . $data['status_str'], $userId);
             if (isset($data['expiry']) && $data['expiry']) {
                 @ym_log_transaction(YM_ACCESS_EXPIRY, $data['expiry'], $userId);
             }
             $data['status'] = $data['new_status'];
             unset($data['new_status']);
             $user = new YourMember_User($userId);
             $user->update($data);
             $user->save();
         }
     }
     $packet = array('user_id' => $userId, 'pack_id' => $subId, 'status' => $complete);
     if ($complete) {
         do_action('ym_membership_transaction_success', $packet);
         do_action('ym_membership_transaction_success_' . $this->code, $packet);
     } else {
         do_action('ym_membership_transaction_failed', $packet);
         do_action('ym_membership_transaction_failed_' . $this->code, $packet);
     }
     do_action('ym_gateway_return', $packet);
     do_action('ym_gateway_return_' . $this->code, $packet);
     $this->notify_user($packet);
 }