Merge pull request #6197 from GSadee/convert-to-paypal

[Payum] Fix converting prices to correct currencies in PayPal
This commit is contained in:
Michał Marcinkowski 2016-09-26 09:06:27 +02:00 committed by GitHub
commit cd29add876
3 changed files with 151 additions and 9 deletions

View file

@ -15,8 +15,10 @@ use Payum\Core\Action\ActionInterface;
use Payum\Core\Exception\RequestNotSupportedException;
use Payum\Core\Request\Convert;
use Sylius\Component\Core\Model\AdjustmentInterface;
use Sylius\Component\Core\Model\OrderInterface;
use Sylius\Component\Core\Model\PaymentInterface;
use Sylius\Component\Core\Payment\InvoiceNumberGeneratorInterface;
use Sylius\Component\Currency\Converter\CurrencyConverterInterface;
class ConvertPaymentToPaypalExpressAction implements ActionInterface
{
@ -26,11 +28,20 @@ class ConvertPaymentToPaypalExpressAction implements ActionInterface
private $invoiceNumberGenerator;
/**
* @param InvoiceNumberGeneratorInterface $invoiceNumberGenerator
* @var CurrencyConverterInterface
*/
public function __construct(InvoiceNumberGeneratorInterface $invoiceNumberGenerator)
{
private $currencyConverter;
/**
* @param InvoiceNumberGeneratorInterface $invoiceNumberGenerator
* @param CurrencyConverterInterface $currencyConverter
*/
public function __construct(
InvoiceNumberGeneratorInterface $invoiceNumberGenerator,
CurrencyConverterInterface $currencyConverter
) {
$this->invoiceNumberGenerator = $invoiceNumberGenerator;
$this->currencyConverter = $currencyConverter;
}
/**
@ -44,18 +55,19 @@ class ConvertPaymentToPaypalExpressAction implements ActionInterface
/** @var PaymentInterface $payment */
$payment = $request->getSource();
/** @var OrderInterface $order */
$order = $payment->getOrder();
$details = [];
$details['PAYMENTREQUEST_0_INVNUM'] = $this->invoiceNumberGenerator->generate($order, $payment);
$details['PAYMENTREQUEST_0_CURRENCYCODE'] = $order->getCurrencyCode();
$details['PAYMENTREQUEST_0_AMT'] = round($order->getTotal() / 100, 2);
$details['PAYMENTREQUEST_0_ITEMAMT'] = round($order->getTotal() / 100, 2);
$details['PAYMENTREQUEST_0_AMT'] = $this->convertAndFormatPrice($order->getTotal(), $order->getCurrencyCode());
$details['PAYMENTREQUEST_0_ITEMAMT'] = $this->convertAndFormatPrice($order->getTotal(), $order->getCurrencyCode());
$m = 0;
foreach ($order->getItems() as $item) {
$details['L_PAYMENTREQUEST_0_NAME'.$m] = $item->getVariant()->getProduct()->getName();
$details['L_PAYMENTREQUEST_0_AMT'.$m] = round($item->getDiscountedUnitPrice() / 100, 2);
$details['L_PAYMENTREQUEST_0_AMT'.$m] = $this->convertAndFormatPrice($item->getDiscountedUnitPrice(), $order->getCurrencyCode());
$details['L_PAYMENTREQUEST_0_QTY'.$m] = $item->getQuantity();
++$m;
@ -63,7 +75,7 @@ class ConvertPaymentToPaypalExpressAction implements ActionInterface
if (0 !== $taxTotal = $order->getAdjustmentsTotalRecursively(AdjustmentInterface::TAX_ADJUSTMENT)) {
$details['L_PAYMENTREQUEST_0_NAME'.$m] = 'Tax Total';
$details['L_PAYMENTREQUEST_0_AMT'.$m] = round($taxTotal / 100, 2);
$details['L_PAYMENTREQUEST_0_AMT'.$m] = $this->convertAndFormatPrice($taxTotal, $order->getCurrencyCode());
$details['L_PAYMENTREQUEST_0_QTY'.$m] = 1;
++$m;
@ -71,7 +83,7 @@ class ConvertPaymentToPaypalExpressAction implements ActionInterface
if (0 !== $promotionTotal = $order->getOrderPromotionTotal()) {
$details['L_PAYMENTREQUEST_0_NAME'.$m] = 'Discount';
$details['L_PAYMENTREQUEST_0_AMT'.$m] = round($promotionTotal / 100, 2);
$details['L_PAYMENTREQUEST_0_AMT'.$m] = $this->convertAndFormatPrice($promotionTotal, $order->getCurrencyCode());
$details['L_PAYMENTREQUEST_0_QTY'.$m] = 1;
++$m;
@ -79,7 +91,7 @@ class ConvertPaymentToPaypalExpressAction implements ActionInterface
if (0 !== $shippingTotal = $order->getShippingTotal()) {
$details['L_PAYMENTREQUEST_0_NAME'.$m] = 'Shipping Total';
$details['L_PAYMENTREQUEST_0_AMT'.$m] = round($shippingTotal / 100, 2);
$details['L_PAYMENTREQUEST_0_AMT'.$m] = $this->convertAndFormatPrice($shippingTotal, $order->getCurrencyCode());
$details['L_PAYMENTREQUEST_0_QTY'.$m] = 1;
}
@ -97,4 +109,15 @@ class ConvertPaymentToPaypalExpressAction implements ActionInterface
$request->getTo() === 'array'
;
}
/**
* @param int $price
* @param string $currencyCode
*
* @return float
*/
private function convertAndFormatPrice($price, $currencyCode)
{
return round($this->currencyConverter->convertFromBase($price, $currencyCode) / 100, 2);
}
}

View file

@ -38,6 +38,7 @@
<!-- PayPal -->
<service id="sylius.payum.action.convert_payment_to_paypal_express" class="Sylius\Bundle\PayumBundle\Action\ConvertPaymentToPaypalExpressAction">
<argument type="service" id="sylius.invoice_number_generator" />
<argument type="service" id="sylius.currency_converter" />
<tag name="payum.action" factory="paypal_express_checkout" alias="sylius.convert_payment" />
</service>

View file

@ -0,0 +1,118 @@
<?php
/*
* This file is a part of the Sylius package.
*
* (c) Paweł Jędrzejewski
*
* For the full copyright and license information, please view the LICENSE
* file that was distributed with this source code.
*/
namespace spec\Sylius\Bundle\PayumBundle\Action;
use Payum\Core\Action\ActionInterface;
use Payum\Core\Exception\RequestNotSupportedException;
use Payum\Core\Request\Convert;
use PhpSpec\ObjectBehavior;
use Sylius\Bundle\PayumBundle\Action\ConvertPaymentToPaypalExpressAction;
use Sylius\Component\Core\Model\AdjustmentInterface;
use Sylius\Component\Core\Model\OrderInterface;
use Sylius\Component\Core\Model\OrderItemInterface;
use Sylius\Component\Core\Model\PaymentInterface;
use Sylius\Component\Core\Model\ProductInterface;
use Sylius\Component\Core\Model\ProductVariantInterface;
use Sylius\Component\Core\Payment\InvoiceNumberGeneratorInterface;
use Sylius\Component\Currency\Converter\CurrencyConverterInterface;
/**
* @mixin ConvertPaymentToPaypalExpressAction
*
* @author Grzegorz Sadowski <grzegorz.sadowski@lakion.com>
*/
final class ConvertPaymentToPaypalExpressActionSpec extends ObjectBehavior
{
function let(
InvoiceNumberGeneratorInterface $invoiceNumberGenerator,
CurrencyConverterInterface $currencyConverter
) {
$this->beConstructedWith($invoiceNumberGenerator, $currencyConverter);
}
function it_is_initializable()
{
$this->shouldHaveType(ConvertPaymentToPaypalExpressAction::class);
}
function it_implements_action_interface()
{
$this->shouldImplement(ActionInterface::class);
}
function it_executes_request(
InvoiceNumberGeneratorInterface $invoiceNumberGenerator,
CurrencyConverterInterface $currencyConverter,
Convert $request,
PaymentInterface $payment,
OrderInterface $order,
OrderItemInterface $orderItem,
ProductVariantInterface $productVariant,
ProductInterface $product
) {
$request->getTo()->willReturn('array');
$payment->getId()->willReturn(19);
$order->getId()->willReturn(92);
$order->getId()->willReturn(92);
$order->getCurrencyCode()->willReturn('PLN');
$order->getTotal()->willReturn(22000);
$order->getItems()->willReturn([$orderItem]);
$order->getAdjustmentsTotalRecursively(AdjustmentInterface::TAX_ADJUSTMENT)->willReturn(0);
$order->getOrderPromotionTotal()->willReturn(0);
$order->getShippingTotal()->willReturn(2000);
$orderItem->getVariant()->willReturn($productVariant);
$orderItem->getDiscountedUnitPrice()->willReturn(20000);
$orderItem->getQuantity()->willReturn(1);
$productVariant->getProduct()->willReturn($product);
$product->getName()->willReturn('Lamborghini Aventador Model');
$request->getSource()->willReturn($payment);
$payment->getOrder()->willReturn($order);
$invoiceNumberGenerator->generate($order, $payment)->willReturn('19-92');
$currencyConverter->convertFromBase(22000, 'PLN')->willReturn(88000);
$currencyConverter->convertFromBase(20000, 'PLN')->willReturn(80000);
$currencyConverter->convertFromBase(2000, 'PLN')->willReturn(8000);
$details = [
'PAYMENTREQUEST_0_INVNUM' => '19-92',
'PAYMENTREQUEST_0_CURRENCYCODE' => 'PLN',
'PAYMENTREQUEST_0_AMT' => 880.00,
'PAYMENTREQUEST_0_ITEMAMT' => 880.00,
'L_PAYMENTREQUEST_0_NAME0' => 'Lamborghini Aventador Model',
'L_PAYMENTREQUEST_0_AMT0' => 800.00,
'L_PAYMENTREQUEST_0_QTY0' => 1,
'L_PAYMENTREQUEST_0_NAME1' => 'Shipping Total',
'L_PAYMENTREQUEST_0_AMT1' => 80.00,
'L_PAYMENTREQUEST_0_QTY1' => 1,
];
$request->setResult($details)->shouldBeCalled();
$this->execute($request);
}
function it_throws_exception_when_source_is_not_a_payment_interface(Convert $request)
{
$request->getSource()->willReturn(null);
$this
->shouldThrow(RequestNotSupportedException::class)
->during('execute', [$request])
;
}
}