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

One Time and Recurring Payment Items in same Payment #484

Open
xeon826 opened this issue Dec 26, 2018 · 1 comment
Open

One Time and Recurring Payment Items in same Payment #484

xeon826 opened this issue Dec 26, 2018 · 1 comment

Comments

@xeon826
Copy link

xeon826 commented Dec 26, 2018

I have some items that will be one time payments and others that will recurring, I'm wanting to know how to have these in the same cart. One idea I had was that I could send them to the payment gateway to pay for the one time items and then redirect them back after the payment was successful or at least attempted and have them attempt to pay for the rest (The recurring payment items) But I don't know that this is the best way, is there a way I can specify both in the same cart?

     /**
     * @Route("/accounts/checkout", name="checkout")
     */
    public function checkoutAction(Request $request)
    {
        $orderForm = $this->createForm(OrderType::class, null, [
            'user' => $this->getUser(),
            'gateways' => $this->getParameter('app.gateways'),
        ]);
        $orderForm->handleRequest($request);
        $filter = $this->createForm(FilterHeroType::class, [], [
            'hierarchy_categories' => new Hierarchy($this->getDoctrine()->getRepository('AppBundle:Category'), 'category', 'categories'),
            'router' => $this->get('router'),
        ]);

        // Calculate total price
        $products = $request->getSession()->get('products');
        if (!$products) {
            $this->addFlash('danger', $this->get('translator')->trans('Cart is empty. Not able to proceed checkout.'));

            return $this->redirectToRoute('cart');
        }

        $price = 0;
        foreach ($products as $product) {
            $price += $product['price'];
        }

        // Save order
        if ($orderForm->isSubmitted() && $orderForm->isValid()) {
            $order = $orderForm->getData();
            $order->setStatus(Order::STATUS_NEW);
            $order->setUser($this->getUser());
            $order->setCurrency($this->getParameter('app.currency'));
            $order->setPrice($price);

            try {
                $em = $this->getDoctrine()->getManager();
                $em->persist($order);
                $em->flush();
            } catch (\Exception $e) {
                $this->addFlash('danger', $this->get('translator')->trans('An error occurred whe saving order.'));
            }

            // Save order items
            foreach ($products as $product) {
                $orderItem = new OrderItem();
                if ($product['type'] == 'pay_for_featured' || $product['type'] == 'pay_for_publish') {
                  $listing = $this->getDoctrine()->getRepository('AppBundle:Listing')->findOneBy(['id' => $product['listing_id']]);
                  $orderItem->setListing($listing);
                } else {
                  $county = $this->getDoctrine()->getRepository('AppBundle:County')->findOneBy(['id' => $product['county_id']]);
                  $orderItem->setCounty($county);
                }

                $orderItem->setOrder($order);
                $orderItem->setPrice($product['price']);
                $orderItem->setType($product['type']);
                $orderItem->setDuration($product['duration']);

                try {
                    $em = $this->getDoctrine()->getManager();
                    $em->persist($orderItem);
                    $em->flush();
                } catch (\Exception $e) {
                    $this->addFlash('danger', $this->get('translator')->trans('An error occurred whe saving order item.'));
                }
            }

            $request->getSession()->remove('products');
            $this->addFlash('success', $this->get('translator')->trans('Order has been successfully saved.'));

            if ($order->getGateway() == 'paypal') {
                $gatewayName = 'paypal_express_checkout';

                $storage = $this->get('payum')->getStorage(Payment::class);

                $payment = $storage->create();
                $payment->setNumber(uniqid());
                $payment->setCurrencyCode($this->getParameter('app.currency'));
                $payment->setTotalAmount($price * 100);
                $payment->setDescription('A description');
                $payment->setClientId($this->getUser()->getId());
                $payment->setClientEmail('user-email@host.com');
                $payment->setDescription('Payment for services rendered');
                $payment->setOrder($order);
                $payment->setDetails([
                  'PAYMENTREQUEST_0_AMT' => 0,
                  'L_BILLINGTYPE0' => Api::BILLINGTYPE_RECURRING_PAYMENTS,
                  'L_BILLINGAGREEMENTDESCRIPTION0' => "asdfasdf",
                  'NOSHIPPING' => 1
                ]);

                $storage->update($payment);

                $captureToken = $this->get('payum')->getTokenFactory()->createCaptureToken($gatewayName, $payment, 'order_paypal_completed');
                return $this->redirect($captureToken->getTargetUrl());
            }

            return $this->redirectToRoute('order');
        }

        return $this->render('FrontBundle::Order/checkout.html.twig', [
          'order' => $orderForm->createView(),
          'filter' => $filter->createView()
        ]);
    }

In this, pay_for_county is the item type that would be a recurring payment and any other would be one time. Looking at this page at L_BILLINGTYPEn I'm lost on a couplethings, one of which, what does n or m indicate? Also, MerchantInitiatedBilling looks like the right option as I need to specify per-transaction billing agreements but how would I set this and then how would I specify which items were one-item and which were recurring?

    /**
     * @Route("/account/county/add/{id}", name="county_add", requirements={"id": "\d+"})
     * @ParamConverter("County", class="DirectoryPlatform\AppBundle\Entity\County")
     */
    public function countyAction(Request $request, County $county)
    {
        // if ($this->getUser() !== $listing->getUser()) {
        //     throw $this->createAccessDeniedException('You are not allowed to access this page.');
        // }

        $payments = $this->getParameter('app.payments');

        if ($payments['pay_for_county']['enabled']) {
            $session = $request->getSession();

            if ($session->get('products')) {
                foreach ($session->get('products') as $product) {
                    if ($product['type'] == 'pay_for_county' && $product['county_id'] == $county->getId()) {
                        $this->addFlash('danger', $this->get('translator')->trans('Product is already in cart.'));

                        return $this->redirectToRoute('user_counties', [
                          'stateId' => $county->getStateId()
                        ]);
                    }
                }
            }

            $product = [
                'type' => 'pay_for_county',
                'county_id' => $county->getId(),
                'price' => $payments['pay_for_county']['price'],
                'duration' => $payments['pay_for_county']['duration'],
            ];

            if ($session->has('products')) {
                $products = $session->get('products');

                array_push($products, $product);
                $session->set('products', $products);
            } else {
                $session->set('products', [$product]);
            }

            $this->addFlash('success', $this->get('translator')->trans('Request for advertising county has been added into cart.'));
        } else {

            $profile = $this->getUser()->getProfile();
            $county->setProfiles($profile);

            try {
                $em = $this->getDoctrine()->getManager();
                $em->persist($county);
                $em->flush();

                $this->addFlash('success', $this->get('translator')->trans('Listing has been successfully marked as featured.'));
            } catch (\Exception $e) {
                $this->addFlash('danger', $this->get('translator')->trans('An error occurred when saving listing object.'));
            }
        }

        return $this->redirectToRoute('user_counties', [
          'stateId' => $county->getStateId()
        ]);
    }

Here I'm adding the products to the final order, could I possibly do it here? And even though it's a thing I'll have to figure out AFTER I fix this, how would I go about pinging the payment gateway to ensure the recurring payment had been successful? Since there are several items that are recurring payments, I don't know that I could have a way of figuring out which had been successful.

@xeon826
Copy link
Author

xeon826 commented Dec 26, 2018

So after looking around, I came up with this

                $payment->setDetails([
                  'METHOD' => 'SetExpressCheckout',
                  'VERSION' => '108',
                  'L_BILLINGTYPE0' => 'RecurringPayments',
                  'L_BILLINGAGREEMENTDESCRIPTION0' => "first item",
                  'L_BILLINGTYPE1' => 'RecurringPayments',
                  'L_BILLINGAGREEMENTDESCRIPTION1' => "second item",
                ]);

But only the first item shows up on Paypal after redirecting to the targetUrl, am I missing something?

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