* @link https://TheTempusProject.com * @license https://opensource.org/licenses/MIT [MIT LICENSE] */ namespace TheTempusProject\Controllers; use TheTempusProject\Houdini\Classes\Template; use TheTempusProject\Houdini\Classes\Views; use TheTempusProject\Houdini\Classes\Issues; use TheTempusProject\Classes\Controller; use TheTempusProject\TheTempusProject as App; use TheTempusProject\Hermes\Functions\Redirect; use TheTempusProject\Bedrock\Functions\Session; use TheTempusProject\Models\MembershipCustomers; use TheTempusProject\Models\MembershipProducts; use TheTempusProject\Bedrock\Classes\Config; use TheTempusProject\Bedrock\Functions\Input; use Stripe\Checkout\Session as StripeSession; use TheTempusProject\Hermes\Functions\Route as Routes; use TheTempusProject\Houdini\Classes\Navigation; use TheTempusProject\Models\Memberships; use TheTempusProject\Houdini\Classes\Components; use TheTempusProject\Classes\Forms; use TheTempusProject\Bedrock\Functions\Hash; use TheTempusProject\Canary\Bin\Canary as Debug; use Stripe\StripeClient; class Member extends Controller { public static $customers; public static $products; public static $stripe; private static $loaded = false; public function __construct() { parent::__construct(); if ( ! self::$loaded ) { Template::noIndex(); self::$customers = new MembershipCustomers; self::$products = new MembershipProducts; $api_key = Config::getValue( 'memberships/stripeSecret' ); if ( $api_key == 'sk_xxxxxxxxxxxxxxx' || empty($api_key) ) { Debug::error( "Memberships:__construct No Stripe Key found" ); } else { self::$stripe = new StripeClient( $api_key ); } self::$loaded = true; } } public function index() { $this->confirmAuth(); self::$title = 'Members Area'; Views::view( 'members.members' ); } public function managepayment( $id = null ) { $this->confirmAuth(); $customer = self::$customers->findByUserID( App::$activeUser->ID ); if ( empty( $customer ) ) { Session::flash( 'error', 'You do not have any active payment methods. You can subscribe by going here' ); return Redirect::to( 'member/manage' ); } try { $session = self::$stripe->billingPortal->sessions->create([ 'customer' => $customer, 'return_url' => Routes::getAddress() . 'member/manage', ]); } catch (\Stripe\Exception\InvalidRequestException $e) { Debug::error('Membership -> ManagePayment - Stripe not configured correctly'); Debug::error( $e ); Session::flash( 'error', 'There was an issue redirecting you to Stripe, please try again.' ); return Redirect::to( 'member/manage' ); } header('Location: ' . $session->url); exit; } public function cancelconfirm( $id = null ) { $this->confirmAuth(); $memberships = new Memberships; $result = $memberships->cancel( $id ); if ( ! empty( $result ) ) { Session::flash( 'success', 'Your Membership has been paused.' ); Redirect::to( 'member/manage' ); } else { Session::flash( 'error', 'There was an error canceling your membership' ); Redirect::to( 'member/manage' ); } } public function pauseconfirm( $id = null ) { $this->confirmAuth(); $memberships = new Memberships; $result = $memberships->cancel( $id ); if ( ! empty( $result ) ) { Session::flash( 'success', 'Your Membership has been paused.' ); Redirect::to( 'member/manage' ); } else { Session::flash( 'error', 'There was an error canceling your membership' ); Redirect::to( 'member/manage' ); } } public function pause( $id = null ) { $this->confirmAuth(); self::$title = 'pause Membership'; Components::set( 'pauseid', $id ); Views::view( 'members.pause' ); } public function resume( $id = null ) { $this->confirmAuth(); self::$title = 'resume Membership'; Views::view( 'members.resume' ); } public function cancel( $id = null ) { $this->confirmAuth(); self::$title = 'Cancel Membership'; Components::set( 'cancelid', $id ); Views::view( 'members.cancel' ); } public function manage( $id = null ) { if ( ! App::$isLoggedIn ) { Session::flash( 'error', 'You do not have permission to access this page.' ); return Redirect::home(); } self::$title = 'Manage Membership'; $menu = Views::simpleView( 'nav.usercp', App::$userCPlinks ); Navigation::activePageSelect( $menu, null, true, true ); $memberships = new Memberships; $userMemberships = $memberships->getUserSubs(); Views::view( 'members.manage', $userMemberships ); } public function upgrade( $id = null ) { if ( ! App::$isLoggedIn ) { Session::flash( 'error', 'You do not have permission to access this page.' ); return Redirect::home(); } self::$title = 'Upgrade Membership'; Views::view( 'members.upgrade' ); } public function join( $plan = 'monthly' ) { if ( ! App::$isLoggedIn ) { Session::flash( 'error', 'You do not have permission to access this page.' ); return Redirect::home(); } $plan = strtolower( $plan ); if ( ! in_array( $plan, ['monthly','yearly'] ) ) { Session::flash( 'error', 'Unknown plan' ); return Redirect::to( 'home/index' ); } self::$title = 'Join {SIITENAME}!'; $stripePrice = $this->findPrice( $plan ); $product = self::$products->findByPriceID( $stripePrice ); if ( empty( $product ) ) { Session::flash( 'success', 'We aren\'t currently accepting new members, please check back soon!' ); return Redirect::home(); } Views::view( 'members.landing1', $product ); } public function checkout( $plan = 'monthly' ) { if ( ! App::$isLoggedIn ) { Session::flash( 'error', 'You do not have permission to access this page.' ); return Redirect::home(); } $customer = self::$customers->findOrCreate( App::$activeUser->ID ); if ( empty( $customer ) ) { Issues::add( 'error', 'no customer' ); return $this->index(); } $stripePrice = $this->findPrice( $plan ); $session = self::$stripe->checkout->sessions->create([ 'payment_method_types' => ['card'], 'customer' => $customer, 'line_items' => [[ 'price' => $stripePrice, 'quantity' => 1, ]], 'mode' => 'subscription', 'success_url' => Routes::getAddress() . 'member/payment/complete?session_id={CHECKOUT_SESSION_ID}', 'cancel_url' => Routes::getAddress() . 'member/payment/cancel', ]); header('Location: ' . $session->url); exit; } public function payment( $type = '' ) { $type = strtolower( $type ); if ( ! in_array( $type, ['cancel','complete'] ) ) { Session::flash( 'error', 'Unknown Payment' ); return Redirect::to( 'home/index' ); } if ( $type == 'cancel' ) { self::$title = '(almost) Members Area'; return Views::view( 'members.paymentcanceled' ); } self::$title = '(almost) Members Area'; Views::view( 'members.paymentcomplete' ); } // This combines a registration with a checkout public function signup( $plan = 'monthly' ) { $plan = strtolower( $plan ); if ( ! in_array( $plan, ['monthly','yearly'] ) ) { Session::flash( 'error', 'Unknown plan' ); return Redirect::to( 'home/index' ); } $product = self::$products->mainProduct(); if ( empty( $product ) ) { Session::flash( 'error', 'Unknown product' ); return Redirect::to( 'home/index' ); } $stripePrice = $this->findPrice( $plan ); $pretty = 'prettyPrice' . ucfirst( $plan ); $prettyPrice = $product->$pretty; self::$title = 'Sign up for {SITENAME} ' . ucfirst( $plan ); Components::set( 'planName', ucfirst( $plan ) ); Components::set( 'prettyPrice', $prettyPrice ); Components::set( 'TERMS', Views::simpleView( 'terms' ) ); if ( App::$isLoggedIn ) { Session::flash( 'notice', 'You are already logged in, you can subscribe here, or upgrade here.' ); return Redirect::to( 'home/index' ); } if ( !Input::exists() ) { return Views::view( 'members.register' ); } if ( ! Forms::check( 'register' ) ) { Issues::add( 'error', [ 'There was an error with your registration.' => Check::userErrors() ] ); return Views::view( 'members.register' ); } self::$user->create( [ 'username' => Input::post( 'username' ), 'password' => Hash::make( Input::post( 'password' ) ), 'email' => Input::post( 'email' ), 'terms' => 1, ] ); if ( !self::$user->logIn( Input::post( 'username' ), Input::post( 'password' ), Input::post( 'remember' ) ) ) { Session::flash( 'error', 'Thank you for registering! Unfortunately, there was an issue logging you in, please log in and order again.' ); return Redirect::to( 'home/index' ); } $user = self::$user->authorize( Input::post( 'username' ), Input::post( 'password' ) ); $customer = self::$customers->findOrCreate( $user->ID ); if ( empty( $customer ) ) { Session::flash( 'error', 'Thank you for registering! Unfortunately, there was an issue communicating with Stripe and we can\'t collect payment right now.' ); return Redirect::to( 'home/index' ); } $session = self::$stripe->checkout->sessions->create([ 'payment_method_types' => ['card'], 'customer' => $customer, 'line_items' => [[ 'price' => $stripePrice, 'quantity' => 1, ]], 'mode' => 'subscription', 'success_url' => Routes::getAddress() . 'member/payment/complete?session_id={CHECKOUT_SESSION_ID}', 'cancel_url' => Routes::getAddress() . 'member/payment/cancel', ]); header('Location: ' . $session->url); exit; } private function findPrice( $plan ) { $plan = strtolower( $plan ); if ( ! in_array( $plan, ['monthly','yearly'] ) ) { Session::flash( 'error', 'Unknown plan' ); return Redirect::to( 'home/index' ); } $product = self::$products->mainProduct(); if ( empty( $product ) ) { Session::flash( 'error', 'Unknown product' ); return Redirect::to( 'home/index' ); } $index = 'stripe_price_' . $plan; $stripePrice = $product->$index; return $stripePrice; } private function confirmAuth() { if ( ! App::$isLoggedIn || ! App::$isMember ) { Session::flash( 'error', 'You do not have permission to access this page.' ); return Redirect::home(); } } }