Seditio Source
Root |
./othercms/xenForo 2.2.8/src/XF/Payment/AbstractProvider.php
<?php

namespace XF\Payment;

use
XF\Entity\PaymentProfile;
use
XF\Entity\PurchaseRequest;
use
XF\Mvc\Controller;
use
XF\Purchasable\Purchase;

abstract class
AbstractProvider
{
    const
ERR_NO_RECURRING = 1;
    const
ERR_INVALID_RECURRENCE = 2;
    const
VALID_RECURRING = 3;

    protected
$providerId;

    abstract public function
getTitle();

    protected function
getPaymentParams(PurchaseRequest $purchaseRequest, Purchase $purchase)
    {
        return [];
    }

    abstract public function
initiatePayment(Controller $controller, PurchaseRequest $purchaseRequest, Purchase $purchase);

   
/**
     * @param \XF\Http\Request $request
     *
     * @return CallbackState
     */
   
abstract public function setupCallback(\XF\Http\Request $request);
   
    abstract public function
getPaymentResult(CallbackState $state);

    abstract public function
prepareLogData(CallbackState $state);

    public function
__construct($providerId)
    {
       
$this->providerId = $providerId;
    }

    public function
renderConfig(\XF\Entity\PaymentProfile $profile)
    {
       
$data = [
           
'profile' => $profile
       
];
        return \
XF::app()->templater()->renderTemplate('admin:payment_profile_' . $this->providerId, $data);
    }

    public function
verifyConfig(array &$options, &$errors = [])
    {
        return
true;
    }

    public function
processPayment(Controller $controller, PurchaseRequest $purchaseRequest, PaymentProfile $paymentProfile, Purchase $purchase)
    {
        return
null;
    }

    public function
renderCancellationTemplate(PurchaseRequest $purchaseRequest)
    {
        return
'';
    }

    protected function
renderCancellationDefault(PurchaseRequest $purchaseRequest)
    {
       
$data = [
           
'purchaseRequest' => $purchaseRequest
       
];
        return \
XF::app()->templater()->renderTemplate('public:payment_cancel_recurring', $data);
    }

   
/**
     * @param Controller $controller
     * @param PurchaseRequest $purchaseRequest
     * @param PaymentProfile $paymentProfile
     *
     * @return \XF\Mvc\Reply\AbstractReply
     */
   
public function processCancellation(Controller $controller, PurchaseRequest $purchaseRequest, PaymentProfile $paymentProfile)
    {
        throw new \
LogicException("processCancellation must be overridden.");
    }

    public function
validateCallback(CallbackState $state)
    {
        return
true;
    }

    public function
validateTransaction(CallbackState $state)
    {
       
/** @var \XF\Repository\Payment $paymentRepo */
       
$paymentRepo = \XF::repository('XF:Payment');
        if (
$paymentRepo->findLogsByTransactionIdForProvider($state->transactionId, $this->providerId)->total())
        {
           
$state->logType = 'info';
           
$state->logMessage = 'Transaction already processed. Skipping.';
            return
false;
        }
        return
true;
    }

    public function
validatePurchaseRequest(CallbackState $state)
    {
        if (!
$state->getPurchaseRequest())
        {
           
$state->logType = 'error';
           
$state->logMessage = 'Invalid purchase request.';
            return
false;
        }
        return
true;
    }

    public function
validatePurchasableHandler(CallbackState $state)
    {
       
$purchasableHandler = $state->getPurchasableHandler();
        if (!
$purchasableHandler)
        {
           
$state->logType = 'error';
           
$state->logMessage = 'Could not find handler for purchasable type \'' . $state->getPurchaseRequest()->purchasable_type_id  . '\'.';
            return
false;
        }

        if (!
$purchasableHandler->validatePurchasable($state, $error))
        {
           
$state->logType = 'error';
           
$state->logMessage = "Could not validate purchasable: $error";
            return
false;
        }

        return
true;
    }
   
    public function
validatePaymentProfile(CallbackState $state)
    {
        if (!
$state->getPaymentProfile())
        {
           
$state->logType = 'error';
           
$state->logMessage = 'Could not find a matching payment profile.';
            return
false;
        }
        return
true;
    }

    public function
validatePurchaser(CallbackState $state)
    {
       
$handler = $state->getPurchasableHandler();

        if (!
$handler->validatePurchaser($state, $error))
        {
           
$state->logType = 'error';
           
$state->logMessage = $error;
            return
false;
        }
        return
true;
    }

    public function
validatePurchasableData(CallbackState $state)
    {
        return
true;
    }

    public function
validateCost(CallbackState $state)
    {
        return
true;
    }

    public function
setProviderMetadata(CallbackState $state)
    {
        return;
    }

    public function
completeTransaction(CallbackState $state)
    {
       
$purchasableHandler = $state->getPurchasableHandler();

        switch (
$state->paymentResult)
        {
            case
CallbackState::PAYMENT_RECEIVED:
               
$purchasableHandler->completePurchase($state);
                try
                {
                   
$purchasableHandler->sendPaymentReceipt($state);
                }
                catch (\
Exception $e)
                {
                    \
XF::logException($e, false, "Error when sending payment receipt: ");
                }
                break;

            case
CallbackState::PAYMENT_REINSTATED:
               
$purchasableHandler->completePurchase($state);
                break;

            case
CallbackState::PAYMENT_REVERSED:
               
$purchasableHandler->reversePurchase($state);
                break;

            default:
               
$state->logType = 'info';
               
$state->logMessage = 'OK, no action';
                break;
        }

        try
        {
           
$purchasableHandler->postCompleteTransaction($state);
        }
        catch (\
Exception $e)
        {
            \
XF::logException($e, false, "Error in after completing transaction: ");
        }
    }

    public function
log(CallbackState $state)
    {
       
$this->prepareLogData($state);

       
/** @var \XF\Repository\Payment $paymentRepo */
       
$paymentRepo = \XF::repository('XF:Payment');
       
$paymentRepo->logCallback(
           
$state->requestKey,
           
$this->providerId,
           
$state->transactionId,
           
$state->logType,
           
$state->logMessage,
           
$state->logDetails,
           
$state->subscriberId
       
);
    }

   
/**
     * Verifies whether a provider supports recurring payments and verifies if the desired length is allowed
     * by the provider. The $result param provides more detail.
     *
     * Most providers only support one year so unless overridden, that will be the case for all providers.
     *
     * @return bool
     */
   
public function supportsRecurring(PaymentProfile $paymentProfile, $unit, $amount, &$result = self::ERR_NO_RECURRING)
    {
       
$supported = false;

       
$ranges = $this->getSupportedRecurrenceRanges();
        if (isset(
$ranges[$unit]))
        {
            list(
$minRange, $maxRange) = $ranges[$unit];
            if (
$amount >= $minRange && $amount <= $maxRange)
            {
               
$supported = true;
            }
        }

        if (
$supported)
        {
           
$result = self::VALID_RECURRING;
        }
        else
        {
           
$result = self::ERR_INVALID_RECURRENCE;
        }

        return
$supported;
    }

    protected function
getSupportedRecurrenceRanges()
    {
        return [
           
'day' => [1, 365],
           
'week' => [1, 52],
           
'month' => [1, 12],
           
'year' => [1, 1]
        ];
    }

    public function
verifyCurrency(PaymentProfile $paymentProfile, $currencyCode)
    {
        return
true;
    }

    public function
getCallbackUrl()
    {
        return \
XF::app()->options()->boardUrl . '/payment_callback.php?_xfProvider=' . $this->providerId;
    }

    public function
getApiEndpoint()
    {
        return
'';
    }

    public function
getProviderId()
    {
        return
$this->providerId;
    }
}