/**
	 * create a new subscription object and corresponding object in database
	 *
	 * @param int|null      $user_id                 CB user id
	 * @param cbpaidProduct $plan                    plan object of this subscription
	 * @param string        $status                  like status class variable
	 * @param boolean       $store                   true (default) if should be stored into db
	 * @param int           $subscriptionTime        time of subscription
	 */
	protected function createMerchandiseRecord( $user_id, &$plan, $status = 'R', $store = true, $subscriptionTime = null ) {
		global $_CB_framework;

		if ( $subscriptionTime === null ) {
			$subscriptionTime			=	$_CB_framework->now();
		}

		$this->reset();

		$this->user_id					=	$user_id;
		$this->plan_id					=	$plan->get( 'id' );
		$this->payment_date				=	date( 'Y-m-d H:i:s', $subscriptionTime );
		$this->getCurrencyAmount( $plan );
		$this->status					=	$status;
		if ( is_object( $plan->_integrations ) ) {
			$this->integrations				=	$plan->_integrations->asJson();
		} else {
			$this->integrations				=	'';
		}
		if ( $store ) {
			$this->ip_addresses			=	cbpaidRequest::getIPlist();
			$this->historySetMessage( $this->recordName() . ' record created' );
			$this->store();
		}
		$this->_plan 					=	$plan;
	}
 /**
  * Fills object with all standard items of a Notification record
  *
  * @param  cbpaidPayHandler     $payHandler
  * @param  int                  $test_ipn
  * @param  string               $log_type
  * @param  string               $paymentStatus
  * @param  string               $paymentType
  * @param  string               $reasonCode
  * @param  int                  $paymentTime
  * @param  string               $charset
  */
 public function initNotification($payHandler, $test_ipn, $log_type, $paymentStatus, $paymentType, $reasonCode, $paymentTime, $charset = 'utf-8')
 {
     $this->payment_method = $payHandler->getPayName();
     $this->gateway_account = $payHandler->getAccountParam('id');
     $this->log_type = $log_type;
     $this->time_received = Application::Database()->getUtcDateTime();
     $this->ip_addresses = cbpaidRequest::getIPlist();
     $this->geo_ip_country_code = cbpaidRequest::getGeoIpCountryCode();
     $this->notify_version = '2.1';
     $this->user_id = (int) cbGetParam($_GET, 'user', 0);
     $this->charset = $charset;
     $this->test_ipn = $test_ipn;
     $this->payer_status = 'unverified';
     $this->payment_status = $paymentStatus;
     if (in_array($paymentStatus, array('Completed', 'Pending', 'Processed', 'Failed', 'Reversed', 'Refunded', 'Partially-Refunded', 'Canceled_Reversal'))) {
         if (in_array($paymentStatus, array('Completed', 'Reversed', 'Refunded', 'Partially-Refunded', 'Canceled_Reversal'))) {
             $this->payment_date = gmdate('H:i:s M d, Y T', $paymentTime);
             // paypal-style
         }
         $this->payment_type = $paymentType;
     }
     if ($reasonCode) {
         $this->reason_code = $reasonCode;
     }
 }
 /**
  * If table key (id) is NULL : inserts a new row
  * otherwise updates existing row in the database table
  *
  * Can be overridden or overloaded by the child class
  *
  * @param  boolean  $updateNulls  TRUE: null object variables are also updated, FALSE: not.
  * @return boolean                TRUE if successful otherwise FALSE
  */
 public function store($updateNulls = false)
 {
     $key = $this->_tbl_key;
     if (!$this->{$key}) {
         $this->event_time = $this->_db->getUtcDateTime();
         $this->user_id = Application::MyUser()->getUserId();
         $this->ip_addresses = cbpaidRequest::getIPlist();
         $this->log_version = 1;
     }
     return parent::store($updateNulls);
 }
예제 #4
0
	/**
	 * If table key (id) is NULL : inserts a new row
	 * otherwise updates existing row in the database table
	 *
	 * Can be overridden or overloaded by the child class
	 *
	 * @param  boolean  $updateNulls  TRUE: null object variables are also updated, FALSE: not.
	 * @return boolean                TRUE if successful otherwise FALSE
	 */
	public function store( $updateNulls = false ) {
		global $_CB_framework;

		$key						=	$this->_tbl_key;
		if ( ! $this->$key ) {
			$this->event_time		=	date( 'Y-m-d H:i:s', $_CB_framework->now() );
			$this->user_id			=	$_CB_framework->myId();
			$this->ip_addresses		=	cbpaidRequest::getIPlist();
			$this->log_version		=	1;
		}
		return parent::store( $updateNulls );
	}
 /**
  * create a new subscription object and corresponding object in database
  *
  * @param int|null      $user_id                 CB user id
  * @param cbpaidProduct $plan                    plan object of this subscription
  * @param string        $status                  like status class variable
  * @param boolean       $store                   true (default) if should be stored into db
  * @param int           $subscriptionTime        time of subscription
  */
 protected function createMerchandiseRecord($user_id, $plan, $status = 'R', $store = true, $subscriptionTime = null)
 {
     if ($subscriptionTime === null) {
         $subscriptionTime = cbpaidTimes::getInstance()->startTime();
     }
     $this->reset();
     $this->user_id = $user_id;
     $this->plan_id = $plan->get('id');
     $this->payment_date = $this->_db->getUtcDateTime($subscriptionTime);
     $this->getCurrencyAmount($plan);
     $this->status = $status;
     if (is_object($plan->_integrations)) {
         $this->integrations = $plan->_integrations->asJson();
     } else {
         $this->integrations = '';
     }
     if ($store) {
         $this->ip_addresses = cbpaidRequest::getIPlist();
         $this->historySetMessage($this->recordName() . ' record created');
         $this->store();
     }
     $this->_plan = $plan;
 }
	/**
	 * create a new subscription object and corresponding object in database
	 *
	 * @param int|null       $user_id                 CB user id
	 * @param cbpaidProduct  $plan                    plan object of this subscription
	 * @param array|null     $replacesSubscriptionId  array( planId, subscriptionId ) or NULL of the replaced subscription
	 * @param array|null     $parentSubId             array( PlanId, SubscriptionId ) or NULL of the parent subscription
	 * @param string         $status                  like status class variable
	 * @param boolean        $store                   true (default) if should be stored into db
	 * @param int            $subscriptionTime        time of subscription
	 */
	public function createSubscription( $user_id, &$plan, $replacesSubscriptionId = null, $parentSubId = null, $status = 'R', $store = true, $subscriptionTime = null ) {
		global $_CB_framework, $_CB_database;

		if ( $subscriptionTime === null ) {
			$subscriptionTime				=	$_CB_framework->now();
		}

		$this->reset();

		$this->user_id						=	$user_id;
		$this->plan_id						=	$plan->get( 'id' );
		if ( $replacesSubscriptionId ) {
			$this->replaces_plan			=	$replacesSubscriptionId[0];
			$this->replaces_subscription	=	$replacesSubscriptionId[1];
		}
		if ( $parentSubId ) {
			$this->parent_plan				=	$parentSubId[0];
			$this->parent_subscription		=	$parentSubId[1];
		} else {
			$this->parent_plan				=	0;
			$this->parent_subscription		=	0;
		}

		$this->subscription_date			=	date( 'Y-m-d H:i:s', $subscriptionTime );
		$this->last_renewed_date			=	$this->subscription_date;
		$this->expiry_date					=	null;
		$this->status						=	$status;
		$this->autorenew_type				=	0;			// will be changed later at payment time
		$this->autorecurring_type			=	0;			// will be changed later at payment time
		$this->regular_recurrings_total		=	$plan->get( 'recurring_max_times' );
		$this->regular_recurrings_used		=	0;
		$this->previous_recurrings_used		=	0;
		if ( is_object( $plan->_integrations ) ) {
			$this->integrations				=	$plan->_integrations->asJson();
		} else {
			$this->integrations				=	'';
		}

		if ( $store ) {
			$this->ip_addresses				=	cbpaidRequest::getIPlist();
			$this->historySetMessage( 'User subscription record created with status: ' . $status );
			if (!$this->store() ) {
				trigger_error( 'subscription store error:'.htmlspecialchars($_CB_database->getErrorMsg()), E_USER_ERROR );
			}
		}
		$this->_plan						=	$plan;
	}
 /**
  * This is the frontend or backend method used directly
  * @see cbpaidPaymentBasket::store()
  *
  * If table key (id) is NULL : inserts a new row
  * otherwise updates existing row in the database table
  *
  * Can be overridden or overloaded by the child class
  *
  * @param  boolean  $updateNulls  TRUE: null object variables are also updated, FALSE: not.
  * @return boolean                TRUE if successful otherwise FALSE
  */
 public function store($updateNulls = false)
 {
     global $_CB_framework, $_CB_database;
     // 1) check:
     if (!in_array($this->payment_status, array('Pending', 'Refunded', 'NotInitiated'))) {
         $this->setError(CBPTXT::T("This payment basket is not pending."));
         return false;
     }
     if ($this->txn_id == '') {
         $this->txn_id = 'None';
         // needed for updatePayment to generate payment record.
     }
     $paymentBasket = new cbpaidPaymentBasket($_CB_database);
     $paymentBasket->load($this->id);
     if (!$paymentBasket->gateway_account) {
         $this->setError(CBPTXT::T("This payment basket has no gateway associated so can not be paid manually."));
         return false;
     }
     $ipn = new cbpaidPaymentNotification($_CB_database);
     $ipn->bindObjectToThisObject($paymentBasket, 'id');
     $ipn->mc_currency = $this->mc_currency;
     $ipn->mc_gross = $this->mc_gross;
     if (!preg_match('/^[1-9][0-9]{3}-[01][0-9]-[0-3][0-9]/', $this->time_completed)) {
         $this->time_completed = Application::Database()->getUtcDateTime();
     }
     $paymentBasket->time_completed = $this->time_completed;
     $ipn->payment_type = $this->payment_type;
     $paymentBasket->payment_type = $this->payment_type;
     $ipn->txn_id = $this->txn_id;
     $paymentBasket->txn_id = $this->txn_id;
     $ipn->payment_status = 'Completed';
     $ipn->txn_type = 'web_accept';
     $ipn->payment_method = $this->payment_method;
     $ipn->gateway_account = $this->gateway_account;
     $ipn->log_type = 'P';
     $ipn->time_received = $_CB_database->getUtcDateTime();
     $ipn->payment_date = gmdate('H:i:s M d, Y T', $this->time_completed ? cbpaidTimes::getInstance()->strToTime($this->time_completed) : cbpaidTimes::getInstance()->startTime());
     // paypal-style				//TBD FIXME: WE SHOULD CHANGE THIS OLD DATE STYLE ONCE WITH UTC timezone inputed
     $ipn->payment_basket_id = $this->id;
     $ipn->raw_result = 'manual';
     $ipn->raw_data = '';
     $ipn->ip_addresses = cbpaidRequest::getIPlist();
     $ipn->user_id = Application::MyUser()->getUserId();
     $ipn->txn_id = $this->txn_id;
     $ipn->payment_type = $this->payment_type;
     $ipn->charset = $_CB_framework->outputCharset();
     //TBD
     /*
     		$paymentBasket->first_name	= $ipn->first_name	= cbGetParam( $_POST, 'txtBTitle' );
     		$paymentBasket->first_name		= $ipn->first_name		= cbGetParam( $_POST, 'txtBFirstName' );
     		$paymentBasket->last_name		= $ipn->last_name		= cbGetParam( $_POST, 'txtBLastName' );
     		$paymentBasket->address_street	= $ipn->address_street	= cbGetParam( $_POST, 'txtBAddr1' );
     		$paymentBasket->address_zip		= $ipn->address_zip		= cbGetParam( $_POST, 'txtBZipCode' );
     		$paymentBasket->address_city	= $ipn->address_city	= cbGetParam( $_POST, 'txtBCity' );
     		$paymentBasket->address_country	= $ipn->address_country	= cbGetParam( $_POST, 'txtBCountry' );
     		//TBD? $paymentBasket->phone	= $ipn->phone			= cbGetParam( $_POST, 'txtBTel' );
     		//TBD? $paymentBasket->fax		= $ipn->fax				= cbGetParam( $_POST, 'txtBFax' );
     		$paymentBasket->payer_email		= $ipn->payer_email		= cbGetParam( $_POST, 'txtBEmail' );
     */
     if (!$_CB_database->insertObject($ipn->getTableName(), $ipn, $ipn->getKeyName())) {
         trigger_error('store error:' . htmlspecialchars($_CB_database->getErrorMsg()), E_USER_ERROR);
         //TBD also in paypal: error code 500 !!!
     }
     $payAccount = cbpaidControllerPaychoices::getInstance()->getPayAccount($paymentBasket->gateway_account);
     if (!$payAccount) {
         $this->setError(CBPTXT::T("This payment basket's associated gateway account is not active, so can not be paid manually."));
         return false;
     }
     $payClass = $payAccount->getPayMean();
     $payClass->updatePaymentStatus($paymentBasket, 'web_accept', 'Completed', $ipn, 1, 0, 0, 'singlepayment');
     return true;
 }
	/**
	 * Logs notification
	 *
	 * @param  string                           $log_type
	 * @param  int                              $now
	 * @param  cbpaidPaymentBasket              $paymentBasket
	 * @return cbpaidPaymentNotification
	 */
	private function _logNotification( $log_type, $now, $paymentBasket )
	{
		global $_CB_database;

		$ipn = new cbpaidPaymentNotification($_CB_database);
		$ipn->payment_method	=	$this->getPayName();
		$ipn->gateway_account	=	$this->getAccountParam( 'id' );
		$ipn->log_type			=	$log_type;
		$ipn->time_received		=	date( 'Y-m-d H:i:s', $now );
		$ipn->payment_basket_id	=	$paymentBasket->id;

		$ipn->raw_data			=	'$_POST=' . var_export( $_POST, true ) . ';\n';

		$ipn->raw_result 		=	'FREE_TRIAL';
		$ipn->ip_addresses		=	cbpaidRequest::getIPlist();
		$ipn->notify_version	=	'2.1';
		$ipn->user_id			=	(int) cbGetParam( $_GET, 'user', 0 );
		$ipn->charset			=	'utf-8';
		$ipn->test_ipn			=	0;
		$ipn->first_name		=	$paymentBasket->first_name;
		$ipn->last_name			=	$paymentBasket->last_name;
		$ipn->payer_status		=	'unverified';
		$ipn->item_name			=	$paymentBasket->item_name;
		$ipn->item_number		=	$paymentBasket->item_number;
		$ipn->quantity			=	$paymentBasket->quantity;
		$ipn->custom			=	$paymentBasket->id;
		$ipn->invoice			=	$paymentBasket->invoice;
		$ipn->mc_currency		=	$paymentBasket->mc_currency;
		$ipn->tax				=	'0.00';
		$ipn->mc_gross			=	'0.00';
		$ipn->payment_status	=	'Completed';
		$ipn->payment_date		=	date( 'H:i:s M d, Y T', $now );			// paypal-style
		$ipn->payment_type		=	'Free trial';
		$ipn->txn_id			=	null;
		$ipn->txn_type			=	'web_accept';
		$ipn->recurring			=	0;

		$_CB_database->insertObject( $ipn->getTableName(), $ipn, $ipn->getKeyName() );

		return $ipn;
	}
	/**
	 * create a paymentBasket in database
	 *
	 * @param  UserTable  $user
	 * @param  float      $price
	 * @param  string     $currency
	 * @param  int        $quantity
	 * @param  string     $item_number
	 * @param  string     $item_name
	 * @param  boolean    $store         default: TRUE: store object in database, FALSE: keep in memory only
	 * @param  int        $now           unix time
	 * @param  int        $owner         basket owner (seller)
	 * @param  string     $reason        payment reason: 'N'=new subscription (default), 'R'=renewal, 'U'=update
	 */
	public function createPaymentBasket( &$user, $price, $currency, $quantity, $item_number, $item_name, $store, $now, $owner, /** @noinspection PhpUnusedParameterInspection */ $reason ) {
		global $_CB_database;

		$this->reset();

		$this->user_id			=	(int) $user->id;
		$this->owner			=	(int) $owner;
		$this->payment_status	=	'NotInitiated';
		$this->time_initiated	=	date( 'Y-m-d H:i:s', $now );
		$this->ip_addresses		=	cbpaidRequest::getIPlist();
		$this->mc_gross			=	$price;		// for now, later sum...
		$this->mc_currency		=	$currency;
		$this->quantity			=	$quantity;
		$this->item_number		=	$item_number;
		$this->item_name		=	$item_name;
		$this->setRandom_shared_secret();
		$this->_setInvoicingAddress( $user );
		if ( $store ) {
			$this->historySetMessage( 'Creating new payment basket' );
			if ( ! $this->store() ) {
				trigger_error( 'payment_basket store error:' . htmlspecialchars( $_CB_database->getErrorMsg() ), E_USER_ERROR );
			}
		}
	}
/**
 * Gets a comma-separated list of IP addresses taking in account the proxys on the way.
 * An array is needed because FORWARDED_FOR can be facked as well.
 *
 * @obsolete since CBSubs 2.1
 *
 * @return string of IP addresses, first one being host, and last one last proxy (except fackings)
 */
function cbpaidGetIPlist()
{
    return cbpaidRequest::getIPlist();
}
	/**
	 * Handle Paypal PDT
	 *
	 * @param  cbpaidPaymentBasket  $paymentBasket  New empty object. returning: includes the id of the payment basket of this callback (strictly verified, otherwise untouched)
	 * @param  array                $postdata       _POST data for saving edited tab content as generated with getEditTab
	 * @return string                               HTML to display if frontend, text to return to gateway if notification, FALSE if registration cancelled and ErrorMSG generated, or NULL if nothing to display
	 */
	private function handlePaypalPDT( $paymentBasket, /** @noinspection PhpUnusedParameterInspection */ $postdata )
	{
		global $_CB_framework, $_CB_database, $_GET, $_POST;

		$ret								=	null;
		// The user got redirected back from paypal with a success message:

		if ( isset( $_GET['tx'] ) && isset( $_GET['st'] ) && isset( $_GET['amt'] ) && isset( $_GET['cc'] ) ) {

			/// P D T :		Process Payment Data Transaction (PDT):

			// check if PDT not already processed:
			$pbTmp							=	new cbpaidPaymentBasket( $_CB_database );
			$paymentBasketId				=	(int) $this->_getReqParam('basket');
			if ( $paymentBasketId
				&& $pbTmp->load( (int) $paymentBasketId )
				&& ( $pbTmp->payment_status == cbGetParam( $_GET, 'st' ) )
				&& ( $pbTmp->txn_id == cbGetParam( $_GET, 'tx' ) )
				&& ( $pbTmp->shared_secret ==cbGetParam( $_GET, 'cbpid' ) ) )
			{
				// this PDT has already been treated...probably a Nth reload or bookmarked page:
				$paymentBasket->load( (int) $pbTmp->id );
			} else {
				$ipn						=	new cbpaidPaymentNotification($_CB_database);
				$ipn->payment_method		=	$this->getPayName();
				$ipn->gateway_account		=	$this->getAccountParam( 'id' );
				// done below: $ipn->log_type			= 'R';
				$ipn->time_received			=	date( 'Y-m-d H:i:s', $_CB_framework->now() );
				$ipn->raw_data				=	/* cbGetParam() not needed: we want raw info */ '$_GET=' . var_export( $_GET, true ) . ";\n";
				$ipn->raw_data				.=	/* cbGetParam() not needed: we want raw info */ '$_POST=' . var_export( $_POST, true ) . ";\n";
				$ipn->ip_addresses			=	cbpaidRequest::getIPlist();
				$ipn->user_id				=	$pbTmp->user_id;

				// post back to PayPal system to validate:
				$formvars					=	array(	'cmd'	=> '_notify-synch',
														'tx'	=> cbGetParam( $_REQUEST, 'tx', '' ),
														'at'	=> trim($this->getAccountParam('paypal_identity_token'))
													 );
				$results					=	null;
				$status						=	null;
				$error						=	$this->_httpsRequest( $this->_paypalUrl() . '/cgi-bin/webscr', $formvars, 30, $results, $status, 'post', 'normal', '*/*', true, 443, '', '', true, null );
				$transaction_info			=	urldecode($results);			//FIXME: urldecode is done below already!

				if ( $error || ( $status != 200 ) ) {
					$ipn->raw_result		=	'COMMUNICATION ERROR';
//					$ipn->raw_data = 'Error: '. $error . ' Status: ' . $status . ' Transaction info: ' . $transaction_info;
					$ipn->raw_data			.=	'$error=\''. $error . "';\n";
					$ipn->raw_data			.=	'$status=\'' . $status . "';\n";
					$ipn->raw_data			.=	'$formvars=' . var_export( $formvars, true ) . ";\n";
					$ipn->raw_data			.=	'$transaction_info=\'' . $transaction_info . "';\n";
					$ipn->log_type			=	'E';
					$ipn->time_received		=	date( 'Y-m-d H:i:s', $_CB_framework->now() );
					$_CB_database->insertObject( $ipn->getTableName(), $ipn, $ipn->getKeyName() );

					$this->_setLogErrorMSG( 3, $ipn, 'Paypal: Error at notification received: could not reach Paypal gateway for notification check at ' . $this->_paypalUrl() . '. ' . $ipn->raw_result, null );
					$this->_setErrorMSG( sprintf( CBPTXT::T("Sorry no response for your payment from payment server (error %s). Please check your email and status later."), $error ) );
					$ret					=	false;
				} else {
					// echo $transaction_info;
					$input = explode("\n", $transaction_info);
					foreach ($input as $k => $in) {
						$input[$k]			=	trim( $in, "\n\r" );
					}
					$resultMessage = array_shift( $input );
					$output					=	array();
					foreach ($input as $in) {
						$posEqualSign		=	strpos($in, '=');
						if ($posEqualSign === false) {
							$output[]		=	$in;
						} else {
							$output[substr($in,0,$posEqualSign)]	=	substr($in, $posEqualSign+1);
						}
					}
					if ( isset( $output['charset'] ) && ( $resultMessage == 'SUCCESS' ) ) {
						if ( strtolower( $output['charset'] ) != strtolower( $_CB_framework->outputCharset() ) ) {
							foreach ($output as $k => $v ) {
								$output[$k]		=	$this->_charsetConv( $v, $output['charset'], $_CB_framework->outputCharset() );
							}
							$output['charset']	=	$_CB_framework->outputCharset();
						}			
					}
					$ipn->bind( $output );
					$ipn->raw_result 		=	$resultMessage;
					$ipn->raw_data			.=	'$transaction_info=\'' . $transaction_info . "';\n";
					$ipn->raw_data			.=	'$PDT_RESULT=' . var_export( $output, true ) . ";\n";
					$ipn->payment_basket_id	=	(int) $ipn->custom;
					/*
					if(!$_CB_database->updateObject( $ipn->_tbl, $ipn, $ipn->_tbl_key, false)) {
						echo 'update error:'.htmlspecialchars($_CB_database->stderr(true))."\n";
						exit();
					}
					*/
	
					if ( $resultMessage == 'SUCCESS' ) {
						$ipn->log_type							= 'R';
						$_CB_database->insertObject( $ipn->getTableName(), $ipn, $ipn->getKeyName() );

						$paymentBasketId						=	(int) $ipn->custom;
						$exists									=	$paymentBasket->load( (int) $paymentBasketId );
						if ( $exists ) {
							$this->_fixPayPalIpnBugs( $ipn, $paymentBasket );
							$noFraudCheckResult					=	$this->_checkNotPayPalFraud( $ipn, $paymentBasket, cbGetParam( $_REQUEST, 'cbpid', '' ) );
							if ( $noFraudCheckResult === true ) {
								$autorecurring_type				=	( in_array( $ipn->txn_type, array( 'subscr_payment', 'subscr_signup', 'subscr_modify', 'subscr_eot', 'subscr_cancel', 'subscr_failed' ) ) ? 2 : 0 );
								$paypalUserChoicePossible		=	( ( $this->getAccountParam( 'enabled', 0 ) == 3 ) && ( $paymentBasket->isAnyAutoRecurring() == 2 ) );
								$autorenew_type					=	( $autorecurring_type ? ( $paypalUserChoicePossible ? 1 : 2 ) : 0 );
								$this->_bindIpnToBasket( $ipn, $paymentBasket );
								$paymentBasket->payment_method	=	$this->getPayName();
								$paymentBasket->gateway_account	=	$this->getAccountParam( 'id' );
								$this->updatePaymentStatus( $paymentBasket, $ipn->txn_type, $ipn->payment_status, $ipn, 1, $autorecurring_type, $autorenew_type, false );

							} else {
								$this->_setLogErrorMSG( 3, $ipn, 'Received back from paypal: ' . var_export( $ipn, true ), CBPTXT::T("Payment notification mismatch: ") . $noFraudCheckResult . '.' );
								$ret = false;
								//TBD: update notification record !
								$ipn->log_type					=	'G';		// PDT FRAUD detected
								$ipn->raw_result				=	$noFraudCheckResult;
								$_CB_database->updateObject( $ipn->getTableName(), $ipn, $ipn->getKeyName(), false);
							}
						}
					} elseif ( $resultMessage == 'FAIL' ) {
						$ipn->log_type							= 'L';
						$_CB_database->insertObject( $ipn->getTableName(), $ipn, $ipn->getKeyName() );

						$this->_setLogErrorMSG( 3, $ipn, 'Paypal: Error: Received FAIL result message from Paypal', CBPTXT::T("Sorry your payment has not been processed. Transaction result:")
							. $transaction_info
							. '. ' . CBPTXT::T("Please try again and notify system administrator.") );
						$ret = false;
					} else {
						$ipn->log_type							= 'N';
						$_CB_database->insertObject( $ipn->getTableName(), $ipn, $ipn->getKeyName() );

						$this->_setLogErrorMSG( 3, $ipn, 'Paypal: Error: Received following unknown result message from Paypal: ' . $resultMessage, CBPTXT::T("Sorry no response for your payment. Please check your email and status later.") );
						$ret = false;
					}
				}
			}
		} else {
			// result=success but not a PDT from paypal:

			// it could be a subscription with a free trial period: in that case, as there is no initial transaction, we get returned without txn_id.
			// we must either guess that user subscribed (if he is allowed for free trials, or must wait for IPN:

			$paymentBasketId											=	(int) $this->_getReqParam( 'basket' );
			if ( $paymentBasketId ) {
				if ( $paymentBasket->load( (int) $paymentBasketId ) ) {
					$cbpid												=	cbGetParam( $_REQUEST, 'cbpid', '' );
					if ( $cbpid == $paymentBasket->shared_secret ) {
						$enable_paypal									=	$this->getAccountParam( 'enabled', 0 );
						$isAnyAutoRecurring								=	$paymentBasket->isAnyAutoRecurring();
						$pay1subscribe2									=	$this->_getPaySubscribePossibilities( $enable_paypal, $paymentBasket );
						if ( $isAnyAutoRecurring && ( ( $pay1subscribe2 & 0x2 ) != 0 ) && $paymentBasket->period1 ) {
							// Free first period: Wait for IPN for 20 times 1 second:
							for ( $i = 0; $i < 20; $i++ ) {
								if ( $paymentBasket->load( (int) $paymentBasketId ) ) {
									if ( $paymentBasket->payment_status == 'Completed' ) {
										break;
									}
								} else {
									break;
								}
								sleep( 1 );
							}
							if ( $paymentBasket->payment_status != 'Completed' ) {
								if ( ( $isAnyAutoRecurring == 1 ) || ( ( $isAnyAutoRecurring == 2 ) && ( $paymentBasket->mc_amount1 != 0 ) ) )  {
									// 1: forced subscription: error if no IPN came to update payment basket:
									// 2: not forced subscription but no free initial value: we really need IPN to know status:
										$this->_setErrorMSG(CBPTXT::T("Sorry, payment has not been confirmed by Paypal (no IPN received). IPN must be enabled for auto-recurring payment subscriptions."));
								} else {
									// user-choice: no need to wait for payment basket completed to activate subscriptions:

									$ipn								=	new cbpaidPaymentNotification($_CB_database);
									$ipn->payment_method				=	$this->getPayName();
									$ipn->gateway_account				=	$this->getAccountParam( 'id' );
									$ipn->log_type						=	'S';
									$ipn->time_received					=	date( 'Y-m-d H:i:s', $_CB_framework->now() );
									$ipn->raw_data						=	/* cbGetParam() not needed: we want raw info */ '$_GET=' . var_export( $_GET, true ) . ";\n";
									$ipn->raw_data						.=	/* cbGetParam() not needed: we want raw info */ '$_POST=' . var_export( $_POST, true ) . ";\n";
									$ipn->ip_addresses					=	cbpaidRequest::getIPlist();
									$ipn->payment_basket_id				=	$paymentBasket->id;
									$ipn->user_id						=	$paymentBasket->user_id;
									$_CB_database->insertObject( $ipn->getTableName(), $ipn, $ipn->getKeyName() );

									if ( $isAnyAutoRecurring == 2 )  {
										$autorecurring_type				=	2;
										$paypalUserChoicePossible		=	( ( $this->getAccountParam( 'enabled', 0 ) == 3 ) && ( $paymentBasket->isAnyAutoRecurring() == 2 ) );
										$autorenew_type					=	( $autorecurring_type ? ( $paypalUserChoicePossible ? 1 : 2 ) : 0 );
									} else {
										$autorecurring_type				=	0;
										$autorenew_type					=	0;
									}
									$paymentBasket->payment_method		=	$this->getPayName();
									$paymentBasket->gateway_account		=	$this->getAccountParam( 'id' );

									$this->updatePaymentStatus( $paymentBasket, 'web_accept', 'Completed', $ipn, 1, $autorecurring_type, $autorenew_type, false );
								}
							}
						}
					}
				}
			}


		}
		return $ret;
	}