Skip to content
Code-Schnipsel Gruppen Projekte
SepaDebit.php 6,01 KiB
Newer Older
Patrick Müller's avatar
Patrick Müller committed
<?php

namespace QUI\ERP\Payments\Stripe\PaymentMethods\Recurring;

use Exception;
use QUI;
use QUI\ERP\Accounting\Invoice\Invoice;
use QUI\ERP\Accounting\Invoice\InvoiceView;
use QUI\ERP\Accounting\Payments\Payments;
use QUI\ERP\Order\AbstractOrder;
use QUI\ERP\Order\OrderInterface;
use QUI\ERP\Payments\Stripe\Provider;
use QUI\ERP\Payments\Stripe\Utils;
use Stripe\Exception\ApiErrorException;
use Stripe\PaymentIntent;
use Stripe\PaymentIntent as StripePaymentIntent;
use Stripe\PaymentMethod;
use Stripe\Subscription;
use Stripe\Subscription as StripeSubscription;

/**
 * Stripe payment with SEPA Direct Debit for recurring payments
 */
class SepaDebit extends AbstractBaseRecurringPayment
{
    /**
     * @return string
     */
    public function getTitle(): string
    {
        return $this->getLocale()->get('quiqqer/payment-stripe', 'payment.Recurring.SepaDebit.title');
    }

    /**
     * @return string
     */
    public function getDescription(): string
    {
        return $this->getLocale()->get('quiqqer/payment-stripe', 'payment.Recurring.SepaDebit.description');
    }

    /**
     * Get title for frontend
     *
     * @return string
     */
    public function getFrontendTitle(): string
    {
        return $this->getLocale()->get('quiqqer/payment-stripe', 'payment.frontend.Recurring.SepaDebit.title');
    }

    /**
     * Get description for frontend
     *
     * @return string
     */
    public function getFrontendDescription(): string
    {
        return $this->getLocale()->get('quiqqer/payment-stripe', 'payment.frontend.Recurring.SepaDebit.description');
    }

    /**
     * Get title for the Payment step (OrderProcess)
     *
     * @return string
     */
    public function getPaymentStepTitle(): string
    {
        return $this->getLocale()->get('quiqqer/payment-stripe', 'payment.PaymentStep.title.SepaDebit');
    }

    /**
     * Get description step for the Payment step (OrderProcess)
     *
     * @return string
     */
    public function getPaymentStepInfo(): string
    {
        return $this->getLocale()->get('quiqqer/payment-stripe', 'payment.Recurring.PaymentStep.info.SepaDebit');
    }

//    /**
//     * Return the payment icon (the URL path)
//     * Can be overwritten
//     *
//     * @return string
//     */
//    public function getIcon(): string
//    {
//        return Payments::getInstance()->getHost() .
//            URL_OPT_DIR .
//            'quiqqer/payment-stripe/bin/images/Payment_Card.png'; // TODO: richtiges Logo
//    }

    /**
     * Get type string of Stripe PaymentMethod
     *
     * @return string
     */
    public function getPaymentMethodType(): string
    {
        return PaymentMethod::TYPE_SEPA_DEBIT;
    }

    /**
     * Return the extra text for the invoice
     *
     * @param Invoice|InvoiceView $Invoice
     * @return string
     */
    public function getInvoiceInformationText($Invoice): string
    {
        try {
            return $Invoice->getCustomer()->getLocale()->get(
                'quiqqer/payment-stripe',
                'additional_invoice_text.SepaDebit'
            );
        } catch (Exception $Exception) {
            QUI\System\Log::writeException($Exception);
            return '';
        }
    }

    /**
     * Return attributes for creating a PaymentIntent
     *
     * @param AbstractOrder $Order
     * @param string $paymentMethodId - Stripe PaymentMethod ID
     * @return StripePaymentIntent
     *
     * @throws ApiErrorException
     * @throws QUI\Exception
     */
    protected function createPaymentIntentForOrder(AbstractOrder $Order, string $paymentMethodId): StripePaymentIntent
    {
        return StripePaymentIntent::create([
            'payment_method' => $paymentMethodId,
            'amount' => Utils::getCentAmount($Order),
            'currency' => mb_strtolower($Order->getCurrency()->getCode()),
            'confirmation_method' => 'manual',
            'confirm' => true,
            'setup_future_usage' => 'off_session',
            'use_stripe_sdk' => true,
            'description' => Utils::getPaymentDescriptionForOrder($Order),
            'statement_descriptor' => Provider::getStatementDescriptor($Order),
            'metadata' => [
                'orderUuid' => $Order->getUUID()
            ],
            'payment_method_types' => [
                PaymentMethod::TYPE_SEPA_DEBIT
            ],
Patrick Müller's avatar
Patrick Müller committed
            'mandate_data' => [
                'customer_acceptance' => [
                    'type' => 'online',
                    'online' => [
                        'ip_address' => $_SERVER['REMOTE_ADDR'],
                        'user_agent' => $_SERVER['HTTP_USER_AGENT'],
                    ],
                ],
            ]
        ]);
    }

    public function canBeUsedInOrder(OrderInterface $order): bool
    {
        // Currency must be EUR
        if ($order->getCurrency()->getCode() !== 'EUR') {
            return false;
        }

        if ($order->getInvoiceAddress()->getCountry()->isEU()) {
            return true;
        }

        // Some Non-EU countries are also part of SEPA
        return match ($order->getInvoiceAddress()->getCountry()->getCode()) {
            'CH', 'GB', 'SM', 'VA', 'AD', 'MC', 'IS', 'NO', 'LI' => true,
            default => false,
        };
    }

    /**
     * Confirms a PaymentIntent with status "requires_confirmation" for a subscription.
     *
     * @param StripeSubscription $subscription
     * @param StripePaymentIntent $paymentIntent
     * @return void
     * @throws ApiErrorException
     */
    public function confirmPaymentIntentForSubscription(
        Subscription $subscription,
        PaymentIntent $paymentIntent
    ): void {
        Provider::setupApi();

        $data = [
            'mandate_data' => [
                'customer_acceptance' => [
                    'type' => 'online',
                    'online' => [
                        'ip_address' => $_SERVER['REMOTE_ADDR'],
                        'user_agent' => $_SERVER['HTTP_USER_AGENT'],
                    ],
                ],
            ]
        ];

        $paymentIntent->confirm($data);
    }
}