Version 4.3.0

This commit is contained in:
Neo committed 2025-12-19 05:47:12 -08:00
1 parent 96997ddd8e
commit fe1acf984a
1349 files changed
+116159 -67711

No files matched your search

@@ -40,11 +40,6 @@ class _checkout extends \IPS\Dispatcher\Controller
*/
public function execute()
{
if ( mb_strtolower( $_SERVER['REQUEST_METHOD'] ) == 'get' and \IPS\Settings::i()->nexus_https and \IPS\Request::i()->url()->data['scheme'] !== 'https' )
{
\IPS\Output::i()->redirect( \IPS\Request::i()->url()->setScheme('https') );
}
\IPS\Output::i()->sidebar['enabled'] = FALSE;
\IPS\Output::i()->bodyClasses[] = 'ipsLayout_minimal';
\IPS\Output::i()->cssFiles = array_merge( \IPS\Output::i()->cssFiles, \IPS\Theme::i()->css( 'checkout.css', 'nexus' ) );
@@ -56,6 +51,7 @@ class _checkout extends \IPS\Dispatcher\Controller
}
\IPS\Output::i()->jsFiles = array_merge( \IPS\Output::i()->jsFiles, \IPS\Output::i()->js( 'front_checkout.js', 'nexus', 'front' ) );
\IPS\Output::i()->jsFiles = array_merge( \IPS\Output::i()->jsFiles, \IPS\Output::i()->js( 'global_gateways.js', 'nexus', 'global' ) );
\IPS\Output::i()->title = \IPS\Member::loggedIn()->language()->addToStack( 'module__nexus_checkout' );
parent::execute();
@@ -75,11 +71,6 @@ class _checkout extends \IPS\Dispatcher\Controller
if ( !$this->invoice->canView() )
{
if ( !$this->invoice->member->member_id and \IPS\Member::loggedIn()->member_id and isset( \IPS\Request::i()->loginKey ) and \IPS\Request::i()->loginKey === md5( json_encode( $this->invoice->items ) . session_id() . \IPS\SUITE_UNIQUE_KEY ) )
{
$this->_assignInvoiceToMember( \IPS\Member::loggedIn() );
}
throw new \OutOfRangeException;
}
}
@@ -168,7 +159,10 @@ class _checkout extends \IPS\Dispatcher\Controller
/* Do we need to log in? */
$this->needsToLogin = ( !\IPS\Member::loggedIn()->member_id and ( $this->invoice->requiresLogin() or \IPS\Settings::i()->nexus_donate_loggedin ) );
/* Facebook Pixel */
\IPS\core\Facebook\Pixel::i()->InitiateCheckout = true;
/* Do the wizard */
\IPS\Output::i()->sidebar['enabled'] = FALSE;
if ( isset( \IPS\Output::i()->breadcrumb['module'][0] ) )
@@ -198,7 +192,7 @@ class _checkout extends \IPS\Dispatcher\Controller
$form = new \IPS\Helpers\Form( 'customer', $buttonLang, $this->invoice->checkoutUrl()->setQueryString( '_step', 'checkout_customer' ) );
/* Account Information */
if ( $this->needsToLogin and \IPS\Settings::i()->allow_reg )
if ( $this->needsToLogin and !in_array( \IPS\Login::registrationType(), array( 'disabled', 'redirect' ) ) )
{
$guestData = $this->invoice->guest_data;
@@ -240,7 +234,7 @@ class _checkout extends \IPS\Dispatcher\Controller
}
/* Billing Information */
if ( $needBillingInfo or ( $this->needsToLogin and \IPS\Settings::i()->allow_reg and !\IPS\Settings::i()->nexus_checkreg_usernames ) )
if ( $needBillingInfo or ( $this->needsToLogin and !in_array( \IPS\Login::registrationType(), array( 'disabled', 'redirect' ) ) and !\IPS\Settings::i()->nexus_checkreg_usernames ) )
{
$form->add( new \IPS\Helpers\Form\Text( 'cm_first_name', $this->invoice->member->cm_first_name, TRUE ) );
$form->add( new \IPS\Helpers\Form\Text( 'cm_last_name', $this->invoice->member->cm_last_name, TRUE ) );
@@ -288,7 +282,7 @@ class _checkout extends \IPS\Dispatcher\Controller
}
/* Additional Information */
if ( $this->needsToLogin and \IPS\Settings::i()->allow_reg )
if ( $this->needsToLogin and !in_array( \IPS\Login::registrationType(), array( 'disabled', 'redirect' ) ) )
{
$form->addHeader('additional_information');
@@ -423,7 +417,7 @@ class _checkout extends \IPS\Dispatcher\Controller
}
/* Misc */
$form->add( new \IPS\Helpers\Form\Checkbox( 'reg_admin_mails', $guestData ? $guestData['member']['allow_admin_mails'] : TRUE, FALSE ) );
$form->add( new \IPS\Helpers\Form\Checkbox( 'reg_admin_mails', $guestData ? $guestData['member']['allow_admin_mails'] : \IPS\Settings::i()->updates_consent_default == 'enabled' ? TRUE : FALSE, FALSE ) );
\IPS\Member::loggedIn()->language()->words[ "reg_agreed_terms" ] = sprintf( \IPS\Member::loggedIn()->language()->get("reg_agreed_terms"), \IPS\Http\Url::internal( 'app=core&module=system&controller=terms', 'front', 'terms', array(), \IPS\Http\Url::PROTOCOL_RELATIVE ) );
/* Build the appropriate links for registration terms & privacy policy */
@@ -452,7 +446,7 @@ class _checkout extends \IPS\Dispatcher\Controller
if ( $this->needsToLogin )
{
/* It shouldn't be possible to get here */
if ( !\IPS\Settings::i()->allow_reg )
if ( in_array( \IPS\Login::registrationType(), array( 'disabled', 'redirect' ) ) )
{
\IPS\Output::i()->error( 'reg_disabled', '3X196/A', 403, '' );
}
@@ -477,7 +471,7 @@ class _checkout extends \IPS\Dispatcher\Controller
/* Security questions */
$securityQuestionAnswers = array();
if ( \IPS\Settings::i()->security_questions_enabled and in_array( \IPS\Settings::i()->security_questions_prompt, array( 'register', 'optional' ) ) )
if ( \IPS\Settings::i()->security_questions_enabled and ( \IPS\Settings::i()->security_questions_prompt === 'register' or ( \IPS\Settings::i()->security_questions_prompt === 'optional' and !$values['security_questions_optout_title'] ) ) )
{
foreach ( $values as $k => $v )
{
@@ -517,8 +511,7 @@ class _checkout extends \IPS\Dispatcher\Controller
$member->name = "{$values['cm_first_name']} {$values['cm_last_name']}";
}
$member->email = $values['email_address'];
$member->members_pass_salt = $member->generateSalt();
$member->members_pass_hash = $member->encryptedPassword( $values['password'] );
$member->setLocalPassword( $values['password'] );
$member->allow_admin_mails = $values['reg_admin_mails'];
$member->member_group_id = \IPS\Settings::i()->member_group;
@@ -554,16 +547,22 @@ class _checkout extends \IPS\Dispatcher\Controller
}
/* Run it through the spam service */
$spamCode = NULL;
$spamAction = NULL;
if( \IPS\Settings::i()->spam_service_enabled )
{
if( $member->spamService() == 4 )
$spamAction = $member->spamService( 'register', NULL, $spamCode );
if( $spamAction == 4 )
{
\IPS\Output::i()->error( 'spam_denied_account', '2S129/1', 403, '' );
}
}
/* Save a copy of the member in SESSIONS so the user can print off an invoice */
$_SESSION['nexusMember'] = $member->changed;
/* Save on invoice */
$this->invoice->guest_data = array( 'member' => $member->changed, 'profileFields' => $profileFields, 'securityAnswers' => $securityQuestionAnswers );
$this->invoice->guest_data = array( 'member' => $member->changed, 'profileFields' => $profileFields, 'securityAnswers' => $securityQuestionAnswers, 'spamData' => array( 'code' => $spamCode, 'action' => $spamAction ) );
}
}
/* Otherwise just update the name and details */
@@ -655,16 +654,72 @@ class _checkout extends \IPS\Dispatcher\Controller
/* If we're not logged in, and we need an account for this purchase, show the login form */
$loginForms = NULL;
$loginError = NULL;
$mfaOutput = NULL;
if ( $this->needsToLogin )
{
$login = new \IPS\Login( $this->invoice->checkoutUrl()->setQueryString( 'loginKey', md5( json_encode( $this->invoice->items ) . session_id() . \IPS\SUITE_UNIQUE_KEY ) ) );
$loginForms = $login->forms( FALSE, TRUE ); // This has to be before authenticate() as the result gets cached and we need to specify the destination is the same page
/* Two-Factor Authentication */
if ( isset( \IPS\Request::i()->mfa ) and isset( $_SESSION['processing2FACheckout'] ) and $_SESSION['processing2FACheckout']['invoice'] === $this->invoice->id )
{
$member = \IPS\Member::load( $_SESSION['processing2FACheckout']['memberId'] );
if ( !$member->member_id )
{
unset( $_SESSION['processing2FACheckout'] );
\IPS\Output::i()->redirect( $this->invoice->checkoutUrl() );
}
$device = \IPS\Member\Device::loadOrCreate( $member );
$mfaOutput = \IPS\MFA\MFAHandler::accessToArea( 'core', $device->known ? 'AuthenticateFrontKnown' : 'AuthenticateFront', $this->invoice->checkoutUrl()->setQueryString( 'mfa', 1 ), $member );
if ( !$mfaOutput )
{
/* Set the invoice owner */
$this->invoice->member = $member;
$this->invoice->save();
/* Process the login */
( new \IPS\Login\Success( $member, \IPS\Login\Handler::load( $_SESSION['processing2FACheckout']['handler'] ), $_SESSION['processing2FACheckout']['remember'], $_SESSION['processing2FACheckout']['anonymous'] ) )->process();
/* Redirect */
\IPS\Output::i()->redirect( $this->invoice->checkoutUrl() );
}
}
/* Login */
$login = new \IPS\Login( $this->invoice->checkoutUrl() );
try
{
$member = $login->authenticate();
if ( $member !== NULL )
if ( $success = $login->authenticate() )
{
$this->_assignInvoiceToMember( $member, $login->flags['remember_me'], $login->flags['signin_anonymous'] );
/* Verify it's okay for this member to be buying those items */
try
{
foreach ( $this->invoice->items as $item )
{
$item->memberCanPurchase( $success->member );
}
}
catch ( \DomainException $e )
{
\IPS\Output::i()->error( $e->getMessage(), '1X196/B', 403, '' );
}
/* Process the login */
if ( $success->mfa() )
{
$_SESSION['processing2FACheckout'] = array( 'memberId' => $success->member->member_id, 'invoice' => $this->invoice->id, 'anonymous' => $success->anonymous, 'remember' => $success->rememberMe, 'handler' => $success->handler->id );
\IPS\Output::i()->redirect( $this->invoice->checkoutUrl()->setQueryString( 'mfa', 1 ) );
}
else
{
/* Set the invoice owner */
$this->invoice->member = $success->member;
$this->invoice->save();
/* Process the login */
$success->process();
/* Redirect */
\IPS\Output::i()->redirect( $this->invoice->checkoutUrl() );
}
}
}
catch ( \IPS\Login\Exception $e )
@@ -672,57 +727,12 @@ class _checkout extends \IPS\Dispatcher\Controller
$loginError = $e->getMessage();
}
}
/* Display */
return \IPS\Theme::i()->getTemplate('checkout')->customerInformation( $form->customTemplate( array( call_user_func_array( array( \IPS\Theme::i(), 'getTemplate' ), array( 'checkout', 'nexus' ) ), 'customerInformationForm' ) ), $loginForms, $loginError, $this->invoice );
}
/**
* Assign invoice to user
*
* @param \IPS\Member $member The member
* @param bool $rememberMe Set "Remember me" flag?
* @param bool $anonymous Login is anonymous?
* @return void
*/
protected function _assignInvoiceToMember( \IPS\Member $member, $rememberMe=TRUE, $anonymous=FALSE )
{
/* Verify it's okay for this member to be buying those items */
try
{
foreach ( $this->invoice->items as $item )
{
$item->memberCanPurchase( $member );
}
}
catch ( \DomainException $e )
{
\IPS\Output::i()->error( $e->getMessage(), '1X196/B', 403, '' );
}
/* Log in */
\IPS\Session::i()->setMember( $member );
if ( $anonymous and !\IPS\Settings::i()->disable_anonymous )
{
\IPS\Session::i()->setAnon();
}
/* Log device */
$device = \IPS\Member\Device::loadOrCreate( $member, FALSE );
$device->anonymous = $anonymous and !\IPS\Settings::i()->disable_anonymous;
$device->updateAfterAuthentication( $rememberMe );
/* Member Sync */
$member->memberSync( 'onLogin', array( $this->invoice->checkoutUrl() ) );
/* Set the invoice owner */
$this->invoice->member = $member;
$this->invoice->save();
/* Redirect */
\IPS\Output::i()->redirect( $this->invoice->checkoutUrl() );
}
/**
* Step: Select Shipping
*
@@ -1145,7 +1155,7 @@ class _checkout extends \IPS\Dispatcher\Controller
if ( $item->groupWithParent and is_int( $item->parent ) and isset( $item->renewalTerm ) and $item->renewalTerm )
{
$parent = $this->invoice->items[ $item->parent ];
if ( isset( $parent->renewalTerm ) and $parent->renewalTerm )
if ( ( isset( $parent->renewalTerm ) and $parent->renewalTerm ) or isset( $overriddenRenewalTerms[ $item->parent ] ) )
{
if ( isset( $overriddenRenewalTerms[ $item->parent ] ) )
{
@@ -1255,6 +1265,7 @@ class _checkout extends \IPS\Dispatcher\Controller
/* Build form */
$elements = array();
$paymentMethodsToggles = array();
$showSubmitButton = FALSE;
foreach ( $paymentMethods as $gateway )
{
foreach ( $gateway->paymentScreen( $this->invoice, $amountToPay, NULL, $recurrings ) as $element )
@@ -1266,16 +1277,23 @@ class _checkout extends \IPS\Dispatcher\Controller
$elements[] = $element;
$paymentMethodsToggles[ $gateway->id ][] = $element->htmlId;
}
if ( $gateway->showSubmitButton() )
{
$showSubmitButton = TRUE;
$paymentMethodsToggles[ $gateway->id ][] = 'paymentMethodSubmit';
}
}
$paymentMethodOptions = array();
foreach ( $paymentMethods as $k => $v )
{
$paymentMethodOptions[ $k ] = $v->_title;
}
if ( $canUseAccountCredit and \IPS\nexus\Customer::loggedIn()->cm_credits[ $this->invoice->currency ]->amount->isGreaterThanZero() )
if ( $canUseAccountCredit and isset( \IPS\nexus\Customer::loggedIn()->cm_credits[ $this->invoice->currency ] ) and \IPS\nexus\Customer::loggedIn()->cm_credits[ $this->invoice->currency ]->amount->isGreaterThanZero() )
{
$paymentMethodOptions[0] = \IPS\Member::loggedIn()->language()->addToStack( 'account_credit_with_amount', FALSE, array( 'sprintf' => array( \IPS\nexus\Customer::loggedIn()->cm_credits[ $this->invoice->currency ] ) ) );
$paymentMethodsToggles[0][] = 'paymentMethodSubmit';
}
$form = new \IPS\Helpers\Form( 'select_method', 'checkout_pay', $this->invoice->checkoutUrl()->setQueryString( '_step', 'checkout_pay' ) );
@@ -1294,7 +1312,7 @@ class _checkout extends \IPS\Dispatcher\Controller
}
if ( \IPS\Settings::i()->nexus_tac === 'checkbox' )
{
$form->add( new \IPS\Helpers\Form\Checkbox( 'i_agree_to_tac', FALSE, TRUE, array( 'labelHtmlSprintf' => array( "<a href='" . htmlspecialchars( \IPS\Settings::i()->nexus_tac_link, \IPS\HTMLENTITIES, 'UTF-8', FALSE ) . "' target='_blank'>" . \IPS\Member::loggedIn()->language()->addToStack( 'terms_and_conditions' ) . '</a>' ) ), function( $val )
$form->add( new \IPS\Helpers\Form\Checkbox( 'i_agree_to_tac', FALSE, TRUE, array( 'labelHtmlSprintf' => array( "<a href='" . htmlspecialchars( \IPS\Settings::i()->nexus_tac_link, ENT_DISALLOWED, 'UTF-8', FALSE ) . "' target='_blank'>" . \IPS\Member::loggedIn()->language()->addToStack( 'terms_and_conditions' ) . '</a>' ) ), function( $val )
{
if ( !$val )
{
@@ -1407,7 +1425,7 @@ class _checkout extends \IPS\Dispatcher\Controller
$transaction->auth = $gateway->auth( $transaction, $values, $maxMind, $recurrings );
}
catch ( \LogicException $e )
{
{
$form->error = $e->getMessage();
return $form;
}
@@ -1487,6 +1505,7 @@ class _checkout extends \IPS\Dispatcher\Controller
throw new \DomainException('coupon_code_invalid');
}
}
return '';
}
) ) );
if ( $values = $couponForm->values() )
@@ -1499,7 +1518,7 @@ class _checkout extends \IPS\Dispatcher\Controller
}
/* Display */
return \IPS\Theme::i()->getTemplate('checkout')->confirmAndPay( $this->invoice, $this->invoice->summary(), $form->customTemplate( array( call_user_func_array( array( \IPS\Theme::i(), 'getTemplate' ), array( 'checkout', 'nexus' ) ), 'paymentForm' ), $this->invoice, $amountToPay ), $amountToPay, $couponForm ? $couponForm->customTemplate( array( call_user_func_array( array( \IPS\Theme::i(), 'getTemplate' ), array( 'checkout', 'nexus' ) ), 'couponForm' ) ) : NULL, $recurrings, $overriddenRenewalTerms );
return \IPS\Theme::i()->getTemplate('checkout')->confirmAndPay( $this->invoice, $this->invoice->summary(), $form->customTemplate( array( call_user_func_array( array( \IPS\Theme::i(), 'getTemplate' ), array( 'checkout', 'nexus' ) ), 'paymentForm' ), $this->invoice, $amountToPay, $showSubmitButton ), $amountToPay, $couponForm ? $couponForm->customTemplate( array( call_user_func_array( array( \IPS\Theme::i(), 'getTemplate' ), array( 'checkout', 'nexus' ) ), 'couponForm' ) ) : NULL, $recurrings, $overriddenRenewalTerms );
}
/**
@@ -1560,7 +1579,7 @@ class _checkout extends \IPS\Dispatcher\Controller
$output = '';
$checkoutStatus = '';
switch ( $transaction->status )
{
case \IPS\nexus\Transaction::STATUS_PAID:
@@ -1606,12 +1625,23 @@ class _checkout extends \IPS\Dispatcher\Controller
$checkoutStatus = 'pending';
$output = \IPS\Theme::i()->getTemplate('checkout')->transactionGatewayPending( $transaction );
break;
case \IPS\nexus\Transaction::STATUS_PENDING:
if ( isset( \IPS\Request::i()->pending ) )
{
$checkoutStatus = 'pending';
$output = \IPS\Theme::i()->getTemplate('checkout')->transactionGatewayPending( $transaction );
break;
}
default:
\IPS\Output::i()->redirect( $transaction->invoice->checkoutUrl() );
break;
}
/* Facebook Pixel */
\IPS\core\Facebook\Pixel::i()->Purchase = true;
\IPS\Output::i()->output = \IPS\Theme::i()->getTemplate('checkout')->checkoutWrapper( $output, $checkoutStatus );
}
}
}