ArthurGuy/BBMembershipSystem

View on GitHub
app/Http/Controllers/PaypalIPNController.php

Summary

Maintainability
B
4 hrs
Test Coverage
<?php namespace BB\Http\Controllers;

use BB\Entities\Payment;
use BB\Entities\User;
use BB\Helpers\PayPalConfig;
use BB\Repo\PaymentRepository;
use BB\Repo\SubscriptionChargeRepository;
use Carbon\Carbon;

class PaypalIPNController extends Controller
{

    /**
     * @var SubscriptionChargeRepository
     */
    private $subscriptionChargeRepository;
    /**
     * @var PaymentRepository
     */
    private $paymentRepository;

    function __construct(SubscriptionChargeRepository $subscriptionChargeRepository, PaymentRepository $paymentRepository)
    {
        $this->subscriptionChargeRepository = $subscriptionChargeRepository;
        $this->paymentRepository = $paymentRepository;
    }

    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']);
            }

            $date = Carbon::now();
            //If the user doesn't have an active sub charge record the payment as a balance payment
            $subCharge = $this->subscriptionChargeRepository->findCharge($user->id, $date);
            if ($subCharge) {
                //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']);
            } else {
                $this->paymentRepository->recordPayment('balance', $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
            }
        }
    }

    /**
     * @param $user
     * @param $amount
     * @return void
     */
    private function setupNewMember(User $user, $amount)
    {
        //At this point the day of the month hasn't been set for the user, set it now
        $user->updateSubscription('paypal', Carbon::now()->day);

        //if this is blank then the user hasn't been setup yet
        $subCharge = $this->subscriptionChargeRepository->createCharge($user->id, Carbon::now(), $amount);
    }
}