Надеюсь, что все, кто читает это, в порядке :)
Пожалуйста, примите мои извинения, если это уже было где-то дано в документации или комментариях, но я не смог ничего найти.
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
]);
}