/** * Clear a payment profile * * @param array $subscription * @param array $paymentProfile * @throws Exception */ public function cancelPaymentProfile(array $subscription, array $paymentProfile) { $subService = SubscriptionsService::instance(); $orderService = OrdersService::instance(); // PPService $paypalService = new PayPalAPIInterfaceServiceService(); $getRPPDetailsReqest = new GetRecurringPaymentsProfileDetailsRequestType(); $getRPPDetailsReqest->ProfileID = $paymentProfile['paymentProfileId']; $getRPPDetailsReq = new GetRecurringPaymentsProfileDetailsReq(); $getRPPDetailsReq->GetRecurringPaymentsProfileDetailsRequest = $getRPPDetailsReqest; $getRPPDetailsResponse = $paypalService->GetRecurringPaymentsProfileDetails($getRPPDetailsReq); if (empty($getRPPDetailsResponse) || $getRPPDetailsResponse->Ack != 'Success') { throw new Exception('Error retrieving payment profile status'); } $profileStatus = $getRPPDetailsResponse->GetRecurringPaymentsProfileDetailsResponseDetails->ProfileStatus; // Active profile, send off the cancel if (strcasecmp($profileStatus, PaymentProfileStatus::ACTIVEPROFILE) === 0 || strcasecmp($profileStatus, PaymentProfileStatus::CANCELLEDPROFILE) === 0) { if (strcasecmp($profileStatus, PaymentProfileStatus::ACTIVEPROFILE) === 0) { // Do we have a payment profile, we need to cancel it with paypal $manageRPPStatusReqestDetails = new ManageRecurringPaymentsProfileStatusRequestDetailsType(); $manageRPPStatusReqestDetails->Action = 'Cancel'; $manageRPPStatusReqestDetails->ProfileID = $paymentProfile['paymentProfileId']; $manageRPPStatusReqest = new ManageRecurringPaymentsProfileStatusRequestType(); $manageRPPStatusReqest->ManageRecurringPaymentsProfileStatusRequestDetails = $manageRPPStatusReqestDetails; $manageRPPStatusReq = new ManageRecurringPaymentsProfileStatusReq(); $manageRPPStatusReq->ManageRecurringPaymentsProfileStatusRequest = $manageRPPStatusReqest; $manageRPPStatusResponse = $paypalService->ManageRecurringPaymentsProfileStatus($manageRPPStatusReq); if (!isset($manageRPPStatusResponse) || $manageRPPStatusResponse->Ack != 'Success') { throw new Exception($manageRPPStatusResponse->Errors[0]->LongMessage); } } $orderService->updatePaymentProfileState($paymentProfile['profileId'], PaymentProfileStatus::CANCELLEDPROFILE); } }
/** * @param array $params * @throws Exception */ public function authenticate(array $params) { if (!isset($params['authtoken']) || empty($params['authtoken'])) { return new Response(Http::STATUS_FORBIDDEN, 'Invalid or empty authToken'); } $authToken = ApiAuthenticationService::instance()->getAuthToken($params['authtoken']); if (empty($authToken)) { return new Response(Http::STATUS_FORBIDDEN, 'Auth token not found'); } $user = UserService::instance()->getUserById($authToken['userId']); if (empty($user)) { return new Response(Http::STATUS_FORBIDDEN, 'User not found'); } $credentials = new SessionCredentials($user); $credentials->setAuthProvider('API'); $credentials->addRoles(UserRole::USER); $credentials->addFeatures(UserFeaturesService::instance()->getUserFeatures($authToken['userId'])); $credentials->addRoles(UserService::instance()->getUserRolesByUserId($authToken['userId'])); $subscription = SubscriptionsService::instance()->getUserActiveSubscription($authToken['userId']); if (!empty($subscription)) { $credentials->addRoles(UserRole::SUBSCRIBER); $credentials->addFeatures(UserFeature::SUBSCRIBER); if ($subscription['subscriptionTier'] == 2) { $credentials->addFeatures(UserFeature::SUBSCRIBERT2); } if ($subscription['subscriptionTier'] == 3) { $credentials->addFeatures(UserFeature::SUBSCRIBERT3); } } $response = new Response(Http::STATUS_OK, json_encode($credentials->getData())); $response->addHeader(Http::HEADER_CONTENTTYPE, MimeType::JSON); return $response; }
public function execute() { $log = Application::instance()->getLogger(); $authenticationService = AuthenticationService::instance(); $subscriptionService = SubscriptionsService::instance(); $users = array(); // Renew any subscription that has an active payment profile. $subscriptions = $subscriptionService->getRecurringSubscriptionsToRenew(); foreach ($subscriptions as $subscription) { try { $subType = $subscriptionService->getSubscriptionType($subscription['subscriptionType']); // Because subscriptions can be revived after months of skipped payments; // The end date may not simply be behind by the subscription frequency. $end = Date::getDateTime($subscription['endDate']); $diff = $end->diff(new \DateTime('NOW')); $end->modify('+' . (intval($diff->format('%y') * 12) + intval($diff->format('%m'))) . ' month'); // $end->modify('+' . $subType['billingFrequency'] . ' ' . strtolower($subType['billingPeriod'])); $subscriptionService->updateSubscription(array('subscriptionId' => $subscription['subscriptionId'], 'endDate' => $end->format('Y-m-d H:i:s'), 'status' => SubscriptionStatus::ACTIVE)); $this->sendResubscribeBroadcast($subscription); $users[] = $subscription['userId']; } catch (\Exception $e) { $log->critical("Could not roll over subscription", $subscription); } } // Expire subscriptions $subscriptions = $subscriptionService->getSubscriptionsToExpire(); if (!empty($subscriptions)) { foreach ($subscriptions as $subscription) { $users[] = $subscription['userId']; $subscriptionService->updateSubscription(array('subscriptionId' => $subscription['subscriptionId'], 'status' => SubscriptionStatus::EXPIRED)); } } // Update users $users = array_unique($users); foreach ($users as $id) { $authenticationService->flagUserForUpdate($id); } // Clean-up old unfinished subscriptions (where users have aborted the process) $conn = Application::instance()->getConnection(); $stmt = $conn->prepare(' DELETE FROM `dfl_users_subscriptions` WHERE `status` = :status AND `createdDate` < (NOW() - INTERVAL 24 HOUR) '); $stmt->bindValue('status', SubscriptionStatus::_NEW, \PDO::PARAM_STR); $stmt->execute(); }
/** * @Route ("/profile") * @HttpMethod ({"GET"}) * @Secure ({"USER"}) * * @param ViewModel $model * @return string */ public function profile(ViewModel $model) { $userService = UserService::instance(); $subscriptionsService = SubscriptionsService::instance(); $userId = Session::getCredentials()->getUserId(); $address = $userService->getAddressByUserId($userId); if (empty($address)) { $address = array(); $address['fullName'] = ''; $address['line1'] = ''; $address['line2'] = ''; $address['city'] = ''; $address['region'] = ''; $address['zip'] = ''; $address['country'] = ''; } if (Session::get('modelSuccess')) { $model->success = Session::get('modelSuccess'); Session::set('modelSuccess'); } if (Session::get('modelError')) { $model->error = Session::get('modelError'); Session::set('modelError'); } $model->title = 'Profile'; $model->user = $userService->getUserById($userId); $subscriptions = $subscriptionsService->getUserActiveAndPendingSubscriptions($userId); for ($i = 0; $i < count($subscriptions); $i++) { $subscriptions[$i]['type'] = $subscriptionsService->getSubscriptionType($subscriptions[$i]['subscriptionType']); } $gifts = $subscriptionsService->getSubscriptionsByGifterIdAndStatus($userId, SubscriptionStatus::ACTIVE); for ($i = 0; $i < count($gifts); $i++) { $gifts[$i]['type'] = $subscriptionsService->getSubscriptionType($gifts[$i]['subscriptionType']); } $model->gifts = $gifts; $model->subscriptions = $subscriptions; $model->address = $address; $model->title = 'Account'; return 'profile'; }
/** * @Route ("/gift/check") * @Secure ({"USER"}) * * @param array $params * @return Response */ public function giftCheckUser(array $params) { FilterParams::required($params, 's'); $userService = UserService::instance(); $subscriptionService = SubscriptionsService::instance(); $userId = Session::getCredentials()->getUserId(); $data = array('valid' => false, 'cangift' => false, 'username' => $params['s']); $user = $userService->getUserByUsername($params['s']); if (!empty($user)) { $data['cangift'] = $subscriptionService->getCanUserReceiveGift($userId, $user['userId']); $data['valid'] = true; } $response = new Response(Http::STATUS_OK); $response->addHeader(Http::HEADER_CONTENTTYPE, MimeType::JSON); $response->setBody(json_encode($data)); return $response; }
/** * @Route ("/admin/user/{id}/subscription/{subscriptionId}/save") * @Route ("/admin/user/{id}/subscription/save") * @Secure ({"ADMIN"}) * @HttpMethod ({"POST"}) * * @param array $params * @param ViewModel $model * @throws Exception * @return string */ public function subscriptionSave(array $params, ViewModel $model) { FilterParams::required($params, 'subscriptionType'); FilterParams::required($params, 'status'); FilterParams::required($params, 'createdDate'); FilterParams::required($params, 'endDate'); $subscriptionsService = SubscriptionsService::instance(); $subscriptionType = $subscriptionsService->getSubscriptionType($params['subscriptionType']); $subscription = array(); $subscription['subscriptionType'] = $subscriptionType['id']; $subscription['subscriptionTier'] = $subscriptionType['tier']; $subscription['status'] = $params['status']; $subscription['createdDate'] = $params['createdDate']; $subscription['endDate'] = $params['endDate']; $subscription['userId'] = $params['id']; $subscription['subscriptionSource'] = isset($params['subscriptionSource']) && !empty($params['subscriptionSource']) ? $params['subscriptionSource'] : Config::$a['subscriptionType']; if (isset($params['subscriptionId']) && !empty($params['subscriptionId'])) { $subscription['subscriptionId'] = $params['subscriptionId']; $subscriptionId = $subscription['subscriptionId']; $subscriptionsService->updateSubscription($subscription); Session::set('modelSuccess', 'Subscription updated!'); } else { $subscriptionId = $subscriptionsService->addSubscription($subscription); Session::set('modelSuccess', 'Subscription created!'); } $authService = AuthenticationService::instance(); $authService->flagUserForUpdate($params['id']); return 'redirect: /admin/user/' . urlencode($params['id']) . '/subscription/' . urlencode($subscriptionId) . '/edit'; }
/** * @Route ("/admin/subscribers") * @Secure ({"ADMIN"}) * * @param ViewModel $model * @return string */ public function adminSubscribers(ViewModel $model) { $subService = SubscriptionsService::instance(); $model->subscribersT4 = $subService->getSubscriptionsByTier(4); $model->subscribersT3 = $subService->getSubscriptionsByTier(3); $model->subscribersT2 = $subService->getSubscriptionsByTier(2); $model->subscribersT1 = $subService->getSubscriptionsByTier(1); $model->title = 'Subscribers'; return 'admin/subscribers'; }
public function execute(LoggerInterface $log) { RememberMeService::instance()->clearExpiredRememberMe(); $expiredSubscriptionCount = SubscriptionsService::instance()->expiredSubscriptions(); $log->debug(sprintf('Expired (%s)', $expiredSubscriptionCount)); }
/** * @param array $user * @param string $authProvider * @return SessionCredentials */ public function getUserCredentials(array $user, $authProvider) { $credentials = new SessionCredentials($user); $credentials->setAuthProvider($authProvider); $credentials->addRoles(UserRole::USER); $credentials->addFeatures(UserFeaturesService::instance()->getUserFeatures($user['userId'])); $credentials->addRoles(UserService::instance()->getUserRolesByUserId($user['userId'])); $subscription = SubscriptionsService::instance()->getUserActiveSubscription($user['userId']); if (!empty($subscription) or $user['istwitchsubscriber']) { $credentials->addRoles(UserRole::SUBSCRIBER); $credentials->addFeatures(UserFeature::SUBSCRIBER); if ($user['istwitchsubscriber']) { $credentials->addFeatures(UserFeature::SUBSCRIBERT0); } } if (!empty($subscription)) { if ($subscription['subscriptionTier'] == 2) { $credentials->addFeatures(UserFeature::SUBSCRIBERT2); } if ($subscription['subscriptionTier'] == 3) { $credentials->addFeatures(UserFeature::SUBSCRIBERT3); } if ($subscription['subscriptionTier'] == 4) { $credentials->addFeatures(UserFeature::SUBSCRIBERT4); } } return $credentials; }
/** * Handles the IPN message * * @param PPIPNMessage $ipnMessage */ protected function handleIPNTransaction($txnId, $txnType, array $data) { $log = Application::instance()->getLogger(); $orderService = OrdersService::instance(); $subService = SubscriptionsService::instance(); $authService = AuthenticationService::instance(); switch (strtolower($txnType)) { // Post back from checkout, make sure the payment lines up // This is sent when a express checkout has been performed by a user case 'express_checkout': $payment = $orderService->getPaymentByTransactionId($txnId); if (!empty($payment)) { // Make sure the payment values are the same if (number_format($payment['amount'], 2) != number_format($data['mc_gross'], 2)) { throw new Exception('Amount for payment do not match'); } // Update the payment status $orderService->updatePaymentStatus($payment['paymentId'], $data['payment_status']); $log->notice(sprintf('Updated payment status %s status %s', $data['txn_id'], $data['payment_status'])); // If the payment status WAS PENDING, and the IPN payment status is COMPLETED // Then we need to activate the attached subscription and complete the order // This is for the ECHECK payment method if (strcasecmp($payment['paymentStatus'], PaymentStatus::PENDING) === 0 && strcasecmp($data['payment_status'], PaymentStatus::COMPLETED) === 0) { $order = $orderService->getOrderByPaymentId($payment['paymentId']); if (!empty($order)) { $orderService->updateOrderState($order['orderId'], OrderStatus::COMPLETED); $log->debug(sprintf('Updated order status %s status %s', $order['orderId'], OrderStatus::COMPLETED)); $subscription = $subService->getUserPendingSubscription($order['userId']); if (!empty($subscription)) { $subService->updateSubscriptionState($subscription['subscriptionId'], SubscriptionStatus::ACTIVE); $log->notice(sprintf('Updated subscription status %s status %s', $order['orderId'], SubscriptionStatus::ACTIVE)); $authService->flagUserForUpdate($subscription['userId']); } } } } else { $log->info(sprintf('Express checkout IPN called, but no payment found [%s]', $txnId)); } break; // Recurring payment, renew subscriptions, or set to pending depending on the type // This is sent from paypal when a recurring payment is billed // Recurring payment, renew subscriptions, or set to pending depending on the type // This is sent from paypal when a recurring payment is billed case 'recurring_payment': if (!isset($data['payment_status'])) { throw new Exception('Invalid payment status'); } if (!isset($data['next_payment_date'])) { throw new Exception('Invalid next_payment_date'); } $paymentProfile = $this->getPaymentProfile($data); // We dont care about what state the sub is in.... $subscription = $subService->getSubscriptionByOrderId($paymentProfile['orderId']); if (empty($subscription)) { $log->critical('Invalid recurring_payment', $data); throw new Exception('Invalid subscription for recurring payment'); } if ($subscription['userId'] != $paymentProfile['userId'] && $subscription['gifter'] != $paymentProfile['userId']) { throw new Exception(sprintf('Invalid subscription for user %s', $subscription['userId'])); } $nextPaymentDate = Date::getDateTime($data['next_payment_date']); $orderService->updatePaymentProfileNextPayment($paymentProfile['profileId'], $nextPaymentDate); // Update the subscription end date regardless if the payment was successful or not // We dont actually know if paypal moves the automatic payment forward if one fails and is then manually processed $end = Date::getDateTime($subscription['endDate']); $end->modify('+' . $paymentProfile['billingFrequency'] . ' ' . strtolower($paymentProfile['billingPeriod'])); // Update subscription end-date $subService->updateSubscriptionDateEnd($subscription['subscriptionId'], $end); $log->debug(sprintf('Update Subscription end date %s [%s]', $subscription['subscriptionId'], $end->format(Date::FORMAT))); // Change the subscription state depending on the payment state if (strcasecmp($data['payment_status'], PaymentStatus::PENDING) === 0) { $subService->updateSubscriptionState($subscription['subscriptionId'], SubscriptionStatus::PENDING); $log->debug(sprintf('Updated subscription state %s status %s', $subscription['subscriptionId'], SubscriptionStatus::PENDING)); } else { if (strcasecmp($data['payment_status'], PaymentStatus::COMPLETED) === 0) { $subService->updateSubscriptionState($subscription['subscriptionId'], SubscriptionStatus::ACTIVE); $log->debug(sprintf('Updated subscription %s status %s', $subscription['subscriptionId'], SubscriptionStatus::ACTIVE)); } else { $log->notice(sprintf('Subscription status %s not changed for payment profile %s', $subscription['subscriptionId'], $paymentProfile['profileId'])); } } // Add a payment to the order $payment = array(); $payment['orderId'] = $paymentProfile['orderId']; $payment['payerId'] = $data['payer_id']; $payment['amount'] = $data['mc_gross']; $payment['currency'] = $data['mc_currency']; $payment['transactionId'] = $txnId; $payment['transactionType'] = $txnType; $payment['paymentType'] = $data['payment_type']; $payment['paymentStatus'] = $data['payment_status']; $payment['paymentDate'] = Date::getDateTime($data['payment_date'])->format('Y-m-d H:i:s'); $orderService->addOrderPayment($payment); $log->notice(sprintf('Added order payment %s status %s', $data['recurring_payment_id'], $data['profile_status'])); $authService->flagUserForUpdate($subscription['userId']); break; // Sent if user cancels subscription from Paypal's site. // Sent if user cancels subscription from Paypal's site. case 'recurring_payment_profile_cancel': $paymentProfile = $this->getPaymentProfile($data); $orderService->updatePaymentProfileState($paymentProfile['profileId'], $data['profile_status']); $log->debug(sprintf('Payment profile cancelled %s status %s', $data['recurring_payment_id'], $data['profile_status'])); break; // sent on first postback when the user subscribes // sent on first postback when the user subscribes case 'recurring_payment_profile_created': $paymentProfile = $this->getPaymentProfile($data); if (strcasecmp($data['profile_status'], 'Active') === 0) { $data['profile_status'] = 'ActiveProfile'; } $orderService->updatePaymentProfileState($paymentProfile['profileId'], $data['profile_status']); $log->debug(sprintf('Updated payment profile %s status %s', $data['recurring_payment_id'], $data['profile_status'])); break; } }
/** * @param array $data * @return array|null * @throws Exception */ protected function getSubscriptionByPaymentProfileData(array $data) { $subscription = null; if (isset($data['recurring_payment_id']) && !empty($data['recurring_payment_id'])) { $subscriptionService = SubscriptionsService::instance(); $subscription = $subscriptionService->getSubscriptionByPaymentProfileId($data['recurring_payment_id']); } if (empty($subscription)) { $log = Application::instance()->getLogger(); $log->critical('Could not load subscription using IPN', $data); throw new Exception('Could not load subscription by payment data'); } return $subscription; }
/** * @Route ("/profile/authentication") * @Secure ({"USER"}) * * @param array $params * @param ViewModel $model * @return string */ public function profileAuthentication(array $params, ViewModel $model) { $userService = UserService::instance(); $subscriptionsService = SubscriptionsService::instance(); $userId = Session::getCredentials()->getUserId(); $model->title = 'Authentication'; $model->user = $userService->getUserById($userId); // Build a list of profile types for UI purposes $authProfiles = $userService->getAuthProfilesByUserId($userId); $authProfileTypes = array(); if (!empty($authProfiles)) { foreach ($authProfiles as $profile) { $authProfileTypes[] = $profile['authProvider']; } $model->authProfiles = $authProfiles; } $model->authProfileTypes = $authProfileTypes; $model->authTokens = ApiAuthenticationService::instance()->getAuthTokensByUserId($userId); $model->title = 'Authentication'; return 'profile/authentication'; }
/** * @Route ("/auth/minecraft") * @HttpMethod ({"POST"}) * * @param array $params * @return Response * @throws Exception */ public function authMinecraftPOST(array $params) { if (!$this->checkPrivateKey($params)) { return new Response(Http::STATUS_BAD_REQUEST, 'privatekey'); } if (empty($params['uuid']) || strlen($params['uuid']) > 36) { return new Response(Http::STATUS_BAD_REQUEST, 'uuid'); } if (!preg_match('/^[a-f0-9-]{32,36}$/', $params['uuid'])) { return new Response(Http::STATUS_BAD_REQUEST, 'uuid'); } if (empty($params['name']) || mb_strlen($params['name']) > 16) { return new Response(Http::STATUS_BAD_REQUEST, 'name'); } $user = UserService::instance(); $userid = $user->getUserIdFromMinecraftName($params['name']); if (!$userid) { return new Response(Http::STATUS_NOT_FOUND, 'nameNotFound'); } $ban = $user->getUserActiveBan($userid, @$params['ipaddress']); if (!empty($ban)) { return new Response(Http::STATUS_FORBIDDEN, 'userBanned'); } $sub = SubscriptionsService::instance()->getUserActiveSubscription($userid); $userRow = $user->getUserById($userid); if (empty($userRow)) { return new Response(Http::STATUS_NOT_FOUND, 'userNotFound'); } if (empty($sub)) { if ($userRow['istwitchsubscriber']) { $sub = array('endDate' => date('Y-m-d H:i:s', strtotime('+1 hour'))); } else { return new Response(Http::STATUS_FORBIDDEN, 'subscriptionNotFound'); } } try { $success = $user->setMinecraftUUID($userid, $params['uuid']); if (!$success) { $existingUserId = $user->getUserIdFromMinecraftUUID($params['uuid']); // only fail if the already set uuid is not the same if (!$existingUserId or $existingUserId != $userid) { return new Response(Http::STATUS_FORBIDDEN, 'uuidAlreadySet'); } } } catch (\Doctrine\DBAL\DBALException $e) { return new Response(Http::STATUS_BAD_REQUEST, 'duplicateUUID'); } $response = array('nick' => $userRow['username'], 'end' => strtotime($sub['endDate']) * 1000); $response = new Response(Http::STATUS_OK, json_encode($response)); $response->addHeader(Http::HEADER_CONTENTTYPE, MimeType::JSON); return $response; }