Wie kann ich die Stripe Live Tax API in Shopware 6 integrieren?
Für E-Commerce-Websites ist eine Live-Berechnung des Steuersatzes erforderlich. Um die Einhaltung dynamischer Steuersätze sicherzustellen, das Kundenerlebnis durch genaue Kostentransparenz zu verbessern und Prozesse für effiziente globale Abläufe zu automatisieren.
Diese Funktion garantiert fehlerfreie Steuerberechnungen in Echtzeit und ermöglicht nahtlose Transaktionen und präzise Finanzberichte.
Schritte zur Live-Steuerberechnung mit der Stripe Lve Tax API
- Sammeln Sie den API-Schlüssel vom Stripe-Entwicklerkonto.
- Melden Sie sich beim Stripe-Dashboard an
- Wählen Sie in der Kopfzeile das Menü „Entwickler“.
- Wählen Sie die Registerkarte „API-Schlüssel“ und erstellen Sie einen Schlüssel
- Erstellen Sie einen neuen Abonnenten mit dem Ereignis CartChangedEventSubscriber
Registrieren Sie den Abonnenten in der Dienstdatei
/custom/plugins/HatslogicLiveTax/src/Resources/config/services.xml
1 2 3 4 5 | <service id="HatslogicLiveTaxSubscriberCartChangedEventSubscriber"> <argument type="service" id="request_stack"/> <argument type="service" id="HatslogicLiveTaxServiceCustomTax"/> <tag name="kernel.event_subscriber"/> </service> |
Das Gleiche müssen wir auch für die folgenden Abonnenten tun
- CustomerAddressWrittenSubscriber
- CustomerSetDefaultShippingAddressEventSubscriber
- CustomerLoginEventSubscriber
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 | <service id="HatslogicLiveTaxSubscriberCustomerAddressWrittenSubscriber"> <argument type="service" id="customer_address.repository"/> <argument type="service" id="request_stack"/> <argument type="service" id="DoctrineDBALConnection"/> <tag name="kernel.event_subscriber"/> </service> <service id="HatslogicLiveTaxSubscriberCustomerSetDefaultShippingAddressEventSubscriber"> <argument type="service" id="request_stack"/> <argument type="service" id="HatslogicLiveTaxServiceCustomTax"/> <argument type="service" id="ShopwareCoreCheckoutCartSalesChannelCartService"/> <argument type="service" id="customer_address.repository"/> <tag name="kernel.event_subscriber"/> </service> <service id="HatslogicLiveTaxSubscriberCustomerLoginEventSubscriber"> <argument type="service" id="request_stack"/> <argument type="service" id="HatslogicLiveTaxServiceCustomTax"/> <argument type="service" id="ShopwareCoreCheckoutCartSalesChannelCartService"/> <tag name="kernel.event_subscriber"/> </service> |
/custom/plugins/HatslogicLiveTax/src/Subscriber/CartChangedEventSubscriber.php
- 1234567891011121314151617181920212223242526272829303132333435363738<?php declare(strict_types=1);namespace HatslogicSubscriber;use HatslogicServiceCustomTax;use SymfonyComponentEventDispatcherEventSubscriberInterface;use ShopwareCoreCheckoutCartEventCartChangedEvent;use SymfonyComponentHttpFoundationRequestStack;class CartChangedEventSubscriber implements EventSubscriberInterface{private $requestStack;private $customTax;public function __construct(RequestStack $requestStack,CustomTax $customTax){$this->requestStack = $requestStack;$this->customTax = $customTax;}public static function getSubscribedEvents(){return [CartChangedEvent::class => 'onEvent'];}public function onEvent(CartChangedEvent $event){$salesChannelContext = $event->getContext();$context = $salesChannelContext->getContext();$cart = $event->getCart();$customer = $salesChannelContext->getCustomer();$shippingLocation = $salesChannelContext->getShippingLocation();if($customer and $cart->getLineItems()->count()){$products = $cart->getLineItems();$taxData = $this->customTax->getLineitemTax( $products, $shippingLocation->getAddress(), $context );$this->requestStack->getSession()->set('HatslogicTaxData', $taxData);}}}
1 2 3 4 5 6 7 | <service id="HatslogicLiveTaxServiceCustomTax"> <argument type="service" id="ShopwareCoreSystemSystemConfigSystemConfigService"/> <argument type="service" id="ShopwareCoreSystemSalesChannelContextSalesChannelContextService"/> <argument type="service" id="order.repository"/> <argument type="service" id="product.repository"/> <argument type="service" id="request_stack"/> </service> |
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 | <?php namespace HatslogicLiveTaxService; use GuzzleHttpClient as HttpClient; use ShopwareCoreCheckoutCartCart; use ShopwareCoreFrameworkContext; use ShopwareCoreFrameworkDataAbstractionLayerSearchCriteria; use ShopwareCoreFrameworkDataAbstractionLayerSearchSortingFieldSorting; use ShopwareCoreSystemSalesChannelSalesChannelContext; use ShopwareCoreSystemSystemConfigSystemConfigService; use ShopwareCoreSystemSalesChannelContextSalesChannelContextServiceInterface; use SymfonyComponentHttpFoundationRequestStack; class CustomTax { private $httpClient; private $orderRepository; private $productRepository; private $systemConfigService; private $contextService; private $requestStack; public function __construct( SystemConfigService $systemConfigService, SalesChannelContextServiceInterface $contextService, $orderRepository, $productRepository, RequestStack $requestStack ) { $this->httpClient = new HttpClient(); $this->systemConfigService = $systemConfigService; $this->contextService = $contextService; $this->orderRepository = $orderRepository; $this->productRepository = $productRepository; $this->requestStack = $requestStack; } private function getLastOrder() { $criteria = new Criteria(); $criteria->setLimit(1); $criteria->addSorting(new FieldSorting('createdAt', FieldSorting::DESCENDING)); $order = $this->orderRepository->search($criteria, Context::createDefaultContext())->first(); return $order; } public function getLineItemTax($lineItems, $shippingLocation, $context) { $zipCodeExplode = explode('-', $shippingLocation->getZipcode()); $zipCode = $zipCodeExplode[0] ?? ''; $stripeSecretKey = $this->systemConfigService->get('HatslogicLiveTax.config.hatsStripeSecretKey'); $url = 'https://api.stripe.com/v1/tax/calculations'; $shipToState = $shippingLocation->getCountryState(); $body = [ 'customer_details'=> [ 'address' => [ 'line1' => (string) $shippingLocation->getStreet(), 'city' => (string) $shippingLocation->getCity(), 'state' => (string) $shipToState, 'postal_code' => (string) $zipCode, 'country' => 'US', ] ], "address_source" => 'shipping' ]; $i = 1; foreach ($lineItems as $lineItem) { if ($lineItem->getType() == 'HatslogicLiveTax_tax') { continue; } $product = $this->getProductById($lineItem->getId(), $context); if(!$product) |
Wir holen diesen Wert wie folgt ab
$stripeSecretKey = $this->systemConfigService->get(‘HatslogicLiveTax.config.hatsStripeSecretKey’);
Durch den Aufruf der Funktion getLineitemTax() erhalten wir den aktuellen Steuerbetrag im Warenkorb.
Nun müssen wir die Steuerberechnungen anhand dieses Wertes ändern.
Dazu müssen wir den Warenkorbprozessor verwenden und die bestehenden Steuerberechnungen des Warenkorbs außer Kraft setzen
Registrieren Sie den Warenkorbprozessor in der Servicedatei
/custom/plugins/HatslogicLiveTax/src/Resources/config/services.xml
1 2 3 4 5 6 7 | <service id="HatslogicLiveTaxCoreCheckoutCustomCartProcessor"> <argument type="service" id="HatslogicLiveTaxCoreCheckoutCartPriceAbsolutePriceCalculator"/> <argument type="service" id="request_stack"/> <argument type="service" id="HatslogicLiveTaxServiceCustomTax"/> <argument type="service" id="logger"/> <tag name="shopware.cart.processor" priority="5000"/> </service> |
Erstellen Sie die Datei CustomCartProcessor in folgendem Pfad
/custom/plugins/HatslogicLiveTax/src/Core/Checkout/CustomCartProcessor.php
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 | <?php declare(strict_types=1); namespace HatslogicLiveTaxCoreCheckout; use HatslogicLiveTaxServiceCustomTax; use ShopwareCoreCheckoutCartCart; use ShopwareCoreCheckoutCartCartBehavior; use ShopwareCoreCheckoutCartCartProcessorInterface; use ShopwareCoreCheckoutCartLineItemCartDataCollection; use ShopwareCoreCheckoutCartLineItemLineItem; use ShopwareCoreCheckoutCartLineItemLineItemCollection; use HatslogicLiveTaxCoreCheckoutCartPriceAbsolutePriceCalculator; use ShopwareCoreCheckoutCartPriceStructAbsolutePriceDefinition; use ShopwareCoreCheckoutCartRuleLineItemRule; use ShopwareCoreFrameworkStructArrayStruct; use ShopwareCoreFrameworkUuidUuid; use ShopwareCoreSystemSalesChannelSalesChannelContext; use SymfonyComponentHttpFoundationRequestStack; use PsrLogLoggerInterface; use ShopwareCoreCheckoutCartTaxStructCalculatedTaxCollection; use ShopwareCoreCheckoutCartTaxStructCalculatedTax; class CustomCartProcessor implements CartProcessorInterface { private $calculator; private $requestStack; private $customTax; private LoggerInterface $logger; public function __construct(AbsolutePriceCalculator $calculator, $requestStack, $customTax, $logger ) { $this->calculator = $calculator; $this->requestStack = $requestStack; $this->customTax = $customTax; $this->logger = $logger; } public function process(CartDataCollection $data, Cart $original, Cart $toCalculate, SalesChannelContext $context, CartBehavior $behavior): void { $customer = $context->getCustomer(); if(!$customer) { $this->requestStack->getSession()->remove('HatslogicTaxData'); return; } $products = $toCalculate->getLineItems(); if ($products->count() === 0) { return; } $taxData = $this->requestStack->getSession()->get('HatslogicTaxData'); if(!$taxData) { return; } if( isset( $taxData['error comments'] ) ) { $this->logger->info($taxData['error comments']); $this->requestStack->getSession()->set('Hatslogic_has_error', true); return; } else { $this->requestStack->getSession()->remove('Hatslogic_has_error'); } $taxTotal = 0; $taxesDetails = []; $taxesLineTotal = []; foreach ($taxData['line_items']['data'] as $taxDatum){ foreach( $taxDatum['tax_breakdown'] as $taxBreakDowns) { if($taxBreakDowns['amount'] > 0) { $slug = strtolower(str_replace(' ','_',$taxBreakDowns['tax_rate_details']['display_name'])); if(isset($taxesLineTotal["total_".$slug])) { $taxesLineTotal["total_".$slug] += $taxBreakDowns['amount']; } else { $taxesLineTotal["total_".$slug] = $taxBreakDowns['amount']; } $taxTotal +=$taxBreakDowns['tax_rate_details']['percentage_decimal']; $taxesDetails["tax_".$slug] = array( 'rate'=>$taxBreakDowns['tax_rate_details']['percentage_decimal'], 'amount'=>$taxesLineTotal["total_".$slug], 'label'=>$taxBreakDowns['tax_rate_details']['display_name'] ); } } } $body['data'] = $taxData; $body['HatslogicTax'] = $taxesDetails; if($taxTotal) { $uuid = Uuid::randomHex(); $taxLineItem = $this->createLineItem($uuid); $definition = new AbsolutePriceDefinition( $taxTotal, new LineItemRule(LineItemRule::OPERATOR_EQ, $products->getKeys()) ); $taxLineItem->setPriceDefinition($definition); $taxLineItem->setPrice( $this->calculator->calculate($definition->getPrice(), $products->getPrices(), $context) ); $taxLineItem->setPayload($body); $toCalculate->add($taxLineItem); } } private function createLineItem(string $id): LineItem { $taxLineItem = new LineItem($id, 'Hatslogic_tax', null, 1); $taxLineItem->setLabel('Hatslogic Tax'); $taxLineItem->setGood(false); $taxLineItem->setStackable(false); $taxLineItem->setRemovable(false); return $taxLineItem; } } |
Hier aktualisieren wir die Steuerberechnungen. Wenn der Einkaufswagen zusätzliche Steuern enthält, werden diese auch als separate Steuerposition hinzugefügt.
Wir müssen Änderungen an der Rechnungsdatei und den Zusammenfassungsseiten der Bestellung vornehmen.
Für die Änderungen am Schaufenster müssen wir die folgenden Twig-Vorlagen aktualisieren.
/custom/plugins/HatslogicLiveTax/src/Resources/views/storefront/page/checkout/checkout-item.html.twig
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 | {% sw_extends '@Storefront/storefront/page/checkout/checkout-item.html.twig' %} {% block page_checkout_item_container %} {% if lineItem.type !== 'Hatslogic_tax' %} {{ parent() }} {% endif %} {% endblock %} /custom/plugins/HatslogicLiveTax/src/Resources/views/storefront/page/checkout/summary/summary-position.html.twig {% sw_extends '@Storefront/storefront/page/checkout/summary/summary-position.html.twig' %} {% block page_checkout_summary_position_value %} {% set lineItem = page.order.lineItems.filterByType('Hatslogic_tax')%} {% set cartData = true %} {% if lineItem %} {% set cartData = false %} {% else %} {% set lineItem = page.cart.lineItems.filterFlatByType('Hatslogic_tax') %} {% endif %} {% if lineItem %} {% if cartData %} {% set lineItem = lineItem[0] %} {% else %} {% set lineItem = lineItem.first() %} {% endif %} {% set hatslogicLiveTax = lineItem.getPayload() %} {% set taxTotal = 0 %} {% for tax in hatslogicLiveTax.HatslogicTax %} {% if (tax.rate > 0) %} {% set taxTotal = (taxTotal + tax.amount) %} {% endif %} {% endfor %} <dd class="col-5 checkout-aside-summary-value"> {{ (summary.price.positionPrice - taxTotal)|currency }}{{ "general.star"|trans|sw_sanitize }} </dd> {% else %} {{ parent() }} {% endif %} {% endblock %} |
Dies sind die einfachen Schritte, die erforderlich sind, um eine Stripe-Live-Steuerberechnung mit der Shopware 6-Kasse einzurichten.
Recent help desk articles
Grüße! Ich bin Aneesh Sreedharan, CEO von 2Hats Logic Solutions. Bei 2Hats Logic Solutions widmen wir uns der Bereitstellung von technischem Fachwissen und der Lösung Ihrer Probleme in der Welt der Technologie. Unsere Blog-Seite dient als Ressource, in der wir Einblicke und Erfahrungen teilen und wertvolle Perspektiven auf Ihre Fragen bieten.