Sylius:传递给 Stripe 的总订单金额错误
Sylius : Wrong total order amount passed to 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)。
SCREENSHOT 1
SCREENSHOT 2
stripe支付出现bug,显示金额为初始金额,不支持礼品卡减值(截图3)
SCREENSHOT 3
如果您使用此 Sylius 插件:flux-se/sylius-payum-stripe-plugin
您必须创建代表您的礼品卡装饰的个人优惠券:https://github.com/FLUX-SE/SyliusPayumStripePlugin/blob/master/src/Provider/DetailsProvider.php the new array member to create is the discounts
like the Stripe doc is defining it : https://stripe.com/docs/api/checkout/sessions/create#create_checkout_session-discounts
该插件仅处理链接到 OrderItem
或 OrderItemUnit
的默认 Sylius 调整。如果调整链接在 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
我添加了一个可以计算礼品卡金额的新处理器。
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)。
SCREENSHOT 1 SCREENSHOT 2
stripe支付出现bug,显示金额为初始金额,不支持礼品卡减值(截图3)
SCREENSHOT 3
如果您使用此 Sylius 插件:flux-se/sylius-payum-stripe-plugin
您必须创建代表您的礼品卡装饰的个人优惠券:https://github.com/FLUX-SE/SyliusPayumStripePlugin/blob/master/src/Provider/DetailsProvider.php the new array member to create is the discounts
like the Stripe doc is defining it : https://stripe.com/docs/api/checkout/sessions/create#create_checkout_session-discounts
该插件仅处理链接到 OrderItem
或 OrderItemUnit
的默认 Sylius 调整。如果调整链接在 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