Symfony - Payum - 为用户的余额增加资金

时间:2018-04-12 14:04:11

标签: php symfony paypal payum

我有一个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。 但是,如果我这样做并且付款失败了,我应该在视图操作中删除它吗?

0 个答案:

没有答案