PayumBundle
PayumBundle copied to clipboard
PayPal express checkout store status in PaymentDetails and show it to the user
trafficstars
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