首页 > 解决方案 > Sylius:传递给 Stripe 的订单总金额错误

问题描述

我添加了一个新的处理器,允许计算礼品卡的金额。

services:
    app.order_processing.gift_card_processor:
        class: App\OrderProcessing\GiftCardProcessor
        arguments:
            - '@sylius.factory.adjustment'
            - '@translator'
        tags:
            - { name: sylius.order_processor, priority: 5 }

<?php

declare(strict_types=1);

namespace App\OrderProcessing;

use App\Entity\Order\Adjustment;
use App\Entity\Order\Order;
use Sylius\Component\Order\Model\OrderInterface as BaseOrderInterface;
use Sylius\Component\Order\Processor\OrderProcessorInterface;
use Sylius\Component\Resource\Factory\FactoryInterface;
use Symfony\Contracts\Translation\TranslatorInterface;
use Webmozart\Assert\Assert;

final class GiftCardProcessor implements OrderProcessorInterface
{
    private FactoryInterface $adjustmentFactory;

    private TranslatorInterface $translator;

    public function __construct(
        FactoryInterface $adjustmentFactory,
        TranslatorInterface $translator
    ) {
        $this->adjustmentFactory = $adjustmentFactory;
        $this->translator = $translator;
    }

    public function process(BaseOrderInterface $order): void
    {
        /** @var Order $order */
        Assert::isInstanceOf($order, Order::class);

        // Remove all gift card adjustments, we recalculate everything from scratch.
        $order->removeAdjustments(Adjustment::ORDER_GIFT_CARD_ADJUSTMENT);

        foreach ($order->getGiftCardOrders() as $giftCardOrder) {
            $giftCard = $giftCardOrder->getGiftCard();
            $giftCardRemainingAmount = (int) $giftCard->getRemainingAmount() * 100;

            $amount = $giftCardRemainingAmount > $order->getTotal() ? $order->getTotal() : $giftCardRemainingAmount;

            /** @var Adjustment $adjustment */
            $adjustment = $this->adjustmentFactory->createNew();
            $adjustment->setType(Adjustment::ORDER_GIFT_CARD_ADJUSTMENT);
            $adjustment->setAmount(-$amount);
            $adjustment->setLabel($this->translator->trans('gift_card.ui.gift_card'));

            $giftCard->addAdjustment($adjustment);

            $giftCardOrder->setAmount($amount / 100);

            $order->addAdjustment($adjustment);
        }
    }
}

购物车中显示并插入数据库的总订单金额是正确的(屏幕截图 1 和 2)

屏幕截图 1 屏幕截图 2

条带支付时出现BUG,显示金额对应初始金额,不支持礼品卡减免(截图3)

截图 3

标签: symfonystripe-paymentssylius

解决方案


如果您正在使用此 Sylius 插件:flux-se/sylius-payum-stripe-plugin您必须创建代表您的礼品卡装饰的单独优惠券:https ://github.com/FLUX-SE/SyliusPayumStripePlugin/blob/master/src/Provider/DetailsProvider.php新的数组成员creatediscounts就像 Stripe 文档定义它一样:https ://stripe.com/docs/api/checkout/sessions/create#create_checkout_session-discounts

该插件仅处理链接到一个OrderItem或一个的默认 Sylius 调整OrderItemUnit。如果调整是链接到的,Order那么它不会被考虑在内,因为 Stripe 只是将所有的总和line_item作为总数。Stripe 不允许订单项出现负数,这就是为什么优惠券是减少支付总额的唯一方法。

如果您使用以下格式标记优惠券 ID,则这是处理优惠券创建所需的 payum 扩展sprintf('GIFT_CARD_%s', $giftCard->getCode())

<?php

declare(strict_types=1);

namespace App\GiftCard\Payum\Extension;

use FluxSE\PayumStripe\Request\Api\Resource\CreateCoupon;
use FluxSE\PayumStripe\Request\Api\Resource\RetrieveCoupon;
use FluxSE\SyliusPayumStripePlugin\Action\ConvertPaymentAction;
use Payum\Core\Extension\Context;
use Payum\Core\Extension\ExtensionInterface;
use Payum\Core\Request\Convert;
use Stripe\Exception\ApiErrorException;
use Sylius\Component\Core\Model\PaymentInterface;

final class CheckCouponsExtension implements ExtensionInterface
{
    public function onPreExecute(Context $context)
    {
    }

    public function onExecute(Context $context)
    {
    }

    public function onPostExecute(Context $context)
    {
        if ($context->getException()) {
            return;
        }

        if (false === $context->getAction() instanceof ConvertPaymentAction) {
            return;
        }

        /** @var mixed|Convert $request */
        $request = $context->getRequest();
        if (false === $request instanceof Convert) {
            return;
        }

        /** @var mixed|PaymentInterface $payment */
        $payment = $request->getSource();
        if (false === $payment instanceof PaymentInterface) {
            return;
        }

        $order = $payment->getOrder();
        if (null === $order) {
            return;
        }

        $gateway = $context->getGateway();
        foreach ($order->getGiftCardOrders() as $giftCardOrder) {
            $giftCard = $giftCardOrder->getGiftCard();
            $couponId = sprintf('GIFT_CARD_%s', $giftCard->getCode());
            $retrieveCouponRequest = new RetrieveCoupon($couponId);
            try {
                $gateway->execute($retrieveCouponRequest);
            } catch (ApiErrorException $e) {
                $createCouponRequest = new CreateCoupon([
                    'id' => $couponId,
                    "amount_off" => $giftCard->getAmount()/100,
                    "currency" => $order->getCurrencyCode(),
                    "metadata" => [
                        'SYLIUS_GIFTCARD_ID' => $giftCard->getId(),
                        'SYLIUS_GIFTCARD_CODE' => $giftCard->getCode(),
                    ],
                    "name" => sprintf("Gift card #%d", $giftCard->getId()),
                ]);
                $gateway->execute($createCouponRequest);
            }
        }
    }
}

这是服务声明:

services:
  App\GiftCard\Payum\Extension\CheckCouponsExtension:
    public: true
    tags:
      - name: payum.extension
        alias: app.extension.check_coupons
        factory: stripe_checkout_session

推荐阅读