Symfony3 PayumBundle - статус экспресс-оплаты PayPal в PaymentDetails и показать его пользователю - PullRequest
0 голосов
/ 24 сентября 2018

Надеюсь, что все, кто читает это, в порядке :)

Пожалуйста, примите мои извинения, если это уже было где-то дано в документации или комментариях, но я не смог ничего найти.

IЯ использую paypal_express_checkout_and_doctrine_orm, и моя цель - показать статус каждого платежа пользователю и администратору.Я проверил, и мне кажется, что я должен создать notify.php или что-то подобное, чтобы PayPal мог отправлять уведомления со статусом, но я не могу понять, как сохранить статус (например, принят или отклонен) в PaymentDetailsдля того, чтобы при представлении платежей показывать статус.На данный момент у меня есть следующая структура:

// файл PaymentDetails

    <?php

namespace AppBundle\Entity;

use Doctrine\ORM\Mapping as ORM;
use Payum\Core\Model\ArrayObject;

/**
 * PaymentDetails
 *
 * @ORM\Table(name="payment_details")
 * @ORM\Entity(repositoryClass="AppBundle\Repository\PaymentDetailsRepository")
 */
class PaymentDetails extends ArrayObject
{

    public function __construct()
    {
        $this->datetimeStamp = new \DateTime();
        $this->datetimeConfirmed = new \DateTime();
//        $this->validUntil = new \DateTime();
    }

    /**
     * @ORM\Column(name="id", type="integer")
     * @ORM\Id
     * @ORM\GeneratedValue(strategy="IDENTITY")
     */
    protected $id;

    /**
     * @var string
     * @ORM\Column(name="number", type="string", length=255)
     */
    private $number;

    /**
     * @var \DateTime
     * @ORM\Column(name="datetime_stamp", type="datetime")
     */
    private $datetimeStamp;

    /**
     * @var \DateTime
     * @ORM\Column(name="datetime_confirmed", type="datetime", nullable=true)
     */
    private $datetimeConfirmed;

    /** @var
     *
     * @ORM\Column(name="valid_until", type="datetime", nullable=true)
     */
    private $validUntil;

    /**
     * @var bool
     *
     * @ORM\Column(name="is_confirmed", type="boolean")
     */
    private $isConfirmed;

    /**
     * @var int
     *
     * @ORM\Column(name="time_period", type="integer")
     */
    private $timePeriod;

    /**
     * @ORM\Column(name="total_amount", type="decimal")
     */
    private $totalAmount;

    /**
     * @var string
     * @ORM\Column(name="currency_code", type="string", length=255)
     */
    private $currencyCode;

    /**
     * @var string
     * @ORM\Column(name="payment_token", type="string", length=255, nullable=true)
     */
    private $paymentToken;

    /**
     * @var string
     * @ORM\Column(name="description", type="string", length=255)
     */
    private $description;

    /**
     * @ORM\ManyToOne(targetEntity="AppBundle\Entity\ContractorDetails", inversedBy="paymentsDetails")
     * @ORM\JoinColumn(name="contractor_details_id", referencedColumnName="id")
     */
    private $contractorDetails;

    /**
     * @return int
     */
    public function getId()
    {
        return $this->id;
    }

    /**
     * @return \DateTime
     */
    public function getDatetimeStamp()
    {
        return $this->datetimeStamp;
    }

    /**
     * @param \DateTime $datetimeStamp
     */
    public function setDatetimeStamp($datetimeStamp)
    {
        $this->datetimeStamp = $datetimeStamp;
    }

    /**
     * @return int
     */
    public function getTotalAmount()
    {
        return $this->totalAmount;
    }

    /**
     * @param int $totalAmount
     */
    public function setTotalAmount($totalAmount)
    {
        $this->totalAmount = $totalAmount;
    }

    /**
     * @return string
     */
    public function getCurrencyCode()
    {
        return $this->currencyCode;
    }

    /**
     * @param string $currencyCode
     */
    public function setCurrencyCode($currencyCode)
    {
        $this->currencyCode = $currencyCode;
    }

    /**
     * @return string
     */
    public function getPaymentToken()
    {
        return $this->paymentToken;
    }

    /**
     * @param string $paymentToken
     */
    public function setPaymentToken($paymentToken)
    {
        $this->paymentToken = $paymentToken;
    }

    /**
     * @return mixed
     */
    public function getContractorDetails()
    {
        return $this->contractorDetails;
    }

    /**
     * @param mixed $contractorDetails
     */
    public function setContractorDetails($contractorDetails)
    {
        $this->contractorDetails = $contractorDetails;
    }

    /**
     * @return string
     */
    public function getDescription()
    {
        return $this->description;
    }

    /**
     * @param string $description
     */
    public function setDescription($description)
    {
        $this->description = $description;
    }

    /**
     * @return string
     */
    public function getNumber()
    {
        return $this->number;
    }

    /**
     * @param string $number
     */
    public function setNumber($number)
    {
        $this->number = $this->getContractorDetails()->getId() . '_' . $number;
    }

    /**
     * @return \DateTime
     */
    public function getDatetimeConfirmed()
    {
        return $this->datetimeConfirmed;
    }

    /**
     * @param \DateTime $datetimeConfirmed
     */
    public function setDatetimeConfirmed($datetimeConfirmed)
    {
        $this->datetimeConfirmed = $datetimeConfirmed;
    }

    /**
     * @return bool
     */
    public function isConfirmed()
    {
        return $this->isConfirmed;
    }

    /**
     * @return bool
     */
    public function isNotConfirmed()
    {
        return !$this->isConfirmed;
    }

    /**
     * @param bool $isConfirmed
     */
    public function setIsConfirmed($isConfirmed)
    {
        $this->isConfirmed = $isConfirmed;
    }

    /**
     * @return mixed
     */
    public function getValidUntil()
    {
        return $this->validUntil;
    }

    /**
     * @param mixed $validUntil
     */
    public function setValidUntil($validUntil)
    {
        $this->validUntil = $validUntil;
    }

    /**
     * @return int
     */
    public function getTimePeriod()
    {
        return $this->timePeriod;
    }

    /**
     * @param int $timePeriod
     */
    public function setTimePeriod($timePeriod)
    {
        $this->timePeriod = $timePeriod;
    }


}

// файл PaymentController

    /**
     * @Route("/payment/paypal", name="payment_paypal")
     * @param Request $request
     * @return \Symfony\Component\HttpFoundation\RedirectResponse|\Symfony\Component\HttpFoundation\Response
     */
    public function prepareSimplePurchaseAndDoctrineOrmAction(Request $request)
    {
        $gatewayName = 'paypal_express_checkout_and_doctrine_orm';

        $form = $this->createForm(PaymentFormType::class);
        $form->handleRequest($request);
        if ($form->isValid()) {
            /** @var PaymentPrice[] $data */
            $data = $form->getData();

            $storage = $this->getPayum()->getStorage(PaymentDetails::class);

            $totalAmount = $data['PaymentPrice']->getAmount();
            $currencyCode = $data['PaymentPrice']->getCurrency();
            $timePeriod = $data['PaymentPrice']->getTimePeriod();
            $description = "PayPal";

            /** @var $payment PaymentDetails */
            $payment = $storage->create();
            $payment['PAYMENTREQUEST_0_CURRENCYCODE'] = $currencyCode;
            $payment['PAYMENTREQUEST_0_AMT'] = $totalAmount;
            $payment['NOSHIPPING'] = '1';      // this is required for digital goods
            $payment['SOLUTIONTYPE'] = 'SOLE'; // this is to add option to pay with credit card without creating account
            $payment['LANDINGPAGE'] = 'Billing'; // Type of PayPal page to display - pay with credit card
//            $payment['LANDINGPAGE'] = 'Login'; // Type of PayPal page to display - pay with account
            $payment['USERSELECTEDFUNDINGSOURCE'] = 'CreditCard'; // added this in order to have option to choose if wanted to create an account
            $payment['LOCALECODE'] = 'IE'; //


//            TODO: check if other of these should be added here?
//            check here for more details: https://developer.paypal.com/docs/classic/api/merchant/SetExpressCheckout_API_Operation_NVP/

            $contractorDetails = $this->getUser()->getContractorDetails();
            $payment->setContractorDetails($contractorDetails);
            $payment->setTotalAmount($totalAmount);
            $payment->setDescription($description);
            $payment->setCurrencyCode($currencyCode);
            $payment->setNumber(uniqid());
            $payment->setIsConfirmed(0);
            $payment->setTimePeriod($timePeriod);

            $storage->update($payment);


            $notifyToken = $this->getPayum()->getTokenFactory()->createNotifyToken($gatewayName, $payment);
            $payment['PAYMENTREQUEST_0_NOTIFYURL'] = $notifyToken->getTargetUrl();

            $captureToken = $this->getPayum()->getTokenFactory()->createCaptureToken(
                $gatewayName,
                $payment,
                'payment_done'
            );

//            $paymentToken = $captureToken->getHash();
//            $payment->setPaymentToken($paymentToken);

            $payment['INVNUM'] = $payment->getId();
            $storage->update($payment);

            return $this->redirect($captureToken->getTargetUrl());
        }

//        return array(
//            'form' => $form->createView(),
//            'gatewayName' => $gatewayName
//        );
        return $this->render('payment/paypal.html.twig', [
            'form' => $form->createView(),
            'gatewayName' => $gatewayName
        ]);
    }

// файл PaymentController

    /**
     * @Route("payment/done", name="payment_done")
     * @param Request $request
     * @return \Symfony\Component\HttpFoundation\Response
     * @throws \Exception
     */
    public function doneAction(Request $request)
    {

        $token = $this->getPayum()->getHttpRequestVerifier()->verify($request);

        $identity = $token->getDetails();
        /** @var PaymentDetails $payment */
        $payment = $this->get('payum')->getStorage($identity->getClass())->find($identity);
        $storage = $this->getPayum()->getStorage(PaymentDetails::class);
//        $payment->setPaymentToken($token->getHash());
//        $storage->update($payment);

        $gateway = $this->getPayum()->getGateway($token->getGatewayName());

        try {
            $gateway->execute(new Sync($token));
        } catch (RequestNotSupportedException $e) {
        }

        $gateway->execute($status = new GetHumanStatus($token));

        $refundToken = null;
        $captureToken = null;
        $cancelToken = null;

        if ($status->isCaptured()) {
            $refundToken = $this->getPayum()->getTokenFactory()->createRefundToken(
                $token->getGatewayName(),
                $status->getFirstModel(),
                $request->getUri()
            );
        }
        if ($status->isAuthorized()) {
            $captureToken = $this->getPayum()->getTokenFactory()->createCaptureToken(
                $token->getGatewayName(),
                $status->getFirstModel(),
                $request->getUri()
            );

            $cancelToken = $this->getPayum()->getTokenFactory()->createCancelToken(
                $token->getGatewayName(),
                $status->getFirstModel(),
                $request->getUri()
            );
        }

//        $storage->update($status->getValue());
        $payment->setPaymentToken($token->getHash());
        $storage->update($payment);


        $details = $status->getFirstModel();
        if ($details instanceof DetailsAggregateInterface) {
            $details = $details->getDetails();
        }

        if ($details instanceof \Traversable) {
            $details = iterator_to_array($details);
        }

        return $this->redirectToRoute("payment");

//        return $this->render('payment/view.html.twig', array(
//            'status' => $status->getValue(),
//            'payment' => htmlspecialchars(json_encode($details, JSON_PRETTY_PRINT | JSON_UNESCAPED_SLASHES | JSON_UNESCAPED_UNICODE)),
//            'gatewayTitle' => ucwords(str_replace(array('_', '-'), ' ', $token->getGatewayName())),
//            'refundToken' => $refundToken,
//            'captureToken' => $captureToken,
//            'cancelToken' => $cancelToken,
//        ));
    }

// file PaymentController

        /**
     * @Route("/payment", name="payment")
     * @return \Symfony\Component\HttpFoundation\Response
     */
    public function indexAction()
    {
        $storage = $this->getPayum()->getStorage(PaymentDetails::class);
        $contractorDetails = $this->getUser()->getContractorDetails();
        $payments = $storage->findBy([
            'contractorDetails' => $contractorDetails
        ]);

        return $this->render('payment/index.html.twig', [
            'payments' => $payments
        ]);
    }
...