Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

PayPal express checkout store status in PaymentDetails and show it to the user #470

Open
nmihaylov opened this issue Sep 17, 2018 · 0 comments

Comments

@nmihaylov
Copy link

nmihaylov commented Sep 17, 2018

Hi there,

Hope everyone who is reading this is ok :)

Please have my apologies if this was already answered somewhere into the documentation or comments but I was not able to find anything.

I'm using paypal_express_checkout_and_doctrine_orm and my goal is to be able to show the status for each payment to the user and the admin. I checked and it seems that I should create notify.php or something like this in order PayPal to be able to send notification with the status but I'm not able to understand how to store the status (for example accepted or denied) in PaymentDetails in order when presenting the payments to show the status. For now I have the following structure:

<?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;
    }


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

Best regards,
Niki

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests

1 participant