/** * 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); } }
/** * 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 } } }
/** * A Bill has been created, these will always start within the system except for subscription payments * * @param array $bills */ private function processNewBills(array $bills) { //We have new bills/payment foreach ($bills as $bill) { //Ignore non subscription payment creations if ($bill['source_type'] != 'subscription') { continue; } try { //Locate the user through their subscription id $user = User::where('payment_method', 'gocardless')->where('subscription_id', $bill['source_id'])->first(); if (!$user) { \Log::warning("GoCardless new sub payment notification for unmatched user. Bill ID: " . $bill['id']); continue; } $ref = null; $this->paymentRepository->recordSubscriptionPayment($user->id, 'gocardless', $bill['id'], $bill['amount'], $bill['status'], $bill['amount'] - $bill['amount_minus_fees'], $ref); } catch (\Exception $e) { \Log::error($e); } } }
/** * 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); } } }