我有一个Symfony 3.4项目,我想将PayumBundle集成到Paypal Express Checkout中,我想要实现的目标如下: 用户可以使用Paypal Express Checkout向其帐户添加资金,一旦他们填写了他们想要添加的金额,我会检查付款是否通过,并且我会增加用户的余额。 用户可以购买"订单"从网站上看,如果他们这样做,订单金额将从他们的余额中扣除。 这就是我现在所设定的:
Config.yml:
payum:
security:
token_storage:
AppBundle\Entity\PaymentToken: { doctrine: orm }
storages:
AppBundle\Entity\Payment: { doctrine: orm }
AppBundle\Entity\PaymentDetails: { doctrine: orm }
gateways:
paypal_express_checkout_default_gateaway:
factory: paypal_express_checkout
username: '**************.email.com'
password: '********************'
signature: '***************'
sandbox: true
我的PaymentDetails类:
/**
* @ORM\Table(name="payum_payment_details")
* @ORM\Entity
*/
class PaymentDetails extends ArrayObject
{
/**
* @ORM\Column(name="id", type="integer")
* @ORM\Id
* @ORM\GeneratedValue(strategy="IDENTITY")
*/
protected $id;
/**
* @return int
*/
/**
* One PaymentDetails has One AccountBalanceTransaction.
* @ORM\OneToOne(targetEntity="AppBundle\Entity\AccountBalanceTransaction", mappedBy="paymentDetails")
*/
private $accountBalanceTransaction;
/**
* Many PaymentDetails have One User.
* @ORM\ManyToOne(targetEntity="Application\Sonata\UserBundle\Entity\User", inversedBy="paymentDetails")
* @ORM\JoinColumn(name="user_id", referencedColumnName="id")
*/
private $user;
// getters and setter removed
}
AccountBalanceTransaction类:
/**
* @ORM\Entity
* @ORM\Table(name="account_balance_transaction")
*/
class AccountBalanceTransaction
{
public function __construct()
{
$this->setDate(new \DateTime());
$this->paymentDetails = new ArrayCollection();
}
/**
* @ORM\Id
* @ORM\GeneratedValue
* @ORM\Column(type="integer")
*/
private $id;
/**
* @ORM\Column(type="decimal", precision=7, scale=2, nullable=true)
*/
private $credit;
/**
* @ORM\Column(type="decimal", precision=7, scale=2, nullable=true)
*/
private $debit;
/**
* @ORM\Column(type="decimal", precision=7, scale=2)
*/
private $balance;
/**
* @ORM\Column(type="datetime")
*/
private $date;
/**
* @ORM\Column(type="text", nullable=true)
*/
private $description;
/**
* One AccountBalanceTransaction Might have One PaymentDetails.
* @ORM\OneToOne(targetEntity="AppBundle\Entity\PaymentDetails", inversedBy="accountBalanceTransaction")
* @ORM\JoinColumn(name="payment_details_id", referencedColumnName="id", nullable=true)
*/
private $paymentDetails;
/**
* One AccountBalanceTransaction Might have One Order.
* @ORM\OneToOne(targetEntity="AppBundle\Entity\Order", inversedBy="accountBalanceTransaction")
* @ORM\JoinColumn(name="order_id", referencedColumnName="id", nullable=true)
*/
private $order;
/**
* Many AccountBalanceTransactions have One User.
* @ORM\ManyToOne(targetEntity="Application\Sonata\UserBundle\Entity\User", inversedBy="accountBalanceTransactions")
* @ORM\JoinColumn(name="user_id", referencedColumnName="id")
*/
private $user;
}
最后,这是我的PaymentController类:
class PaymentController extends Controller
{
/**
* @Extra\Route(
* "/prepare_add_funds",
* name="paypal_express_checkout_prepare_add_funds"
* )
*
* @Extra\Template(":payment:prepare.html.twig")
*/
public function prepareSimplePurchaseAndDoctrineOrmAction(Request $request)
{
$user = $this->getUser();
if (!is_object($user) || !$user instanceof UserInterface) {
throw new AccessDeniedException('This user does not have access to this section.');
}
$gatewayName = 'paypal_express_checkout_default_gateaway';
$form = $this->createPurchaseForm();
$form->handleRequest($request);
if ($form->isValid()) {
$data = $form->getData();
$storage = $this->get('payum')->getStorage(PaymentDetails::class);
/** @var $payment PaymentDetails */
$payment = $storage->create();
$amount = $data['amount'];
$payment['PAYMENTREQUEST_0_CURRENCYCODE'] = 'USD';
$payment['PAYMENTREQUEST_0_AMT'] = $amount;
$storage->update($payment);
$captureToken = $this->get('payum')->getTokenFactory()->createCaptureToken(
$gatewayName,
$payment,
'paypal_express_checkout_done_add_funds'
);
$payment['INVNUM'] = $payment->getId();
$payment->setUser($user);
$storage->update($payment);
return $this->redirect($captureToken->getTargetUrl());
}
return array(
'form' => $form->createView(),
'gatewayName' => $gatewayName
);
}
/**
* @Extra\Route(
* "/payment/details",
* name="paypal_express_checkout_done_add_funds"
* )
*/
public function viewAction(Request $request)
{
$user = $this->getUser();
if (!is_object($user) || !$user instanceof UserInterface) {
throw new AccessDeniedException('This user does not have access to this section.');
}
$token = $this->get('payum')->getHttpRequestVerifier()->verify($request);
$gateway = $this->get('payum')->getGateway($token->getGatewayName());
try {
$gateway->execute(new Sync($token));
} catch (RequestNotSupportedException $e) {}
$gateway->execute($status = new GetHumanStatus($token));
$payment = $status->getFirstModel();
if ($user->getId() != || $payment->getUser()->getId()) {
throw new AccessDeniedException('This user does not have access to this section.');
}
if ($status->isCaptured()) {
$entityManager = $this->getDoctrine()->getManager();
$amount = $details['AMT'];
// check if this paymentDetails already has an AccountBalanceTransaction
$accountBalanceTransaction = $this->getDoctrine()
->getRepository(AccountBalanceTransaction::class)
->findOneBy(['paymentDetails' => $payment->getId()]);
// if not then create a new one and increase the user's balance
if($accountBalanceTransaction === null){
$accountBalanceTransaction = new AccountBalanceTransaction();
$accountBalanceTransaction->setUser($user);
$accountBalanceTransaction->setPaymentDetails($payment);
$accountBalanceTransaction->setCredit($amount);
$accountBalanceTransaction->setDescription('User added funds with Paypal.');
$accountBalanceTransaction->setBalance($user->getBalance() + $amount);
$entityManager->persist($accountBalanceTransaction);
$entityManager->flush();
$user->setBalance($user->getBalance() + $amount);
$entityManager->persist($user);
$entityManager->flush();
}
$refundToken = $this->get('payum')->getTokenFactory()->createRefundToken(
$token->getGatewayName(),
$status->getFirstModel(),
$request->getUri()
);
}
return $this->render('payment/view.html.twig', array(
'status' => $status->getValue(),
'refundToken' => $refundToken
));
}
/**
* @return \Symfony\Component\Form\FormInterface
*/
protected function createPurchaseForm()
{
return $this->createFormBuilder()
->add('amount', null, array(
'data' => 100,
'constraints' => array(new Range(array('max' => 10000)))
))
->getForm()
;
}
}
我使用FosUserBundle进行用户管理。
这种作品,但我对它并不满意,我认为有更好的方法可以做到这一点,但由于我是Payum和支付集成的新手,所以我&# 39;我需要别人的帮助。
另外,我不确定是否应该在viewAction中创建Entity AccountBalanceTransaction,也许我应该在prepareAction中创建它以及PaymentDetails。 但是,如果我这样做并且付款失败了,我应该在视图操作中删除它吗?