/**
  * Handle the event.
  *
  * @param UnknownPayPalPaymentReceived $event
  */
 public function handle(UnknownPayPalPaymentReceived $event)
 {
     $email = $event->emailAddress;
     $payment = $this->paymentRepository->getById($event->paymentId);
     $this->mailer->send('emails.paypal-donation', ['email' => $email, 'payment' => $payment], function ($m) use($email) {
         $m->to($email);
         $m->cc('*****@*****.**');
         $m->subject('Unknown PayPal Payment Received');
     });
 }
 /**
  * Start the creation of a new gocardless payment
  *   Details get posted into this method and the redirected to gocardless
  * @param $userId
  * @throws \BB\Exceptions\AuthenticationException
  * @throws \BB\Exceptions\FormValidationException
  * @throws \BB\Exceptions\NotImplementedException
  */
 public function store($userId)
 {
     User::findWithPermission($userId);
     $requestData = \Request::only(['reason', 'amount', 'return_path', 'stripeToken', 'ref']);
     $stripeToken = $requestData['stripeToken'];
     $amount = $requestData['amount'];
     $reason = $requestData['reason'];
     $returnPath = $requestData['return_path'];
     $ref = $requestData['ref'];
     try {
         $charge = Stripe_Charge::create(array("amount" => $amount, "currency" => "gbp", "card" => $stripeToken, "description" => $reason));
     } catch (\Exception $e) {
         \Log::error($e);
         if (\Request::wantsJson()) {
             return \Response::json(['error' => 'There was an error confirming your payment'], 400);
         }
         \Notification::error("There was an error confirming your payment");
         return \Redirect::to($returnPath);
     }
     //Replace the amount with the one from the charge, this prevents issues with variable tempering
     $amount = $charge->amount / 100;
     //Stripe don't provide us with the fee so this should be OK
     $fee = $amount * 0.024 + 0.2;
     $this->paymentRepository->recordPayment($reason, $userId, 'stripe', $charge->id, $amount, 'paid', $fee, $ref);
     if (\Request::wantsJson()) {
         return \Response::json(['message' => 'Payment made']);
     }
     \Notification::success("Payment made");
     return \Redirect::to($returnPath);
 }
 public function update($logEntryId)
 {
     $reason = \Request::get('reason');
     if (!in_array($reason, ['training', 'testing'])) {
         throw new \BB\Exceptions\ValidationException("Not a valid reason");
     }
     $equipmentLog = $this->equipmentLogRepository->getById($logEntryId);
     /*
     if ($equipmentLog->user_id == \Auth::user()->id) {
         throw new \BB\Exceptions\ValidationException("You can't update your own record");
     }
     */
     if (!\Auth::user()->hasRole($equipmentLog->device) && !\Auth::user()->isAdmin()) {
         throw new \BB\Exceptions\ValidationException("You don't have permission to alter this record");
     }
     if (!empty($equipmentLog->reason)) {
         throw new \BB\Exceptions\ValidationException("Reason already set");
     }
     $billedStatus = $equipmentLog->billed;
     if ($equipmentLog->billed) {
         //the user has been billed, we need to undo this.
         $payments = $this->paymentRepository->getPaymentsByReference($equipmentLog->id . ':' . $equipmentLog->device);
         if ($payments->count() == 1) {
             $this->paymentRepository->delete($payments->first()->id);
             $billedStatus = false;
         } else {
             throw new \BB\Exceptions\ValidationException("Unable to locate related payment, please contact an admin");
         }
     }
     $this->equipmentLogRepository->update($logEntryId, ['reason' => $reason, 'billed' => $billedStatus]);
     \Notification::success("Record Updated");
     return \Redirect::back();
 }
 /**
  * Start the creation of a new balance payment
  *   Details get posted into this method
  * @param $userId
  * @throws \BB\Exceptions\AuthenticationException
  * @throws \BB\Exceptions\FormValidationException
  * @throws \BB\Exceptions\NotImplementedException
  */
 public function store($userId)
 {
     $user = User::findWithPermission($userId);
     $this->bbCredit->setUserId($user->id);
     $requestData = \Request::only(['reason', 'amount', 'return_path', 'ref']);
     $amount = $requestData['amount'] * 1 / 100;
     $reason = $requestData['reason'];
     $returnPath = $requestData['return_path'];
     $ref = $requestData['ref'];
     //Can the users balance go below 0
     $minimumBalance = $this->bbCredit->acceptableNegativeBalance($reason);
     //What is the users balance
     $userBalance = $this->bbCredit->getBalance();
     //With this payment will the users balance go to low?
     if ($userBalance - $amount < $minimumBalance) {
         if (\Request::wantsJson()) {
             return \Response::json(['error' => 'You don\'t have the money for this'], 400);
         }
         \Notification::error("You don't have the money for this");
         return \Redirect::to($returnPath);
     }
     //Everything looks gooc, create the payment
     $this->paymentRepository->recordPayment($reason, $userId, 'balance', '', $amount, 'paid', 0, $ref);
     //Update the users cached balance
     $this->bbCredit->recalculate();
     if (\Request::wantsJson()) {
         return \Response::json(['message' => 'Payment made']);
     }
     \Notification::success("Payment made");
     return \Redirect::to($returnPath);
 }
 /**
  * Create a charge and immediately bill it through the direct debit process
  *
  * @param integer   $userId
  * @param \DateTime $date
  * @param integer   $amount
  * @param string    $status
  * @param string    $DDAuthId
  * @return SubscriptionCharge
  */
 public function createChargeAndBillDD($userId, $date, $amount, $status, $DDAuthId)
 {
     $charge = $this->createCharge($userId, $date, $amount, $status);
     $bill = $this->goCardless->newBill($DDAuthId, $amount, $this->goCardless->getNameFromReason('subscription'));
     if ($bill) {
         $this->paymentRepository->recordSubscriptionPayment($userId, 'gocardless-variable', $bill->id, $bill->amount, $bill->status, $bill->gocardless_fees, $charge->id);
     }
 }
 public function handle()
 {
     $data = \Request::only(['device', 'tag', 'service']);
     try {
         $keyFob = $this->keyFobAccess->lookupKeyFob($data['tag']);
     } catch (\Exception $e) {
         \Log::debug(json_encode($data));
         return \Response::make('Not found', 404);
     }
     $user = $keyFob->user()->first();
     $this->paymentRepository->recordPayment($data['service'], $user->id, 'balance', null, 0.05, 'paid', 0, $data['device']);
     event(new MemberActivity($keyFob, $data['service']));
     return \Response::make('OK', 201);
 }
 /**
  * @param string $action
  */
 private function processBills($action, array $bills)
 {
     foreach ($bills as $bill) {
         $existingPayment = $this->paymentRepository->getPaymentBySourceId($bill['id']);
         if ($existingPayment) {
             if ($bill['status'] == 'failed' || $bill['status'] == 'cancelled') {
                 //Payment failed or cancelled - either way we don't have the money!
                 //We need to retrieve the payment from the user somehow but don't want to cancel the subscription.
                 //$this->handleFailedCancelledBill($existingPayment);
                 $this->paymentRepository->recordPaymentFailure($existingPayment->id, $bill['status']);
             } elseif ($bill['status'] == 'pending' && $action == 'retried') {
                 //Failed payment is being retried
                 $subCharge = $this->subscriptionChargeRepository->getById($existingPayment->reference);
                 if ($subCharge) {
                     if ($subCharge->amount == $bill['amount']) {
                         $this->subscriptionChargeRepository->markChargeAsProcessing($subCharge->id);
                     } else {
                         //@TODO: Handle partial payments
                         \Log::warning("Sub charge handling - gocardless partial payment");
                     }
                 }
             } elseif ($bill['status'] == 'refunded') {
                 //Payment refunded
                 //Update the payment record and possible the user record
             } elseif ($bill['status'] == 'withdrawn') {
                 //Money taken out - not our concern
             }
         } else {
             \Log::info("GoCardless Webhook received for unknown payment: " . $bill['id']);
         }
     }
 }
 private function updateSubPayment($paymentId, $userId, $status)
 {
     $payment = $this->paymentRepository->getById($paymentId);
     $subCharge = $this->subscriptionChargeRepository->findCharge($userId);
     if (!$subCharge) {
         \Log::warning('Subscription payment without a sub charge. Payment ID:' . $paymentId);
         return;
     }
     //The sub charge record id gets saved onto the payment
     if (empty($payment->reference)) {
         $payment->reference = $subCharge->id;
         $payment->save();
     } else {
         if ($payment->reference != $subCharge->id) {
             throw new PaymentException('Attempting to update sub charge (' . $subCharge->id . ') but payment (' . $payment->id . ') doesn\'t match. Sub charge has an existing reference on it.');
         }
     }
     if ($status == 'paid') {
         $this->subscriptionChargeRepository->markChargeAsPaid($subCharge->id);
     } else {
         if ($status == 'pending') {
             $this->subscriptionChargeRepository->markChargeAsProcessing($subCharge->id);
         }
     }
     //The amount isn't stored on the sub charge record until its paid or processing
     if ($payment->amount != $subCharge->amount) {
         $this->subscriptionChargeRepository->updateAmount($subCharge->id, $payment->amount);
     }
 }
 /**
  * Remove cash from the users balance
  *
  * @param $userId
  * @return mixed
  * @throws \BB\Exceptions\AuthenticationException
  * @throws \BB\Exceptions\InvalidDataException
  */
 public function destroy($userId)
 {
     $user = User::findWithPermission($userId);
     $this->bbCredit->setUserId($userId);
     $amount = \Request::get('amount');
     $returnPath = \Request::get('return_path');
     $ref = \Request::get('ref');
     $minimumBalance = $this->bbCredit->acceptableNegativeBalance('withdrawal');
     if ($user->cash_balance + $minimumBalance * 100 < $amount * 100) {
         \Notification::error("Not enough money");
         return \Redirect::to($returnPath);
     }
     $this->paymentRepository->recordPayment('withdrawal', $userId, 'balance', '', $amount, 'paid', 0, $ref);
     $this->bbCredit->recalculate();
     \Notification::success("Payment recorded");
     return \Redirect::to($returnPath);
 }
 /**
  * Bill members based on the sub charges that are due
  */
 public function billMembers()
 {
     $subCharges = $this->subscriptionChargeRepository->getDue();
     foreach ($subCharges as $charge) {
         if ($charge->user->payment_method == 'gocardless-variable') {
             //Look the the previous attempts - there may be multiple failures
             $existingPayments = $this->paymentRepository->getPaymentsByReference($charge->id);
             if ($existingPayments->count() > 0) {
                 //We will let the user retry the payment if it fails
                 continue;
             }
             $bill = $this->goCardless->newBill($charge->user->subscription_id, $charge->user->monthly_subscription, $this->goCardless->getNameFromReason('subscription'));
             if ($bill) {
                 $this->paymentRepository->recordSubscriptionPayment($charge->user->id, 'gocardless-variable', $bill->id, $bill->amount, $bill->status, $bill->gocardless_fees, $charge->id);
             }
         }
     }
 }
 public function receiveNotification()
 {
     $ipnMessage = new \PayPal\IPN\PPIPNMessage('', PayPalConfig::getConfig());
     if (!$ipnMessage->validate()) {
         \Log::error("Invalid IPN");
     }
     $ipnData = $ipnMessage->getRawData();
     if (isset($ipnData['txn_type']) && $ipnData['txn_type'] == 'subscr_payment') {
         if ($ipnData['payment_status'] != 'Completed') {
             \Log::error("PayPal IPN: Received unknown payment status for sub payment: \"" . $ipnData['payment_status'] . "\" Email: " . $ipnData['payer_email']);
             return;
         }
         $user = User::where('email', $ipnData['payer_email'])->first();
         if (!$user) {
             $user = User::where('secondary_email', $ipnData['payer_email'])->first();
         }
         if (!$user) {
             //\Log::error("PayPal IPN Received for unknown email " . $ipnData['payer_email']);
             $paymentId = $this->paymentRepository->recordPayment('donation', 0, 'paypal', $ipnData['txn_id'], $ipnData['mc_gross'], 'paid', $ipnData['mc_fee'], $ipnData['payer_email']);
             event(new \BB\Events\UnknownPayPalPaymentReceived($paymentId, $ipnData['payer_email']));
             return;
         }
         //It looks like the user might be joining again
         if ($user->status == 'left') {
             $user->rejoin();
         }
         //If its a new user set them up by creating the first sub charge record and setting the payment day
         if ($user->status == 'setting-up') {
             $this->setupNewMember($user, $ipnData['mc_gross']);
         }
         //Record the subscription payment, this will automatically deal with locating the sub charge and updating that
         $this->paymentRepository->recordSubscriptionPayment($user->id, 'paypal', $ipnData['txn_id'], $ipnData['mc_gross'], 'paid', $ipnData['mc_fee']);
     } elseif (isset($ipnData['txn_type']) && $ipnData['txn_type'] == 'subscr_cancel') {
         $user = User::where('email', $ipnData['payer_email'])->first();
         if ($user) {
             //The user may have already changed to another method, only cancel if its still paypal
             if ($user->payment_method == 'paypal') {
                 $user->cancelSubscription();
             }
             //@TODO: Deal with any open sub payment records
         }
     }
 }
 /**
  * This is a basic method for recording a payment transfer between two people
  * This should not exist and the normal balance payment controller should be used
  * If any more work is needed here please take the time and move it over!
  *
  * @param Request $request
  * @param integer $userId
  *
  * @return mixed
  * @throws ValidationException
  * @throws AuthenticationException
  */
 public function recordTransfer(Request $request, $userId)
 {
     $user = User::findWithPermission($userId);
     $this->bbCredit->setUserId($user->id);
     $amount = $request->get('amount');
     $targetUserId = $request->get('target_user_id');
     $targetUser = $this->userRepository->getById($targetUserId);
     if ($targetUserId === $userId) {
         throw new ValidationException('Your\'e trying to send money to yourself, no!');
     }
     //What is the users balance
     $userBalance = $this->bbCredit->getBalance();
     //With this payment will the users balance go to low?
     if ($userBalance - $amount < 0) {
         \Notification::error("You don't have the money for this");
         return \Redirect::route('account.balance.index', $user->id);
     }
     $this->paymentRepository->recordBalanceTransfer($user->id, $targetUser->id, $amount);
     \Notification::success("Transfer made");
     return \Redirect::route('account.balance.index', $user->id);
 }
 /**
  * Bill members based on the sub charges that are due
  */
 public function billMembers()
 {
     $subCharges = $this->subscriptionChargeRepository->getDue();
     //Check each of the due charges, if they have previous attempted payments ignore them
     // we don't want to retry failed payments as for DD's this will generate bank charges
     $subCharges->reject(function ($charge) {
         return $this->paymentRepository->getPaymentsByReference($charge->id)->count() > 0;
     });
     //Filter the list into two gocardless and balance subscriptions
     $goCardlessUsers = $subCharges->filter(function ($charge) {
         return $charge->user->payment_method == 'gocardless-variable';
     });
     $balanceUsers = $subCharges->filter(function ($charge) {
         return $charge->user->payment_method == 'balance';
     });
     //Charge the balance users
     foreach ($balanceUsers as $charge) {
         if ($charge->user->monthly_subscription * 100 > $charge->user->cash_balance) {
             //user doesn't have enough money
             //If they have a secondary payment method of gocardless try that
             if ($charge->user->secondary_payment_method == 'gocardless-variable') {
                 //Add the charge to the gocardless list for processing
                 $goCardlessUsers->push($charge);
                 event(new SubscriptionPayment\InsufficientFundsTryingDirectDebit($charge->user->id, $charge->id));
             } else {
                 event(new SubscriptionPayment\FailedInsufficientFunds($charge->user->id, $charge->id));
             }
             continue;
         }
         $this->paymentRepository->recordSubscriptionPayment($charge->user->id, 'balance', '', $charge->user->monthly_subscription, 'paid', 0, $charge->id);
         event(new MemberBalanceChanged($charge->user->id));
     }
     //Charge the gocardless users
     foreach ($goCardlessUsers as $charge) {
         $bill = $this->goCardless->newBill($charge->user->subscription_id, $charge->user->monthly_subscription, $this->goCardless->getNameFromReason('subscription'));
         if ($bill) {
             $this->paymentRepository->recordSubscriptionPayment($charge->user->id, 'gocardless-variable', $bill->id, $bill->amount, $bill->status, $bill->gocardless_fees, $charge->id);
         }
     }
 }
 public function calculatePendingFees()
 {
     $records = $this->equipmentLogRepository->getFinishedUnbilledRecords();
     foreach ($records as $record) {
         $equipment = $this->equipmentRepository->findBySlug($record->device);
         if ($equipment->hasUsageCharge()) {
             $feePerSecond = $this->costPerSecond($equipment->usageCost);
             //How may seconds was the device in use
             $secondsActive = $record->finished->diffInSeconds($record->started);
             //Charges are for a minimum of 15 minutes
             $secondsActive = $this->roundUpSecondsActive($secondsActive);
             $incurredFee = $this->sessionFee($feePerSecond, $secondsActive);
             //If the reason is empty then its not a special case and should be billed
             if (empty($record->reason)) {
                 //Create a payment against the user
                 $this->paymentRepository->recordPayment('equipment-fee', $record->user_id, 'balance', '', $incurredFee, 'paid', 0, $record->id . ':' . $record->device);
             }
         }
         //Mark this log as being billed and complete
         $record->billed = true;
         $record->save();
     }
 }
 /**
  * Remove the specified payment
  *
  * @param  int $id
  * @return Illuminate\Http\RedirectResponse
  * @throws \BB\Exceptions\ValidationException
  */
 public function destroy($id)
 {
     $payment = $this->paymentRepository->getById($id);
     //we can only allow some records to get deleted, only cash payments can be removed, everything else must be refunded off
     if ($payment->source != 'cash') {
         throw new \BB\Exceptions\ValidationException('Only cash payments can be deleted');
     }
     if ($payment->reason != 'balance') {
         throw new \BB\Exceptions\ValidationException('Currently only payments to the members balance can be deleted');
     }
     //The delete event will broadcast an event and allow related actions to occur
     $this->paymentRepository->delete($id);
     \Notification::success('Payment deleted');
     return \Redirect::back();
 }
 /**
  * Process a direct debit payment when we have a preauth
  *
  * @param $amount
  * @param $reason
  * @param User $user
  * @param $ref
  * @param $returnPath
  * @return mixed
  */
 private function handleBill($amount, $reason, $user, $ref, $returnPath)
 {
     $bill = $this->goCardless->newBill($user->subscription_id, $amount, $this->goCardless->getNameFromReason($reason));
     if ($bill) {
         //Store the payment
         $fee = $bill->amount - $bill->amount_minus_fees;
         $paymentSourceId = $bill->id;
         $amount = $bill->amount;
         $status = $bill->status;
         //The record payment process will make the necessary record updates
         $this->paymentRepository->recordPayment($reason, $user->id, 'gocardless-variable', $paymentSourceId, $amount, $status, $fee, $ref);
         if (\Request::wantsJson()) {
             return \Response::json(['message' => 'The payment was submitted successfully']);
         }
         \Notification::success("The payment was submitted successfully");
     } else {
         //something went wrong - we still have the pre auth though
         if (\Request::wantsJson()) {
             return \Response::json(['error' => 'There was a problem charging your account'], 400);
         }
         \Notification::error("There was a problem charging your account");
     }
     return \Redirect::to($returnPath);
 }
示例#17
0
 public function getBalancePaymentsPaginated()
 {
     return $this->paymentRepository->getBalancePaymentsPaginated($this->user->id);
 }
 public function index()
 {
     $this->paymentRepository->reasonFilter('balance');
     $balancePaidIn = $this->paymentRepository->getTotalAmount();
     $this->paymentRepository->resetFilters();
     $this->paymentRepository->sourceFilter('balance');
     $balancePaidOut = $this->paymentRepository->getTotalAmount();
     $balanceLiability = $balancePaidIn - $balancePaidOut;
     $this->paymentRepository->resetFilters();
     $this->paymentRepository->reasonFilter('storage-box');
     $storageBoxLiability = $this->paymentRepository->getTotalAmount();
     $this->paymentRepository->resetFilters();
     $this->paymentRepository->reasonFilter('door-key');
     $doorKeyLiability = $this->paymentRepository->getTotalAmount();
     $laserCutterInvestment = $this->paymentRepository->getPaymentsByReference('laser-cutter')->sum('amount');
     $laserCutterMoneySpent = $this->paymentRepository->getEquipmentFeePayments('laser')->sum('amount');
     return \View::make('payment_overview.index')->with(compact('balancePaidIn', 'balancePaidOut', 'balanceLiability', 'storageBoxLiability', 'doorKeyLiability', 'laserCutterInvestment', 'laserCutterMoneySpent'));
 }
 /**
  * Handle the event.
  *
  * @param  ExpenseWasApproved  $event
  * @return void
  */
 public function handle(ExpenseWasApproved $event)
 {
     $this->paymentRepository->recordPayment('balance', $event->expense->user_id, 'reimbursement', $event->expense->id, $event->expense->amount / 100);
 }
 /**
  * @param int $memberId
  */
 public function setMember($memberId)
 {
     $this->memberId = $memberId;
     $this->memberBoxes = $this->storageBoxRepository->getMemberBoxes($this->memberId);
     $this->boxPayments = $this->paymentRepository->getStorageBoxPayments($this->memberId);
 }