table('mkbh_subscribers_aggregation')->count(); } /** * Get local stripe customer. * * @param string $email * * @return mixed */ function mkbh_general_stripe_get_local_customer_by_email(string $email) { return database()->table('mkbh_stripe_customers')->where('user_email', '=', $email)->where('environment', '=', MKBH_STRIPE_ENVIRONMENT)->first(); } /** * Get local stripe backer. * * @param string $email * * @return mixed */ function mkbh_general_stripe_get_local_backer_by_email(string $email) { return database()->table('mkbh_stripe_anonymous_backers')->where('user_email', '=', $email)->where('environment', '=', MKBH_STRIPE_ENVIRONMENT)->first(); } /** * Lookup stripe customer id by email. * * @param string $email * * @return mixed */ function mkbh_general_stripe_lookup_customer_id(string $email) { if ($customer = mkbh_general_stripe_get_local_customer_by_email($email)) { return $customer->customer_id; } if ($backer = mkbh_general_stripe_get_local_backer_by_email($email)) { return $backer->customer_id; } return null; } /** * Get stripe customer active subscription. * * @param \Stripe\Customer $customer * * @return \Stripe\Subscription|null */ function mkbh_general_stripe_get_customer_active_subscription(\Stripe\Customer $customer) { $subscriptions = $customer->subscriptions->all(); if (!empty($subscriptions->data)) { foreach ($subscriptions->data as $subscription) { if (in_array($subscription->plan->id, mkbh_general_stripe_plan_ids())) { return $subscription; } } } return null; } /** * Get list of personal stripe plan IDs. * @return array */ function mkbh_general_stripe_personal_plan_ids() { return [ MKBH_DONATE_PERSONAL_BASIS_PLAN_ID, MKBH_DONATE_PERSONAL_BASIS_YEAR_PLAN_ID, MKBH_DONATE_PERSONAL_PLUS_PLAN_ID, MKBH_DONATE_PERSONAL_PLUS_YEAR_PLAN_ID, ]; } /** * Get list of business stripe plan IDs. * * @return array */ function mkbh_general_stripe_business_plan_ids() { return [ MKBH_DONATE_BUSINESS_PER_MONTH_PLAN_ID, MKBH_DONATE_BUSINESS_PER_YEAR_PLAN_ID ]; } /** * Get list of all stripe plan IDs. * * @return array */ function mkbh_general_stripe_plan_ids() { return array_merge( mkbh_general_stripe_personal_plan_ids(), mkbh_general_stripe_business_plan_ids() ); } /** * Get list of manual stripe plan IDs * respecting current stripe environment. * * @param $account * @return \Illuminate\Support\Collection */ function mkbh_general_stripe_manual_plan_ids($account): \Illuminate\Support\Collection { if (!property_exists($account, 'field_manual_membership_plans')) { $account = user_load($account->uid); } return collect($account->field_manual_membership_plans[LANGUAGE_NONE] ?? [])->map(function($fieldValue) { $value = data_get($fieldValue, 'value'); if(MKBH_STRIPE_ENVIRONMENT !== 'live') { switch ($value) { case MKBH_DONATE_PERSONAL_BASIS_LIVE_PLAN_ID: return MKBH_DONATE_PERSONAL_BASIS_SANDBOX_PLAN_ID; case MKBH_DONATE_PERSONAL_PLUS_LIVE_PLAN_ID: return MKBH_DONATE_PERSONAL_PLUS_SANDBOX_PLAN_ID; case MKBH_DONATE_BUSINESS_PER_MONTH_LIVE_PLAN_ID: return MKBH_DONATE_BUSINESS_PER_MONTH_SANDBOX_PLAN_ID; case MKBH_DONATE_BUSINESS_PER_YEAR_LIVE_PLAN_ID: return MKBH_DONATE_BUSINESS_PER_YEAR_SANDBOX_PLAN_ID; default: throw new RuntimeException('Unrecognized manual stripe plan detected!'); } } return $value; }); } /** * Create local stripe account. * * @param \Stripe\Customer $customer * @param $account */ function mkbh_general_stripe_create_local_customer(\Stripe\Customer $customer, $account) { if ($account && property_exists($account, 'uid')) { database()->table('mkbh_stripe_customers')->updateOrInsert( [ 'customer_id' => $customer['id'], ], [ 'user_id' => $account->uid, 'customer_id' => $customer['id'], 'user_email' => $customer['email'], 'environment' => MKBH_STRIPE_ENVIRONMENT, 'created_at' => REQUEST_TIME, 'updated_at' => REQUEST_TIME, ] ); } } /** * Create local stripe subscription. * * @param \Stripe\Customer $customer * @param \Stripe\Subscription $subscription * @param $account */ function mkbh_general_stripe_create_local_subscription(\Stripe\Customer $customer, Stripe\Subscription $subscription, $account) { if ($account && property_exists($account, 'uid')) { database()->table('mkbh_stripe_subscriptions')->updateOrInsert( [ 'customer_id' => $customer['id'], ], [ 'user_id' => $account->uid, 'customer_id' => $customer['id'], 'subscription_id' => $subscription->id, 'plan_id' => $subscription->plan->id, 'plan_name' => $subscription->plan->nickname, 'frequency' => $subscription->plan->interval, 'quantity' => (int)$subscription->quantity, 'created_at' => REQUEST_TIME, 'updated_at' => REQUEST_TIME, ] ); } } /** * Create local business employee stripe subscription. * * @param \Stripe\Customer $customer * @param \Stripe\Subscription $subscription * @param $account */ function mkbh_general_stripe_create_local_business_employee_subscription(\Stripe\Customer $customer, Stripe\Subscription $subscription, $account) { if ($account && property_exists($account, 'uid')) { database()->table('mkbh_stripe_subscriptions')->updateOrInsert( [ 'user_id' => $account->uid, ], [ 'user_id' => $account->uid, 'customer_id' => $customer['id'], 'subscription_id' => $subscription->id, 'plan_id' => $subscription->plan->id, 'plan_name' => $subscription->plan->nickname, 'frequency' => (int)$subscription->plan->interval, 'quantity' => (int)$subscription->quantity, 'created_at' => REQUEST_TIME, 'updated_at' => REQUEST_TIME, ] ); } } /** * Delete local stripe subscription for a user. * * @param $account */ function mkbh_general_stripe_delete_local_subscription($account) { if ($account && property_exists($account, 'uid')) { database()->table('mkbh_stripe_subscriptions')->where('user_id', '=', $account->uid)->delete(); } } /** * Create local stripe account and subscription. * * @param \Stripe\Customer $customer * @param \Stripe\Subscription $subscription * @param $account */ function mkbh_general_stripe_create_local_customer_and_subscription(\Stripe\Customer $customer, Stripe\Subscription $subscription, $account) { mkbh_general_stripe_create_local_customer($customer, $account); mkbh_general_stripe_create_local_subscription($customer, $subscription, $account); } /** * Create stripe customer and link to local customer and subscription. * * @param string $email * @param string $source * @param string|null $plan * * @return \Stripe\Customer */ function mkbh_general_stripe_create_customer(string $email, string $source, string $plan = null) { $attributes = [ 'email' => $email, 'source' => $source, ]; if (trim($plan) !== '') { $attributes['plan'] = trim($plan); } $stripeCustomer = Stripe\Customer::create($attributes); $drupalAccount = user_load_by_mail($email); mkbh_general_stripe_create_local_customer($stripeCustomer, $drupalAccount); $activeSubscription = mkbh_general_stripe_get_customer_active_subscription($stripeCustomer); if ($activeSubscription instanceof Stripe\Subscription) { mkbh_general_stripe_create_local_subscription($stripeCustomer, $activeSubscription, $drupalAccount); } return $stripeCustomer; } /** * Function to generate html of a stripe checkout button. * * @param string $url * @param null|string $button * @param null|string $popup_title * @param string $subtitle * @param null|string $popup_button * @param array $classes * @param string $mode * @param $plan_field_collection_item_id * * @param bool $showUnitsSelector * * @return string * @throws \Exception */ function mkbh_general_stripe_generate_button($url, $button = null, $popup_title = null, $subtitle = null, $popup_button = null, $classes = [], $mode = 'plan', $planName = null, $plan_field_collection_item_id = null, $showUnitsSelector = false) { global $user; drupal_add_js(['mkbh_stripe' => ['uid' => $user->uid]], 'setting'); drupal_add_js( drupal_get_path('module', 'mkbh_donate_page') . '/assets/javascript/donate-page-manual-donate.js' ); if (empty(MKBH_STRIPE_LIVE_PK_KEY) && empty(MKBH_STRIPE_TEST_SK_KEY)) { watchdog('mkbh_general', 'Stripe publishable key is not set', [], WATCHDOG_ERROR); throw new Exception('Stripe publishable key is not set'); } if ($mode === 'plan' && in_array($planName, ['basis', 'plus', MKBH_DONATE_PERSONAL_BASIS_PLAN_ID, MKBH_DONATE_PERSONAL_PLUS_PLAN_ID]) && drupal_match_path(current_path(), 'node/' . MKBH_DONATE_PERSONAL_NID)) { return l('Ja tak', '/medlem/kassen', [ 'attributes' => [ 'class' => [ 'mkbh-stripe-button' ], ], 'query' => [ 'plan' => $planName ] ]); } if (!$button) { $button = t('Ja tak'); } if (!$popup_title) { $popup_title = t('Checkout'); } if (!$popup_button) { $popup_button = t('Proceed with payment'); } $classes = array_merge($classes, ['mkbh-stripe-button']); $form['script'] = [ '#theme' => 'mkbh_general_stripe_button', '#button_classes' => $classes, '#url' => $url, '#button' => $button, '#key' => MKBH_STRIPE_IS_LIVE ? MKBH_STRIPE_LIVE_PK_KEY : MKBH_STRIPE_TEST_PK_KEY, '#title' => $popup_title, '#subtitle' => $subtitle, '#popup_button' => $popup_button, '#mode' => $mode, '#plan_name' => trim($planName), '#plan_field_collection_item_id' => $plan_field_collection_item_id, '#show_units_selector' => $showUnitsSelector, ]; drupal_add_js('https://js.stripe.com/v3', 'external'); return render($form); } /** * Handle Stripe Webhook POST */ function mkbh_general_stripe_webhooks_handler() { $responder = new \Drupal\mkbh_general\Stripe\Webhooks\Responder\StripeWebhookResponder( @file_get_contents("php://input") ); $responder->respond(); } /** * Handle Stripe Webhook Log View */ function mkbh_general_stripe_webhook_log_handler($logKey) { if (trim($logKey) === '' || !is_numeric($logKey)) { drupal_access_denied(); } $log = database()->table('mkbh_stripe_webhook_logs')->where('id', '=', (int)$logKey)->first(); if (is_null($log)) { drupal_not_found(); } $log->logs = unserialize($log->logs); if (!is_array($log->logs)) { unset($log->logs); } $build = [ '#theme' => 'mkbh_general_stripe_webhook_log_view', '#log' => $log ]; return drupal_render($build); } /** * Get business master sub (employee) accounts. * * @param $masterAccount * @return \Illuminate\Support\Collection */ function mkbh_general_stripe_business_get_sub_accounts($masterAccount) { $query = database()->table('mkbh_business_sub_accounts')->where('master_uid', '=', $masterAccount->uid); $accounts = $query->pluck('sub_uid')->map(function ($uid) { return user_load($uid); }); return $accounts->filter()->unique('uid')->keyBy('mail'); } function mkbh_general_stripe_business_get_master_takes_seat($masterAccount) { $query = database()->table('mkbh_business_info')->where('master_uid', '=', $masterAccount->uid); $businessInfo = $query->first(); if (!$businessInfo) { return false; } return (bool)data_get($businessInfo, 'master_takes_seat', false); } /** * Link business sub-account. * * @param $masterAccount * @param $subAccount */ function mkbh_general_stripe_business_link_sub_account($masterAccount, $subAccount) { database()->table('mkbh_business_sub_accounts')->updateOrInsert( [ 'master_uid' => $masterAccount->uid, 'sub_uid' => $subAccount->uid, ], [ 'master_uid' => $masterAccount->uid, 'sub_uid' => $subAccount->uid, ] ); mkbh_general_stripe_business_assign_roles($masterAccount, 'add', $subAccount, 'add'); } /** * Unlink business sub-account. * * @param $masterAccount * @param $subAccount */ function mkbh_general_stripe_business_unlink_sub_account($masterAccount, $subAccount) { database()->table('mkbh_business_sub_accounts') ->where('master_uid', '=', $masterAccount->uid) ->where('sub_uid', '=', $subAccount->uid) ->delete(); mkbh_general_stripe_business_assign_roles($masterAccount, 'remove', $subAccount, 'remove'); } /** * Manage business and employee role assignment. * * @param $masterAccount * @param string $masterOp * @param $employeeAccount * @param string $employeeOp */ function mkbh_general_stripe_business_assign_roles($masterAccount, $masterOp = 'add', $employeeAccount = null, $employeeOp = 'add') { $roleNames = [ MKBH_DONATE_BUSINESS_MASTER_ROLE_NAME, MKBH_DONATE_BUSINESS_EMPLOYEE_ROLE_NAME ]; foreach ($roleNames as $roleName) { $existingRole = user_role_load_by_name($roleName); if (!$existingRole) { user_role_save((object)[ 'name' => $roleName, ]); } } if (!in_array($masterOp, ['add', 'remove']) || !in_array($employeeOp, [null, 'add', 'remove'])) { throw new \InvalidArgumentException('Wrong role operation given!'); } $existingMasterRole = user_role_load_by_name(MKBH_DONATE_BUSINESS_MASTER_ROLE_NAME); $existingEmployeeRole = user_role_load_by_name(MKBH_DONATE_BUSINESS_EMPLOYEE_ROLE_NAME); user_multiple_role_edit([$masterAccount->uid], "{$masterOp}_role", $existingMasterRole->rid); if ($employeeAccount && $employeeOp) { user_multiple_role_edit([$employeeAccount->uid], "{$employeeOp}_role", $existingEmployeeRole->rid); } } /** * @param $email * @return mixed|null */ function mkbh_general_stripe_business_get_business_plan_id_by_email($email) { if ($account = user_load_by_mail($email)) { $businessAccountQuery = database()->table('mkbh_business_sub_accounts') ->where('master_uid', '=', $account->uid) ->orWhere('sub_uid', '=', $account->uid); if($businessAccount = $businessAccountQuery->first()) { $businessInfo = database()->table('mkbh_business_info') ->where('master_uid', '=', $businessAccount->master_uid) ->first(); // of user is master without access, return no subscriptions if ($businessAccount->master_uid === $account->uid && ((bool)$businessInfo->master_takes_seat) === false) { return null; } $subscription = database()->table('mkbh_stripe_subscriptions')->where('user_id', '=', (int)$businessAccount->master_uid)->first(); if ($subscription !== null) { return $subscription->plan_id; } $manualPlans = mkbh_general_stripe_manual_plan_ids( user_load($businessAccount->master_uid) ); if ($manualPlans->isNotEmpty()) { return $manualPlans->first(); } return null; } return null; } return null; }