diff --git a/.github/scripts/resolve-dockware-tag.py b/.github/scripts/resolve-dockware-tag.py new file mode 100755 index 00000000..e6724ed8 --- /dev/null +++ b/.github/scripts/resolve-dockware-tag.py @@ -0,0 +1,57 @@ +#!/usr/bin/env python3 +"""Resolve the newest dockware/shopware image tag for a Shopware series. + +The pinned-version problem this solves: when Shopware ships a patch, a +hardcoded matrix keeps testing the previous one and the new release goes +unverified until somebody notices. + +dockware publishes a plain multi-arch tag (6.7.13.0) plus per-arch tags +(6.7.13.0-amd64). A fresh release often appears as -amd64 first and only +gains its manifest hours later, so prefer the plain tag and fall back to +-amd64 rather than skipping a release that is already testable. +""" +import json +import re +import sys +import urllib.request + +REGISTRY = 'https://hub.docker.com/v2/repositories/dockware/shopware/tags' +MAX_PAGES = 5 + + +def fetch_tags(): + names, url = [], f'{REGISTRY}?page_size=100' + for _ in range(MAX_PAGES): + with urllib.request.urlopen(url, timeout=30) as res: + payload = json.load(res) + names.extend(t['name'] for t in payload.get('results', [])) + url = payload.get('next') + if not url: + break + return names + + +def resolve(series, names): + pattern = re.compile(r'^' + re.escape(series) + r'\.(\d+)\.(\d+)(-amd64)?$') + versions = {} + for name in names: + match = pattern.match(name) + if not match: + continue + key = (int(match.group(1)), int(match.group(2))) + versions.setdefault(key, set()).add(name) + + if not versions: + raise SystemExit(f'no dockware tag found for series {series}') + + newest = max(versions) + candidates = versions[newest] + plain = f'{series}.{newest[0]}.{newest[1]}' + # Plain tag is multi-arch; the -amd64 fallback still runs on GitHub runners. + return plain if plain in candidates else f'{plain}-amd64' + + +if __name__ == '__main__': + if len(sys.argv) != 2: + raise SystemExit('usage: resolve-dockware-tag.py ') + print(resolve(sys.argv[1], fetch_tags())) diff --git a/.github/workflows/e2e-nightly.yml b/.github/workflows/e2e-nightly.yml new file mode 100644 index 00000000..2caa880d --- /dev/null +++ b/.github/workflows/e2e-nightly.yml @@ -0,0 +1,42 @@ +name: E2E Nightly + +# Walks the whole range the plugin claims in composer.json (>=6.5.8.0 <6.8). +# This is what turns that claim into something verified rather than asserted: +# when Shopware ships a patch that moves a template or renames a block, this +# goes red the next morning instead of surfacing in a support ticket. +on: + schedule: + - cron: '15 2 * * *' + workflow_dispatch: + +jobs: + # The newest patch of each supported series is resolved at run time, so a + # fresh Shopware release is covered the next night with no edit here. + resolve: + runs-on: ubuntu-latest + outputs: + matrix: ${{ steps.build.outputs.matrix }} + steps: + - uses: actions/checkout@v4 + - id: build + run: | + set -e + latest_67=$(python3 .github/scripts/resolve-dockware-tag.py 6.7) + latest_66=$(python3 .github/scripts/resolve-dockware-tag.py 6.6) # extended support until 2028-02-28 + latest_65=$(python3 .github/scripts/resolve-dockware-tag.py 6.5) # extended support until 2027-02-28, our floor + # Two older 6.7 patches stay pinned: the resolver only yields the + # newest per series, and drift often shows up one patch back. + matrix=$(python3 -c 'import json,sys; print(json.dumps(sys.argv[1:]))' \ + "$latest_67" '6.7.12.2' '6.7.11.1' "$latest_66" "$latest_65") + echo "matrix: $matrix" + echo "matrix=$matrix" >> "$GITHUB_OUTPUT" + + matrix: + needs: resolve + strategy: + fail-fast: false + matrix: + shopware: ${{ fromJson(needs.resolve.outputs.matrix) }} + uses: ./.github/workflows/e2e-shopware.yml + with: + shopware: ${{ matrix.shopware }} diff --git a/.github/workflows/e2e-shopware.yml b/.github/workflows/e2e-shopware.yml new file mode 100644 index 00000000..fcd57c4d --- /dev/null +++ b/.github/workflows/e2e-shopware.yml @@ -0,0 +1,176 @@ +name: E2E (reusable) + +# Runs the shop-level regression suite against one real Shopware version. +# Called by e2e.yml (per PR, latest only) and e2e-nightly.yml (full matrix). +on: + workflow_call: + inputs: + shopware: + description: 'Shopware version, must exist as a dockware/shopware tag' + required: true + type: string + +jobs: + e2e: + name: Shopware ${{ inputs.shopware }} + runs-on: ubuntu-latest + timeout-minutes: 40 + + steps: + - name: Checkout plugin + uses: actions/checkout@v4 + with: + path: plugin + + - name: Start Shopware ${{ inputs.shopware }} + run: | + docker run -d --rm --name shop -p 80:80 \ + -e SHOPWARE_SKIP_BUNDLE_DUMP=1 \ + dockware/shopware:${{ inputs.shopware }} + + # -p 80:80 means the browser sends Host: localhost, which matches the + # sales channel domain dockware ships. Do not remap the port without also + # updating sales_channel_domain, or Shopware answers 400. + - name: Wait for the shop to answer + run: | + # Any HTTP status means the web server is answering. Do not gate on + # 200: a domain mismatch answers 400 on 6.7 and 500 on 6.5, and + # gating on specific codes made 6.5 look like it never booted. + for i in $(seq 1 90); do + code=$(curl -s -o /dev/null -w '%{http_code}' --max-time 10 http://localhost/ || true) + if [ -n "$code" ] && [ "$code" != "000" ]; then echo "shop up (HTTP $code)"; exit 0; fi + sleep 5 + done + echo "::error::shop did not become ready"; docker logs shop | tail -50; exit 1 + + - name: Copy plugin into the container + run: | + docker exec shop mkdir -p /var/www/html/custom/plugins + docker cp plugin shop:/var/www/html/custom/plugins/BuckarooPayments + docker exec -u root shop chown -R www-data:www-data /var/www/html/custom/plugins + + # Shopware 6.7.13 pins mcp/sdk ^0.6.0, which carries CVE-2026-53965 with no + # in-range fix, so Composer 2.10+ refuses to resolve it. + # Best-effort on purpose: the dockware images currently ship Composer + # 2.2.x, which predates advisory blocking and rejects the policy.* key + # outright. Keep the step so newer images stay unblocked. + - name: Allow the known mcp/sdk advisory (best effort) + run: | + docker exec -u www-data -w /var/www/html shop \ + composer config policy.advisories.ignore-id.CVE-2026-53965 \ + "no in-range fix; MCP server not enabled" \ + || echo "composer in this image predates advisory blocking - nothing to ignore" + + - name: Install plugin via composer path repository + run: | + docker exec -u www-data -w /var/www/html shop \ + composer config repositories.buckaroo path 'custom/plugins/BuckarooPayments' + docker exec -u www-data -w /var/www/html shop \ + composer require buckaroo/shopware6:'*' --no-interaction --no-scripts + + - name: Activate plugin and build assets + run: | + docker exec -u www-data -w /var/www/html shop bin/console plugin:refresh + docker exec -u www-data -w /var/www/html shop bin/console plugin:install --activate BuckarooPayments + docker exec -u www-data -w /var/www/html shop bin/console assets:install + docker exec -u www-data -w /var/www/html shop bin/console theme:compile + docker exec -u www-data -w /var/www/html shop bin/console cache:clear + + # A fresh install renders zero buckaroo methods on the confirm page, for + # two independent reasons. Both are environment setup, not plugin bugs, + # and both silently reduced the buckaroo assertions to an empty set - a + # page-wide [class*="bk-"] check stayed green here while nothing buckaroo + # rendered at all, because the override tags Shopware's own methods with + # a bare `bk-` too. + # + # mysql runs as root over the socket: dockware's default exec user gets + # EACCES on /var/run/mysqld/mysqld.sock, and -u www-data does too. + - name: Make the buckaroo methods selectable in the storefront + run: | + # 1. plugin:install --activate marks the methods active but never + # writes sales_channel_payment_method, and Shopware only offers + # methods attached to the sales channel. + docker exec -i -u root shop mysql -uroot -proot shopware <<'SQL' + INSERT IGNORE INTO sales_channel_payment_method (sales_channel_id, payment_method_id) + SELECT sc.id, pm.id + FROM sales_channel sc + CROSS JOIN payment_method pm + JOIN plugin p ON pm.plugin_id = p.id + WHERE p.name = 'BuckarooPayments' AND pm.active = 1; + SQL + + # 2. CheckoutConfirmTemplateSubscriber::hideNotEnabledPaymentMethods + # drops every method whose Enabled setting is falsy, + # and a fresh install has no such settings at all. + docker exec -i -u root shop mysql -uroot -proot shopware <<'SQL' + INSERT INTO system_config (id, configuration_key, configuration_value, sales_channel_id, created_at) + SELECT UNHEX(REPLACE(UUID(), '-', '')), + CONCAT('BuckarooPayments.config.', bkey, 'Enabled'), + '{"_value": true}', NULL, NOW() + FROM ( + SELECT DISTINCT JSON_UNQUOTE(JSON_EXTRACT(pmt.custom_fields, '$.buckaroo_key')) AS bkey + FROM payment_method pm + JOIN plugin p ON pm.plugin_id = p.id + JOIN payment_method_translation pmt ON pmt.payment_method_id = pm.id + WHERE p.name = 'BuckarooPayments' + AND JSON_EXTRACT(pmt.custom_fields, '$.buckaroo_key') IS NOT NULL + ) keys_found + WHERE bkey NOT IN ( + SELECT REPLACE(REPLACE(configuration_key, 'BuckarooPayments.config.', ''), 'Enabled', '') + FROM system_config WHERE configuration_key LIKE 'BuckarooPayments.config.%Enabled' + ); + SQL + + attached=$(docker exec -u root shop mysql -uroot -proot shopware -N -e "SELECT COUNT(*) FROM sales_channel_payment_method scpm JOIN payment_method pm ON scpm.payment_method_id = pm.id JOIN plugin p ON pm.plugin_id = p.id WHERE p.name = 'BuckarooPayments';") + enabled=$(docker exec -u root shop mysql -uroot -proot shopware -N -e "SELECT COUNT(*) FROM system_config WHERE configuration_key LIKE 'BuckarooPayments.config.%Enabled';") + echo "buckaroo methods attached to sales channels: $attached" + echo "buckaroo methods enabled in config: $enabled" + # Fail here rather than letting the suite report a confusing template + # failure when the real problem is an unconfigured shop. + if [ "$attached" -eq 0 ] || [ "$enabled" -eq 0 ]; then + echo "::error::buckaroo methods could not be made selectable (attached=$attached enabled=$enabled)" + exit 1 + fi + docker exec -u www-data -w /var/www/html shop bin/console cache:clear + + # First hit on a cold shop pays for cache + theme generation and can take + # minutes on 6.5/6.6. Warm it here so the suite's own timeouts are not + # measuring container start-up. + - name: Warm the storefront + run: | + for path in / /account/register /checkout/cart; do + curl -s -o /dev/null -w "warmed $path -> %{http_code}\n" --max-time 180 "http://localhost$path" || true + done + + - name: Setup Node + uses: actions/setup-node@v4 + with: + node-version: '22' + + - name: Install Playwright + working-directory: plugin/tests/e2e + run: | + npm ci || npm install + npx playwright install chromium --with-deps + + - name: Run E2E suite + working-directory: plugin/tests/e2e + env: + SHOP_BASE_URL: http://localhost + CI: 'true' + run: npx playwright test + + - name: Shop logs on failure + if: failure() + run: docker logs shop | tail -100 + + - name: Upload Playwright report + if: always() + uses: actions/upload-artifact@v4 + with: + name: playwright-report-${{ inputs.shopware }} + path: | + plugin/tests/e2e/playwright-report + plugin/tests/e2e/test-results + retention-days: 7 + if-no-files-found: ignore diff --git a/.github/workflows/e2e.yml b/.github/workflows/e2e.yml new file mode 100644 index 00000000..2edd1f4c --- /dev/null +++ b/.github/workflows/e2e.yml @@ -0,0 +1,35 @@ +name: E2E + +# Fast gate: only the newest supported Shopware. The full range runs nightly. +on: + pull_request: + branches: [ main, master, develop ] + workflow_dispatch: + inputs: + shopware: + description: 'Shopware version to test (blank = newest 6.7 on dockware)' + required: false + +jobs: + # The version is resolved at run time, not pinned. A pinned default meant a + # new Shopware patch went untested until somebody edited this file. + resolve: + runs-on: ubuntu-latest + outputs: + shopware: ${{ steps.pick.outputs.tag }} + steps: + - uses: actions/checkout@v4 + - id: pick + run: | + tag="${{ github.event.inputs.shopware }}" + if [ -z "$tag" ]; then + tag=$(python3 .github/scripts/resolve-dockware-tag.py 6.7) + fi + echo "resolved Shopware image tag: $tag" + echo "tag=$tag" >> "$GITHUB_OUTPUT" + + latest: + needs: resolve + uses: ./.github/workflows/e2e-shopware.yml + with: + shopware: ${{ needs.resolve.outputs.shopware }} diff --git a/.github/workflows/extension-verifier.yml b/.github/workflows/extension-verifier.yml new file mode 100644 index 00000000..13842029 --- /dev/null +++ b/.github/workflows/extension-verifier.yml @@ -0,0 +1,24 @@ +name: Extension Verifier + +# Runs the same static validation the Shopware Store applies on upload, so +# store-blocking findings surface here instead of at submission time. +on: + pull_request: + branches: [ main, master, develop ] + workflow_dispatch: + +jobs: + validate: + name: shopware-cli extension validate + runs-on: ubuntu-latest + # Non-blocking until the existing baseline of findings is cleared, then + # remove this line so it gates like the Store does. + continue-on-error: true + steps: + - uses: actions/checkout@v4 + + - name: Setup shopware-cli + uses: shopware/shopware-cli-action@v1 + + - name: Validate extension + run: shopware-cli extension validate . diff --git a/.gitignore b/.gitignore index dced0b56..ac330cf3 100644 --- a/.gitignore +++ b/.gitignore @@ -4,4 +4,9 @@ vendor/ composer.lock node_modules/ -src/Resources/app/administration/.tmp/ \ No newline at end of file +src/Resources/app/administration/.tmp/ +# E2E (Playwright) generated output +tests/e2e/test-results/ +tests/e2e/playwright-report/ +tests/e2e/playwright/.cache/ +.phpunit.result.cache diff --git a/CHANGELOG.md b/CHANGELOG.md index c06c13e1..3dfd173b 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -448,4 +448,25 @@ Compatible from Shopware 6.5.0 up to 6.5.6.1 - BTI-901 Add support for Shopware 6.7.9.1 & 6.6.10.16 - BTI-776 Add support for native refunds. -- BTI-906 Rest API support for the “Capture on shipment” setting for Klarna (MoR). \ No newline at end of file +- BTI-906 Rest API support for the “Capture on shipment” setting for Klarna (MoR). + +# 3.5.0 + +- BTI-1391 Add support for Shopware 6.7.13.1 & 6.6.10.23. +- BTI-1374 Added support for Shopware 6.7.13. +- BTI-1230 Added support for Shopware 6.7.12. +- BTI-1149 Added a general language setting for the payment gateway, so the checkout language can be set centrally instead of per payment method. +- BTI-1060 Added sandbox environment support for PayPal Express. +- BTI-1133 Added Apple Pay support for all web browsers instead of Safari only. +- BTI-1134 Added support for Klarna (MoR) cancellations triggered from Shopware. +- BTI-1176 Removed the optional customer fields for Billink in the checkout, reducing the number of steps for the consumer. +- BTI-1258 Improved the design of the iDEAL | Wero Fast Checkout button so it matches the rest of the storefront. +- BTI-1384 Add automated compatibility testing against Shopware versions. +- BTI-1288 Updated the README.md file. +- BTI-1340 We’ve removed the payment method GoSettle (discontinued). +- BTI-970 Fixed Apple Pay not being visible in the checkout for a specific merchant configuration. +- BTI-1046 Fixed Credit Card Hosted Fields not being editable during checkout on Shopware 6.5. +- BTI-1069 Fixed the culture in the transaction request always being sent as en-GB instead of the actual checkout language. +- BTI-1256 Fixed inconsistent express checkout button heights across the storefront pages. +- BTI-1257 Fixed the Apple Pay express button always being displayed on the checkout page, even when it should be hidden. +- BTI-1365 Fixed the Auto Capture and Capture on Shipment settings causing incorrect capture and refund handling for KlarnaKP. \ No newline at end of file diff --git a/README.md b/README.md index 9d2c34c3..04ac0c33 100644 --- a/README.md +++ b/README.md @@ -1,44 +1,65 @@

- + + Buckaroo — Payments for Shopware 6 + +

+ +

Buckaroo for Shopware 6

+ + +

+ Latest release + Documentation + Shopware Store +

+ +

+ About · + Requirements · + Installation · + Upgrade · + Configuration · + Payment methods · + Support · + Contribute

-# Buckaroo Shopware 6 Payments Plugin -[![Latest release](https://badgen.net/github/release/buckaroo-it/Shopware_6)](https://github.com/buckaroo-it/Shopware_6/releases) - -### Index -- [About](#about) -- [Requirements](#requirements) -- [Installation](#installation) -- [Upgrade](#upgrade) -- [Configuration](#configuration) -- [Versioning](#versioning) -- [Additional information](#additional-information) --- -### About +## About -Shopware is a modular online shop system developed in Germany since 2004. It is available both as open source software and in commercial editions. +Shopware is a modular online shop system developed in Germany since 2004, available both as open source software and in commercial editions. -The Buckaroo Payments Plugin ([Dutch](https://support.buckaroo.nl/categorieen/plugins/shopware-6) or [English](https://support.buckaroo.eu/categories/plugins)) for Shopware 6 enables a ready-to-sell payment gateway. You can choose from popular online payment methods in The Netherlands, Belgium, France, Germany and globally. -Start accepting payments within a few minutes. +The Buckaroo plugin for Shopware 6 connects your store to the Buckaroo payment gateway, so you can start accepting payments within minutes. Buckaroo is a Dutch Payment Service Provider and a certified Shopware Technology Partner. -### Requirements +Card payments run through Hosted Fields, which keeps the card entry inside your own checkout instead of redirecting the customer away. -To use the Buckaroo plugin, please be aware of the following minimum requirements: -- A Buckaroo account ([Dutch](https://www.buckaroo.nl/start) or [English](https://www.buckaroo.eu/solutions/request-form)) -- Shopware 6.5.0 up to 6.7.6.0 -- PHP 8.2 or higher +[Full plugin documentation on docs.buckaroo.io](https://docs.buckaroo.io/docs/shopware-6) -> **No administration rebuild required.** The plugin ships pre-built administration assets for all supported Shopware versions (6.6 and 6.7+). After installing or updating the plugin you do **not** need to run `bin/build-administration.sh` or any other build command. +--- -### Installation +## Requirements -We recommend you to install the Buckaroo Shopware 6 Payments plugin with composer. It is easy to install, update and maintain. +| Requirement | Supported versions | +|---|---| +| Shopware | 6.5.8.0 up to 6.7.x | +| PHP | 8.2 or higher | +| Composer | 2.x | -**Run the following commands:** +You also need a Buckaroo account. Don't have one yet? [Request an account](https://www.buckaroo.nl/start). -``` -cd S6_INSTALLATION_ROOT +> [!NOTE] +> No administration rebuild is required. The plugin ships pre-built administration assets for all supported Shopware versions, so you do not need to run `bin/build-administration.sh` or any other build command after installing or updating. + +--- + +## Installation + +We recommend installing the plugin with Composer. It is the easiest way to install, update and maintain. + +Run the following commands from your Shopware 6 root folder: + +```bash composer require buckaroo/shopware6 ln -s ../../vendor/buckaroo/shopware6 custom/plugins/BuckarooPayments bin/console plugin:refresh @@ -46,41 +67,105 @@ bin/console plugin:install --activate BuckarooPayments bin/console cache:clear ``` -### Upgrade +
+Installing from the Shopware Store -**You can also upgrade/update the Buckaroo plugin with composer. To do this, please run the following commands:** +You can also install the plugin without Composer: -``` +1. Sign in to your Shopware 6 administration. +2. Go to **Extensions → Store** and search for Buckaroo. +3. Install the extension and activate it. + +
+ +--- + +## Upgrade + +```bash composer update buckaroo/shopware6 bin/console plugin:update BuckarooPayments bin/console cache:clear ``` -> No administration rebuild is needed after upgrading. The plugin automatically uses the correct pre-built assets for your Shopware version. +> [!TIP] +> Always test an upgrade on a staging environment first and check the [release notes](https://github.com/buckaroo-it/Shopware6/releases) for breaking changes. + +--- -### Configuration +## Configuration -For the configuration of the plugin, please refer to our [Dutch](https://support.buckaroo.nl/categorieen/plugins/shopware-6) or [English](https://support.buckaroo.eu/categories/plugins) support website. -You will find all the necessary information there. But if you still have some unanswered questions, then please contact our [technical support department](mailto:support@buckaroo.nl). +Sign in to your Shopware 6 administration and go to **Extensions → My extensions**. Find the Buckaroo extension, make sure it is active, and press **Configure**. -### Contribute +You will need your **Store key** and **Secret key**, which you can find under [API credentials in Buckaroo Plaza](https://plaza.buckaroo.nl/Configuration/Merchant/ApiKeys). The Store key is unique per store, the Secret key applies to your whole account. -We really appreciate it when developers contribute to improve the Buckaroo plugins. -If you want to contribute as well, then please follow our [Contribution Guidelines](CONTRIBUTING.md). +To offer Apple Pay you also need your Buckaroo Guid, found in the [Buckaroo Plaza](https://plaza.buckaroo.nl/) under **My Buckaroo → General**. -### Versioning -

- -

+Step-by-step instructions: [Configuring the Shopware 6 plugin](https://docs.buckaroo.io/docs/shopware-6-configuration) -- **MAJOR:** Breaking changes that require additional testing/caution. -- **MINOR:** Changes that should not have a big impact. -- **PATCHES:** Bug and hotfixes only. +--- -### Additional information -- **Knowledge base & FAQ:** Available in [Dutch](https://support.buckaroo.nl/categorieen/plugins/shopware-6) or [English](https://support.buckaroo.nl/categorieen/plugins). -- **Support:** https://support.buckaroo.eu/contact -- **Contact:** [support@buckaroo.nl](mailto:support@buckaroo.nl) or [+31 (0)30 711 50 50](tel:+310307115050) +## Payment methods -Please note:
-This file has been prepared with the greatest possible care and is subject to language and/or spelling errors. +The plugin supports the following payment methods. Each one can be enabled or disabled individually and switched between live and test mode. + +| | | | +|---|---|---| +| [Alipay](https://docs.buckaroo.io/docs/alipay) | [Apple Pay](https://docs.buckaroo.io/docs/apple-pay) | [Bancontact](https://docs.buckaroo.io/docs/bancontact) | +| [Bank Transfer](https://docs.buckaroo.io/docs/transfer) | [Belfius](https://docs.buckaroo.io/docs/belfius) | [Billink](https://docs.buckaroo.io/docs/billink) | +| [Bizum](https://docs.buckaroo.io/docs/bizum) | [Blik](https://docs.buckaroo.io/docs/blik) | [Credit and debit cards](https://docs.buckaroo.io/docs/creditcards) | +| [EPS](https://docs.buckaroo.io/docs/eps) | [Giftcards](https://docs.buckaroo.io/docs/giftcards) | [Google Pay](https://docs.buckaroo.io/docs/google-pay) | +| [iDEAL / Wero](https://docs.buckaroo.io/docs/ideal) | [iDEAL QR](https://docs.buckaroo.io/docs/ideal-qr) | [In3](https://docs.buckaroo.io/docs/in3) | +| [KBC](https://docs.buckaroo.io/docs/kbc) | [Klarna](https://docs.buckaroo.io/docs/klarna-kp) | [MB Way](https://docs.buckaroo.io/docs/mb-way) | +| [Multibanco](https://docs.buckaroo.io/docs/multibanco) | [Pay by Bank](https://docs.buckaroo.io/docs/pay-by-bank) | [PayPal](https://docs.buckaroo.io/docs/paypal) | +| [PayPerEmail](https://docs.buckaroo.io/docs/payperemail) | [Przelewy24](https://docs.buckaroo.io/docs/przelewy24) | [Riverty](https://docs.buckaroo.io/docs/riverty) | +| [SEPA Direct Debit](https://docs.buckaroo.io/docs/sepa-direct-debit) | [Swish](https://docs.buckaroo.io/docs/swish) | [Trustly](https://docs.buckaroo.io/docs/trustly) | +| [Twint](https://docs.buckaroo.io/docs/twint) | [WeChatPay](https://docs.buckaroo.io/docs/wechatpay) | [Wero](https://docs.buckaroo.io/docs/wero) | + +> [!IMPORTANT] +> All supported methods appear in the Shopware administration, but you need an active Buckaroo subscription for a method before you can offer it in your checkout. + +--- + +## Support + +Having trouble? Work through this list before reaching out: + +1. Check the [frequently asked questions](https://docs.buckaroo.io/docs/shopware-6-faq). +2. Confirm you are on the [latest release](https://github.com/buckaroo-it/Shopware6/releases). +3. Enable debug logging in the plugin configuration and reproduce the issue. +4. Verify that your push URL is reachable from outside your network. Buckaroo sends push messages from fixed IP addresses and ports, so make sure these are on your allow list. See [push messages](https://docs.buckaroo.io/docs/integration-push-messages) for the current list. + +Still stuck? Contact us and include your Shopware version, plugin version, PHP version, the relevant log lines and the transaction key. + +- **Bug reports and feature requests:** [open an issue](https://github.com/buckaroo-it/Shopware6/issues) +- **Technical support:** [support@buckaroo.nl](mailto:support@buckaroo.nl) +- **Phone:** +31 (0)30 711 50 50 +- **Gateway status:** [status.buckaroo.io](https://status.buckaroo.io/) + +--- + +## Contribute + +We really appreciate it when developers help improve the Buckaroo plugins. Please read our [Contribution Guidelines](https://github.com/buckaroo-it/Shopware6/blob/master/CONTRIBUTING.md) before opening a pull request, and target the `master` branch. + +Found a security issue? Please report it privately to [support@buckaroo.nl](mailto:support@buckaroo.nl) instead of opening a public issue. + +--- + +## Versioning + +We follow semantic versioning (`MAJOR.MINOR.PATCH`): + +- **MAJOR** — breaking changes that require additional testing and caution. +- **MINOR** — new functionality with limited impact. +- **PATCH** — bug fixes and hotfixes only. + +All changes are documented in the [changelog](https://github.com/buckaroo-it/Shopware6/blob/master/CHANGELOG.md) and on the [releases page](https://github.com/buckaroo-it/Shopware6/releases). + +--- + +

+ Made with care by Buckaroo.
+ This document is subject to change; typos and language errors are possible.
+

diff --git a/composer.json b/composer.json index ed62bc96..98496b29 100644 --- a/composer.json +++ b/composer.json @@ -2,7 +2,7 @@ "name": "buckaroo/shopware6", "description": "Buckaroo payment provider plugin for Shopware 6", "type": "shopware-platform-plugin", - "version": "3.4.0", + "version": "3.5.0", "license": "proprietary", "minimum-stability": "stable", "require": { @@ -11,15 +11,17 @@ "ext-json": "*", "ext-pcre": "*", "ext-fileinfo": "*", - "buckaroo/sdk": "^1.23.2", - "shopware/core": "6.5.0.0 - 6.7.10.2" + "buckaroo/sdk": "^1.24.3", + "shopware/core": ">=6.5.8.0 <6.8" }, - "authors": [{ - "name": "Buckaroo", - "email": "support@buckaroo.nl", - "homepage": "https://www.buckaroo.nl", - "role": "Developer" - }], + "authors": [ + { + "name": "Buckaroo", + "email": "support@buckaroo.nl", + "homepage": "https://www.buckaroo.nl", + "role": "Developer" + } + ], "autoload": { "psr-4": { "Buckaroo\\Shopware6\\": "src/" @@ -35,20 +37,20 @@ "plugin-icon": "src/Resources/public/plugin.png", "copyright": "(c) by Buckaroo", "label": { - "de-DE": "Buckaroo Payment", - "en-GB": "Buckaroo Payment" + "de-DE": "Buckaroo Payments", + "en-GB": "Buckaroo Payments" }, "description": { - "de-DE": "Buckaroo Payment Plugins", - "en-GB": "Buckaroo Payment Plugin" + "de-DE": "Das offizielle Buckaroo Zahlungs-Plugin für Shopware 6. Akzeptieren Sie eine Vielzahl lokaler und internationaler Zahlungsarten und erstatten Sie direkt in der Administration.", + "en-GB": "The official Buckaroo payment plugin for Shopware 6. Accept a wide range of local and international payment methods and issue refunds directly from the Administration." }, "manufacturerLink": { - "de-DE": "https://store.shopware.com/buckaroo.html", - "en-GB": "https://store.shopware.com/en/buckaroo.html" + "de-DE": "https://store.shopware.com/de/extension-partners/buckaroo", + "en-GB": "https://store.shopware.com/en/extension-partners/buckaroo" }, "supportLink": { - "de-DE": "https://support.buckaroo.nl/contact", - "en-GB": "https://support.buckaroo.nl/contact" + "de-DE": "https://docs.buckaroo.io/docs/contact-us", + "en-GB": "https://docs.buckaroo.io/docs/contact-us" } }, "require-dev": { diff --git a/src/Buckaroo/Client.php b/src/Buckaroo/Client.php index c0a4255e..4a597818 100644 --- a/src/Buckaroo/Client.php +++ b/src/Buckaroo/Client.php @@ -32,7 +32,8 @@ public function __construct( string $secretKey, string $paymentCode, string $mode = 'live', - string $shopwareVersion = 'unknown' + string $shopwareVersion = 'unknown', + ?string $culture = null ) { $this->client = new BuckarooClient( new DefaultConfig( @@ -47,7 +48,8 @@ public function __construct( $shopwareVersion, 'Buckaroo', 'BuckarooPayments', - InstalledVersions::getVersion('buckaroo/shopware6') + InstalledVersions::getVersion('buckaroo/shopware6'), + $culture ) ); $this->paymentCode = $paymentCode; diff --git a/src/Events/AfterPaymentRequestEvent.php b/src/Events/AfterPaymentRequestEvent.php index cece4e90..e4c3084d 100644 --- a/src/Events/AfterPaymentRequestEvent.php +++ b/src/Events/AfterPaymentRequestEvent.php @@ -9,12 +9,17 @@ use Shopware\Core\System\SalesChannel\SalesChannelContext; use Shopware\Core\Framework\Event\ShopwareSalesChannelEvent; use Shopware\Core\Framework\Validation\DataBag\RequestDataBag; -use Shopware\Core\Checkout\Payment\Cart\PaymentTransactionStruct; +/** + * $transaction is typed as `object` rather than the modern PaymentTransactionStruct because + * that class does not exist on Shopware < 6.7 (this plugin also supports the legacy + * AsyncPaymentTransactionStruct via PaymentHandlerLegacy). Callers should narrow the type + * themselves, e.g. via instanceof checks, the same way CheckoutSubscriber::getOrder() does. + */ class AfterPaymentRequestEvent implements ShopwareSalesChannelEvent { - protected PaymentTransactionStruct $transaction; + protected object $transaction; protected RequestDataBag $dataBag; @@ -25,7 +30,7 @@ class AfterPaymentRequestEvent implements ShopwareSalesChannelEvent protected string $paymentCode; public function __construct( - PaymentTransactionStruct $transaction, + object $transaction, RequestDataBag $dataBag, SalesChannelContext $context, ClientResponseInterface $response, @@ -48,7 +53,7 @@ public function getContext(): Context return $this->salesChannelContext->getContext(); } - public function getAsyncPaymentTransaction(): PaymentTransactionStruct + public function getAsyncPaymentTransaction(): object { return $this->transaction; } diff --git a/src/Events/BeforePaymentRequestEvent.php b/src/Events/BeforePaymentRequestEvent.php index 4450a241..ec72531c 100644 --- a/src/Events/BeforePaymentRequestEvent.php +++ b/src/Events/BeforePaymentRequestEvent.php @@ -9,12 +9,17 @@ use Shopware\Core\System\SalesChannel\SalesChannelContext; use Shopware\Core\Framework\Event\ShopwareSalesChannelEvent; use Shopware\Core\Framework\Validation\DataBag\RequestDataBag; -use Shopware\Core\Checkout\Payment\Cart\PaymentTransactionStruct; +/** + * $transaction is typed as `object` rather than the modern PaymentTransactionStruct because + * that class does not exist on Shopware < 6.7 (this plugin also supports the legacy + * AsyncPaymentTransactionStruct via PaymentHandlerLegacy). Callers should narrow the type + * themselves, e.g. via instanceof checks, the same way CheckoutSubscriber::getOrder() does. + */ class BeforePaymentRequestEvent implements ShopwareSalesChannelEvent { - protected PaymentTransactionStruct $transaction; + protected object $transaction; protected RequestDataBag $dataBag; @@ -23,7 +28,7 @@ class BeforePaymentRequestEvent implements ShopwareSalesChannelEvent protected Client $client; public function __construct( - PaymentTransactionStruct $transaction, + object $transaction, RequestDataBag $dataBag, SalesChannelContext $context, Client $client @@ -44,7 +49,7 @@ public function getContext(): Context return $this->salesChannelContext->getContext(); } - public function getAsyncPaymentTransaction(): PaymentTransactionStruct + public function getAsyncPaymentTransaction(): object { return $this->transaction; } diff --git a/src/Events/OrderStateChangeEvent.php b/src/Events/OrderStateChangeEvent.php index 5e1f2927..399cbba2 100644 --- a/src/Events/OrderStateChangeEvent.php +++ b/src/Events/OrderStateChangeEvent.php @@ -12,11 +12,18 @@ use Symfony\Component\HttpFoundation\Request; use Buckaroo\Shopware6\Service\CaptureService; use Buckaroo\Shopware6\Service\InvoiceService; +use Buckaroo\Shopware6\Service\KlarnaMorService; use Buckaroo\Shopware6\Service\SettingsService; use Buckaroo\Shopware6\Service\TransactionService; +use Buckaroo\Shopware6\Service\StateTransitionService; use Buckaroo\Shopware6\Service\NotificationServiceFactory; use Symfony\Component\EventDispatcher\EventSubscriberInterface; +use Shopware\Core\Checkout\Order\OrderStates; +use Shopware\Core\Checkout\Order\OrderDefinition; +use Shopware\Core\Checkout\Order\Aggregate\OrderDelivery\OrderDeliveryStates; +use Shopware\Core\Checkout\Order\Aggregate\OrderTransaction\OrderTransactionStates; use Shopware\Core\Checkout\Order\Event\OrderStateMachineStateChangeEvent; +use Shopware\Core\System\StateMachine\Event\StateMachineTransitionEvent; class OrderStateChangeEvent implements EventSubscriberInterface { @@ -30,6 +37,10 @@ class OrderStateChangeEvent implements EventSubscriberInterface protected CaptureService $captureService; + protected KlarnaMorService $klarnaMorService; + + protected StateTransitionService $stateTransitionService; + protected object $notificationService; // Can be either NotificationService /** @var LoggerInterface */ @@ -45,7 +56,9 @@ public function __construct( OrderService $orderService, LoggerInterface $logger, CaptureService $captureService, - NotificationServiceFactory $notificationServiceFactory + NotificationServiceFactory $notificationServiceFactory, + KlarnaMorService $klarnaMorService, + StateTransitionService $stateTransitionService ) { $this->transactionService = $transactionService; $this->invoiceService = $invoiceService; @@ -54,6 +67,8 @@ public function __construct( $this->logger = $logger; $this->captureService = $captureService; $this->notificationService = $notificationServiceFactory->getNotificationService(); + $this->klarnaMorService = $klarnaMorService; + $this->stateTransitionService = $stateTransitionService; } /** @@ -63,9 +78,255 @@ public static function getSubscribedEvents(): array { return [ 'state_enter.order_delivery.state.shipped' => 'onOrderDeliveryStateShipped', + 'state_enter.order.state.cancelled' => 'onOrderStateCancelled', + StateMachineTransitionEvent::class => 'onStateMachineTransition', ]; } + /** + * Fallback path: StateMachineRegistry dispatches this class-based event for + * every state transition, independently of the `state_enter.*` business + * events. Deduplication with onOrderStateCancelled is handled by the + * `reservationCancelled` custom field and the transaction-state guards. + */ + public function onStateMachineTransition(StateMachineTransitionEvent $event): void + { + if ($event->getEntityName() !== OrderDefinition::ENTITY_NAME) { + return; + } + + if ($event->getToPlace()->getTechnicalName() !== OrderStates::STATE_CANCELLED) { + return; + } + + $this->logger->info('Buckaroo Klarna MoR: order cancelled transition received (state machine)', [ + 'orderId' => $event->getEntityId(), + ]); + + try { + $this->cancelKlarnaMorReservation( + $event->getEntityId(), + $event->getContext() + ); + } catch (\Throwable $th) { + // Never let a Buckaroo failure break the merchant's order-cancellation flow. + $this->logger->error(__METHOD__ . ' ' . (string)$th); + } + } + + /** + * When an order is cancelled from the Shopware Administration (or any other + * state-machine transition into `cancelled`), release the Klarna MoR + * authorization in Buckaroo if the payment transaction is still authorized. + */ + public function onOrderStateCancelled(OrderStateMachineStateChangeEvent $event): void + { + $this->logger->info('Buckaroo Klarna MoR: order cancelled event received', [ + 'orderId' => $event->getOrder()->getId(), + ]); + + try { + $this->cancelKlarnaMorReservation( + $event->getOrder()->getId(), + $event->getContext() + ); + } catch (\Throwable $th) { + // Never let a Buckaroo failure break the merchant's order-cancellation flow. + $this->logger->error(__METHOD__ . ' ' . (string)$th); + } + } + + /** + * Send a Klarna MoR CancelReservation datarequest to Buckaroo for an + * eligible cancelled order and synchronize the Shopware payment state. + */ + public function cancelKlarnaMorReservation(string $orderId, Context $context): void + { + $order = $this->orderService->getOrderById( + $orderId, + [ + 'transactions', + 'transactions.paymentMethod', + 'transactions.paymentMethod.plugin', + 'transactions.stateMachineState', + 'deliveries', + 'deliveries.stateMachineState', + 'salesChannel', + 'currency' + ], + $context + ); + + if ($order === null) { + $this->logger->debug(__METHOD__ . ' Cannot find order entity', ['orderId' => $orderId]); + return; + } + + $customFields = $this->transactionService->getCustomFields($order, $context); + + if (!$this->canCancelKlarnaMorReservation($order, $customFields)) { + return; + } + + $this->logger->info('Buckaroo Klarna MoR: sending CancelReservation datarequest', [ + 'orderId' => $order->getId(), + 'orderNumber' => $order->getOrderNumber(), + 'dataRequestKey' => $customFields['dataRequestKey'], + ]); + + $result = $this->klarnaMorService->execute( + Request::createFromGlobals(), + $order, + $context, + KlarnaMorService::ACTION_CANCEL_RESERVATION + ); + + if (isset($result['status']) && $result['status'] === true) { + $this->logger->info('Buckaroo Klarna MoR: reservation cancelled successfully', [ + 'orderId' => $order->getId(), + 'orderNumber' => $order->getOrderNumber(), + ]); + + $orderTransactionId = $this->transactionService->getLastTransactionId($order); + if ($orderTransactionId !== null) { + $this->stateTransitionService->transitionPaymentState( + 'cancelled', + $orderTransactionId, + $context + ); + $this->transactionService->saveTransactionData( + $orderTransactionId, + $context, + ['reservationCancelled' => true] + ); + } + } else { + $this->logger->error('Buckaroo Klarna MoR: CancelReservation datarequest failed', [ + 'orderId' => $order->getId(), + 'orderNumber' => $order->getOrderNumber(), + 'message' => $result['message'] ?? 'Unknown error', + 'code' => $result['code'] ?? null, + ]); + } + + $this->createNotifications($result, $context); + } + + /** + * Eligibility guards: Klarna MoR payment, authorization still active, + * not captured, not already cancelled/released, order not shipped. + * + * @param array $customFields + */ + private function canCancelKlarnaMorReservation(OrderEntity $order, array $customFields): bool + { + if ( + !isset($customFields['brqPaymentMethod']) || + !is_string($customFields['brqPaymentMethod']) || + strtolower($customFields['brqPaymentMethod']) !== 'klarna' + ) { + return false; + } + + if ( + !isset($customFields['dataRequestKey']) || + !is_string($customFields['dataRequestKey']) || + $customFields['dataRequestKey'] === '' + ) { + $this->logger->debug('Buckaroo Klarna MoR: skipping cancellation, missing dataRequestKey', [ + 'orderId' => $order->getId(), + ]); + return false; + } + + if (isset($customFields['captured'])) { + $this->logger->info('Buckaroo Klarna MoR: skipping cancellation, payment already captured', [ + 'orderId' => $order->getId(), + ]); + return false; + } + + if (isset($customFields['reservationCancelled']) && $customFields['reservationCancelled'] === true) { + $this->logger->debug('Buckaroo Klarna MoR: skipping cancellation, reservation already cancelled', [ + 'orderId' => $order->getId(), + ]); + return false; + } + + // Eligible while the Buckaroo authorization is still active. The Shopware + // transaction is either still `authorized`, or already `cancelled` locally + // (the admin cancel dialog cancels the payment together with the order, + // and that local transition does not release anything at Buckaroo). + // Captured/paid/refunded transactions are excluded. + $transactionState = $this->getLastTransactionState($order); + if ( + !in_array( + $transactionState, + [OrderTransactionStates::STATE_AUTHORIZED, OrderTransactionStates::STATE_CANCELLED], + true + ) + ) { + $this->logger->info( + 'Buckaroo Klarna MoR: skipping cancellation, payment transaction is not authorized', + [ + 'orderId' => $order->getId(), + 'transactionState' => $transactionState, + ] + ); + return false; + } + + if ($this->isShipped($order)) { + $this->logger->info('Buckaroo Klarna MoR: skipping cancellation, order already shipped', [ + 'orderId' => $order->getId(), + ]); + return false; + } + + return true; + } + + private function getLastTransactionState(OrderEntity $order): ?string + { + $transactions = $order->getTransactions(); + if ($transactions === null) { + return null; + } + + $transaction = $transactions->last(); + if ($transaction === null) { + return null; + } + + $state = $transaction->getStateMachineState(); + + return $state !== null ? $state->getTechnicalName() : null; + } + + private function isShipped(OrderEntity $order): bool + { + $deliveries = $order->getDeliveries(); + if ($deliveries === null) { + return false; + } + + foreach ($deliveries as $delivery) { + $state = $delivery->getStateMachineState(); + if ( + $state !== null && + in_array( + $state->getTechnicalName(), + [OrderDeliveryStates::STATE_SHIPPED, OrderDeliveryStates::STATE_PARTIALLY_SHIPPED], + true + ) + ) { + return true; + } + } + + return false; + } + public function onOrderDeliveryStateShipped(OrderStateMachineStateChangeEvent $event): bool { return $this->triggerCaptureForShippedOrder( @@ -83,11 +344,18 @@ public function onOrderDeliveryStateShipped(OrderStateMachineStateChangeEvent $e * Deduplication between the two paths is handled by the customFields['captured'] * flag which CaptureService sets synchronously after a successful capture; the * canCapture* guards short-circuit when it is present. + * + * @param array|null $onlyPaymentMethods When given, the trigger is + * restricted to these Buckaroo payment methods (lowercase `brqPaymentMethod` + * values). The direct DAL write path uses this to opt in one method at a time + * instead of every capture-on-shipment method; see + * OrderDeliveryWrittenSubscriber::CAPTURE_METHODS_ON_DAL_WRITE. */ public function triggerCaptureForShippedOrder( string $orderId, ?string $salesChannelId, - Context $context + Context $context, + ?array $onlyPaymentMethods = null ): bool { $order = $this->orderService->getOrderById( $orderId, @@ -119,6 +387,20 @@ public function triggerCaptureForShippedOrder( return false; } + if ( + $onlyPaymentMethods !== null && + !in_array(strtolower($customFields['brqPaymentMethod']), $onlyPaymentMethods, true) + ) { + $this->logger->debug( + 'Buckaroo capture-on-shipment: payment method not enabled for this trigger path', + [ + 'orderId' => $orderId, + 'brqPaymentMethod' => $customFields['brqPaymentMethod'], + 'allowedMethods' => $onlyPaymentMethods, + ] + ); + return false; + } if ( $this->canCaptureAfterpay( diff --git a/src/Handlers/ApplePayPaymentHandler.php b/src/Handlers/ApplePayPaymentHandler.php index 9db83713..8a6412ed 100644 --- a/src/Handlers/ApplePayPaymentHandler.php +++ b/src/Handlers/ApplePayPaymentHandler.php @@ -29,30 +29,26 @@ public function getMethodPayload( SalesChannelContext $salesChannelContext, string $paymentCode ): array { - $usingApplepayHostedPaymentPageConfig = $this->asyncPaymentService->settingsService->getSetting( - 'applepayHostedPaymentPage', - $salesChannelContext->getSalesChannelId() - ); - - if ($usingApplepayHostedPaymentPageConfig == 1) { - return array( - 'continueOnIncomplete' => '1', - ); - } - $applePayInfo = $dataBag->get('applePayInfo'); + // TEMP DIAGNOSTIC: does the Apple Pay token reach the handler? + $this->asyncPaymentService->logger->info('[ApplePay][getMethodPayload]', [ + 'dataBagKeys' => array_keys($dataBag->all()), + 'applePayInfoIsString' => is_string($applePayInfo), + 'applePayInfoLength' => is_string($applePayInfo) ? strlen($applePayInfo) : 0, + ]); if (!is_string($applePayInfo)) { return []; } $data = json_decode($applePayInfo); - if ($data === false || !is_object($data)) { + // json_decode() returns null on failure (never false) + if ($data === null || !is_object($data)) { return []; } return [ - "customerCardName" => $this->getCustomerName($data), + "customerCardName" => $this->getCustomerName($data, $order), "paymentData" => $this->getPaymentData($data) ]; } @@ -78,20 +74,35 @@ private function getPaymentData($data): string } /** + * Card holder name sent to Buckaroo (shown as the customer in Plaza). + * Prefer the Apple Pay billing contact, fall back to the shipping contact + * (express flow) and finally to the order customer — in the standard + * checkout the shop always knows the customer, so the transaction should + * never end up as "Customer Unknown". + * * @param mixed $data + * @param OrderEntity $order * @return string */ - private function getCustomerName($data): string + private function getCustomerName($data, OrderEntity $order): string { - if (!is_object($data)) { - return ''; + if (is_object($data)) { + foreach (['billingContact', 'shippingContact'] as $contactKey) { + if (!empty($data->{$contactKey}) && + !empty($data->{$contactKey}->givenName) && + !empty($data->{$contactKey}->familyName) + ) { + return $data->{$contactKey}->givenName . ' ' . $data->{$contactKey}->familyName; + } + } } - if (!empty($data->billingContact) && - !empty($data->billingContact->givenName) && - !empty($data->billingContact->familyName) - ) { - return $data->billingContact->givenName . ' ' . $data->billingContact->familyName; + + $orderCustomer = $order->getOrderCustomer(); + if ($orderCustomer !== null) { + return trim($orderCustomer->getFirstName() . ' ' . $orderCustomer->getLastName()); } + return ''; } } + diff --git a/src/Handlers/BillinkPaymentHandler.php b/src/Handlers/BillinkPaymentHandler.php index df9cd443..315adaf9 100644 --- a/src/Handlers/BillinkPaymentHandler.php +++ b/src/Handlers/BillinkPaymentHandler.php @@ -9,6 +9,7 @@ use Shopware\Core\System\SalesChannel\SalesChannelContext; use Shopware\Core\Framework\Validation\DataBag\RequestDataBag; use Shopware\Core\Checkout\Order\Aggregate\OrderAddress\OrderAddressEntity; +use Shopware\Core\Checkout\Order\Aggregate\OrderCustomer\OrderCustomerEntity; class BillinkPaymentHandler extends PaymentHandlerSimple { @@ -73,34 +74,40 @@ protected function getBillingData( $streetParts = $this->formatRequestParamService->formatStreet($address->getStreet()); + $billing = [ + 'recipient' => $this->filterEmpty([ + 'category' => $this->getCategory($address), + 'careOf' => $this->getCareOf($address), + 'initials' => $this->getInitials($address->getFirstName()), + 'firstName' => $address->getFirstName(), + 'lastName' => $address->getLastName(), + 'birthDate' => $this->getBirthDate($dataBag, $customer), + 'salutation' => $this->getGender($dataBag, $customer) + ]), + 'address' => [ + 'street' => $this->formatRequestParamService->getStreet($address, $streetParts), + 'houseNumber' => $this->formatRequestParamService->getHouseNumber($address, $streetParts), + 'houseNumberAdditional' => $this->formatRequestParamService + ->getAdditionalHouseNumber( + $address, + $streetParts + ), + 'zipcode' => $address->getZipcode(), + 'city' => $address->getCity(), + 'country' => $this->asyncPaymentService->getCountry($address)->getIso() + ], + 'email' => $customer->getEmail() + ]; + + $phone = $this->getPhone($dataBag, $address, $customer); + if ($phone !== null) { + $billing['phone'] = [ + 'mobile' => $phone, + ]; + } + return [ - 'billing' => [ - 'recipient' => [ - 'category' => $this->getCategory($address), - 'careOf' => $this->getCareOf($address), - 'initials' => $this->getInitials($address->getFirstName()), - 'firstName' => $address->getFirstName(), - 'lastName' => $address->getLastName(), - 'birthDate' => $this->getBirthDate($dataBag), - 'salutation' => $dataBag->get('buckaroo_billink_gender') - ], - 'address' => [ - 'street' => $this->formatRequestParamService->getStreet($address, $streetParts), - 'houseNumber' => $this->formatRequestParamService->getHouseNumber($address, $streetParts), - 'houseNumberAdditional' => $this->formatRequestParamService - ->getAdditionalHouseNumber( - $address, - $streetParts - ), - 'zipcode' => $address->getZipcode(), - 'city' => $address->getCity(), - 'country' => $this->asyncPaymentService->getCountry($address)->getIso() - ], - 'phone' => [ - 'mobile' => $this->getPhone($dataBag, $address), - ], - 'email' => $customer->getEmail() - ] + 'billing' => $billing ]; } @@ -115,18 +122,19 @@ protected function getShippingData( RequestDataBag $dataBag ): array { $address = $this->asyncPaymentService->getShippingAddress($order); + $customer = $this->asyncPaymentService->getCustomer($order); $streetParts = $this->formatRequestParamService->formatStreet($address->getStreet()); return [ 'shipping' => [ - 'recipient' => [ + 'recipient' => $this->filterEmpty([ 'category' => $this->getCategory($address), 'careOf' => $this->getCareOf($address), 'initials' => $this->getInitials($address->getFirstName()), 'firstName' => $address->getFirstName(), 'lastName' => $address->getLastName(), - 'birthDate' => $this->getBirthDate($dataBag), - ], + 'birthDate' => $this->getBirthDate($dataBag, $customer), + ]), 'address' => [ 'street' => $this->formatRequestParamService->getStreet($address, $streetParts), 'houseNumber' => $this->formatRequestParamService->getHouseNumber($address, $streetParts), @@ -203,13 +211,40 @@ protected function getCoc(OrderAddressEntity $billingAddress, RequestDataBag $da return []; } - private function getPhone(RequestDataBag $dataBag, OrderAddressEntity $address): string - { - $phone = $dataBag->get('buckaroo_billink_phone', $address->getPhoneNumber()); - if (!is_scalar($phone)) { - return ''; + /** + * Get mobile phone number from existing Shopware data. + * The checkout form no longer asks for it; Billink One requests it on the + * hosted payment page when missing. + * Priority: + * 1. Legacy dataBag value (kept for backwards compatibility, e.g. headless clients) + * 2. Billing address phone number + * 3. Customer / address custom fields + * + * @param RequestDataBag $dataBag + * @param OrderAddressEntity $address + * @param OrderCustomerEntity $customer + * + * @return null|string + */ + private function getPhone( + RequestDataBag $dataBag, + OrderAddressEntity $address, + OrderCustomerEntity $customer + ): ?string { + $phone = $dataBag->get('buckaroo_billink_phone'); + if (is_scalar($phone) && !empty(trim((string)$phone))) { + return trim((string)$phone); } - return (string)$phone; + + $addressPhone = $address->getPhoneNumber(); + if (is_string($addressPhone) && !empty(trim($addressPhone))) { + return trim($addressPhone); + } + + return $this->getCustomFieldValue( + [$address->getCustomFields(), $this->getCustomerCustomFields($customer)], + ['buckaroo_billink_phone', 'phoneNumber', 'phone_number', 'phone', 'mobile', 'mobileNumber'] + ); } /** @@ -347,27 +382,141 @@ private function getInitials(string $name): string } /** - * Get birth date + * Get birth date from existing Shopware data. + * The checkout form no longer asks for it; Billink One requests it on the + * hosted payment page when missing. + * Priority: + * 1. Legacy dataBag value (kept for backwards compatibility, e.g. headless clients) + * 2. Customer profile birthday + * 3. Customer custom fields * * @param RequestDataBag $dataBag + * @param OrderCustomerEntity $customer * * @return null|string */ - private function getBirthDate(RequestDataBag $dataBag) + private function getBirthDate(RequestDataBag $dataBag, OrderCustomerEntity $customer): ?string { - if (!$dataBag->has('buckaroo_billink_DoB')) { - return null; + $dateString = $dataBag->get('buckaroo_billink_DoB'); + if (is_scalar($dateString)) { + $date = strtotime((string)$dateString); + if ($date !== false) { + return @date('d-m-Y', $date); + } } - $dateString = $dataBag->get('buckaroo_billink_DoB'); - if (!is_scalar($dateString)) { - return null; + $profile = $customer->getCustomer(); + if ($profile !== null && $profile->getBirthday() !== null) { + return $profile->getBirthday()->format('d-m-Y'); } - $date = strtotime((string)$dateString); - if ($date === false) { - return null; + + $customValue = $this->getCustomFieldValue( + [$this->getCustomerCustomFields($customer)], + ['buckaroo_billink_DoB', 'buckaroo_dob', 'dateOfBirth', 'date_of_birth', 'birthday', 'dob'] + ); + if ($customValue !== null) { + $date = strtotime($customValue); + if ($date !== false) { + return @date('d-m-Y', $date); + } } - return @date("d-m-Y", $date); + return null; + } + + /** + * Get gender/salutation from existing Shopware data. + * The checkout form no longer asks for it; Billink One requests it on the + * hosted payment page when missing. + * Priority: + * 1. Legacy dataBag value (kept for backwards compatibility, e.g. headless clients) + * 2. Derived from the order customer's salutation key + * + * @param RequestDataBag $dataBag + * @param OrderCustomerEntity $customer + * + * @return null|string + */ + private function getGender(RequestDataBag $dataBag, OrderCustomerEntity $customer): ?string + { + $gender = $dataBag->get('buckaroo_billink_gender'); + if (is_string($gender) && in_array($gender, ['Male', 'Female', 'Unknown'], true)) { + return $gender; + } + + $salutation = $customer->getSalutation(); + if ($salutation !== null) { + if ($salutation->getSalutationKey() === 'mr') { + return 'Male'; + } + if ($salutation->getSalutationKey() === 'mrs') { + return 'Female'; + } + } + + return null; + } + + /** + * Get custom fields from the order customer and, when loaded, + * the underlying customer profile. + * + * @param OrderCustomerEntity $customer + * + * @return array + */ + private function getCustomerCustomFields(OrderCustomerEntity $customer): array + { + $customFields = $customer->getCustomFields() ?? []; + + $profile = $customer->getCustomer(); + if ($profile !== null) { + $customFields = array_merge($profile->getCustomFields() ?? [], $customFields); + } + + return $customFields; + } + + /** + * Find the first non-empty string value for any of the candidate keys + * in the given custom field sets. + * + * @param array $customFieldSets + * @param array $keys + * + * @return null|string + */ + private function getCustomFieldValue(array $customFieldSets, array $keys): ?string + { + foreach ($customFieldSets as $customFields) { + if (!is_array($customFields)) { + continue; + } + foreach ($keys as $key) { + if ( + isset($customFields[$key]) && + is_scalar($customFields[$key]) && + !empty(trim((string)$customFields[$key])) + ) { + return trim((string)$customFields[$key]); + } + } + } + + return null; + } + + /** + * Remove null and empty-string values so they are not sent to Billink. + * + * @param array $data + * + * @return array + */ + private function filterEmpty(array $data): array + { + return array_filter($data, function ($value) { + return $value !== null && $value !== ''; + }); } } diff --git a/src/Handlers/KnakenPaymentHandler.php b/src/Handlers/KnakenPaymentHandler.php deleted file mode 100644 index 54663b94..00000000 --- a/src/Handlers/KnakenPaymentHandler.php +++ /dev/null @@ -1,12 +0,0 @@ -getCustomFieldsValue('buckarooFee') ?? 0.0); + $existingFeeValue = $order->getCustomFieldsValue('buckarooFee'); + $existingFee = is_numeric($existingFeeValue) ? (float) $existingFeeValue : 0.0; if ($fee > 0 || $existingFee > 0) { $this->asyncPaymentService ->checkoutHelper @@ -90,27 +93,34 @@ public function pay( return $this->completeZeroAmountPayment($transaction, $salesChannelContext); } + // Resolve the gateway language (HPP & payment instructions) + $culture = $this->resolveCulture($salesChannelContext, $order); + + $payload = array_merge_recursive( + $this->getCommonRequestPayload( + $transaction, + $dataBag, + $salesChannelContext, + $paymentCode + ), + $this->getMethodPayload( + $order, + $dataBag, + $salesChannelContext, + $paymentCode + ) + ); + if (!isset($payload['culture'])) { + $payload['culture'] = $culture; + } + $client = $this->getClient( $paymentCode, $salesChannelId, - $dataBag + $dataBag, + $culture ) - ->setPayload( - array_merge_recursive( - $this->getCommonRequestPayload( - $transaction, - $dataBag, - $salesChannelContext, - $paymentCode - ), - $this->getMethodPayload( - $order, - $dataBag, - $salesChannelContext, - $paymentCode - ) - ) - ) + ->setPayload($payload) ->setAction( $this->getMethodAction( $dataBag, @@ -119,7 +129,9 @@ public function pay( ) ); - // Skip legacy BeforePaymentRequestEvent in CI (expects modern struct) + $this->asyncPaymentService->dispatchEvent( + new BeforePaymentRequestEvent($transaction, $dataBag, $salesChannelContext, $client) + ); return $this->handleResponse( $client->execute(), @@ -162,7 +174,9 @@ protected function handleResponse( SalesChannelContext $salesChannelContext, string $paymentCode ): RedirectResponse { - // Skip legacy AfterPaymentRequestEvent in CI (expects modern struct) + $this->asyncPaymentService->dispatchEvent( + new AfterPaymentRequestEvent($transaction, $dataBag, $salesChannelContext, $response, $paymentCode) + ); $returnUrl = $this->getReturnUrl($transaction, $dataBag); $this->storeTransactionInfo($transaction, $response, $salesChannelContext, $paymentCode); @@ -375,8 +389,12 @@ protected function getFee(string $paymentCode, string $salesChannelId): float ->getBuckarooFee($paymentCode, $salesChannelId); } - private function getClient(string $paymentCode, string $salesChannelId, DataBag $dataBag): Client - { + private function getClient( + string $paymentCode, + string $salesChannelId, + DataBag $dataBag, + ?string $culture = null + ): Client { if ( $paymentCode === 'paybybank' && $dataBag->get('payBybankMethodId') === 'INGBNL2A' && @@ -386,7 +404,23 @@ private function getClient(string $paymentCode, string $salesChannelId, DataBag } return $this->asyncPaymentService ->clientService - ->get($paymentCode, $salesChannelId); + ->get($paymentCode, $salesChannelId, $culture); + } + + /** + * Resolve the Buckaroo culture code (ex. "nl-NL") for the current payment, + * based on the general "language" plugin setting. + */ + private function resolveCulture( + SalesChannelContext $salesChannelContext, + ?OrderEntity $order = null + ): string { + $resolver = $this->asyncPaymentService->getLanguageResolver(); + if ($resolver === null) { + return \Buckaroo\Shopware6\Service\BuckarooLanguageResolver::FALLBACK_CULTURE; + } + + return $resolver->resolveLanguage($salesChannelContext, null, $order); } private function getPayment(string $transactionId): AbstractPayment diff --git a/src/Handlers/PaymentHandlerModern.php b/src/Handlers/PaymentHandlerModern.php index ed0d0572..035b8fdb 100644 --- a/src/Handlers/PaymentHandlerModern.php +++ b/src/Handlers/PaymentHandlerModern.php @@ -5,6 +5,8 @@ namespace Buckaroo\Shopware6\Handlers; use Buckaroo\Shopware6\Buckaroo\ClientResponseInterface; +use Buckaroo\Shopware6\Events\AfterPaymentRequestEvent; +use Buckaroo\Shopware6\Events\BeforePaymentRequestEvent; use Buckaroo\Shopware6\Service\AsyncPaymentService; use Buckaroo\Shopware6\PaymentMethods\AbstractPayment; use Buckaroo\Shopware6\Buckaroo\Client; @@ -14,7 +16,6 @@ use Buckaroo\Shopware6\Storefront\Exceptions\InvalidParameterException; use Shopware\Core\Checkout\Order\Aggregate\OrderTransaction\OrderTransactionEntity; use Shopware\Core\Checkout\Order\OrderEntity; -use Shopware\Core\Checkout\Payment\Cart\AsyncPaymentTransactionStruct; use Shopware\Core\Checkout\Payment\Cart\PaymentHandler\AbstractPaymentHandler; use Shopware\Core\Checkout\Payment\Cart\PaymentTransactionStruct; use Shopware\Core\Checkout\Payment\PaymentException; @@ -97,7 +98,8 @@ public function pay( $paymentCode, $order->getSalesChannelId() ); - $existingFee = (float) ($order->getCustomFieldsValue('buckarooFee') ?? 0.0); + $existingFeeValue = $order->getCustomFieldsValue('buckarooFee'); + $existingFee = is_numeric($existingFeeValue) ? (float) $existingFeeValue : 0.0; if ($fee > 0 || $existingFee > 0) { $this->feeCalculator->applyFeeToOrder($order->getId(), $fee, $salesChannelContext->getContext()); // Reload order to get updated total @@ -127,16 +129,30 @@ public function pay( $methodPayload = $this->getMethodPayload($order, $dataBag, $salesChannelContext, $paymentCode); $payload = array_merge_recursive($commonPayload, $methodPayload); - $client = $this->getClient($paymentCode, $order->getSalesChannelId(), $dataBag) + $culture = $this->resolveCulture($salesChannelContext, $request, $order); + if (!isset($payload['culture'])) { + $payload['culture'] = $culture; + } + + $client = $this->getClient($paymentCode, $order->getSalesChannelId(), $dataBag, $culture) ->setPayload($payload) ->setAction($this->getMethodAction($dataBag, $salesChannelContext, $paymentCode)); // Allow specific payment handlers to configure the client $this->configureClient($client, $paymentCode, $salesChannelContext); + $this->asyncPaymentService->dispatchEvent( + new BeforePaymentRequestEvent($transaction, $dataBag, $salesChannelContext, $client) + ); + $response = $client->execute(); + + $this->asyncPaymentService->dispatchEvent( + new AfterPaymentRequestEvent($transaction, $dataBag, $salesChannelContext, $response, $paymentCode) + ); + $returnUrl = $this->urlGenerator->getReturnUrl($orderTransaction, $order, $dataBag); - + return $this->responseHandler->handleResponse( $response, $orderTransaction, @@ -266,8 +282,12 @@ protected function configureClient( // Child classes can override this to configure the client } - private function getClient(string $paymentCode, string $salesChannelId, RequestDataBag $dataBag): Client - { + private function getClient( + string $paymentCode, + string $salesChannelId, + RequestDataBag $dataBag, + ?string $culture = null + ): Client { if ( $paymentCode === 'paybybank' && $dataBag->get('payBybankMethodId') === 'INGBNL2A' && @@ -275,7 +295,24 @@ private function getClient(string $paymentCode, string $salesChannelId, RequestD ) { $paymentCode = 'ideal'; } - return $this->asyncPaymentService->clientService->get($paymentCode, $salesChannelId); + return $this->asyncPaymentService->clientService->get($paymentCode, $salesChannelId, $culture); + } + + /** + * Resolve the Buckaroo culture code (ex. "nl-NL") for the current payment, + * based on the general "language" plugin setting. + */ + private function resolveCulture( + SalesChannelContext $salesChannelContext, + ?Request $request = null, + ?OrderEntity $order = null + ): string { + $resolver = $this->asyncPaymentService->getLanguageResolver(); + if ($resolver === null) { + return \Buckaroo\Shopware6\Service\BuckarooLanguageResolver::FALLBACK_CULTURE; + } + + return $resolver->resolveLanguage($salesChannelContext, $request, $order); } /** diff --git a/src/Handlers/PaymentHandlerSimple.php b/src/Handlers/PaymentHandlerSimple.php index 6571e06c..b3109434 100644 --- a/src/Handlers/PaymentHandlerSimple.php +++ b/src/Handlers/PaymentHandlerSimple.php @@ -268,7 +268,8 @@ public function pay( $paymentCode, $salesChannelContext->getSalesChannelId() ); - $existingFee = (float) ($order->getCustomFieldsValue('buckarooFee') ?? 0.0); + $existingFeeValue = $order->getCustomFieldsValue('buckarooFee'); + $existingFee = is_numeric($existingFeeValue) ? (float) $existingFeeValue : 0.0; if ($fee > 0 || $existingFee > 0) { $feeCalculator->applyFeeToOrder($order->getId(), $fee, $context); // Reload order to get updated total @@ -313,13 +314,22 @@ public function pay( $methodPayload = $this->getMethodPayload($order, $dataBag, $salesChannelContext, $paymentCode); $methodAction = $this->getMethodAction($dataBag, $salesChannelContext, $paymentCode); + // Resolve the gateway language (HPP & payment instructions) + $culture = $this->resolveCulture($salesChannelContext, $request, $order); + // Process payment using existing services $client = $this->asyncPaymentService->clientService->get( $paymentCode, - $salesChannelContext->getSalesChannelId() + $salesChannelContext->getSalesChannelId(), + $culture ); - - $client->setPayload(array_merge_recursive($commonPayload, $methodPayload)) + + $payload = array_merge_recursive($commonPayload, $methodPayload); + if (!isset($payload['culture'])) { + $payload['culture'] = $culture; + } + + $client->setPayload($payload) ->setAction($methodAction); // Allow specific payment handlers to configure the client @@ -361,7 +371,20 @@ public function pay( 'Payment was canceled' ); } - + + // Post-processing hook for handlers that need the successful response. + // The 6.5 path gets this through handleResponse(); this branch never + // calls handleResponse(), so without the hook PayPal Express never + // writes the payer's real name/address back onto the order. + $this->afterPaymentResponse( + $response, + $orderTransaction, + $order, + $dataBag, + $salesChannelContext, + $paymentCode + ); + if ($response->hasRedirect()) { return new RedirectResponse($response->getRedirectUrl()); } @@ -430,6 +453,23 @@ protected function handleResponse( return new RedirectResponse('/checkout/finish'); } + /** + * Hook invoked after a successful Buckaroo response, before the redirect is + * built. Default implementation does nothing. + * + * @param mixed $orderTransaction + */ + protected function afterPaymentResponse( + \Buckaroo\Shopware6\Buckaroo\ClientResponseInterface $response, + $orderTransaction, + \Shopware\Core\Checkout\Order\OrderEntity $order, + \Shopware\Core\Framework\Validation\DataBag\RequestDataBag $dataBag, + \Shopware\Core\System\SalesChannel\SalesChannelContext $salesChannelContext, + string $paymentCode + ): void { + // Default implementation - do nothing + } + public function finalize( Request $request, PaymentTransactionStruct $transaction, diff --git a/src/Handlers/PaymentHandlerTemplateMethods.php b/src/Handlers/PaymentHandlerTemplateMethods.php index 198c02c5..b9485c20 100644 --- a/src/Handlers/PaymentHandlerTemplateMethods.php +++ b/src/Handlers/PaymentHandlerTemplateMethods.php @@ -4,9 +4,11 @@ namespace Buckaroo\Shopware6\Handlers; +use Buckaroo\Shopware6\Service\BuckarooLanguageResolver; use Shopware\Core\Checkout\Order\OrderEntity; use Shopware\Core\Framework\Validation\DataBag\RequestDataBag; use Shopware\Core\System\SalesChannel\SalesChannelContext; +use Symfony\Component\HttpFoundation\Request; /** * Trait containing template methods shared between both versions @@ -34,6 +36,23 @@ public function getMethodAction( return 'pay'; } + /** + * Resolve the Buckaroo culture code (ex. "nl-NL") for the current payment, + * based on the general "language" plugin setting. + */ + protected function resolveCulture( + SalesChannelContext $salesChannelContext, + ?Request $request = null, + ?OrderEntity $order = null + ): string { + $resolver = $this->asyncPaymentService->getLanguageResolver(); + if ($resolver === null) { + return BuckarooLanguageResolver::FALLBACK_CULTURE; + } + + return $resolver->resolveLanguage($salesChannelContext, $request, $order); + } + /** * Extract context token from data bag */ diff --git a/src/Handlers/PaypalPaymentHandler.php b/src/Handlers/PaypalPaymentHandler.php index ade48818..ee0ee30f 100644 --- a/src/Handlers/PaypalPaymentHandler.php +++ b/src/Handlers/PaypalPaymentHandler.php @@ -51,16 +51,22 @@ public function getMethodPayload( SalesChannelContext $salesChannelContext, string $paymentCode ): array { - // We dont really need this. - - // if ($dataBag->has('orderId')) { - // return ['payPalOrderId' => $dataBag->get('orderId')]; - // } + $payload = []; + + // PayPal Express: the shopper already approved a PayPal order in the popup. + // Without payPalOrderId Buckaroo starts a *new* redirect-based PayPal + // transaction and answers with a RequiredAction redirect, which parks the + // shopper on redirect.ashx ("Redirecting, please wait...") instead of + // returning to the finish page. + if ($dataBag->has('orderId') && is_scalar($dataBag->get('orderId'))) { + $payload['payPalOrderId'] = (string)$dataBag->get('orderId'); + } if ($this->isSellerProtection($salesChannelContext)) { - return $this->getSellerProtectionData($order); + $payload = array_merge($payload, $this->getSellerProtectionData($order)); } - return []; + + return $payload; } /** @@ -110,6 +116,25 @@ protected function handleResponse( ); } + /** + * Shopware 6.7: PaymentHandlerSimple::pay() never calls handleResponse(), so the + * PayPal payer details have to be written back from this hook instead. Without it + * the express guest keeps its placeholder name + * ("Unknown Customer - Buckaroo Payments"). + * + * @param mixed $orderTransaction + */ + protected function afterPaymentResponse( + ClientResponseInterface $response, + $orderTransaction, + OrderEntity $order, + RequestDataBag $dataBag, + SalesChannelContext $salesChannelContext, + string $paymentCode + ): void { + $this->orderUpdater->update($response, $order, $salesChannelContext); + } + /** * Get seller protection data * diff --git a/src/Helpers/Constants/ResponseStatus.php b/src/Helpers/Constants/ResponseStatus.php index 1b03e277..9b7d84ba 100644 --- a/src/Helpers/Constants/ResponseStatus.php +++ b/src/Helpers/Constants/ResponseStatus.php @@ -25,4 +25,11 @@ class ResponseStatus public const BUCKAROO_MUTATION_TYPE_INFORMATIONAL = 'Informational'; public const BUCKAROO_MUTATION_TYPE_PROCESSING = 'Processing'; public const BUCKAROO_BILLINK_CAPTURE_TYPE_ACCEPT = 'C073'; + + /** + * Buckaroo transaction type of a Klarna KP Pay (pay on reservation) transaction. + * Present on the push that confirms the reservation was captured, whether that + * capture was initiated by this plugin, by KlarnaKP AutoPay, or in the Plaza. + */ + public const BUCKAROO_KLARNAKP_PAY_TYPE = 'V610'; } diff --git a/src/Helpers/GatewayHelper.php b/src/Helpers/GatewayHelper.php index 31362fd1..18e9bee9 100644 --- a/src/Helpers/GatewayHelper.php +++ b/src/Helpers/GatewayHelper.php @@ -33,7 +33,6 @@ use Buckaroo\Shopware6\PaymentMethods\Multibanco; use Buckaroo\Shopware6\PaymentMethods\Creditcards; use Buckaroo\Shopware6\PaymentMethods\PayPerEmail; -use Buckaroo\Shopware6\PaymentMethods\Knaken; use Buckaroo\Shopware6\PaymentMethods\SepaDirectDebit; use Buckaroo\Shopware6\PaymentMethods\Swish; use Buckaroo\Shopware6\PaymentMethods\Bizum; @@ -73,7 +72,6 @@ class GatewayHelper IdealQr::class, MBWay::class, Multibanco::class, - Knaken::class, Swish::class, Bizum::class, Twint::class, diff --git a/src/Helpers/KlarnaKpCaptureDetector.php b/src/Helpers/KlarnaKpCaptureDetector.php new file mode 100644 index 00000000..c5b78cc4 --- /dev/null +++ b/src/Helpers/KlarnaKpCaptureDetector.php @@ -0,0 +1,65 @@ +request->get(self::AUTO_PAY_TRANSACTION_KEY))) { + return true; + } + + if (!empty($request->request->get(self::CAPTURE_ID))) { + return true; + } + + return (string)$request->request->get('brq_transaction_type') + === ResponseStatus::BUCKAROO_KLARNAKP_PAY_TYPE; + } + + private static function isKlarnaKp(Request $request): bool + { + // The reserve/datarequest push identifies the method through + // brq_primary_service, the financial pushes through brq_transaction_method. + $method = $request->request->get('brq_primary_service') + ?: $request->request->get('brq_transaction_method'); + + return is_string($method) && strtolower($method) === 'klarnakp'; + } +} diff --git a/src/Migration/Migration1787734800RemoveGoSettle.php b/src/Migration/Migration1787734800RemoveGoSettle.php new file mode 100644 index 00000000..0d89b48f --- /dev/null +++ b/src/Migration/Migration1787734800RemoveGoSettle.php @@ -0,0 +1,99 @@ +executeStatement( + "UPDATE `payment_method` + SET `active` = 0 + WHERE `handler_identifier` = :handlerIdentifier", + ['handlerIdentifier' => self::HANDLER_IDENTIFIER] + ); + } + + public function updateDestructive(Connection $connection): void + { + $paymentMethodId = $connection->fetchOne( + "SELECT `id` FROM `payment_method` WHERE `handler_identifier` = :handlerIdentifier", + ['handlerIdentifier' => self::HANDLER_IDENTIFIER] + ); + + if (!$paymentMethodId) { + return; + } + + $customerReferences = $this->countCustomerReferences($connection, $paymentMethodId); + + $orderTransactionReferences = $connection->fetchOne( + "SELECT COUNT(*) FROM `order_transaction` WHERE `payment_method_id` = :paymentMethodId", + ['paymentMethodId' => $paymentMethodId] + ); + + if ($customerReferences == 0 && $orderTransactionReferences == 0) { + $connection->executeStatement( + "DELETE FROM `payment_method` WHERE `handler_identifier` = :handlerIdentifier", + ['handlerIdentifier' => self::HANDLER_IDENTIFIER] + ); + } + } + + /** + * @param mixed $paymentMethodId + */ + private function countCustomerReferences(Connection $connection, $paymentMethodId): int + { + foreach (self::CUSTOMER_PAYMENT_METHOD_COLUMNS as $column) { + if (!$this->hasColumn($connection, 'customer', $column)) { + continue; + } + + $count = $connection->fetchOne( + "SELECT COUNT(*) FROM `customer` WHERE `{$column}` = :paymentMethodId", + ['paymentMethodId' => $paymentMethodId] + ); + + return is_numeric($count) ? (int) $count : 0; + } + + return 0; + } + + private function hasColumn(Connection $connection, string $table, string $column): bool + { + return (bool) $connection->fetchOne( + "SELECT COUNT(*) + FROM `information_schema`.`COLUMNS` + WHERE `TABLE_SCHEMA` = DATABASE() + AND `TABLE_NAME` = :table + AND `COLUMN_NAME` = :column", + ['table' => $table, 'column' => $column] + ); + } +} diff --git a/src/PaymentMethods/Knaken.php b/src/PaymentMethods/Knaken.php deleted file mode 100644 index 7f062751..00000000 --- a/src/PaymentMethods/Knaken.php +++ /dev/null @@ -1,77 +0,0 @@ - - */ - public function getTranslations(): array - { - return [ - 'de-DE' => [ - 'name' => $this->getName(), - 'description' => 'Bezahlen mit goSettle', - ], - 'en-GB' => [ - 'name' => $this->getName(), - 'description' => $this->getDescription(), - ], - ]; - } -} diff --git a/src/Resources/app/administration/src/components/buckaroo-payment-list/index.js b/src/Resources/app/administration/src/components/buckaroo-payment-list/index.js index 2801286b..74c72326 100644 --- a/src/Resources/app/administration/src/components/buckaroo-payment-list/index.js +++ b/src/Resources/app/administration/src/components/buckaroo-payment-list/index.js @@ -94,10 +94,6 @@ Component.register("buckaroo-payment-list", { code: "klarnakp", logo: "klarna.svg" }, - { - code: "knaken", - logo: "gosettle.svg" - }, { code: "mbway", logo: "mbway.svg" diff --git a/src/Resources/app/storefront/dist/storefront/js/buckaroo-payments/buckaroo-payments.js b/src/Resources/app/storefront/dist/storefront/js/buckaroo-payments/buckaroo-payments.js index ce93c140..f4ed5f1d 100644 --- a/src/Resources/app/storefront/dist/storefront/js/buckaroo-payments/buckaroo-payments.js +++ b/src/Resources/app/storefront/dist/storefront/js/buckaroo-payments/buckaroo-payments.js @@ -1,4 +1,4 @@ -(()=>{"use strict";var e={156:e=>{var t=function(e){var t;return!!e&&"object"==typeof e&&"[object RegExp]"!==(t=Object.prototype.toString.call(e))&&"[object Date]"!==t&&e.$$typeof!==r},r="function"==typeof Symbol&&Symbol.for?Symbol.for("react.element"):60103;function n(e,t){return!1!==t.clone&&t.isMergeableObject(e)?s(Array.isArray(e)?[]:{},e,t):e}function o(e,t,r){return e.concat(t).map(function(e){return n(e,r)})}function i(e){return Object.keys(e).concat(Object.getOwnPropertySymbols?Object.getOwnPropertySymbols(e).filter(function(t){return Object.propertyIsEnumerable.call(e,t)}):[])}function a(e,t){try{return t in e}catch(e){return!1}}function s(e,r,l){(l=l||{}).arrayMerge=l.arrayMerge||o,l.isMergeableObject=l.isMergeableObject||t,l.cloneUnlessOtherwiseSpecified=n;var c,d,u=Array.isArray(r);return u!==Array.isArray(e)?n(r,l):u?l.arrayMerge(e,r,l):(d={},(c=l).isMergeableObject(e)&&i(e).forEach(function(t){d[t]=n(e[t],c)}),i(r).forEach(function(t){(!a(e,t)||Object.hasOwnProperty.call(e,t)&&Object.propertyIsEnumerable.call(e,t))&&(a(e,t)&&c.isMergeableObject(r[t])?d[t]=(function(e,t){if(!t.customMerge)return s;var r=t.customMerge(e);return"function"==typeof r?r:s})(t,c)(e[t],r[t],c):d[t]=n(r[t],c))}),d)}s.all=function(e,t){if(!Array.isArray(e))throw Error("first argument should be an array");return e.reduce(function(e,r){return s(e,r,t)},{})},e.exports=s}},t={};function r(n){var o=t[n];if(void 0!==o)return o.exports;var i=t[n]={exports:{}};return e[n](i,i.exports,r),i.exports}r.n=e=>{var t=e&&e.__esModule?()=>e.default:()=>e;return r.d(t,{a:t}),t},r.d=(e,t)=>{for(var n in t)r.o(t,n)&&!r.o(e,n)&&Object.defineProperty(e,n,{enumerable:!0,get:t[n]})},r.o=(e,t)=>Object.prototype.hasOwnProperty.call(e,t);var n=r(156),o=r.n(n);class i{static ucFirst(e){return e.charAt(0).toUpperCase()+e.slice(1)}static lcFirst(e){return e.charAt(0).toLowerCase()+e.slice(1)}static toDashCase(e){return e.replace(/([A-Z])/g,"-$1").replace(/^-/,"").toLowerCase()}static toLowerCamelCase(e,t){let r=i.toUpperCamelCase(e,t);return i.lcFirst(r)}static toUpperCamelCase(e,t){return t?e.split(t).map(e=>i.ucFirst(e.toLowerCase())).join(""):i.ucFirst(e.toLowerCase())}static parsePrimitive(e){try{return/^\d+(.|,)\d+$/.test(e)&&(e=e.replace(",",".")),JSON.parse(e)}catch(t){return e.toString()}}}class a{constructor(e=document){this._el=e,e.$emitter=this,this._listeners=[]}publish(e){let t=arguments.length>1&&void 0!==arguments[1]?arguments[1]:{},r=arguments.length>2&&void 0!==arguments[2]&&arguments[2],n=new CustomEvent(e,{detail:t,cancelable:r});return this.el.dispatchEvent(n),n}subscribe(e,t){let r=arguments.length>2&&void 0!==arguments[2]?arguments[2]:{},n=this,o=e.split("."),i=r.scope?t.bind(r.scope):t;if(r.once&&!0===r.once){let t=i;i=function(r){n.unsubscribe(e),t(r)}}return this.el.addEventListener(o[0],i),this.listeners.push({splitEventName:o,opts:r,cb:i}),!0}unsubscribe(e){let t=e.split(".");return this.listeners=this.listeners.reduce((e,r)=>([...r.splitEventName].sort().toString()===t.sort().toString()?this.el.removeEventListener(r.splitEventName[0],r.cb):e.push(r),e),[]),!0}reset(){return this.listeners.forEach(e=>{this.el.removeEventListener(e.splitEventName[0],e.cb)}),this.listeners=[],!0}get el(){return this._el}set el(e){this._el=e}get listeners(){return this._listeners}set listeners(e){this._listeners=e}}class s{constructor(e,t={},r=!1){if(!(e instanceof Node)){console.warn(`There is no valid element given while trying to create a plugin instance for "${r}".`);return}this.el=e,this.$emitter=new a(this.el),this._pluginName=this._getPluginName(r),this.options=this._mergeOptions(t),this._initialized=!1,this._registerInstance(),this._init()}init(){console.warn(`The "init" method for the plugin "${this._pluginName}" is not defined. The plugin will not be initialized.`)}update(){}_init(){this._initialized||(this.init(),this._initialized=!0)}_update(){this._initialized&&this.update()}_mergeOptions(e){let t=[this.constructor.options,this.options,e];return t.push(this._getConfigFromDataAttribute()),t.push(this._getOptionsFromDataAttribute()),o().all(t.filter(e=>e instanceof Object&&!(e instanceof Array)).map(e=>e||{}))}_getConfigFromDataAttribute(){let e={};if("function"!=typeof this.el.getAttribute)return e;let t=i.toDashCase(this._pluginName),r=this.el.getAttribute(`data-${t}-config`);return r?window.PluginConfigManager.get(this._pluginName,r):e}_getOptionsFromDataAttribute(){let e={};if("function"!=typeof this.el.getAttribute)return e;let t=i.toDashCase(this._pluginName),r=this.el.getAttribute(`data-${t}-options`);if(r)try{return JSON.parse(r)}catch(e){console.error(`The data attribute "data-${t}-options" could not be parsed to json: ${e.message}`)}return e}_registerInstance(){window.PluginManager.getPluginInstancesFromElement(this.el).set(this._pluginName,this),window.PluginManager.getPlugin(this._pluginName,!1).get("instances").push(this)}_getPluginName(e){return e||(e=this.constructor.name),e}}class l{constructor(){this._request=null,this._errorHandlingInternal=!1}get(e,t){let r=arguments.length>2&&void 0!==arguments[2]?arguments[2]:"application/json",n=this._createPreparedRequest("GET",e,r);return this._sendRequest(n,null,t)}post(e,t,r){let n=arguments.length>3&&void 0!==arguments[3]?arguments[3]:"application/json";n=this._getContentType(t,n);let o=this._createPreparedRequest("POST",e,n);return this._sendRequest(o,t,r)}delete(e,t,r){let n=arguments.length>3&&void 0!==arguments[3]?arguments[3]:"application/json";n=this._getContentType(t,n);let o=this._createPreparedRequest("DELETE",e,n);return this._sendRequest(o,t,r)}patch(e,t,r){let n=arguments.length>3&&void 0!==arguments[3]?arguments[3]:"application/json";n=this._getContentType(t,n);let o=this._createPreparedRequest("PATCH",e,n);return this._sendRequest(o,t,r)}abort(){if(this._request)return this._request.abort()}setErrorHandlingInternal(e){this._errorHandlingInternal=e}_registerOnLoaded(e,t){t&&(!0===this._errorHandlingInternal?(e.addEventListener("load",()=>{t(e.responseText,e)}),e.addEventListener("abort",()=>{console.warn(`the request to ${e.responseURL} was aborted`)}),e.addEventListener("error",()=>{console.warn(`the request to ${e.responseURL} failed with status ${e.status}`)}),e.addEventListener("timeout",()=>{console.warn(`the request to ${e.responseURL} timed out`)})):e.addEventListener("loadend",()=>{t(e.responseText,e)}))}_sendRequest(e,t,r){return this._registerOnLoaded(e,r),e.send(t),e}_getContentType(e,t){return e instanceof FormData&&(t=!1),t}_createPreparedRequest(e,t,r){return this._request=new XMLHttpRequest,this._request.open(e,t),this._request.setRequestHeader("X-Requested-With","XMLHttpRequest"),r&&this._request.setRequestHeader("Content-type",r),this._request}}class c extends s{static #e=this.options={page:"unknown",merchantId:null};init(){null===this.merchantId&&alert("Merchant id is required"),document.$emitter.subscribe("buckaroo_scripts_loaded",()=>{this.sdk=BuckarooSdk.PayPal,this.sdk.initiate(this.sdkOptions)})}onShippingChangeHandler(e,t){return this.setShipping(e).then(e=>{if(!1===e.error)return this.cartToken=e.token,this.sdkOptions.amount=e.cart.value,t.order.patch([{op:"replace",path:"/purchase_units/@reference_id=='default'/amount",value:e.cart}]);this.displayErrorMessage(e.message),t.reject(e.message)})}createPaymentHandler(e){return this.createTransaction(e.orderID)}onSuccessCallback(){!0===this.result.error?this.displayErrorMessage(message):this.result.redirect?window.location=this.result.redirect:this.displayErrorMessage(this.options.i18n.cannot_create_payment)}onErrorCallback(e){this.displayErrorMessage(e)}onCancelCallback(){this.displayErrorMessage(this.options.i18n.cancel_error_message)}onClickCallback(){this.result=null}createTransaction(e){let t={orderId:e};return this.cartToken&&(t.cartToken=this.cartToken),new Promise(e=>{this.httpClient.post(`${this.url}/paypal/pay`,JSON.stringify(t),t=>{this.result=JSON.parse(t),e(JSON.parse(t))})})}getFormData(){let e=document.getElementById("productDetailPageBuyProductForm");if(!e)return console.error("Product form not found"),null;let t=new FormData(e),r={};return t.forEach((e,t)=>{r[t]=e}),r}setShipping(e){let t={};"product"!==this.options.page||(t=this.getFormData())||console.error("[Buckaroo] Form element not found on product page.");let r={form:t,customer:e,page:this.options.page};return new Promise(e=>{this.httpClient.post(`${this.url}/paypal/create`,JSON.stringify(r),t=>{e(JSON.parse(t))})})}displayErrorMessage(e){$(".buckaroo-paypal-express-error").remove(),"object"==typeof e&&(e=this.options.i18n.cannot_create_payment);let t=` +(()=>{"use strict";var e={156(e){var t=function(e){var t;return!!e&&"object"==typeof e&&"[object RegExp]"!==(t=Object.prototype.toString.call(e))&&"[object Date]"!==t&&e.$$typeof!==n},n="function"==typeof Symbol&&Symbol.for?Symbol.for("react.element"):60103;function i(e,t){return!1!==t.clone&&t.isMergeableObject(e)?a(Array.isArray(e)?[]:{},e,t):e}function o(e,t,n){return e.concat(t).map(function(e){return i(e,n)})}function r(e){return Object.keys(e).concat(Object.getOwnPropertySymbols?Object.getOwnPropertySymbols(e).filter(function(t){return Object.propertyIsEnumerable.call(e,t)}):[])}function s(e,t){try{return t in e}catch(e){return!1}}function a(e,n,l){(l=l||{}).arrayMerge=l.arrayMerge||o,l.isMergeableObject=l.isMergeableObject||t,l.cloneUnlessOtherwiseSpecified=i;var c,d,u=Array.isArray(n);return u!==Array.isArray(e)?i(n,l):u?l.arrayMerge(e,n,l):(d={},(c=l).isMergeableObject(e)&&r(e).forEach(function(t){d[t]=i(e[t],c)}),r(n).forEach(function(t){(!s(e,t)||Object.hasOwnProperty.call(e,t)&&Object.propertyIsEnumerable.call(e,t))&&(s(e,t)&&c.isMergeableObject(n[t])?d[t]=(function(e,t){if(!t.customMerge)return a;var n=t.customMerge(e);return"function"==typeof n?n:a})(t,c)(e[t],n[t],c):d[t]=i(n[t],c))}),d)}a.all=function(e,t){if(!Array.isArray(e))throw Error("first argument should be an array");return e.reduce(function(e,n){return a(e,n,t)},{})},e.exports=a}},t={};function n(i){var o=t[i];if(void 0!==o)return o.exports;var r=t[i]={exports:{}};return e[i](r,r.exports,n),r.exports}n.n=e=>{var t=e&&e.__esModule?()=>e.default:()=>e;return n.d(t,{a:t}),t},n.d=(e,t)=>{for(var i in t)n.o(t,i)&&!n.o(e,i)&&Object.defineProperty(e,i,{enumerable:!0,get:t[i]})},n.o=(e,t)=>Object.prototype.hasOwnProperty.call(e,t);var i=n(156),o=n.n(i);class r{static ucFirst(e){return e.charAt(0).toUpperCase()+e.slice(1)}static lcFirst(e){return e.charAt(0).toLowerCase()+e.slice(1)}static toDashCase(e){return e.replace(/([A-Z])/g,"-$1").replace(/^-/,"").toLowerCase()}static toLowerCamelCase(e,t){let n=r.toUpperCamelCase(e,t);return r.lcFirst(n)}static toUpperCamelCase(e,t){return t?e.split(t).map(e=>r.ucFirst(e.toLowerCase())).join(""):r.ucFirst(e.toLowerCase())}static parsePrimitive(e){try{return/^\d+(.|,)\d+$/.test(e)&&(e=e.replace(",",".")),JSON.parse(e)}catch(t){return e.toString()}}}class s{constructor(e=document){this._el=e,e.$emitter=this,this._listeners=[]}publish(e){let t=arguments.length>1&&void 0!==arguments[1]?arguments[1]:{},n=arguments.length>2&&void 0!==arguments[2]&&arguments[2],i=new CustomEvent(e,{detail:t,cancelable:n});return this.el.dispatchEvent(i),i}subscribe(e,t){let n=arguments.length>2&&void 0!==arguments[2]?arguments[2]:{},i=this,o=e.split("."),r=n.scope?t.bind(n.scope):t;if(n.once&&!0===n.once){let t=r;r=function(n){i.unsubscribe(e),t(n)}}return this.el.addEventListener(o[0],r),this.listeners.push({splitEventName:o,opts:n,cb:r}),!0}unsubscribe(e){let t=e.split(".");return this.listeners=this.listeners.reduce((e,n)=>([...n.splitEventName].sort().toString()===t.sort().toString()?this.el.removeEventListener(n.splitEventName[0],n.cb):e.push(n),e),[]),!0}reset(){return this.listeners.forEach(e=>{this.el.removeEventListener(e.splitEventName[0],e.cb)}),this.listeners=[],!0}get el(){return this._el}set el(e){this._el=e}get listeners(){return this._listeners}set listeners(e){this._listeners=e}}class a{constructor(e,t={},n=!1){if(!(e instanceof Node)){console.warn(`There is no valid element given while trying to create a plugin instance for "${n}".`);return}this.el=e,this.$emitter=new s(this.el),this._pluginName=this._getPluginName(n),this.options=this._mergeOptions(t),this._initialized=!1,this._registerInstance(),this._init()}init(){console.warn(`The "init" method for the plugin "${this._pluginName}" is not defined. The plugin will not be initialized.`)}update(){}_init(){this._initialized||(this.init(),this._initialized=!0)}_update(){this._initialized&&this.update()}_mergeOptions(e){let t=[this.constructor.options,this.options,e];return t.push(this._getConfigFromDataAttribute()),t.push(this._getOptionsFromDataAttribute()),o().all(t.filter(e=>e instanceof Object&&!(e instanceof Array)).map(e=>e||{}))}_getConfigFromDataAttribute(){let e={};if("function"!=typeof this.el.getAttribute)return e;let t=r.toDashCase(this._pluginName),n=this.el.getAttribute(`data-${t}-config`);return n?window.PluginConfigManager.get(this._pluginName,n):e}_getOptionsFromDataAttribute(){let e={};if("function"!=typeof this.el.getAttribute)return e;let t=r.toDashCase(this._pluginName),n=this.el.getAttribute(`data-${t}-options`);if(n)try{return JSON.parse(n)}catch(e){console.error(`The data attribute "data-${t}-options" could not be parsed to json: ${e.message}`)}return e}_registerInstance(){window.PluginManager.getPluginInstancesFromElement(this.el).set(this._pluginName,this),window.PluginManager.getPlugin(this._pluginName,!1).get("instances").push(this)}_getPluginName(e){return e||(e=this.constructor.name),e}}let l="buckaroo-sdk",c=null;class d{constructor(){this._request=null,this._errorHandlingInternal=!1}get(e,t){let n=arguments.length>2&&void 0!==arguments[2]?arguments[2]:"application/json",i=this._createPreparedRequest("GET",e,n);return this._sendRequest(i,null,t)}post(e,t,n){let i=arguments.length>3&&void 0!==arguments[3]?arguments[3]:"application/json";i=this._getContentType(t,i);let o=this._createPreparedRequest("POST",e,i);return this._sendRequest(o,t,n)}delete(e,t,n){let i=arguments.length>3&&void 0!==arguments[3]?arguments[3]:"application/json";i=this._getContentType(t,i);let o=this._createPreparedRequest("DELETE",e,i);return this._sendRequest(o,t,n)}patch(e,t,n){let i=arguments.length>3&&void 0!==arguments[3]?arguments[3]:"application/json";i=this._getContentType(t,i);let o=this._createPreparedRequest("PATCH",e,i);return this._sendRequest(o,t,n)}abort(){if(this._request)return this._request.abort()}setErrorHandlingInternal(e){this._errorHandlingInternal=e}_registerOnLoaded(e,t){t&&(!0===this._errorHandlingInternal?(e.addEventListener("load",()=>{t(e.responseText,e)}),e.addEventListener("abort",()=>{console.warn(`the request to ${e.responseURL} was aborted`)}),e.addEventListener("error",()=>{console.warn(`the request to ${e.responseURL} failed with status ${e.status}`)}),e.addEventListener("timeout",()=>{console.warn(`the request to ${e.responseURL} timed out`)})):e.addEventListener("loadend",()=>{t(e.responseText,e)}))}_sendRequest(e,t,n){return this._registerOnLoaded(e,n),e.send(t),e}_getContentType(e,t){return e instanceof FormData&&(t=!1),t}_createPreparedRequest(e,t,n){return this._request=new XMLHttpRequest,this._request.open(e,t),this._request.setRequestHeader("X-Requested-With","XMLHttpRequest"),n&&this._request.setRequestHeader("Content-type",n),this._request}}class u extends a{static #e=this.options={page:"unknown",merchantId:null,isTestMode:!1};init(){null===this.merchantId&&alert("Merchant id is required"),document.$emitter.subscribe("buckaroo_scripts_loaded",()=>{this.sdk=BuckarooSdk.PayPal,this.setSdkTestMode(),this.sdk.initiate(this.sdkOptions)})}setSdkTestMode(){void 0!==BuckarooSdk.Base&&"function"==typeof BuckarooSdk.Base.setTestMode&&BuckarooSdk.Base.setTestMode(!0===this.options.isTestMode)}onShippingChangeHandler(e,t){return this.setShipping(e).then(e=>{if(!1===e.error)return this.cartToken=e.token,this.sdkOptions.amount=e.cart.value,t.order.patch([{op:"replace",path:"/purchase_units/@reference_id=='default'/amount",value:e.cart}]);this.displayErrorMessage(e.message),t.reject(e.message)})}createPaymentHandler(e){return this.createTransaction(e.orderID)}onSuccessCallback(){if(null===this.result||void 0===this.result){this.displayErrorMessage(this.options.i18n.cannot_create_payment);return}!0===this.result.error?this.displayErrorMessage(this.result.message||this.options.i18n.cannot_create_payment):this.result.redirect?window.location=this.result.redirect:this.displayErrorMessage(this.options.i18n.cannot_create_payment)}onErrorCallback(e){this.displayErrorMessage(e)}onCancelCallback(){this.displayErrorMessage(this.options.i18n.cancel_error_message)}onClickCallback(){this.result=null}createTransaction(e){let t={orderId:e};return this.cartToken&&(t.cartToken=this.cartToken),new Promise(e=>{this.httpClient.post(`${this.url}/paypal/pay`,JSON.stringify(t),t=>{this.result=JSON.parse(t),e(JSON.parse(t))})})}getFormData(){let e=document.getElementById("productDetailPageBuyProductForm");if(!e)return console.error("Product form not found"),null;let t=new FormData(e),n={};return t.forEach((e,t)=>{n[t]=e}),n}setShipping(e){let t={};"product"!==this.options.page||(t=this.getFormData())||console.error("[Buckaroo] Form element not found on product page.");let n={form:t,customer:e,page:this.options.page};return new Promise(e=>{this.httpClient.post(`${this.url}/paypal/create`,JSON.stringify(n),t=>{e(JSON.parse(t))})})}displayErrorMessage(e){$(".buckaroo-paypal-express-error").remove(),"object"==typeof e&&(e=this.options.i18n.cannot_create_payment);let t=` - `;$(".flashbags").first().prepend(t),setTimeout(function(){$(".buckaroo-paypal-express-error").fadeOut(1e3)},1e4)}constructor(...e){super(...e),this.httpClient=new l,this.url="/buckaroo",this.result=null,this.sdkOptions={containerSelector:".buckaroo-paypal-express",buckarooWebsiteKey:this.options.websiteKey,paypalMerchantId:this.options.merchantId,currency:"EUR",amount:.1,createPaymentHandler:this.createPaymentHandler.bind(this),onShippingChangeHandler:this.onShippingChangeHandler.bind(this),onSuccessCallback:this.onSuccessCallback.bind(this),onErrorCallback:this.onErrorCallback.bind(this),onCancelCallback:this.onCancelCallback.bind(this),onClickCallback:this.onClickCallback.bind(this)}}}class d extends s{static #e=this.options={page:"unknown",merchantId:null,websiteKey:null,i18n:{cancel_error_message:"Payment was cancelled.",cannot_create_payment:"Cannot create the payment. Please try again.",customer_not_found:"You must be logged in to perform this action.",general_error:"An error occurred while processing your payment."}};init(){let e=document.querySelector("[data-buckaroo-ideal-fast-checkout-plugin-options]");if(!e){console.error("Plugin options element not found");return}let t=e.getAttribute("data-buckaroo-ideal-fast-checkout-plugin-options");if(!t){console.error("No data found in plugin options");return}let r=JSON.parse(t);this.options.page=r.page;let n=document.getElementById("fast-checkout-ideal-btn");if(!n){console.error("Ideal Fast Checkout button not found");return}n.addEventListener("click",e=>this.initPayment(e))}initPayment(e){e.preventDefault();let t=document.getElementById("fast-checkout-ideal-btn");t&&t.setAttribute("disabled","disabled"),this.createCart().finally(()=>{t&&t.removeAttribute("disabled")})}createCart(){let e={};if("product"===this.options.page&&(e=this.getFormData()),!e){console.error("Form data could not be retrieved");return}return this.sendPostRequest(`${this.url}/idealfastcheckout/pay`,{form:e,page:this.options.page}).then(e=>{if(e.redirect)window.location=e.redirect;else if(e.errorCode)this.handleErrorResponse(e);else{let t=e.message||this.options.i18n.cannot_create_payment;this.displayErrorMessage(t)}}).catch(e=>{console.error("Error creating cart:",e),this.displayErrorMessage(this.options.i18n.general_error)})}handleErrorResponse(e){let t=e.message||this.options.i18n.general_error;"CUSTOMER_NOT_FOUND"===e.errorCode&&(t=this.options.i18n.customer_not_found),this.displayErrorMessage(t)}getFormData(){let e=document.getElementById("productDetailPageBuyProductForm");if(!e)return console.error("Product form not found"),null;let t=new FormData(e),r={};return t.forEach((e,t)=>{r[t]=e}),r}sendPostRequest(e,t){return new Promise((r,n)=>{this.httpClient.post(e,JSON.stringify(t),e=>{try{let t=JSON.parse(e);r(t)}catch(e){console.error("Error parsing response:",e),n(e)}})})}displayErrorMessage(e){let t=document.createElement("div");t.className="buckaroo-idealfastcheckout-express-error alert alert-warning alert-has-icon",t.innerHTML=` + `;$(".flashbags").first().prepend(t),setTimeout(function(){$(".buckaroo-paypal-express-error").fadeOut(1e3)},1e4)}constructor(...e){super(...e),this.httpClient=new d,this.url="/buckaroo",this.result=null,this.sdkOptions={containerSelector:".buckaroo-paypal-express",buckarooWebsiteKey:this.options.websiteKey,paypalMerchantId:this.options.merchantId,isTestMode:!0===this.options.isTestMode,currency:"EUR",amount:.1,createPaymentHandler:this.createPaymentHandler.bind(this),onShippingChangeHandler:this.onShippingChangeHandler.bind(this),onSuccessCallback:this.onSuccessCallback.bind(this),onErrorCallback:this.onErrorCallback.bind(this),onCancelCallback:this.onCancelCallback.bind(this),onClickCallback:this.onClickCallback.bind(this)}}}class p extends a{static #e=this.options={page:"unknown",merchantId:null,websiteKey:null,i18n:{cancel_error_message:"Payment was cancelled.",cannot_create_payment:"Cannot create the payment. Please try again.",customer_not_found:"You must be logged in to perform this action.",general_error:"An error occurred while processing your payment."}};init(){let e=document.querySelector("[data-buckaroo-ideal-fast-checkout-plugin-options]");if(!e){console.error("Plugin options element not found");return}let t=e.getAttribute("data-buckaroo-ideal-fast-checkout-plugin-options");if(!t){console.error("No data found in plugin options");return}let n=JSON.parse(t);this.options.page=n.page;let i=document.getElementById("fast-checkout-ideal-btn");if(!i){console.error("Ideal Fast Checkout button not found");return}i.addEventListener("click",e=>this.initPayment(e))}initPayment(e){e.preventDefault();let t=document.getElementById("fast-checkout-ideal-btn");t&&t.setAttribute("disabled","disabled"),this.createCart().finally(()=>{t&&t.removeAttribute("disabled")})}createCart(){let e={};if("product"===this.options.page&&(e=this.getFormData()),!e){console.error("Form data could not be retrieved");return}return this.sendPostRequest(`${this.url}/idealfastcheckout/pay`,{form:e,page:this.options.page}).then(e=>{if(e.redirect)window.location=e.redirect;else if(e.errorCode)this.handleErrorResponse(e);else{let t=e.message||this.options.i18n.cannot_create_payment;this.displayErrorMessage(t)}}).catch(e=>{console.error("Error creating cart:",e),this.displayErrorMessage(this.options.i18n.general_error)})}handleErrorResponse(e){let t=e.message||this.options.i18n.general_error;"CUSTOMER_NOT_FOUND"===e.errorCode&&(t=this.options.i18n.customer_not_found),this.displayErrorMessage(t)}getFormData(){let e=document.getElementById("productDetailPageBuyProductForm");if(!e)return console.error("Product form not found"),null;let t=new FormData(e),n={};return t.forEach((e,t)=>{n[t]=e}),n}sendPostRequest(e,t){return new Promise((n,i)=>{this.httpClient.post(e,JSON.stringify(t),e=>{try{let t=JSON.parse(e);n(t)}catch(e){console.error("Error parsing response:",e),i(e)}})})}displayErrorMessage(e){let t=document.createElement("div");t.className="buckaroo-idealfastcheckout-express-error alert alert-warning alert-has-icon",t.innerHTML=` !
${e}
- `;let r=document.querySelector(".flashbags");r&&(r.prepend(t),setTimeout(()=>t.remove(),1e4))}constructor(...e){super(...e),this.httpClient=new l,this.url="/buckaroo",this.result=null,this.cartToken=null}}class u{static serialize(e){let t=!(arguments.length>1)||void 0===arguments[1]||arguments[1];if("FORM"!==e.nodeName){if(t)throw Error("The passed element is not a form!");return{}}return new FormData(e)}static serializeJson(e){let t=!(arguments.length>1)||void 0===arguments[1]||arguments[1],r=u.serialize(e,t);if(!(r instanceof FormData)&&0===Object.keys(r).length||r instanceof FormData&&0===Array.from(r.entries()).length)return{};let n={};for(let[e,t]of r.entries())n[e]=t;return n}}class h extends s{static #e=this.options={page:"unknown",productId:null,merchantId:null,gatewayMerchantId:null,merchantName:"",buttonColor:"default",environment:"TEST"};init(){this.options.merchantId&&this.options.gatewayMerchantId&&("checkout"===this.options.page&&(window.isGooglePay=!0,this.setConfirmButtonDisabled(!0)),this.loadBuckarooSdk().then(()=>this.retrieveCartData()).then(e=>this.checkIsAvailable(e).then(t=>{t?this.renderButton(e):"checkout"===this.options.page&&(window.isGooglePay=!1,this.setConfirmButtonDisabled(!1))})).catch(()=>{"checkout"===this.options.page&&(window.isGooglePay=!1,this.setConfirmButtonDisabled(!1))}))}setConfirmButtonDisabled(e){let t=document.getElementById("confirmFormSubmit");t&&(t.disabled=e)}_loadScript(e,t,r){let n=arguments.length>3&&void 0!==arguments[3]?arguments[3]:50;return new Promise((o,i)=>{if(t()){o();return}let a=function(){let e=arguments.length>0&&void 0!==arguments[0]?arguments[0]:0;if(t()){o();return}if(e>=n){i(Error(r+" not available after "+n/10+"s"));return}setTimeout(()=>a(e+1),100)};if(document.querySelector('script[src="'+e+'"]')){a();return}let s=document.createElement("script");s.src=e,s.async=!0,s.onload=()=>a(),s.onerror=e=>i(e),document.head.appendChild(s)})}loadBuckarooSdk(){return Promise.all([this._loadScript("https://checkout.buckaroo.nl/api/buckaroosdk/script",()=>!!(window.BuckarooSdk&&window.BuckarooSdk.GooglePay),"BuckarooSdk.GooglePay"),this._loadScript("https://pay.google.com/gp/p/js/pay.js",()=>!!(window.google&&window.google.payments&&window.google.payments.api),"google.payments.api")])}checkIsAvailable(e){return new Promise(e=>{if(!window.BuckarooSdk||!window.BuckarooSdk.GooglePay||!window.google||!window.google.payments||!window.google.payments.api){e(!1);return}let t="PRODUCTION"===this.options.environment?"PRODUCTION":"TEST";new window.google.payments.api.PaymentsClient({environment:t}).isReadyToPay({apiVersion:2,apiVersionMinor:0,allowedPaymentMethods:[{type:"CARD",parameters:{allowedAuthMethods:["PAN_ONLY","CRYPTOGRAM_3DS"],allowedCardNetworks:["MASTERCARD","VISA"]}}]}).then(t=>e(!!t.result)).catch(()=>e(!1))})}renderButton(e){"checkout"===this.options.page?this._wireCheckoutConfirmButton(e):this._renderNativeButton(e)}_wireCheckoutConfirmButton(e){this.setConfirmButtonDisabled(!1);let t=document.getElementById("confirmFormSubmit");if(!t){window.isGooglePay=!1;return}t.addEventListener("click",t=>{t.preventDefault(),t.stopPropagation(),this.setConfirmButtonDisabled(!0),this._openPaymentSheet(e)})}_renderNativeButton(e){let t=document.getElementById("google-pay-button-container");if(!t)return;let r="PRODUCTION"===this.options.environment?"PRODUCTION":"TEST",n=new window.google.payments.api.PaymentsClient({environment:r}),o="white"===this.options.buttonColor?"white":"black",i=n.createButton({buttonColor:o,buttonType:"buy",buttonSizeMode:"fill",onClick:()=>this._openPaymentSheet(e)});t.innerHTML="",t.appendChild(i)}_openPaymentSheet(e){let t="PRODUCTION"===this.options.environment?"PRODUCTION":"TEST",r=new window.google.payments.api.PaymentsClient({environment:t}),n={apiVersion:2,apiVersionMinor:0,merchantInfo:{merchantId:this.options.merchantId,merchantName:e.storeName||this.options.merchantName},allowedPaymentMethods:[{type:"CARD",parameters:{allowedAuthMethods:["PAN_ONLY","CRYPTOGRAM_3DS"],allowedCardNetworks:["MASTERCARD","VISA"]},tokenizationSpecification:{type:"PAYMENT_GATEWAY",parameters:{gateway:"buckaroo",gatewayMerchantId:e.gatewayMerchantId||this.options.gatewayMerchantId}}}],transactionInfo:{totalPriceStatus:"FINAL",totalPrice:e.totalPrice||"0.01",currencyCode:e.currency||"EUR",countryCode:e.country||"NL"}};r.loadPaymentData(n).then(t=>this.captureFunds(t,e)).then(e=>{(!e||!e.success)&&(this.setConfirmButtonDisabled(!1),e&&e.error&&this.displayErrorMessage(e.error))}).catch(e=>{this.setConfirmButtonDisabled(!1),e&&"CANCELED"!==e.statusCode&&this.displayErrorMessage("Could not complete Google Pay payment.")})}retrieveCartData(){let e=null;if("product"===this.options.page){let t=this.el.closest("form")||document.getElementById("productDetailPageBuyProductForm")||document.querySelector("[data-product-detail-buy-form]")||document.querySelector("form[action*='line-item/add'], form[action*='add-to-cart']");if(t){let r=u.serializeJson(t);r&&Object.keys(r).some(e=>e.includes("lineItems"))&&(e=r)}if(!e&&this.options.productId){let t=this.options.productId,r=document.querySelector(`input[name="lineItems[${t}][quantity]"], .product-detail-quantity-select, [data-quantity-selector] input, [data-quantity-selector] select`);e={[`lineItems[${t}][id]`]:t,[`lineItems[${t}][referencedId]`]:t,[`lineItems[${t}][type]`]:"product",[`lineItems[${t}][quantity]`]:String(r&&parseInt(r.value,10)||1),[`lineItems[${t}][stackable]`]:"1",[`lineItems[${t}][removable]`]:"1"}}}let t={form:e,page:this.options.page};return new Promise((e,r)=>{this.httpClient.post(`${this.url}/googlepay/cart/get`,JSON.stringify(t),t=>{let n=JSON.parse(t);if(n.error){if(n.emptyCart){let e=document.getElementById("google-pay-button-container");e&&(e.style.display="none"),r(n.message);return}this.displayErrorMessage(n.message),r(n.message)}else this.cartToken=n.cartToken,e(n)})})}captureFunds(e,t){let r={payment:JSON.stringify(e),cartToken:this.cartToken,page:this.options.page};return new Promise(e=>{this.httpClient.post(`${this.url}/googlepay/order/create`,JSON.stringify(r),t=>{let r=null;try{r=t?JSON.parse(t):null}catch(e){}if(r&&r.redirect)e({success:!0}),window.location=r.redirect;else{let t=r&&r.message||"Could not complete Google Pay payment.";this.displayErrorMessage(t),e({success:!1,error:t})}})})}displayErrorMessage(e){let t=document.querySelector(".buckaroo-googlepay-error");t&&t.remove(),"object"==typeof e&&(e="Could not complete Google Pay payment.");let r=` + `;let n=document.querySelector(".flashbags");n&&(n.prepend(t),setTimeout(()=>t.remove(),1e4))}constructor(...e){super(...e),this.httpClient=new d,this.url="/buckaroo",this.result=null,this.cartToken=null}}class h{static serialize(e){let t=!(arguments.length>1)||void 0===arguments[1]||arguments[1];if("FORM"!==e.nodeName){if(t)throw Error("The passed element is not a form!");return{}}return new FormData(e)}static serializeJson(e){let t=!(arguments.length>1)||void 0===arguments[1]||arguments[1],n=h.serialize(e,t);if(!(n instanceof FormData)&&0===Object.keys(n).length||n instanceof FormData&&0===Array.from(n.entries()).length)return{};let i={};for(let[e,t]of n.entries())i[e]=t;return i}}let m={PayPayment:function(e){var t=this;this.applePayVersion=4,this.validationUrl="https://applepay.buckaroo.io/v1/request-session",this.abortSession=function(){t.session&&t.session.abort()},this.init=function(){},this.validate=function(){if(!t.options.processCallback)throw"ApplePay: processCallback must be set";if(!t.options.storeName)throw"ApplePay: storeName is not set";if(!t.options.countryCode)throw"ApplePay: countryCode is not set";if(!t.options.currencyCode)throw"ApplePay: currencyCode is not set"},this.beginPayment=function(){var e={countryCode:t.options.countryCode,currencyCode:t.options.currencyCode,merchantCapabilities:t.options.merchantCapabilities,supportedNetworks:t.options.supportedNetworks,lineItems:t.options.lineItems,total:t.options.totalLineItem,requiredBillingContactFields:t.options.requiredBillingContactFields,requiredShippingContactFields:t.options.requiredShippingContactFields,shippingType:t.options.shippingType,shippingMethods:t.options.shippingMethods};t.session=new ApplePaySession(t.applePayVersion,e),t.session.onvalidatemerchant=t.onValidateMerchant,t.options.shippingMethodSelectedCallback&&(t.session.onshippingmethodselected=t.onShippingMethodSelected),t.options.shippingContactSelectedCallback&&(t.session.onshippingcontactselected=t.onShippingContactSelected),t.options.cancelCallback&&(t.session.oncancel=t.onCancel),t.session.onpaymentauthorized=t.onPaymentAuthorized,t.session.begin()},this.onValidateMerchant=function(e){var n={validationUrl:e.validationURL,displayName:t.options.storeName,domainName:window.location.hostname,merchantIdentifier:t.options.merchantIdentifier};fetch(t.validationUrl,{method:"POST",body:JSON.stringify(n)}).then(function(e){if(!e.ok)throw Error("Merchant validation failed: HTTP "+e.status);return e.json()}).then(function(e){if(!e||e.statusCode>=400||e.error)throw Error("Merchant validation failed: invalid merchant session");t.session.completeMerchantValidation(e)}).catch(function(e){console.warn("Apple Pay merchant validation failed:",e),t.abortSession()})},this.onPaymentAuthorized=function(e){var n=e.payment;t.options.processCallback(n).then(function(e){t.session.completePayment(e)})},this.onShippingMethodSelected=function(e){t.options.shippingMethodSelectedCallback&&t.options.shippingMethodSelectedCallback(e.shippingMethod).then(function(e){e&&t.session.completeShippingMethodSelection(e)})},this.onShippingContactSelected=function(e){t.options.shippingContactSelectedCallback&&t.options.shippingContactSelectedCallback(e.shippingContact).then(function(e){e&&t.session.completeShippingContactSelection(e)})},this.onCancel=function(e){t.options.cancelCallback&&t.options.cancelCallback(e)},this.options=e,this.init(),this.validate()},PayOptions:function(e,t,n,i,o,r,s,a,l,c,d,u,p,h,m,y,g){void 0===d&&(d=null),void 0===u&&(u=null),void 0===p&&(p=["email","name","postalAddress"]),void 0===h&&(h=["email","name","postalAddress"]),void 0===m&&(m=null),void 0===y&&(y=["supports3DS","supportsCredit","supportsDebit"]),void 0===g&&(g=["masterCard","visa","maestro","vPay","cartesBancaires","privateLabel"]),this.storeName=e,this.countryCode=t,this.currencyCode=n,this.cultureCode=i,this.merchantIdentifier=o,this.lineItems=r,this.totalLineItem=s,this.shippingType=a,this.shippingMethods=l,this.processCallback=c,this.shippingMethodSelectedCallback=d,this.shippingContactSelectedCallback=u,this.requiredBillingContactFields=p,this.requiredShippingContactFields=h,this.cancelCallback=m,this.merchantCapabilities=y,this.supportedNetworks=g},checkPaySupport:async function(e){if(!("ApplePaySession"in window)||"undefined"==typeof ApplePaySession||!1===window.isSecureContext)return!1;let t=function(){try{return!0===ApplePaySession.canMakePayments()}catch(e){return!1}};try{if("function"==typeof ApplePaySession.applePayCapabilities)try{let n=await ApplePaySession.applePayCapabilities(e);if(n&&"applePayUnsupported"!==n.paymentCredentialStatus)return!0;return t()}catch(e){}return t()}catch(e){return!1}},loadOfficialSdk:function(){return new Promise(function(e){if(void 0!==window.ApplePaySession&&"function"==typeof ApplePaySession.applePayCapabilities){e();return}let t=document.getElementById("apple-pay-sdk");if(t){t.addEventListener("load",function(){e()}),t.addEventListener("error",function(){e()});return}let n=document.createElement("script");n.id="apple-pay-sdk",n.src="https://applepay.cdn-apple.com/jsapi/1.latest/apple-pay-sdk.js",n.crossOrigin="anonymous",n.onload=function(){e()},n.onerror=function(){e()},document.head.appendChild(n)})},createButton:function(e){let t="string"==typeof(e=e||{}).locale&&""!==e.locale.trim()?e.locale:"undefined"!=typeof navigator&&navigator.language||"en-US",n=document.createElement("apple-pay-button");return n.setAttribute("locale",t),n.setAttribute("buttonstyle",e.buttonStyle||"black"),n.setAttribute("type",e.buttonType||"plain"),n.style.width="100%",n.style.cursor="pointer",n}};class y extends a{static #e=this.options={page:"unknown",merchantId:null,cultureCode:"nl-NL"};init(){let e="checkout"===this.options.page;e&&(window.isApplePay=!0,this.setConfirmButtonDisabled(!0)),document.$emitter.subscribe("buckaroo_scripts_jquery_loaded",()=>{m.loadOfficialSdk().then(()=>this.retrieveCartData()).then(e=>{this.cartData=e,this.renderButton(e)}).catch(()=>{e&&(window.isApplePay=!1,this.setConfirmButtonDisabled(!1))})})}setConfirmButtonDisabled(e){let t=document.getElementById("confirmFormSubmit");t&&(t.disabled=e)}renderButton(e){"checkout"===this.options.page?this.wireCheckoutConfirmButton(e):this.renderExpressButton(e)}wireCheckoutConfirmButton(e){this.setConfirmButtonDisabled(!1);let t=document.getElementById("confirmFormSubmit");t&&document.addEventListener("click",n=>{let i=n.target;if(i!==t&&!(i&&i.closest&&i.closest("#confirmFormSubmit")))return;n.preventDefault(),n.stopImmediatePropagation();let o=document.forms.confirmOrderForm;(!o||o.reportValidity())&&this.initApplePayment(e)},!0)}renderExpressButton(e){let t=$(".bk-apple-pay-button");t.empty();let n=m.createButton({buttonStyle:"black",locale:this.options.cultureCode});n.addEventListener("click",t=>{t.preventDefault(),this.initApplePayment(e)}),t.append(n)}retrieveCartData(){let e=null;if("product"===this.options.page){let t=this.el.closest("form");t&&(e=h.serializeJson(t))}return new Promise((t,n)=>{this.httpClient.post(`${this.url}/apple/cart/get`,JSON.stringify({form:e,page:this.options.page,productId:this.options.productId||null}),e=>{let i=JSON.parse(e);i.error?n(i.message):(this.cartToken=i.cartToken,t(i))})})}initApplePayment(e){try{let t=new m.PayOptions(e.storeName,e.country,e.currency,this.options.cultureCode,this.options.merchantId,e.lineItems,e.totals,"shipping",this.isCheckout(e.shippingMethods,[]),this.captureFunds.bind(this),this.isCheckout(this.updateCart.bind(this),null),this.isCheckout(this.updateCart.bind(this),null),this.isCheckout(["email","name","postalAddress"],["name"]),this.isCheckout(["email","name","postalAddress"],[]));this.payment=new m.PayPayment(t),this.payment.beginPayment()}catch(e){console.warn("Apple Pay could not open the payment sheet:",e),this.displayErrorMessage(this.options.i18n&&this.options.i18n.cannot_create_payment||"Apple Pay is not available in this browser."),"checkout"===this.options.page&&this.setConfirmButtonDisabled(!1)}}isCheckout(e,t){return"checkout"===this.options.page?t:e}captureFunds(e){return new Promise(t=>{this.httpClient.post(`${this.url}/apple/order/create`,JSON.stringify({payment:JSON.stringify(e),cartToken:this.cartToken,page:this.options.page}),e=>{let n=null;try{n=JSON.parse(e)}catch(e){n={error:!0}}if(n&&n.redirect)t({status:ApplePaySession.STATUS_SUCCESS,errors:[]}),window.location=n.redirect;else{let e=this.options.i18n.cannot_create_payment;n&&n.message&&(e=n.message),this.displayErrorMessage(e),t({status:ApplePaySession.STATUS_FAILURE,errors:[]})}})})}updateCart(e){let t={cartToken:this.cartToken};return void 0!==e.identifier&&(t={...t,shippingMethod:e.identifier}),void 0!==e.countryCode&&(t={...t,shippingContact:e}),new Promise(e=>{this.httpClient.post(`${this.url}/apple/cart/update`,JSON.stringify(t),t=>{let n=null;try{n=JSON.parse(t)}catch(e){n={error:!0,message:null}}if(n.error){n.message&&(this.displayErrorMessage(n.message),console.warn(n.message));let t=[];"function"==typeof ApplePayError&&t.push(new ApplePayError("shippingContactInvalid","postalAddress","string"==typeof n.message&&""!==n.message?n.message:"This address cannot be processed.")),e({newTotal:this.cartData?this.cartData.totals:void 0,newLineItems:this.cartData?this.cartData.lineItems:void 0,errors:t});return}e({newTotal:n.newTotal,newLineItems:n.newLineItems,newShippingMethods:n.newShippingMethods})})})}checkIsAvailable(){return m.checkPaySupport(this.options.merchantId)}displayErrorMessage(e){$(".buckaroo-apple-error").remove(),"object"==typeof e&&(e=this.options.i18n.cannot_create_payment);let t=` + + `;$(".flashbags").first().prepend(t),setTimeout(function(){$(".buckaroo-apple-error").fadeOut(1e3)},1e4)}constructor(...e){super(...e),this.httpClient=new d,this.url="/buckaroo",this.result=null,this.cartData=null}}class g extends a{static #e=this.options={page:"unknown",productId:null,merchantId:null,gatewayMerchantId:null,merchantName:"",buttonColor:"default",environment:"TEST"};init(){this.options.merchantId&&this.options.gatewayMerchantId&&("checkout"===this.options.page&&(window.isGooglePay=!0,this.setConfirmButtonDisabled(!0)),this.loadBuckarooSdk().then(()=>this.retrieveCartData()).then(e=>this.checkIsAvailable(e).then(t=>{t?this.renderButton(e):"checkout"===this.options.page&&(window.isGooglePay=!1,this.setConfirmButtonDisabled(!1))})).catch(()=>{"checkout"===this.options.page&&(window.isGooglePay=!1,this.setConfirmButtonDisabled(!1))}))}setConfirmButtonDisabled(e){let t=document.getElementById("confirmFormSubmit");t&&(t.disabled=e)}_loadScript(e,t,n){let i=arguments.length>3&&void 0!==arguments[3]?arguments[3]:50;return new Promise((o,r)=>{if(t()){o();return}let s=function(){let e=arguments.length>0&&void 0!==arguments[0]?arguments[0]:0;if(t()){o();return}if(e>=i){r(Error(n+" not available after "+i/10+"s"));return}setTimeout(()=>s(e+1),100)};if(document.querySelector('script[src="'+e+'"]')){s();return}let a=document.createElement("script");a.src=e,a.async=!0,a.onload=()=>s(),a.onerror=e=>r(e),document.head.appendChild(a)})}loadBuckarooSdk(){return Promise.all([this._loadScript("https://checkout.buckaroo.nl/api/buckaroosdk/script",()=>!!(window.BuckarooSdk&&window.BuckarooSdk.GooglePay),"BuckarooSdk.GooglePay"),this._loadScript("https://pay.google.com/gp/p/js/pay.js",()=>!!(window.google&&window.google.payments&&window.google.payments.api),"google.payments.api")])}checkIsAvailable(e){return new Promise(e=>{if(!window.BuckarooSdk||!window.BuckarooSdk.GooglePay||!window.google||!window.google.payments||!window.google.payments.api){e(!1);return}let t="PRODUCTION"===this.options.environment?"PRODUCTION":"TEST";new window.google.payments.api.PaymentsClient({environment:t}).isReadyToPay({apiVersion:2,apiVersionMinor:0,allowedPaymentMethods:[{type:"CARD",parameters:{allowedAuthMethods:["PAN_ONLY","CRYPTOGRAM_3DS"],allowedCardNetworks:["MASTERCARD","VISA"]}}]}).then(t=>e(!!t.result)).catch(()=>e(!1))})}renderButton(e){"checkout"===this.options.page?this._wireCheckoutConfirmButton(e):this._renderNativeButton(e)}_wireCheckoutConfirmButton(e){this.setConfirmButtonDisabled(!1);let t=document.getElementById("confirmFormSubmit");if(!t){window.isGooglePay=!1;return}t.addEventListener("click",t=>{t.preventDefault(),t.stopPropagation(),this.setConfirmButtonDisabled(!0),this._openPaymentSheet(e)})}_renderNativeButton(e){let t=document.getElementById("google-pay-button-container");if(!t)return;let n="PRODUCTION"===this.options.environment?"PRODUCTION":"TEST",i=new window.google.payments.api.PaymentsClient({environment:n}),o="white"===this.options.buttonColor?"white":"black",r=i.createButton({buttonColor:o,buttonType:"buy",buttonSizeMode:"fill",onClick:()=>this._openPaymentSheet(e)});t.innerHTML="",t.appendChild(r)}_openPaymentSheet(e){let t="PRODUCTION"===this.options.environment?"PRODUCTION":"TEST",n=new window.google.payments.api.PaymentsClient({environment:t}),i={apiVersion:2,apiVersionMinor:0,merchantInfo:{merchantId:this.options.merchantId,merchantName:e.storeName||this.options.merchantName},allowedPaymentMethods:[{type:"CARD",parameters:{allowedAuthMethods:["PAN_ONLY","CRYPTOGRAM_3DS"],allowedCardNetworks:["MASTERCARD","VISA"]},tokenizationSpecification:{type:"PAYMENT_GATEWAY",parameters:{gateway:"buckaroo",gatewayMerchantId:e.gatewayMerchantId||this.options.gatewayMerchantId}}}],transactionInfo:{totalPriceStatus:"FINAL",totalPrice:e.totalPrice||"0.01",currencyCode:e.currency||"EUR",countryCode:e.country||"NL"}};n.loadPaymentData(i).then(t=>this.captureFunds(t,e)).then(e=>{(!e||!e.success)&&(this.setConfirmButtonDisabled(!1),e&&e.error&&this.displayErrorMessage(e.error))}).catch(e=>{this.setConfirmButtonDisabled(!1),e&&"CANCELED"!==e.statusCode&&this.displayErrorMessage("Could not complete Google Pay payment.")})}retrieveCartData(){let e=null;if("product"===this.options.page){let t=this.el.closest("form")||document.getElementById("productDetailPageBuyProductForm")||document.querySelector("[data-product-detail-buy-form]")||document.querySelector("form[action*='line-item/add'], form[action*='add-to-cart']");if(t){let n=h.serializeJson(t);n&&Object.keys(n).some(e=>e.includes("lineItems"))&&(e=n)}if(!e&&this.options.productId){let t=this.options.productId,n=document.querySelector(`input[name="lineItems[${t}][quantity]"], .product-detail-quantity-select, [data-quantity-selector] input, [data-quantity-selector] select`);e={[`lineItems[${t}][id]`]:t,[`lineItems[${t}][referencedId]`]:t,[`lineItems[${t}][type]`]:"product",[`lineItems[${t}][quantity]`]:String(n&&parseInt(n.value,10)||1),[`lineItems[${t}][stackable]`]:"1",[`lineItems[${t}][removable]`]:"1"}}}let t={form:e,page:this.options.page};return new Promise((e,n)=>{this.httpClient.post(`${this.url}/googlepay/cart/get`,JSON.stringify(t),t=>{let i=JSON.parse(t);if(i.error){if(i.emptyCart){let e=document.getElementById("google-pay-button-container");e&&(e.style.display="none"),n(i.message);return}this.displayErrorMessage(i.message),n(i.message)}else this.cartToken=i.cartToken,e(i)})})}captureFunds(e,t){let n={payment:JSON.stringify(e),cartToken:this.cartToken,page:this.options.page};return new Promise(e=>{this.httpClient.post(`${this.url}/googlepay/order/create`,JSON.stringify(n),t=>{let n=null;try{n=t?JSON.parse(t):null}catch(e){}if(n&&n.redirect)e({success:!0}),window.location=n.redirect;else{let t=n&&n.message||"Could not complete Google Pay payment.";this.displayErrorMessage(t),e({success:!1,error:t})}})})}displayErrorMessage(e){let t=document.querySelector(".buckaroo-googlepay-error");t&&t.remove(),"object"==typeof e&&(e="Could not complete Google Pay payment.");let n=` `,n=document.querySelector(".flashbags");n&&(n.insertAdjacentHTML("afterbegin",r),setTimeout(()=>{let e=document.querySelector(".buckaroo-googlepay-error");e&&(e.style.transition="opacity 1s",e.style.opacity="0",setTimeout(()=>e.remove(),1e3))},1e4))}constructor(...e){super(...e),this.httpClient=new l,this.url="/buckaroo",this.cartToken=null,this.googlePayment=null}}class m extends s{static #e=this.options={orderId:null,pullUrl:null,interval:5e3};init(){this.pullStatus()}pullStatus(){setInterval(this.singlePullStatus.bind(this),this.options.interval)}singlePullStatus(){this.options,this.httpClient.post(this.options.pullUrl,JSON.stringify({orderId:this.options.orderId}),e=>{let t=JSON.parse(e);void 0!==t.redirectUrl&&(window.location.href=t.redirectUrl)})}constructor(...e){super(...e),this.httpClient=new l}}let p="bk-is-mobile",y="bk-paybybank-selected";class g extends s{static #e=this.options={issuerSelected:""};init(){this.listenToIsMobile(),this.onPageLoad(),this.listenToResize(),this.listenToIssuerChange(),this.togglePayByBankList(),this.emitSavedIssuer()}emitSavedIssuer(){"string"==typeof this.options.issuerSelected&&this.options.issuerSelected.length>0&&document.$emitter.publish(y,{code:this.options.issuerSelected,source:"other"})}onPageLoad(){document.$emitter.publish(p,{isMobile:768>(window.innerWidth||document.documentElement.clientWidth||document.body.clientWidth)})}listenToResize(){window.addEventListener("resize",(function(){let e=window.innerWidth||document.documentElement.clientWidth||document.body.clientWidth,t=!1;e<768&&(t=!0),this.isMobile!==t&&document.$emitter.publish(p,{isMobile:t})}).bind(this))}listenToIsMobile(){document.$emitter.subscribe(p,(function(e){this.isMobile=e.detail.isMobile,this.toggleInputType()}).bind(this))}toggleInputType(){let e=document.querySelector(".bk-paybybank-mobile"),t=document.querySelector(".bk-paybybank-not-mobile");this.isMobile&&e&&t?(e.style.display="block",t.style.display="none"):(e.style.display="none",t.style.display="block")}togglePayByBankList(){this._elementsToShow=document.querySelectorAll(".bk-paybybank-selector .custom-radio:nth-child(n+6)"),setTimeout(()=>{let e=localStorage.getItem("confirmOrderForm.payBybankMethod");null!==e&&document.$emitter.publish(y,{code:e,source:"other"})},300),this.toggleElements(!1),this.el.addEventListener("click",(function(e){let t=document.querySelector(".bk-toggle-wrap");if(null===t)return;let r=t.querySelector(".bk-toggle-text");if(e.target===r){let e=t.querySelector(".bk-toggle"),n=e.classList.contains("bk-toggle-down");e.classList.toggle("bk-toggle-down"),e.classList.toggle("bk-toggle-up");let o=r.getAttribute("text-less"),i=r.getAttribute("text-more");n?r.textContent=o:r.textContent=i,this.toggleElements(n)}}).bind(this))}listenToIssuerChange(){let e=function(){let e=document.querySelector(".bk-toggle-wrap");if(null!==e){let t=e.querySelector(".bk-toggle-text"),r=e.querySelector(".bk-toggle"),n=r.classList.contains("bk-toggle-down"),o=t.getAttribute("text-more");n||(r.classList.toggle("bk-toggle-down"),r.classList.toggle("bk-toggle-up"),t.textContent=o)}};document.$emitter.subscribe(y,(function(e){this.syncInputs(e.detail)}).bind(this)),document.querySelector("#payBybankMethod").addEventListener("change",function(t){document.$emitter.publish(y,{code:t.target.value,source:"select"}),e()}),document.querySelectorAll(".bk-paybybank-radio input").forEach(function(e){e.addEventListener("change",function(e){document.$emitter.publish(y,{code:e.target.value,source:"radio"})})})}syncInputs(e){this._elementsToShow=document.querySelectorAll(`.bk-paybybank-selector .custom-radio:not(.bankMethod${e.code})`),"other"===e.source&&this.toggleElements(!1),-1!==["radio","other"].indexOf(e.source)&&(document.querySelector("#payBybankMethod").value=e.code),-1===["select","other"].indexOf(e.source)||(document.querySelectorAll(".bk-paybybank-radio").forEach(function(t){let r=t.querySelector("input");t.style.display="none",null!==r&&(r.checked=!1,r.value===e.code&&(r.checked=!0,t.style.display="block"))}),e.code&&0!==e.code.length||this.showDefaultsIfEmptyIssuer())}showDefaultsIfEmptyIssuer(){document.querySelectorAll(".bk-paybybank-selector .custom-radio:nth-child(-n+5)").forEach(function(e){e.style.display="block"})}toggleElements(e){let t=arguments.length>1&&void 0!==arguments[1]?arguments[1]:"inline";this._elementsToShow.forEach(function(r){r.style.display=e?t:"none"})}constructor(...e){super(...e),this.httpClient=new l}}class b extends s{static #e=this.options={issuerSelected:"",issuerLogos:[]};init(){this.initialLogo(),this.listenToIssuerChange()}listenToIssuerChange(){document.$emitter.subscribe("bk-paybybank-selected",(function(e){this.updateLogo(e.detail.code)}).bind(this))}initialLogo(){this.updateLogo(this.options.issuerSelected)}updateLogo(e){if(this.options.issuerLogos[e]){let t=document.querySelector(".bk-paybybank .payment-method-image");t&&(t.src=this.options.issuerLogos[e])}}}let k=window.PluginManager;"BuckarooPaymentValidateSubmit"in window.PluginManager.getPluginList()||(k.register("BuckarooPaymentValidateSubmit",class e extends s{init(){try{this._registerCheckoutSubmitButton(),this._toggleApplePay(),this._getActivePayByBankLogo()}catch(e){console.log("init error",e)}}_getActivePayByBankLogo(){let e=document.querySelector(".bk-paybybank .payment-method-image"),t=document.querySelector(".bk-paybybank-active-logo");e&&t&&t.value&&t.value.length>0&&(e.src=t.value)}_toggleApplePay(){let e=document.querySelector(".payment-method.bk-applepay");if(e){let t=async function(e){return"ApplePaySession"in window&&void 0!==ApplePaySession?await ApplePaySession.canMakePaymentsWithActiveCard(e):Promise.resolve(!1)};(async function(){let r=document.getElementById("bk-apple-merchant-id");if(r&&r.value.length>0){let n=await t(r);e.style.display=n?"block":"none"}})().catch()}}_registerCheckoutSubmitButton(){let e=document.getElementById("confirmOrderForm");e&&e.querySelector('[type="submit"]').addEventListener("click",this._handleCheckoutSubmit.bind(this))}_handleCheckoutSubmit(e){e.preventDefault(),document.$emitter.unsubscribe("buckaroo_payment_validate"),this._listenToValidation(),document.$emitter.publish("buckaroo_payment_submit")}_listenToValidation(){let e={general:this._deferred(),credicard:this._deferred()};document.$emitter.subscribe("buckaroo_payment_validate",function(t){t.detail.type&&e[t.detail.type]&&e[t.detail.type].resolve(t.detail.valid)}),Promise.all([e.general,e.credicard]).then(function(e){let[t,r]=e;void 0!==document.forms.confirmOrderForm&&document.forms.confirmOrderForm.reportValidity()&&(t&&r?(void 0!==window.buckaroo_back_link&&window.history.pushState(null,null,buckaroo_back_link),window.isApplePay||window.isGooglePay||document.forms.confirmOrderForm.requestSubmit()):document.getElementById("changePaymentForm").scrollIntoView())})}_deferred(){let e,t;let r=new Promise((r,n)=>{[e,t]=[r,n]});return r.resolve=e,r.reject=t,r}}),k.register("BuckarooPaymentCreditcards",class e extends s{init(){this._listenToSubmit(),this._createScript(()=>{for(let e of["creditcards_issuer","creditcards_cardholdername","creditcards_cardnumber","creditcards_expirationmonth","creditcards_expirationyear","creditcards_cvc"]){let t=document.getElementById(e);t&&t.addEventListener("change",this._handleInputChanged.bind(this))}let e=document.getElementById("creditcards_issuer");e&&document.getElementById("card_kind_img").setAttribute("src",e.options[e.selectedIndex].getAttribute("data-logo")),this._getEncryptedData()})}_createScript(e){let t=document.createElement("script");t.type="text/javascript",t.src="https://static.buckaroo.nl/script/ClientSideEncryption001.js",t.addEventListener("load",e.bind(this),!1),document.head.appendChild(t)}_getEncryptedData(){let e=document.getElementById("creditcards_cardnumber"),t=document.getElementById("creditcards_expirationyear"),r=document.getElementById("creditcards_expirationmonth"),n=document.getElementById("creditcards_cvc"),o=document.getElementById("creditcards_cardholdername");if(e&&t&&r&&n&&o){var i,a,s,l,c;i=e.value,a=t.value,s=r.value,l=n.value,c=o.value,window.BuckarooClientSideEncryption.V001.encryptCardData(i,a,s,l,c,function(e){let t=document.getElementById("encryptedCardData");t&&(t.value=e)})}}_handleInputChanged(e){let t=e.target.id,r=document.getElementById(t);"creditcards_issuer"===t?document.getElementById("card_kind_img").setAttribute("src",r.options[r.selectedIndex].getAttribute("data-logo")):this._CheckValidate(),this._getEncryptedData()}_handleCheckField(e){switch(document.getElementById(e.id+"Error").style.display="none",e.id){case"creditcards_cardnumber":if(!window.BuckarooClientSideEncryption.V001.validateCardNumber(e.value.replace(/\s+/g,"")))return document.getElementById(e.id+"Error").style.display="block",!1;break;case"creditcards_cardholdername":if(!window.BuckarooClientSideEncryption.V001.validateCardholderName(e.value))return document.getElementById(e.id+"Error").style.display="block",!1;break;case"creditcards_cvc":if(!window.BuckarooClientSideEncryption.V001.validateCvc(e.value))return document.getElementById(e.id+"Error").style.display="block",!1;break;case"creditcards_expirationmonth":if(!window.BuckarooClientSideEncryption.V001.validateMonth(e.value))return document.getElementById(e.id+"Error").style.display="block",!1;break;case"creditcards_expirationyear":if(!window.BuckarooClientSideEncryption.V001.validateYear(e.value))return document.getElementById(e.id+"Error").style.display="block",!1}return!0}_CheckValidate(){let e=!1;for(let t of["creditcards_cardholdername","creditcards_cardnumber","creditcards_expirationmonth","creditcards_expirationyear","creditcards_cvc"]){let r=document.getElementById(t);r&&!this._handleCheckField(r)&&(e=!0)}return this._disableConfirmFormSubmit(e)}_disableConfirmFormSubmit(e){return document.getElementById("confirmFormSubmit")&&(document.getElementById("confirmFormSubmit").disabled=e),e}_registerCheckoutSubmitButton(){let e=document.getElementById("confirmFormSubmit");e&&e.addEventListener("click",this._handleCheckoutSubmit.bind(this))}_validateOnSubmit(e){e.preventDefault();let t=!this._CheckValidate();document.$emitter.publish("buckaroo_payment_validate",{valid:t,type:"credicard"})}_listenToSubmit(){document.$emitter.subscribe("buckaroo_payment_submit",this._validateOnSubmit.bind(this))}}),k.register("BuckarooPaymentCreditcard",class e extends s{init(){document.getElementById("tailwind-wrapper-creditcards")&&this._loadHostedFieldsScript(()=>{this._initializeHostedFields(),this._listenToSubmit()})}_loadHostedFieldsScript(e){if(document.getElementById("buckaroo-sdk"))e();else{let t=document.createElement("script");t.id="buckaroo-sdk",t.src="https://hostedfields-externalapi.prod-pci.buckaroo.io/v1/sdk",t.addEventListener("load",e.bind(this),!1),document.head.appendChild(t)}}async _initializeHostedFields(){try{let e=await this._getOrRefreshToken();if(!e||!e.access_token){console.error("Failed to retrieve Buckaroo OAuth token.");return}let t=e.access_token;this.sdkClient=new BuckarooHostedFieldsSdk.HFClient(t),this.sdkClient.setLanguage("en"),await this.sdkClient.setSupportedServices(e.issuers);let r=document.getElementById("selected-issuer"),n=document.getElementById("pay"),o="";await this.sdkClient.startSession(e=>{this.sdkClient.handleValidation(e,"cc-name-error","cc-number-error","cc-expiry-error","cc-cvc-error"),n&&this._updateButtonState(n),o=this.sdkClient.getService(),r.value=o});let i={height:"80%",position:"absolute",border:"1px solid gray",radius:"5px",opacity:"1",transition:"all 0.3s ease",right:"5px",backgroundColor:"inherit"},a={fontSize:"14px",fontFamily:"Consolas, Liberation Mono, Menlo, Courier, monospace",textAlign:"left",background:"inherit",color:"black",placeholderColor:"grey",cardLogoStyling:i};await this.sdkClient.mountCardHolderName("#cc-name-wrapper",{id:"ccname",placeHolder:"John Doe",labelSelector:"#cc-name-label",baseStyling:a}).then(e=>e.focus()),await this.sdkClient.mountCardNumber("#cc-number-wrapper",{id:"cc",placeHolder:"555x xxxx xxxx xxxx",labelSelector:"#cc-number-label",baseStyling:a,cardLogoStyling:i}),await this.sdkClient.mountCvc("#cc-cvc-wrapper",{id:"cvc",placeHolder:"1234",labelSelector:"#cc-cvc-label",baseStyling:a}),await this.sdkClient.mountExpiryDate("#cc-expiry-wrapper",{id:"expiry",placeHolder:"MM / YY",labelSelector:"#cc-expiry-label",baseStyling:a})}catch(e){console.error("Error initializing Buckaroo Hosted Fields:",e)}}async _handleSubmit(e){e.preventDefault();try{let e=await this.sdkClient.submitSession();if(!e){console.error("Failed to retrieve Hosted Fields token.");return}let t=document.getElementById("buckaroo-token");t&&(t.value=e),document.getElementById("confirmOrderForm").requestSubmit()}catch(e){console.error("Error processing Buckaroo payment:",e)}}_listenToSubmit(){let e=document.getElementById("pay");e&&e.addEventListener("click",this._handleSubmit.bind(this));let t=document.getElementById("tos")||document.querySelector(".checkout-confirm-tos-checkbox");t&&e&&t.addEventListener("change",()=>{this._updateButtonState(e)})}_updateButtonState(e){if(!e)return;let t=this.sdkClient&&this.sdkClient.formIsValid(),r=document.getElementById("tos")||document.querySelector(".checkout-confirm-tos-checkbox"),n=!r||r.checked,o=!t||!n;e.disabled=o,e.style.backgroundColor=o?"#ff5555":"",e.style.cursor=o?"not-allowed":"",e.style.opacity=o?"0.5":""}_getStorefrontBaseUrl(){let e=window.location.origin,t=window.location.pathname.split("/").filter(Boolean);return t.length>0&&/^[a-z]{2}(-[A-Z]{2})?$/i.test(t[0])?`${e}/${t[0]}`:e}async _getOrRefreshToken(){let e=Date.now();if(this.tokenExpiresAt&&e0&&(r=!0,t="block");let n=document.getElementById("buckaroo_capayablein3_COCNumberDiv");return n&&(n.style.display=t,document.getElementById("buckaroo_capayablein3_CompanyNameDiv").style.display=t,document.getElementById("buckaroo_capayablein3_COCNumber").required=r,document.getElementById("buckaroo_capayablein3_CompanyName").required=r),r}_handleInputChanged(e){"buckaroo_capayablein3_OrderAs"===e.target.id&&this._checkCompany()}_handleMobileInputChanged(){this._CheckValidate()}_handleDoBInputChanged(){this._CheckValidate()}_CheckValidate(){let e=!1;for(let t of this.buckarooMobileInputs){let r=document.getElementById(t);r&&!this._handleCheckMobile(r)&&(e=!0)}for(let t of this.buckarooDoBInputs){let r=document.getElementById(t);r&&!this._handleCheckDoB(r)&&(e=!0)}return this._disableConfirmFormSubmit(e)}_handleCheckMobile(e){let t=document.getElementById("buckarooMobilePhoneError");return t&&(t.style.display="none"),!!e.value.match(/^\d{10}$/)||(t&&(t.style.display="block"),!1)}_handleCheckDoB(e){let t=document.getElementById("buckarooDoBError");t&&(t.style.display="none");let r=new Date(Date.parse(e.value));return!("Invalid Date"==r||new Date().getFullYear()-r.getFullYear()<18||1900>r.getFullYear())||(t&&(t.style.display="block"),!1)}_disableConfirmFormSubmit(e){return document.getElementById("confirmFormSubmit")&&(document.getElementById("confirmFormSubmit").disabled=e),e}_handleCompanyName(){let e=document.getElementById("buckaroo_capayablein3_CompanyNameError");return e.style.display="none",!!document.getElementById("buckaroo_capayablein3_CompanyName").value.length||(e.style.display="block",!1)}_isRadioOrCeckbox(e){return"radio"==e.type||"checkbox"==e.type}radioGroupHasRequired(e){let t=e.querySelectorAll('input[type="radio"]');return!!t&&[...t].filter(function(e){return e.checked}).length>0}isRadioGroup(e){return e.classList.contains("radio-group-required")}_handleRequired(){let e=document.getElementById("changePaymentForm").querySelectorAll("[required]");e&&e.length&&e.forEach(e=>{let t=e.parentElement;if("radio"===e.type&&(t=t.parentElement),t){let r=t.querySelector('[class="buckaroo-required"]');this.isRadioGroup(e)&&this.radioGroupHasRequired(e)?r&&r.remove():this._isRadioOrCeckbox(e)&&e.checked?r&&r.remove():this._isRadioOrCeckbox(e)||this.isRadioGroup(e)||!(e.value.length>0)?null===r&&(r=this._createMessageElement(e),null===t.querySelector('[id$="Error"]')&&t.append(r)):r&&r.remove()}})}_createMessageElement(e){let t=buckaroo_required_message,r=e.getAttribute("required-message");null!=r&&r.length&&(t=r);let n=document.createElement("label");return n.setAttribute("for",e.id),n.classList.add("buckaroo-required"),n.style.color="red",n.style.width="100%",n.innerHTML=t,n}_validateOnSubmit(){let e=!0;for(let t of(this._handleRequired(),document.querySelectorAll(".radio-group-required")))e=e&&this.radioGroupHasRequired(t);for(let t of this.buckarooMobileInputs)document.getElementById(t)&&(e=e&&!this._CheckValidate());for(let t of this.buckarooDoBInputs)document.getElementById(t)&&(e=e&&!this._CheckValidate());document.$emitter.publish("buckaroo_payment_validate",{valid:e,type:"general"})}_listenToSubmit(){document.$emitter.subscribe("buckaroo_payment_submit",this._validateOnSubmit.bind(this));let e=document.getElementById("confirmFormSubmit");e&&e.addEventListener("click",t=>{e.disabled=!0,setTimeout(()=>{this._CheckValidate()&&(e.disabled=!1)},2e3)})}}),k.register("PaypalExpressPlugin",c,"[data-paypal-express]"),k.register("BuckarooIdealQrPlugin",m,"[data-ideal-qr]"),k.register("BuckarooLoadScripts",class e extends s{loadSdk(){return new Promise(e=>{var t=document.createElement("script");t.src="https://checkout.buckaroo.nl/api/buckaroosdk/script/en-US",t.async=!0,document.head.appendChild(t),t.onload=()=>{e()}})}loadJquery(){return"undefined"==typeof jQuery||void 0===jQuery.ajax?new Promise(e=>{var t=document.createElement("script");t.src="https://code.jquery.com/jquery-3.2.1.min.js",t.async=!0,document.head.appendChild(t),t.onload=()=>{e()}}):Promise.resolve()}init(){this.loadJquery().then(()=>{document.$emitter.publish("buckaroo_scripts_jquery_loaded",{loaded:!0}),this.loadSdk().then(()=>{document.$emitter.publish("buckaroo_scripts_loaded",{loaded:!0})})})}}),k.register("BuckarooBanContact",class e extends s{init(){this._listenToSubmit(),this._createScript(()=>{for(let e of["bancontactmrcash_cardholdername","bancontactmrcash_cardnumber","bancontactmrcash_expirationmonth","bancontactmrcash_expirationyear"]){let t=document.getElementById(e);t&&t.addEventListener("change",this._handleInputChanged.bind(this))}this._getEncryptedData()})}_createScript(e){let t=document.createElement("script");t.type="text/javascript",t.src="https://static.buckaroo.nl/script/ClientSideEncryption001.js",t.addEventListener("load",e.bind(this),!1),document.head.appendChild(t)}_getEncryptedData(){let e=document.getElementById("bancontactmrcash_cardnumber"),t=document.getElementById("bancontactmrcash_expirationyear"),r=document.getElementById("bancontactmrcash_expirationmonth"),n=document.getElementById("bancontactmrcash_cardholdername");if(e&&t&&r&&n){var o,i,a,s;o=e.value,i=t.value,a=r.value,s=n.value,window.BuckarooClientSideEncryption.V001.encryptCardData(o,i,a,"",s,function(e){let t=document.getElementById("encryptedCardData");t&&(t.value=e)})}}_handleInputChanged(e){this._CheckValidate(),this._getEncryptedData()}_handleCheckField(e){switch(document.getElementById(e.id+"Error").style.display="none",e.id){case"bancontactmrcash_cardnumber":if(!window.BuckarooClientSideEncryption.V001.validateCardNumber(e.value.replace(/\s+/g,"")))return document.getElementById(e.id+"Error").style.display="block",!1;break;case"bancontactmrcash_cardholdername":if(!window.BuckarooClientSideEncryption.V001.validateCardholderName(e.value))return document.getElementById(e.id+"Error").style.display="block",!1;break;case"bancontactmrcash_expirationmonth":if(!window.BuckarooClientSideEncryption.V001.validateMonth(e.value))return document.getElementById(e.id+"Error").style.display="block",!1;break;case"bancontactmrcash_expirationyear":if(!window.BuckarooClientSideEncryption.V001.validateYear(e.value))return document.getElementById(e.id+"Error").style.display="block",!1}return!0}_CheckValidate(){let e=!1;for(let t of["bancontactmrcash_cardholdername","bancontactmrcash_cardnumber","bancontactmrcash_expirationmonth","bancontactmrcash_expirationyear"]){let r=document.getElementById(t);r&&!this._handleCheckField(r)&&(e=!0)}return this._disableConfirmFormSubmit(e)}_disableConfirmFormSubmit(e){return document.getElementById("confirmFormSubmit")&&(document.getElementById("confirmFormSubmit").disabled=e),e}_validateOnSubmit(e){e.preventDefault();let t=!this._CheckValidate();document.$emitter.publish("buckaroo_payment_validate",{valid:t,type:"bancontactmrcash"})}_listenToSubmit(){document.$emitter.subscribe("buckaroo_payment_submit",this._validateOnSubmit.bind(this))}}),k.register("BuckarooPayByBankSelect",g,"[data-bk-select]"),k.register("BuckarooPayByBankLogo",b,"[data-bk-paybybank-logo]"),k.register("IdealFastCheckoutPlugin",d,"[data-bk-ideal-fast-checkout]"),k.register("GooglePayPlugin",h,"[data-bk-googlepay]"))})(); \ No newline at end of file + `,i=document.querySelector(".flashbags");i&&(i.insertAdjacentHTML("afterbegin",n),setTimeout(()=>{let e=document.querySelector(".buckaroo-googlepay-error");e&&(e.style.transition="opacity 1s",e.style.opacity="0",setTimeout(()=>e.remove(),1e3))},1e4))}constructor(...e){super(...e),this.httpClient=new d,this.url="/buckaroo",this.cartToken=null,this.googlePayment=null}}class b extends a{static #e=this.options={orderId:null,pullUrl:null,interval:5e3};init(){this.pullStatus()}pullStatus(){setInterval(this.singlePullStatus.bind(this),this.options.interval)}singlePullStatus(){this.options,this.httpClient.post(this.options.pullUrl,JSON.stringify({orderId:this.options.orderId}),e=>{let t=JSON.parse(e);void 0!==t.redirectUrl&&(window.location.href=t.redirectUrl)})}constructor(...e){super(...e),this.httpClient=new d}}let k="bk-is-mobile",f="bk-paybybank-selected";class _ extends a{static #e=this.options={issuerSelected:""};init(){this.listenToIsMobile(),this.onPageLoad(),this.listenToResize(),this.listenToIssuerChange(),this.togglePayByBankList(),this.emitSavedIssuer()}emitSavedIssuer(){"string"==typeof this.options.issuerSelected&&this.options.issuerSelected.length>0&&document.$emitter.publish(f,{code:this.options.issuerSelected,source:"other"})}onPageLoad(){document.$emitter.publish(k,{isMobile:768>(window.innerWidth||document.documentElement.clientWidth||document.body.clientWidth)})}listenToResize(){window.addEventListener("resize",(function(){let e=window.innerWidth||document.documentElement.clientWidth||document.body.clientWidth,t=!1;e<768&&(t=!0),this.isMobile!==t&&document.$emitter.publish(k,{isMobile:t})}).bind(this))}listenToIsMobile(){document.$emitter.subscribe(k,(function(e){this.isMobile=e.detail.isMobile,this.toggleInputType()}).bind(this))}toggleInputType(){let e=document.querySelector(".bk-paybybank-mobile"),t=document.querySelector(".bk-paybybank-not-mobile");this.isMobile&&e&&t?(e.style.display="block",t.style.display="none"):(e.style.display="none",t.style.display="block")}togglePayByBankList(){this._elementsToShow=document.querySelectorAll(".bk-paybybank-selector .custom-radio:nth-child(n+6)"),setTimeout(()=>{let e=localStorage.getItem("confirmOrderForm.payBybankMethod");null!==e&&document.$emitter.publish(f,{code:e,source:"other"})},300),this.toggleElements(!1),this.el.addEventListener("click",(function(e){let t=document.querySelector(".bk-toggle-wrap");if(null===t)return;let n=t.querySelector(".bk-toggle-text");if(e.target===n){let e=t.querySelector(".bk-toggle"),i=e.classList.contains("bk-toggle-down");e.classList.toggle("bk-toggle-down"),e.classList.toggle("bk-toggle-up");let o=n.getAttribute("text-less"),r=n.getAttribute("text-more");i?n.textContent=o:n.textContent=r,this.toggleElements(i)}}).bind(this))}listenToIssuerChange(){let e=function(){let e=document.querySelector(".bk-toggle-wrap");if(null!==e){let t=e.querySelector(".bk-toggle-text"),n=e.querySelector(".bk-toggle"),i=n.classList.contains("bk-toggle-down"),o=t.getAttribute("text-more");i||(n.classList.toggle("bk-toggle-down"),n.classList.toggle("bk-toggle-up"),t.textContent=o)}};document.$emitter.subscribe(f,(function(e){this.syncInputs(e.detail)}).bind(this)),document.querySelector("#payBybankMethod").addEventListener("change",function(t){document.$emitter.publish(f,{code:t.target.value,source:"select"}),e()}),document.querySelectorAll(".bk-paybybank-radio input").forEach(function(e){e.addEventListener("change",function(e){document.$emitter.publish(f,{code:e.target.value,source:"radio"})})})}syncInputs(e){this._elementsToShow=document.querySelectorAll(`.bk-paybybank-selector .custom-radio:not(.bankMethod${e.code})`),"other"===e.source&&this.toggleElements(!1),-1!==["radio","other"].indexOf(e.source)&&(document.querySelector("#payBybankMethod").value=e.code),-1===["select","other"].indexOf(e.source)||(document.querySelectorAll(".bk-paybybank-radio").forEach(function(t){let n=t.querySelector("input");t.style.display="none",null!==n&&(n.checked=!1,n.value===e.code&&(n.checked=!0,t.style.display="block"))}),e.code&&0!==e.code.length||this.showDefaultsIfEmptyIssuer())}showDefaultsIfEmptyIssuer(){document.querySelectorAll(".bk-paybybank-selector .custom-radio:nth-child(-n+5)").forEach(function(e){e.style.display="block"})}toggleElements(e){let t=arguments.length>1&&void 0!==arguments[1]?arguments[1]:"inline";this._elementsToShow.forEach(function(n){n.style.display=e?t:"none"})}constructor(...e){super(...e),this.httpClient=new d}}class w extends a{static #e=this.options={issuerSelected:"",issuerLogos:[]};init(){this.initialLogo(),this.listenToIssuerChange()}listenToIssuerChange(){document.$emitter.subscribe("bk-paybybank-selected",(function(e){this.updateLogo(e.detail.code)}).bind(this))}initialLogo(){this.updateLogo(this.options.issuerSelected)}updateLogo(e){if(this.options.issuerLogos[e]){let t=document.querySelector(".bk-paybybank .payment-method-image");t&&(t.src=this.options.issuerLogos[e])}}}let C=window.PluginManager;"BuckarooPaymentValidateSubmit"in window.PluginManager.getPluginList()||(C.register("BuckarooPaymentValidateSubmit",class e extends a{init(){try{this._registerCheckoutSubmitButton(),this._toggleApplePay(),this._getActivePayByBankLogo()}catch(e){console.log("init error",e)}}_getActivePayByBankLogo(){let e=document.querySelector(".bk-paybybank .payment-method-image"),t=document.querySelector(".bk-paybybank-active-logo");e&&t&&t.value&&t.value.length>0&&(e.src=t.value)}_toggleApplePay(){let e=document.querySelector(".payment-method.bk-applepay");if(e){let t=async function(e){return"ApplePaySession"in window&&void 0!==ApplePaySession?await ApplePaySession.canMakePaymentsWithActiveCard(e):Promise.resolve(!1)};(async function(){let n=document.getElementById("bk-apple-merchant-id");if(n&&n.value.length>0){let i=await t(n);e.style.display=i?"block":"none"}})().catch()}}_registerCheckoutSubmitButton(){let e=document.getElementById("confirmOrderForm");e&&e.querySelector('[type="submit"]').addEventListener("click",this._handleCheckoutSubmit.bind(this))}_handleCheckoutSubmit(e){e.preventDefault(),document.$emitter.unsubscribe("buckaroo_payment_validate"),this._listenToValidation(),document.$emitter.publish("buckaroo_payment_submit")}_listenToValidation(){let e={general:this._deferred(),credicard:this._deferred()};document.$emitter.subscribe("buckaroo_payment_validate",function(t){t.detail.type&&e[t.detail.type]&&e[t.detail.type].resolve(t.detail.valid)}),Promise.all([e.general,e.credicard]).then(function(e){let[t,n]=e;void 0!==document.forms.confirmOrderForm&&document.forms.confirmOrderForm.reportValidity()&&(t&&n?(void 0!==window.buckaroo_back_link&&window.history.pushState(null,null,buckaroo_back_link),window.isApplePay||window.isGooglePay||document.forms.confirmOrderForm.requestSubmit()):document.getElementById("changePaymentForm").scrollIntoView())})}_deferred(){let e,t;let n=new Promise((n,i)=>{[e,t]=[n,i]});return n.resolve=e,n.reject=t,n}}),C.register("BuckarooPaymentCreditcards",class e extends a{init(){this._listenToSubmit(),this._createScript(()=>{for(let e of["creditcards_issuer","creditcards_cardholdername","creditcards_cardnumber","creditcards_expirationmonth","creditcards_expirationyear","creditcards_cvc"]){let t=document.getElementById(e);t&&t.addEventListener("change",this._handleInputChanged.bind(this))}let e=document.getElementById("creditcards_issuer");e&&document.getElementById("card_kind_img").setAttribute("src",e.options[e.selectedIndex].getAttribute("data-logo")),this._getEncryptedData()})}_createScript(e){let t=document.createElement("script");t.type="text/javascript",t.src="https://static.buckaroo.nl/script/ClientSideEncryption001.js",t.addEventListener("load",e.bind(this),!1),document.head.appendChild(t)}_getEncryptedData(){let e=document.getElementById("creditcards_cardnumber"),t=document.getElementById("creditcards_expirationyear"),n=document.getElementById("creditcards_expirationmonth"),i=document.getElementById("creditcards_cvc"),o=document.getElementById("creditcards_cardholdername");if(e&&t&&n&&i&&o){var r,s,a,l,c;r=e.value,s=t.value,a=n.value,l=i.value,c=o.value,window.BuckarooClientSideEncryption.V001.encryptCardData(r,s,a,l,c,function(e){let t=document.getElementById("encryptedCardData");t&&(t.value=e)})}}_handleInputChanged(e){let t=e.target.id,n=document.getElementById(t);"creditcards_issuer"===t?document.getElementById("card_kind_img").setAttribute("src",n.options[n.selectedIndex].getAttribute("data-logo")):this._CheckValidate(),this._getEncryptedData()}_handleCheckField(e){switch(document.getElementById(e.id+"Error").style.display="none",e.id){case"creditcards_cardnumber":if(!window.BuckarooClientSideEncryption.V001.validateCardNumber(e.value.replace(/\s+/g,"")))return document.getElementById(e.id+"Error").style.display="block",!1;break;case"creditcards_cardholdername":if(!window.BuckarooClientSideEncryption.V001.validateCardholderName(e.value))return document.getElementById(e.id+"Error").style.display="block",!1;break;case"creditcards_cvc":if(!window.BuckarooClientSideEncryption.V001.validateCvc(e.value))return document.getElementById(e.id+"Error").style.display="block",!1;break;case"creditcards_expirationmonth":if(!window.BuckarooClientSideEncryption.V001.validateMonth(e.value))return document.getElementById(e.id+"Error").style.display="block",!1;break;case"creditcards_expirationyear":if(!window.BuckarooClientSideEncryption.V001.validateYear(e.value))return document.getElementById(e.id+"Error").style.display="block",!1}return!0}_CheckValidate(){let e=!1;for(let t of["creditcards_cardholdername","creditcards_cardnumber","creditcards_expirationmonth","creditcards_expirationyear","creditcards_cvc"]){let n=document.getElementById(t);n&&!this._handleCheckField(n)&&(e=!0)}return this._disableConfirmFormSubmit(e)}_disableConfirmFormSubmit(e){return document.getElementById("confirmFormSubmit")&&(document.getElementById("confirmFormSubmit").disabled=e),e}_registerCheckoutSubmitButton(){let e=document.getElementById("confirmFormSubmit");e&&e.addEventListener("click",this._handleCheckoutSubmit.bind(this))}_validateOnSubmit(e){e.preventDefault();let t=!this._CheckValidate();document.$emitter.publish("buckaroo_payment_validate",{valid:t,type:"credicard"})}_listenToSubmit(){document.$emitter.subscribe("buckaroo_payment_submit",this._validateOnSubmit.bind(this))}}),C.register("BuckarooPaymentCreditcard",class e extends a{init(){this._initialized=!1,this._initialize()}async _initialize(){if(!this._initialized){this._initialized=!0;try{await this._loadHostedFieldsScript(),await this._waitUntilVisible(),await this._initializeHostedFields(),this._listenToSubmit()}catch(e){console.error("Error initializing Buckaroo Hosted Fields:",e)}}}_loadHostedFieldsScript(){return window.BuckarooHostedFieldsSdk?Promise.resolve():new Promise((e,t)=>{let n=document.getElementById(l);n||((n=document.createElement("script")).id=l,n.src="https://hostedfields-externalapi.prod-pci.buckaroo.io/v1/sdk",n.async=!0,document.head.appendChild(n)),n.addEventListener("load",()=>e(),{once:!0}),n.addEventListener("error",()=>t(Error("Failed to load the Buckaroo Hosted Fields SDK.")),{once:!0}),window.BuckarooHostedFieldsSdk&&e()})}_waitUntilVisible(){return null!==this.el.offsetParent?Promise.resolve():new Promise(e=>{let t=!1,n=()=>{t||(t=!0,i.disconnect(),e())},i=new IntersectionObserver(e=>{e.some(e=>e.isIntersecting)&&n()});i.observe(this.el);let o=this.el.closest(".collapse");o&&o.addEventListener("shown.bs.collapse",n,{once:!0})})}async _initializeHostedFields(){if(!["#cc-name-wrapper","#cc-number-wrapper","#cc-expiry-wrapper","#cc-cvc-wrapper"].every(e=>this.el.querySelector(e))){console.error("Buckaroo Hosted Fields wrappers are missing from the checkout DOM.");return}let e=await this._getOrRefreshToken();if(!e||!e.access_token){console.error("Failed to retrieve Buckaroo OAuth token.");return}this.sdkClient=new BuckarooHostedFieldsSdk.HFClient(e.access_token),this.sdkClient.setLanguage("en"),await this.sdkClient.setSupportedServices(e.issuers),await this.sdkClient.startSession(e=>{this.sdkClient.handleValidation(e,"cc-name-error","cc-number-error","cc-expiry-error","cc-cvc-error"),this._updateButtonState();let t=document.getElementById("selected-issuer");t&&(t.value=this.sdkClient.getService())});let t={height:"80%",position:"absolute",border:"1px solid gray",radius:"5px",opacity:"1",transition:"all 0.3s ease",right:"5px",backgroundColor:"inherit"},n={fontSize:"14px",fontFamily:"Consolas, Liberation Mono, Menlo, Courier, monospace",textAlign:"left",background:"inherit",color:"black",placeholderColor:"grey",cardLogoStyling:t};await this.sdkClient.mountCardHolderName("#cc-name-wrapper",{id:"ccname",placeHolder:"John Doe",labelSelector:"#cc-name-label",baseStyling:n}),await this.sdkClient.mountCardNumber("#cc-number-wrapper",{id:"cc",placeHolder:"555x xxxx xxxx xxxx",labelSelector:"#cc-number-label",baseStyling:n,cardLogoStyling:t}),await this.sdkClient.mountCvc("#cc-cvc-wrapper",{id:"cvc",placeHolder:"1234",labelSelector:"#cc-cvc-label",baseStyling:n}),await this.sdkClient.mountExpiryDate("#cc-expiry-wrapper",{id:"expiry",placeHolder:"MM / YY",labelSelector:"#cc-expiry-label",baseStyling:n})}async _handleSubmit(e){e.preventDefault();try{let e=await this.sdkClient.submitSession();if(!e){console.error("Failed to retrieve Hosted Fields token.");return}let t=document.getElementById("buckaroo-token");t&&(t.value=e);let n=document.getElementById("confirmOrderForm");n?n.requestSubmit():console.error("Shopware confirm order form (#confirmOrderForm) not found.")}catch(e){console.error("Error processing Buckaroo payment:",e)}}_listenToSubmit(){let e=this.el.querySelector("#pay");e&&e.addEventListener("click",this._handleSubmit.bind(this));let t=document.getElementById("tos")||document.querySelector(".checkout-confirm-tos-checkbox");t&&t.addEventListener("change",()=>this._updateButtonState()),this._updateButtonState()}_updateButtonState(){let e=document.getElementById("pay");if(!e)return;let t=this.sdkClient&&this.sdkClient.formIsValid(),n=document.getElementById("tos")||document.querySelector(".checkout-confirm-tos-checkbox"),i=!n||n.checked,o=!t||!i;e.disabled=o,e.style.backgroundColor=o?"#ff5555":"",e.style.cursor=o?"not-allowed":"",e.style.opacity=o?"0.5":"";let r=this.el.querySelector(".buckaroo-hf-error");r&&(t&&!i?(r.textContent="Please accept the terms and conditions to place your order.",r.style.display="block"):(r.textContent="",r.style.display="none"))}_getStorefrontBaseUrl(){let e=window.location.origin,t=window.location.pathname.split("/").filter(Boolean);return t.length>0&&/^[a-z]{2}(-[A-Z]{2})?$/i.test(t[0])?`${e}/${t[0]}`:e}async _getOrRefreshToken(){let e=Date.now();if(c&&e0&&(n=!0,t="block");let i=document.getElementById("buckaroo_capayablein3_COCNumberDiv");return i&&(i.style.display=t,document.getElementById("buckaroo_capayablein3_CompanyNameDiv").style.display=t,document.getElementById("buckaroo_capayablein3_COCNumber").required=n,document.getElementById("buckaroo_capayablein3_CompanyName").required=n),n}_handleInputChanged(e){"buckaroo_capayablein3_OrderAs"===e.target.id&&this._checkCompany()}_handleMobileInputChanged(){this._CheckValidate()}_handleDoBInputChanged(){this._CheckValidate()}_CheckValidate(){let e=!1;for(let t of this.buckarooMobileInputs){let n=document.getElementById(t);n&&!this._handleCheckMobile(n)&&(e=!0)}for(let t of this.buckarooDoBInputs){let n=document.getElementById(t);n&&!this._handleCheckDoB(n)&&(e=!0)}return this._disableConfirmFormSubmit(e)}_handleCheckMobile(e){let t=document.getElementById("buckarooMobilePhoneError");return t&&(t.style.display="none"),!!e.value.match(/^\d{10}$/)||(t&&(t.style.display="block"),!1)}_handleCheckDoB(e){let t=document.getElementById("buckarooDoBError");t&&(t.style.display="none");let n=new Date(Date.parse(e.value));return!("Invalid Date"==n||new Date().getFullYear()-n.getFullYear()<18||1900>n.getFullYear())||(t&&(t.style.display="block"),!1)}_disableConfirmFormSubmit(e){return document.getElementById("confirmFormSubmit")&&(document.getElementById("confirmFormSubmit").disabled=e),e}_handleCompanyName(){let e=document.getElementById("buckaroo_capayablein3_CompanyNameError");return e.style.display="none",!!document.getElementById("buckaroo_capayablein3_CompanyName").value.length||(e.style.display="block",!1)}_isRadioOrCeckbox(e){return"radio"==e.type||"checkbox"==e.type}radioGroupHasRequired(e){let t=e.querySelectorAll('input[type="radio"]');return!!t&&[...t].filter(function(e){return e.checked}).length>0}isRadioGroup(e){return e.classList.contains("radio-group-required")}_handleRequired(){let e=document.getElementById("changePaymentForm").querySelectorAll("[required]");e&&e.length&&e.forEach(e=>{let t=e.parentElement;if("radio"===e.type&&(t=t.parentElement),t){let n=t.querySelector('[class="buckaroo-required"]');this.isRadioGroup(e)&&this.radioGroupHasRequired(e)?n&&n.remove():this._isRadioOrCeckbox(e)&&e.checked?n&&n.remove():this._isRadioOrCeckbox(e)||this.isRadioGroup(e)||!(e.value.length>0)?null===n&&(n=this._createMessageElement(e),null===t.querySelector('[id$="Error"]')&&t.append(n)):n&&n.remove()}})}_getRequiredMessage(){let e=document.querySelector("[data-bk-required-message]");return e&&e.dataset.bkRequiredMessage?e.dataset.bkRequiredMessage:"string"==typeof window.buckaroo_required_message&&window.buckaroo_required_message.trim().length?window.buckaroo_required_message:"Please enter a valid value"}_createMessageElement(e){let t=this._getRequiredMessage(),n=e.getAttribute("required-message");null!=n&&n.length&&(t=n);let i=document.createElement("label");return i.setAttribute("for",e.id),i.classList.add("buckaroo-required"),i.style.color="red",i.style.width="100%",i.innerHTML=t,i}_validateOnSubmit(){let e=!0;for(let t of(this._handleRequired(),document.querySelectorAll(".radio-group-required")))e=e&&this.radioGroupHasRequired(t);for(let t of this.buckarooMobileInputs)document.getElementById(t)&&(e=e&&!this._CheckValidate());for(let t of this.buckarooDoBInputs)document.getElementById(t)&&(e=e&&!this._CheckValidate());document.$emitter.publish("buckaroo_payment_validate",{valid:e,type:"general"})}_listenToSubmit(){document.$emitter.subscribe("buckaroo_payment_submit",this._validateOnSubmit.bind(this));let e=document.getElementById("confirmFormSubmit");e&&e.addEventListener("click",t=>{e.disabled=!0,setTimeout(()=>{this._CheckValidate()&&(e.disabled=!1)},2e3)})}}),C.register("PaypalExpressPlugin",u,"[data-paypal-express]"),C.register("BuckarooIdealQrPlugin",b,"[data-ideal-qr]"),C.register("BuckarooApplePayPlugin",y,"[data-bk-applepay]"),C.register("BuckarooLoadScripts",class e extends a{loadSdk(){return new Promise(e=>{var t=document.createElement("script");t.src=this.getSdkUrl(),t.async=!0,document.head.appendChild(t),t.onload=()=>{e()}})}getSdkUrl(){let e=this.isPaypalExpressTestMode()?"https://testcheckout.buckaroo.nl":"https://checkout.buckaroo.nl";return`${e}/api/buckaroosdk/script/en-US`}isPaypalExpressTestMode(){let e=document.querySelector("[data-paypal-express-plugin-options]");if(!e)return!1;try{let t=JSON.parse(e.getAttribute("data-paypal-express-plugin-options"));return!0===t.isTestMode}catch(e){return!1}}loadJquery(){return"undefined"==typeof jQuery||void 0===jQuery.ajax?new Promise(e=>{var t=document.createElement("script");t.src="https://code.jquery.com/jquery-3.2.1.min.js",t.async=!0,document.head.appendChild(t),t.onload=()=>{e()}}):Promise.resolve()}init(){this.loadJquery().then(()=>{document.$emitter.publish("buckaroo_scripts_jquery_loaded",{loaded:!0}),this.loadSdk().then(()=>{document.$emitter.publish("buckaroo_scripts_loaded",{loaded:!0})})})}}),C.register("BuckarooBanContact",class e extends a{init(){this._listenToSubmit(),this._createScript(()=>{for(let e of["bancontactmrcash_cardholdername","bancontactmrcash_cardnumber","bancontactmrcash_expirationmonth","bancontactmrcash_expirationyear"]){let t=document.getElementById(e);t&&t.addEventListener("change",this._handleInputChanged.bind(this))}this._getEncryptedData()})}_createScript(e){let t=document.createElement("script");t.type="text/javascript",t.src="https://static.buckaroo.nl/script/ClientSideEncryption001.js",t.addEventListener("load",e.bind(this),!1),document.head.appendChild(t)}_getEncryptedData(){let e=document.getElementById("bancontactmrcash_cardnumber"),t=document.getElementById("bancontactmrcash_expirationyear"),n=document.getElementById("bancontactmrcash_expirationmonth"),i=document.getElementById("bancontactmrcash_cardholdername");if(e&&t&&n&&i){var o,r,s,a;o=e.value,r=t.value,s=n.value,a=i.value,window.BuckarooClientSideEncryption.V001.encryptCardData(o,r,s,"",a,function(e){let t=document.getElementById("encryptedCardData");t&&(t.value=e)})}}_handleInputChanged(e){this._CheckValidate(),this._getEncryptedData()}_handleCheckField(e){switch(document.getElementById(e.id+"Error").style.display="none",e.id){case"bancontactmrcash_cardnumber":if(!window.BuckarooClientSideEncryption.V001.validateCardNumber(e.value.replace(/\s+/g,"")))return document.getElementById(e.id+"Error").style.display="block",!1;break;case"bancontactmrcash_cardholdername":if(!window.BuckarooClientSideEncryption.V001.validateCardholderName(e.value))return document.getElementById(e.id+"Error").style.display="block",!1;break;case"bancontactmrcash_expirationmonth":if(!window.BuckarooClientSideEncryption.V001.validateMonth(e.value))return document.getElementById(e.id+"Error").style.display="block",!1;break;case"bancontactmrcash_expirationyear":if(!window.BuckarooClientSideEncryption.V001.validateYear(e.value))return document.getElementById(e.id+"Error").style.display="block",!1}return!0}_CheckValidate(){let e=!1;for(let t of["bancontactmrcash_cardholdername","bancontactmrcash_cardnumber","bancontactmrcash_expirationmonth","bancontactmrcash_expirationyear"]){let n=document.getElementById(t);n&&!this._handleCheckField(n)&&(e=!0)}return this._disableConfirmFormSubmit(e)}_disableConfirmFormSubmit(e){return document.getElementById("confirmFormSubmit")&&(document.getElementById("confirmFormSubmit").disabled=e),e}_validateOnSubmit(e){e.preventDefault();let t=!this._CheckValidate();document.$emitter.publish("buckaroo_payment_validate",{valid:t,type:"bancontactmrcash"})}_listenToSubmit(){document.$emitter.subscribe("buckaroo_payment_submit",this._validateOnSubmit.bind(this))}}),C.register("BuckarooPayByBankSelect",_,"[data-bk-select]"),C.register("BuckarooPayByBankLogo",w,"[data-bk-paybybank-logo]"),C.register("IdealFastCheckoutPlugin",p,"[data-bk-ideal-fast-checkout]"),C.register("GooglePayPlugin",g,"[data-bk-googlepay]"))})(); \ No newline at end of file diff --git a/src/Resources/app/storefront/src/applepay/applepay.plugin.js b/src/Resources/app/storefront/src/applepay/applepay.plugin.js index 17df7096..18862451 100644 --- a/src/Resources/app/storefront/src/applepay/applepay.plugin.js +++ b/src/Resources/app/storefront/src/applepay/applepay.plugin.js @@ -12,65 +12,119 @@ export default class ApplePayPlugin extends Plugin { httpClient = new HttpClient(); url = "/buckaroo"; - /** - * buckaroo sdk - */ - sdk; result = null; cartToken; + cartData = null; + + payment; + init() { - if (this.merchantId === null) { - alert("Apple Pay Merchant id is required"); + const isCheckout = this.options.page === "checkout"; + + if (isCheckout) { + window.isApplePay = true; + this.setConfirmButtonDisabled(true); } document.$emitter.subscribe("buckaroo_scripts_jquery_loaded", () => { - $("#confirmFormSubmit").prop("disabled", true); - this.checkIsAvailable().then((available) => { - $("#confirmFormSubmit").prop("disabled", !available); - if (available) { - this.renderButton(); - } - }); + ApplePay.loadOfficialSdk() + .then(() => this.retrieveCartData()) + .then((cartData) => { + this.cartData = cartData; + this.renderButton(cartData); + }) + .catch(() => { + if (isCheckout) { + window.isApplePay = false; + this.setConfirmButtonDisabled(false); + } + }); }); } /** - * Render the pay button if not on the checkout page + * Enable/disable the checkout confirm (Place Order) button. */ - renderButton() { - if (this.options.page !== "checkout") { - $(".bk-apple-pay-button") - .addClass(ApplePay.getButtonClass()) - .attr("lang", this.options.cultureCode) - .on("click", this.initPayment.bind(this)); + setConfirmButtonDisabled(disabled) { + const btn = document.getElementById("confirmFormSubmit"); + if (btn) { + btn.disabled = disabled; + } + } + + renderButton(cartData) { + if (this.options.page === "checkout") { + this.wireCheckoutConfirmButton(cartData); } else { - window.isApplePay = true; - $("#confirmFormSubmit").on("click", this.initPayment.bind(this)); + this.renderExpressButton(cartData); } } + /** - * Start the payment process + * Standard checkout method: open the Apple Pay sheet from "Place Order". + * begin() runs synchronously inside the trusted click so the sheet/QR opens. */ - initPayment(e) { - e.preventDefault(); + wireCheckoutConfirmButton(cartData) { + this.setConfirmButtonDisabled(false); + + const btn = document.getElementById("confirmFormSubmit"); + if (!btn) { + return; + } - this.retrieveCartData().then((data) => { - this.initApplePayment(data); + document.addEventListener( + "click", + (e) => { + const t = e.target; + if (t !== btn && !(t && t.closest && t.closest("#confirmFormSubmit"))) { + return; + } + e.preventDefault(); + e.stopImmediatePropagation(); + // Respect native form validation (e.g. required terms checkbox) + // before opening the Apple Pay sheet/QR modal. + const form = document.forms["confirmOrderForm"]; + if (form && !form.reportValidity()) { + return; + } + this.initApplePayment(cartData); + }, + true + ); + } + + /** + * Express (product/cart, confirm-page express button): render Apple's + * official and open the sheet synchronously on click. + */ + renderExpressButton(cartData) { + const container = $(".bk-apple-pay-button"); + container.empty(); + const button = ApplePay.createButton({ + buttonStyle: "black", + locale: this.options.cultureCode, }); + button.addEventListener("click", (e) => { + e.preventDefault(); + this.initApplePayment(cartData); + }); + container.append(button); } /** - * Retire cart data required by Apple - * @returns Promise + * Retrieve cart data up front (not on click), so the sheet can open synchronously. */ retrieveCartData() { let formData = null; if (this.options.page === "product") { - formData = FormSerializeUtil.serializeJson(this.el.closest("form")); + const form = this.el.closest("form"); + if (form) { + formData = FormSerializeUtil.serializeJson(form); + } } return new Promise((resolve, reject) => { @@ -79,62 +133,77 @@ export default class ApplePayPlugin extends Plugin { JSON.stringify({ form: formData, page: this.options.page, + productId: this.options.productId || null, }), (response) => { let resp = JSON.parse(response); - if(resp.error) { - this.displayErrorMessage(resp.message); + if (resp.error) { reject(resp.message); } else { this.cartToken = resp.cartToken; resolve(resp); } - } ); }); } /** - * Start the payment process - * @param {*} cart + * Construct the Apple Pay session and open the sheet. MUST be called + * synchronously from a click handler with already-fetched cart data. */ initApplePayment(cart) { const self = this; - const options = new ApplePay.PayOptions( - cart.storeName, - cart.country, - cart.currency, - self.options.cultureCode, - self.options.merchantId, - cart.lineItems, - cart.totals, - "shipping", - self.isCheckout(cart.shippingMethods, []), - self.captureFunds, - self.isCheckout(self.updateCart, null), - self.isCheckout(self.updateCart, null), - ); - - ApplePay.PayPayment(options); + try { + const options = new ApplePay.PayOptions( + cart.storeName, + cart.country, + cart.currency, + self.options.cultureCode, + self.options.merchantId, + cart.lineItems, + cart.totals, + "shipping", + self.isCheckout(cart.shippingMethods, []), + self.captureFunds.bind(self), + self.isCheckout(self.updateCart.bind(self), null), + self.isCheckout(self.updateCart.bind(self), null), + // Billing: keep the card holder name in standard checkout too — it is + // forwarded to Buckaroo as customerCardName (matches the old SDK and + // the Magento implementation, which used the full default field set). + self.isCheckout(["email", "name", "postalAddress"], ["name"]), + self.isCheckout(["email", "name", "postalAddress"], []), + ); - ApplePay.beginPayment(); + self.payment = new ApplePay.PayPayment(options); + self.payment.beginPayment(); + } catch (e) { + // Apple Pay cannot open here. Keep window.isApplePay true so no order is + // placed without authorisation; surface a message and re-enable the button. + console.warn("Apple Pay could not open the payment sheet:", e); + self.displayErrorMessage( + (self.options.i18n && self.options.i18n.cannot_create_payment) || + "Apple Pay is not available in this browser." + ); + if (self.options.page === "checkout") { + self.setConfirmButtonDisabled(false); + } + } } /** - * Check if the page is checkout and return the correct action + * Return inCheckout on the checkout page, otherwise notInCheckout. */ - isCheckout(noTinCheckout, inCheckout) { + isCheckout(notInCheckout, inCheckout) { if (this.options.page === "checkout") { return inCheckout; } - return noTinCheckout; + return notInCheckout; } /** - * Create the sw6 order with the payment data - * @param {*} payment + * Create the sw6 order with the payment data (after authorisation). */ captureFunds(payment) { return new Promise((resolve) => { @@ -143,26 +212,33 @@ export default class ApplePayPlugin extends Plugin { JSON.stringify({ payment: JSON.stringify(payment), cartToken: this.cartToken, - page: this.options.page + page: this.options.page, }), (response) => { - const resp = JSON.parse(response); - if (resp.redirect) { + let resp = null; + try { + resp = JSON.parse(response); + } catch (e) { + resp = { error: true }; + } + if (resp && resp.redirect) { resolve({ status: ApplePaySession.STATUS_SUCCESS, errors: [], }); window.location = resp.redirect; } else { - let message = this.options.i18n.cannot_create_payment; - if(resp.message) { + if (resp && resp.message) { message = resp.message; } this.displayErrorMessage(message); + // errors must contain ApplePayError objects — plain strings make + // completePayment() throw and kill the session with a generic + // device-side error instead of showing anything useful. resolve({ status: ApplePaySession.STATUS_FAILURE, - errors: [message], + errors: [], }); } } @@ -171,16 +247,13 @@ export default class ApplePayPlugin extends Plugin { } /** - * Update cart with the data received from apple pay - * @param {*} data - * @returns Promise + * Update cart with the data received from apple pay (express only) */ updateCart(data) { let request = { cartToken: this.cartToken, }; - //request body for changing shipping address if (data.identifier !== undefined) { request = { ...request, @@ -188,7 +261,6 @@ export default class ApplePayPlugin extends Plugin { }; } - // request body for setting the user if (data.countryCode !== undefined) { request = { ...request, @@ -201,35 +273,57 @@ export default class ApplePayPlugin extends Plugin { `${this.url}/apple/cart/update`, JSON.stringify(request), (response) => { - const resp = JSON.parse(response); + let resp = null; + try { + resp = JSON.parse(response); + } catch (e) { + resp = { error: true, message: null }; + } + + if (resp.error) { + if (resp.message) { + this.displayErrorMessage(resp.message); + console.warn(resp.message); + } + // Keep the session alive: the one-argument completion form REQUIRES + // newTotal — resolving without it (or with string errors) throws in + // WebKit, aborts the session and shows "Service Unavailable" on the + // device. Fall back to the totals fetched at page load and report a + // proper ApplePayError instead. + const errors = []; + if (typeof ApplePayError === "function") { + errors.push( + new ApplePayError( + "shippingContactInvalid", + "postalAddress", + typeof resp.message === "string" && resp.message !== "" + ? resp.message + : "This address cannot be processed." + ) + ); + } + resolve({ + newTotal: this.cartData ? this.cartData.totals : undefined, + newLineItems: this.cartData ? this.cartData.lineItems : undefined, + errors: errors, + }); + return; + } - let status = ApplePaySession.STATUS_SUCCESS; - if(resp.error) { - status = ApplePaySession.STATUS_FAILURE; - this.displayErrorMessage(resp.message); - console.warn(resp.message); - } resolve({ - status: status, - ...resp + newTotal: resp.newTotal, + newLineItems: resp.newLineItems, + newShippingMethods: resp.newShippingMethods, }); } ); }); } - /** - * Check if apple pay is available - * @returns Promise - */ checkIsAvailable() { return ApplePay.checkPaySupport(this.options.merchantId); } - /** - * Display any validation errors we receive - * @param {string} message - */ displayErrorMessage(message) { $(".buckaroo-apple-error").remove(); if (typeof message === "object") { @@ -239,15 +333,13 @@ export default class ApplePayPlugin extends Plugin { \r\n {% parent %}\r\n{% endblock %}\r\n\r\n\r\n{% block sw_order_detail_content_tabs_general %}\r\n {% parent %}\r\n\r\n \r\n {{ $tc('buckaroo-payment.tabs.title') }}\r\n \r\n \r\n{% endblock %}\r\n\r\n{% block sw_order_detail_actions %}\r\n \r\n {% parent %}\r\n{% endblock %}","import template from './sw-order.html.twig';\r\n\r\nconst { Component, Context } = Shopware;\r\nconst Criteria = Shopware.Data.Criteria;\r\n\r\nComponent.override('sw-order-detail', {\r\n template,\r\n\r\n data() {\r\n return {\r\n isBuckarooPayment: false,\r\n isPaymentInTestMode: false\r\n };\r\n },\r\n\r\n computed: {\r\n isEditable() {\r\n return !this.isBuckarooPayment || this.$route.name !== 'buckaroo.payment.detail';\r\n },\r\n\r\n showTabs() {\r\n return true;\r\n }\r\n },\r\n\r\n watch: {\r\n orderId: {\r\n deep: true,\r\n handler() {\r\n if (!this.orderId) {\r\n this.setIsBuckarooPayment(null);\r\n return;\r\n }\r\n\r\n const orderRepository = this.repositoryFactory.create('order');\r\n const orderCriteria = new Criteria(1, 1);\r\n orderCriteria.addAssociation('transactions');\r\n\r\n orderRepository.get(this.orderId, Context.api, orderCriteria).then((order) => {\r\n\r\n this.setPaymentInTestMode(order);\r\n\r\n if (order.transactions.length <= 0 ||\r\n !order.transactions.last().paymentMethodId\r\n ) {\r\n this.setIsBuckarooPayment(null);\r\n return;\r\n }\r\n\r\n const paymentMethodId = order.transactions.last().paymentMethodId;\r\n\r\n if (paymentMethodId !== undefined && paymentMethodId !== null) {\r\n this.setIsBuckarooPayment(paymentMethodId);\r\n }\r\n });\r\n },\r\n immediate: true\r\n }\r\n },\r\n\r\n methods: {\r\n setPaymentInTestMode(order) {\r\n if (order.customFields && order.customFields.buckaroo_payment_in_test_mode) {\r\n this.isPaymentInTestMode = order.customFields.buckaroo_payment_in_test_mode === true;\r\n }\r\n },\r\n setIsBuckarooPayment(paymentMethodId) {\r\n if (!paymentMethodId) {\r\n return;\r\n }\r\n const paymentMethodRepository = this.repositoryFactory.create('payment_method');\r\n paymentMethodRepository.get(paymentMethodId, Context.api).then(\r\n (paymentMethod) => {\r\n this.isBuckarooPayment = paymentMethod.formattedHandlerIdentifier.indexOf('buckaroo') >= 0;\r\n }\r\n );\r\n }\r\n }\r\n});","{% block sw_order_detail_base_line_items_summary %}\r\n\r\n \r\n 0\">\r\n \r\n
{{ $tc('buckaroo-payment.fee') }}
\r\n
{{ order.customFields.buckarooFee }}\r\n {% if order.currency.isoCode == \"PLN\" %}\r\n PLN\r\n {% else %}\r\n {{ order.currency.symbol }}\r\n {% endif %}\r\n
\r\n
\r\n
\r\n
\r\n\r\n {% parent %}\r\n \r\n{% endblock %}","import template from './sw-order-detail-base.html.twig';\r\n\r\nconst { Component, Context } = Shopware;\r\nconst Criteria = Shopware.Data.Criteria;\r\n\r\nComponent.override('sw-order-detail-base', {\r\n template\r\n});\r\n","{% block sw_order_detail_base_secondary_info_payment %}\r\n \r\n \r\n{% endblock %}\r\n\r\n","import template from './sw-order-user-card.html.twig';\r\n\r\nconst { Component } = Shopware;\r\n\r\nComponent.override('sw-order-user-card', {\r\n template,\r\n\r\n inject: [ 'systemConfigApiService' ],\r\n\r\n data() {\r\n return {\r\n config: {}\r\n };\r\n },\r\n\r\n created() {\r\n this.systemConfigApiService.getValues('BuckarooPayments.config', null)\r\n .then(values => {\r\n this.config = values;\r\n })\r\n .finally(() => {\r\n });\r\n }\r\n\r\n});\r\n"," {% block sw_system_config_content_card %}\r\n \r\n \r\n {% endblock %}"," import template from './sw-system-config.html.twig';\r\n\r\nconst { Component } = Shopware;\r\n\r\nComponent.override('sw-system-config', {\r\n template,\r\n \r\n watch: {\r\n currentSalesChannelId: {\r\n handler(newVal, oldVal) {\r\n if (newVal && this.domain === 'BuckarooPayments.config') {\r\n this.loadBuckarooConfigData();\r\n }\r\n },\r\n immediate: true\r\n },\r\n domain: {\r\n handler(newVal) {\r\n if (newVal === 'BuckarooPayments.config' && this.currentSalesChannelId) {\r\n this.loadBuckarooConfigData();\r\n }\r\n },\r\n immediate: true\r\n }\r\n },\r\n\r\n methods: {\r\n loadBuckarooConfigData() {\r\n \r\n this.systemConfigApiService.getValues('BuckarooPayments.config', this.currentSalesChannelId)\r\n .then(response => {\r\n \r\n if (!this.actualConfigData[this.currentSalesChannelId]) {\r\n this.actualConfigData[this.currentSalesChannelId] = {};\r\n }\r\n\r\n const processedData = {};\r\n \r\n if (response && typeof response === 'object') {\r\n Object.keys(response).forEach(key => {\r\n const value = response[key];\r\n\r\n if (value && typeof value === 'object' && value.hasOwnProperty('_value')) {\r\n processedData[key] = value._value;\r\n } else {\r\n processedData[key] = value;\r\n }\r\n\r\n const shortKey = key.replace('BuckarooPayments.config.', '');\r\n if (shortKey !== key) {\r\n processedData[shortKey] = processedData[key];\r\n }\r\n });\r\n }\r\n\r\n this.actualConfigData[this.currentSalesChannelId] = {};\r\n Object.keys(processedData).forEach(key => {\r\n this.actualConfigData[this.currentSalesChannelId][key] = processedData[key];\r\n });\r\n\r\n this.$nextTick(() => {\r\n this.$forceUpdate();\r\n });\r\n })\r\n .catch(error => {\r\n console.error('Error fetching system config:', error);\r\n });\r\n },\r\n\r\n onConfigDataUpdate(newValue) {\r\n if (!this.actualConfigData[this.currentSalesChannelId]) {\r\n this.actualConfigData[this.currentSalesChannelId] = {};\r\n }\r\n Object.keys(newValue).forEach(key => {\r\n this.actualConfigData[this.currentSalesChannelId][key] = newValue[key];\r\n if (!key.startsWith('BuckarooPayments.config.')) {\r\n const fullFieldName = `BuckarooPayments.config.${key}`;\r\n this.actualConfigData[this.currentSalesChannelId][fullFieldName] = newValue[key];\r\n }\r\n });\r\n },\r\n\r\n saveAll() {\r\n if (this.domain !== 'BuckarooPayments.config') {\r\n return this.$super('saveAll');\r\n }\r\n return this.saveBuckaroo();\r\n },\r\n \r\n saveBuckaroo() {\r\n this.isLoading = true;\r\n return this.systemConfigApiService\r\n .batchSave(this.getSelectedValues())\r\n .finally(() => {\r\n this.isLoading = false;\r\n });\r\n },\r\n \r\n getCurrentConfigCard() {\r\n const code = this.$route.params?.paymentCode || 'general';\r\n return this.config.filter((card) => card.name === code)?.pop();\r\n },\r\n \r\n getSelectedValues() {\r\n const currentConfigValues = this.actualConfigData[this.currentSalesChannelId];\r\n const currentPaymentCard = this.getCurrentConfigCard();\r\n\r\n if (currentPaymentCard?.elements) {\r\n let actualConfigValues = {};\r\n currentPaymentCard?.elements.forEach((element) => {\r\n if (element?.name) {\r\n let value = currentConfigValues[element.name];\r\n\r\n if (value === undefined) {\r\n const cleanFieldName = element.name.replace('BuckarooPayments.config.', '');\r\n value = currentConfigValues[cleanFieldName];\r\n }\r\n \r\n actualConfigValues[element.name] = value;\r\n }\r\n });\r\n return { [this.currentSalesChannelId]: actualConfigValues };\r\n }\r\n\r\n return this.actualConfigData;\r\n }\r\n }\r\n});\r\n","{% block buckaroo_payment_detail %}\r\n
\r\n \r\n \r\n\r\n {{ $tc('buckaroo-payment.paymentDetail.paylinkDescription') }}\r\n \r\n
\r\n {{ $tc('buckaroo-payment.paymentDetail.yourLink') }}: {{ paylink }}\r\n
\r\n\r\n \r\n
\r\n \r\n \r\n {{ $tc('buckaroo-payment.paymentDetail.paylinkButton') }}\r\n
\r\n
\r\n
\r\n\r\n
\r\n\r\n \r\n \r\n {{ $tc('buckaroo-payment.orderItems.title') }}\r\n \r\n\r\n \r\n \r\n\r\n \r\n\r\n \r\n \r\n
{{ $tc('buckaroo-payment.paymentDetail.amountTotalTitle') }}:
\r\n
{{ buckaroo_refund_amount }} {{ currency }}
\r\n
\r\n
\r\n \r\n \r\n \r\n \r\n\r\n \r\n\r\n \r\n\r\n \r\n\r\n \r\n\r\n \r\n \r\n
{{ $tc('buckaroo-payment.paymentDetail.amountCustomRefundTitle') }}:
\r\n
\r\n \r\n {{ currency }}\r\n
\r\n
\r\n \r\n
{{ $tc('buckaroo-payment.paymentDetail.amountRefundTotalTitle') }}:
\r\n
{{ buckaroo_refund_total_amount }} {{ currency }}
\r\n
\r\n
\r\n \r\n
\r\n\r\n \r\n
\r\n \r\n {{ $tc('buckaroo-payment.paymentDetail.buttonTitle') }}\r\n
\r\n
\r\n
\r\n\r\n
\r\n\r\n \r\n\r\n {{ $tc('buckaroo-payment.paymentDetail.payDescription') }}\r\n\r\n \r\n
\r\n \r\n {{ $tc('buckaroo-payment.paymentDetail.payButton') }}\r\n
\r\n
\r\n
\r\n\r\n
\r\n\r\n \r\n\r\n {{ $tc('buckaroo-payment.paymentDetail.klarnaMorDescription') }}\r\n\r\n \r\n \r\n
{{ $tc('buckaroo-payment.paymentDetail.klarnaMorCancel') }}
\r\n
\r\n \r\n {{ $tc('buckaroo-payment.paymentDetail.klarnaMorCancelButton') }}\r\n \r\n
\r\n
\r\n
\r\n\r\n \r\n \r\n
{{ $tc('buckaroo-payment.paymentDetail.klarnaMorUpdate') }}
\r\n
\r\n \r\n {{ $tc('buckaroo-payment.paymentDetail.klarnaMorUpdateButton') }}\r\n \r\n
\r\n
\r\n
\r\n\r\n \r\n \r\n
{{ $tc('buckaroo-payment.paymentDetail.klarnaMorExtend') }}
\r\n
\r\n \r\n {{ $tc('buckaroo-payment.paymentDetail.klarnaMorExtendButton') }}\r\n \r\n
\r\n
\r\n
\r\n\r\n \r\n \r\n
{{ $tc('buckaroo-payment.paymentDetail.klarnaMorShipping') }}
\r\n
\r\n \r\n {{ $tc('buckaroo-payment.paymentDetail.klarnaMorShippingButton') }}\r\n \r\n
\r\n
\r\n
\r\n\r\n
\r\n\r\n \r\n \r\n\r\n \r\n\r\n \r\n \r\n\r\n\r\n \r\n \r\n
\r\n{% endblock %}","import template from './buckaroo-payment-detail.html.twig';\r\nimport './buckaroo-payment-detail.scss';\r\n\r\nconst { Component, Filter, Context } = Shopware;\r\nconst Criteria = Shopware.Data.Criteria;\r\n\r\nComponent.register('buckaroo-payment-detail', {\r\n template,\r\n\r\n inject: [\r\n 'repositoryFactory',\r\n 'BuckarooPaymentService',\r\n 'systemConfigApiService'\r\n ],\r\n\r\n data() {\r\n return {\r\n config: {},\r\n buckaroo_refund_amount: '0',\r\n buckaroo_refund_total_amount: '0',\r\n currency: 'EUR',\r\n isRefundPossible: true,\r\n isCapturePossible: false,\r\n isPaylinkAvailable: false,\r\n isPaylinkVisible: false,\r\n paylinkMessage: '',\r\n paylink: '',\r\n isLoading: false,\r\n order: false,\r\n buckarooTransactions: null,\r\n orderItems: [],\r\n transactionsToRefund: [],\r\n relatedResources: [],\r\n isAuthorized: false,\r\n isKlarnaMor: false,\r\n fulfillmentMessage: '',\r\n fulfillmentStatus: null\r\n };\r\n },\r\n\r\n computed: {\r\n orderItemsColumns() {\r\n return [\r\n {\r\n property: 'name',\r\n label: this.$tc('buckaroo-payment.orderItems.types.name'),\r\n allowResize: false,\r\n primary: true,\r\n inlineEdit: true,\r\n multiLine: true,\r\n },\r\n {\r\n property: 'quantity',\r\n label: this.$tc('buckaroo-payment.orderItems.types.quantity'),\r\n rawData: true,\r\n align: 'right'\r\n },\r\n {\r\n property: 'totalAmount',\r\n label: this.$tc('buckaroo-payment.orderItems.types.totalAmount'),\r\n rawData: true,\r\n align: 'right'\r\n }\r\n ];\r\n },\r\n\r\n transactionsToRefundColumns() {\r\n return [\r\n {\r\n property: 'transaction_method',\r\n rawData: true\r\n },{\r\n property: 'amount',\r\n rawData: true\r\n }\r\n ];\r\n },\r\n\r\n relatedResourceColumns() {\r\n return [\r\n {\r\n property: 'created_at',\r\n label: this.$tc('buckaroo-payment.transactionHistory.types.created_at'),\r\n rawData: true\r\n },\r\n {\r\n property: 'total',\r\n label: this.$tc('buckaroo-payment.transactionHistory.types.total'),\r\n rawData: true\r\n },{\r\n property: 'shipping_costs',\r\n label: this.$tc('buckaroo-payment.transactionHistory.types.shipping_costs'),\r\n rawData: true\r\n },{\r\n property: 'total_excluding_vat',\r\n label: this.$tc('buckaroo-payment.transactionHistory.types.total_excluding_vat'),\r\n rawData: true\r\n },{\r\n property: 'vat',\r\n label: this.$tc('buckaroo-payment.transactionHistory.types.vat'),\r\n rawData: true\r\n },{\r\n property: 'transaction_key',\r\n label: this.$tc('buckaroo-payment.transactionHistory.types.transaction_key'),\r\n rawData: true\r\n },{\r\n property: 'transaction_method',\r\n label: this.$tc('buckaroo-payment.transactionHistory.types.transaction_method'),\r\n rawData: true\r\n },{\r\n property: 'statuscode',\r\n label: this.$tc('buckaroo-payment.transactionHistory.types.statuscode'),\r\n rawData: true\r\n }\r\n ];\r\n }\r\n },\r\n\r\n created() {\r\n this.createdComponent();\r\n },\r\n\r\n methods: {\r\n recalculateOrderItems() {\r\n this.buckaroo_refund_amount = 0;\r\n for (const key in this.orderItems) {\r\n this.orderItems[key]['totalAmount'] = parseFloat(parseFloat(this.orderItems[key]['unitPrice']) * parseFloat(this.orderItems[key]['quantity'] || 0)).toFixed(2);\r\n this.buckaroo_refund_amount = parseFloat(parseFloat(this.buckaroo_refund_amount) + parseFloat(this.orderItems[key]['totalAmount'])).toFixed(2);\r\n }\r\n },\r\n recalculateRefundItems() {\r\n this.buckaroo_refund_total_amount = 0;\r\n for (const key in this.transactionsToRefund) {\r\n if (this.transactionsToRefund[key]['amount']) {\r\n this.buckaroo_refund_total_amount = parseFloat(parseFloat(this.buckaroo_refund_total_amount) + parseFloat(this.transactionsToRefund[key]['amount'])).toFixed(2);\r\n }\r\n }\r\n },\r\n\r\n getCustomRefundEnabledEl() {\r\n return document.getElementById('buckaroo_custom_refund_enabled');\r\n },\r\n\r\n getCustomRefundAmountEl() {\r\n return document.getElementById('buckaroo_custom_refund_amount');\r\n },\r\n\r\n toggleCustomRefund() {\r\n if (this.getCustomRefundEnabledEl() && this.getCustomRefundAmountEl()) {\r\n this.getCustomRefundAmountEl().disabled = !this.getCustomRefundEnabledEl().checked;\r\n }\r\n },\r\n\r\n getCustomRefundAmount() {\r\n if (this.getCustomRefundEnabledEl() && this.getCustomRefundAmountEl() && this.getCustomRefundEnabledEl().checked) {\r\n return this.getCustomRefundAmountEl().value;\r\n }\r\n return 0;\r\n },\r\n\r\n createdComponent() {\r\n let that = this;\r\n const orderId = this.$route.params.id;\r\n\r\n this.systemConfigApiService.getValues('BuckarooPayments.config', null)\r\n .then(values => {\r\n this.config = values;\r\n });\r\n\r\n const orderRepository = this.repositoryFactory.create('order');\r\n const orderCriteria = new Criteria(1, 1);\r\n\r\n this.orderId = orderId;\r\n orderCriteria.addAssociation('transactions.paymentMethod')\r\n .addAssociation('transactions');\r\n\r\n orderCriteria.getAssociation('transactions').addSorting(Criteria.sort('createdAt'));\r\n\r\n orderRepository.get(orderId, Context.api, orderCriteria).then((order) => {\r\n that.checkedIsAuthorized(order);\r\n const buckarooKey = order.transactions &&\r\n order.transactions.last().paymentMethod &&\r\n order.transactions.last().paymentMethod.customFields &&\r\n order.transactions.last().paymentMethod.customFields.buckaroo_key\r\n ? order.transactions.last().paymentMethod.customFields.buckaroo_key.toLowerCase()\r\n : '';\r\n\r\n that.isCapturePossible = !!buckarooKey &&\r\n (['klarnakp', 'billink', 'afterpay', 'klarna'].includes(buckarooKey) || that.isAfterpayCapturePossible(order));\r\n\r\n that.isKlarnaMor = buckarooKey === 'klarna';\r\n\r\n that.isPaylinkVisible = that.isPaylinkAvailable = this.getConfigValue('paylinkEnabled') && order.stateMachineState && order.stateMachineState.technicalName && order.stateMachineState.technicalName == 'open' && order.transactions && order.transactions.last().stateMachineState.technicalName == 'open';\r\n });\r\n\r\n this.BuckarooPaymentService.getBuckarooTransaction(orderId)\r\n .then((response) => {\r\n that.orderItems = [];\r\n that.transactionsToRefund = [];\r\n that.relatedResources = [];\r\n\r\n this.$emit('loading-change', false);\r\n\r\n if (response.orderItems && Array.isArray(response.orderItems)) {\r\n response.orderItems.forEach((element) => {\r\n that.orderItems.push({\r\n id: element.id,\r\n name: element.name,\r\n quantity: element.quantity,\r\n quantityMax: element.quantity,\r\n unitPrice: element.unitPrice.value,\r\n totalAmount: element.totalAmount.value,\r\n variations: element.variations || [],\r\n });\r\n });\r\n }\r\n\r\n // Use backend-calculated total (single source of truth)\r\n that.buckaroo_refund_amount = response.refundTotals ? response.refundTotals.totalAmount : 0;\r\n that.currency = response.refundTotals ? response.refundTotals.currency : 'EUR';\r\n\r\n if (response.transactionsToRefund && Array.isArray(response.transactionsToRefund)) {\r\n response.transactionsToRefund.forEach((element) => {\r\n that.transactionsToRefund.push({\r\n id: element.id,\r\n transactions: element.transactions,\r\n amount: element.total,\r\n amountMax: element.total,\r\n currency: element.currency,\r\n transaction_method: element.transaction_method,\r\n logo: element.transaction_method ? element.logo : null\r\n });\r\n that.currency = element.currency;\r\n });\r\n }\r\n that.recalculateRefundItems();\r\n\r\n if (response.transactions && Array.isArray(response.transactions)) {\r\n response.transactions.forEach((element) => {\r\n that.relatedResources.push({\r\n id: element.id,\r\n transaction_key: element.transaction,\r\n total: element.total,\r\n total_excluding_vat: element.total_excluding_vat,\r\n shipping_costs: element.shipping_costs,\r\n vat: element.vat,\r\n transaction_method: element.transaction_method,\r\n logo: element.transaction_method ? element.logo : null,\r\n created_at: element.created_at,\r\n statuscode: element.statuscode\r\n });\r\n });\r\n }\r\n\r\n })\r\n .catch((errorResponse) => {\r\n console.log('errorResponse', errorResponse);\r\n });\r\n\r\n },\r\n\r\n isAfterpayCapturePossible(order) {\r\n return order.customFields.buckaroo_is_authorize === true;\r\n },\r\n\r\n checkedIsAuthorized(order) {\r\n this.isAuthorized = order?.transactions?.last()?.stateMachineState?.technicalName === \"authorized\";\r\n },\r\n\r\n refundOrder(transaction, amount) {\r\n let that = this;\r\n that.isRefundPossible = false;\r\n this.BuckarooPaymentService.refundPayment(transaction, this.transactionsToRefund, this.orderItems, this.getCustomRefundAmount())\r\n .then((response) => {\r\n for (const key in response) {\r\n if (response[key].status) {\r\n this.$store.dispatch('notification/createNotification', {\r\n variant: 'success',\r\n title: that.$tc('buckaroo-payment.settingsForm.titleSuccess'),\r\n message: that.$tc(response[key].message) + response[key].amount\r\n });\r\n } else {\r\n this.$store.dispatch('notification/createNotification', {\r\n variant: 'error',\r\n title: that.$tc('buckaroo-payment.settingsForm.titleError'),\r\n message: that.$tc(response[key].message)\r\n });\r\n }\r\n }\r\n that.isRefundPossible = true;\r\n this.createdComponent();\r\n })\r\n .catch((errorResponse) => {\r\n this.$store.dispatch('notification/createNotification', {\r\n variant: 'error',\r\n title: this.$tc('buckaroo-payment.settingsForm.titleError'),\r\n message: errorResponse.response.data.message\r\n });\r\n that.isRefundPossible = true;\r\n });\r\n },\r\n\r\n createPaylink(transaction) {\r\n let that = this;\r\n that.isPaylinkAvailable = false;\r\n this.BuckarooPaymentService.createPaylink(transaction, this.transactionsToRefund, this.orderItems)\r\n .then((response) => {\r\n if (response.status) {\r\n that.paylinkMessage = that.$tc(response.message) + response.paylinkhref;\r\n that.paylink = response.paylink;\r\n this.$store.dispatch('notification/createNotification', {\r\n variant: 'success',\r\n title: that.$tc('buckaroo-payment.settingsForm.titleSuccess'),\r\n message: that.paylinkMessage\r\n });\r\n } else {\r\n this.$store.dispatch('notification/createNotification', {\r\n variant: 'error',\r\n title: that.$tc('buckaroo-payment.settingsForm.titleError'),\r\n message: that.$tc(response.message)\r\n });\r\n }\r\n that.isPaylinkAvailable = true;\r\n })\r\n .catch((errorResponse) => {\r\n this.$store.dispatch('notification/createNotification', {\r\n variant: 'error',\r\n title: this.$tc('buckaroo-payment.settingsForm.titleError'),\r\n message: errorResponse.response.data.message\r\n });\r\n that.isPaylinkAvailable = true;\r\n });\r\n },\r\n\r\n getConfigValue(field) {\r\n return this.config[`BuckarooPayments.config.${field}`];\r\n },\r\n\r\n captureOrder(transaction) {\r\n let that = this;\r\n that.isCapturePossible = false;\r\n this.BuckarooPaymentService.captureOrder(transaction, this.transactionsToRefund, this.orderItems)\r\n .then((response) => {\r\n if (response.status) {\r\n this.$store.dispatch('notification/createNotification', {\r\n variant: 'success',\r\n title: that.$tc('buckaroo-payment.settingsForm.titleSuccess'),\r\n message: response.message\r\n });\r\n } else {\r\n this.$store.dispatch('notification/createNotification', {\r\n variant: 'error',\r\n title: that.$tc('buckaroo-payment.settingsForm.titleError'),\r\n message: response.message\r\n });\r\n }\r\n that.isCapturePossible = true;\r\n this.createdComponent();\r\n })\r\n .catch((errorResponse) => {\r\n this.$store.dispatch('notification/createNotification', {\r\n variant: 'error',\r\n title: this.$tc('buckaroo-payment.settingsForm.titleError'),\r\n message: that.$tc(errorResponse.response.data.message)\r\n });\r\n that.isCapturePossible = true;\r\n });\r\n },\r\n\r\n klarnaMor(action) {\r\n let that = this;\r\n that.isLoading = true;\r\n this.BuckarooPaymentService.klarnaMor(this.orderId, action)\r\n .then((response) => {\r\n if (response.status) {\r\n this.$store.dispatch('notification/createNotification', {\r\n variant: 'success',\r\n title: that.$tc('buckaroo-payment.settingsForm.titleSuccess'),\r\n message: response.message\r\n });\r\n } else {\r\n this.$store.dispatch('notification/createNotification', {\r\n variant: 'error',\r\n title: that.$tc('buckaroo-payment.settingsForm.titleError'),\r\n message: response.message\r\n });\r\n }\r\n that.isLoading = false;\r\n this.createdComponent();\r\n })\r\n .catch((errorResponse) => {\r\n this.$store.dispatch('notification/createNotification', {\r\n variant: 'error',\r\n title: this.$tc('buckaroo-payment.settingsForm.titleError'),\r\n message: errorResponse.response && errorResponse.response.data\r\n ? errorResponse.response.data.message\r\n : 'An error occurred'\r\n });\r\n that.isLoading = false;\r\n });\r\n }\r\n }\r\n});\r\n","\r\nconst { Component } = Shopware;\r\n\r\nComponent.extend('buckaroo-payment-config', 'sw-extension-config', {\r\n});","const { Module } = Shopware;\r\n\r\nimport './extension/sw-order';\r\nimport './extension/sw-order-detail-base';\r\nimport './extension/sw-order-user-card';\r\nimport './extension/sw-system-config';\r\nimport './page/buckaroo-payment-detail';\r\n\r\nimport './page/buckaroo-payment-config';\r\n\r\nimport nlNL from './snippet/nl-NL.json';\r\nimport deDE from './snippet/de-DE.json';\r\nimport enGB from './snippet/en-GB.json';\r\n\r\nModule.register('buckaroo-payment', {\r\n type: 'plugin',\r\n name: 'BuckarooPayment',\r\n title: 'buckaroo-payment.general.title',\r\n description: 'buckaroo-payment.general.description',\r\n version: '1.0.0',\r\n targetVersion: '1.0.0',\r\n color: '#000000',\r\n icon: 'default-action-settings',\r\n\r\n snippets: {\r\n 'nl-NL': nlNL,\r\n 'de-DE': deDE,\r\n 'en-GB': enGB\r\n },\r\n\r\n routeMiddleware(next, currentRoute) {\r\n if (currentRoute.name === 'sw.order.detail') {\r\n currentRoute.children.push({\r\n component: 'buckaroo-payment-detail',\r\n name: 'buckaroo.payment.detail',\r\n isChildren: true,\r\n path: '/sw/order/buckaroo/detail/:id'\r\n });\r\n }\r\n next(currentRoute);\r\n },\r\n\r\n routes: {\r\n config: {\r\n component: 'buckaroo-payment-config',\r\n path: ':namespace/payment/:paymentCode',\r\n name: 'buckaroo.config.payment',\r\n meta: {\r\n parentPath:'sw.extension.config'\r\n },\r\n props: {\r\n default(route) {\r\n return { namespace: route.params.namespace };\r\n },\r\n },\r\n }\r\n }\r\n});\r\n","const { ApiService } = Shopware.Classes;\r\n\r\nclass BuckarooPaymentService extends ApiService {\r\n constructor(httpClient, loginService, apiEndpoint = 'buckaroo')\r\n {\r\n super(httpClient, loginService, apiEndpoint);\r\n }\r\n\r\n getBasicHeaders() {\r\n if (this.loginService && typeof this.loginService.getToken === 'function') {\r\n return super.getBasicHeaders();\r\n }\r\n return {\r\n 'Content-Type': 'application/json',\r\n 'Accept': 'application/json'\r\n };\r\n }\r\n\r\n getBuckarooTransaction(transaction)\r\n {\r\n const apiRoute = `_action/${this.getApiBasePath()}/getBuckarooTransaction`;\r\n\r\n return this.httpClient.post(\r\n apiRoute,\r\n {\r\n transaction: transaction\r\n },\r\n {\r\n headers: this.getBasicHeaders()\r\n }\r\n ).then((response) => {\r\n return ApiService.handleResponse(response);\r\n });\r\n }\r\n\r\n refundPayment(transaction, transactionsToRefund, orderItems, customRefundAmount)\r\n {\r\n const apiRoute = `_action/${this.getApiBasePath()}/refund`;\r\n\r\n return this.httpClient.post(\r\n apiRoute,\r\n {\r\n transaction: transaction,\r\n transactionsToRefund: transactionsToRefund,\r\n orderItems: orderItems,\r\n customRefundAmount: customRefundAmount\r\n },\r\n {\r\n headers: this.getBasicHeaders()\r\n }\r\n ).then((response) => {\r\n return ApiService.handleResponse(response);\r\n });\r\n }\r\n\r\n captureOrder(transaction)\r\n {\r\n const apiRoute = `_action/${this.getApiBasePath()}/capture`;\r\n\r\n return this.httpClient.post(\r\n apiRoute,\r\n {\r\n transaction: transaction\r\n },\r\n {\r\n headers: this.getBasicHeaders()\r\n }\r\n ).then((response) => {\r\n return ApiService.handleResponse(response);\r\n });\r\n }\r\n\r\n createPaylink(transaction)\r\n {\r\n const apiRoute = `_action/${this.getApiBasePath()}/paylink`;\r\n\r\n return this.httpClient.post(\r\n apiRoute,\r\n {\r\n transaction: transaction\r\n },\r\n {\r\n headers: this.getBasicHeaders()\r\n }\r\n ).then((response) => {\r\n return ApiService.handleResponse(response);\r\n });\r\n }\r\n\r\n klarnaMor(orderId, action)\r\n {\r\n const apiRoute = `_action/${this.getApiBasePath()}/klarna-mor`;\r\n\r\n return this.httpClient.post(\r\n apiRoute,\r\n {\r\n orderId: orderId,\r\n action: action\r\n },\r\n {\r\n headers: this.getBasicHeaders()\r\n }\r\n ).then((response) => {\r\n return ApiService.handleResponse(response);\r\n });\r\n }\r\n\r\n}\r\n\r\nShopware.Service().register('BuckarooPaymentService', () => {\r\n const initContainer = Shopware.Application.getContainer('init');\r\n // Ensure we use the global loginService which always exists in admin\r\n const loginService = Shopware.Service('loginService');\r\n return new BuckarooPaymentService(initContainer.httpClient, loginService);\r\n});\r\n\r\n","const { ApiService } = Shopware.Classes;\r\n\r\nclass BuckarooPaymentSettingsService extends ApiService {\r\n constructor(httpClient, loginService, apiEndpoint = 'buckaroo')\r\n {\r\n super(httpClient, loginService, apiEndpoint);\r\n }\r\n\r\n getBasicHeaders() {\r\n if (this.loginService && typeof this.loginService.getToken === 'function') {\r\n return super.getBasicHeaders();\r\n }\r\n return {\r\n 'Content-Type': 'application/json',\r\n 'Accept': 'application/json'\r\n };\r\n }\r\n\r\n getSupportVersion()\r\n {\r\n const apiRoute = `_action/${this.getApiBasePath()}/version`;\r\n\r\n return this.httpClient.post(\r\n apiRoute,\r\n {\r\n },\r\n {\r\n headers: this.getBasicHeaders()\r\n }\r\n ).then((response) => {\r\n return ApiService.handleResponse(response);\r\n });\r\n }\r\n\r\n getTaxes()\r\n {\r\n const apiRoute = `_action/${this.getApiBasePath()}/taxes`;\r\n\r\n return this.httpClient.post(\r\n apiRoute,\r\n {\r\n },\r\n {\r\n headers: this.getBasicHeaders()\r\n }\r\n ).then((response) => {\r\n return ApiService.handleResponse(response);\r\n });\r\n }\r\n\r\n getIn3Icons()\r\n {\r\n const apiRoute = `_action/${this.getApiBasePath()}/in3/logos`;\r\n\r\n return this.httpClient.post(\r\n apiRoute,\r\n {\r\n },\r\n {\r\n headers: this.getBasicHeaders()\r\n }\r\n ).then((response) => {\r\n return ApiService.handleResponse(response);\r\n });\r\n }\r\n\r\n getApiTest(websiteKeyId, secretKeyId, currentSalesChannelId)\r\n {\r\n const apiRoute = `_action/${this.getApiBasePath()}/getBuckarooApiTest`;\r\n\r\n return this.httpClient.post(\r\n apiRoute,\r\n {\r\n websiteKeyId: websiteKeyId,\r\n secretKeyId: secretKeyId,\r\n saleChannelId: currentSalesChannelId\r\n },\r\n {\r\n headers: this.getBasicHeaders()\r\n }\r\n ).then((response) => {\r\n return ApiService.handleResponse(response);\r\n });\r\n }\r\n}\r\n\r\nShopware.Service().register('BuckarooPaymentSettingsService', () => {\r\n const initContainer = Shopware.Application.getContainer('init');\r\n // Ensure we use the global loginService which always exists in admin\r\n const loginService = Shopware.Service('loginService');\r\n return new BuckarooPaymentSettingsService(initContainer.httpClient, loginService);\r\n});\r\n\r\n","
\r\n {{$tc('buckaroo-payment.afterpay.setup')}}\r\n
\r\n
\r\n setTaxAssociation(tax.id, value)\"\r\n @input=\"(value) => setTaxAssociation(tax.id, value)\"\r\n @update:value=\"(value) => setTaxAssociation(tax.id, value)\"\r\n :value=\"getSelectValue(tax.id)\"\r\n >\r\n
\r\n
\r\n
","const { Component } = Shopware;\r\n\r\nimport template from './buckaroo-afterpay-old-tax.html.twig';\r\n\r\nComponent.register('buckaroo-afterpay-old-tax', {\r\n template,\r\n\r\n inject: ['BuckarooPaymentSettingsService'],\r\n\r\n data() {\r\n return {\r\n taxes: [],\r\n showTaxes: false,\r\n afterpayTaxes: [\r\n { name: this.$tc('buckaroo-payment.afterpay.hightTaxes'), id: 1 },\r\n { name: this.$tc('buckaroo-payment.afterpay.middleTaxes'), id: 5 },\r\n { name: this.$tc('buckaroo-payment.afterpay.lowTaxes'), id: 2 },\r\n { name: this.$tc('buckaroo-payment.afterpay.zeroTaxes'), id: 3 },\r\n { name: this.$tc('buckaroo-payment.afterpay.noTaxes'), id: 4 },\r\n ],\r\n taxAssociation: {}\r\n };\r\n },\r\n\r\n model: {\r\n prop: 'value',\r\n event: 'change',\r\n },\r\n\r\n computed: {\r\n\r\n },\r\n props: {\r\n name: {\r\n type: String,\r\n required: true,\r\n default: ''\r\n },\r\n value: {\r\n type: Object,\r\n required: false,\r\n default() {\r\n return {}\r\n }\r\n }\r\n },\r\n\r\n\r\n created() {\r\n this.BuckarooPaymentSettingsService.getTaxes()\r\n .then((result) => {\r\n this.taxes = result.taxes.map((tax) => {\r\n return {\r\n id: tax.id,\r\n name: tax.name\r\n };\r\n })\r\n });\r\n\r\n },\r\n methods: {\r\n setTaxAssociation(taxId, eventOrValue) {\r\n \r\n try {\r\n let actualValue = eventOrValue;\r\n \r\n if (eventOrValue && typeof eventOrValue === 'object') {\r\n if (eventOrValue.target) {\r\n actualValue = eventOrValue.target.value;\r\n } else if (eventOrValue.hasOwnProperty('value')) {\r\n actualValue = eventOrValue.value;\r\n } else if (eventOrValue.hasOwnProperty('id')) {\r\n actualValue = eventOrValue.id;\r\n }\r\n }\r\n this.taxAssociation[taxId] = actualValue;\r\n this.$emit('change', {...this.value, ...this.taxAssociation});\r\n \r\n } catch (error) {\r\n console.error('Error in setTaxAssociation:', error);\r\n }\r\n },\r\n getSelectValue(taxId) {\r\n if (this.value[taxId]) {\r\n return this.value[taxId];\r\n }\r\n return;\r\n }\r\n }\r\n });\r\n","
\r\n \r\n \r\n\r\n \r\n \r\n
","const { Component } = Shopware;\r\n\r\nimport template from \"./buckaroo-main-config.html.twig\";\r\n\r\nComponent.register(\"buckaroo-main-config\", {\r\n template,\r\n props: {\r\n configSettings: {\r\n type: Array,\r\n required: false,\r\n default: () => []\r\n },\r\n value: {\r\n type: Object,\r\n required: false,\r\n default: () => ({})\r\n },\r\n elementMethods: {\r\n type: Object,\r\n required: false,\r\n default: () => ({})\r\n },\r\n isNotDefaultSalesChannel: {\r\n type: Boolean,\r\n required: false,\r\n default: false\r\n },\r\n currentSalesChannelId: {\r\n type: String,\r\n required: false,\r\n default: null\r\n }\r\n },\r\n emits: ['input'],\r\n\r\n model: {\r\n prop: 'value',\r\n event: 'input'\r\n },\r\n\r\n\r\n data() {\r\n return {\r\n selectedCard: this.$route.params?.paymentCode || 'general'\r\n }\r\n },\r\n\r\n watch: {\r\n value: {\r\n handler(newVal, oldVal) {\r\n this.$nextTick(() => {\r\n this.$forceUpdate();\r\n });\r\n },\r\n deep: true,\r\n immediate: true\r\n },\r\n $route(to) {\r\n if (to.params?.paymentCode) {\r\n this.selectedCard = to.params.paymentCode;\r\n }\r\n }\r\n },\r\n\r\n computed: {\r\n mainCard() {\r\n const card = this.configSettings.filter((card) => card.name === this.selectedCard)?.pop();\r\n return card;\r\n }\r\n },\r\n\r\n methods: {\r\n onInput(value) {\r\n this.$emit('input', value);\r\n }\r\n }\r\n\r\n})","{% block buckaroo_config_card %}\r\n \r\n \r\n\r\n
\r\n
\r\n \r\n \r\n \r\n \r\n \r\n
\r\n
\r\n\r\n \r\n
\r\n{% endblock %}\r\n","import template from './buckaroo-config-card.html.twig';\r\n\r\nconst { Component } = Shopware;\r\n\r\nComponent.register('buckaroo-config-card', {\r\n template,\r\n\r\n inject: ['BuckarooPaymentSettingsService'],\r\n\r\n data() {\r\n return {\r\n shopwareVersion: null\r\n };\r\n },\r\n\r\n mounted() {\r\n this.fetchShopwareVersion();\r\n this.$nextTick(() => {\r\n this.$forceUpdate();\r\n });\r\n },\r\n watch: {\r\n value: {\r\n handler() {\r\n this.$nextTick(() => {\r\n this.$forceUpdate();\r\n });\r\n },\r\n deep: true,\r\n immediate: true\r\n },\r\n \r\n currentSalesChannelId: {\r\n handler(newChannelId, oldChannelId) {\r\n if (newChannelId !== oldChannelId) {\r\n \r\n this.$nextTick(() => {\r\n this.$forceUpdate();\r\n });\r\n }\r\n },\r\n immediate: false\r\n }\r\n },\r\n computed: {\r\n canShowCredentialTester() {\r\n const key = this.getValueForName('websiteKey');\r\n const secretKey = this.getValueForName('secretKey');\r\n const isGeneralConfig = this.card?.name === 'general';\r\n \r\n if (!isGeneralConfig) {\r\n return false;\r\n }\r\n\r\n const hasWebsiteKey = key !== undefined && key !== null && key !== '';\r\n const hasSecretKey = secretKey !== undefined && secretKey !== null && secretKey !== '';\r\n const canShow = hasWebsiteKey || hasSecretKey;\r\n return canShow;\r\n },\r\n \r\n hasValidConfigData() {\r\n return this.value && typeof this.value === 'object' && Object.keys(this.value).length > 0;\r\n },\r\n \r\n reactiveValue() {\r\n return this.value;\r\n }\r\n },\r\n\r\n emits: ['input'],\r\n\r\n model: {\r\n prop: 'value',\r\n event: 'input'\r\n },\r\n\r\n props: {\r\n card: {\r\n type: Object,\r\n required: false,\r\n default: () => ({ elements: [] })\r\n },\r\n configSettings: {\r\n type: Array,\r\n required: false,\r\n default: () => []\r\n },\r\n methods: {\r\n type: Object,\r\n required: true,\r\n },\r\n isNotDefaultSalesChannel: {\r\n type: Boolean,\r\n required: true,\r\n },\r\n currentSalesChannelId: {\r\n type: String,\r\n required: true,\r\n },\r\n value: {\r\n type: Object,\r\n required: false,\r\n default: () => ({})\r\n },\r\n },\r\n\r\n methods: {\r\n fetchShopwareVersion() {\r\n const service = this.BuckarooPaymentSettingsService;\r\n if (service && typeof service.getSupportVersion === 'function') {\r\n service.getSupportVersion().then((data) => {\r\n if (data && data.shopware_version) {\r\n this.shopwareVersion = data.shopware_version;\r\n }\r\n }).catch(() => {});\r\n }\r\n },\r\n\r\n /**\r\n * Returns true if Shopware version is >= 6.7.4.0 (label fix applies; older versions show duplicate labels if we use enhanced label logic).\r\n * When version is unknown, returns false to avoid duplicate labels on older Shopware.\r\n */\r\n isShopware674OrNewer() {\r\n if (!this.shopwareVersion || typeof this.shopwareVersion !== 'string') {\r\n return false;\r\n }\r\n const parts = this.shopwareVersion.split('.').map((n) => parseInt(n, 10) || 0);\r\n const major = parts[0] || 0;\r\n const minor = parts[1] || 0;\r\n const patch = parts[2] || 0;\r\n const build = parts[3] || 0;\r\n if (major > 6) return true;\r\n if (major < 6) return false;\r\n if (minor > 7) return true;\r\n if (minor < 7) return false;\r\n if (patch > 4) return true;\r\n if (patch < 4) return false;\r\n return build >= 0;\r\n },\r\n\r\n getElementBind(element, props = {}) {\r\n if (!this.methods || !this.methods.getElementBind) {\r\n const label = element.label ? this.getInlineSnippet(element.label) : null;\r\n return {\r\n name: element.name,\r\n type: element.type || 'text',\r\n config: element.config || {},\r\n label: label,\r\n value: this.getValueForName(element.name.replace('BuckarooPayments.config.', ''))\r\n };\r\n }\r\n \r\n const baseBinding = this.methods.getElementBind(element, props);\r\n \r\n const fieldName = element.name.replace('BuckarooPayments.config.', '');\r\n let currentValue = this.getValueForName(fieldName);\r\n \r\n // Ensure config object exists\r\n const config = baseBinding.config || element.config || {};\r\n \r\n // For bool fields, ensure we have a proper boolean value\r\n if (element.type === 'bool') {\r\n if (currentValue === null || currentValue === undefined) {\r\n currentValue = baseBinding.value !== undefined ? baseBinding.value : false;\r\n } else {\r\n // Ensure it's a proper boolean - handle string values like \"0\", \"1\", \"false\", \"true\"\r\n if (typeof currentValue === 'string') {\r\n currentValue = currentValue === '1' || currentValue === 'true' || currentValue === 'on';\r\n } else {\r\n currentValue = Boolean(currentValue);\r\n }\r\n }\r\n }\r\n \r\n // Extract label only for Shopware >= 6.7.4.0; in older versions baseBinding/template already show the label and our enhanced logic causes duplicate labels\r\n let finalLabel = null;\r\n const useEnhancedLabels = this.isShopware674OrNewer();\r\n\r\n if (useEnhancedLabels) {\r\n // For bool/select fields, prioritize configSettings since baseBinding.label is often undefined in SW 6.7.4+\r\n if ((element.type === 'bool' || element.type === 'single-select' || element.type === 'multi-select') && this.configSettings && Array.isArray(this.configSettings)) {\r\n for (const configCard of this.configSettings) {\r\n if (configCard.elements && Array.isArray(configCard.elements)) {\r\n const configElement = configCard.elements.find(el => el.name === element.name);\r\n if (configElement) {\r\n if (configElement.label) {\r\n let extractedLabel = this.getInlineSnippet(configElement.label);\r\n if (!extractedLabel || (typeof extractedLabel === 'string' && extractedLabel.trim().length === 0)) {\r\n if (typeof configElement.label === 'object' && configElement.label !== null) {\r\n const locale = this.$i18n?.locale || 'en-GB';\r\n extractedLabel = configElement.label[locale] || configElement.label['en-GB'] || Object.values(configElement.label)[0] || null;\r\n } else if (typeof configElement.label === 'string') {\r\n extractedLabel = configElement.label;\r\n }\r\n }\r\n if (extractedLabel && typeof extractedLabel === 'string' && extractedLabel.trim().length > 0) {\r\n finalLabel = extractedLabel;\r\n break;\r\n }\r\n }\r\n if (!finalLabel && configElement.config && configElement.config.label) {\r\n let extractedLabel = this.getInlineSnippet(configElement.config.label);\r\n if (!extractedLabel || (typeof extractedLabel === 'string' && extractedLabel.trim().length === 0)) {\r\n if (typeof configElement.config.label === 'object' && configElement.config.label !== null) {\r\n const locale = this.$i18n?.locale || 'en-GB';\r\n extractedLabel = configElement.config.label[locale] || configElement.config.label['en-GB'] || Object.values(configElement.config.label)[0] || null;\r\n } else if (typeof configElement.config.label === 'string') {\r\n extractedLabel = configElement.config.label;\r\n }\r\n }\r\n if (extractedLabel && typeof extractedLabel === 'string' && extractedLabel.trim().length > 0) {\r\n finalLabel = extractedLabel;\r\n break;\r\n }\r\n }\r\n }\r\n }\r\n }\r\n }\r\n\r\n if (!finalLabel) {\r\n if (baseBinding.label && typeof baseBinding.label === 'string' && baseBinding.label.trim().length > 0) {\r\n finalLabel = baseBinding.label;\r\n } else if (element.label) {\r\n let extractedLabel = this.getInlineSnippet(element.label);\r\n if (!extractedLabel || (typeof extractedLabel === 'string' && extractedLabel.trim().length === 0)) {\r\n if (typeof element.label === 'object' && element.label !== null) {\r\n const locale = this.$i18n?.locale || 'en-GB';\r\n extractedLabel = element.label[locale] || element.label['en-GB'] || Object.values(element.label)[0] || null;\r\n } else if (typeof element.label === 'string') {\r\n extractedLabel = element.label;\r\n }\r\n }\r\n if (extractedLabel && typeof extractedLabel === 'string' && extractedLabel.trim().length > 0) {\r\n finalLabel = extractedLabel;\r\n }\r\n } else if (this.card && this.card.elements && Array.isArray(this.card.elements)) {\r\n const rawElement = this.card.elements.find(el => el.name === element.name);\r\n if (rawElement && rawElement.label) {\r\n let extractedLabel = this.getInlineSnippet(rawElement.label);\r\n if (!extractedLabel || (typeof extractedLabel === 'string' && extractedLabel.trim().length === 0)) {\r\n if (typeof rawElement.label === 'object' && rawElement.label !== null) {\r\n const locale = this.$i18n?.locale || 'en-GB';\r\n extractedLabel = rawElement.label[locale] || rawElement.label['en-GB'] || Object.values(rawElement.label)[0] || null;\r\n } else if (typeof rawElement.label === 'string') {\r\n extractedLabel = rawElement.label;\r\n }\r\n }\r\n if (extractedLabel && typeof extractedLabel === 'string' && extractedLabel.trim().length > 0) {\r\n finalLabel = extractedLabel;\r\n }\r\n }\r\n }\r\n }\r\n if (!finalLabel && baseBinding.config && baseBinding.config.label && typeof baseBinding.config.label === 'string' && baseBinding.config.label.trim().length > 0) {\r\n finalLabel = baseBinding.config.label;\r\n }\r\n }\r\n\r\n // Only add label to config for SW >= 6.7.4.0 (avoids duplicate labels in older versions)\r\n let finalConfig = config;\r\n if (useEnhancedLabels && finalLabel && typeof finalLabel === 'string' && finalLabel.trim().length > 0) {\r\n if (element.type === 'bool' || element.type === 'single-select' || element.type === 'multi-select') {\r\n finalConfig = {\r\n ...config,\r\n label: finalLabel\r\n };\r\n }\r\n }\r\n\r\n const binding = {\r\n ...baseBinding,\r\n config: finalConfig\r\n };\r\n\r\n // Ensure specific fields are treated as real multi-selects in the UI\r\n const forcedMultiSelectFields = [\r\n 'allowedcreditcard',\r\n 'allowedcreditcards',\r\n 'allowedgiftcards',\r\n 'giftcardsPaymentmethods',\r\n 'payperemailAllowed'\r\n ];\r\n\r\n if (forcedMultiSelectFields.includes(fieldName)) {\r\n binding.type = 'multi-select';\r\n // Force Shopware to render the correct component\r\n binding.componentName = 'sw-multi-select';\r\n\r\n binding.config = {\r\n ...(binding.config || {}),\r\n multiple: true,\r\n // Prefer options coming from binding.config; fall back to element/config when needed\r\n options: (binding.config && binding.config.options)\r\n || (config && config.options)\r\n || element.options\r\n || []\r\n };\r\n\r\n // Debug logging to inspect how the multi-select is bound\r\n const sampleOption = Array.isArray(binding.config?.options) && binding.config.options.length > 0\r\n ? binding.config.options[0]\r\n : null;\r\n console.debug('[BuckarooConfigCard] getElementBind multi-select binding', {\r\n fieldName,\r\n bindingType: binding.type,\r\n componentName: binding.componentName,\r\n optionsCount: Array.isArray(binding.config?.options) ? binding.config.options.length : 0,\r\n currentValue,\r\n sampleOption\r\n });\r\n }\r\n \r\n // Only set binding.label for SW >= 6.7.4.0; older versions already show the label and would show duplicates\r\n if (useEnhancedLabels && finalLabel && typeof finalLabel === 'string' && finalLabel.trim().length > 0) {\r\n if (element.type === 'bool') {\r\n binding.label = finalLabel;\r\n } else if (!binding.label || (typeof binding.label === 'string' && binding.label.trim().length === 0)) {\r\n binding.label = finalLabel;\r\n }\r\n }\r\n\r\n if (element.type === 'bool') {\r\n binding.value = currentValue;\r\n // Only set fallback label for SW >= 6.7.4.0 to avoid duplicate labels in older versions\r\n if (useEnhancedLabels && (!binding.label || (typeof binding.label === 'string' && binding.label.trim().length === 0))) {\r\n binding.label = binding.config?.label || element.name.replace('BuckarooPayments.config.', '').replace(/([A-Z])/g, ' $1').trim();\r\n }\r\n }\r\n \r\n // Debug: Log if label is missing for bool/select fields\r\n if ((element.type === 'bool' || element.type === 'single-select' || element.type === 'multi-select') && (!binding.label || (typeof binding.label === 'string' && binding.label.trim().length === 0))) {\r\n console.warn('Missing label for field:', element.name, 'Type:', element.type, 'Element label:', element.label, 'Extracted:', finalLabel, 'BaseBinding label:', baseBinding.label, 'Final binding label:', binding.label);\r\n }\r\n \r\n return binding;\r\n },\r\n\r\n getInheritWrapperBind(element) {\r\n if (!this.methods || !this.methods.getInheritWrapperBind) {\r\n const fieldName = element.name.replace('BuckarooPayments.config.', '');\r\n return {\r\n name: element.name,\r\n currentValue: this.getValueForName(fieldName)\r\n };\r\n }\r\n \r\n const baseBinding = this.methods.getInheritWrapperBind(element);\r\n const fieldName = element.name.replace('BuckarooPayments.config.', '');\r\n const currentValue = this.getValueForName(fieldName);\r\n\r\n baseBinding.currentValue = currentValue;\r\n\r\n \r\n return baseBinding;\r\n },\r\n\r\n getFieldError(name) {\r\n if (!this.methods || !this.methods.getFieldError) {\r\n return null;\r\n }\r\n return this.methods.getFieldError(name);\r\n },\r\n\r\n kebabCase(string) {\r\n if (!this.methods || !this.methods.kebabCase) {\r\n return string ? string.toLowerCase().replace(/[A-Z]/g, '-$&').replace(/^-/, '') : '';\r\n }\r\n return this.methods.kebabCase(string);\r\n },\r\n\r\n getInlineSnippet(title) {\r\n try {\r\n if (typeof title === 'object' && title !== null) {\r\n const locale = this.$i18n?.locale || 'en-GB';\r\n \r\n if (title[locale]) {\r\n return title[locale];\r\n }\r\n \r\n if (title['en-GB']) {\r\n return title['en-GB'];\r\n }\r\n const firstKey = Object.keys(title)[0];\r\n if (firstKey && title[firstKey]) {\r\n return title[firstKey];\r\n }\r\n \r\n return JSON.stringify(title);\r\n }\r\n \r\n if (typeof title === 'string') {\r\n if (this.$t && typeof this.$t === 'function') {\r\n return this.$t(title);\r\n }\r\n return title;\r\n }\r\n return String(title);\r\n \r\n } catch (error) {\r\n console.warn('Translation error for:', title, error);\r\n return typeof title === 'object' ? JSON.stringify(title) : String(title);\r\n }\r\n },\r\n\r\n getInheritedValue(element) {\r\n if (!this.methods || !this.methods.getInheritedValue) {\r\n return null;\r\n }\r\n return this.methods.getInheritedValue(element);\r\n },\r\n\r\n getValueForName(name) {\r\n const currentValue = this.reactiveValue;\r\n \r\n if (!currentValue || typeof currentValue !== 'object') {\r\n return null;\r\n }\r\n\r\n let val = undefined;\r\n\r\n const keyVariations = [\r\n `BuckarooPayments.config.${name}`, // Full prefixed key\r\n name.toLowerCase(),\r\n name.charAt(0).toLowerCase() + name.slice(1),\r\n name.charAt(0).toUpperCase() + name.slice(1)\r\n ];\r\n\r\n for (const key of keyVariations) {\r\n if (currentValue[key] !== undefined) {\r\n val = currentValue[key];\r\n break;\r\n }\r\n }\r\n\r\n if (val === undefined && currentValue['BuckarooPayments.config'] && typeof currentValue['BuckarooPayments.config'] === 'object') {\r\n for (const key of keyVariations) {\r\n if (currentValue['BuckarooPayments.config'][key] !== undefined) {\r\n val = currentValue['BuckarooPayments.config'][key];\r\n break;\r\n }\r\n }\r\n }\r\n\r\n if (val && typeof val === 'object' && val.hasOwnProperty('_value')) {\r\n val = val._value;\r\n }\r\n return val;\r\n },\r\n\r\n canShow(element) {\r\n if (!element || !element.name) {\r\n return false;\r\n }\r\n \r\n const name = element.name.replace('BuckarooPayments.config.', '');\r\n\r\n const advancedToggleFields = [\r\n 'orderStatus',\r\n 'paymentSuccesStatus',\r\n 'automaticallyCloseOpenOrders',\r\n 'sendInvoiceEmail'\r\n ];\r\n if (advancedToggleFields.includes(name)) {\r\n const advancedConfig = this.getValueForName('advancedConfiguration');\r\n return Boolean(advancedConfig);\r\n }\r\n\r\n if (name === 'idealprocessingRenderMode') {\r\n return Boolean(this.getValueForName('idealprocessingShowissuers'));\r\n }\r\n\r\n if (name === 'idealRenderMode') {\r\n return Boolean(this.getValueForName('idealShowissuers'));\r\n }\r\n\r\n const idealFastCheckoutFields = [\r\n 'idealFastCheckoutEnabled',\r\n 'idealFastCheckoutVisibility',\r\n 'idealFastCheckoutLogoScheme'\r\n ];\r\n if (idealFastCheckoutFields.includes(name)) {\r\n return Boolean(this.getValueForName('idealFastCheckout'));\r\n }\r\n\r\n if (name === 'afterpayPaymentstatus') {\r\n return Boolean(this.getValueForName('afterpayCaptureonshippent'));\r\n }\r\n\r\n if (name === 'afterpayOldtax') {\r\n return Boolean(this.getValueForName('afterpayEnabledold'));\r\n }\r\n\r\n return true;\r\n },\r\n\r\n onInput(value) {\r\n this.$emit('input', value);\r\n },\r\n onFieldInput(fieldName, eventOrValue) {\r\n\r\n try {\r\n let actualValue = eventOrValue;\r\n \r\n if (eventOrValue && typeof eventOrValue === 'object') {\r\n if (eventOrValue.target) {\r\n const target = eventOrValue.target;\r\n\r\n if (target.type === 'checkbox' || target.type === 'radio') {\r\n actualValue = target.checked;\r\n } else if (target.tagName === 'SELECT' || target.type === 'select-one' || target.type === 'select-multiple') {\r\n if (target.multiple) {\r\n actualValue = Array.from(target.selectedOptions).map(option => option.value);\r\n } else {\r\n actualValue = target.value;\r\n }\r\n } else {\r\n actualValue = target.value;\r\n }\r\n } else if (eventOrValue.hasOwnProperty('value')) {\r\n actualValue = eventOrValue.value;\r\n } else if (eventOrValue.hasOwnProperty('id') && eventOrValue.hasOwnProperty('name')) {\r\n actualValue = eventOrValue.id;\r\n } else if (Array.isArray(eventOrValue)) {\r\n const totalCharacters = eventOrValue.filter(item => typeof item === 'string' && item.length === 1).length;\r\n const hasCommas = eventOrValue.some(item => item === ',');\r\n const hasLongStrings = eventOrValue.some(item => typeof item === 'string' && item.length > 1);\r\n\r\n const isCharacterArray = totalCharacters > 10 && hasCommas;\r\n\r\n \r\n if (isCharacterArray) {\r\n const correctValues = eventOrValue.filter(item => typeof item === 'string' && item.length > 1);\r\n const characterPart = eventOrValue.filter(item => typeof item === 'string' && item.length === 1);\r\n const rejoined = characterPart.join('');\r\n \r\n let splitValues = [];\r\n if (rejoined.includes(',')) {\r\n splitValues = rejoined.split(',').map(item => item.trim()).filter(item => item.length > 0);\r\n } else if (rejoined.length > 0) {\r\n splitValues = [rejoined];\r\n }\r\n\r\n actualValue = [...splitValues, ...correctValues].filter(item => item && item.length > 0);\r\n } else {\r\n actualValue = eventOrValue\r\n .filter(item => {\r\n if (item === null || item === undefined || item === '') {\r\n return false;\r\n }\r\n\r\n if (typeof item === 'string' && item.length === 1) {\r\n return false;\r\n }\r\n\r\n if (typeof item === 'string' && (item.startsWith('+') || /^\\d+$/.test(item))) {\r\n\r\n return false;\r\n }\r\n \r\n return true;\r\n })\r\n .map(item => {\r\n if (typeof item === 'object' && item !== null) {\r\n let extractedValue = item.id || item.value || item.code || item.key || item;\r\n return extractedValue;\r\n }\r\n return item;\r\n });\r\n }\r\n\r\n } else {\r\n const possibleKeys = ['id', 'value', 'key', 'code'];\r\n for (const key of possibleKeys) {\r\n if (eventOrValue[key] !== undefined) {\r\n actualValue = eventOrValue[key];\r\n break;\r\n }\r\n }\r\n }\r\n } else if (typeof eventOrValue === 'boolean') {\r\n actualValue = eventOrValue;\r\n } else if (typeof eventOrValue === 'string' || typeof eventOrValue === 'number') {\r\n actualValue = eventOrValue;\r\n }\r\n\r\n // Determine the element definition once so we can branch on its type\r\n const element = this.card?.elements?.find(\r\n el => el.name === fieldName\r\n || el.name.replace('BuckarooPayments.config.', '') === fieldName.replace('BuckarooPayments.config.', '')\r\n );\r\n\r\n if (actualValue === \"on\") {\r\n actualValue = true;\r\n } else if (actualValue === \"off\") {\r\n actualValue = false;\r\n }\r\n \r\n // For bool fields, ensure we always have a proper boolean\r\n if (element && element.type === 'bool') {\r\n if (typeof actualValue === 'string') {\r\n actualValue = actualValue === '1' || actualValue === 'true' || actualValue === 'on';\r\n } else {\r\n actualValue = Boolean(actualValue);\r\n }\r\n }\r\n\r\n // For multi-select fields, ALWAYS store an array of selected values.\r\n // This ensures components like sw-multi-select keep multiple selections\r\n // instead of degrading to a single selected option.\r\n if (element && element.type === 'multi-select') {\r\n console.debug('[BuckarooConfigCard] onFieldInput before normalize (multi-select)', {\r\n fieldName,\r\n rawEvent: eventOrValue,\r\n rawValue: actualValue\r\n });\r\n\r\n if (Array.isArray(actualValue)) {\r\n // Normalize array items to primitive ids / values\r\n actualValue = actualValue\r\n .filter(item => item !== null && item !== undefined && item !== '')\r\n .map(item => {\r\n if (typeof item === 'object' && item !== null) {\r\n return item.id || item.value || item.code || item.key || item;\r\n }\r\n return item;\r\n });\r\n } else if (typeof actualValue === 'string') {\r\n // Support comma-separated string values (just in case)\r\n actualValue = actualValue\r\n .split(',')\r\n .map(v => v.trim())\r\n .filter(v => v.length > 0);\r\n } else if (actualValue === null || actualValue === undefined) {\r\n actualValue = [];\r\n } else {\r\n // Fallback: wrap single primitive value into an array\r\n actualValue = [actualValue];\r\n }\r\n\r\n console.debug('[BuckarooConfigCard] onFieldInput after normalize (multi-select)', {\r\n fieldName,\r\n normalizedValue: actualValue\r\n });\r\n }\r\n \r\n const cleanFieldName = fieldName.replace('BuckarooPayments.config.', '');\r\n const updatedValue = { ...this.value };\r\n\r\n updatedValue[cleanFieldName] = actualValue;\r\n updatedValue[fieldName] = actualValue;\r\n\r\n this.$emit('input', updatedValue);\r\n \r\n } catch (error) {\r\n console.error('Error in onFieldInput:', error);\r\n console.error('Error details:', error.stack);\r\n }\r\n }\r\n }\r\n});\r\n","\r\n
\r\n \r\n
\r\n
\r\n \r\n
\r\n \"Payment\r\n
\r\n
\r\n {{ getPaymentTitle(payment.code) }}\r\n
\r\n
\r\n\r\n \r\n\r\n \r\n {{$tc('buckaroo-payment.configure-link')}}\r\n \r\n
\r\n
\r\n \r\n
\r\n","const { Component, Filter } = Shopware;\r\nimport template from \"./buckaroo-payment-list.html.twig\";\r\nimport \"./style.scss\";\r\n\r\nComponent.register(\"buckaroo-payment-list\", {\r\n template,\r\n props: {\r\n configSettings: {\r\n type: Array,\r\n required: false,\r\n default: () => []\r\n },\r\n value: {\r\n type: Object,\r\n required: false,\r\n default: () => ({})\r\n },\r\n currentSalesChannelId: {\r\n type: String,\r\n required: true\r\n }\r\n },\r\n\r\n emits: ['input'],\r\n\r\n data() {\r\n return {\r\n payments: [\r\n {\r\n code: \"Alipay\",\r\n logo: \"alipay.svg\"\r\n },\r\n {\r\n code: \"applepay\",\r\n logo: \"applepay.svg\"\r\n },\r\n {\r\n code: \"googlepay\",\r\n logo: \"googlepay.svg\"\r\n },\r\n {\r\n code: \"bancontactmrcash\",\r\n logo: \"bancontact.svg\"\r\n },\r\n {\r\n code: \"blik\",\r\n logo: \"blik.svg\"\r\n },\r\n {\r\n code: \"belfius\",\r\n logo: \"belfius.svg\"\r\n },\r\n {\r\n code: \"Billink\",\r\n logo: \"billink.svg\"\r\n },\r\n {\r\n code: \"creditcard\",\r\n logo: \"creditcards.svg\"\r\n },\r\n {\r\n code: \"creditcards\",\r\n logo: \"creditcards.svg\"\r\n },\r\n {\r\n code: \"eps\",\r\n logo: \"eps.svg\"\r\n },\r\n {\r\n code: \"giftcards\",\r\n logo: \"giftcards.svg\"\r\n },\r\n {\r\n code: \"idealqr\",\r\n logo: \"ideal-qr.svg\"\r\n },\r\n {\r\n code: \"ideal\",\r\n logo: \"ideal-wero.svg\"\r\n },\r\n {\r\n code: \"capayable\",\r\n logo: \"in3.svg\"\r\n },\r\n {\r\n code: \"KBCPaymentButton\",\r\n logo: \"kbc.svg\"\r\n },\r\n {\r\n code: \"klarna\",\r\n logo: \"klarna.svg\"\r\n },\r\n {\r\n code: \"klarnakp\",\r\n logo: \"klarna.svg\"\r\n },\r\n {\r\n code: \"knaken\",\r\n logo: \"gosettle.svg\"\r\n },\r\n {\r\n code: \"mbway\",\r\n logo: \"mbway.svg\"\r\n },\r\n {\r\n code: \"multibanco\",\r\n logo: \"multibanco.svg\"\r\n },\r\n {\r\n code: \"paybybank\",\r\n logo: \"paybybank.svg\"\r\n },\r\n {\r\n code: \"payconiq\",\r\n logo: \"payconiq.svg\"\r\n },\r\n {\r\n code: \"paypal\",\r\n logo: \"paypal.svg\"\r\n },\r\n {\r\n code: \"payperemail\",\r\n logo: \"payperemail.svg\"\r\n },\r\n {\r\n code: \"Przelewy24\",\r\n logo: \"przelewy24.svg\"\r\n },\r\n {\r\n code: \"afterpay\",\r\n logo: \"afterpay.svg\"\r\n },\r\n {\r\n code: \"sepadirectdebit\",\r\n logo: \"sepa-directdebit.svg\"\r\n },\r\n {\r\n code: \"transfer\",\r\n logo: \"sepa-credittransfer.svg\"\r\n },\r\n {\r\n code: \"Trustly\",\r\n logo: \"trustly.svg\"\r\n },\r\n {\r\n code: \"WeChatPay\",\r\n logo: \"wechatpay.svg\"\r\n },\r\n {\r\n code: \"swish\",\r\n logo: \"swish.svg\"\r\n },\r\n {\r\n code: \"bizum\",\r\n logo: \"bizum.svg\"\r\n },\r\n {\r\n code: \"twint\",\r\n logo: \"twint.svg\"\r\n },\r\n {\r\n code: \"wero\",\r\n logo: \"wero.svg\"\r\n }\r\n ]\r\n };\r\n },\r\n methods: {\r\n getPaymentTitle(code) {\r\n if (this.configSettings && Array.isArray(this.configSettings)) {\r\n const card = this.configSettings.find((card) => card.name === code);\r\n if (card && card.title) {\r\n try {\r\n if (typeof card.title === 'object' && card.title !== null) {\r\n const locale = this.$i18n?.locale || 'en-GB';\r\n\r\n if (card.title[locale]) {\r\n return card.title[locale];\r\n }\r\n if (card.title['en-GB']) {\r\n return card.title['en-GB'];\r\n }\r\n \r\n const firstKey = Object.keys(card.title)[0];\r\n if (firstKey && card.title[firstKey]) {\r\n return card.title[firstKey];\r\n }\r\n \r\n return JSON.stringify(card.title);\r\n }\r\n \r\n if (typeof card.title === 'string') {\r\n if (this.$t && typeof this.$t === 'function') {\r\n return this.$t(card.title);\r\n }\r\n return card.title;\r\n }\r\n \r\n return String(card.title);\r\n \r\n } catch (error) {\r\n console.warn('Translation error for:', card.title, error);\r\n return typeof card.title === 'object' ? JSON.stringify(card.title) : String(card.title);\r\n }\r\n }\r\n }\r\n\r\n const payment = this.payments.find(payment => payment.code === code);\r\n return payment ? payment.code : 'Unknown Payment';\r\n },\r\n assetFilter(path) {\r\n return Filter.getByName('asset')(path);\r\n }\r\n }\r\n});"," {{ $tc('buckaroo-payment.button.labelTestApi') }}","const { Component } = Shopware;\r\nimport template from \"./buckaroo-test-credentials.twig\";\r\n\r\nComponent.register(\"buckaroo-test-credentials\", {\r\n template,\r\n mixins: [\r\n Shopware.Mixin.getByName('notification')\r\n ],\r\n data() {\r\n return {\r\n isLoading: false,\r\n }\r\n },\r\n inject: [ 'BuckarooPaymentSettingsService' ],\r\n\r\n props: {\r\n config: {\r\n type: Object,\r\n required: true\r\n },\r\n currentSalesChannelId: {\r\n required: true\r\n }\r\n },\r\n computed: {\r\n enabled: function() {\r\n return (this.getConfigValue('websiteKey') || '').length > 0 &&\r\n (this.getConfigValue('secretKey') || '').length > 0\r\n }\r\n },\r\n methods: {\r\n getConfigValue: function(name) {\r\n return this.config[\"BuckarooPayments.config.\"+name];\r\n },\r\n sendTestApi() {\r\n this.isLoading = true;\r\n let websiteKeyId = this.getConfigValue('websiteKey'),\r\n secretKeyId = this.getConfigValue('secretKey');\r\n this.BuckarooPaymentSettingsService.getApiTest(websiteKeyId, secretKeyId, this.currentSalesChannelId)\r\n .then((result) => {\r\n this.isLoading = false;\r\n\r\n if (result.status == 'success') {\r\n this.createNotificationSuccess({\r\n title: this.$tc('buckaroo-payment.settingsForm.titleSuccess'),\r\n message: this.$tc(result.message)\r\n });\r\n } else {\r\n this.createNotificationError({\r\n title: this.$tc('buckaroo-payment.settingsForm.titleError'),\r\n message: this.$tc(result.message)\r\n });\r\n }\r\n\r\n })\r\n .catch(() => {\r\n this.isLoading = false;\r\n });\r\n },\r\n }\r\n})","
\r\n \r\n Live\r\n \r\n\r\n \r\n Test\r\n \r\n\r\n \r\n Off\r\n \r\n
\r\n","const { Component } = Shopware;\r\nimport template from \"./buckaroo-toggle-status.html.twig\";\r\nimport './style.scss'\r\n\r\nComponent.register(\"buckaroo-toggle-status\", {\r\n template,\r\n props: {\r\n method: {\r\n type: String,\r\n required: true\r\n },\r\n value: {\r\n required: true\r\n },\r\n currentSalesChannelId: {\r\n required: true,\r\n }\r\n },\r\n\r\n emits: ['input'],\r\n\r\n inject: ['systemConfigApiService'],\r\n data() {\r\n return {\r\n status: 'disabled',\r\n isLoading: false,\r\n }\r\n },\r\n\r\n mounted() {\r\n this.status = this.getStatus();\r\n },\r\n\r\n watch: {\r\n value: {\r\n handler(newVal) {\r\n this.status = this.getStatus();\r\n },\r\n deep: true,\r\n immediate: true\r\n }\r\n },\r\n methods: {\r\n getStatus() {\r\n const isActive = this.isActive();\r\n const environment = this.getEnvironment();\r\n return isActive ? environment : 'disabled';\r\n },\r\n isActive() {\r\n const enabled = this.getValueForName(`${this.method}Enabled`);\r\n if (typeof enabled === 'string') {\r\n return enabled.toLowerCase() === 'true';\r\n }\r\n return Boolean(enabled);\r\n },\r\n getEnvironment() {\r\n const env = this.getValueForName(`${this.method}Environment`);\r\n \r\n if (env === undefined || env === null || env === '') {\r\n return 'test';\r\n }\r\n const validEnvs = ['test', 'live'];\r\n return validEnvs.includes(env) ? env : 'test';\r\n },\r\n getValueForName(name) {\r\n const key = `BuckarooPayments.config.${name}`;\r\n if (!this.value || typeof this.value !== 'object') {\r\n return null;\r\n }\r\n\r\n let val = undefined;\r\n\r\n if (this.value[key] !== undefined) {\r\n val = this.value[key];\r\n }\r\n else if (this.value[name] !== undefined) {\r\n val = this.value[name];\r\n }\r\n else if (this.value['BuckarooPayments.config'] && typeof this.value['BuckarooPayments.config'] === 'object') {\r\n if (this.value['BuckarooPayments.config'][name] !== undefined) {\r\n val = this.value['BuckarooPayments.config'][name];\r\n }\r\n }\r\n else {\r\n const variations = [\r\n name,\r\n name.toLowerCase(),\r\n name.charAt(0).toLowerCase() + name.slice(1),\r\n name.charAt(0).toUpperCase() + name.slice(1)\r\n ];\r\n \r\n for (const variation of variations) {\r\n const variationKey = `BuckarooPayments.config.${variation}`;\r\n if (this.value[variationKey] !== undefined) {\r\n val = this.value[variationKey];\r\n break;\r\n }\r\n if (this.value[variation] !== undefined) {\r\n val = this.value[variation];\r\n break;\r\n }\r\n }\r\n }\r\n\r\n if (val && typeof val === 'object' && val.hasOwnProperty('_value')) {\r\n val = val._value;\r\n }\r\n \r\n return val;\r\n },\r\n setStatus(status) {\r\n this.status = status;\r\n this.saveStatus();\r\n },\r\n getClass(buttonStatus) {\r\n return this.status === buttonStatus ? 'active' : '';\r\n },\r\n async saveStatus() {\r\n const enabledKey = `BuckarooPayments.config.${this.method}Enabled`;\r\n const environmentKey = `BuckarooPayments.config.${this.method}Environment`;\r\n\r\n let data = {[enabledKey]: false};\r\n const updatedValue = { ...this.value };\r\n updatedValue[enabledKey] = false;\r\n\r\n if (['live', 'test'].indexOf(this.status) !== -1) {\r\n data = {\r\n [enabledKey]: true,\r\n [environmentKey]: this.status\r\n }\r\n updatedValue[enabledKey] = true;\r\n updatedValue[environmentKey] = this.status;\r\n }\r\n\r\n this.$emit('input', updatedValue);\r\n\r\n this.isLoading = true;\r\n try {\r\n await this.systemConfigApiService\r\n .batchSave({[this.currentSalesChannelId]: data})\r\n .finally(() => {\r\n this.isLoading = false;\r\n });\r\n this.renderSuccess();\r\n } catch (error) {\r\n this.renderError(error);\r\n }\r\n \r\n },\r\n renderSuccess() {\r\n this.$store.dispatch('notification/createNotification', {\r\n variant: 'success',\r\n message: this.$tc('sw-extension-store.component.sw-extension-config.messageSaveSuccess'),\r\n });\r\n },\r\n\r\n renderError(err) {\r\n this.$store.dispatch('notification/createNotification', {\r\n variant: 'error',\r\n message: err,\r\n });\r\n }\r\n }\r\n})"],"names":["template$a","Component","Context","Criteria","template","orderRepository","orderCriteria","order","paymentMethodId","paymentMethod","template$9","template$8","values","template$7","newVal","oldVal","response","processedData","key","value","shortKey","error","newValue","fullFieldName","_a","_b","code","card","currentConfigValues","currentPaymentCard","actualConfigValues","element","cleanFieldName","template$6","Filter","that","orderId","buckarooKey","errorResponse","_c","transaction","amount","field","action","Module","nlNL","deDE","enGB","next","currentRoute","route","ApiService","BuckarooPaymentService","httpClient","loginService","apiEndpoint","apiRoute","transactionsToRefund","orderItems","customRefundAmount","initContainer","BuckarooPaymentSettingsService","websiteKeyId","secretKeyId","currentSalesChannelId","template$5","result","tax","taxId","eventOrValue","actualValue","template$4","to","template$3","newChannelId","oldChannelId","secretKey","hasWebsiteKey","hasSecretKey","service","data","parts","n","major","minor","patch","build","props","_d","_e","_f","_g","label","baseBinding","fieldName","currentValue","config","finalLabel","useEnhancedLabels","configCard","configElement","el","extractedLabel","locale","rawElement","finalConfig","binding","sampleOption","name","string","title","firstKey","val","keyVariations","target","option","totalCharacters","item","hasCommas","hasLongStrings","correctValues","rejoined","splitValues","possibleKeys","v","updatedValue","template$2","payment","path","template$1","isActive","environment","enabled","env","variations","variation","variationKey","status","buttonStatus","enabledKey","environmentKey","err"],"mappings":"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"} \ No newline at end of file diff --git a/src/Resources/public/administration/assets/buckaroo-payments-BbqpZqUI.js b/src/Resources/public/administration/assets/buckaroo-payments-CjP84r_i.js similarity index 90% rename from src/Resources/public/administration/assets/buckaroo-payments-BbqpZqUI.js rename to src/Resources/public/administration/assets/buckaroo-payments-CjP84r_i.js index 389dcb75..9a88b8b4 100644 --- a/src/Resources/public/administration/assets/buckaroo-payments-BbqpZqUI.js +++ b/src/Resources/public/administration/assets/buckaroo-payments-CjP84r_i.js @@ -1,2 +1,2 @@ -const T=`{% block sw_order_detail_content_tabs %}

{{ $tc('buckaroo-payment.paymentInTestMode') }}

{% parent %} {% endblock %} {% block sw_order_detail_content_tabs_general %} {% parent %} {{ $tc('buckaroo-payment.tabs.title') }} {% endblock %} {% block sw_order_detail_actions %} {% parent %} {% endblock %}`,{Component:$,Context:S}=Shopware,P=Shopware.Data.Criteria;$.override("sw-order-detail",{template:T,data(){return{isBuckarooPayment:!1,isPaymentInTestMode:!1}},computed:{isEditable(){return!this.isBuckarooPayment||this.$route.name!=="buckaroo.payment.detail"},showTabs(){return!0}},watch:{orderId:{deep:!0,handler(){if(!this.orderId){this.setIsBuckarooPayment(null);return}const e=this.repositoryFactory.create("order"),t=new P(1,1);t.addAssociation("transactions"),e.get(this.orderId,S.api,t).then(a=>{if(this.setPaymentInTestMode(a),a.transactions.length<=0||!a.transactions.last().paymentMethodId){this.setIsBuckarooPayment(null);return}const o=a.transactions.last().paymentMethodId;o!=null&&this.setIsBuckarooPayment(o)})},immediate:!0}},methods:{setPaymentInTestMode(e){e.customFields&&e.customFields.buckaroo_payment_in_test_mode&&(this.isPaymentInTestMode=e.customFields.buckaroo_payment_in_test_mode===!0)},setIsBuckarooPayment(e){if(!e)return;this.repositoryFactory.create("payment_method").get(e,S.api).then(a=>{this.isBuckarooPayment=a.formattedHandlerIdentifier.indexOf("buckaroo")>=0})}}});const I=`{% block sw_order_detail_base_line_items_summary %}
{{ $tc('buckaroo-payment.fee') }}
{{ order.customFields.buckarooFee }} {% if order.currency.isoCode == "PLN" %} PLN {% else %} {{ order.currency.symbol }} {% endif %}
{% parent %} {% endblock %}`,{Component:x,Context:oe}=Shopware;Shopware.Data.Criteria;x.override("sw-order-detail-base",{template:I});const A=`{% block sw_order_detail_base_secondary_info_payment %} {% endblock %}`,{Component:M}=Shopware;M.override("sw-order-user-card",{template:A,inject:["systemConfigApiService"],data(){return{config:{}}},created(){this.systemConfigApiService.getValues("BuckarooPayments.config",null).then(e=>{this.config=e}).finally(()=>{})}});const R=`{% block sw_system_config_content_card %} {% endblock %}`,{Component:F}=Shopware;F.override("sw-system-config",{template:R,watch:{currentSalesChannelId:{handler(e,t){e&&this.domain==="BuckarooPayments.config"&&this.loadBuckarooConfigData()},immediate:!0},domain:{handler(e){e==="BuckarooPayments.config"&&this.currentSalesChannelId&&this.loadBuckarooConfigData()},immediate:!0}},methods:{loadBuckarooConfigData(){this.systemConfigApiService.getValues("BuckarooPayments.config",this.currentSalesChannelId).then(e=>{this.actualConfigData[this.currentSalesChannelId]||(this.actualConfigData[this.currentSalesChannelId]={});const t={};e&&typeof e=="object"&&Object.keys(e).forEach(a=>{const o=e[a];o&&typeof o=="object"&&o.hasOwnProperty("_value")?t[a]=o._value:t[a]=o;const n=a.replace("BuckarooPayments.config.","");n!==a&&(t[n]=t[a])}),this.actualConfigData[this.currentSalesChannelId]={},Object.keys(t).forEach(a=>{this.actualConfigData[this.currentSalesChannelId][a]=t[a]}),this.$nextTick(()=>{this.$forceUpdate()})}).catch(e=>{console.error("Error fetching system config:",e)})},onConfigDataUpdate(e){this.actualConfigData[this.currentSalesChannelId]||(this.actualConfigData[this.currentSalesChannelId]={}),Object.keys(e).forEach(t=>{if(this.actualConfigData[this.currentSalesChannelId][t]=e[t],!t.startsWith("BuckarooPayments.config.")){const a=`BuckarooPayments.config.${t}`;this.actualConfigData[this.currentSalesChannelId][a]=e[t]}})},saveAll(){return this.domain!=="BuckarooPayments.config"?this.$super("saveAll"):this.saveBuckaroo()},saveBuckaroo(){return this.isLoading=!0,this.systemConfigApiService.batchSave(this.getSelectedValues()).finally(()=>{this.isLoading=!1})},getCurrentConfigCard(){var t,a;const e=((t=this.$route.params)==null?void 0:t.paymentCode)||"general";return(a=this.config.filter(o=>o.name===e))==null?void 0:a.pop()},getSelectedValues(){const e=this.actualConfigData[this.currentSalesChannelId],t=this.getCurrentConfigCard();if(t!=null&&t.elements){let a={};return t==null||t.elements.forEach(o=>{if(o!=null&&o.name){let n=e[o.name];if(n===void 0){const i=o.name.replace("BuckarooPayments.config.","");n=e[i]}a[o.name]=n}}),{[this.currentSalesChannelId]:a}}return this.actualConfigData}}});const E=`{% block buckaroo_payment_detail %}
{{ $tc('buckaroo-payment.paymentDetail.paylinkDescription') }}
{{ $tc('buckaroo-payment.paymentDetail.yourLink') }}: {{ paylink }}
{{ $tc('buckaroo-payment.paymentDetail.paylinkButton') }}
{{ $tc('buckaroo-payment.orderItems.title') }}
{{ $tc('buckaroo-payment.paymentDetail.amountTotalTitle') }}:
{{ buckaroo_refund_amount }} {{ currency }}
{{ $tc('buckaroo-payment.paymentDetail.amountCustomRefundTitle') }}:
{{ currency }}
{{ $tc('buckaroo-payment.paymentDetail.amountRefundTotalTitle') }}:
{{ buckaroo_refund_total_amount }} {{ currency }}
{{ $tc('buckaroo-payment.paymentDetail.buttonTitle') }}
{{ $tc('buckaroo-payment.paymentDetail.payDescription') }}
{{ $tc('buckaroo-payment.paymentDetail.payButton') }}
{{ $tc('buckaroo-payment.paymentDetail.klarnaMorDescription') }}
{{ $tc('buckaroo-payment.paymentDetail.klarnaMorCancel') }}
{{ $tc('buckaroo-payment.paymentDetail.klarnaMorCancelButton') }}
{{ $tc('buckaroo-payment.paymentDetail.klarnaMorUpdate') }}
{{ $tc('buckaroo-payment.paymentDetail.klarnaMorUpdateButton') }}
{{ $tc('buckaroo-payment.paymentDetail.klarnaMorExtend') }}
{{ $tc('buckaroo-payment.paymentDetail.klarnaMorExtendButton') }}
{{ $tc('buckaroo-payment.paymentDetail.klarnaMorShipping') }}
{{ $tc('buckaroo-payment.paymentDetail.klarnaMorShippingButton') }}
{% endblock %}`,{Component:D,Filter:ie,Context:V}=Shopware,_=Shopware.Data.Criteria;D.register("buckaroo-payment-detail",{template:E,inject:["repositoryFactory","BuckarooPaymentService","systemConfigApiService"],data(){return{config:{},buckaroo_refund_amount:"0",buckaroo_refund_total_amount:"0",currency:"EUR",isRefundPossible:!0,isCapturePossible:!1,isPaylinkAvailable:!1,isPaylinkVisible:!1,paylinkMessage:"",paylink:"",isLoading:!1,order:!1,buckarooTransactions:null,orderItems:[],transactionsToRefund:[],relatedResources:[],isAuthorized:!1,isKlarnaMor:!1,fulfillmentMessage:"",fulfillmentStatus:null}},computed:{orderItemsColumns(){return[{property:"name",label:this.$tc("buckaroo-payment.orderItems.types.name"),allowResize:!1,primary:!0,inlineEdit:!0,multiLine:!0},{property:"quantity",label:this.$tc("buckaroo-payment.orderItems.types.quantity"),rawData:!0,align:"right"},{property:"totalAmount",label:this.$tc("buckaroo-payment.orderItems.types.totalAmount"),rawData:!0,align:"right"}]},transactionsToRefundColumns(){return[{property:"transaction_method",rawData:!0},{property:"amount",rawData:!0}]},relatedResourceColumns(){return[{property:"created_at",label:this.$tc("buckaroo-payment.transactionHistory.types.created_at"),rawData:!0},{property:"total",label:this.$tc("buckaroo-payment.transactionHistory.types.total"),rawData:!0},{property:"shipping_costs",label:this.$tc("buckaroo-payment.transactionHistory.types.shipping_costs"),rawData:!0},{property:"total_excluding_vat",label:this.$tc("buckaroo-payment.transactionHistory.types.total_excluding_vat"),rawData:!0},{property:"vat",label:this.$tc("buckaroo-payment.transactionHistory.types.vat"),rawData:!0},{property:"transaction_key",label:this.$tc("buckaroo-payment.transactionHistory.types.transaction_key"),rawData:!0},{property:"transaction_method",label:this.$tc("buckaroo-payment.transactionHistory.types.transaction_method"),rawData:!0},{property:"statuscode",label:this.$tc("buckaroo-payment.transactionHistory.types.statuscode"),rawData:!0}]}},created(){this.createdComponent()},methods:{recalculateOrderItems(){this.buckaroo_refund_amount=0;for(const e in this.orderItems)this.orderItems[e].totalAmount=parseFloat(parseFloat(this.orderItems[e].unitPrice)*parseFloat(this.orderItems[e].quantity||0)).toFixed(2),this.buckaroo_refund_amount=parseFloat(parseFloat(this.buckaroo_refund_amount)+parseFloat(this.orderItems[e].totalAmount)).toFixed(2)},recalculateRefundItems(){this.buckaroo_refund_total_amount=0;for(const e in this.transactionsToRefund)this.transactionsToRefund[e].amount&&(this.buckaroo_refund_total_amount=parseFloat(parseFloat(this.buckaroo_refund_total_amount)+parseFloat(this.transactionsToRefund[e].amount)).toFixed(2))},getCustomRefundEnabledEl(){return document.getElementById("buckaroo_custom_refund_enabled")},getCustomRefundAmountEl(){return document.getElementById("buckaroo_custom_refund_amount")},toggleCustomRefund(){this.getCustomRefundEnabledEl()&&this.getCustomRefundAmountEl()&&(this.getCustomRefundAmountEl().disabled=!this.getCustomRefundEnabledEl().checked)},getCustomRefundAmount(){return this.getCustomRefundEnabledEl()&&this.getCustomRefundAmountEl()&&this.getCustomRefundEnabledEl().checked?this.getCustomRefundAmountEl().value:0},createdComponent(){let e=this;const t=this.$route.params.id;this.systemConfigApiService.getValues("BuckarooPayments.config",null).then(n=>{this.config=n});const a=this.repositoryFactory.create("order"),o=new _(1,1);this.orderId=t,o.addAssociation("transactions.paymentMethod").addAssociation("transactions"),o.getAssociation("transactions").addSorting(_.sort("createdAt")),a.get(t,V.api,o).then(n=>{e.checkedIsAuthorized(n);const i=n.transactions&&n.transactions.last().paymentMethod&&n.transactions.last().paymentMethod.customFields&&n.transactions.last().paymentMethod.customFields.buckaroo_key?n.transactions.last().paymentMethod.customFields.buckaroo_key.toLowerCase():"";e.isCapturePossible=!!i&&(["klarnakp","billink","afterpay","klarna","wero"].includes(i)||e.isAfterpayCapturePossible(n)),e.isKlarnaMor=i==="klarna",e.isPaylinkVisible=e.isPaylinkAvailable=this.getConfigValue("paylinkEnabled")&&n.stateMachineState&&n.stateMachineState.technicalName&&n.stateMachineState.technicalName=="open"&&n.transactions&&n.transactions.last().stateMachineState.technicalName=="open"}),this.BuckarooPaymentService.getBuckarooTransaction(t).then(n=>{e.orderItems=[],e.transactionsToRefund=[],e.relatedResources=[],this.$emit("loading-change",!1),n.orderItems&&Array.isArray(n.orderItems)&&n.orderItems.forEach(i=>{e.orderItems.push({id:i.id,name:i.name,quantity:i.quantity,quantityMax:i.quantity,unitPrice:i.unitPrice.value,totalAmount:i.totalAmount.value,variations:i.variations||[]})}),e.buckaroo_refund_amount=n.refundTotals?n.refundTotals.totalAmount:0,e.currency=n.refundTotals?n.refundTotals.currency:"EUR",n.transactionsToRefund&&Array.isArray(n.transactionsToRefund)&&n.transactionsToRefund.forEach(i=>{e.transactionsToRefund.push({id:i.id,transactions:i.transactions,amount:i.total,amountMax:i.total,currency:i.currency,transaction_method:i.transaction_method,logo:i.transaction_method?i.logo:null}),e.currency=i.currency}),e.recalculateRefundItems(),n.transactions&&Array.isArray(n.transactions)&&n.transactions.forEach(i=>{e.relatedResources.push({id:i.id,transaction_key:i.transaction,total:i.total,total_excluding_vat:i.total_excluding_vat,shipping_costs:i.shipping_costs,vat:i.vat,transaction_method:i.transaction_method,logo:i.transaction_method?i.logo:null,created_at:i.created_at,statuscode:i.statuscode})})}).catch(n=>{console.log("errorResponse",n)})},isAfterpayCapturePossible(e){return e.customFields.buckaroo_is_authorize===!0},checkedIsAuthorized(e){var t,a,o;this.isAuthorized=((o=(a=(t=e==null?void 0:e.transactions)==null?void 0:t.last())==null?void 0:a.stateMachineState)==null?void 0:o.technicalName)==="authorized"},refundOrder(e,t){let a=this;a.isRefundPossible=!1,this.BuckarooPaymentService.refundPayment(e,this.transactionsToRefund,this.orderItems,this.getCustomRefundAmount()).then(o=>{for(const n in o)o[n].status?this.$store.dispatch("notification/createNotification",{variant:"success",title:a.$tc("buckaroo-payment.settingsForm.titleSuccess"),message:a.$tc(o[n].message)+o[n].amount}):this.$store.dispatch("notification/createNotification",{variant:"error",title:a.$tc("buckaroo-payment.settingsForm.titleError"),message:a.$tc(o[n].message)});a.isRefundPossible=!0,this.createdComponent()}).catch(o=>{this.$store.dispatch("notification/createNotification",{variant:"error",title:this.$tc("buckaroo-payment.settingsForm.titleError"),message:o.response.data.message}),a.isRefundPossible=!0})},createPaylink(e){let t=this;t.isPaylinkAvailable=!1,this.BuckarooPaymentService.createPaylink(e,this.transactionsToRefund,this.orderItems).then(a=>{a.status?(t.paylinkMessage=t.$tc(a.message)+a.paylinkhref,t.paylink=a.paylink,this.$store.dispatch("notification/createNotification",{variant:"success",title:t.$tc("buckaroo-payment.settingsForm.titleSuccess"),message:t.paylinkMessage})):this.$store.dispatch("notification/createNotification",{variant:"error",title:t.$tc("buckaroo-payment.settingsForm.titleError"),message:t.$tc(a.message)}),t.isPaylinkAvailable=!0}).catch(a=>{this.$store.dispatch("notification/createNotification",{variant:"error",title:this.$tc("buckaroo-payment.settingsForm.titleError"),message:a.response.data.message}),t.isPaylinkAvailable=!0})},getConfigValue(e){return this.config[`BuckarooPayments.config.${e}`]},captureOrder(e){let t=this;t.isCapturePossible=!1,this.BuckarooPaymentService.captureOrder(e,this.transactionsToRefund,this.orderItems).then(a=>{a.status?this.$store.dispatch("notification/createNotification",{variant:"success",title:t.$tc("buckaroo-payment.settingsForm.titleSuccess"),message:a.message}):this.$store.dispatch("notification/createNotification",{variant:"error",title:t.$tc("buckaroo-payment.settingsForm.titleError"),message:a.message}),t.isCapturePossible=!0,this.createdComponent()}).catch(a=>{this.$store.dispatch("notification/createNotification",{variant:"error",title:this.$tc("buckaroo-payment.settingsForm.titleError"),message:t.$tc(a.response.data.message)}),t.isCapturePossible=!0})},klarnaMor(e){let t=this;t.isLoading=!0,this.BuckarooPaymentService.klarnaMor(this.orderId,e).then(a=>{a.status?this.$store.dispatch("notification/createNotification",{variant:"success",title:t.$tc("buckaroo-payment.settingsForm.titleSuccess"),message:a.message}):this.$store.dispatch("notification/createNotification",{variant:"error",title:t.$tc("buckaroo-payment.settingsForm.titleError"),message:a.message}),t.isLoading=!1,this.createdComponent()}).catch(a=>{this.$store.dispatch("notification/createNotification",{variant:"error",title:this.$tc("buckaroo-payment.settingsForm.titleError"),message:a.response&&a.response.data?a.response.data.message:"An error occurred"}),t.isLoading=!1})}}});const{Component:N}=Shopware;N.extend("buckaroo-payment-config","sw-extension-config",{});const L={"buckaroo-payment":{fee:"Buckaroo Betaaltoeslag",order:{refundDescription:"Refund voor bestelling #orderNumber"},general:{title:"Buckaroo",description:"Buckaroo Payment"},settingsForm:{save:"Opslaan",titleSuccess:"Succes",titleError:"Foutmelding"},supportModal:{menuButton:"Version & Support",title:"Versie & Support",support:{description:"Zorg ervoor dat u uw website key bij de hand heeft voordat u contact opneemt met Buckaroo technical support",label1:"Buckaroo Plaza:",label2:"Telefoonnummer:",label3:"E-mail:",label4:"Website:",your_version:"Uw PHP versie:",version:"Versie compatibiliteit",information:"Informatie"}},tabs:{title:"Buckaroo Payment",overview:"Overzicht"},paymentDetail:{yourLink:"Uw Paylink",paylinkButton:"Creëer Paylink",paylinkDescription:"Creëer Paylink voor order",paylinkTitle:"Paylink",refundTitle:"Terugbetaling",transactionsTitle:"Transacties",amountTitle:"Hoeveelheid",amountTotalTitle:"Algemeen totaal (grand total)",amountRefundTotalTitle:"Terugbetaling Algemeen totaal (grand total)",amountCustomRefundTitle:"Aangepast bedrag terugbetalen",buttonTitle:"Terugbetaling",successTitle:"Success",successMessage:"Buckaroo terugbetaling succesvol",errorTitle:"Foutmelding",payTitle:"Betaling vastleggen (Capture)",payDescription:"Factuur voor bestelling vastleggen (Capture) en aanmaken",payButton:"Betaling vastleggen (Capture)",klarnaMorTitle:"Klarna (MoR)",klarnaMorDescription:"Beheer de Klarna reservering voor deze bestelling.",klarnaMorCancel:"Reservering annuleren",klarnaMorCancelButton:"Reservering annuleren",klarnaMorUpdate:"Reservering bijwerken",klarnaMorUpdateButton:"Reservering bijwerken",klarnaMorExtend:"Reservering verlengen",klarnaMorExtendButton:"Reservering verlengen",klarnaMorShipping:"Verzendinfo toevoegen",klarnaMorShippingButton:"Verzendinfo toevoegen"},orderItems:{title:"Artikelen om terug te betalen",types:{id:"id",name:"Titel",quantity:"Aantal om terug te betalen",totalAmount:"Subtotaal"}},transactionsToRefund:{title:"Terugbetaling Totaal"},transactionHistory:{types:{id:"id",created_at:"Datum/tijd",total:"Totaal",shipping_costs:"Verzendkosten",total_excluding_vat:"Totaal exclusief BTW",total_including_vat:"Totaal inclusief BTW",vat:"BTW",transaction_key:"Transactie key",transaction_method:"Betaalmethode",statuscode:"Status"}},messageNotValid:"Dit veld is niet geldig.",messageNotBlank:"Dit veld mag niet leeg zijn.",button:{labelTestApi:"Test gegevens"},afterpay:{setup:"Belastingkoppeling instellen voor Riverty old ",hightTaxes:"Hoge BTW-heffingen",middleTaxes:"Middelmatige BTW-belastingen",lowTaxes:"Lage BTW-heffingen",zeroTaxes:"Nul VAT",noTaxes:"Geen BTW"},paymentInTestMode:"De betaling voor deze bestelling is in testmodus uitgevoerd",refund:{not_supported:"Terugbetaling wordt niet ondersteund",already_refunded:"Deze bestelling is al terugbetaald",refunded_amount:"Buckaroo terugbetaling succesvol"},test_api:{connection_ready:"Verbinding gereed",connection_failed:"Verbinding mislukt"},paylink:{invalid_amount:"Het bedrag is niet geldig",pay_link:"Uw Paylink:"},missing_order_id:"Ontbrekende bestelling orderId",missing_transaction:"Order transactie niet gevonden",general_request_error:"Helaas is er een fout opgetreden tijdens het verwerken van uw aanvraag. Probeer het opnieuw.",in3LogoLabel:"Betaalmethode Logo:","configure-payment":"Configure payment","configure-link":"Configure","payment-methods":"Payment methods"}},j={"buckaroo-payment":{fee:"Buckaroo Gebühr",order:{refundDescription:"Rückerstattung für Bestellung #orderNumber"},general:{title:"Buckaroo",description:"Buckaroo Zahlung"},settingsForm:{save:"Speichern",titleSuccess:"Erfolg",titleError:"Fehler"},supportModal:{menuButton:"Version & Unterstützung",title:"Version & Unterstützung",support:{description:"Bevor Sie den technischen Support von Buckaroo kontaktieren, bitte holen Sie Ihren (Händler-)Schlüssel und Geheimschlüssel ab.",label1:"Buckaroo Plaza:",label2:"Telefon:",label3:"E-Mail:",label4:"Webseite:",your_version:"Ihre PHP-Version:",version:"Versionskompatibilität",information:"Informationen"}},tabs:{title:"Buckaroo Payment",overview:"Übersicht"},paymentDetail:{yourLink:"Ihr Paylink",paylinkButton:"Paylink erstellen",paylinkDescription:"Paylink erstellen für Bestellung",paylinkTitle:"Paylink",refundTitle:"Rückerstattung",transactionsTitle:"Transaktionen",amountTitle:"Betrag",amountTotalTitle:"Gesamtsumme",amountRefundTotalTitle:"Gesamtsumme der Rückerstattung",amountCustomRefundTitle:"Rückerstattung individueller Betrag",buttonTitle:"Rückerstattung",successTitle:"Erfolg",successMessage:"Buckaroo-Erfolg, zurückerstattet",errorTitle:"Fehler",payTitle:"Zahlung erfassen (Capture)",payDescription:"Erfassen (Capture) und Rechnung für Bestellung erstellen",payButton:"Zahlung erfassen (Capture)",klarnaMorTitle:"Klarna (MoR)",klarnaMorDescription:"Verwalten Sie die Klarna-Reservierung für diese Bestellung.",klarnaMorCancel:"Reservierung stornieren",klarnaMorCancelButton:"Reservierung stornieren",klarnaMorUpdate:"Reservierung aktualisieren",klarnaMorUpdateButton:"Reservierung aktualisieren",klarnaMorExtend:"Reservierung verlängern",klarnaMorExtendButton:"Reservierung verlängern",klarnaMorShipping:"Versandinformationen hinzufügen",klarnaMorShippingButton:"Versandinformationen hinzufügen"},orderItems:{title:"Artikel zur Rückerstattung",types:{id:"id",name:"Titel",quantity:"Menge zur Rückerstattung",totalAmount:"Teilsumme"}},transactionsToRefund:{title:"Rückerstattungssummen"},transactionHistory:{types:{id:"id",created_at:"Datum/Uhrzeit",total:"Gesamt",shipping_costs:"Versandkosten",total_excluding_vat:"Gesamt ohne MwSt. (VAT)",total_including_vat:"Gesamt inklusive MwSt. (VAT)",vat:"MwSt. (VAT)",transaction_key:"Transaktionsschlüssel",transaction_method:"Zahlungsmethode",statuscode:"Status"}},messageNotValid:"Dieses Feld ist nicht gültig.",messageNotBlank:"Dieses Feld darf nicht leer sein.",button:{labelTestApi:"Verbindung testen"},afterpay:{setup:"Steuerzuordnung für Riverty old einrichten ",hightTaxes:"Hohe MwSt. (VAT)",middleTaxes:"Mittlere MwSt. (VAT)",lowTaxes:"Niedrige MwSt. (VAT)",zeroTaxes:"Keine MwSt. (VAT)",noTaxes:"Keine Mehrwertsteuer"},paymentInTestMode:"Die Zahlung für diese Bestellung wurde im Testmodus durchgeführt",refund:{not_supported:"Rückerstattung wird nicht unterstützt",already_refunded:"Diese Bestellung wurde bereits zurückerstattet",refunded_amount:"Erfolgreich von Buckaroo erstattet"},test_api:{connection_ready:"Verbindung bereit",connection_failed:"Verbindung fehlgeschlagen"},paylink:{invalid_amount:"Betrag ist nicht gültig",pay_link:"Ihr Zahlungslink (Paylink):"},missing_order_id:"Fehlende Bestell-ID",missing_transaction:"Transaktion der Bestellung nicht gefunden",general_request_error:"Leider ist ein Fehler bei der Bearbeitung Ihrer Anfrage aufgetreten. Bitte versuchen Sie es erneut.",in3LogoLabel:"Zahlungslogo:","configure-payment":"Configure payment","configure-link":"Configure","payment-methods":"Payment methods"}},z={"buckaroo-payment":{fee:"Buckaroo Fee",order:{refundDescription:"Refund for order #orderNumber"},general:{title:"Buckaroo",description:"Buckaroo Payment"},settingsForm:{save:"Save",titleSuccess:"Success",titleError:"Error"},supportModal:{menuButton:"Version & Support",title:"Version & Support",support:{description:"Before contacting Buckaroo technical support, please retrieve your (Merchant) key, Secret key, certificate and certificate thumbprint.",label1:"Buckaroo Payment Plaza:",label2:"Phone:",label3:"E-mail:",label4:"Website:",your_version:"Your PHP version:",version:"Version compatibility",information:"Information"}},tabs:{title:"Buckaroo Payment",overview:"Overview"},paymentDetail:{yourLink:"Your Paylink",paylinkButton:"Create paylink",paylinkDescription:"Create paylink for order",paylinkTitle:"Paylink",refundTitle:"Refund",transactionsTitle:"Transactions",amountTitle:"Amount",amountTotalTitle:"Grand total",amountRefundTotalTitle:"Refund Grand total",amountCustomRefundTitle:"Refund custom amount",buttonTitle:"Refund",successTitle:"Success",successMessage:"Buckaroo success refunded ",errorTitle:"Error",payTitle:"Capture payment",payDescription:"Capture and create invoice for order",payButton:"Capture payment",klarnaMorTitle:"Klarna (MoR)",klarnaMorDescription:"Manage the Klarna reservation for this order.",klarnaMorCancel:"Cancel reservation",klarnaMorCancelButton:"Cancel reservation",klarnaMorUpdate:"Update reservation",klarnaMorUpdateButton:"Update reservation",klarnaMorExtend:"Extend reservation",klarnaMorExtendButton:"Extend reservation",klarnaMorShipping:"Add shipping info",klarnaMorShippingButton:"Add shipping info"},orderItems:{title:"Items to Refund",types:{id:"id",name:"Title",quantity:"Qty to Refund",totalAmount:"Subtotal"}},transactionsToRefund:{title:"Refund Totals"},transactionHistory:{types:{id:"id",created_at:"Date/time",total:"Total",shipping_costs:"Shipping costs",total_excluding_vat:"Total excluding VAT",total_including_vat:"Total including VAT",vat:"VAT",transaction_key:"Transaction key",transaction_method:"Payment method",statuscode:"Status"}},messageNotValid:"This field not valid.",messageNotBlank:"This field must not be empty.",button:{labelTestApi:"Test connection"},afterpay:{setup:"Setup tax association for Riverty old ",hightTaxes:"High VAT taxes",middleTaxes:"Middle VAT taxes",lowTaxes:"Low VAT taxes",zeroTaxes:"Zero VAT",noTaxes:"No VAT tax"},paymentInTestMode:"The payment for this order was made in test mode",refund:{not_supported:"Refund is not supported",already_refunded:"This order is already refunded",refunded_amount:"Buckaroo success refunded"},test_api:{connection_ready:"Connection ready",connection_failed:"Connection failed"},paylink:{invalid_amount:"Amount is not valid",pay_link:"Your Paylink:"},missing_order_id:"Missing order orderId",missing_transaction:"Order transaction not found",general_request_error:"Unfortunately an error occurred while processing your request. Please try again.",in3LogoLabel:"Payment Logo:","configure-payment":"Configure payment","configure-link":"Configure","payment-methods":"Payment methods"}},{Module:q}=Shopware;q.register("buckaroo-payment",{type:"plugin",name:"BuckarooPayment",title:"buckaroo-payment.general.title",description:"buckaroo-payment.general.description",version:"1.0.0",targetVersion:"1.0.0",color:"#000000",icon:"default-action-settings",snippets:{"nl-NL":L,"de-DE":j,"en-GB":z},routeMiddleware(e,t){t.name==="sw.order.detail"&&t.children.push({component:"buckaroo-payment-detail",name:"buckaroo.payment.detail",isChildren:!0,path:"/sw/order/buckaroo/detail/:id"}),e(t)},routes:{config:{component:"buckaroo-payment-config",path:":namespace/payment/:paymentCode",name:"buckaroo.config.payment",meta:{parentPath:"sw.extension.config"},props:{default(e){return{namespace:e.params.namespace}}}}}});const{ApiService:y}=Shopware.Classes;class H extends y{constructor(t,a,o="buckaroo"){super(t,a,o)}getBasicHeaders(){return this.loginService&&typeof this.loginService.getToken=="function"?super.getBasicHeaders():{"Content-Type":"application/json",Accept:"application/json"}}getBuckarooTransaction(t){const a=`_action/${this.getApiBasePath()}/getBuckarooTransaction`;return this.httpClient.post(a,{transaction:t},{headers:this.getBasicHeaders()}).then(o=>y.handleResponse(o))}refundPayment(t,a,o,n){const i=`_action/${this.getApiBasePath()}/refund`;return this.httpClient.post(i,{transaction:t,transactionsToRefund:a,orderItems:o,customRefundAmount:n},{headers:this.getBasicHeaders()}).then(d=>y.handleResponse(d))}captureOrder(t){const a=`_action/${this.getApiBasePath()}/capture`;return this.httpClient.post(a,{transaction:t},{headers:this.getBasicHeaders()}).then(o=>y.handleResponse(o))}createPaylink(t){const a=`_action/${this.getApiBasePath()}/paylink`;return this.httpClient.post(a,{transaction:t},{headers:this.getBasicHeaders()}).then(o=>y.handleResponse(o))}klarnaMor(t,a){const o=`_action/${this.getApiBasePath()}/klarna-mor`;return this.httpClient.post(o,{orderId:t,action:a},{headers:this.getBasicHeaders()}).then(n=>y.handleResponse(n))}}Shopware.Service().register("BuckarooPaymentService",()=>{const e=Shopware.Application.getContainer("init"),t=Shopware.Service("loginService");return new H(e.httpClient,t)});const{ApiService:b}=Shopware.Classes;class K extends b{constructor(t,a,o="buckaroo"){super(t,a,o)}getBasicHeaders(){return this.loginService&&typeof this.loginService.getToken=="function"?super.getBasicHeaders():{"Content-Type":"application/json",Accept:"application/json"}}getSupportVersion(){const t=`_action/${this.getApiBasePath()}/version`;return this.httpClient.post(t,{},{headers:this.getBasicHeaders()}).then(a=>b.handleResponse(a))}getTaxes(){const t=`_action/${this.getApiBasePath()}/taxes`;return this.httpClient.post(t,{},{headers:this.getBasicHeaders()}).then(a=>b.handleResponse(a))}getIn3Icons(){const t=`_action/${this.getApiBasePath()}/in3/logos`;return this.httpClient.post(t,{},{headers:this.getBasicHeaders()}).then(a=>b.handleResponse(a))}getApiTest(t,a,o){const n=`_action/${this.getApiBasePath()}/getBuckarooApiTest`;return this.httpClient.post(n,{websiteKeyId:t,secretKeyId:a,saleChannelId:o},{headers:this.getBasicHeaders()}).then(i=>b.handleResponse(i))}}Shopware.Service().register("BuckarooPaymentSettingsService",()=>{const e=Shopware.Application.getContainer("init"),t=Shopware.Service("loginService");return new K(e.httpClient,t)});const O=``,{Component:U}=Shopware;U.register("buckaroo-afterpay-old-tax",{template:O,inject:["BuckarooPaymentSettingsService"],data(){return{taxes:[],showTaxes:!1,afterpayTaxes:[{name:this.$tc("buckaroo-payment.afterpay.hightTaxes"),id:1},{name:this.$tc("buckaroo-payment.afterpay.middleTaxes"),id:5},{name:this.$tc("buckaroo-payment.afterpay.lowTaxes"),id:2},{name:this.$tc("buckaroo-payment.afterpay.zeroTaxes"),id:3},{name:this.$tc("buckaroo-payment.afterpay.noTaxes"),id:4}],taxAssociation:{}}},model:{prop:"value",event:"change"},computed:{},props:{name:{type:String,required:!0,default:""},value:{type:Object,required:!1,default(){return{}}}},created(){this.BuckarooPaymentSettingsService.getTaxes().then(e=>{this.taxes=e.taxes.map(t=>({id:t.id,name:t.name}))})},methods:{setTaxAssociation(e,t){try{let a=t;t&&typeof t=="object"&&(t.target?a=t.target.value:t.hasOwnProperty("value")?a=t.value:t.hasOwnProperty("id")&&(a=t.id)),this.taxAssociation[e]=a,this.$emit("change",{...this.value,...this.taxAssociation})}catch(a){console.error("Error in setTaxAssociation:",a)}},getSelectValue(e){if(this.value[e])return this.value[e]}}});const G=`
`,{Component:W}=Shopware;W.register("buckaroo-main-config",{template:G,props:{configSettings:{type:Array,required:!1,default:()=>[]},value:{type:Object,required:!1,default:()=>({})},elementMethods:{type:Object,required:!1,default:()=>({})},isNotDefaultSalesChannel:{type:Boolean,required:!1,default:!1},currentSalesChannelId:{type:String,required:!1,default:null}},emits:["input"],model:{prop:"value",event:"input"},data(){var e;return{selectedCard:((e=this.$route.params)==null?void 0:e.paymentCode)||"general"}},watch:{value:{handler(e,t){this.$nextTick(()=>{this.$forceUpdate()})},deep:!0,immediate:!0},$route(e){var t;(t=e.params)!=null&&t.paymentCode&&(this.selectedCard=e.params.paymentCode)}},computed:{mainCard(){var t;return(t=this.configSettings.filter(a=>a.name===this.selectedCard))==null?void 0:t.pop()}},methods:{onInput(e){this.$emit("input",e)}}});const Z=`{% block buckaroo_config_card %}
{% endblock %}`,{Component:J}=Shopware;J.register("buckaroo-config-card",{template:Z,inject:["BuckarooPaymentSettingsService"],data(){return{shopwareVersion:null}},mounted(){this.fetchShopwareVersion(),this.$nextTick(()=>{this.$forceUpdate()})},watch:{value:{handler(){this.$nextTick(()=>{this.$forceUpdate()})},deep:!0,immediate:!0},currentSalesChannelId:{handler(e,t){e!==t&&this.$nextTick(()=>{this.$forceUpdate()})},immediate:!1}},computed:{canShowCredentialTester(){var d;const e=this.getValueForName("websiteKey"),t=this.getValueForName("secretKey");if(!(((d=this.card)==null?void 0:d.name)==="general"))return!1;const o=e!=null&&e!=="",n=t!=null&&t!=="";return o||n},hasValidConfigData(){return this.value&&typeof this.value=="object"&&Object.keys(this.value).length>0},reactiveValue(){return this.value}},emits:["input"],model:{prop:"value",event:"input"},props:{card:{type:Object,required:!1,default:()=>({elements:[]})},configSettings:{type:Array,required:!1,default:()=>[]},methods:{type:Object,required:!0},isNotDefaultSalesChannel:{type:Boolean,required:!0},currentSalesChannelId:{type:String,required:!0},value:{type:Object,required:!1,default:()=>({})}},methods:{fetchShopwareVersion(){const e=this.BuckarooPaymentSettingsService;e&&typeof e.getSupportVersion=="function"&&e.getSupportVersion().then(t=>{t&&t.shopware_version&&(this.shopwareVersion=t.shopware_version)}).catch(()=>{})},isShopware674OrNewer(){if(!this.shopwareVersion||typeof this.shopwareVersion!="string")return!1;const e=this.shopwareVersion.split(".").map(i=>parseInt(i,10)||0),t=e[0]||0,a=e[1]||0,o=e[2]||0,n=e[3]||0;return t>6?!0:t<6?!1:a>7?!0:a<7?!1:o>4?!0:o<4?!1:n>=0},getElementBind(e,t={}){var v,c,k,f,h,m,C;if(!this.methods||!this.methods.getElementBind){const u=e.label?this.getInlineSnippet(e.label):null;return{name:e.name,type:e.type||"text",config:e.config||{},label:u,value:this.getValueForName(e.name.replace("BuckarooPayments.config.",""))}}const a=this.methods.getElementBind(e,t),o=e.name.replace("BuckarooPayments.config.","");let n=this.getValueForName(o);const i=a.config||e.config||{};e.type==="bool"&&(n==null?n=a.value!==void 0?a.value:!1:typeof n=="string"?n=n==="1"||n==="true"||n==="on":n=!!n);let d=null;const g=this.isShopware674OrNewer();if(g){if((e.type==="bool"||e.type==="single-select"||e.type==="multi-select")&&this.configSettings&&Array.isArray(this.configSettings)){for(const u of this.configSettings)if(u.elements&&Array.isArray(u.elements)){const l=u.elements.find(p=>p.name===e.name);if(l){if(l.label){let p=this.getInlineSnippet(l.label);if(!p||typeof p=="string"&&p.trim().length===0)if(typeof l.label=="object"&&l.label!==null){const w=((v=this.$i18n)==null?void 0:v.locale)||"en-GB";p=l.label[w]||l.label["en-GB"]||Object.values(l.label)[0]||null}else typeof l.label=="string"&&(p=l.label);if(p&&typeof p=="string"&&p.trim().length>0){d=p;break}}if(!d&&l.config&&l.config.label){let p=this.getInlineSnippet(l.config.label);if(!p||typeof p=="string"&&p.trim().length===0)if(typeof l.config.label=="object"&&l.config.label!==null){const w=((c=this.$i18n)==null?void 0:c.locale)||"en-GB";p=l.config.label[w]||l.config.label["en-GB"]||Object.values(l.config.label)[0]||null}else typeof l.config.label=="string"&&(p=l.config.label);if(p&&typeof p=="string"&&p.trim().length>0){d=p;break}}}}}if(!d){if(a.label&&typeof a.label=="string"&&a.label.trim().length>0)d=a.label;else if(e.label){let u=this.getInlineSnippet(e.label);if(!u||typeof u=="string"&&u.trim().length===0)if(typeof e.label=="object"&&e.label!==null){const l=((k=this.$i18n)==null?void 0:k.locale)||"en-GB";u=e.label[l]||e.label["en-GB"]||Object.values(e.label)[0]||null}else typeof e.label=="string"&&(u=e.label);u&&typeof u=="string"&&u.trim().length>0&&(d=u)}else if(this.card&&this.card.elements&&Array.isArray(this.card.elements)){const u=this.card.elements.find(l=>l.name===e.name);if(u&&u.label){let l=this.getInlineSnippet(u.label);if(!l||typeof l=="string"&&l.trim().length===0)if(typeof u.label=="object"&&u.label!==null){const p=((f=this.$i18n)==null?void 0:f.locale)||"en-GB";l=u.label[p]||u.label["en-GB"]||Object.values(u.label)[0]||null}else typeof u.label=="string"&&(l=u.label);l&&typeof l=="string"&&l.trim().length>0&&(d=l)}}}!d&&a.config&&a.config.label&&typeof a.config.label=="string"&&a.config.label.trim().length>0&&(d=a.config.label)}let r=i;g&&d&&typeof d=="string"&&d.trim().length>0&&(e.type==="bool"||e.type==="single-select"||e.type==="multi-select")&&(r={...i,label:d});const s={...a,config:r};if(["allowedcreditcard","allowedcreditcards","allowedgiftcards","giftcardsPaymentmethods","payperemailAllowed"].includes(o)){s.type="multi-select",s.componentName="sw-multi-select",s.config={...s.config||{},multiple:!0,options:s.config&&s.config.options||i&&i.options||e.options||[]};const u=Array.isArray((h=s.config)==null?void 0:h.options)&&s.config.options.length>0?s.config.options[0]:null;console.debug("[BuckarooConfigCard] getElementBind multi-select binding",{fieldName:o,bindingType:s.type,componentName:s.componentName,optionsCount:Array.isArray((m=s.config)==null?void 0:m.options)?s.config.options.length:0,currentValue:n,sampleOption:u})}return g&&d&&typeof d=="string"&&d.trim().length>0&&(e.type==="bool"||!s.label||typeof s.label=="string"&&s.label.trim().length===0)&&(s.label=d),e.type==="bool"&&(s.value=n,g&&(!s.label||typeof s.label=="string"&&s.label.trim().length===0)&&(s.label=((C=s.config)==null?void 0:C.label)||e.name.replace("BuckarooPayments.config.","").replace(/([A-Z])/g," $1").trim())),(e.type==="bool"||e.type==="single-select"||e.type==="multi-select")&&(!s.label||typeof s.label=="string"&&s.label.trim().length===0)&&console.warn("Missing label for field:",e.name,"Type:",e.type,"Element label:",e.label,"Extracted:",d,"BaseBinding label:",a.label,"Final binding label:",s.label),s},getInheritWrapperBind(e){if(!this.methods||!this.methods.getInheritWrapperBind){const n=e.name.replace("BuckarooPayments.config.","");return{name:e.name,currentValue:this.getValueForName(n)}}const t=this.methods.getInheritWrapperBind(e),a=e.name.replace("BuckarooPayments.config.",""),o=this.getValueForName(a);return t.currentValue=o,t},getFieldError(e){return!this.methods||!this.methods.getFieldError?null:this.methods.getFieldError(e)},kebabCase(e){return!this.methods||!this.methods.kebabCase?e?e.toLowerCase().replace(/[A-Z]/g,"-$&").replace(/^-/,""):"":this.methods.kebabCase(e)},getInlineSnippet(e){var t;try{if(typeof e=="object"&&e!==null){const a=((t=this.$i18n)==null?void 0:t.locale)||"en-GB";if(e[a])return e[a];if(e["en-GB"])return e["en-GB"];const o=Object.keys(e)[0];return o&&e[o]?e[o]:JSON.stringify(e)}return typeof e=="string"?this.$t&&typeof this.$t=="function"?this.$t(e):e:String(e)}catch(a){return console.warn("Translation error for:",e,a),typeof e=="object"?JSON.stringify(e):String(e)}},getInheritedValue(e){return!this.methods||!this.methods.getInheritedValue?null:this.methods.getInheritedValue(e)},getValueForName(e){const t=this.reactiveValue;if(!t||typeof t!="object")return null;let a;const o=[`BuckarooPayments.config.${e}`,e.toLowerCase(),e.charAt(0).toLowerCase()+e.slice(1),e.charAt(0).toUpperCase()+e.slice(1)];for(const n of o)if(t[n]!==void 0){a=t[n];break}if(a===void 0&&t["BuckarooPayments.config"]&&typeof t["BuckarooPayments.config"]=="object"){for(const n of o)if(t["BuckarooPayments.config"][n]!==void 0){a=t["BuckarooPayments.config"][n];break}}return a&&typeof a=="object"&&a.hasOwnProperty("_value")&&(a=a._value),a},canShow(e){if(!e||!e.name)return!1;const t=e.name.replace("BuckarooPayments.config.","");return["orderStatus","paymentSuccesStatus","automaticallyCloseOpenOrders","sendInvoiceEmail"].includes(t)?!!this.getValueForName("advancedConfiguration"):t==="idealprocessingRenderMode"?!!this.getValueForName("idealprocessingShowissuers"):t==="idealRenderMode"?!!this.getValueForName("idealShowissuers"):["idealFastCheckoutEnabled","idealFastCheckoutVisibility","idealFastCheckoutLogoScheme"].includes(t)?!!this.getValueForName("idealFastCheckout"):t==="afterpayPaymentstatus"?!!this.getValueForName("afterpayCaptureonshippent"):t==="afterpayOldtax"?!!this.getValueForName("afterpayEnabledold"):!0},onInput(e){this.$emit("input",e)},onFieldInput(e,t){var a,o;try{let n=t;if(t&&typeof t=="object")if(t.target){const r=t.target;r.type==="checkbox"||r.type==="radio"?n=r.checked:(r.tagName==="SELECT"||r.type==="select-one"||r.type==="select-multiple")&&r.multiple?n=Array.from(r.selectedOptions).map(s=>s.value):n=r.value}else if(t.hasOwnProperty("value"))n=t.value;else if(t.hasOwnProperty("id")&&t.hasOwnProperty("name"))n=t.id;else if(Array.isArray(t)){const r=t.filter(c=>typeof c=="string"&&c.length===1).length,s=t.some(c=>c===","),B=t.some(c=>typeof c=="string"&&c.length>1);if(r>10&&s){const c=t.filter(m=>typeof m=="string"&&m.length>1),f=t.filter(m=>typeof m=="string"&&m.length===1).join("");let h=[];f.includes(",")?h=f.split(",").map(m=>m.trim()).filter(m=>m.length>0):f.length>0&&(h=[f]),n=[...h,...c].filter(m=>m&&m.length>0)}else n=t.filter(c=>!(c==null||c===""||typeof c=="string"&&c.length===1||typeof c=="string"&&(c.startsWith("+")||/^\d+$/.test(c)))).map(c=>typeof c=="object"&&c!==null&&(c.id||c.value||c.code||c.key)||c)}else{const r=["id","value","key","code"];for(const s of r)if(t[s]!==void 0){n=t[s];break}}else(typeof t=="boolean"||typeof t=="string"||typeof t=="number")&&(n=t);const i=(o=(a=this.card)==null?void 0:a.elements)==null?void 0:o.find(r=>r.name===e||r.name.replace("BuckarooPayments.config.","")===e.replace("BuckarooPayments.config.",""));n==="on"?n=!0:n==="off"&&(n=!1),i&&i.type==="bool"&&(typeof n=="string"?n=n==="1"||n==="true"||n==="on":n=!!n),i&&i.type==="multi-select"&&(console.debug("[BuckarooConfigCard] onFieldInput before normalize (multi-select)",{fieldName:e,rawEvent:t,rawValue:n}),Array.isArray(n)?n=n.filter(r=>r!=null&&r!=="").map(r=>typeof r=="object"&&r!==null&&(r.id||r.value||r.code||r.key)||r):typeof n=="string"?n=n.split(",").map(r=>r.trim()).filter(r=>r.length>0):n==null?n=[]:n=[n],console.debug("[BuckarooConfigCard] onFieldInput after normalize (multi-select)",{fieldName:e,normalizedValue:n}));const d=e.replace("BuckarooPayments.config.",""),g={...this.value};g[d]=n,g[e]=n,this.$emit("input",g)}catch(n){console.error("Error in onFieldInput:",n),console.error("Error details:",n.stack)}}}});const Y=`
`,{Component:Q,Filter:X}=Shopware;Q.register("buckaroo-payment-list",{template:Y,props:{configSettings:{type:Array,required:!1,default:()=>[]},value:{type:Object,required:!1,default:()=>({})},currentSalesChannelId:{type:String,required:!0}},emits:["input"],data(){return{payments:[{code:"Alipay",logo:"alipay.svg"},{code:"applepay",logo:"applepay.svg"},{code:"googlepay",logo:"googlepay.svg"},{code:"bancontactmrcash",logo:"bancontact.svg"},{code:"blik",logo:"blik.svg"},{code:"belfius",logo:"belfius.svg"},{code:"Billink",logo:"billink.svg"},{code:"creditcard",logo:"creditcards.svg"},{code:"creditcards",logo:"creditcards.svg"},{code:"eps",logo:"eps.svg"},{code:"giftcards",logo:"giftcards.svg"},{code:"idealqr",logo:"ideal-qr.svg"},{code:"ideal",logo:"ideal-wero.svg"},{code:"capayable",logo:"in3.svg"},{code:"KBCPaymentButton",logo:"kbc.svg"},{code:"klarna",logo:"klarna.svg"},{code:"klarnakp",logo:"klarna.svg"},{code:"knaken",logo:"gosettle.svg"},{code:"mbway",logo:"mbway.svg"},{code:"multibanco",logo:"multibanco.svg"},{code:"paybybank",logo:"paybybank.svg"},{code:"payconiq",logo:"payconiq.svg"},{code:"paypal",logo:"paypal.svg"},{code:"payperemail",logo:"payperemail.svg"},{code:"Przelewy24",logo:"przelewy24.svg"},{code:"afterpay",logo:"afterpay.svg"},{code:"sepadirectdebit",logo:"sepa-directdebit.svg"},{code:"transfer",logo:"sepa-credittransfer.svg"},{code:"Trustly",logo:"trustly.svg"},{code:"WeChatPay",logo:"wechatpay.svg"},{code:"swish",logo:"swish.svg"},{code:"bizum",logo:"bizum.svg"},{code:"twint",logo:"twint.svg"},{code:"wero",logo:"wero.svg"}]}},methods:{getPaymentTitle(e){var a;if(this.configSettings&&Array.isArray(this.configSettings)){const o=this.configSettings.find(n=>n.name===e);if(o&&o.title)try{if(typeof o.title=="object"&&o.title!==null){const n=((a=this.$i18n)==null?void 0:a.locale)||"en-GB";if(o.title[n])return o.title[n];if(o.title["en-GB"])return o.title["en-GB"];const i=Object.keys(o.title)[0];return i&&o.title[i]?o.title[i]:JSON.stringify(o.title)}return typeof o.title=="string"?this.$t&&typeof this.$t=="function"?this.$t(o.title):o.title:String(o.title)}catch(n){return console.warn("Translation error for:",o.title,n),typeof o.title=="object"?JSON.stringify(o.title):String(o.title)}}const t=this.payments.find(o=>o.code===e);return t?t.code:"Unknown Payment"},assetFilter(e){return X.getByName("asset")(e)}}});const ee=`{{ $tc('buckaroo-payment.button.labelTestApi') }}`,{Component:te}=Shopware;te.register("buckaroo-test-credentials",{template:ee,mixins:[Shopware.Mixin.getByName("notification")],data(){return{isLoading:!1}},inject:["BuckarooPaymentSettingsService"],props:{config:{type:Object,required:!0},currentSalesChannelId:{required:!0}},computed:{enabled:function(){return(this.getConfigValue("websiteKey")||"").length>0&&(this.getConfigValue("secretKey")||"").length>0}},methods:{getConfigValue:function(e){return this.config["BuckarooPayments.config."+e]},sendTestApi(){this.isLoading=!0;let e=this.getConfigValue("websiteKey"),t=this.getConfigValue("secretKey");this.BuckarooPaymentSettingsService.getApiTest(e,t,this.currentSalesChannelId).then(a=>{this.isLoading=!1,a.status=="success"?this.createNotificationSuccess({title:this.$tc("buckaroo-payment.settingsForm.titleSuccess"),message:this.$tc(a.message)}):this.createNotificationError({title:this.$tc("buckaroo-payment.settingsForm.titleError"),message:this.$tc(a.message)})}).catch(()=>{this.isLoading=!1})}}});const ae=`
`,{Component:ne}=Shopware;ne.register("buckaroo-toggle-status",{template:ae,props:{method:{type:String,required:!0},value:{required:!0},currentSalesChannelId:{required:!0}},emits:["input"],inject:["systemConfigApiService"],data(){return{status:"disabled",isLoading:!1}},mounted(){this.status=this.getStatus()},watch:{value:{handler(e){this.status=this.getStatus()},deep:!0,immediate:!0}},methods:{getStatus(){const e=this.isActive(),t=this.getEnvironment();return e?t:"disabled"},isActive(){const e=this.getValueForName(`${this.method}Enabled`);return typeof e=="string"?e.toLowerCase()==="true":!!e},getEnvironment(){const e=this.getValueForName(`${this.method}Environment`);return e==null||e===""?"test":["test","live"].includes(e)?e:"test"},getValueForName(e){const t=`BuckarooPayments.config.${e}`;if(!this.value||typeof this.value!="object")return null;let a;if(this.value[t]!==void 0)a=this.value[t];else if(this.value[e]!==void 0)a=this.value[e];else if(this.value["BuckarooPayments.config"]&&typeof this.value["BuckarooPayments.config"]=="object")this.value["BuckarooPayments.config"][e]!==void 0&&(a=this.value["BuckarooPayments.config"][e]);else{const o=[e,e.toLowerCase(),e.charAt(0).toLowerCase()+e.slice(1),e.charAt(0).toUpperCase()+e.slice(1)];for(const n of o){const i=`BuckarooPayments.config.${n}`;if(this.value[i]!==void 0){a=this.value[i];break}if(this.value[n]!==void 0){a=this.value[n];break}}}return a&&typeof a=="object"&&a.hasOwnProperty("_value")&&(a=a._value),a},setStatus(e){this.status=e,this.saveStatus()},getClass(e){return this.status===e?"active":""},async saveStatus(){const e=`BuckarooPayments.config.${this.method}Enabled`,t=`BuckarooPayments.config.${this.method}Environment`;let a={[e]:!1};const o={...this.value};o[e]=!1,["live","test"].indexOf(this.status)!==-1&&(a={[e]:!0,[t]:this.status},o[e]=!0,o[t]=this.status),this.$emit("input",o),this.isLoading=!0;try{await this.systemConfigApiService.batchSave({[this.currentSalesChannelId]:a}).finally(()=>{this.isLoading=!1}),this.renderSuccess()}catch(n){this.renderError(n)}},renderSuccess(){this.$store.dispatch("notification/createNotification",{variant:"success",message:this.$tc("sw-extension-store.component.sw-extension-config.messageSaveSuccess")})},renderError(e){this.$store.dispatch("notification/createNotification",{variant:"error",message:e})}}}); -//# sourceMappingURL=buckaroo-payments-BbqpZqUI.js.map +const T=`{% block sw_order_detail_content_tabs %}

{{ $tc('buckaroo-payment.paymentInTestMode') }}

{% parent %} {% endblock %} {% block sw_order_detail_content_tabs_general %} {% parent %} {{ $tc('buckaroo-payment.tabs.title') }} {% endblock %} {% block sw_order_detail_actions %} {% parent %} {% endblock %}`,{Component:$,Context:S}=Shopware,P=Shopware.Data.Criteria;$.override("sw-order-detail",{template:T,data(){return{isBuckarooPayment:!1,isPaymentInTestMode:!1}},computed:{isEditable(){return!this.isBuckarooPayment||this.$route.name!=="buckaroo.payment.detail"},showTabs(){return!0}},watch:{orderId:{deep:!0,handler(){if(!this.orderId){this.setIsBuckarooPayment(null);return}const e=this.repositoryFactory.create("order"),t=new P(1,1);t.addAssociation("transactions"),e.get(this.orderId,S.api,t).then(a=>{if(this.setPaymentInTestMode(a),a.transactions.length<=0||!a.transactions.last().paymentMethodId){this.setIsBuckarooPayment(null);return}const o=a.transactions.last().paymentMethodId;o!=null&&this.setIsBuckarooPayment(o)})},immediate:!0}},methods:{setPaymentInTestMode(e){e.customFields&&e.customFields.buckaroo_payment_in_test_mode&&(this.isPaymentInTestMode=e.customFields.buckaroo_payment_in_test_mode===!0)},setIsBuckarooPayment(e){if(!e)return;this.repositoryFactory.create("payment_method").get(e,S.api).then(a=>{this.isBuckarooPayment=a.formattedHandlerIdentifier.indexOf("buckaroo")>=0})}}});const I=`{% block sw_order_detail_base_line_items_summary %}
{{ $tc('buckaroo-payment.fee') }}
{{ order.customFields.buckarooFee }} {% if order.currency.isoCode == "PLN" %} PLN {% else %} {{ order.currency.symbol }} {% endif %}
{% parent %} {% endblock %}`,{Component:x,Context:oe}=Shopware;Shopware.Data.Criteria;x.override("sw-order-detail-base",{template:I});const A=`{% block sw_order_detail_base_secondary_info_payment %} {% endblock %}`,{Component:M}=Shopware;M.override("sw-order-user-card",{template:A,inject:["systemConfigApiService"],data(){return{config:{}}},created(){this.systemConfigApiService.getValues("BuckarooPayments.config",null).then(e=>{this.config=e}).finally(()=>{})}});const R=`{% block sw_system_config_content_card %} {% endblock %}`,{Component:F}=Shopware;F.override("sw-system-config",{template:R,watch:{currentSalesChannelId:{handler(e,t){e&&this.domain==="BuckarooPayments.config"&&this.loadBuckarooConfigData()},immediate:!0},domain:{handler(e){e==="BuckarooPayments.config"&&this.currentSalesChannelId&&this.loadBuckarooConfigData()},immediate:!0}},methods:{loadBuckarooConfigData(){this.systemConfigApiService.getValues("BuckarooPayments.config",this.currentSalesChannelId).then(e=>{this.actualConfigData[this.currentSalesChannelId]||(this.actualConfigData[this.currentSalesChannelId]={});const t={};e&&typeof e=="object"&&Object.keys(e).forEach(a=>{const o=e[a];o&&typeof o=="object"&&o.hasOwnProperty("_value")?t[a]=o._value:t[a]=o;const n=a.replace("BuckarooPayments.config.","");n!==a&&(t[n]=t[a])}),this.actualConfigData[this.currentSalesChannelId]={},Object.keys(t).forEach(a=>{this.actualConfigData[this.currentSalesChannelId][a]=t[a]}),this.$nextTick(()=>{this.$forceUpdate()})}).catch(e=>{console.error("Error fetching system config:",e)})},onConfigDataUpdate(e){this.actualConfigData[this.currentSalesChannelId]||(this.actualConfigData[this.currentSalesChannelId]={}),Object.keys(e).forEach(t=>{if(this.actualConfigData[this.currentSalesChannelId][t]=e[t],!t.startsWith("BuckarooPayments.config.")){const a=`BuckarooPayments.config.${t}`;this.actualConfigData[this.currentSalesChannelId][a]=e[t]}})},saveAll(){return this.domain!=="BuckarooPayments.config"?this.$super("saveAll"):this.saveBuckaroo()},saveBuckaroo(){return this.isLoading=!0,this.systemConfigApiService.batchSave(this.getSelectedValues()).finally(()=>{this.isLoading=!1})},getCurrentConfigCard(){var t,a;const e=((t=this.$route.params)==null?void 0:t.paymentCode)||"general";return(a=this.config.filter(o=>o.name===e))==null?void 0:a.pop()},getSelectedValues(){const e=this.actualConfigData[this.currentSalesChannelId],t=this.getCurrentConfigCard();if(t!=null&&t.elements){let a={};return t==null||t.elements.forEach(o=>{if(o!=null&&o.name){let n=e[o.name];if(n===void 0){const i=o.name.replace("BuckarooPayments.config.","");n=e[i]}a[o.name]=n}}),{[this.currentSalesChannelId]:a}}return this.actualConfigData}}});const E=`{% block buckaroo_payment_detail %}
{{ $tc('buckaroo-payment.paymentDetail.paylinkDescription') }}
{{ $tc('buckaroo-payment.paymentDetail.yourLink') }}: {{ paylink }}
{{ $tc('buckaroo-payment.paymentDetail.paylinkButton') }}
{{ $tc('buckaroo-payment.orderItems.title') }}
{{ $tc('buckaroo-payment.paymentDetail.amountTotalTitle') }}:
{{ buckaroo_refund_amount }} {{ currency }}
{{ $tc('buckaroo-payment.paymentDetail.amountCustomRefundTitle') }}:
{{ currency }}
{{ $tc('buckaroo-payment.paymentDetail.amountRefundTotalTitle') }}:
{{ buckaroo_refund_total_amount }} {{ currency }}
{{ $tc('buckaroo-payment.paymentDetail.buttonTitle') }}
{{ $tc('buckaroo-payment.paymentDetail.payDescription') }}
{{ $tc('buckaroo-payment.paymentDetail.payButton') }}
{{ $tc('buckaroo-payment.paymentDetail.klarnaMorDescription') }}
{{ $tc('buckaroo-payment.paymentDetail.klarnaMorCancel') }}
{{ $tc('buckaroo-payment.paymentDetail.klarnaMorCancelButton') }}
{{ $tc('buckaroo-payment.paymentDetail.klarnaMorUpdate') }}
{{ $tc('buckaroo-payment.paymentDetail.klarnaMorUpdateButton') }}
{{ $tc('buckaroo-payment.paymentDetail.klarnaMorExtend') }}
{{ $tc('buckaroo-payment.paymentDetail.klarnaMorExtendButton') }}
{{ $tc('buckaroo-payment.paymentDetail.klarnaMorShipping') }}
{{ $tc('buckaroo-payment.paymentDetail.klarnaMorShippingButton') }}
{% endblock %}`,{Component:D,Filter:ie,Context:V}=Shopware,_=Shopware.Data.Criteria;D.register("buckaroo-payment-detail",{template:E,inject:["repositoryFactory","BuckarooPaymentService","systemConfigApiService"],data(){return{config:{},buckaroo_refund_amount:"0",buckaroo_refund_total_amount:"0",currency:"EUR",isRefundPossible:!0,isCapturePossible:!1,isPaylinkAvailable:!1,isPaylinkVisible:!1,paylinkMessage:"",paylink:"",isLoading:!1,order:!1,buckarooTransactions:null,orderItems:[],transactionsToRefund:[],relatedResources:[],isAuthorized:!1,isKlarnaMor:!1,fulfillmentMessage:"",fulfillmentStatus:null}},computed:{orderItemsColumns(){return[{property:"name",label:this.$tc("buckaroo-payment.orderItems.types.name"),allowResize:!1,primary:!0,inlineEdit:!0,multiLine:!0},{property:"quantity",label:this.$tc("buckaroo-payment.orderItems.types.quantity"),rawData:!0,align:"right"},{property:"totalAmount",label:this.$tc("buckaroo-payment.orderItems.types.totalAmount"),rawData:!0,align:"right"}]},transactionsToRefundColumns(){return[{property:"transaction_method",rawData:!0},{property:"amount",rawData:!0}]},relatedResourceColumns(){return[{property:"created_at",label:this.$tc("buckaroo-payment.transactionHistory.types.created_at"),rawData:!0},{property:"total",label:this.$tc("buckaroo-payment.transactionHistory.types.total"),rawData:!0},{property:"shipping_costs",label:this.$tc("buckaroo-payment.transactionHistory.types.shipping_costs"),rawData:!0},{property:"total_excluding_vat",label:this.$tc("buckaroo-payment.transactionHistory.types.total_excluding_vat"),rawData:!0},{property:"vat",label:this.$tc("buckaroo-payment.transactionHistory.types.vat"),rawData:!0},{property:"transaction_key",label:this.$tc("buckaroo-payment.transactionHistory.types.transaction_key"),rawData:!0},{property:"transaction_method",label:this.$tc("buckaroo-payment.transactionHistory.types.transaction_method"),rawData:!0},{property:"statuscode",label:this.$tc("buckaroo-payment.transactionHistory.types.statuscode"),rawData:!0}]}},created(){this.createdComponent()},methods:{recalculateOrderItems(){this.buckaroo_refund_amount=0;for(const e in this.orderItems)this.orderItems[e].totalAmount=parseFloat(parseFloat(this.orderItems[e].unitPrice)*parseFloat(this.orderItems[e].quantity||0)).toFixed(2),this.buckaroo_refund_amount=parseFloat(parseFloat(this.buckaroo_refund_amount)+parseFloat(this.orderItems[e].totalAmount)).toFixed(2)},recalculateRefundItems(){this.buckaroo_refund_total_amount=0;for(const e in this.transactionsToRefund)this.transactionsToRefund[e].amount&&(this.buckaroo_refund_total_amount=parseFloat(parseFloat(this.buckaroo_refund_total_amount)+parseFloat(this.transactionsToRefund[e].amount)).toFixed(2))},getCustomRefundEnabledEl(){return document.getElementById("buckaroo_custom_refund_enabled")},getCustomRefundAmountEl(){return document.getElementById("buckaroo_custom_refund_amount")},toggleCustomRefund(){this.getCustomRefundEnabledEl()&&this.getCustomRefundAmountEl()&&(this.getCustomRefundAmountEl().disabled=!this.getCustomRefundEnabledEl().checked)},getCustomRefundAmount(){return this.getCustomRefundEnabledEl()&&this.getCustomRefundAmountEl()&&this.getCustomRefundEnabledEl().checked?this.getCustomRefundAmountEl().value:0},createdComponent(){let e=this;const t=this.$route.params.id;this.systemConfigApiService.getValues("BuckarooPayments.config",null).then(n=>{this.config=n});const a=this.repositoryFactory.create("order"),o=new _(1,1);this.orderId=t,o.addAssociation("transactions.paymentMethod").addAssociation("transactions"),o.getAssociation("transactions").addSorting(_.sort("createdAt")),a.get(t,V.api,o).then(n=>{e.checkedIsAuthorized(n);const i=n.transactions&&n.transactions.last().paymentMethod&&n.transactions.last().paymentMethod.customFields&&n.transactions.last().paymentMethod.customFields.buckaroo_key?n.transactions.last().paymentMethod.customFields.buckaroo_key.toLowerCase():"";e.isCapturePossible=!!i&&(["klarnakp","billink","afterpay","klarna","wero"].includes(i)||e.isAfterpayCapturePossible(n)),e.isKlarnaMor=i==="klarna",e.isPaylinkVisible=e.isPaylinkAvailable=this.getConfigValue("paylinkEnabled")&&n.stateMachineState&&n.stateMachineState.technicalName&&n.stateMachineState.technicalName=="open"&&n.transactions&&n.transactions.last().stateMachineState.technicalName=="open"}),this.BuckarooPaymentService.getBuckarooTransaction(t).then(n=>{e.orderItems=[],e.transactionsToRefund=[],e.relatedResources=[],this.$emit("loading-change",!1),n.orderItems&&Array.isArray(n.orderItems)&&n.orderItems.forEach(i=>{e.orderItems.push({id:i.id,name:i.name,quantity:i.quantity,quantityMax:i.quantity,unitPrice:i.unitPrice.value,totalAmount:i.totalAmount.value,variations:i.variations||[]})}),e.buckaroo_refund_amount=n.refundTotals?n.refundTotals.totalAmount:0,e.currency=n.refundTotals?n.refundTotals.currency:"EUR",n.transactionsToRefund&&Array.isArray(n.transactionsToRefund)&&n.transactionsToRefund.forEach(i=>{e.transactionsToRefund.push({id:i.id,transactions:i.transactions,amount:i.total,amountMax:i.total,currency:i.currency,transaction_method:i.transaction_method,logo:i.transaction_method?i.logo:null}),e.currency=i.currency}),e.recalculateRefundItems(),n.transactions&&Array.isArray(n.transactions)&&n.transactions.forEach(i=>{e.relatedResources.push({id:i.id,transaction_key:i.transaction,total:i.total,total_excluding_vat:i.total_excluding_vat,shipping_costs:i.shipping_costs,vat:i.vat,transaction_method:i.transaction_method,logo:i.transaction_method?i.logo:null,created_at:i.created_at,statuscode:i.statuscode})})}).catch(n=>{console.log("errorResponse",n)})},isAfterpayCapturePossible(e){return e.customFields.buckaroo_is_authorize===!0},checkedIsAuthorized(e){var t,a,o;this.isAuthorized=((o=(a=(t=e==null?void 0:e.transactions)==null?void 0:t.last())==null?void 0:a.stateMachineState)==null?void 0:o.technicalName)==="authorized"},refundOrder(e,t){let a=this;a.isRefundPossible=!1,this.BuckarooPaymentService.refundPayment(e,this.transactionsToRefund,this.orderItems,this.getCustomRefundAmount()).then(o=>{for(const n in o)o[n].status?this.$store.dispatch("notification/createNotification",{variant:"success",title:a.$tc("buckaroo-payment.settingsForm.titleSuccess"),message:a.$tc(o[n].message)+o[n].amount}):this.$store.dispatch("notification/createNotification",{variant:"error",title:a.$tc("buckaroo-payment.settingsForm.titleError"),message:a.$tc(o[n].message)});a.isRefundPossible=!0,this.createdComponent()}).catch(o=>{this.$store.dispatch("notification/createNotification",{variant:"error",title:this.$tc("buckaroo-payment.settingsForm.titleError"),message:o.response.data.message}),a.isRefundPossible=!0})},createPaylink(e){let t=this;t.isPaylinkAvailable=!1,this.BuckarooPaymentService.createPaylink(e,this.transactionsToRefund,this.orderItems).then(a=>{a.status?(t.paylinkMessage=t.$tc(a.message)+a.paylinkhref,t.paylink=a.paylink,this.$store.dispatch("notification/createNotification",{variant:"success",title:t.$tc("buckaroo-payment.settingsForm.titleSuccess"),message:t.paylinkMessage})):this.$store.dispatch("notification/createNotification",{variant:"error",title:t.$tc("buckaroo-payment.settingsForm.titleError"),message:t.$tc(a.message)}),t.isPaylinkAvailable=!0}).catch(a=>{this.$store.dispatch("notification/createNotification",{variant:"error",title:this.$tc("buckaroo-payment.settingsForm.titleError"),message:a.response.data.message}),t.isPaylinkAvailable=!0})},getConfigValue(e){return this.config[`BuckarooPayments.config.${e}`]},captureOrder(e){let t=this;t.isCapturePossible=!1,this.BuckarooPaymentService.captureOrder(e,this.transactionsToRefund,this.orderItems).then(a=>{a.status?this.$store.dispatch("notification/createNotification",{variant:"success",title:t.$tc("buckaroo-payment.settingsForm.titleSuccess"),message:a.message}):this.$store.dispatch("notification/createNotification",{variant:"error",title:t.$tc("buckaroo-payment.settingsForm.titleError"),message:a.message}),t.isCapturePossible=!0,this.createdComponent()}).catch(a=>{this.$store.dispatch("notification/createNotification",{variant:"error",title:this.$tc("buckaroo-payment.settingsForm.titleError"),message:t.$tc(a.response.data.message)}),t.isCapturePossible=!0})},klarnaMor(e){let t=this;t.isLoading=!0,this.BuckarooPaymentService.klarnaMor(this.orderId,e).then(a=>{a.status?this.$store.dispatch("notification/createNotification",{variant:"success",title:t.$tc("buckaroo-payment.settingsForm.titleSuccess"),message:a.message}):this.$store.dispatch("notification/createNotification",{variant:"error",title:t.$tc("buckaroo-payment.settingsForm.titleError"),message:a.message}),t.isLoading=!1,this.createdComponent()}).catch(a=>{this.$store.dispatch("notification/createNotification",{variant:"error",title:this.$tc("buckaroo-payment.settingsForm.titleError"),message:a.response&&a.response.data?a.response.data.message:"An error occurred"}),t.isLoading=!1})}}});const{Component:N}=Shopware;N.extend("buckaroo-payment-config","sw-extension-config",{});const L={"buckaroo-payment":{fee:"Buckaroo Betaaltoeslag",order:{refundDescription:"Refund voor bestelling #orderNumber"},general:{title:"Buckaroo",description:"Buckaroo Payment"},settingsForm:{save:"Opslaan",titleSuccess:"Succes",titleError:"Foutmelding"},supportModal:{menuButton:"Version & Support",title:"Versie & Support",support:{description:"Zorg ervoor dat u uw website key bij de hand heeft voordat u contact opneemt met Buckaroo technical support",label1:"Buckaroo Plaza:",label2:"Telefoonnummer:",label3:"E-mail:",label4:"Website:",your_version:"Uw PHP versie:",version:"Versie compatibiliteit",information:"Informatie"}},tabs:{title:"Buckaroo Payment",overview:"Overzicht"},paymentDetail:{yourLink:"Uw Paylink",paylinkButton:"Creëer Paylink",paylinkDescription:"Creëer Paylink voor order",paylinkTitle:"Paylink",refundTitle:"Terugbetaling",transactionsTitle:"Transacties",amountTitle:"Hoeveelheid",amountTotalTitle:"Algemeen totaal (grand total)",amountRefundTotalTitle:"Terugbetaling Algemeen totaal (grand total)",amountCustomRefundTitle:"Aangepast bedrag terugbetalen",buttonTitle:"Terugbetaling",successTitle:"Success",successMessage:"Buckaroo terugbetaling succesvol",errorTitle:"Foutmelding",payTitle:"Betaling vastleggen (Capture)",payDescription:"Factuur voor bestelling vastleggen (Capture) en aanmaken",payButton:"Betaling vastleggen (Capture)",klarnaMorTitle:"Klarna (MoR)",klarnaMorDescription:"Beheer de Klarna reservering voor deze bestelling.",klarnaMorCancel:"Reservering annuleren",klarnaMorCancelButton:"Reservering annuleren",klarnaMorUpdate:"Reservering bijwerken",klarnaMorUpdateButton:"Reservering bijwerken",klarnaMorExtend:"Reservering verlengen",klarnaMorExtendButton:"Reservering verlengen",klarnaMorShipping:"Verzendinfo toevoegen",klarnaMorShippingButton:"Verzendinfo toevoegen"},orderItems:{title:"Artikelen om terug te betalen",types:{id:"id",name:"Titel",quantity:"Aantal om terug te betalen",totalAmount:"Subtotaal"}},transactionsToRefund:{title:"Terugbetaling Totaal"},transactionHistory:{types:{id:"id",created_at:"Datum/tijd",total:"Totaal",shipping_costs:"Verzendkosten",total_excluding_vat:"Totaal exclusief BTW",total_including_vat:"Totaal inclusief BTW",vat:"BTW",transaction_key:"Transactie key",transaction_method:"Betaalmethode",statuscode:"Status"}},messageNotValid:"Dit veld is niet geldig.",messageNotBlank:"Dit veld mag niet leeg zijn.",button:{labelTestApi:"Test gegevens"},afterpay:{setup:"Belastingkoppeling instellen voor Riverty old ",hightTaxes:"Hoge BTW-heffingen",middleTaxes:"Middelmatige BTW-belastingen",lowTaxes:"Lage BTW-heffingen",zeroTaxes:"Nul VAT",noTaxes:"Geen BTW"},paymentInTestMode:"De betaling voor deze bestelling is in testmodus uitgevoerd",refund:{not_supported:"Terugbetaling wordt niet ondersteund",already_refunded:"Deze bestelling is al terugbetaald",refunded_amount:"Buckaroo terugbetaling succesvol"},test_api:{connection_ready:"Verbinding gereed",connection_failed:"Verbinding mislukt"},paylink:{invalid_amount:"Het bedrag is niet geldig",pay_link:"Uw Paylink:"},missing_order_id:"Ontbrekende bestelling orderId",missing_transaction:"Order transactie niet gevonden",general_request_error:"Helaas is er een fout opgetreden tijdens het verwerken van uw aanvraag. Probeer het opnieuw.",in3LogoLabel:"Betaalmethode Logo:","configure-payment":"Configure payment","configure-link":"Configure","payment-methods":"Payment methods"}},j={"buckaroo-payment":{fee:"Buckaroo Gebühr",order:{refundDescription:"Rückerstattung für Bestellung #orderNumber"},general:{title:"Buckaroo",description:"Buckaroo Zahlung"},settingsForm:{save:"Speichern",titleSuccess:"Erfolg",titleError:"Fehler"},supportModal:{menuButton:"Version & Unterstützung",title:"Version & Unterstützung",support:{description:"Bevor Sie den technischen Support von Buckaroo kontaktieren, bitte holen Sie Ihren (Händler-)Schlüssel und Geheimschlüssel ab.",label1:"Buckaroo Plaza:",label2:"Telefon:",label3:"E-Mail:",label4:"Webseite:",your_version:"Ihre PHP-Version:",version:"Versionskompatibilität",information:"Informationen"}},tabs:{title:"Buckaroo Payment",overview:"Übersicht"},paymentDetail:{yourLink:"Ihr Paylink",paylinkButton:"Paylink erstellen",paylinkDescription:"Paylink erstellen für Bestellung",paylinkTitle:"Paylink",refundTitle:"Rückerstattung",transactionsTitle:"Transaktionen",amountTitle:"Betrag",amountTotalTitle:"Gesamtsumme",amountRefundTotalTitle:"Gesamtsumme der Rückerstattung",amountCustomRefundTitle:"Rückerstattung individueller Betrag",buttonTitle:"Rückerstattung",successTitle:"Erfolg",successMessage:"Buckaroo-Erfolg, zurückerstattet",errorTitle:"Fehler",payTitle:"Zahlung erfassen (Capture)",payDescription:"Erfassen (Capture) und Rechnung für Bestellung erstellen",payButton:"Zahlung erfassen (Capture)",klarnaMorTitle:"Klarna (MoR)",klarnaMorDescription:"Verwalten Sie die Klarna-Reservierung für diese Bestellung.",klarnaMorCancel:"Reservierung stornieren",klarnaMorCancelButton:"Reservierung stornieren",klarnaMorUpdate:"Reservierung aktualisieren",klarnaMorUpdateButton:"Reservierung aktualisieren",klarnaMorExtend:"Reservierung verlängern",klarnaMorExtendButton:"Reservierung verlängern",klarnaMorShipping:"Versandinformationen hinzufügen",klarnaMorShippingButton:"Versandinformationen hinzufügen"},orderItems:{title:"Artikel zur Rückerstattung",types:{id:"id",name:"Titel",quantity:"Menge zur Rückerstattung",totalAmount:"Teilsumme"}},transactionsToRefund:{title:"Rückerstattungssummen"},transactionHistory:{types:{id:"id",created_at:"Datum/Uhrzeit",total:"Gesamt",shipping_costs:"Versandkosten",total_excluding_vat:"Gesamt ohne MwSt. (VAT)",total_including_vat:"Gesamt inklusive MwSt. (VAT)",vat:"MwSt. (VAT)",transaction_key:"Transaktionsschlüssel",transaction_method:"Zahlungsmethode",statuscode:"Status"}},messageNotValid:"Dieses Feld ist nicht gültig.",messageNotBlank:"Dieses Feld darf nicht leer sein.",button:{labelTestApi:"Verbindung testen"},afterpay:{setup:"Steuerzuordnung für Riverty old einrichten ",hightTaxes:"Hohe MwSt. (VAT)",middleTaxes:"Mittlere MwSt. (VAT)",lowTaxes:"Niedrige MwSt. (VAT)",zeroTaxes:"Keine MwSt. (VAT)",noTaxes:"Keine Mehrwertsteuer"},paymentInTestMode:"Die Zahlung für diese Bestellung wurde im Testmodus durchgeführt",refund:{not_supported:"Rückerstattung wird nicht unterstützt",already_refunded:"Diese Bestellung wurde bereits zurückerstattet",refunded_amount:"Erfolgreich von Buckaroo erstattet"},test_api:{connection_ready:"Verbindung bereit",connection_failed:"Verbindung fehlgeschlagen"},paylink:{invalid_amount:"Betrag ist nicht gültig",pay_link:"Ihr Zahlungslink (Paylink):"},missing_order_id:"Fehlende Bestell-ID",missing_transaction:"Transaktion der Bestellung nicht gefunden",general_request_error:"Leider ist ein Fehler bei der Bearbeitung Ihrer Anfrage aufgetreten. Bitte versuchen Sie es erneut.",in3LogoLabel:"Zahlungslogo:","configure-payment":"Configure payment","configure-link":"Configure","payment-methods":"Payment methods"}},z={"buckaroo-payment":{fee:"Buckaroo Fee",order:{refundDescription:"Refund for order #orderNumber"},general:{title:"Buckaroo",description:"Buckaroo Payment"},settingsForm:{save:"Save",titleSuccess:"Success",titleError:"Error"},supportModal:{menuButton:"Version & Support",title:"Version & Support",support:{description:"Before contacting Buckaroo technical support, please retrieve your (Merchant) key, Secret key, certificate and certificate thumbprint.",label1:"Buckaroo Payment Plaza:",label2:"Phone:",label3:"E-mail:",label4:"Website:",your_version:"Your PHP version:",version:"Version compatibility",information:"Information"}},tabs:{title:"Buckaroo Payment",overview:"Overview"},paymentDetail:{yourLink:"Your Paylink",paylinkButton:"Create paylink",paylinkDescription:"Create paylink for order",paylinkTitle:"Paylink",refundTitle:"Refund",transactionsTitle:"Transactions",amountTitle:"Amount",amountTotalTitle:"Grand total",amountRefundTotalTitle:"Refund Grand total",amountCustomRefundTitle:"Refund custom amount",buttonTitle:"Refund",successTitle:"Success",successMessage:"Buckaroo success refunded ",errorTitle:"Error",payTitle:"Capture payment",payDescription:"Capture and create invoice for order",payButton:"Capture payment",klarnaMorTitle:"Klarna (MoR)",klarnaMorDescription:"Manage the Klarna reservation for this order.",klarnaMorCancel:"Cancel reservation",klarnaMorCancelButton:"Cancel reservation",klarnaMorUpdate:"Update reservation",klarnaMorUpdateButton:"Update reservation",klarnaMorExtend:"Extend reservation",klarnaMorExtendButton:"Extend reservation",klarnaMorShipping:"Add shipping info",klarnaMorShippingButton:"Add shipping info"},orderItems:{title:"Items to Refund",types:{id:"id",name:"Title",quantity:"Qty to Refund",totalAmount:"Subtotal"}},transactionsToRefund:{title:"Refund Totals"},transactionHistory:{types:{id:"id",created_at:"Date/time",total:"Total",shipping_costs:"Shipping costs",total_excluding_vat:"Total excluding VAT",total_including_vat:"Total including VAT",vat:"VAT",transaction_key:"Transaction key",transaction_method:"Payment method",statuscode:"Status"}},messageNotValid:"This field not valid.",messageNotBlank:"This field must not be empty.",button:{labelTestApi:"Test connection"},afterpay:{setup:"Setup tax association for Riverty old ",hightTaxes:"High VAT taxes",middleTaxes:"Middle VAT taxes",lowTaxes:"Low VAT taxes",zeroTaxes:"Zero VAT",noTaxes:"No VAT tax"},paymentInTestMode:"The payment for this order was made in test mode",refund:{not_supported:"Refund is not supported",already_refunded:"This order is already refunded",refunded_amount:"Buckaroo success refunded"},test_api:{connection_ready:"Connection ready",connection_failed:"Connection failed"},paylink:{invalid_amount:"Amount is not valid",pay_link:"Your Paylink:"},missing_order_id:"Missing order orderId",missing_transaction:"Order transaction not found",general_request_error:"Unfortunately an error occurred while processing your request. Please try again.",in3LogoLabel:"Payment Logo:","configure-payment":"Configure payment","configure-link":"Configure","payment-methods":"Payment methods"}},{Module:q}=Shopware;q.register("buckaroo-payment",{type:"plugin",name:"BuckarooPayment",title:"buckaroo-payment.general.title",description:"buckaroo-payment.general.description",version:"1.0.0",targetVersion:"1.0.0",color:"#000000",icon:"default-action-settings",snippets:{"nl-NL":L,"de-DE":j,"en-GB":z},routeMiddleware(e,t){t.name==="sw.order.detail"&&t.children.push({component:"buckaroo-payment-detail",name:"buckaroo.payment.detail",isChildren:!0,path:"/sw/order/buckaroo/detail/:id"}),e(t)},routes:{config:{component:"buckaroo-payment-config",path:":namespace/payment/:paymentCode",name:"buckaroo.config.payment",meta:{parentPath:"sw.extension.config"},props:{default(e){return{namespace:e.params.namespace}}}}}});const{ApiService:y}=Shopware.Classes;class H extends y{constructor(t,a,o="buckaroo"){super(t,a,o)}getBasicHeaders(){return this.loginService&&typeof this.loginService.getToken=="function"?super.getBasicHeaders():{"Content-Type":"application/json",Accept:"application/json"}}getBuckarooTransaction(t){const a=`_action/${this.getApiBasePath()}/getBuckarooTransaction`;return this.httpClient.post(a,{transaction:t},{headers:this.getBasicHeaders()}).then(o=>y.handleResponse(o))}refundPayment(t,a,o,n){const i=`_action/${this.getApiBasePath()}/refund`;return this.httpClient.post(i,{transaction:t,transactionsToRefund:a,orderItems:o,customRefundAmount:n},{headers:this.getBasicHeaders()}).then(d=>y.handleResponse(d))}captureOrder(t){const a=`_action/${this.getApiBasePath()}/capture`;return this.httpClient.post(a,{transaction:t},{headers:this.getBasicHeaders()}).then(o=>y.handleResponse(o))}createPaylink(t){const a=`_action/${this.getApiBasePath()}/paylink`;return this.httpClient.post(a,{transaction:t},{headers:this.getBasicHeaders()}).then(o=>y.handleResponse(o))}klarnaMor(t,a){const o=`_action/${this.getApiBasePath()}/klarna-mor`;return this.httpClient.post(o,{orderId:t,action:a},{headers:this.getBasicHeaders()}).then(n=>y.handleResponse(n))}}Shopware.Service().register("BuckarooPaymentService",()=>{const e=Shopware.Application.getContainer("init"),t=Shopware.Service("loginService");return new H(e.httpClient,t)});const{ApiService:b}=Shopware.Classes;class K extends b{constructor(t,a,o="buckaroo"){super(t,a,o)}getBasicHeaders(){return this.loginService&&typeof this.loginService.getToken=="function"?super.getBasicHeaders():{"Content-Type":"application/json",Accept:"application/json"}}getSupportVersion(){const t=`_action/${this.getApiBasePath()}/version`;return this.httpClient.post(t,{},{headers:this.getBasicHeaders()}).then(a=>b.handleResponse(a))}getTaxes(){const t=`_action/${this.getApiBasePath()}/taxes`;return this.httpClient.post(t,{},{headers:this.getBasicHeaders()}).then(a=>b.handleResponse(a))}getIn3Icons(){const t=`_action/${this.getApiBasePath()}/in3/logos`;return this.httpClient.post(t,{},{headers:this.getBasicHeaders()}).then(a=>b.handleResponse(a))}getApiTest(t,a,o){const n=`_action/${this.getApiBasePath()}/getBuckarooApiTest`;return this.httpClient.post(n,{websiteKeyId:t,secretKeyId:a,saleChannelId:o},{headers:this.getBasicHeaders()}).then(i=>b.handleResponse(i))}}Shopware.Service().register("BuckarooPaymentSettingsService",()=>{const e=Shopware.Application.getContainer("init"),t=Shopware.Service("loginService");return new K(e.httpClient,t)});const O=``,{Component:U}=Shopware;U.register("buckaroo-afterpay-old-tax",{template:O,inject:["BuckarooPaymentSettingsService"],data(){return{taxes:[],showTaxes:!1,afterpayTaxes:[{name:this.$tc("buckaroo-payment.afterpay.hightTaxes"),id:1},{name:this.$tc("buckaroo-payment.afterpay.middleTaxes"),id:5},{name:this.$tc("buckaroo-payment.afterpay.lowTaxes"),id:2},{name:this.$tc("buckaroo-payment.afterpay.zeroTaxes"),id:3},{name:this.$tc("buckaroo-payment.afterpay.noTaxes"),id:4}],taxAssociation:{}}},model:{prop:"value",event:"change"},computed:{},props:{name:{type:String,required:!0,default:""},value:{type:Object,required:!1,default(){return{}}}},created(){this.BuckarooPaymentSettingsService.getTaxes().then(e=>{this.taxes=e.taxes.map(t=>({id:t.id,name:t.name}))})},methods:{setTaxAssociation(e,t){try{let a=t;t&&typeof t=="object"&&(t.target?a=t.target.value:t.hasOwnProperty("value")?a=t.value:t.hasOwnProperty("id")&&(a=t.id)),this.taxAssociation[e]=a,this.$emit("change",{...this.value,...this.taxAssociation})}catch(a){console.error("Error in setTaxAssociation:",a)}},getSelectValue(e){if(this.value[e])return this.value[e]}}});const G=`
`,{Component:W}=Shopware;W.register("buckaroo-main-config",{template:G,props:{configSettings:{type:Array,required:!1,default:()=>[]},value:{type:Object,required:!1,default:()=>({})},elementMethods:{type:Object,required:!1,default:()=>({})},isNotDefaultSalesChannel:{type:Boolean,required:!1,default:!1},currentSalesChannelId:{type:String,required:!1,default:null}},emits:["input"],model:{prop:"value",event:"input"},data(){var e;return{selectedCard:((e=this.$route.params)==null?void 0:e.paymentCode)||"general"}},watch:{value:{handler(e,t){this.$nextTick(()=>{this.$forceUpdate()})},deep:!0,immediate:!0},$route(e){var t;(t=e.params)!=null&&t.paymentCode&&(this.selectedCard=e.params.paymentCode)}},computed:{mainCard(){var t;return(t=this.configSettings.filter(a=>a.name===this.selectedCard))==null?void 0:t.pop()}},methods:{onInput(e){this.$emit("input",e)}}});const Z=`{% block buckaroo_config_card %}
{% endblock %}`,{Component:J}=Shopware;J.register("buckaroo-config-card",{template:Z,inject:["BuckarooPaymentSettingsService"],data(){return{shopwareVersion:null}},mounted(){this.fetchShopwareVersion(),this.$nextTick(()=>{this.$forceUpdate()})},watch:{value:{handler(){this.$nextTick(()=>{this.$forceUpdate()})},deep:!0,immediate:!0},currentSalesChannelId:{handler(e,t){e!==t&&this.$nextTick(()=>{this.$forceUpdate()})},immediate:!1}},computed:{canShowCredentialTester(){var d;const e=this.getValueForName("websiteKey"),t=this.getValueForName("secretKey");if(!(((d=this.card)==null?void 0:d.name)==="general"))return!1;const o=e!=null&&e!=="",n=t!=null&&t!=="";return o||n},hasValidConfigData(){return this.value&&typeof this.value=="object"&&Object.keys(this.value).length>0},reactiveValue(){return this.value}},emits:["input"],model:{prop:"value",event:"input"},props:{card:{type:Object,required:!1,default:()=>({elements:[]})},configSettings:{type:Array,required:!1,default:()=>[]},methods:{type:Object,required:!0},isNotDefaultSalesChannel:{type:Boolean,required:!0},currentSalesChannelId:{type:String,required:!0},value:{type:Object,required:!1,default:()=>({})}},methods:{fetchShopwareVersion(){const e=this.BuckarooPaymentSettingsService;e&&typeof e.getSupportVersion=="function"&&e.getSupportVersion().then(t=>{t&&t.shopware_version&&(this.shopwareVersion=t.shopware_version)}).catch(()=>{})},isShopware674OrNewer(){if(!this.shopwareVersion||typeof this.shopwareVersion!="string")return!1;const e=this.shopwareVersion.split(".").map(i=>parseInt(i,10)||0),t=e[0]||0,a=e[1]||0,o=e[2]||0,n=e[3]||0;return t>6?!0:t<6?!1:a>7?!0:a<7?!1:o>4?!0:o<4?!1:n>=0},getElementBind(e,t={}){var v,c,k,f,h,m,C;if(!this.methods||!this.methods.getElementBind){const u=e.label?this.getInlineSnippet(e.label):null;return{name:e.name,type:e.type||"text",config:e.config||{},label:u,value:this.getValueForName(e.name.replace("BuckarooPayments.config.",""))}}const a=this.methods.getElementBind(e,t),o=e.name.replace("BuckarooPayments.config.","");let n=this.getValueForName(o);const i=a.config||e.config||{};e.type==="bool"&&(n==null?n=a.value!==void 0?a.value:!1:typeof n=="string"?n=n==="1"||n==="true"||n==="on":n=!!n);let d=null;const g=this.isShopware674OrNewer();if(g){if((e.type==="bool"||e.type==="single-select"||e.type==="multi-select")&&this.configSettings&&Array.isArray(this.configSettings)){for(const u of this.configSettings)if(u.elements&&Array.isArray(u.elements)){const l=u.elements.find(p=>p.name===e.name);if(l){if(l.label){let p=this.getInlineSnippet(l.label);if(!p||typeof p=="string"&&p.trim().length===0)if(typeof l.label=="object"&&l.label!==null){const w=((v=this.$i18n)==null?void 0:v.locale)||"en-GB";p=l.label[w]||l.label["en-GB"]||Object.values(l.label)[0]||null}else typeof l.label=="string"&&(p=l.label);if(p&&typeof p=="string"&&p.trim().length>0){d=p;break}}if(!d&&l.config&&l.config.label){let p=this.getInlineSnippet(l.config.label);if(!p||typeof p=="string"&&p.trim().length===0)if(typeof l.config.label=="object"&&l.config.label!==null){const w=((c=this.$i18n)==null?void 0:c.locale)||"en-GB";p=l.config.label[w]||l.config.label["en-GB"]||Object.values(l.config.label)[0]||null}else typeof l.config.label=="string"&&(p=l.config.label);if(p&&typeof p=="string"&&p.trim().length>0){d=p;break}}}}}if(!d){if(a.label&&typeof a.label=="string"&&a.label.trim().length>0)d=a.label;else if(e.label){let u=this.getInlineSnippet(e.label);if(!u||typeof u=="string"&&u.trim().length===0)if(typeof e.label=="object"&&e.label!==null){const l=((k=this.$i18n)==null?void 0:k.locale)||"en-GB";u=e.label[l]||e.label["en-GB"]||Object.values(e.label)[0]||null}else typeof e.label=="string"&&(u=e.label);u&&typeof u=="string"&&u.trim().length>0&&(d=u)}else if(this.card&&this.card.elements&&Array.isArray(this.card.elements)){const u=this.card.elements.find(l=>l.name===e.name);if(u&&u.label){let l=this.getInlineSnippet(u.label);if(!l||typeof l=="string"&&l.trim().length===0)if(typeof u.label=="object"&&u.label!==null){const p=((f=this.$i18n)==null?void 0:f.locale)||"en-GB";l=u.label[p]||u.label["en-GB"]||Object.values(u.label)[0]||null}else typeof u.label=="string"&&(l=u.label);l&&typeof l=="string"&&l.trim().length>0&&(d=l)}}}!d&&a.config&&a.config.label&&typeof a.config.label=="string"&&a.config.label.trim().length>0&&(d=a.config.label)}let r=i;g&&d&&typeof d=="string"&&d.trim().length>0&&(e.type==="bool"||e.type==="single-select"||e.type==="multi-select")&&(r={...i,label:d});const s={...a,config:r};if(["allowedcreditcard","allowedcreditcards","allowedgiftcards","giftcardsPaymentmethods","payperemailAllowed"].includes(o)){s.type="multi-select",s.componentName="sw-multi-select",s.config={...s.config||{},multiple:!0,options:s.config&&s.config.options||i&&i.options||e.options||[]};const u=Array.isArray((h=s.config)==null?void 0:h.options)&&s.config.options.length>0?s.config.options[0]:null;console.debug("[BuckarooConfigCard] getElementBind multi-select binding",{fieldName:o,bindingType:s.type,componentName:s.componentName,optionsCount:Array.isArray((m=s.config)==null?void 0:m.options)?s.config.options.length:0,currentValue:n,sampleOption:u})}return g&&d&&typeof d=="string"&&d.trim().length>0&&(e.type==="bool"||!s.label||typeof s.label=="string"&&s.label.trim().length===0)&&(s.label=d),e.type==="bool"&&(s.value=n,g&&(!s.label||typeof s.label=="string"&&s.label.trim().length===0)&&(s.label=((C=s.config)==null?void 0:C.label)||e.name.replace("BuckarooPayments.config.","").replace(/([A-Z])/g," $1").trim())),(e.type==="bool"||e.type==="single-select"||e.type==="multi-select")&&(!s.label||typeof s.label=="string"&&s.label.trim().length===0)&&console.warn("Missing label for field:",e.name,"Type:",e.type,"Element label:",e.label,"Extracted:",d,"BaseBinding label:",a.label,"Final binding label:",s.label),s},getInheritWrapperBind(e){if(!this.methods||!this.methods.getInheritWrapperBind){const n=e.name.replace("BuckarooPayments.config.","");return{name:e.name,currentValue:this.getValueForName(n)}}const t=this.methods.getInheritWrapperBind(e),a=e.name.replace("BuckarooPayments.config.",""),o=this.getValueForName(a);return t.currentValue=o,t},getFieldError(e){return!this.methods||!this.methods.getFieldError?null:this.methods.getFieldError(e)},kebabCase(e){return!this.methods||!this.methods.kebabCase?e?e.toLowerCase().replace(/[A-Z]/g,"-$&").replace(/^-/,""):"":this.methods.kebabCase(e)},getInlineSnippet(e){var t;try{if(typeof e=="object"&&e!==null){const a=((t=this.$i18n)==null?void 0:t.locale)||"en-GB";if(e[a])return e[a];if(e["en-GB"])return e["en-GB"];const o=Object.keys(e)[0];return o&&e[o]?e[o]:JSON.stringify(e)}return typeof e=="string"?this.$t&&typeof this.$t=="function"?this.$t(e):e:String(e)}catch(a){return console.warn("Translation error for:",e,a),typeof e=="object"?JSON.stringify(e):String(e)}},getInheritedValue(e){return!this.methods||!this.methods.getInheritedValue?null:this.methods.getInheritedValue(e)},getValueForName(e){const t=this.reactiveValue;if(!t||typeof t!="object")return null;let a;const o=[`BuckarooPayments.config.${e}`,e.toLowerCase(),e.charAt(0).toLowerCase()+e.slice(1),e.charAt(0).toUpperCase()+e.slice(1)];for(const n of o)if(t[n]!==void 0){a=t[n];break}if(a===void 0&&t["BuckarooPayments.config"]&&typeof t["BuckarooPayments.config"]=="object"){for(const n of o)if(t["BuckarooPayments.config"][n]!==void 0){a=t["BuckarooPayments.config"][n];break}}return a&&typeof a=="object"&&a.hasOwnProperty("_value")&&(a=a._value),a},canShow(e){if(!e||!e.name)return!1;const t=e.name.replace("BuckarooPayments.config.","");return["orderStatus","paymentSuccesStatus","automaticallyCloseOpenOrders","sendInvoiceEmail"].includes(t)?!!this.getValueForName("advancedConfiguration"):t==="idealprocessingRenderMode"?!!this.getValueForName("idealprocessingShowissuers"):t==="idealRenderMode"?!!this.getValueForName("idealShowissuers"):["idealFastCheckoutEnabled","idealFastCheckoutVisibility","idealFastCheckoutLogoScheme"].includes(t)?!!this.getValueForName("idealFastCheckout"):t==="afterpayPaymentstatus"?!!this.getValueForName("afterpayCaptureonshippent"):t==="afterpayOldtax"?!!this.getValueForName("afterpayEnabledold"):!0},onInput(e){this.$emit("input",e)},onFieldInput(e,t){var a,o;try{let n=t;if(t&&typeof t=="object")if(t.target){const r=t.target;r.type==="checkbox"||r.type==="radio"?n=r.checked:(r.tagName==="SELECT"||r.type==="select-one"||r.type==="select-multiple")&&r.multiple?n=Array.from(r.selectedOptions).map(s=>s.value):n=r.value}else if(t.hasOwnProperty("value"))n=t.value;else if(t.hasOwnProperty("id")&&t.hasOwnProperty("name"))n=t.id;else if(Array.isArray(t)){const r=t.filter(c=>typeof c=="string"&&c.length===1).length,s=t.some(c=>c===","),B=t.some(c=>typeof c=="string"&&c.length>1);if(r>10&&s){const c=t.filter(m=>typeof m=="string"&&m.length>1),f=t.filter(m=>typeof m=="string"&&m.length===1).join("");let h=[];f.includes(",")?h=f.split(",").map(m=>m.trim()).filter(m=>m.length>0):f.length>0&&(h=[f]),n=[...h,...c].filter(m=>m&&m.length>0)}else n=t.filter(c=>!(c==null||c===""||typeof c=="string"&&c.length===1||typeof c=="string"&&(c.startsWith("+")||/^\d+$/.test(c)))).map(c=>typeof c=="object"&&c!==null&&(c.id||c.value||c.code||c.key)||c)}else{const r=["id","value","key","code"];for(const s of r)if(t[s]!==void 0){n=t[s];break}}else(typeof t=="boolean"||typeof t=="string"||typeof t=="number")&&(n=t);const i=(o=(a=this.card)==null?void 0:a.elements)==null?void 0:o.find(r=>r.name===e||r.name.replace("BuckarooPayments.config.","")===e.replace("BuckarooPayments.config.",""));n==="on"?n=!0:n==="off"&&(n=!1),i&&i.type==="bool"&&(typeof n=="string"?n=n==="1"||n==="true"||n==="on":n=!!n),i&&i.type==="multi-select"&&(console.debug("[BuckarooConfigCard] onFieldInput before normalize (multi-select)",{fieldName:e,rawEvent:t,rawValue:n}),Array.isArray(n)?n=n.filter(r=>r!=null&&r!=="").map(r=>typeof r=="object"&&r!==null&&(r.id||r.value||r.code||r.key)||r):typeof n=="string"?n=n.split(",").map(r=>r.trim()).filter(r=>r.length>0):n==null?n=[]:n=[n],console.debug("[BuckarooConfigCard] onFieldInput after normalize (multi-select)",{fieldName:e,normalizedValue:n}));const d=e.replace("BuckarooPayments.config.",""),g={...this.value};g[d]=n,g[e]=n,this.$emit("input",g)}catch(n){console.error("Error in onFieldInput:",n),console.error("Error details:",n.stack)}}}});const Y=`
`,{Component:Q,Filter:X}=Shopware;Q.register("buckaroo-payment-list",{template:Y,props:{configSettings:{type:Array,required:!1,default:()=>[]},value:{type:Object,required:!1,default:()=>({})},currentSalesChannelId:{type:String,required:!0}},emits:["input"],data(){return{payments:[{code:"Alipay",logo:"alipay.svg"},{code:"applepay",logo:"applepay.svg"},{code:"googlepay",logo:"googlepay.svg"},{code:"bancontactmrcash",logo:"bancontact.svg"},{code:"blik",logo:"blik.svg"},{code:"belfius",logo:"belfius.svg"},{code:"Billink",logo:"billink.svg"},{code:"creditcard",logo:"creditcards.svg"},{code:"creditcards",logo:"creditcards.svg"},{code:"eps",logo:"eps.svg"},{code:"giftcards",logo:"giftcards.svg"},{code:"idealqr",logo:"ideal-qr.svg"},{code:"ideal",logo:"ideal-wero.svg"},{code:"capayable",logo:"in3.svg"},{code:"KBCPaymentButton",logo:"kbc.svg"},{code:"klarna",logo:"klarna.svg"},{code:"klarnakp",logo:"klarna.svg"},{code:"mbway",logo:"mbway.svg"},{code:"multibanco",logo:"multibanco.svg"},{code:"paybybank",logo:"paybybank.svg"},{code:"payconiq",logo:"payconiq.svg"},{code:"paypal",logo:"paypal.svg"},{code:"payperemail",logo:"payperemail.svg"},{code:"Przelewy24",logo:"przelewy24.svg"},{code:"afterpay",logo:"afterpay.svg"},{code:"sepadirectdebit",logo:"sepa-directdebit.svg"},{code:"transfer",logo:"sepa-credittransfer.svg"},{code:"Trustly",logo:"trustly.svg"},{code:"WeChatPay",logo:"wechatpay.svg"},{code:"swish",logo:"swish.svg"},{code:"bizum",logo:"bizum.svg"},{code:"twint",logo:"twint.svg"},{code:"wero",logo:"wero.svg"}]}},methods:{getPaymentTitle(e){var a;if(this.configSettings&&Array.isArray(this.configSettings)){const o=this.configSettings.find(n=>n.name===e);if(o&&o.title)try{if(typeof o.title=="object"&&o.title!==null){const n=((a=this.$i18n)==null?void 0:a.locale)||"en-GB";if(o.title[n])return o.title[n];if(o.title["en-GB"])return o.title["en-GB"];const i=Object.keys(o.title)[0];return i&&o.title[i]?o.title[i]:JSON.stringify(o.title)}return typeof o.title=="string"?this.$t&&typeof this.$t=="function"?this.$t(o.title):o.title:String(o.title)}catch(n){return console.warn("Translation error for:",o.title,n),typeof o.title=="object"?JSON.stringify(o.title):String(o.title)}}const t=this.payments.find(o=>o.code===e);return t?t.code:"Unknown Payment"},assetFilter(e){return X.getByName("asset")(e)}}});const ee=`{{ $tc('buckaroo-payment.button.labelTestApi') }}`,{Component:te}=Shopware;te.register("buckaroo-test-credentials",{template:ee,mixins:[Shopware.Mixin.getByName("notification")],data(){return{isLoading:!1}},inject:["BuckarooPaymentSettingsService"],props:{config:{type:Object,required:!0},currentSalesChannelId:{required:!0}},computed:{enabled:function(){return(this.getConfigValue("websiteKey")||"").length>0&&(this.getConfigValue("secretKey")||"").length>0}},methods:{getConfigValue:function(e){return this.config["BuckarooPayments.config."+e]},sendTestApi(){this.isLoading=!0;let e=this.getConfigValue("websiteKey"),t=this.getConfigValue("secretKey");this.BuckarooPaymentSettingsService.getApiTest(e,t,this.currentSalesChannelId).then(a=>{this.isLoading=!1,a.status=="success"?this.createNotificationSuccess({title:this.$tc("buckaroo-payment.settingsForm.titleSuccess"),message:this.$tc(a.message)}):this.createNotificationError({title:this.$tc("buckaroo-payment.settingsForm.titleError"),message:this.$tc(a.message)})}).catch(()=>{this.isLoading=!1})}}});const ae=`
`,{Component:ne}=Shopware;ne.register("buckaroo-toggle-status",{template:ae,props:{method:{type:String,required:!0},value:{required:!0},currentSalesChannelId:{required:!0}},emits:["input"],inject:["systemConfigApiService"],data(){return{status:"disabled",isLoading:!1}},mounted(){this.status=this.getStatus()},watch:{value:{handler(e){this.status=this.getStatus()},deep:!0,immediate:!0}},methods:{getStatus(){const e=this.isActive(),t=this.getEnvironment();return e?t:"disabled"},isActive(){const e=this.getValueForName(`${this.method}Enabled`);return typeof e=="string"?e.toLowerCase()==="true":!!e},getEnvironment(){const e=this.getValueForName(`${this.method}Environment`);return e==null||e===""?"test":["test","live"].includes(e)?e:"test"},getValueForName(e){const t=`BuckarooPayments.config.${e}`;if(!this.value||typeof this.value!="object")return null;let a;if(this.value[t]!==void 0)a=this.value[t];else if(this.value[e]!==void 0)a=this.value[e];else if(this.value["BuckarooPayments.config"]&&typeof this.value["BuckarooPayments.config"]=="object")this.value["BuckarooPayments.config"][e]!==void 0&&(a=this.value["BuckarooPayments.config"][e]);else{const o=[e,e.toLowerCase(),e.charAt(0).toLowerCase()+e.slice(1),e.charAt(0).toUpperCase()+e.slice(1)];for(const n of o){const i=`BuckarooPayments.config.${n}`;if(this.value[i]!==void 0){a=this.value[i];break}if(this.value[n]!==void 0){a=this.value[n];break}}}return a&&typeof a=="object"&&a.hasOwnProperty("_value")&&(a=a._value),a},setStatus(e){this.status=e,this.saveStatus()},getClass(e){return this.status===e?"active":""},async saveStatus(){const e=`BuckarooPayments.config.${this.method}Enabled`,t=`BuckarooPayments.config.${this.method}Environment`;let a={[e]:!1};const o={...this.value};o[e]=!1,["live","test"].indexOf(this.status)!==-1&&(a={[e]:!0,[t]:this.status},o[e]=!0,o[t]=this.status),this.$emit("input",o),this.isLoading=!0;try{await this.systemConfigApiService.batchSave({[this.currentSalesChannelId]:a}).finally(()=>{this.isLoading=!1}),this.renderSuccess()}catch(n){this.renderError(n)}},renderSuccess(){this.$store.dispatch("notification/createNotification",{variant:"success",message:this.$tc("sw-extension-store.component.sw-extension-config.messageSaveSuccess")})},renderError(e){this.$store.dispatch("notification/createNotification",{variant:"error",message:e})}}}); +//# sourceMappingURL=buckaroo-payments-CjP84r_i.js.map diff --git a/src/Resources/public/administration/assets/buckaroo-payments-CjP84r_i.js.map b/src/Resources/public/administration/assets/buckaroo-payments-CjP84r_i.js.map new file mode 100644 index 00000000..51ff4f18 --- /dev/null +++ b/src/Resources/public/administration/assets/buckaroo-payments-CjP84r_i.js.map @@ -0,0 +1 @@ +{"version":3,"file":"buckaroo-payments-CjP84r_i.js","sources":["../../../app/administration/src/module/buckaroo-payment/extension/sw-order/sw-order.html.twig","../../../app/administration/src/module/buckaroo-payment/extension/sw-order/index.js","../../../app/administration/src/module/buckaroo-payment/extension/sw-order-detail-base/sw-order-detail-base.html.twig","../../../app/administration/src/module/buckaroo-payment/extension/sw-order-detail-base/index.js","../../../app/administration/src/module/buckaroo-payment/extension/sw-order-user-card/sw-order-user-card.html.twig","../../../app/administration/src/module/buckaroo-payment/extension/sw-order-user-card/index.js","../../../app/administration/src/module/buckaroo-payment/extension/sw-system-config/sw-system-config.html.twig","../../../app/administration/src/module/buckaroo-payment/extension/sw-system-config/index.js","../../../app/administration/src/module/buckaroo-payment/page/buckaroo-payment-detail/buckaroo-payment-detail.html.twig","../../../app/administration/src/module/buckaroo-payment/page/buckaroo-payment-detail/index.js","../../../app/administration/src/module/buckaroo-payment/page/buckaroo-payment-config/index.js","../../../app/administration/src/module/buckaroo-payment/index.js","../../../app/administration/src/api/buckaroo-payment.service.js","../../../app/administration/src/api/buckaroo-payment-settings.service.js","../../../app/administration/src/components/buckaroo-afterpay-old-tax/buckaroo-afterpay-old-tax.html.twig","../../../app/administration/src/components/buckaroo-afterpay-old-tax/index.js","../../../app/administration/src/components/buckaroo-main-config/buckaroo-main-config.html.twig","../../../app/administration/src/components/buckaroo-main-config/index.js","../../../app/administration/src/components/buckaroo-config-card/buckaroo-config-card.html.twig","../../../app/administration/src/components/buckaroo-config-card/index.js","../../../app/administration/src/components/buckaroo-payment-list/buckaroo-payment-list.html.twig","../../../app/administration/src/components/buckaroo-payment-list/index.js","../../../app/administration/src/components/buckaroo-test-credentials/buckaroo-test-credentials.twig","../../../app/administration/src/components/buckaroo-test-credentials/index.js","../../../app/administration/src/components/buckaroo-toggle-status/buckaroo-toggle-status.html.twig","../../../app/administration/src/components/buckaroo-toggle-status/index.js"],"sourcesContent":["{% block sw_order_detail_content_tabs %}\n \n
\n

{{ $tc('buckaroo-payment.paymentInTestMode') }}

\n \n {% parent %}\n{% endblock %}\n\n\n{% block sw_order_detail_content_tabs_general %}\n {% parent %}\n\n \n {{ $tc('buckaroo-payment.tabs.title') }}\n \n \n{% endblock %}\n\n{% block sw_order_detail_actions %}\n \n {% parent %}\n{% endblock %}","import template from './sw-order.html.twig';\n\nconst { Component, Context } = Shopware;\nconst Criteria = Shopware.Data.Criteria;\n\nComponent.override('sw-order-detail', {\n template,\n\n data() {\n return {\n isBuckarooPayment: false,\n isPaymentInTestMode: false\n };\n },\n\n computed: {\n isEditable() {\n return !this.isBuckarooPayment || this.$route.name !== 'buckaroo.payment.detail';\n },\n\n showTabs() {\n return true;\n }\n },\n\n watch: {\n orderId: {\n deep: true,\n handler() {\n if (!this.orderId) {\n this.setIsBuckarooPayment(null);\n return;\n }\n\n const orderRepository = this.repositoryFactory.create('order');\n const orderCriteria = new Criteria(1, 1);\n orderCriteria.addAssociation('transactions');\n\n orderRepository.get(this.orderId, Context.api, orderCriteria).then((order) => {\n\n this.setPaymentInTestMode(order);\n\n if (order.transactions.length <= 0 ||\n !order.transactions.last().paymentMethodId\n ) {\n this.setIsBuckarooPayment(null);\n return;\n }\n\n const paymentMethodId = order.transactions.last().paymentMethodId;\n\n if (paymentMethodId !== undefined && paymentMethodId !== null) {\n this.setIsBuckarooPayment(paymentMethodId);\n }\n });\n },\n immediate: true\n }\n },\n\n methods: {\n setPaymentInTestMode(order) {\n if (order.customFields && order.customFields.buckaroo_payment_in_test_mode) {\n this.isPaymentInTestMode = order.customFields.buckaroo_payment_in_test_mode === true;\n }\n },\n setIsBuckarooPayment(paymentMethodId) {\n if (!paymentMethodId) {\n return;\n }\n const paymentMethodRepository = this.repositoryFactory.create('payment_method');\n paymentMethodRepository.get(paymentMethodId, Context.api).then(\n (paymentMethod) => {\n this.isBuckarooPayment = paymentMethod.formattedHandlerIdentifier.indexOf('buckaroo') >= 0;\n }\n );\n }\n }\n});","{% block sw_order_detail_base_line_items_summary %}\n\n \n 0\">\n \n
{{ $tc('buckaroo-payment.fee') }}
\n
{{ order.customFields.buckarooFee }}\n {% if order.currency.isoCode == \"PLN\" %}\n PLN\n {% else %}\n {{ order.currency.symbol }}\n {% endif %}\n
\n
\n
\n
\n\n {% parent %}\n \n{% endblock %}","import template from './sw-order-detail-base.html.twig';\n\nconst { Component, Context } = Shopware;\nconst Criteria = Shopware.Data.Criteria;\n\nComponent.override('sw-order-detail-base', {\n template\n});\n","{% block sw_order_detail_base_secondary_info_payment %}\n \n \n{% endblock %}\n\n","import template from './sw-order-user-card.html.twig';\n\nconst { Component } = Shopware;\n\nComponent.override('sw-order-user-card', {\n template,\n\n inject: [ 'systemConfigApiService' ],\n\n data() {\n return {\n config: {}\n };\n },\n\n created() {\n this.systemConfigApiService.getValues('BuckarooPayments.config', null)\n .then(values => {\n this.config = values;\n })\n .finally(() => {\n });\n }\n\n});\n"," {% block sw_system_config_content_card %}\n \n \n {% endblock %}"," import template from './sw-system-config.html.twig';\n\nconst { Component } = Shopware;\n\nComponent.override('sw-system-config', {\n template,\n \n watch: {\n currentSalesChannelId: {\n handler(newVal, oldVal) {\n if (newVal && this.domain === 'BuckarooPayments.config') {\n this.loadBuckarooConfigData();\n }\n },\n immediate: true\n },\n domain: {\n handler(newVal) {\n if (newVal === 'BuckarooPayments.config' && this.currentSalesChannelId) {\n this.loadBuckarooConfigData();\n }\n },\n immediate: true\n }\n },\n\n methods: {\n loadBuckarooConfigData() {\n \n this.systemConfigApiService.getValues('BuckarooPayments.config', this.currentSalesChannelId)\n .then(response => {\n \n if (!this.actualConfigData[this.currentSalesChannelId]) {\n this.actualConfigData[this.currentSalesChannelId] = {};\n }\n\n const processedData = {};\n \n if (response && typeof response === 'object') {\n Object.keys(response).forEach(key => {\n const value = response[key];\n\n if (value && typeof value === 'object' && value.hasOwnProperty('_value')) {\n processedData[key] = value._value;\n } else {\n processedData[key] = value;\n }\n\n const shortKey = key.replace('BuckarooPayments.config.', '');\n if (shortKey !== key) {\n processedData[shortKey] = processedData[key];\n }\n });\n }\n\n this.actualConfigData[this.currentSalesChannelId] = {};\n Object.keys(processedData).forEach(key => {\n this.actualConfigData[this.currentSalesChannelId][key] = processedData[key];\n });\n\n this.$nextTick(() => {\n this.$forceUpdate();\n });\n })\n .catch(error => {\n console.error('Error fetching system config:', error);\n });\n },\n\n onConfigDataUpdate(newValue) {\n if (!this.actualConfigData[this.currentSalesChannelId]) {\n this.actualConfigData[this.currentSalesChannelId] = {};\n }\n Object.keys(newValue).forEach(key => {\n this.actualConfigData[this.currentSalesChannelId][key] = newValue[key];\n if (!key.startsWith('BuckarooPayments.config.')) {\n const fullFieldName = `BuckarooPayments.config.${key}`;\n this.actualConfigData[this.currentSalesChannelId][fullFieldName] = newValue[key];\n }\n });\n },\n\n saveAll() {\n if (this.domain !== 'BuckarooPayments.config') {\n return this.$super('saveAll');\n }\n return this.saveBuckaroo();\n },\n \n saveBuckaroo() {\n this.isLoading = true;\n return this.systemConfigApiService\n .batchSave(this.getSelectedValues())\n .finally(() => {\n this.isLoading = false;\n });\n },\n \n getCurrentConfigCard() {\n const code = this.$route.params?.paymentCode || 'general';\n return this.config.filter((card) => card.name === code)?.pop();\n },\n \n getSelectedValues() {\n const currentConfigValues = this.actualConfigData[this.currentSalesChannelId];\n const currentPaymentCard = this.getCurrentConfigCard();\n\n if (currentPaymentCard?.elements) {\n let actualConfigValues = {};\n currentPaymentCard?.elements.forEach((element) => {\n if (element?.name) {\n let value = currentConfigValues[element.name];\n\n if (value === undefined) {\n const cleanFieldName = element.name.replace('BuckarooPayments.config.', '');\n value = currentConfigValues[cleanFieldName];\n }\n \n actualConfigValues[element.name] = value;\n }\n });\n return { [this.currentSalesChannelId]: actualConfigValues };\n }\n\n return this.actualConfigData;\n }\n }\n});\n","{% block buckaroo_payment_detail %}\n
\n \n \n\n {{ $tc('buckaroo-payment.paymentDetail.paylinkDescription') }}\n \n
\n {{ $tc('buckaroo-payment.paymentDetail.yourLink') }}: {{ paylink }}\n
\n\n \n
\n \n \n {{ $tc('buckaroo-payment.paymentDetail.paylinkButton') }}\n
\n
\n
\n\n
\n\n \n \n {{ $tc('buckaroo-payment.orderItems.title') }}\n \n\n \n \n\n \n\n \n \n
{{ $tc('buckaroo-payment.paymentDetail.amountTotalTitle') }}:
\n
{{ buckaroo_refund_amount }} {{ currency }}
\n
\n
\n \n \n \n \n\n \n\n \n\n \n\n \n\n \n \n
{{ $tc('buckaroo-payment.paymentDetail.amountCustomRefundTitle') }}:
\n
\n \n {{ currency }}\n
\n
\n \n
{{ $tc('buckaroo-payment.paymentDetail.amountRefundTotalTitle') }}:
\n
{{ buckaroo_refund_total_amount }} {{ currency }}
\n
\n
\n \n
\n\n \n
\n \n {{ $tc('buckaroo-payment.paymentDetail.buttonTitle') }}\n
\n
\n
\n\n
\n\n \n\n {{ $tc('buckaroo-payment.paymentDetail.payDescription') }}\n\n \n
\n \n {{ $tc('buckaroo-payment.paymentDetail.payButton') }}\n
\n
\n
\n\n
\n\n \n\n {{ $tc('buckaroo-payment.paymentDetail.klarnaMorDescription') }}\n\n \n \n
{{ $tc('buckaroo-payment.paymentDetail.klarnaMorCancel') }}
\n
\n \n {{ $tc('buckaroo-payment.paymentDetail.klarnaMorCancelButton') }}\n \n
\n
\n
\n\n \n \n
{{ $tc('buckaroo-payment.paymentDetail.klarnaMorUpdate') }}
\n
\n \n {{ $tc('buckaroo-payment.paymentDetail.klarnaMorUpdateButton') }}\n \n
\n
\n
\n\n \n \n
{{ $tc('buckaroo-payment.paymentDetail.klarnaMorExtend') }}
\n
\n \n {{ $tc('buckaroo-payment.paymentDetail.klarnaMorExtendButton') }}\n \n
\n
\n
\n\n \n \n
{{ $tc('buckaroo-payment.paymentDetail.klarnaMorShipping') }}
\n
\n \n {{ $tc('buckaroo-payment.paymentDetail.klarnaMorShippingButton') }}\n \n
\n
\n
\n\n
\n\n \n \n\n \n\n \n \n\n\n \n \n
\n{% endblock %}","import template from './buckaroo-payment-detail.html.twig';\nimport './buckaroo-payment-detail.scss';\n\nconst { Component, Filter, Context } = Shopware;\nconst Criteria = Shopware.Data.Criteria;\n\nComponent.register('buckaroo-payment-detail', {\n template,\n\n inject: [\n 'repositoryFactory',\n 'BuckarooPaymentService',\n 'systemConfigApiService'\n ],\n\n data() {\n return {\n config: {},\n buckaroo_refund_amount: '0',\n buckaroo_refund_total_amount: '0',\n currency: 'EUR',\n isRefundPossible: true,\n isCapturePossible: false,\n isPaylinkAvailable: false,\n isPaylinkVisible: false,\n paylinkMessage: '',\n paylink: '',\n isLoading: false,\n order: false,\n buckarooTransactions: null,\n orderItems: [],\n transactionsToRefund: [],\n relatedResources: [],\n isAuthorized: false,\n isKlarnaMor: false,\n fulfillmentMessage: '',\n fulfillmentStatus: null\n };\n },\n\n computed: {\n orderItemsColumns() {\n return [\n {\n property: 'name',\n label: this.$tc('buckaroo-payment.orderItems.types.name'),\n allowResize: false,\n primary: true,\n inlineEdit: true,\n multiLine: true,\n },\n {\n property: 'quantity',\n label: this.$tc('buckaroo-payment.orderItems.types.quantity'),\n rawData: true,\n align: 'right'\n },\n {\n property: 'totalAmount',\n label: this.$tc('buckaroo-payment.orderItems.types.totalAmount'),\n rawData: true,\n align: 'right'\n }\n ];\n },\n\n transactionsToRefundColumns() {\n return [\n {\n property: 'transaction_method',\n rawData: true\n },{\n property: 'amount',\n rawData: true\n }\n ];\n },\n\n relatedResourceColumns() {\n return [\n {\n property: 'created_at',\n label: this.$tc('buckaroo-payment.transactionHistory.types.created_at'),\n rawData: true\n },\n {\n property: 'total',\n label: this.$tc('buckaroo-payment.transactionHistory.types.total'),\n rawData: true\n },{\n property: 'shipping_costs',\n label: this.$tc('buckaroo-payment.transactionHistory.types.shipping_costs'),\n rawData: true\n },{\n property: 'total_excluding_vat',\n label: this.$tc('buckaroo-payment.transactionHistory.types.total_excluding_vat'),\n rawData: true\n },{\n property: 'vat',\n label: this.$tc('buckaroo-payment.transactionHistory.types.vat'),\n rawData: true\n },{\n property: 'transaction_key',\n label: this.$tc('buckaroo-payment.transactionHistory.types.transaction_key'),\n rawData: true\n },{\n property: 'transaction_method',\n label: this.$tc('buckaroo-payment.transactionHistory.types.transaction_method'),\n rawData: true\n },{\n property: 'statuscode',\n label: this.$tc('buckaroo-payment.transactionHistory.types.statuscode'),\n rawData: true\n }\n ];\n }\n },\n\n created() {\n this.createdComponent();\n },\n\n methods: {\n recalculateOrderItems() {\n this.buckaroo_refund_amount = 0;\n for (const key in this.orderItems) {\n this.orderItems[key]['totalAmount'] = parseFloat(parseFloat(this.orderItems[key]['unitPrice']) * parseFloat(this.orderItems[key]['quantity'] || 0)).toFixed(2);\n this.buckaroo_refund_amount = parseFloat(parseFloat(this.buckaroo_refund_amount) + parseFloat(this.orderItems[key]['totalAmount'])).toFixed(2);\n }\n },\n recalculateRefundItems() {\n this.buckaroo_refund_total_amount = 0;\n for (const key in this.transactionsToRefund) {\n if (this.transactionsToRefund[key]['amount']) {\n this.buckaroo_refund_total_amount = parseFloat(parseFloat(this.buckaroo_refund_total_amount) + parseFloat(this.transactionsToRefund[key]['amount'])).toFixed(2);\n }\n }\n },\n\n getCustomRefundEnabledEl() {\n return document.getElementById('buckaroo_custom_refund_enabled');\n },\n\n getCustomRefundAmountEl() {\n return document.getElementById('buckaroo_custom_refund_amount');\n },\n\n toggleCustomRefund() {\n if (this.getCustomRefundEnabledEl() && this.getCustomRefundAmountEl()) {\n this.getCustomRefundAmountEl().disabled = !this.getCustomRefundEnabledEl().checked;\n }\n },\n\n getCustomRefundAmount() {\n if (this.getCustomRefundEnabledEl() && this.getCustomRefundAmountEl() && this.getCustomRefundEnabledEl().checked) {\n return this.getCustomRefundAmountEl().value;\n }\n return 0;\n },\n\n createdComponent() {\n let that = this;\n const orderId = this.$route.params.id;\n\n this.systemConfigApiService.getValues('BuckarooPayments.config', null)\n .then(values => {\n this.config = values;\n });\n\n const orderRepository = this.repositoryFactory.create('order');\n const orderCriteria = new Criteria(1, 1);\n\n this.orderId = orderId;\n orderCriteria.addAssociation('transactions.paymentMethod')\n .addAssociation('transactions');\n\n orderCriteria.getAssociation('transactions').addSorting(Criteria.sort('createdAt'));\n\n orderRepository.get(orderId, Context.api, orderCriteria).then((order) => {\n that.checkedIsAuthorized(order);\n const buckarooKey = order.transactions &&\n order.transactions.last().paymentMethod &&\n order.transactions.last().paymentMethod.customFields &&\n order.transactions.last().paymentMethod.customFields.buckaroo_key\n ? order.transactions.last().paymentMethod.customFields.buckaroo_key.toLowerCase()\n : '';\n\n that.isCapturePossible = !!buckarooKey &&\n (['klarnakp', 'billink', 'afterpay', 'klarna', 'wero'].includes(buckarooKey) || that.isAfterpayCapturePossible(order));\n\n that.isKlarnaMor = buckarooKey === 'klarna';\n\n that.isPaylinkVisible = that.isPaylinkAvailable = this.getConfigValue('paylinkEnabled') && order.stateMachineState && order.stateMachineState.technicalName && order.stateMachineState.technicalName == 'open' && order.transactions && order.transactions.last().stateMachineState.technicalName == 'open';\n });\n\n this.BuckarooPaymentService.getBuckarooTransaction(orderId)\n .then((response) => {\n that.orderItems = [];\n that.transactionsToRefund = [];\n that.relatedResources = [];\n\n this.$emit('loading-change', false);\n\n if (response.orderItems && Array.isArray(response.orderItems)) {\n response.orderItems.forEach((element) => {\n that.orderItems.push({\n id: element.id,\n name: element.name,\n quantity: element.quantity,\n quantityMax: element.quantity,\n unitPrice: element.unitPrice.value,\n totalAmount: element.totalAmount.value,\n variations: element.variations || [],\n });\n });\n }\n\n // Use backend-calculated total (single source of truth)\n that.buckaroo_refund_amount = response.refundTotals ? response.refundTotals.totalAmount : 0;\n that.currency = response.refundTotals ? response.refundTotals.currency : 'EUR';\n\n if (response.transactionsToRefund && Array.isArray(response.transactionsToRefund)) {\n response.transactionsToRefund.forEach((element) => {\n that.transactionsToRefund.push({\n id: element.id,\n transactions: element.transactions,\n amount: element.total,\n amountMax: element.total,\n currency: element.currency,\n transaction_method: element.transaction_method,\n logo: element.transaction_method ? element.logo : null\n });\n that.currency = element.currency;\n });\n }\n that.recalculateRefundItems();\n\n if (response.transactions && Array.isArray(response.transactions)) {\n response.transactions.forEach((element) => {\n that.relatedResources.push({\n id: element.id,\n transaction_key: element.transaction,\n total: element.total,\n total_excluding_vat: element.total_excluding_vat,\n shipping_costs: element.shipping_costs,\n vat: element.vat,\n transaction_method: element.transaction_method,\n logo: element.transaction_method ? element.logo : null,\n created_at: element.created_at,\n statuscode: element.statuscode\n });\n });\n }\n\n })\n .catch((errorResponse) => {\n console.log('errorResponse', errorResponse);\n });\n\n },\n\n isAfterpayCapturePossible(order) {\n return order.customFields.buckaroo_is_authorize === true;\n },\n\n checkedIsAuthorized(order) {\n this.isAuthorized = order?.transactions?.last()?.stateMachineState?.technicalName === \"authorized\";\n },\n\n refundOrder(transaction, amount) {\n let that = this;\n that.isRefundPossible = false;\n this.BuckarooPaymentService.refundPayment(transaction, this.transactionsToRefund, this.orderItems, this.getCustomRefundAmount())\n .then((response) => {\n for (const key in response) {\n if (response[key].status) {\n this.$store.dispatch('notification/createNotification', {\n variant: 'success',\n title: that.$tc('buckaroo-payment.settingsForm.titleSuccess'),\n message: that.$tc(response[key].message) + response[key].amount\n });\n } else {\n this.$store.dispatch('notification/createNotification', {\n variant: 'error',\n title: that.$tc('buckaroo-payment.settingsForm.titleError'),\n message: that.$tc(response[key].message)\n });\n }\n }\n that.isRefundPossible = true;\n this.createdComponent();\n })\n .catch((errorResponse) => {\n this.$store.dispatch('notification/createNotification', {\n variant: 'error',\n title: this.$tc('buckaroo-payment.settingsForm.titleError'),\n message: errorResponse.response.data.message\n });\n that.isRefundPossible = true;\n });\n },\n\n createPaylink(transaction) {\n let that = this;\n that.isPaylinkAvailable = false;\n this.BuckarooPaymentService.createPaylink(transaction, this.transactionsToRefund, this.orderItems)\n .then((response) => {\n if (response.status) {\n that.paylinkMessage = that.$tc(response.message) + response.paylinkhref;\n that.paylink = response.paylink;\n this.$store.dispatch('notification/createNotification', {\n variant: 'success',\n title: that.$tc('buckaroo-payment.settingsForm.titleSuccess'),\n message: that.paylinkMessage\n });\n } else {\n this.$store.dispatch('notification/createNotification', {\n variant: 'error',\n title: that.$tc('buckaroo-payment.settingsForm.titleError'),\n message: that.$tc(response.message)\n });\n }\n that.isPaylinkAvailable = true;\n })\n .catch((errorResponse) => {\n this.$store.dispatch('notification/createNotification', {\n variant: 'error',\n title: this.$tc('buckaroo-payment.settingsForm.titleError'),\n message: errorResponse.response.data.message\n });\n that.isPaylinkAvailable = true;\n });\n },\n\n getConfigValue(field) {\n return this.config[`BuckarooPayments.config.${field}`];\n },\n\n captureOrder(transaction) {\n let that = this;\n that.isCapturePossible = false;\n this.BuckarooPaymentService.captureOrder(transaction, this.transactionsToRefund, this.orderItems)\n .then((response) => {\n if (response.status) {\n this.$store.dispatch('notification/createNotification', {\n variant: 'success',\n title: that.$tc('buckaroo-payment.settingsForm.titleSuccess'),\n message: response.message\n });\n } else {\n this.$store.dispatch('notification/createNotification', {\n variant: 'error',\n title: that.$tc('buckaroo-payment.settingsForm.titleError'),\n message: response.message\n });\n }\n that.isCapturePossible = true;\n this.createdComponent();\n })\n .catch((errorResponse) => {\n this.$store.dispatch('notification/createNotification', {\n variant: 'error',\n title: this.$tc('buckaroo-payment.settingsForm.titleError'),\n message: that.$tc(errorResponse.response.data.message)\n });\n that.isCapturePossible = true;\n });\n },\n\n klarnaMor(action) {\n let that = this;\n that.isLoading = true;\n this.BuckarooPaymentService.klarnaMor(this.orderId, action)\n .then((response) => {\n if (response.status) {\n this.$store.dispatch('notification/createNotification', {\n variant: 'success',\n title: that.$tc('buckaroo-payment.settingsForm.titleSuccess'),\n message: response.message\n });\n } else {\n this.$store.dispatch('notification/createNotification', {\n variant: 'error',\n title: that.$tc('buckaroo-payment.settingsForm.titleError'),\n message: response.message\n });\n }\n that.isLoading = false;\n this.createdComponent();\n })\n .catch((errorResponse) => {\n this.$store.dispatch('notification/createNotification', {\n variant: 'error',\n title: this.$tc('buckaroo-payment.settingsForm.titleError'),\n message: errorResponse.response && errorResponse.response.data\n ? errorResponse.response.data.message\n : 'An error occurred'\n });\n that.isLoading = false;\n });\n }\n }\n});\n","\nconst { Component } = Shopware;\n\nComponent.extend('buckaroo-payment-config', 'sw-extension-config', {\n});","const { Module } = Shopware;\n\nimport './extension/sw-order';\nimport './extension/sw-order-detail-base';\nimport './extension/sw-order-user-card';\nimport './extension/sw-system-config';\nimport './page/buckaroo-payment-detail';\n\nimport './page/buckaroo-payment-config';\n\nimport nlNL from './snippet/nl-NL.json';\nimport deDE from './snippet/de-DE.json';\nimport enGB from './snippet/en-GB.json';\n\nModule.register('buckaroo-payment', {\n type: 'plugin',\n name: 'BuckarooPayment',\n title: 'buckaroo-payment.general.title',\n description: 'buckaroo-payment.general.description',\n version: '1.0.0',\n targetVersion: '1.0.0',\n color: '#000000',\n icon: 'default-action-settings',\n\n snippets: {\n 'nl-NL': nlNL,\n 'de-DE': deDE,\n 'en-GB': enGB\n },\n\n routeMiddleware(next, currentRoute) {\n if (currentRoute.name === 'sw.order.detail') {\n currentRoute.children.push({\n component: 'buckaroo-payment-detail',\n name: 'buckaroo.payment.detail',\n isChildren: true,\n path: '/sw/order/buckaroo/detail/:id'\n });\n }\n next(currentRoute);\n },\n\n routes: {\n config: {\n component: 'buckaroo-payment-config',\n path: ':namespace/payment/:paymentCode',\n name: 'buckaroo.config.payment',\n meta: {\n parentPath:'sw.extension.config'\n },\n props: {\n default(route) {\n return { namespace: route.params.namespace };\n },\n },\n }\n }\n});\n","const { ApiService } = Shopware.Classes;\n\nclass BuckarooPaymentService extends ApiService {\n constructor(httpClient, loginService, apiEndpoint = 'buckaroo')\n {\n super(httpClient, loginService, apiEndpoint);\n }\n\n getBasicHeaders() {\n if (this.loginService && typeof this.loginService.getToken === 'function') {\n return super.getBasicHeaders();\n }\n return {\n 'Content-Type': 'application/json',\n 'Accept': 'application/json'\n };\n }\n\n getBuckarooTransaction(transaction)\n {\n const apiRoute = `_action/${this.getApiBasePath()}/getBuckarooTransaction`;\n\n return this.httpClient.post(\n apiRoute,\n {\n transaction: transaction\n },\n {\n headers: this.getBasicHeaders()\n }\n ).then((response) => {\n return ApiService.handleResponse(response);\n });\n }\n\n refundPayment(transaction, transactionsToRefund, orderItems, customRefundAmount)\n {\n const apiRoute = `_action/${this.getApiBasePath()}/refund`;\n\n return this.httpClient.post(\n apiRoute,\n {\n transaction: transaction,\n transactionsToRefund: transactionsToRefund,\n orderItems: orderItems,\n customRefundAmount: customRefundAmount\n },\n {\n headers: this.getBasicHeaders()\n }\n ).then((response) => {\n return ApiService.handleResponse(response);\n });\n }\n\n captureOrder(transaction)\n {\n const apiRoute = `_action/${this.getApiBasePath()}/capture`;\n\n return this.httpClient.post(\n apiRoute,\n {\n transaction: transaction\n },\n {\n headers: this.getBasicHeaders()\n }\n ).then((response) => {\n return ApiService.handleResponse(response);\n });\n }\n\n createPaylink(transaction)\n {\n const apiRoute = `_action/${this.getApiBasePath()}/paylink`;\n\n return this.httpClient.post(\n apiRoute,\n {\n transaction: transaction\n },\n {\n headers: this.getBasicHeaders()\n }\n ).then((response) => {\n return ApiService.handleResponse(response);\n });\n }\n\n klarnaMor(orderId, action)\n {\n const apiRoute = `_action/${this.getApiBasePath()}/klarna-mor`;\n\n return this.httpClient.post(\n apiRoute,\n {\n orderId: orderId,\n action: action\n },\n {\n headers: this.getBasicHeaders()\n }\n ).then((response) => {\n return ApiService.handleResponse(response);\n });\n }\n\n}\n\nShopware.Service().register('BuckarooPaymentService', () => {\n const initContainer = Shopware.Application.getContainer('init');\n // Ensure we use the global loginService which always exists in admin\n const loginService = Shopware.Service('loginService');\n return new BuckarooPaymentService(initContainer.httpClient, loginService);\n});\n\n","const { ApiService } = Shopware.Classes;\n\nclass BuckarooPaymentSettingsService extends ApiService {\n constructor(httpClient, loginService, apiEndpoint = 'buckaroo')\n {\n super(httpClient, loginService, apiEndpoint);\n }\n\n getBasicHeaders() {\n if (this.loginService && typeof this.loginService.getToken === 'function') {\n return super.getBasicHeaders();\n }\n return {\n 'Content-Type': 'application/json',\n 'Accept': 'application/json'\n };\n }\n\n getSupportVersion()\n {\n const apiRoute = `_action/${this.getApiBasePath()}/version`;\n\n return this.httpClient.post(\n apiRoute,\n {\n },\n {\n headers: this.getBasicHeaders()\n }\n ).then((response) => {\n return ApiService.handleResponse(response);\n });\n }\n\n getTaxes()\n {\n const apiRoute = `_action/${this.getApiBasePath()}/taxes`;\n\n return this.httpClient.post(\n apiRoute,\n {\n },\n {\n headers: this.getBasicHeaders()\n }\n ).then((response) => {\n return ApiService.handleResponse(response);\n });\n }\n\n getIn3Icons()\n {\n const apiRoute = `_action/${this.getApiBasePath()}/in3/logos`;\n\n return this.httpClient.post(\n apiRoute,\n {\n },\n {\n headers: this.getBasicHeaders()\n }\n ).then((response) => {\n return ApiService.handleResponse(response);\n });\n }\n\n getApiTest(websiteKeyId, secretKeyId, currentSalesChannelId)\n {\n const apiRoute = `_action/${this.getApiBasePath()}/getBuckarooApiTest`;\n\n return this.httpClient.post(\n apiRoute,\n {\n websiteKeyId: websiteKeyId,\n secretKeyId: secretKeyId,\n saleChannelId: currentSalesChannelId\n },\n {\n headers: this.getBasicHeaders()\n }\n ).then((response) => {\n return ApiService.handleResponse(response);\n });\n }\n}\n\nShopware.Service().register('BuckarooPaymentSettingsService', () => {\n const initContainer = Shopware.Application.getContainer('init');\n // Ensure we use the global loginService which always exists in admin\n const loginService = Shopware.Service('loginService');\n return new BuckarooPaymentSettingsService(initContainer.httpClient, loginService);\n});\n\n","
\n {{$tc('buckaroo-payment.afterpay.setup')}}\n
\n
\n setTaxAssociation(tax.id, value)\"\n @input=\"(value) => setTaxAssociation(tax.id, value)\"\n @update:value=\"(value) => setTaxAssociation(tax.id, value)\"\n :value=\"getSelectValue(tax.id)\"\n >\n
\n
\n
","const { Component } = Shopware;\n\nimport template from './buckaroo-afterpay-old-tax.html.twig';\n\nComponent.register('buckaroo-afterpay-old-tax', {\n template,\n\n inject: ['BuckarooPaymentSettingsService'],\n\n data() {\n return {\n taxes: [],\n showTaxes: false,\n afterpayTaxes: [\n { name: this.$tc('buckaroo-payment.afterpay.hightTaxes'), id: 1 },\n { name: this.$tc('buckaroo-payment.afterpay.middleTaxes'), id: 5 },\n { name: this.$tc('buckaroo-payment.afterpay.lowTaxes'), id: 2 },\n { name: this.$tc('buckaroo-payment.afterpay.zeroTaxes'), id: 3 },\n { name: this.$tc('buckaroo-payment.afterpay.noTaxes'), id: 4 },\n ],\n taxAssociation: {}\n };\n },\n\n model: {\n prop: 'value',\n event: 'change',\n },\n\n computed: {\n\n },\n props: {\n name: {\n type: String,\n required: true,\n default: ''\n },\n value: {\n type: Object,\n required: false,\n default() {\n return {}\n }\n }\n },\n\n\n created() {\n this.BuckarooPaymentSettingsService.getTaxes()\n .then((result) => {\n this.taxes = result.taxes.map((tax) => {\n return {\n id: tax.id,\n name: tax.name\n };\n })\n });\n\n },\n methods: {\n setTaxAssociation(taxId, eventOrValue) {\n \n try {\n let actualValue = eventOrValue;\n \n if (eventOrValue && typeof eventOrValue === 'object') {\n if (eventOrValue.target) {\n actualValue = eventOrValue.target.value;\n } else if (eventOrValue.hasOwnProperty('value')) {\n actualValue = eventOrValue.value;\n } else if (eventOrValue.hasOwnProperty('id')) {\n actualValue = eventOrValue.id;\n }\n }\n this.taxAssociation[taxId] = actualValue;\n this.$emit('change', {...this.value, ...this.taxAssociation});\n \n } catch (error) {\n console.error('Error in setTaxAssociation:', error);\n }\n },\n getSelectValue(taxId) {\n if (this.value[taxId]) {\n return this.value[taxId];\n }\n return;\n }\n }\n });\n","
\n \n \n\n \n \n
","const { Component } = Shopware;\n\nimport template from \"./buckaroo-main-config.html.twig\";\n\nComponent.register(\"buckaroo-main-config\", {\n template,\n props: {\n configSettings: {\n type: Array,\n required: false,\n default: () => []\n },\n value: {\n type: Object,\n required: false,\n default: () => ({})\n },\n elementMethods: {\n type: Object,\n required: false,\n default: () => ({})\n },\n isNotDefaultSalesChannel: {\n type: Boolean,\n required: false,\n default: false\n },\n currentSalesChannelId: {\n type: String,\n required: false,\n default: null\n }\n },\n emits: ['input'],\n\n model: {\n prop: 'value',\n event: 'input'\n },\n\n\n data() {\n return {\n selectedCard: this.$route.params?.paymentCode || 'general'\n }\n },\n\n watch: {\n value: {\n handler(newVal, oldVal) {\n this.$nextTick(() => {\n this.$forceUpdate();\n });\n },\n deep: true,\n immediate: true\n },\n $route(to) {\n if (to.params?.paymentCode) {\n this.selectedCard = to.params.paymentCode;\n }\n }\n },\n\n computed: {\n mainCard() {\n const card = this.configSettings.filter((card) => card.name === this.selectedCard)?.pop();\n return card;\n }\n },\n\n methods: {\n onInput(value) {\n this.$emit('input', value);\n }\n }\n\n})","{% block buckaroo_config_card %}\n \n \n\n
\n
\n \n \n \n \n \n
\n
\n\n \n
\n{% endblock %}\n","import template from './buckaroo-config-card.html.twig';\n\nconst { Component } = Shopware;\n\nComponent.register('buckaroo-config-card', {\n template,\n\n inject: ['BuckarooPaymentSettingsService'],\n\n data() {\n return {\n shopwareVersion: null\n };\n },\n\n mounted() {\n this.fetchShopwareVersion();\n this.$nextTick(() => {\n this.$forceUpdate();\n });\n },\n watch: {\n value: {\n handler() {\n this.$nextTick(() => {\n this.$forceUpdate();\n });\n },\n deep: true,\n immediate: true\n },\n \n currentSalesChannelId: {\n handler(newChannelId, oldChannelId) {\n if (newChannelId !== oldChannelId) {\n \n this.$nextTick(() => {\n this.$forceUpdate();\n });\n }\n },\n immediate: false\n }\n },\n computed: {\n canShowCredentialTester() {\n const key = this.getValueForName('websiteKey');\n const secretKey = this.getValueForName('secretKey');\n const isGeneralConfig = this.card?.name === 'general';\n \n if (!isGeneralConfig) {\n return false;\n }\n\n const hasWebsiteKey = key !== undefined && key !== null && key !== '';\n const hasSecretKey = secretKey !== undefined && secretKey !== null && secretKey !== '';\n const canShow = hasWebsiteKey || hasSecretKey;\n return canShow;\n },\n \n hasValidConfigData() {\n return this.value && typeof this.value === 'object' && Object.keys(this.value).length > 0;\n },\n \n reactiveValue() {\n return this.value;\n }\n },\n\n emits: ['input'],\n\n model: {\n prop: 'value',\n event: 'input'\n },\n\n props: {\n card: {\n type: Object,\n required: false,\n default: () => ({ elements: [] })\n },\n configSettings: {\n type: Array,\n required: false,\n default: () => []\n },\n methods: {\n type: Object,\n required: true,\n },\n isNotDefaultSalesChannel: {\n type: Boolean,\n required: true,\n },\n currentSalesChannelId: {\n type: String,\n required: true,\n },\n value: {\n type: Object,\n required: false,\n default: () => ({})\n },\n },\n\n methods: {\n fetchShopwareVersion() {\n const service = this.BuckarooPaymentSettingsService;\n if (service && typeof service.getSupportVersion === 'function') {\n service.getSupportVersion().then((data) => {\n if (data && data.shopware_version) {\n this.shopwareVersion = data.shopware_version;\n }\n }).catch(() => {});\n }\n },\n\n /**\n * Returns true if Shopware version is >= 6.7.4.0 (label fix applies; older versions show duplicate labels if we use enhanced label logic).\n * When version is unknown, returns false to avoid duplicate labels on older Shopware.\n */\n isShopware674OrNewer() {\n if (!this.shopwareVersion || typeof this.shopwareVersion !== 'string') {\n return false;\n }\n const parts = this.shopwareVersion.split('.').map((n) => parseInt(n, 10) || 0);\n const major = parts[0] || 0;\n const minor = parts[1] || 0;\n const patch = parts[2] || 0;\n const build = parts[3] || 0;\n if (major > 6) return true;\n if (major < 6) return false;\n if (minor > 7) return true;\n if (minor < 7) return false;\n if (patch > 4) return true;\n if (patch < 4) return false;\n return build >= 0;\n },\n\n getElementBind(element, props = {}) {\n if (!this.methods || !this.methods.getElementBind) {\n const label = element.label ? this.getInlineSnippet(element.label) : null;\n return {\n name: element.name,\n type: element.type || 'text',\n config: element.config || {},\n label: label,\n value: this.getValueForName(element.name.replace('BuckarooPayments.config.', ''))\n };\n }\n \n const baseBinding = this.methods.getElementBind(element, props);\n \n const fieldName = element.name.replace('BuckarooPayments.config.', '');\n let currentValue = this.getValueForName(fieldName);\n \n // Ensure config object exists\n const config = baseBinding.config || element.config || {};\n \n // For bool fields, ensure we have a proper boolean value\n if (element.type === 'bool') {\n if (currentValue === null || currentValue === undefined) {\n currentValue = baseBinding.value !== undefined ? baseBinding.value : false;\n } else {\n // Ensure it's a proper boolean - handle string values like \"0\", \"1\", \"false\", \"true\"\n if (typeof currentValue === 'string') {\n currentValue = currentValue === '1' || currentValue === 'true' || currentValue === 'on';\n } else {\n currentValue = Boolean(currentValue);\n }\n }\n }\n \n // Extract label only for Shopware >= 6.7.4.0; in older versions baseBinding/template already show the label and our enhanced logic causes duplicate labels\n let finalLabel = null;\n const useEnhancedLabels = this.isShopware674OrNewer();\n\n if (useEnhancedLabels) {\n // For bool/select fields, prioritize configSettings since baseBinding.label is often undefined in SW 6.7.4+\n if ((element.type === 'bool' || element.type === 'single-select' || element.type === 'multi-select') && this.configSettings && Array.isArray(this.configSettings)) {\n for (const configCard of this.configSettings) {\n if (configCard.elements && Array.isArray(configCard.elements)) {\n const configElement = configCard.elements.find(el => el.name === element.name);\n if (configElement) {\n if (configElement.label) {\n let extractedLabel = this.getInlineSnippet(configElement.label);\n if (!extractedLabel || (typeof extractedLabel === 'string' && extractedLabel.trim().length === 0)) {\n if (typeof configElement.label === 'object' && configElement.label !== null) {\n const locale = this.$i18n?.locale || 'en-GB';\n extractedLabel = configElement.label[locale] || configElement.label['en-GB'] || Object.values(configElement.label)[0] || null;\n } else if (typeof configElement.label === 'string') {\n extractedLabel = configElement.label;\n }\n }\n if (extractedLabel && typeof extractedLabel === 'string' && extractedLabel.trim().length > 0) {\n finalLabel = extractedLabel;\n break;\n }\n }\n if (!finalLabel && configElement.config && configElement.config.label) {\n let extractedLabel = this.getInlineSnippet(configElement.config.label);\n if (!extractedLabel || (typeof extractedLabel === 'string' && extractedLabel.trim().length === 0)) {\n if (typeof configElement.config.label === 'object' && configElement.config.label !== null) {\n const locale = this.$i18n?.locale || 'en-GB';\n extractedLabel = configElement.config.label[locale] || configElement.config.label['en-GB'] || Object.values(configElement.config.label)[0] || null;\n } else if (typeof configElement.config.label === 'string') {\n extractedLabel = configElement.config.label;\n }\n }\n if (extractedLabel && typeof extractedLabel === 'string' && extractedLabel.trim().length > 0) {\n finalLabel = extractedLabel;\n break;\n }\n }\n }\n }\n }\n }\n\n if (!finalLabel) {\n if (baseBinding.label && typeof baseBinding.label === 'string' && baseBinding.label.trim().length > 0) {\n finalLabel = baseBinding.label;\n } else if (element.label) {\n let extractedLabel = this.getInlineSnippet(element.label);\n if (!extractedLabel || (typeof extractedLabel === 'string' && extractedLabel.trim().length === 0)) {\n if (typeof element.label === 'object' && element.label !== null) {\n const locale = this.$i18n?.locale || 'en-GB';\n extractedLabel = element.label[locale] || element.label['en-GB'] || Object.values(element.label)[0] || null;\n } else if (typeof element.label === 'string') {\n extractedLabel = element.label;\n }\n }\n if (extractedLabel && typeof extractedLabel === 'string' && extractedLabel.trim().length > 0) {\n finalLabel = extractedLabel;\n }\n } else if (this.card && this.card.elements && Array.isArray(this.card.elements)) {\n const rawElement = this.card.elements.find(el => el.name === element.name);\n if (rawElement && rawElement.label) {\n let extractedLabel = this.getInlineSnippet(rawElement.label);\n if (!extractedLabel || (typeof extractedLabel === 'string' && extractedLabel.trim().length === 0)) {\n if (typeof rawElement.label === 'object' && rawElement.label !== null) {\n const locale = this.$i18n?.locale || 'en-GB';\n extractedLabel = rawElement.label[locale] || rawElement.label['en-GB'] || Object.values(rawElement.label)[0] || null;\n } else if (typeof rawElement.label === 'string') {\n extractedLabel = rawElement.label;\n }\n }\n if (extractedLabel && typeof extractedLabel === 'string' && extractedLabel.trim().length > 0) {\n finalLabel = extractedLabel;\n }\n }\n }\n }\n if (!finalLabel && baseBinding.config && baseBinding.config.label && typeof baseBinding.config.label === 'string' && baseBinding.config.label.trim().length > 0) {\n finalLabel = baseBinding.config.label;\n }\n }\n\n // Only add label to config for SW >= 6.7.4.0 (avoids duplicate labels in older versions)\n let finalConfig = config;\n if (useEnhancedLabels && finalLabel && typeof finalLabel === 'string' && finalLabel.trim().length > 0) {\n if (element.type === 'bool' || element.type === 'single-select' || element.type === 'multi-select') {\n finalConfig = {\n ...config,\n label: finalLabel\n };\n }\n }\n\n const binding = {\n ...baseBinding,\n config: finalConfig\n };\n\n // Ensure specific fields are treated as real multi-selects in the UI\n const forcedMultiSelectFields = [\n 'allowedcreditcard',\n 'allowedcreditcards',\n 'allowedgiftcards',\n 'giftcardsPaymentmethods',\n 'payperemailAllowed'\n ];\n\n if (forcedMultiSelectFields.includes(fieldName)) {\n binding.type = 'multi-select';\n // Force Shopware to render the correct component\n binding.componentName = 'sw-multi-select';\n\n binding.config = {\n ...(binding.config || {}),\n multiple: true,\n // Prefer options coming from binding.config; fall back to element/config when needed\n options: (binding.config && binding.config.options)\n || (config && config.options)\n || element.options\n || []\n };\n\n // Debug logging to inspect how the multi-select is bound\n const sampleOption = Array.isArray(binding.config?.options) && binding.config.options.length > 0\n ? binding.config.options[0]\n : null;\n console.debug('[BuckarooConfigCard] getElementBind multi-select binding', {\n fieldName,\n bindingType: binding.type,\n componentName: binding.componentName,\n optionsCount: Array.isArray(binding.config?.options) ? binding.config.options.length : 0,\n currentValue,\n sampleOption\n });\n }\n \n // Only set binding.label for SW >= 6.7.4.0; older versions already show the label and would show duplicates\n if (useEnhancedLabels && finalLabel && typeof finalLabel === 'string' && finalLabel.trim().length > 0) {\n if (element.type === 'bool') {\n binding.label = finalLabel;\n } else if (!binding.label || (typeof binding.label === 'string' && binding.label.trim().length === 0)) {\n binding.label = finalLabel;\n }\n }\n\n if (element.type === 'bool') {\n binding.value = currentValue;\n // Only set fallback label for SW >= 6.7.4.0 to avoid duplicate labels in older versions\n if (useEnhancedLabels && (!binding.label || (typeof binding.label === 'string' && binding.label.trim().length === 0))) {\n binding.label = binding.config?.label || element.name.replace('BuckarooPayments.config.', '').replace(/([A-Z])/g, ' $1').trim();\n }\n }\n \n // Debug: Log if label is missing for bool/select fields\n if ((element.type === 'bool' || element.type === 'single-select' || element.type === 'multi-select') && (!binding.label || (typeof binding.label === 'string' && binding.label.trim().length === 0))) {\n console.warn('Missing label for field:', element.name, 'Type:', element.type, 'Element label:', element.label, 'Extracted:', finalLabel, 'BaseBinding label:', baseBinding.label, 'Final binding label:', binding.label);\n }\n \n return binding;\n },\n\n getInheritWrapperBind(element) {\n if (!this.methods || !this.methods.getInheritWrapperBind) {\n const fieldName = element.name.replace('BuckarooPayments.config.', '');\n return {\n name: element.name,\n currentValue: this.getValueForName(fieldName)\n };\n }\n \n const baseBinding = this.methods.getInheritWrapperBind(element);\n const fieldName = element.name.replace('BuckarooPayments.config.', '');\n const currentValue = this.getValueForName(fieldName);\n\n baseBinding.currentValue = currentValue;\n\n \n return baseBinding;\n },\n\n getFieldError(name) {\n if (!this.methods || !this.methods.getFieldError) {\n return null;\n }\n return this.methods.getFieldError(name);\n },\n\n kebabCase(string) {\n if (!this.methods || !this.methods.kebabCase) {\n return string ? string.toLowerCase().replace(/[A-Z]/g, '-$&').replace(/^-/, '') : '';\n }\n return this.methods.kebabCase(string);\n },\n\n getInlineSnippet(title) {\n try {\n if (typeof title === 'object' && title !== null) {\n const locale = this.$i18n?.locale || 'en-GB';\n \n if (title[locale]) {\n return title[locale];\n }\n \n if (title['en-GB']) {\n return title['en-GB'];\n }\n const firstKey = Object.keys(title)[0];\n if (firstKey && title[firstKey]) {\n return title[firstKey];\n }\n \n return JSON.stringify(title);\n }\n \n if (typeof title === 'string') {\n if (this.$t && typeof this.$t === 'function') {\n return this.$t(title);\n }\n return title;\n }\n return String(title);\n \n } catch (error) {\n console.warn('Translation error for:', title, error);\n return typeof title === 'object' ? JSON.stringify(title) : String(title);\n }\n },\n\n getInheritedValue(element) {\n if (!this.methods || !this.methods.getInheritedValue) {\n return null;\n }\n return this.methods.getInheritedValue(element);\n },\n\n getValueForName(name) {\n const currentValue = this.reactiveValue;\n \n if (!currentValue || typeof currentValue !== 'object') {\n return null;\n }\n\n let val = undefined;\n\n const keyVariations = [\n `BuckarooPayments.config.${name}`, // Full prefixed key\n name.toLowerCase(),\n name.charAt(0).toLowerCase() + name.slice(1),\n name.charAt(0).toUpperCase() + name.slice(1)\n ];\n\n for (const key of keyVariations) {\n if (currentValue[key] !== undefined) {\n val = currentValue[key];\n break;\n }\n }\n\n if (val === undefined && currentValue['BuckarooPayments.config'] && typeof currentValue['BuckarooPayments.config'] === 'object') {\n for (const key of keyVariations) {\n if (currentValue['BuckarooPayments.config'][key] !== undefined) {\n val = currentValue['BuckarooPayments.config'][key];\n break;\n }\n }\n }\n\n if (val && typeof val === 'object' && val.hasOwnProperty('_value')) {\n val = val._value;\n }\n return val;\n },\n\n canShow(element) {\n if (!element || !element.name) {\n return false;\n }\n \n const name = element.name.replace('BuckarooPayments.config.', '');\n\n const advancedToggleFields = [\n 'orderStatus',\n 'paymentSuccesStatus',\n 'automaticallyCloseOpenOrders',\n 'sendInvoiceEmail'\n ];\n if (advancedToggleFields.includes(name)) {\n const advancedConfig = this.getValueForName('advancedConfiguration');\n return Boolean(advancedConfig);\n }\n\n if (name === 'idealprocessingRenderMode') {\n return Boolean(this.getValueForName('idealprocessingShowissuers'));\n }\n\n if (name === 'idealRenderMode') {\n return Boolean(this.getValueForName('idealShowissuers'));\n }\n\n const idealFastCheckoutFields = [\n 'idealFastCheckoutEnabled',\n 'idealFastCheckoutVisibility',\n 'idealFastCheckoutLogoScheme'\n ];\n if (idealFastCheckoutFields.includes(name)) {\n return Boolean(this.getValueForName('idealFastCheckout'));\n }\n\n if (name === 'afterpayPaymentstatus') {\n return Boolean(this.getValueForName('afterpayCaptureonshippent'));\n }\n\n if (name === 'afterpayOldtax') {\n return Boolean(this.getValueForName('afterpayEnabledold'));\n }\n\n return true;\n },\n\n onInput(value) {\n this.$emit('input', value);\n },\n onFieldInput(fieldName, eventOrValue) {\n\n try {\n let actualValue = eventOrValue;\n \n if (eventOrValue && typeof eventOrValue === 'object') {\n if (eventOrValue.target) {\n const target = eventOrValue.target;\n\n if (target.type === 'checkbox' || target.type === 'radio') {\n actualValue = target.checked;\n } else if (target.tagName === 'SELECT' || target.type === 'select-one' || target.type === 'select-multiple') {\n if (target.multiple) {\n actualValue = Array.from(target.selectedOptions).map(option => option.value);\n } else {\n actualValue = target.value;\n }\n } else {\n actualValue = target.value;\n }\n } else if (eventOrValue.hasOwnProperty('value')) {\n actualValue = eventOrValue.value;\n } else if (eventOrValue.hasOwnProperty('id') && eventOrValue.hasOwnProperty('name')) {\n actualValue = eventOrValue.id;\n } else if (Array.isArray(eventOrValue)) {\n const totalCharacters = eventOrValue.filter(item => typeof item === 'string' && item.length === 1).length;\n const hasCommas = eventOrValue.some(item => item === ',');\n const hasLongStrings = eventOrValue.some(item => typeof item === 'string' && item.length > 1);\n\n const isCharacterArray = totalCharacters > 10 && hasCommas;\n\n \n if (isCharacterArray) {\n const correctValues = eventOrValue.filter(item => typeof item === 'string' && item.length > 1);\n const characterPart = eventOrValue.filter(item => typeof item === 'string' && item.length === 1);\n const rejoined = characterPart.join('');\n \n let splitValues = [];\n if (rejoined.includes(',')) {\n splitValues = rejoined.split(',').map(item => item.trim()).filter(item => item.length > 0);\n } else if (rejoined.length > 0) {\n splitValues = [rejoined];\n }\n\n actualValue = [...splitValues, ...correctValues].filter(item => item && item.length > 0);\n } else {\n actualValue = eventOrValue\n .filter(item => {\n if (item === null || item === undefined || item === '') {\n return false;\n }\n\n if (typeof item === 'string' && item.length === 1) {\n return false;\n }\n\n if (typeof item === 'string' && (item.startsWith('+') || /^\\d+$/.test(item))) {\n\n return false;\n }\n \n return true;\n })\n .map(item => {\n if (typeof item === 'object' && item !== null) {\n let extractedValue = item.id || item.value || item.code || item.key || item;\n return extractedValue;\n }\n return item;\n });\n }\n\n } else {\n const possibleKeys = ['id', 'value', 'key', 'code'];\n for (const key of possibleKeys) {\n if (eventOrValue[key] !== undefined) {\n actualValue = eventOrValue[key];\n break;\n }\n }\n }\n } else if (typeof eventOrValue === 'boolean') {\n actualValue = eventOrValue;\n } else if (typeof eventOrValue === 'string' || typeof eventOrValue === 'number') {\n actualValue = eventOrValue;\n }\n\n // Determine the element definition once so we can branch on its type\n const element = this.card?.elements?.find(\n el => el.name === fieldName\n || el.name.replace('BuckarooPayments.config.', '') === fieldName.replace('BuckarooPayments.config.', '')\n );\n\n if (actualValue === \"on\") {\n actualValue = true;\n } else if (actualValue === \"off\") {\n actualValue = false;\n }\n \n // For bool fields, ensure we always have a proper boolean\n if (element && element.type === 'bool') {\n if (typeof actualValue === 'string') {\n actualValue = actualValue === '1' || actualValue === 'true' || actualValue === 'on';\n } else {\n actualValue = Boolean(actualValue);\n }\n }\n\n // For multi-select fields, ALWAYS store an array of selected values.\n // This ensures components like sw-multi-select keep multiple selections\n // instead of degrading to a single selected option.\n if (element && element.type === 'multi-select') {\n console.debug('[BuckarooConfigCard] onFieldInput before normalize (multi-select)', {\n fieldName,\n rawEvent: eventOrValue,\n rawValue: actualValue\n });\n\n if (Array.isArray(actualValue)) {\n // Normalize array items to primitive ids / values\n actualValue = actualValue\n .filter(item => item !== null && item !== undefined && item !== '')\n .map(item => {\n if (typeof item === 'object' && item !== null) {\n return item.id || item.value || item.code || item.key || item;\n }\n return item;\n });\n } else if (typeof actualValue === 'string') {\n // Support comma-separated string values (just in case)\n actualValue = actualValue\n .split(',')\n .map(v => v.trim())\n .filter(v => v.length > 0);\n } else if (actualValue === null || actualValue === undefined) {\n actualValue = [];\n } else {\n // Fallback: wrap single primitive value into an array\n actualValue = [actualValue];\n }\n\n console.debug('[BuckarooConfigCard] onFieldInput after normalize (multi-select)', {\n fieldName,\n normalizedValue: actualValue\n });\n }\n \n const cleanFieldName = fieldName.replace('BuckarooPayments.config.', '');\n const updatedValue = { ...this.value };\n\n updatedValue[cleanFieldName] = actualValue;\n updatedValue[fieldName] = actualValue;\n\n this.$emit('input', updatedValue);\n \n } catch (error) {\n console.error('Error in onFieldInput:', error);\n console.error('Error details:', error.stack);\n }\n }\n }\n});\n","\n
\n \n
\n
\n \n
\n \"Payment\n
\n
\n {{ getPaymentTitle(payment.code) }}\n
\n
\n\n \n\n \n {{$tc('buckaroo-payment.configure-link')}}\n \n
\n
\n \n
\n","const { Component, Filter } = Shopware;\nimport template from \"./buckaroo-payment-list.html.twig\";\nimport \"./style.scss\";\n\nComponent.register(\"buckaroo-payment-list\", {\n template,\n props: {\n configSettings: {\n type: Array,\n required: false,\n default: () => []\n },\n value: {\n type: Object,\n required: false,\n default: () => ({})\n },\n currentSalesChannelId: {\n type: String,\n required: true\n }\n },\n\n emits: ['input'],\n\n data() {\n return {\n payments: [\n {\n code: \"Alipay\",\n logo: \"alipay.svg\"\n },\n {\n code: \"applepay\",\n logo: \"applepay.svg\"\n },\n {\n code: \"googlepay\",\n logo: \"googlepay.svg\"\n },\n {\n code: \"bancontactmrcash\",\n logo: \"bancontact.svg\"\n },\n {\n code: \"blik\",\n logo: \"blik.svg\"\n },\n {\n code: \"belfius\",\n logo: \"belfius.svg\"\n },\n {\n code: \"Billink\",\n logo: \"billink.svg\"\n },\n {\n code: \"creditcard\",\n logo: \"creditcards.svg\"\n },\n {\n code: \"creditcards\",\n logo: \"creditcards.svg\"\n },\n {\n code: \"eps\",\n logo: \"eps.svg\"\n },\n {\n code: \"giftcards\",\n logo: \"giftcards.svg\"\n },\n {\n code: \"idealqr\",\n logo: \"ideal-qr.svg\"\n },\n {\n code: \"ideal\",\n logo: \"ideal-wero.svg\"\n },\n {\n code: \"capayable\",\n logo: \"in3.svg\"\n },\n {\n code: \"KBCPaymentButton\",\n logo: \"kbc.svg\"\n },\n {\n code: \"klarna\",\n logo: \"klarna.svg\"\n },\n {\n code: \"klarnakp\",\n logo: \"klarna.svg\"\n },\n {\n code: \"mbway\",\n logo: \"mbway.svg\"\n },\n {\n code: \"multibanco\",\n logo: \"multibanco.svg\"\n },\n {\n code: \"paybybank\",\n logo: \"paybybank.svg\"\n },\n {\n code: \"payconiq\",\n logo: \"payconiq.svg\"\n },\n {\n code: \"paypal\",\n logo: \"paypal.svg\"\n },\n {\n code: \"payperemail\",\n logo: \"payperemail.svg\"\n },\n {\n code: \"Przelewy24\",\n logo: \"przelewy24.svg\"\n },\n {\n code: \"afterpay\",\n logo: \"afterpay.svg\"\n },\n {\n code: \"sepadirectdebit\",\n logo: \"sepa-directdebit.svg\"\n },\n {\n code: \"transfer\",\n logo: \"sepa-credittransfer.svg\"\n },\n {\n code: \"Trustly\",\n logo: \"trustly.svg\"\n },\n {\n code: \"WeChatPay\",\n logo: \"wechatpay.svg\"\n },\n {\n code: \"swish\",\n logo: \"swish.svg\"\n },\n {\n code: \"bizum\",\n logo: \"bizum.svg\"\n },\n {\n code: \"twint\",\n logo: \"twint.svg\"\n },\n {\n code: \"wero\",\n logo: \"wero.svg\"\n }\n ]\n };\n },\n methods: {\n getPaymentTitle(code) {\n if (this.configSettings && Array.isArray(this.configSettings)) {\n const card = this.configSettings.find((card) => card.name === code);\n if (card && card.title) {\n try {\n if (typeof card.title === 'object' && card.title !== null) {\n const locale = this.$i18n?.locale || 'en-GB';\n\n if (card.title[locale]) {\n return card.title[locale];\n }\n if (card.title['en-GB']) {\n return card.title['en-GB'];\n }\n \n const firstKey = Object.keys(card.title)[0];\n if (firstKey && card.title[firstKey]) {\n return card.title[firstKey];\n }\n \n return JSON.stringify(card.title);\n }\n \n if (typeof card.title === 'string') {\n if (this.$t && typeof this.$t === 'function') {\n return this.$t(card.title);\n }\n return card.title;\n }\n \n return String(card.title);\n \n } catch (error) {\n console.warn('Translation error for:', card.title, error);\n return typeof card.title === 'object' ? JSON.stringify(card.title) : String(card.title);\n }\n }\n }\n\n const payment = this.payments.find(payment => payment.code === code);\n return payment ? payment.code : 'Unknown Payment';\n },\n assetFilter(path) {\n return Filter.getByName('asset')(path);\n }\n }\n});"," {{ $tc('buckaroo-payment.button.labelTestApi') }}","const { Component } = Shopware;\nimport template from \"./buckaroo-test-credentials.twig\";\n\nComponent.register(\"buckaroo-test-credentials\", {\n template,\n mixins: [\n Shopware.Mixin.getByName('notification')\n ],\n data() {\n return {\n isLoading: false,\n }\n },\n inject: [ 'BuckarooPaymentSettingsService' ],\n\n props: {\n config: {\n type: Object,\n required: true\n },\n currentSalesChannelId: {\n required: true\n }\n },\n computed: {\n enabled: function() {\n return (this.getConfigValue('websiteKey') || '').length > 0 &&\n (this.getConfigValue('secretKey') || '').length > 0\n }\n },\n methods: {\n getConfigValue: function(name) {\n return this.config[\"BuckarooPayments.config.\"+name];\n },\n sendTestApi() {\n this.isLoading = true;\n let websiteKeyId = this.getConfigValue('websiteKey'),\n secretKeyId = this.getConfigValue('secretKey');\n this.BuckarooPaymentSettingsService.getApiTest(websiteKeyId, secretKeyId, this.currentSalesChannelId)\n .then((result) => {\n this.isLoading = false;\n\n if (result.status == 'success') {\n this.createNotificationSuccess({\n title: this.$tc('buckaroo-payment.settingsForm.titleSuccess'),\n message: this.$tc(result.message)\n });\n } else {\n this.createNotificationError({\n title: this.$tc('buckaroo-payment.settingsForm.titleError'),\n message: this.$tc(result.message)\n });\n }\n\n })\n .catch(() => {\n this.isLoading = false;\n });\n },\n }\n})","
\n \n Live\n \n\n \n Test\n \n\n \n Off\n \n
\n","const { Component } = Shopware;\nimport template from \"./buckaroo-toggle-status.html.twig\";\nimport './style.scss'\n\nComponent.register(\"buckaroo-toggle-status\", {\n template,\n props: {\n method: {\n type: String,\n required: true\n },\n value: {\n required: true\n },\n currentSalesChannelId: {\n required: true,\n }\n },\n\n emits: ['input'],\n\n inject: ['systemConfigApiService'],\n data() {\n return {\n status: 'disabled',\n isLoading: false,\n }\n },\n\n mounted() {\n this.status = this.getStatus();\n },\n\n watch: {\n value: {\n handler(newVal) {\n this.status = this.getStatus();\n },\n deep: true,\n immediate: true\n }\n },\n methods: {\n getStatus() {\n const isActive = this.isActive();\n const environment = this.getEnvironment();\n return isActive ? environment : 'disabled';\n },\n isActive() {\n const enabled = this.getValueForName(`${this.method}Enabled`);\n if (typeof enabled === 'string') {\n return enabled.toLowerCase() === 'true';\n }\n return Boolean(enabled);\n },\n getEnvironment() {\n const env = this.getValueForName(`${this.method}Environment`);\n \n if (env === undefined || env === null || env === '') {\n return 'test';\n }\n const validEnvs = ['test', 'live'];\n return validEnvs.includes(env) ? env : 'test';\n },\n getValueForName(name) {\n const key = `BuckarooPayments.config.${name}`;\n if (!this.value || typeof this.value !== 'object') {\n return null;\n }\n\n let val = undefined;\n\n if (this.value[key] !== undefined) {\n val = this.value[key];\n }\n else if (this.value[name] !== undefined) {\n val = this.value[name];\n }\n else if (this.value['BuckarooPayments.config'] && typeof this.value['BuckarooPayments.config'] === 'object') {\n if (this.value['BuckarooPayments.config'][name] !== undefined) {\n val = this.value['BuckarooPayments.config'][name];\n }\n }\n else {\n const variations = [\n name,\n name.toLowerCase(),\n name.charAt(0).toLowerCase() + name.slice(1),\n name.charAt(0).toUpperCase() + name.slice(1)\n ];\n \n for (const variation of variations) {\n const variationKey = `BuckarooPayments.config.${variation}`;\n if (this.value[variationKey] !== undefined) {\n val = this.value[variationKey];\n break;\n }\n if (this.value[variation] !== undefined) {\n val = this.value[variation];\n break;\n }\n }\n }\n\n if (val && typeof val === 'object' && val.hasOwnProperty('_value')) {\n val = val._value;\n }\n \n return val;\n },\n setStatus(status) {\n this.status = status;\n this.saveStatus();\n },\n getClass(buttonStatus) {\n return this.status === buttonStatus ? 'active' : '';\n },\n async saveStatus() {\n const enabledKey = `BuckarooPayments.config.${this.method}Enabled`;\n const environmentKey = `BuckarooPayments.config.${this.method}Environment`;\n\n let data = {[enabledKey]: false};\n const updatedValue = { ...this.value };\n updatedValue[enabledKey] = false;\n\n if (['live', 'test'].indexOf(this.status) !== -1) {\n data = {\n [enabledKey]: true,\n [environmentKey]: this.status\n }\n updatedValue[enabledKey] = true;\n updatedValue[environmentKey] = this.status;\n }\n\n this.$emit('input', updatedValue);\n\n this.isLoading = true;\n try {\n await this.systemConfigApiService\n .batchSave({[this.currentSalesChannelId]: data})\n .finally(() => {\n this.isLoading = false;\n });\n this.renderSuccess();\n } catch (error) {\n this.renderError(error);\n }\n \n },\n renderSuccess() {\n this.$store.dispatch('notification/createNotification', {\n variant: 'success',\n message: this.$tc('sw-extension-store.component.sw-extension-config.messageSaveSuccess'),\n });\n },\n\n renderError(err) {\n this.$store.dispatch('notification/createNotification', {\n variant: 'error',\n message: err,\n });\n }\n }\n})"],"names":["template$a","Component","Context","Criteria","template","orderRepository","orderCriteria","order","paymentMethodId","paymentMethod","template$9","template$8","values","template$7","newVal","oldVal","response","processedData","key","value","shortKey","error","newValue","fullFieldName","_a","_b","code","card","currentConfigValues","currentPaymentCard","actualConfigValues","element","cleanFieldName","template$6","Filter","that","orderId","buckarooKey","errorResponse","_c","transaction","amount","field","action","Module","nlNL","deDE","enGB","next","currentRoute","route","ApiService","BuckarooPaymentService","httpClient","loginService","apiEndpoint","apiRoute","transactionsToRefund","orderItems","customRefundAmount","initContainer","BuckarooPaymentSettingsService","websiteKeyId","secretKeyId","currentSalesChannelId","template$5","result","tax","taxId","eventOrValue","actualValue","template$4","to","template$3","newChannelId","oldChannelId","secretKey","hasWebsiteKey","hasSecretKey","service","data","parts","n","major","minor","patch","build","props","_d","_e","_f","_g","label","baseBinding","fieldName","currentValue","config","finalLabel","useEnhancedLabels","configCard","configElement","el","extractedLabel","locale","rawElement","finalConfig","binding","sampleOption","name","string","title","firstKey","val","keyVariations","target","option","totalCharacters","item","hasCommas","hasLongStrings","correctValues","rejoined","splitValues","possibleKeys","v","updatedValue","template$2","payment","path","template$1","isActive","environment","enabled","env","variations","variation","variationKey","status","buttonStatus","enabledKey","environmentKey","err"],"mappings":"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"} \ No newline at end of file diff --git a/src/Resources/public/administration/css/buckaroo-payments.css b/src/Resources/public/administration/css/buckaroo-payments.css deleted file mode 100644 index 10f78d30..00000000 --- a/src/Resources/public/administration/css/buckaroo-payments.css +++ /dev/null @@ -1,5 +0,0 @@ -.buckaroo-feedback .buckaroo-feedback__col h3{text-align:center}.buckaroo-payment-detail .sw-product-variant-info{white-space:normal;text-overflow:unset}.buckaroo-payment-detail .bk-reund-qty{text-align:right} -.bk-payment-wrap{display:flex;flex-wrap:wrap}.bk-payment-wrap .bk-payment .bk-payment-inner{display:flex;width:170px;flex-direction:column;align-items:center;margin:.25rem .125rem;padding:.5rem;background-color:#fafafa;border-radius:.5rem}.bk-payment-wrap .bk-payment .bk-payment-inner a{text-decoration:none}.bk-payment-wrap .bk-payment .bk-payment-inner .bk-payment-name{text-align:center;text-decoration:none;padding:.25rem 0 .5rem;color:#555;font-weight:bold;font-size:16px}.bk-payment-wrap .bk-payment{flex:0 20%;display:flex;flex-direction:column;align-items:center}.bk-payment-wrap .bk-payment .bk-payment-img{height:60px;width:auto;padding:10px;display:flex}.bk-payment-wrap .bk-payment .bk-payment-img img{width:100%;height:auto}.bk-payment-wrap .bk-link{padding:.25rem 0 .125rem;color:#555}.bk-payment-wrap .bk-link:hover{font-weight:bold} -.bk-toogle-wrap{display:flex;border-radius:.25rem;box-shadow:0 0 1px rgba(0,0,0,.2);padding:.125rem;background-color:#fff}.bk-toogle-wrap button{outline:none;margin:.125rem;padding:.25rem;background-color:#e5e7eb;border-radius:.125rem;text-transform:uppercase;border:0;color:#9ca3af;cursor:pointer;flex-grow:1}.bk-toogle-wrap button.test:hover,.bk-toogle-wrap button.test.active{background-color:#eab308;color:#fff}.bk-toogle-wrap button.live:hover,.bk-toogle-wrap button.live.active{background-color:#22c55e;color:#fff}.bk-toogle-wrap button.disabled:hover,.bk-toogle-wrap button.disabled.active{background-color:#000;color:#fff}.bk-toogle-wrap .bk-edit-link{display:flex;align-items:center;margin:0 .125rem} - -/*# sourceMappingURL=buckaroo-payments.css.map*/ \ No newline at end of file diff --git a/src/Resources/public/administration/css/buckaroo-payments.css.map b/src/Resources/public/administration/css/buckaroo-payments.css.map deleted file mode 100644 index ac876e51..00000000 --- a/src/Resources/public/administration/css/buckaroo-payments.css.map +++ /dev/null @@ -1 +0,0 @@ -{"version":3,"file":"../css/buckaroo-payments.css","mappings":"AAEQ,8CACI,kBAKR,kDACI,mBACA,oBAEJ,uCACI,iB;ACbR,iBACI,aACA,eAEI,+CACI,aACA,YACA,sBACA,mBACA,sBACA,cACA,yBACA,oBACA,iDACI,qBAEJ,gEACI,kBACA,qBACA,uBACA,WACA,iBACA,eAnBZ,6BAsBI,WACA,aACA,sBACA,mBAEA,6CACI,YACA,WACA,aACA,aACA,iDACI,WACA,YAKZ,0BACI,yBACA,WAGJ,gCACG,iB;AChDP,gBACI,aACA,qBACA,kCACA,gBACA,sBACA,uBACI,aACA,eACA,eACA,yBACA,sBACA,yBACA,SACA,cACA,eACA,YAEJ,qEACI,yBACA,WAEJ,qEACI,yBACA,WAEJ,6EACI,sBACA,WAEJ,8BACI,aACA,mBACA,iB","sources":["webpack://buckaroo-payments/./src/Resources/app/administration/src/module/buckaroo-payment/page/buckaroo-payment-detail/buckaroo-payment-detail.scss","webpack://buckaroo-payments/./src/Resources/app/administration/src/components/buckaroo-payment-list/style.scss","webpack://buckaroo-payments/./src/Resources/app/administration/src/components/buckaroo-toggle-status/style.scss"],"sourcesContent":[".buckaroo-feedback {\r\n .buckaroo-feedback__col{\r\n h3{\r\n text-align: center;\r\n }\r\n }\r\n}\r\n.buckaroo-payment-detail {\r\n .sw-product-variant-info {\r\n white-space: normal;\r\n text-overflow: unset;\r\n }\r\n .bk-reund-qty {\r\n text-align: right;\r\n }\r\n}",".bk-payment-wrap {\r\n display: flex;\r\n flex-wrap: wrap;\r\n .bk-payment {\r\n .bk-payment-inner {\r\n display: flex;\r\n width: 170px;\r\n flex-direction: column;\r\n align-items: center;\r\n margin: 0.25rem 0.125rem;\r\n padding: 0.5rem;\r\n background-color: #fafafa;\r\n border-radius: 0.5rem;\r\n a {\r\n text-decoration: none;\r\n }\r\n .bk-payment-name {\r\n text-align: center;\r\n text-decoration: none;\r\n padding: 0.25rem 0 0.5rem;;\r\n color: #555555;\r\n font-weight: bold;\r\n font-size: 16px;\r\n }\r\n }\r\n flex: 0 20%;\r\n display: flex;\r\n flex-direction: column;\r\n align-items: center;\r\n \r\n .bk-payment-img {\r\n height: 60px;\r\n width: auto;\r\n padding: 10px;\r\n display: flex;\r\n img {\r\n width: 100%;\r\n height: auto;\r\n }\r\n }\r\n \r\n }\r\n .bk-link {\r\n padding: 0.25rem 0 0.125rem;\r\n color: #555555;\r\n }\r\n\r\n .bk-link:hover {\r\n font-weight: bold;\r\n }\r\n}",".bk-toogle-wrap {\r\n display: flex;\r\n border-radius: 0.25rem;\r\n box-shadow: 0 0 1px rgba(0, 0, 0, 0.2);\r\n padding:0.125rem;\r\n background-color: #fff;\r\n button {\r\n outline: none;\r\n margin:0.125rem;\r\n padding:0.25rem;\r\n background-color: rgb(229 231 235);\r\n border-radius: 0.125rem;\r\n text-transform: uppercase;\r\n border:0;\r\n color: #9ca3af;\r\n cursor: pointer;\r\n flex-grow: 1;\r\n }\r\n button.test:hover, button.test.active {\r\n background-color: #eab308;\r\n color:#fff;\r\n }\r\n button.live:hover, button.live.active {\r\n background-color: #22c55e;\r\n color:#fff;\r\n }\r\n button.disabled:hover, button.disabled.active {\r\n background-color: #000;\r\n color:#fff;\r\n }\r\n .bk-edit-link {\r\n display: flex;\r\n align-items: center;\r\n margin:0 0.125rem\r\n }\r\n}"],"names":[],"sourceRoot":""} \ No newline at end of file diff --git a/src/Resources/public/administration/js/buckaroo-payments.js b/src/Resources/public/administration/js/buckaroo-payments.js deleted file mode 100644 index bb2f8d3c..00000000 --- a/src/Resources/public/administration/js/buckaroo-payments.js +++ /dev/null @@ -1,2 +0,0 @@ -(()=>{var e={519(){const{ApiService:e}=Shopware.Classes;class t extends e{constructor(e,t,n="buckaroo"){super(e,t,n)}getBasicHeaders(){return this.loginService&&"function"==typeof this.loginService.getToken?super.getBasicHeaders():{"Content-Type":"application/json",Accept:"application/json"}}getSupportVersion(){const t=`_action/${this.getApiBasePath()}/version`;return this.httpClient.post(t,{},{headers:this.getBasicHeaders()}).then(t=>e.handleResponse(t))}getTaxes(){const t=`_action/${this.getApiBasePath()}/taxes`;return this.httpClient.post(t,{},{headers:this.getBasicHeaders()}).then(t=>e.handleResponse(t))}getIn3Icons(){const t=`_action/${this.getApiBasePath()}/in3/logos`;return this.httpClient.post(t,{},{headers:this.getBasicHeaders()}).then(t=>e.handleResponse(t))}getApiTest(t,n,a){const r=`_action/${this.getApiBasePath()}/getBuckarooApiTest`;return this.httpClient.post(r,{websiteKeyId:t,secretKeyId:n,saleChannelId:a},{headers:this.getBasicHeaders()}).then(t=>e.handleResponse(t))}}Shopware.Service().register("BuckarooPaymentSettingsService",()=>{const e=Shopware.Application.getContainer("init"),n=Shopware.Service("loginService");return new t(e.httpClient,n)})},183(){const{ApiService:e}=Shopware.Classes;class t extends e{constructor(e,t,n="buckaroo"){super(e,t,n)}getBasicHeaders(){return this.loginService&&"function"==typeof this.loginService.getToken?super.getBasicHeaders():{"Content-Type":"application/json",Accept:"application/json"}}getBuckarooTransaction(t){const n=`_action/${this.getApiBasePath()}/getBuckarooTransaction`;return this.httpClient.post(n,{transaction:t},{headers:this.getBasicHeaders()}).then(t=>e.handleResponse(t))}refundPayment(t,n,a,r){const o=`_action/${this.getApiBasePath()}/refund`;return this.httpClient.post(o,{transaction:t,transactionsToRefund:n,orderItems:a,customRefundAmount:r},{headers:this.getBasicHeaders()}).then(t=>e.handleResponse(t))}captureOrder(t){const n=`_action/${this.getApiBasePath()}/capture`;return this.httpClient.post(n,{transaction:t},{headers:this.getBasicHeaders()}).then(t=>e.handleResponse(t))}createPaylink(t){const n=`_action/${this.getApiBasePath()}/paylink`;return this.httpClient.post(n,{transaction:t},{headers:this.getBasicHeaders()}).then(t=>e.handleResponse(t))}klarnaMor(t,n){const a=`_action/${this.getApiBasePath()}/klarna-mor`;return this.httpClient.post(a,{orderId:t,action:n},{headers:this.getBasicHeaders()}).then(t=>e.handleResponse(t))}}Shopware.Service().register("BuckarooPaymentService",()=>{const e=Shopware.Application.getContainer("init"),n=Shopware.Service("loginService");return new t(e.httpClient,n)})},622(){const{Component:e}=Shopware;e.extend("buckaroo-payment-config","sw-extension-config",{})}},t={};function n(a){var r=t[a];if(void 0!==r)return r.exports;var o=t[a]={exports:{}};return e[a](o,o.exports,n),o.exports}(()=>{"use strict";const{Component:e,Context:t}=Shopware,a=Shopware.Data.Criteria;e.override("sw-order-detail",{template:'{% block sw_order_detail_content_tabs %}\r\n \r\n
\r\n

{{ $tc(\'buckaroo-payment.paymentInTestMode\') }}

\r\n \r\n {% parent %}\r\n{% endblock %}\r\n\r\n\r\n{% block sw_order_detail_content_tabs_general %}\r\n {% parent %}\r\n\r\n \r\n {{ $tc(\'buckaroo-payment.tabs.title\') }}\r\n \r\n \r\n{% endblock %}\r\n\r\n{% block sw_order_detail_actions %}\r\n \r\n {% parent %}\r\n{% endblock %}',data:()=>({isBuckarooPayment:!1,isPaymentInTestMode:!1}),computed:{isEditable(){return!this.isBuckarooPayment||"buckaroo.payment.detail"!==this.$route.name},showTabs:()=>!0},watch:{orderId:{deep:!0,handler(){if(!this.orderId)return void this.setIsBuckarooPayment(null);const e=this.repositoryFactory.create("order"),n=new a(1,1);n.addAssociation("transactions"),e.get(this.orderId,t.api,n).then(e=>{if(this.setPaymentInTestMode(e),e.transactions.length<=0||!e.transactions.last().paymentMethodId)return void this.setIsBuckarooPayment(null);const t=e.transactions.last().paymentMethodId;null!=t&&this.setIsBuckarooPayment(t)})},immediate:!0}},methods:{setPaymentInTestMode(e){e.customFields&&e.customFields.buckaroo_payment_in_test_mode&&(this.isPaymentInTestMode=!0===e.customFields.buckaroo_payment_in_test_mode)},setIsBuckarooPayment(e){e&&this.repositoryFactory.create("payment_method").get(e,t.api).then(e=>{this.isBuckarooPayment=e.formattedHandlerIdentifier.indexOf("buckaroo")>=0})}}});const{Component:r,Context:o}=Shopware;Shopware.Data.Criteria,r.override("sw-order-detail-base",{template:'{% block sw_order_detail_base_line_items_summary %}\r\n\r\n \r\n \r\n \r\n
{{ $tc(\'buckaroo-payment.fee\') }}
\r\n
{{ order.customFields.buckarooFee }}\r\n {% if order.currency.isoCode == "PLN" %}\r\n PLN\r\n {% else %}\r\n {{ order.currency.symbol }}\r\n {% endif %}\r\n
\r\n
\r\n
\r\n
\r\n\r\n {% parent %}\r\n \r\n{% endblock %}'});const{Component:i}=Shopware;i.override("sw-order-user-card",{template:"{% block sw_order_detail_base_secondary_info_payment %}\r\n \r\n \r\n{% endblock %}\r\n\r\n",inject:["systemConfigApiService"],data:()=>({config:{}}),created(){this.systemConfigApiService.getValues("BuckarooPayments.config",null).then(e=>{this.config=e}).finally(()=>{})}});const{Component:s}=Shopware;s.override("sw-system-config",{template:' {% block sw_system_config_content_card %}\r\n \r\n \r\n {% endblock %}',watch:{currentSalesChannelId:{handler(e,t){e&&"BuckarooPayments.config"===this.domain&&this.loadBuckarooConfigData()},immediate:!0},domain:{handler(e){"BuckarooPayments.config"===e&&this.currentSalesChannelId&&this.loadBuckarooConfigData()},immediate:!0}},methods:{loadBuckarooConfigData(){this.systemConfigApiService.getValues("BuckarooPayments.config",this.currentSalesChannelId).then(e=>{this.actualConfigData[this.currentSalesChannelId]||(this.actualConfigData[this.currentSalesChannelId]={});const t={};e&&"object"==typeof e&&Object.keys(e).forEach(n=>{const a=e[n];a&&"object"==typeof a&&a.hasOwnProperty("_value")?t[n]=a._value:t[n]=a;const r=n.replace("BuckarooPayments.config.","");r!==n&&(t[r]=t[n])}),this.actualConfigData[this.currentSalesChannelId]={},Object.keys(t).forEach(e=>{this.actualConfigData[this.currentSalesChannelId][e]=t[e]}),this.$nextTick(()=>{this.$forceUpdate()})}).catch(e=>{console.error("Error fetching system config:",e)})},onConfigDataUpdate(e){this.actualConfigData[this.currentSalesChannelId]||(this.actualConfigData[this.currentSalesChannelId]={}),Object.keys(e).forEach(t=>{if(this.actualConfigData[this.currentSalesChannelId][t]=e[t],!t.startsWith("BuckarooPayments.config.")){const n=`BuckarooPayments.config.${t}`;this.actualConfigData[this.currentSalesChannelId][n]=e[t]}})},saveAll(){return"BuckarooPayments.config"!==this.domain?this.$super("saveAll"):this.saveBuckaroo()},saveBuckaroo(){return this.isLoading=!0,this.systemConfigApiService.batchSave(this.getSelectedValues()).finally(()=>{this.isLoading=!1})},getCurrentConfigCard(){const e=this.$route.params?.paymentCode||"general";return this.config.filter(t=>t.name===e)?.pop()},getSelectedValues(){const e=this.actualConfigData[this.currentSalesChannelId],t=this.getCurrentConfigCard();if(t?.elements){let n={};return t?.elements.forEach(t=>{if(t?.name){let a=e[t.name];if(void 0===a){const n=t.name.replace("BuckarooPayments.config.","");a=e[n]}n[t.name]=a}}),{[this.currentSalesChannelId]:n}}return this.actualConfigData}}});const{Component:l,Filter:c,Context:d}=Shopware,u=Shopware.Data.Criteria;l.register("buckaroo-payment-detail",{template:'{% block buckaroo_payment_detail %}\r\n
\r\n \r\n \r\n\r\n {{ $tc(\'buckaroo-payment.paymentDetail.paylinkDescription\') }}\r\n \r\n
\r\n {{ $tc(\'buckaroo-payment.paymentDetail.yourLink\') }}: {{ paylink }}\r\n
\r\n\r\n \r\n
\r\n \r\n \r\n {{ $tc(\'buckaroo-payment.paymentDetail.paylinkButton\') }}\r\n
\r\n
\r\n
\r\n\r\n
\r\n\r\n \r\n \r\n {{ $tc(\'buckaroo-payment.orderItems.title\') }}\r\n \r\n\r\n \r\n \r\n\r\n \r\n\r\n \r\n \r\n
{{ $tc(\'buckaroo-payment.paymentDetail.amountTotalTitle\') }}:
\r\n
{{ buckaroo_refund_amount }} {{ currency }}
\r\n
\r\n
\r\n \r\n \r\n \r\n \r\n\r\n \r\n\r\n \r\n\r\n \r\n\r\n \r\n\r\n \r\n \r\n
{{ $tc(\'buckaroo-payment.paymentDetail.amountCustomRefundTitle\') }}:
\r\n
\r\n \r\n {{ currency }}\r\n
\r\n
\r\n \r\n
{{ $tc(\'buckaroo-payment.paymentDetail.amountRefundTotalTitle\') }}:
\r\n
{{ buckaroo_refund_total_amount }} {{ currency }}
\r\n
\r\n
\r\n \r\n
\r\n\r\n \r\n
\r\n \r\n {{ $tc(\'buckaroo-payment.paymentDetail.buttonTitle\') }}\r\n
\r\n
\r\n
\r\n\r\n
\r\n\r\n \r\n\r\n {{ $tc(\'buckaroo-payment.paymentDetail.payDescription\') }}\r\n\r\n \r\n
\r\n \r\n {{ $tc(\'buckaroo-payment.paymentDetail.payButton\') }}\r\n
\r\n
\r\n
\r\n\r\n
\r\n\r\n \r\n\r\n {{ $tc(\'buckaroo-payment.paymentDetail.klarnaMorDescription\') }}\r\n\r\n \r\n \r\n
{{ $tc(\'buckaroo-payment.paymentDetail.klarnaMorCancel\') }}
\r\n
\r\n \r\n {{ $tc(\'buckaroo-payment.paymentDetail.klarnaMorCancelButton\') }}\r\n \r\n
\r\n
\r\n
\r\n\r\n \r\n \r\n
{{ $tc(\'buckaroo-payment.paymentDetail.klarnaMorUpdate\') }}
\r\n
\r\n \r\n {{ $tc(\'buckaroo-payment.paymentDetail.klarnaMorUpdateButton\') }}\r\n \r\n
\r\n
\r\n
\r\n\r\n \r\n \r\n
{{ $tc(\'buckaroo-payment.paymentDetail.klarnaMorExtend\') }}
\r\n
\r\n \r\n {{ $tc(\'buckaroo-payment.paymentDetail.klarnaMorExtendButton\') }}\r\n \r\n
\r\n
\r\n
\r\n\r\n \r\n \r\n
{{ $tc(\'buckaroo-payment.paymentDetail.klarnaMorShipping\') }}
\r\n
\r\n \r\n {{ $tc(\'buckaroo-payment.paymentDetail.klarnaMorShippingButton\') }}\r\n \r\n
\r\n
\r\n
\r\n\r\n
\r\n\r\n \r\n \r\n\r\n \r\n\r\n \r\n \r\n\r\n\r\n \r\n \r\n
\r\n{% endblock %}',inject:["repositoryFactory","BuckarooPaymentService","systemConfigApiService"],data:()=>({config:{},buckaroo_refund_amount:"0",buckaroo_refund_total_amount:"0",currency:"EUR",isRefundPossible:!0,isCapturePossible:!1,isPaylinkAvailable:!1,isPaylinkVisible:!1,paylinkMessage:"",paylink:"",isLoading:!1,order:!1,buckarooTransactions:null,orderItems:[],transactionsToRefund:[],relatedResources:[],isAuthorized:!1,isKlarnaMor:!1,fulfillmentMessage:"",fulfillmentStatus:null}),computed:{orderItemsColumns(){return[{property:"name",label:this.$tc("buckaroo-payment.orderItems.types.name"),allowResize:!1,primary:!0,inlineEdit:!0,multiLine:!0},{property:"quantity",label:this.$tc("buckaroo-payment.orderItems.types.quantity"),rawData:!0,align:"right"},{property:"totalAmount",label:this.$tc("buckaroo-payment.orderItems.types.totalAmount"),rawData:!0,align:"right"}]},transactionsToRefundColumns:()=>[{property:"transaction_method",rawData:!0},{property:"amount",rawData:!0}],relatedResourceColumns(){return[{property:"created_at",label:this.$tc("buckaroo-payment.transactionHistory.types.created_at"),rawData:!0},{property:"total",label:this.$tc("buckaroo-payment.transactionHistory.types.total"),rawData:!0},{property:"shipping_costs",label:this.$tc("buckaroo-payment.transactionHistory.types.shipping_costs"),rawData:!0},{property:"total_excluding_vat",label:this.$tc("buckaroo-payment.transactionHistory.types.total_excluding_vat"),rawData:!0},{property:"vat",label:this.$tc("buckaroo-payment.transactionHistory.types.vat"),rawData:!0},{property:"transaction_key",label:this.$tc("buckaroo-payment.transactionHistory.types.transaction_key"),rawData:!0},{property:"transaction_method",label:this.$tc("buckaroo-payment.transactionHistory.types.transaction_method"),rawData:!0},{property:"statuscode",label:this.$tc("buckaroo-payment.transactionHistory.types.statuscode"),rawData:!0}]}},created(){this.createdComponent()},methods:{recalculateOrderItems(){this.buckaroo_refund_amount=0;for(const e in this.orderItems)this.orderItems[e].totalAmount=parseFloat(parseFloat(this.orderItems[e].unitPrice)*parseFloat(this.orderItems[e].quantity||0)).toFixed(2),this.buckaroo_refund_amount=parseFloat(parseFloat(this.buckaroo_refund_amount)+parseFloat(this.orderItems[e].totalAmount)).toFixed(2)},recalculateRefundItems(){this.buckaroo_refund_total_amount=0;for(const e in this.transactionsToRefund)this.transactionsToRefund[e].amount&&(this.buckaroo_refund_total_amount=parseFloat(parseFloat(this.buckaroo_refund_total_amount)+parseFloat(this.transactionsToRefund[e].amount)).toFixed(2))},getCustomRefundEnabledEl:()=>document.getElementById("buckaroo_custom_refund_enabled"),getCustomRefundAmountEl:()=>document.getElementById("buckaroo_custom_refund_amount"),toggleCustomRefund(){this.getCustomRefundEnabledEl()&&this.getCustomRefundAmountEl()&&(this.getCustomRefundAmountEl().disabled=!this.getCustomRefundEnabledEl().checked)},getCustomRefundAmount(){return this.getCustomRefundEnabledEl()&&this.getCustomRefundAmountEl()&&this.getCustomRefundEnabledEl().checked?this.getCustomRefundAmountEl().value:0},createdComponent(){let e=this;const t=this.$route.params.id;this.systemConfigApiService.getValues("BuckarooPayments.config",null).then(e=>{this.config=e});const n=this.repositoryFactory.create("order"),a=new u(1,1);this.orderId=t,a.addAssociation("transactions.paymentMethod").addAssociation("transactions"),a.getAssociation("transactions").addSorting(u.sort("createdAt")),n.get(t,d.api,a).then(t=>{e.checkedIsAuthorized(t);const n=t.transactions&&t.transactions.last().paymentMethod&&t.transactions.last().paymentMethod.customFields&&t.transactions.last().paymentMethod.customFields.buckaroo_key?t.transactions.last().paymentMethod.customFields.buckaroo_key.toLowerCase():"";e.isCapturePossible=!!n&&(["klarnakp","billink","afterpay","klarna","wero"].includes(n)||e.isAfterpayCapturePossible(t)),e.isKlarnaMor="klarna"===n,e.isPaylinkVisible=e.isPaylinkAvailable=this.getConfigValue("paylinkEnabled")&&t.stateMachineState&&t.stateMachineState.technicalName&&"open"==t.stateMachineState.technicalName&&t.transactions&&"open"==t.transactions.last().stateMachineState.technicalName}),this.BuckarooPaymentService.getBuckarooTransaction(t).then(t=>{e.orderItems=[],e.transactionsToRefund=[],e.relatedResources=[],this.$emit("loading-change",!1),t.orderItems&&Array.isArray(t.orderItems)&&t.orderItems.forEach(t=>{e.orderItems.push({id:t.id,name:t.name,quantity:t.quantity,quantityMax:t.quantity,unitPrice:t.unitPrice.value,totalAmount:t.totalAmount.value,variations:t.variations||[]})}),e.buckaroo_refund_amount=t.refundTotals?t.refundTotals.totalAmount:0,e.currency=t.refundTotals?t.refundTotals.currency:"EUR",t.transactionsToRefund&&Array.isArray(t.transactionsToRefund)&&t.transactionsToRefund.forEach(t=>{e.transactionsToRefund.push({id:t.id,transactions:t.transactions,amount:t.total,amountMax:t.total,currency:t.currency,transaction_method:t.transaction_method,logo:t.transaction_method?t.logo:null}),e.currency=t.currency}),e.recalculateRefundItems(),t.transactions&&Array.isArray(t.transactions)&&t.transactions.forEach(t=>{e.relatedResources.push({id:t.id,transaction_key:t.transaction,total:t.total,total_excluding_vat:t.total_excluding_vat,shipping_costs:t.shipping_costs,vat:t.vat,transaction_method:t.transaction_method,logo:t.transaction_method?t.logo:null,created_at:t.created_at,statuscode:t.statuscode})})}).catch(e=>{console.log("errorResponse",e)})},isAfterpayCapturePossible:e=>!0===e.customFields.buckaroo_is_authorize,checkedIsAuthorized(e){this.isAuthorized="authorized"===e?.transactions?.last()?.stateMachineState?.technicalName},refundOrder(e,t){let n=this;n.isRefundPossible=!1,this.BuckarooPaymentService.refundPayment(e,this.transactionsToRefund,this.orderItems,this.getCustomRefundAmount()).then(e=>{for(const t in e)e[t].status?this.$store.dispatch("notification/createNotification",{variant:"success",title:n.$tc("buckaroo-payment.settingsForm.titleSuccess"),message:n.$tc(e[t].message)+e[t].amount}):this.$store.dispatch("notification/createNotification",{variant:"error",title:n.$tc("buckaroo-payment.settingsForm.titleError"),message:n.$tc(e[t].message)});n.isRefundPossible=!0,this.createdComponent()}).catch(e=>{this.$store.dispatch("notification/createNotification",{variant:"error",title:this.$tc("buckaroo-payment.settingsForm.titleError"),message:e.response.data.message}),n.isRefundPossible=!0})},createPaylink(e){let t=this;t.isPaylinkAvailable=!1,this.BuckarooPaymentService.createPaylink(e,this.transactionsToRefund,this.orderItems).then(e=>{e.status?(t.paylinkMessage=t.$tc(e.message)+e.paylinkhref,t.paylink=e.paylink,this.$store.dispatch("notification/createNotification",{variant:"success",title:t.$tc("buckaroo-payment.settingsForm.titleSuccess"),message:t.paylinkMessage})):this.$store.dispatch("notification/createNotification",{variant:"error",title:t.$tc("buckaroo-payment.settingsForm.titleError"),message:t.$tc(e.message)}),t.isPaylinkAvailable=!0}).catch(e=>{this.$store.dispatch("notification/createNotification",{variant:"error",title:this.$tc("buckaroo-payment.settingsForm.titleError"),message:e.response.data.message}),t.isPaylinkAvailable=!0})},getConfigValue(e){return this.config[`BuckarooPayments.config.${e}`]},captureOrder(e){let t=this;t.isCapturePossible=!1,this.BuckarooPaymentService.captureOrder(e,this.transactionsToRefund,this.orderItems).then(e=>{e.status?this.$store.dispatch("notification/createNotification",{variant:"success",title:t.$tc("buckaroo-payment.settingsForm.titleSuccess"),message:e.message}):this.$store.dispatch("notification/createNotification",{variant:"error",title:t.$tc("buckaroo-payment.settingsForm.titleError"),message:e.message}),t.isCapturePossible=!0,this.createdComponent()}).catch(e=>{this.$store.dispatch("notification/createNotification",{variant:"error",title:this.$tc("buckaroo-payment.settingsForm.titleError"),message:t.$tc(e.response.data.message)}),t.isCapturePossible=!0})},klarnaMor(e){let t=this;t.isLoading=!0,this.BuckarooPaymentService.klarnaMor(this.orderId,e).then(e=>{e.status?this.$store.dispatch("notification/createNotification",{variant:"success",title:t.$tc("buckaroo-payment.settingsForm.titleSuccess"),message:e.message}):this.$store.dispatch("notification/createNotification",{variant:"error",title:t.$tc("buckaroo-payment.settingsForm.titleError"),message:e.message}),t.isLoading=!1,this.createdComponent()}).catch(e=>{this.$store.dispatch("notification/createNotification",{variant:"error",title:this.$tc("buckaroo-payment.settingsForm.titleError"),message:e.response&&e.response.data?e.response.data.message:"An error occurred"}),t.isLoading=!1})}}}),n(622);const p=JSON.parse('{"buckaroo-payment":{"fee":"Buckaroo Betaaltoeslag","order":{"refundDescription":"Refund voor bestelling #orderNumber"},"general":{"title":"Buckaroo","description":"Buckaroo Payment"},"settingsForm":{"save":"Opslaan","titleSuccess":"Succes","titleError":"Foutmelding"},"supportModal":{"menuButton":"Version & Support","title":"Versie & Support","support":{"description":"Zorg ervoor dat u uw website key bij de hand heeft voordat u contact opneemt met Buckaroo technical support","label1":"Buckaroo Plaza:","label2":"Telefoonnummer:","label3":"E-mail:","label4":"Website:","your_version":"Uw PHP versie:","version":"Versie compatibiliteit","information":"Informatie"}},"tabs":{"title":"Buckaroo Payment","overview":"Overzicht"},"paymentDetail":{"yourLink":"Uw Paylink","paylinkButton":"Creëer Paylink","paylinkDescription":"Creëer Paylink voor order","paylinkTitle":"Paylink","refundTitle":"Terugbetaling","transactionsTitle":"Transacties","amountTitle":"Hoeveelheid","amountTotalTitle":"Algemeen totaal (grand total)","amountRefundTotalTitle":"Terugbetaling Algemeen totaal (grand total)","amountCustomRefundTitle":"Aangepast bedrag terugbetalen","buttonTitle":"Terugbetaling","successTitle":"Success","successMessage":"Buckaroo terugbetaling succesvol","errorTitle":"Foutmelding","payTitle":"Betaling vastleggen (Capture)","payDescription":"Factuur voor bestelling vastleggen (Capture) en aanmaken","payButton":"Betaling vastleggen (Capture)","klarnaMorTitle":"Klarna (MoR)","klarnaMorDescription":"Beheer de Klarna reservering voor deze bestelling.","klarnaMorCancel":"Reservering annuleren","klarnaMorCancelButton":"Reservering annuleren","klarnaMorUpdate":"Reservering bijwerken","klarnaMorUpdateButton":"Reservering bijwerken","klarnaMorExtend":"Reservering verlengen","klarnaMorExtendButton":"Reservering verlengen","klarnaMorShipping":"Verzendinfo toevoegen","klarnaMorShippingButton":"Verzendinfo toevoegen"},"orderItems":{"title":"Artikelen om terug te betalen","types":{"id":"id","name":"Titel","quantity":"Aantal om terug te betalen","totalAmount":"Subtotaal"}},"transactionsToRefund":{"title":"Terugbetaling Totaal"},"transactionHistory":{"types":{"id":"id","created_at":"Datum/tijd","total":"Totaal","shipping_costs":"Verzendkosten","total_excluding_vat":"Totaal exclusief BTW","total_including_vat":"Totaal inclusief BTW","vat":"BTW","transaction_key":"Transactie key","transaction_method":"Betaalmethode","statuscode":"Status"}},"messageNotValid":"Dit veld is niet geldig.","messageNotBlank":"Dit veld mag niet leeg zijn.","button":{"labelTestApi":"Test gegevens"},"afterpay":{"setup":"Belastingkoppeling instellen voor Riverty old ","hightTaxes":"Hoge BTW-heffingen","middleTaxes":"Middelmatige BTW-belastingen","lowTaxes":"Lage BTW-heffingen","zeroTaxes":"Nul VAT","noTaxes":"Geen BTW"},"paymentInTestMode":"De betaling voor deze bestelling is in testmodus uitgevoerd","refund":{"not_supported":"Terugbetaling wordt niet ondersteund","already_refunded":"Deze bestelling is al terugbetaald","refunded_amount":"Buckaroo terugbetaling succesvol"},"test_api":{"connection_ready":"Verbinding gereed","connection_failed":"Verbinding mislukt"},"paylink":{"invalid_amount":"Het bedrag is niet geldig","pay_link":"Uw Paylink:"},"missing_order_id":"Ontbrekende bestelling orderId","missing_transaction":"Order transactie niet gevonden","general_request_error":"Helaas is er een fout opgetreden tijdens het verwerken van uw aanvraag. Probeer het opnieuw.","in3LogoLabel":"Betaalmethode Logo:","configure-payment":"Configure payment","configure-link":"Configure","payment-methods":"Payment methods"}}'),m=JSON.parse('{"buckaroo-payment":{"fee":"Buckaroo Gebühr","order":{"refundDescription":"Rückerstattung für Bestellung #orderNumber"},"general":{"title":"Buckaroo","description":"Buckaroo Zahlung"},"settingsForm":{"save":"Speichern","titleSuccess":"Erfolg","titleError":"Fehler"},"supportModal":{"menuButton":"Version & Unterstützung","title":"Version & Unterstützung","support":{"description":"Bevor Sie den technischen Support von Buckaroo kontaktieren, bitte holen Sie Ihren (Händler-)Schlüssel und Geheimschlüssel ab.","label1":"Buckaroo Plaza:","label2":"Telefon:","label3":"E-Mail:","label4":"Webseite:","your_version":"Ihre PHP-Version:","version":"Versionskompatibilität","information":"Informationen"}},"tabs":{"title":"Buckaroo Payment","overview":"Übersicht"},"paymentDetail":{"yourLink":"Ihr Paylink","paylinkButton":"Paylink erstellen","paylinkDescription":"Paylink erstellen für Bestellung","paylinkTitle":"Paylink","refundTitle":"Rückerstattung","transactionsTitle":"Transaktionen","amountTitle":"Betrag","amountTotalTitle":"Gesamtsumme","amountRefundTotalTitle":"Gesamtsumme der Rückerstattung","amountCustomRefundTitle":"Rückerstattung individueller Betrag","buttonTitle":"Rückerstattung","successTitle":"Erfolg","successMessage":"Buckaroo-Erfolg, zurückerstattet","errorTitle":"Fehler","payTitle":"Zahlung erfassen (Capture)","payDescription":"Erfassen (Capture) und Rechnung für Bestellung erstellen","payButton":"Zahlung erfassen (Capture)","klarnaMorTitle":"Klarna (MoR)","klarnaMorDescription":"Verwalten Sie die Klarna-Reservierung für diese Bestellung.","klarnaMorCancel":"Reservierung stornieren","klarnaMorCancelButton":"Reservierung stornieren","klarnaMorUpdate":"Reservierung aktualisieren","klarnaMorUpdateButton":"Reservierung aktualisieren","klarnaMorExtend":"Reservierung verlängern","klarnaMorExtendButton":"Reservierung verlängern","klarnaMorShipping":"Versandinformationen hinzufügen","klarnaMorShippingButton":"Versandinformationen hinzufügen"},"orderItems":{"title":"Artikel zur Rückerstattung","types":{"id":"id","name":"Titel","quantity":"Menge zur Rückerstattung","totalAmount":"Teilsumme"}},"transactionsToRefund":{"title":"Rückerstattungssummen"},"transactionHistory":{"types":{"id":"id","created_at":"Datum/Uhrzeit","total":"Gesamt","shipping_costs":"Versandkosten","total_excluding_vat":"Gesamt ohne MwSt. (VAT)","total_including_vat":"Gesamt inklusive MwSt. (VAT)","vat":"MwSt. (VAT)","transaction_key":"Transaktionsschlüssel","transaction_method":"Zahlungsmethode","statuscode":"Status"}},"messageNotValid":"Dieses Feld ist nicht gültig.","messageNotBlank":"Dieses Feld darf nicht leer sein.","button":{"labelTestApi":"Verbindung testen"},"afterpay":{"setup":"Steuerzuordnung für Riverty old einrichten ","hightTaxes":"Hohe MwSt. (VAT)","middleTaxes":"Mittlere MwSt. (VAT)","lowTaxes":"Niedrige MwSt. (VAT)","zeroTaxes":"Keine MwSt. (VAT)","noTaxes":"Keine Mehrwertsteuer"},"paymentInTestMode":"Die Zahlung für diese Bestellung wurde im Testmodus durchgeführt","refund":{"not_supported":"Rückerstattung wird nicht unterstützt","already_refunded":"Diese Bestellung wurde bereits zurückerstattet","refunded_amount":"Erfolgreich von Buckaroo erstattet"},"test_api":{"connection_ready":"Verbindung bereit","connection_failed":"Verbindung fehlgeschlagen"},"paylink":{"invalid_amount":"Betrag ist nicht gültig","pay_link":"Ihr Zahlungslink (Paylink):"},"missing_order_id":"Fehlende Bestell-ID","missing_transaction":"Transaktion der Bestellung nicht gefunden","general_request_error":"Leider ist ein Fehler bei der Bearbeitung Ihrer Anfrage aufgetreten. Bitte versuchen Sie es erneut.","in3LogoLabel":"Zahlungslogo:","configure-payment":"Configure payment","configure-link":"Configure","payment-methods":"Payment methods"}}'),g=JSON.parse('{"buckaroo-payment":{"fee":"Buckaroo Fee","order":{"refundDescription":"Refund for order #orderNumber"},"general":{"title":"Buckaroo","description":"Buckaroo Payment"},"settingsForm":{"save":"Save","titleSuccess":"Success","titleError":"Error"},"supportModal":{"menuButton":"Version & Support","title":"Version & Support","support":{"description":"Before contacting Buckaroo technical support, please retrieve your (Merchant) key, Secret key, certificate and certificate thumbprint.","label1":"Buckaroo Payment Plaza:","label2":"Phone:","label3":"E-mail:","label4":"Website:","your_version":"Your PHP version:","version":"Version compatibility","information":"Information"}},"tabs":{"title":"Buckaroo Payment","overview":"Overview"},"paymentDetail":{"yourLink":"Your Paylink","paylinkButton":"Create paylink","paylinkDescription":"Create paylink for order","paylinkTitle":"Paylink","refundTitle":"Refund","transactionsTitle":"Transactions","amountTitle":"Amount","amountTotalTitle":"Grand total","amountRefundTotalTitle":"Refund Grand total","amountCustomRefundTitle":"Refund custom amount","buttonTitle":"Refund","successTitle":"Success","successMessage":"Buckaroo success refunded ","errorTitle":"Error","payTitle":"Capture payment","payDescription":"Capture and create invoice for order","payButton":"Capture payment","klarnaMorTitle":"Klarna (MoR)","klarnaMorDescription":"Manage the Klarna reservation for this order.","klarnaMorCancel":"Cancel reservation","klarnaMorCancelButton":"Cancel reservation","klarnaMorUpdate":"Update reservation","klarnaMorUpdateButton":"Update reservation","klarnaMorExtend":"Extend reservation","klarnaMorExtendButton":"Extend reservation","klarnaMorShipping":"Add shipping info","klarnaMorShippingButton":"Add shipping info"},"orderItems":{"title":"Items to Refund","types":{"id":"id","name":"Title","quantity":"Qty to Refund","totalAmount":"Subtotal"}},"transactionsToRefund":{"title":"Refund Totals"},"transactionHistory":{"types":{"id":"id","created_at":"Date/time","total":"Total","shipping_costs":"Shipping costs","total_excluding_vat":"Total excluding VAT","total_including_vat":"Total including VAT","vat":"VAT","transaction_key":"Transaction key","transaction_method":"Payment method","statuscode":"Status"}},"messageNotValid":"This field not valid.","messageNotBlank":"This field must not be empty.","button":{"labelTestApi":"Test connection"},"afterpay":{"setup":"Setup tax association for Riverty old ","hightTaxes":"High VAT taxes","middleTaxes":"Middle VAT taxes","lowTaxes":"Low VAT taxes","zeroTaxes":"Zero VAT","noTaxes":"No VAT tax"},"paymentInTestMode":"The payment for this order was made in test mode","refund":{"not_supported":"Refund is not supported","already_refunded":"This order is already refunded","refunded_amount":"Buckaroo success refunded"},"test_api":{"connection_ready":"Connection ready","connection_failed":"Connection failed"},"paylink":{"invalid_amount":"Amount is not valid","pay_link":"Your Paylink:"},"missing_order_id":"Missing order orderId","missing_transaction":"Order transaction not found","general_request_error":"Unfortunately an error occurred while processing your request. Please try again.","in3LogoLabel":"Payment Logo:","configure-payment":"Configure payment","configure-link":"Configure","payment-methods":"Payment methods"}}'),{Module:h}=Shopware;h.register("buckaroo-payment",{type:"plugin",name:"BuckarooPayment",title:"buckaroo-payment.general.title",description:"buckaroo-payment.general.description",version:"1.0.0",targetVersion:"1.0.0",color:"#000000",icon:"default-action-settings",snippets:{"nl-NL":p,"de-DE":m,"en-GB":g},routeMiddleware(e,t){"sw.order.detail"===t.name&&t.children.push({component:"buckaroo-payment-detail",name:"buckaroo.payment.detail",isChildren:!0,path:"/sw/order/buckaroo/detail/:id"}),e(t)},routes:{config:{component:"buckaroo-payment-config",path:":namespace/payment/:paymentCode",name:"buckaroo.config.payment",meta:{parentPath:"sw.extension.config"},props:{default:e=>({namespace:e.params.namespace})}}}}),n(183),n(519);const{Component:y}=Shopware;y.register("buckaroo-afterpay-old-tax",{template:'
\r\n {{$tc(\'buckaroo-payment.afterpay.setup\')}}\r\n
\r\n
\r\n \r\n
\r\n
\r\n
',inject:["BuckarooPaymentSettingsService"],data(){return{taxes:[],showTaxes:!1,afterpayTaxes:[{name:this.$tc("buckaroo-payment.afterpay.hightTaxes"),id:1},{name:this.$tc("buckaroo-payment.afterpay.middleTaxes"),id:5},{name:this.$tc("buckaroo-payment.afterpay.lowTaxes"),id:2},{name:this.$tc("buckaroo-payment.afterpay.zeroTaxes"),id:3},{name:this.$tc("buckaroo-payment.afterpay.noTaxes"),id:4}],taxAssociation:{}}},model:{prop:"value",event:"change"},computed:{},props:{name:{type:String,required:!0,default:""},value:{type:Object,required:!1,default:()=>({})}},created(){this.BuckarooPaymentSettingsService.getTaxes().then(e=>{this.taxes=e.taxes.map(e=>({id:e.id,name:e.name}))})},methods:{setTaxAssociation(e,t){try{let n=t;t&&"object"==typeof t&&(t.target?n=t.target.value:t.hasOwnProperty("value")?n=t.value:t.hasOwnProperty("id")&&(n=t.id)),this.taxAssociation[e]=n,this.$emit("change",{...this.value,...this.taxAssociation})}catch(e){console.error("Error in setTaxAssociation:",e)}},getSelectValue(e){if(this.value[e])return this.value[e]}}});const{Component:f}=Shopware;f.register("buckaroo-main-config",{template:'
\r\n \r\n \r\n\r\n \r\n \r\n
',props:{configSettings:{type:Array,required:!1,default:()=>[]},value:{type:Object,required:!1,default:()=>({})},elementMethods:{type:Object,required:!1,default:()=>({})},isNotDefaultSalesChannel:{type:Boolean,required:!1,default:!1},currentSalesChannelId:{type:String,required:!1,default:null}},emits:["input"],model:{prop:"value",event:"input"},data(){return{selectedCard:this.$route.params?.paymentCode||"general"}},watch:{value:{handler(e,t){this.$nextTick(()=>{this.$forceUpdate()})},deep:!0,immediate:!0},$route(e){e.params?.paymentCode&&(this.selectedCard=e.params.paymentCode)}},computed:{mainCard(){const e=this.configSettings.filter(e=>e.name===this.selectedCard)?.pop();return e}},methods:{onInput(e){this.$emit("input",e)}}});const{Component:b}=Shopware;b.register("buckaroo-config-card",{template:'{% block buckaroo_config_card %}\r\n \r\n \r\n\r\n
\r\n
\r\n \r\n \r\n \r\n \r\n \r\n
\r\n
\r\n\r\n \r\n
\r\n{% endblock %}\r\n',inject:["BuckarooPaymentSettingsService"],data:()=>({shopwareVersion:null}),mounted(){this.fetchShopwareVersion(),this.$nextTick(()=>{this.$forceUpdate()})},watch:{value:{handler(){this.$nextTick(()=>{this.$forceUpdate()})},deep:!0,immediate:!0},currentSalesChannelId:{handler(e,t){e!==t&&this.$nextTick(()=>{this.$forceUpdate()})},immediate:!1}},computed:{canShowCredentialTester(){const e=this.getValueForName("websiteKey"),t=this.getValueForName("secretKey");return"general"===this.card?.name&&(null!=e&&""!==e||null!=t&&""!==t)},hasValidConfigData(){return this.value&&"object"==typeof this.value&&Object.keys(this.value).length>0},reactiveValue(){return this.value}},emits:["input"],model:{prop:"value",event:"input"},props:{card:{type:Object,required:!1,default:()=>({elements:[]})},configSettings:{type:Array,required:!1,default:()=>[]},methods:{type:Object,required:!0},isNotDefaultSalesChannel:{type:Boolean,required:!0},currentSalesChannelId:{type:String,required:!0},value:{type:Object,required:!1,default:()=>({})}},methods:{fetchShopwareVersion(){const e=this.BuckarooPaymentSettingsService;e&&"function"==typeof e.getSupportVersion&&e.getSupportVersion().then(e=>{e&&e.shopware_version&&(this.shopwareVersion=e.shopware_version)}).catch(()=>{})},isShopware674OrNewer(){if(!this.shopwareVersion||"string"!=typeof this.shopwareVersion)return!1;const e=this.shopwareVersion.split(".").map(e=>parseInt(e,10)||0),t=e[0]||0,n=e[1]||0,a=e[2]||0,r=e[3]||0;return t>6||!(t<6)&&(n>7||!(n<7)&&(a>4||!(a<4)&&r>=0))},getElementBind(e,t={}){if(!this.methods||!this.methods.getElementBind){const t=e.label?this.getInlineSnippet(e.label):null;return{name:e.name,type:e.type||"text",config:e.config||{},label:t,value:this.getValueForName(e.name.replace("BuckarooPayments.config.",""))}}const n=this.methods.getElementBind(e,t),a=e.name.replace("BuckarooPayments.config.","");let r=this.getValueForName(a);const o=n.config||e.config||{};"bool"===e.type&&(r=null==r?void 0!==n.value&&n.value:"string"==typeof r?"1"===r||"true"===r||"on"===r:Boolean(r));let i=null;const s=this.isShopware674OrNewer();if(s){if(("bool"===e.type||"single-select"===e.type||"multi-select"===e.type)&&this.configSettings&&Array.isArray(this.configSettings))for(const t of this.configSettings)if(t.elements&&Array.isArray(t.elements)){const n=t.elements.find(t=>t.name===e.name);if(n){if(n.label){let e=this.getInlineSnippet(n.label);if(!e||"string"==typeof e&&0===e.trim().length)if("object"==typeof n.label&&null!==n.label){const t=this.$i18n?.locale||"en-GB";e=n.label[t]||n.label["en-GB"]||Object.values(n.label)[0]||null}else"string"==typeof n.label&&(e=n.label);if(e&&"string"==typeof e&&e.trim().length>0){i=e;break}}if(!i&&n.config&&n.config.label){let e=this.getInlineSnippet(n.config.label);if(!e||"string"==typeof e&&0===e.trim().length)if("object"==typeof n.config.label&&null!==n.config.label){const t=this.$i18n?.locale||"en-GB";e=n.config.label[t]||n.config.label["en-GB"]||Object.values(n.config.label)[0]||null}else"string"==typeof n.config.label&&(e=n.config.label);if(e&&"string"==typeof e&&e.trim().length>0){i=e;break}}}}if(!i)if(n.label&&"string"==typeof n.label&&n.label.trim().length>0)i=n.label;else if(e.label){let t=this.getInlineSnippet(e.label);if(!t||"string"==typeof t&&0===t.trim().length)if("object"==typeof e.label&&null!==e.label){const n=this.$i18n?.locale||"en-GB";t=e.label[n]||e.label["en-GB"]||Object.values(e.label)[0]||null}else"string"==typeof e.label&&(t=e.label);t&&"string"==typeof t&&t.trim().length>0&&(i=t)}else if(this.card&&this.card.elements&&Array.isArray(this.card.elements)){const t=this.card.elements.find(t=>t.name===e.name);if(t&&t.label){let e=this.getInlineSnippet(t.label);if(!e||"string"==typeof e&&0===e.trim().length)if("object"==typeof t.label&&null!==t.label){const n=this.$i18n?.locale||"en-GB";e=t.label[n]||t.label["en-GB"]||Object.values(t.label)[0]||null}else"string"==typeof t.label&&(e=t.label);e&&"string"==typeof e&&e.trim().length>0&&(i=e)}}!i&&n.config&&n.config.label&&"string"==typeof n.config.label&&n.config.label.trim().length>0&&(i=n.config.label)}let l=o;s&&i&&"string"==typeof i&&i.trim().length>0&&("bool"!==e.type&&"single-select"!==e.type&&"multi-select"!==e.type||(l={...o,label:i}));const c={...n,config:l};if(["allowedcreditcard","allowedcreditcards","allowedgiftcards","giftcardsPaymentmethods","payperemailAllowed"].includes(a)){c.type="multi-select",c.componentName="sw-multi-select",c.config={...c.config||{},multiple:!0,options:c.config&&c.config.options||o&&o.options||e.options||[]};const t=Array.isArray(c.config?.options)&&c.config.options.length>0?c.config.options[0]:null;console.debug("[BuckarooConfigCard] getElementBind multi-select binding",{fieldName:a,bindingType:c.type,componentName:c.componentName,optionsCount:Array.isArray(c.config?.options)?c.config.options.length:0,currentValue:r,sampleOption:t})}return s&&i&&"string"==typeof i&&i.trim().length>0&&("bool"===e.type||!c.label||"string"==typeof c.label&&0===c.label.trim().length)&&(c.label=i),"bool"===e.type&&(c.value=r,s&&(!c.label||"string"==typeof c.label&&0===c.label.trim().length)&&(c.label=c.config?.label||e.name.replace("BuckarooPayments.config.","").replace(/([A-Z])/g," $1").trim())),"bool"!==e.type&&"single-select"!==e.type&&"multi-select"!==e.type||c.label&&("string"!=typeof c.label||0!==c.label.trim().length)||console.warn("Missing label for field:",e.name,"Type:",e.type,"Element label:",e.label,"Extracted:",i,"BaseBinding label:",n.label,"Final binding label:",c.label),c},getInheritWrapperBind(e){if(!this.methods||!this.methods.getInheritWrapperBind){const t=e.name.replace("BuckarooPayments.config.","");return{name:e.name,currentValue:this.getValueForName(t)}}const t=this.methods.getInheritWrapperBind(e),n=e.name.replace("BuckarooPayments.config.",""),a=this.getValueForName(n);return t.currentValue=a,t},getFieldError(e){return this.methods&&this.methods.getFieldError?this.methods.getFieldError(e):null},kebabCase(e){return this.methods&&this.methods.kebabCase?this.methods.kebabCase(e):e?e.toLowerCase().replace(/[A-Z]/g,"-$&").replace(/^-/,""):""},getInlineSnippet(e){try{if("object"==typeof e&&null!==e){const t=this.$i18n?.locale||"en-GB";if(e[t])return e[t];if(e["en-GB"])return e["en-GB"];const n=Object.keys(e)[0];return n&&e[n]?e[n]:JSON.stringify(e)}return"string"==typeof e?this.$t&&"function"==typeof this.$t?this.$t(e):e:String(e)}catch(t){return console.warn("Translation error for:",e,t),"object"==typeof e?JSON.stringify(e):String(e)}},getInheritedValue(e){return this.methods&&this.methods.getInheritedValue?this.methods.getInheritedValue(e):null},getValueForName(e){const t=this.reactiveValue;if(!t||"object"!=typeof t)return null;let n;const a=[`BuckarooPayments.config.${e}`,e.toLowerCase(),e.charAt(0).toLowerCase()+e.slice(1),e.charAt(0).toUpperCase()+e.slice(1)];for(const e of a)if(void 0!==t[e]){n=t[e];break}if(void 0===n&&t["BuckarooPayments.config"]&&"object"==typeof t["BuckarooPayments.config"])for(const e of a)if(void 0!==t["BuckarooPayments.config"][e]){n=t["BuckarooPayments.config"][e];break}return n&&"object"==typeof n&&n.hasOwnProperty("_value")&&(n=n._value),n},canShow(e){if(!e||!e.name)return!1;const t=e.name.replace("BuckarooPayments.config.","");if(["orderStatus","paymentSuccesStatus","automaticallyCloseOpenOrders","sendInvoiceEmail"].includes(t)){const e=this.getValueForName("advancedConfiguration");return Boolean(e)}return"idealprocessingRenderMode"===t?Boolean(this.getValueForName("idealprocessingShowissuers")):"idealRenderMode"===t?Boolean(this.getValueForName("idealShowissuers")):["idealFastCheckoutEnabled","idealFastCheckoutVisibility","idealFastCheckoutLogoScheme"].includes(t)?Boolean(this.getValueForName("idealFastCheckout")):"afterpayPaymentstatus"===t?Boolean(this.getValueForName("afterpayCaptureonshippent")):"afterpayOldtax"!==t||Boolean(this.getValueForName("afterpayEnabledold"))},onInput(e){this.$emit("input",e)},onFieldInput(e,t){try{let n=t;if(t&&"object"==typeof t)if(t.target){const e=t.target;n="checkbox"===e.type||"radio"===e.type?e.checked:"SELECT"!==e.tagName&&"select-one"!==e.type&&"select-multiple"!==e.type||!e.multiple?e.value:Array.from(e.selectedOptions).map(e=>e.value)}else if(t.hasOwnProperty("value"))n=t.value;else if(t.hasOwnProperty("id")&&t.hasOwnProperty("name"))n=t.id;else if(Array.isArray(t)){const e=t.filter(e=>"string"==typeof e&&1===e.length).length,a=t.some(e=>","===e);if(t.some(e=>"string"==typeof e&&e.length>1),e>10&&a){const e=t.filter(e=>"string"==typeof e&&e.length>1),a=t.filter(e=>"string"==typeof e&&1===e.length).join("");let r=[];a.includes(",")?r=a.split(",").map(e=>e.trim()).filter(e=>e.length>0):a.length>0&&(r=[a]),n=[...r,...e].filter(e=>e&&e.length>0)}else n=t.filter(e=>!(null==e||""===e||"string"==typeof e&&1===e.length||"string"==typeof e&&(e.startsWith("+")||/^\d+$/.test(e)))).map(e=>"object"==typeof e&&null!==e&&(e.id||e.value||e.code||e.key)||e)}else{const e=["id","value","key","code"];for(const a of e)if(void 0!==t[a]){n=t[a];break}}else"boolean"==typeof t?n=t:"string"!=typeof t&&"number"!=typeof t||(n=t);const a=this.card?.elements?.find(t=>t.name===e||t.name.replace("BuckarooPayments.config.","")===e.replace("BuckarooPayments.config.",""));"on"===n?n=!0:"off"===n&&(n=!1),a&&"bool"===a.type&&(n="string"==typeof n?"1"===n||"true"===n||"on"===n:Boolean(n)),a&&"multi-select"===a.type&&(console.debug("[BuckarooConfigCard] onFieldInput before normalize (multi-select)",{fieldName:e,rawEvent:t,rawValue:n}),n=Array.isArray(n)?n.filter(e=>null!=e&&""!==e).map(e=>"object"==typeof e&&null!==e&&(e.id||e.value||e.code||e.key)||e):"string"==typeof n?n.split(",").map(e=>e.trim()).filter(e=>e.length>0):null==n?[]:[n],console.debug("[BuckarooConfigCard] onFieldInput after normalize (multi-select)",{fieldName:e,normalizedValue:n}));const r=e.replace("BuckarooPayments.config.",""),o={...this.value};o[r]=n,o[e]=n,this.$emit("input",o)}catch(e){console.error("Error in onFieldInput:",e),console.error("Error details:",e.stack)}}}});const{Component:k,Filter:v}=Shopware;k.register("buckaroo-payment-list",{template:'\r\n
\r\n \r\n
\r\n
\r\n \r\n
\r\n Payment logo\r\n
\r\n
\r\n {{ getPaymentTitle(payment.code) }}\r\n
\r\n
\r\n\r\n \r\n\r\n \r\n {{$tc(\'buckaroo-payment.configure-link\')}}\r\n \r\n
\r\n
\r\n \r\n
\r\n',props:{configSettings:{type:Array,required:!1,default:()=>[]},value:{type:Object,required:!1,default:()=>({})},currentSalesChannelId:{type:String,required:!0}},emits:["input"],data:()=>({payments:[{code:"Alipay",logo:"alipay.svg"},{code:"applepay",logo:"applepay.svg"},{code:"googlepay",logo:"googlepay.svg"},{code:"bancontactmrcash",logo:"bancontact.svg"},{code:"blik",logo:"blik.svg"},{code:"belfius",logo:"belfius.svg"},{code:"Billink",logo:"billink.svg"},{code:"creditcard",logo:"creditcards.svg"},{code:"creditcards",logo:"creditcards.svg"},{code:"eps",logo:"eps.svg"},{code:"giftcards",logo:"giftcards.svg"},{code:"idealqr",logo:"ideal-qr.svg"},{code:"ideal",logo:"ideal-wero.svg"},{code:"capayable",logo:"in3.svg"},{code:"KBCPaymentButton",logo:"kbc.svg"},{code:"klarna",logo:"klarna.svg"},{code:"klarnakp",logo:"klarna.svg"},{code:"knaken",logo:"gosettle.svg"},{code:"mbway",logo:"mbway.svg"},{code:"multibanco",logo:"multibanco.svg"},{code:"paybybank",logo:"paybybank.svg"},{code:"payconiq",logo:"payconiq.svg"},{code:"paypal",logo:"paypal.svg"},{code:"payperemail",logo:"payperemail.svg"},{code:"Przelewy24",logo:"przelewy24.svg"},{code:"afterpay",logo:"afterpay.svg"},{code:"sepadirectdebit",logo:"sepa-directdebit.svg"},{code:"transfer",logo:"sepa-credittransfer.svg"},{code:"Trustly",logo:"trustly.svg"},{code:"WeChatPay",logo:"wechatpay.svg"},{code:"swish",logo:"swish.svg"},{code:"bizum",logo:"bizum.svg"},{code:"twint",logo:"twint.svg"},{code:"wero",logo:"wero.svg"}]}),methods:{getPaymentTitle(e){if(this.configSettings&&Array.isArray(this.configSettings)){const t=this.configSettings.find(t=>t.name===e);if(t&&t.title)try{if("object"==typeof t.title&&null!==t.title){const e=this.$i18n?.locale||"en-GB";if(t.title[e])return t.title[e];if(t.title["en-GB"])return t.title["en-GB"];const n=Object.keys(t.title)[0];return n&&t.title[n]?t.title[n]:JSON.stringify(t.title)}return"string"==typeof t.title?this.$t&&"function"==typeof this.$t?this.$t(t.title):t.title:String(t.title)}catch(e){return console.warn("Translation error for:",t.title,e),"object"==typeof t.title?JSON.stringify(t.title):String(t.title)}}const t=this.payments.find(t=>t.code===e);return t?t.code:"Unknown Payment"},assetFilter:e=>v.getByName("asset")(e)}});const{Component:w}=Shopware;w.register("buckaroo-test-credentials",{template:' {{ $tc(\'buckaroo-payment.button.labelTestApi\') }}',mixins:[Shopware.Mixin.getByName("notification")],data:()=>({isLoading:!1}),inject:["BuckarooPaymentSettingsService"],props:{config:{type:Object,required:!0},currentSalesChannelId:{required:!0}},computed:{enabled:function(){return(this.getConfigValue("websiteKey")||"").length>0&&(this.getConfigValue("secretKey")||"").length>0}},methods:{getConfigValue:function(e){return this.config["BuckarooPayments.config."+e]},sendTestApi(){this.isLoading=!0;let e=this.getConfigValue("websiteKey"),t=this.getConfigValue("secretKey");this.BuckarooPaymentSettingsService.getApiTest(e,t,this.currentSalesChannelId).then(e=>{this.isLoading=!1,"success"==e.status?this.createNotificationSuccess({title:this.$tc("buckaroo-payment.settingsForm.titleSuccess"),message:this.$tc(e.message)}):this.createNotificationError({title:this.$tc("buckaroo-payment.settingsForm.titleError"),message:this.$tc(e.message)})}).catch(()=>{this.isLoading=!1})}}});const{Component:_}=Shopware;_.register("buckaroo-toggle-status",{template:'
\r\n \r\n Live\r\n \r\n\r\n \r\n Test\r\n \r\n\r\n \r\n Off\r\n \r\n
\r\n',props:{method:{type:String,required:!0},value:{required:!0},currentSalesChannelId:{required:!0}},emits:["input"],inject:["systemConfigApiService"],data:()=>({status:"disabled",isLoading:!1}),mounted(){this.status=this.getStatus()},watch:{value:{handler(e){this.status=this.getStatus()},deep:!0,immediate:!0}},methods:{getStatus(){const e=this.isActive(),t=this.getEnvironment();return e?t:"disabled"},isActive(){const e=this.getValueForName(`${this.method}Enabled`);return"string"==typeof e?"true"===e.toLowerCase():Boolean(e)},getEnvironment(){const e=this.getValueForName(`${this.method}Environment`);return null==e||""===e?"test":["test","live"].includes(e)?e:"test"},getValueForName(e){const t=`BuckarooPayments.config.${e}`;if(!this.value||"object"!=typeof this.value)return null;let n;if(void 0!==this.value[t])n=this.value[t];else if(void 0!==this.value[e])n=this.value[e];else if(this.value["BuckarooPayments.config"]&&"object"==typeof this.value["BuckarooPayments.config"])void 0!==this.value["BuckarooPayments.config"][e]&&(n=this.value["BuckarooPayments.config"][e]);else{const t=[e,e.toLowerCase(),e.charAt(0).toLowerCase()+e.slice(1),e.charAt(0).toUpperCase()+e.slice(1)];for(const e of t){const t=`BuckarooPayments.config.${e}`;if(void 0!==this.value[t]){n=this.value[t];break}if(void 0!==this.value[e]){n=this.value[e];break}}}return n&&"object"==typeof n&&n.hasOwnProperty("_value")&&(n=n._value),n},setStatus(e){this.status=e,this.saveStatus()},getClass(e){return this.status===e?"active":""},async saveStatus(){const e=`BuckarooPayments.config.${this.method}Enabled`,t=`BuckarooPayments.config.${this.method}Environment`;let n={[e]:!1};const a={...this.value};a[e]=!1,-1!==["live","test"].indexOf(this.status)&&(n={[e]:!0,[t]:this.status},a[e]=!0,a[t]=this.status),this.$emit("input",a),this.isLoading=!0;try{await this.systemConfigApiService.batchSave({[this.currentSalesChannelId]:n}).finally(()=>{this.isLoading=!1}),this.renderSuccess()}catch(e){this.renderError(e)}},renderSuccess(){this.$store.dispatch("notification/createNotification",{variant:"success",message:this.$tc("sw-extension-store.component.sw-extension-config.messageSaveSuccess")})},renderError(e){this.$store.dispatch("notification/createNotification",{variant:"error",message:e})}}})})()})(); -//# sourceMappingURL=buckaroo-payments.js.map \ No newline at end of file diff --git a/src/Resources/public/administration/js/buckaroo-payments.js.map b/src/Resources/public/administration/js/buckaroo-payments.js.map deleted file mode 100644 index 30cd97c4..00000000 --- a/src/Resources/public/administration/js/buckaroo-payments.js.map +++ /dev/null @@ -1 +0,0 @@ -{"version":3,"file":"buckaroo-payments.js","mappings":"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","sources":["webpack://buckaroo-payments/./src/Resources/app/administration/src/api/buckaroo-payment-settings.service.js","webpack://buckaroo-payments/./src/Resources/app/administration/src/api/buckaroo-payment.service.js","webpack://buckaroo-payments/./src/Resources/app/administration/src/module/buckaroo-payment/page/buckaroo-payment-config/index.js","webpack://buckaroo-payments/webpack/bootstrap","webpack://buckaroo-payments/./src/Resources/app/administration/src/module/buckaroo-payment/extension/sw-order/index.js","webpack://buckaroo-payments/./src/Resources/app/administration/src/module/buckaroo-payment/extension/sw-order-detail-base/index.js","webpack://buckaroo-payments/./src/Resources/app/administration/src/module/buckaroo-payment/extension/sw-order-user-card/index.js","webpack://buckaroo-payments/./src/Resources/app/administration/src/module/buckaroo-payment/extension/sw-system-config/index.js","webpack://buckaroo-payments/./src/Resources/app/administration/src/module/buckaroo-payment/page/buckaroo-payment-detail/index.js","webpack://buckaroo-payments/./src/Resources/app/administration/src/module/buckaroo-payment/index.js","webpack://buckaroo-payments/./src/Resources/app/administration/src/components/buckaroo-afterpay-old-tax/index.js","webpack://buckaroo-payments/./src/Resources/app/administration/src/components/buckaroo-main-config/index.js","webpack://buckaroo-payments/./src/Resources/app/administration/src/components/buckaroo-config-card/index.js","webpack://buckaroo-payments/./src/Resources/app/administration/src/components/buckaroo-payment-list/index.js","webpack://buckaroo-payments/./src/Resources/app/administration/src/components/buckaroo-test-credentials/index.js","webpack://buckaroo-payments/./src/Resources/app/administration/src/components/buckaroo-toggle-status/index.js"],"sourcesContent":["const { ApiService } = Shopware.Classes;\r\n\r\nclass BuckarooPaymentSettingsService extends ApiService {\r\n constructor(httpClient, loginService, apiEndpoint = 'buckaroo')\r\n {\r\n super(httpClient, loginService, apiEndpoint);\r\n }\r\n\r\n getBasicHeaders() {\r\n if (this.loginService && typeof this.loginService.getToken === 'function') {\r\n return super.getBasicHeaders();\r\n }\r\n return {\r\n 'Content-Type': 'application/json',\r\n 'Accept': 'application/json'\r\n };\r\n }\r\n\r\n getSupportVersion()\r\n {\r\n const apiRoute = `_action/${this.getApiBasePath()}/version`;\r\n\r\n return this.httpClient.post(\r\n apiRoute,\r\n {\r\n },\r\n {\r\n headers: this.getBasicHeaders()\r\n }\r\n ).then((response) => {\r\n return ApiService.handleResponse(response);\r\n });\r\n }\r\n\r\n getTaxes()\r\n {\r\n const apiRoute = `_action/${this.getApiBasePath()}/taxes`;\r\n\r\n return this.httpClient.post(\r\n apiRoute,\r\n {\r\n },\r\n {\r\n headers: this.getBasicHeaders()\r\n }\r\n ).then((response) => {\r\n return ApiService.handleResponse(response);\r\n });\r\n }\r\n\r\n getIn3Icons()\r\n {\r\n const apiRoute = `_action/${this.getApiBasePath()}/in3/logos`;\r\n\r\n return this.httpClient.post(\r\n apiRoute,\r\n {\r\n },\r\n {\r\n headers: this.getBasicHeaders()\r\n }\r\n ).then((response) => {\r\n return ApiService.handleResponse(response);\r\n });\r\n }\r\n\r\n getApiTest(websiteKeyId, secretKeyId, currentSalesChannelId)\r\n {\r\n const apiRoute = `_action/${this.getApiBasePath()}/getBuckarooApiTest`;\r\n\r\n return this.httpClient.post(\r\n apiRoute,\r\n {\r\n websiteKeyId: websiteKeyId,\r\n secretKeyId: secretKeyId,\r\n saleChannelId: currentSalesChannelId\r\n },\r\n {\r\n headers: this.getBasicHeaders()\r\n }\r\n ).then((response) => {\r\n return ApiService.handleResponse(response);\r\n });\r\n }\r\n}\r\n\r\nShopware.Service().register('BuckarooPaymentSettingsService', () => {\r\n const initContainer = Shopware.Application.getContainer('init');\r\n // Ensure we use the global loginService which always exists in admin\r\n const loginService = Shopware.Service('loginService');\r\n return new BuckarooPaymentSettingsService(initContainer.httpClient, loginService);\r\n});\r\n\r\n","const { ApiService } = Shopware.Classes;\r\n\r\nclass BuckarooPaymentService extends ApiService {\r\n constructor(httpClient, loginService, apiEndpoint = 'buckaroo')\r\n {\r\n super(httpClient, loginService, apiEndpoint);\r\n }\r\n\r\n getBasicHeaders() {\r\n if (this.loginService && typeof this.loginService.getToken === 'function') {\r\n return super.getBasicHeaders();\r\n }\r\n return {\r\n 'Content-Type': 'application/json',\r\n 'Accept': 'application/json'\r\n };\r\n }\r\n\r\n getBuckarooTransaction(transaction)\r\n {\r\n const apiRoute = `_action/${this.getApiBasePath()}/getBuckarooTransaction`;\r\n\r\n return this.httpClient.post(\r\n apiRoute,\r\n {\r\n transaction: transaction\r\n },\r\n {\r\n headers: this.getBasicHeaders()\r\n }\r\n ).then((response) => {\r\n return ApiService.handleResponse(response);\r\n });\r\n }\r\n\r\n refundPayment(transaction, transactionsToRefund, orderItems, customRefundAmount)\r\n {\r\n const apiRoute = `_action/${this.getApiBasePath()}/refund`;\r\n\r\n return this.httpClient.post(\r\n apiRoute,\r\n {\r\n transaction: transaction,\r\n transactionsToRefund: transactionsToRefund,\r\n orderItems: orderItems,\r\n customRefundAmount: customRefundAmount\r\n },\r\n {\r\n headers: this.getBasicHeaders()\r\n }\r\n ).then((response) => {\r\n return ApiService.handleResponse(response);\r\n });\r\n }\r\n\r\n captureOrder(transaction)\r\n {\r\n const apiRoute = `_action/${this.getApiBasePath()}/capture`;\r\n\r\n return this.httpClient.post(\r\n apiRoute,\r\n {\r\n transaction: transaction\r\n },\r\n {\r\n headers: this.getBasicHeaders()\r\n }\r\n ).then((response) => {\r\n return ApiService.handleResponse(response);\r\n });\r\n }\r\n\r\n createPaylink(transaction)\r\n {\r\n const apiRoute = `_action/${this.getApiBasePath()}/paylink`;\r\n\r\n return this.httpClient.post(\r\n apiRoute,\r\n {\r\n transaction: transaction\r\n },\r\n {\r\n headers: this.getBasicHeaders()\r\n }\r\n ).then((response) => {\r\n return ApiService.handleResponse(response);\r\n });\r\n }\r\n\r\n klarnaMor(orderId, action)\r\n {\r\n const apiRoute = `_action/${this.getApiBasePath()}/klarna-mor`;\r\n\r\n return this.httpClient.post(\r\n apiRoute,\r\n {\r\n orderId: orderId,\r\n action: action\r\n },\r\n {\r\n headers: this.getBasicHeaders()\r\n }\r\n ).then((response) => {\r\n return ApiService.handleResponse(response);\r\n });\r\n }\r\n\r\n}\r\n\r\nShopware.Service().register('BuckarooPaymentService', () => {\r\n const initContainer = Shopware.Application.getContainer('init');\r\n // Ensure we use the global loginService which always exists in admin\r\n const loginService = Shopware.Service('loginService');\r\n return new BuckarooPaymentService(initContainer.httpClient, loginService);\r\n});\r\n\r\n","\r\nconst { Component } = Shopware;\r\n\r\nComponent.extend('buckaroo-payment-config', 'sw-extension-config', {\r\n});","// The module cache\nvar __webpack_module_cache__ = {};\n\n// The require function\nfunction __webpack_require__(moduleId) {\n\t// Check if module is in cache\n\tvar cachedModule = __webpack_module_cache__[moduleId];\n\tif (cachedModule !== undefined) {\n\t\treturn cachedModule.exports;\n\t}\n\t// Create a new module (and put it into the cache)\n\tvar module = __webpack_module_cache__[moduleId] = {\n\t\t// no module.id needed\n\t\t// no module.loaded needed\n\t\texports: {}\n\t};\n\n\t// Execute the module function\n\t__webpack_modules__[moduleId](module, module.exports, __webpack_require__);\n\n\t// Return the exports of the module\n\treturn module.exports;\n}\n\n","import template from './sw-order.html.twig';\r\n\r\nconst { Component, Context } = Shopware;\r\nconst Criteria = Shopware.Data.Criteria;\r\n\r\nComponent.override('sw-order-detail', {\r\n template,\r\n\r\n data() {\r\n return {\r\n isBuckarooPayment: false,\r\n isPaymentInTestMode: false\r\n };\r\n },\r\n\r\n computed: {\r\n isEditable() {\r\n return !this.isBuckarooPayment || this.$route.name !== 'buckaroo.payment.detail';\r\n },\r\n\r\n showTabs() {\r\n return true;\r\n }\r\n },\r\n\r\n watch: {\r\n orderId: {\r\n deep: true,\r\n handler() {\r\n if (!this.orderId) {\r\n this.setIsBuckarooPayment(null);\r\n return;\r\n }\r\n\r\n const orderRepository = this.repositoryFactory.create('order');\r\n const orderCriteria = new Criteria(1, 1);\r\n orderCriteria.addAssociation('transactions');\r\n\r\n orderRepository.get(this.orderId, Context.api, orderCriteria).then((order) => {\r\n\r\n this.setPaymentInTestMode(order);\r\n\r\n if (order.transactions.length <= 0 ||\r\n !order.transactions.last().paymentMethodId\r\n ) {\r\n this.setIsBuckarooPayment(null);\r\n return;\r\n }\r\n\r\n const paymentMethodId = order.transactions.last().paymentMethodId;\r\n\r\n if (paymentMethodId !== undefined && paymentMethodId !== null) {\r\n this.setIsBuckarooPayment(paymentMethodId);\r\n }\r\n });\r\n },\r\n immediate: true\r\n }\r\n },\r\n\r\n methods: {\r\n setPaymentInTestMode(order) {\r\n if (order.customFields && order.customFields.buckaroo_payment_in_test_mode) {\r\n this.isPaymentInTestMode = order.customFields.buckaroo_payment_in_test_mode === true;\r\n }\r\n },\r\n setIsBuckarooPayment(paymentMethodId) {\r\n if (!paymentMethodId) {\r\n return;\r\n }\r\n const paymentMethodRepository = this.repositoryFactory.create('payment_method');\r\n paymentMethodRepository.get(paymentMethodId, Context.api).then(\r\n (paymentMethod) => {\r\n this.isBuckarooPayment = paymentMethod.formattedHandlerIdentifier.indexOf('buckaroo') >= 0;\r\n }\r\n );\r\n }\r\n }\r\n});","import template from './sw-order-detail-base.html.twig';\r\n\r\nconst { Component, Context } = Shopware;\r\nconst Criteria = Shopware.Data.Criteria;\r\n\r\nComponent.override('sw-order-detail-base', {\r\n template\r\n});\r\n","import template from './sw-order-user-card.html.twig';\r\n\r\nconst { Component } = Shopware;\r\n\r\nComponent.override('sw-order-user-card', {\r\n template,\r\n\r\n inject: [ 'systemConfigApiService' ],\r\n\r\n data() {\r\n return {\r\n config: {}\r\n };\r\n },\r\n\r\n created() {\r\n this.systemConfigApiService.getValues('BuckarooPayments.config', null)\r\n .then(values => {\r\n this.config = values;\r\n })\r\n .finally(() => {\r\n });\r\n }\r\n\r\n});\r\n"," import template from './sw-system-config.html.twig';\r\n\r\nconst { Component } = Shopware;\r\n\r\nComponent.override('sw-system-config', {\r\n template,\r\n \r\n watch: {\r\n currentSalesChannelId: {\r\n handler(newVal, oldVal) {\r\n if (newVal && this.domain === 'BuckarooPayments.config') {\r\n this.loadBuckarooConfigData();\r\n }\r\n },\r\n immediate: true\r\n },\r\n domain: {\r\n handler(newVal) {\r\n if (newVal === 'BuckarooPayments.config' && this.currentSalesChannelId) {\r\n this.loadBuckarooConfigData();\r\n }\r\n },\r\n immediate: true\r\n }\r\n },\r\n\r\n methods: {\r\n loadBuckarooConfigData() {\r\n \r\n this.systemConfigApiService.getValues('BuckarooPayments.config', this.currentSalesChannelId)\r\n .then(response => {\r\n \r\n if (!this.actualConfigData[this.currentSalesChannelId]) {\r\n this.actualConfigData[this.currentSalesChannelId] = {};\r\n }\r\n\r\n const processedData = {};\r\n \r\n if (response && typeof response === 'object') {\r\n Object.keys(response).forEach(key => {\r\n const value = response[key];\r\n\r\n if (value && typeof value === 'object' && value.hasOwnProperty('_value')) {\r\n processedData[key] = value._value;\r\n } else {\r\n processedData[key] = value;\r\n }\r\n\r\n const shortKey = key.replace('BuckarooPayments.config.', '');\r\n if (shortKey !== key) {\r\n processedData[shortKey] = processedData[key];\r\n }\r\n });\r\n }\r\n\r\n this.actualConfigData[this.currentSalesChannelId] = {};\r\n Object.keys(processedData).forEach(key => {\r\n this.actualConfigData[this.currentSalesChannelId][key] = processedData[key];\r\n });\r\n\r\n this.$nextTick(() => {\r\n this.$forceUpdate();\r\n });\r\n })\r\n .catch(error => {\r\n console.error('Error fetching system config:', error);\r\n });\r\n },\r\n\r\n onConfigDataUpdate(newValue) {\r\n if (!this.actualConfigData[this.currentSalesChannelId]) {\r\n this.actualConfigData[this.currentSalesChannelId] = {};\r\n }\r\n Object.keys(newValue).forEach(key => {\r\n this.actualConfigData[this.currentSalesChannelId][key] = newValue[key];\r\n if (!key.startsWith('BuckarooPayments.config.')) {\r\n const fullFieldName = `BuckarooPayments.config.${key}`;\r\n this.actualConfigData[this.currentSalesChannelId][fullFieldName] = newValue[key];\r\n }\r\n });\r\n },\r\n\r\n saveAll() {\r\n if (this.domain !== 'BuckarooPayments.config') {\r\n return this.$super('saveAll');\r\n }\r\n return this.saveBuckaroo();\r\n },\r\n \r\n saveBuckaroo() {\r\n this.isLoading = true;\r\n return this.systemConfigApiService\r\n .batchSave(this.getSelectedValues())\r\n .finally(() => {\r\n this.isLoading = false;\r\n });\r\n },\r\n \r\n getCurrentConfigCard() {\r\n const code = this.$route.params?.paymentCode || 'general';\r\n return this.config.filter((card) => card.name === code)?.pop();\r\n },\r\n \r\n getSelectedValues() {\r\n const currentConfigValues = this.actualConfigData[this.currentSalesChannelId];\r\n const currentPaymentCard = this.getCurrentConfigCard();\r\n\r\n if (currentPaymentCard?.elements) {\r\n let actualConfigValues = {};\r\n currentPaymentCard?.elements.forEach((element) => {\r\n if (element?.name) {\r\n let value = currentConfigValues[element.name];\r\n\r\n if (value === undefined) {\r\n const cleanFieldName = element.name.replace('BuckarooPayments.config.', '');\r\n value = currentConfigValues[cleanFieldName];\r\n }\r\n \r\n actualConfigValues[element.name] = value;\r\n }\r\n });\r\n return { [this.currentSalesChannelId]: actualConfigValues };\r\n }\r\n\r\n return this.actualConfigData;\r\n }\r\n }\r\n});\r\n","import template from './buckaroo-payment-detail.html.twig';\r\nimport './buckaroo-payment-detail.scss';\r\n\r\nconst { Component, Filter, Context } = Shopware;\r\nconst Criteria = Shopware.Data.Criteria;\r\n\r\nComponent.register('buckaroo-payment-detail', {\r\n template,\r\n\r\n inject: [\r\n 'repositoryFactory',\r\n 'BuckarooPaymentService',\r\n 'systemConfigApiService'\r\n ],\r\n\r\n data() {\r\n return {\r\n config: {},\r\n buckaroo_refund_amount: '0',\r\n buckaroo_refund_total_amount: '0',\r\n currency: 'EUR',\r\n isRefundPossible: true,\r\n isCapturePossible: false,\r\n isPaylinkAvailable: false,\r\n isPaylinkVisible: false,\r\n paylinkMessage: '',\r\n paylink: '',\r\n isLoading: false,\r\n order: false,\r\n buckarooTransactions: null,\r\n orderItems: [],\r\n transactionsToRefund: [],\r\n relatedResources: [],\r\n isAuthorized: false,\r\n isKlarnaMor: false,\r\n fulfillmentMessage: '',\r\n fulfillmentStatus: null\r\n };\r\n },\r\n\r\n computed: {\r\n orderItemsColumns() {\r\n return [\r\n {\r\n property: 'name',\r\n label: this.$tc('buckaroo-payment.orderItems.types.name'),\r\n allowResize: false,\r\n primary: true,\r\n inlineEdit: true,\r\n multiLine: true,\r\n },\r\n {\r\n property: 'quantity',\r\n label: this.$tc('buckaroo-payment.orderItems.types.quantity'),\r\n rawData: true,\r\n align: 'right'\r\n },\r\n {\r\n property: 'totalAmount',\r\n label: this.$tc('buckaroo-payment.orderItems.types.totalAmount'),\r\n rawData: true,\r\n align: 'right'\r\n }\r\n ];\r\n },\r\n\r\n transactionsToRefundColumns() {\r\n return [\r\n {\r\n property: 'transaction_method',\r\n rawData: true\r\n },{\r\n property: 'amount',\r\n rawData: true\r\n }\r\n ];\r\n },\r\n\r\n relatedResourceColumns() {\r\n return [\r\n {\r\n property: 'created_at',\r\n label: this.$tc('buckaroo-payment.transactionHistory.types.created_at'),\r\n rawData: true\r\n },\r\n {\r\n property: 'total',\r\n label: this.$tc('buckaroo-payment.transactionHistory.types.total'),\r\n rawData: true\r\n },{\r\n property: 'shipping_costs',\r\n label: this.$tc('buckaroo-payment.transactionHistory.types.shipping_costs'),\r\n rawData: true\r\n },{\r\n property: 'total_excluding_vat',\r\n label: this.$tc('buckaroo-payment.transactionHistory.types.total_excluding_vat'),\r\n rawData: true\r\n },{\r\n property: 'vat',\r\n label: this.$tc('buckaroo-payment.transactionHistory.types.vat'),\r\n rawData: true\r\n },{\r\n property: 'transaction_key',\r\n label: this.$tc('buckaroo-payment.transactionHistory.types.transaction_key'),\r\n rawData: true\r\n },{\r\n property: 'transaction_method',\r\n label: this.$tc('buckaroo-payment.transactionHistory.types.transaction_method'),\r\n rawData: true\r\n },{\r\n property: 'statuscode',\r\n label: this.$tc('buckaroo-payment.transactionHistory.types.statuscode'),\r\n rawData: true\r\n }\r\n ];\r\n }\r\n },\r\n\r\n created() {\r\n this.createdComponent();\r\n },\r\n\r\n methods: {\r\n recalculateOrderItems() {\r\n this.buckaroo_refund_amount = 0;\r\n for (const key in this.orderItems) {\r\n this.orderItems[key]['totalAmount'] = parseFloat(parseFloat(this.orderItems[key]['unitPrice']) * parseFloat(this.orderItems[key]['quantity'] || 0)).toFixed(2);\r\n this.buckaroo_refund_amount = parseFloat(parseFloat(this.buckaroo_refund_amount) + parseFloat(this.orderItems[key]['totalAmount'])).toFixed(2);\r\n }\r\n },\r\n recalculateRefundItems() {\r\n this.buckaroo_refund_total_amount = 0;\r\n for (const key in this.transactionsToRefund) {\r\n if (this.transactionsToRefund[key]['amount']) {\r\n this.buckaroo_refund_total_amount = parseFloat(parseFloat(this.buckaroo_refund_total_amount) + parseFloat(this.transactionsToRefund[key]['amount'])).toFixed(2);\r\n }\r\n }\r\n },\r\n\r\n getCustomRefundEnabledEl() {\r\n return document.getElementById('buckaroo_custom_refund_enabled');\r\n },\r\n\r\n getCustomRefundAmountEl() {\r\n return document.getElementById('buckaroo_custom_refund_amount');\r\n },\r\n\r\n toggleCustomRefund() {\r\n if (this.getCustomRefundEnabledEl() && this.getCustomRefundAmountEl()) {\r\n this.getCustomRefundAmountEl().disabled = !this.getCustomRefundEnabledEl().checked;\r\n }\r\n },\r\n\r\n getCustomRefundAmount() {\r\n if (this.getCustomRefundEnabledEl() && this.getCustomRefundAmountEl() && this.getCustomRefundEnabledEl().checked) {\r\n return this.getCustomRefundAmountEl().value;\r\n }\r\n return 0;\r\n },\r\n\r\n createdComponent() {\r\n let that = this;\r\n const orderId = this.$route.params.id;\r\n\r\n this.systemConfigApiService.getValues('BuckarooPayments.config', null)\r\n .then(values => {\r\n this.config = values;\r\n });\r\n\r\n const orderRepository = this.repositoryFactory.create('order');\r\n const orderCriteria = new Criteria(1, 1);\r\n\r\n this.orderId = orderId;\r\n orderCriteria.addAssociation('transactions.paymentMethod')\r\n .addAssociation('transactions');\r\n\r\n orderCriteria.getAssociation('transactions').addSorting(Criteria.sort('createdAt'));\r\n\r\n orderRepository.get(orderId, Context.api, orderCriteria).then((order) => {\r\n that.checkedIsAuthorized(order);\r\n const buckarooKey = order.transactions &&\r\n order.transactions.last().paymentMethod &&\r\n order.transactions.last().paymentMethod.customFields &&\r\n order.transactions.last().paymentMethod.customFields.buckaroo_key\r\n ? order.transactions.last().paymentMethod.customFields.buckaroo_key.toLowerCase()\r\n : '';\r\n\r\n that.isCapturePossible = !!buckarooKey &&\r\n (['klarnakp', 'billink', 'afterpay', 'klarna', 'wero'].includes(buckarooKey) || that.isAfterpayCapturePossible(order));\r\n\r\n that.isKlarnaMor = buckarooKey === 'klarna';\r\n\r\n that.isPaylinkVisible = that.isPaylinkAvailable = this.getConfigValue('paylinkEnabled') && order.stateMachineState && order.stateMachineState.technicalName && order.stateMachineState.technicalName == 'open' && order.transactions && order.transactions.last().stateMachineState.technicalName == 'open';\r\n });\r\n\r\n this.BuckarooPaymentService.getBuckarooTransaction(orderId)\r\n .then((response) => {\r\n that.orderItems = [];\r\n that.transactionsToRefund = [];\r\n that.relatedResources = [];\r\n\r\n this.$emit('loading-change', false);\r\n\r\n if (response.orderItems && Array.isArray(response.orderItems)) {\r\n response.orderItems.forEach((element) => {\r\n that.orderItems.push({\r\n id: element.id,\r\n name: element.name,\r\n quantity: element.quantity,\r\n quantityMax: element.quantity,\r\n unitPrice: element.unitPrice.value,\r\n totalAmount: element.totalAmount.value,\r\n variations: element.variations || [],\r\n });\r\n });\r\n }\r\n\r\n // Use backend-calculated total (single source of truth)\r\n that.buckaroo_refund_amount = response.refundTotals ? response.refundTotals.totalAmount : 0;\r\n that.currency = response.refundTotals ? response.refundTotals.currency : 'EUR';\r\n\r\n if (response.transactionsToRefund && Array.isArray(response.transactionsToRefund)) {\r\n response.transactionsToRefund.forEach((element) => {\r\n that.transactionsToRefund.push({\r\n id: element.id,\r\n transactions: element.transactions,\r\n amount: element.total,\r\n amountMax: element.total,\r\n currency: element.currency,\r\n transaction_method: element.transaction_method,\r\n logo: element.transaction_method ? element.logo : null\r\n });\r\n that.currency = element.currency;\r\n });\r\n }\r\n that.recalculateRefundItems();\r\n\r\n if (response.transactions && Array.isArray(response.transactions)) {\r\n response.transactions.forEach((element) => {\r\n that.relatedResources.push({\r\n id: element.id,\r\n transaction_key: element.transaction,\r\n total: element.total,\r\n total_excluding_vat: element.total_excluding_vat,\r\n shipping_costs: element.shipping_costs,\r\n vat: element.vat,\r\n transaction_method: element.transaction_method,\r\n logo: element.transaction_method ? element.logo : null,\r\n created_at: element.created_at,\r\n statuscode: element.statuscode\r\n });\r\n });\r\n }\r\n\r\n })\r\n .catch((errorResponse) => {\r\n console.log('errorResponse', errorResponse);\r\n });\r\n\r\n },\r\n\r\n isAfterpayCapturePossible(order) {\r\n return order.customFields.buckaroo_is_authorize === true;\r\n },\r\n\r\n checkedIsAuthorized(order) {\r\n this.isAuthorized = order?.transactions?.last()?.stateMachineState?.technicalName === \"authorized\";\r\n },\r\n\r\n refundOrder(transaction, amount) {\r\n let that = this;\r\n that.isRefundPossible = false;\r\n this.BuckarooPaymentService.refundPayment(transaction, this.transactionsToRefund, this.orderItems, this.getCustomRefundAmount())\r\n .then((response) => {\r\n for (const key in response) {\r\n if (response[key].status) {\r\n this.$store.dispatch('notification/createNotification', {\r\n variant: 'success',\r\n title: that.$tc('buckaroo-payment.settingsForm.titleSuccess'),\r\n message: that.$tc(response[key].message) + response[key].amount\r\n });\r\n } else {\r\n this.$store.dispatch('notification/createNotification', {\r\n variant: 'error',\r\n title: that.$tc('buckaroo-payment.settingsForm.titleError'),\r\n message: that.$tc(response[key].message)\r\n });\r\n }\r\n }\r\n that.isRefundPossible = true;\r\n this.createdComponent();\r\n })\r\n .catch((errorResponse) => {\r\n this.$store.dispatch('notification/createNotification', {\r\n variant: 'error',\r\n title: this.$tc('buckaroo-payment.settingsForm.titleError'),\r\n message: errorResponse.response.data.message\r\n });\r\n that.isRefundPossible = true;\r\n });\r\n },\r\n\r\n createPaylink(transaction) {\r\n let that = this;\r\n that.isPaylinkAvailable = false;\r\n this.BuckarooPaymentService.createPaylink(transaction, this.transactionsToRefund, this.orderItems)\r\n .then((response) => {\r\n if (response.status) {\r\n that.paylinkMessage = that.$tc(response.message) + response.paylinkhref;\r\n that.paylink = response.paylink;\r\n this.$store.dispatch('notification/createNotification', {\r\n variant: 'success',\r\n title: that.$tc('buckaroo-payment.settingsForm.titleSuccess'),\r\n message: that.paylinkMessage\r\n });\r\n } else {\r\n this.$store.dispatch('notification/createNotification', {\r\n variant: 'error',\r\n title: that.$tc('buckaroo-payment.settingsForm.titleError'),\r\n message: that.$tc(response.message)\r\n });\r\n }\r\n that.isPaylinkAvailable = true;\r\n })\r\n .catch((errorResponse) => {\r\n this.$store.dispatch('notification/createNotification', {\r\n variant: 'error',\r\n title: this.$tc('buckaroo-payment.settingsForm.titleError'),\r\n message: errorResponse.response.data.message\r\n });\r\n that.isPaylinkAvailable = true;\r\n });\r\n },\r\n\r\n getConfigValue(field) {\r\n return this.config[`BuckarooPayments.config.${field}`];\r\n },\r\n\r\n captureOrder(transaction) {\r\n let that = this;\r\n that.isCapturePossible = false;\r\n this.BuckarooPaymentService.captureOrder(transaction, this.transactionsToRefund, this.orderItems)\r\n .then((response) => {\r\n if (response.status) {\r\n this.$store.dispatch('notification/createNotification', {\r\n variant: 'success',\r\n title: that.$tc('buckaroo-payment.settingsForm.titleSuccess'),\r\n message: response.message\r\n });\r\n } else {\r\n this.$store.dispatch('notification/createNotification', {\r\n variant: 'error',\r\n title: that.$tc('buckaroo-payment.settingsForm.titleError'),\r\n message: response.message\r\n });\r\n }\r\n that.isCapturePossible = true;\r\n this.createdComponent();\r\n })\r\n .catch((errorResponse) => {\r\n this.$store.dispatch('notification/createNotification', {\r\n variant: 'error',\r\n title: this.$tc('buckaroo-payment.settingsForm.titleError'),\r\n message: that.$tc(errorResponse.response.data.message)\r\n });\r\n that.isCapturePossible = true;\r\n });\r\n },\r\n\r\n klarnaMor(action) {\r\n let that = this;\r\n that.isLoading = true;\r\n this.BuckarooPaymentService.klarnaMor(this.orderId, action)\r\n .then((response) => {\r\n if (response.status) {\r\n this.$store.dispatch('notification/createNotification', {\r\n variant: 'success',\r\n title: that.$tc('buckaroo-payment.settingsForm.titleSuccess'),\r\n message: response.message\r\n });\r\n } else {\r\n this.$store.dispatch('notification/createNotification', {\r\n variant: 'error',\r\n title: that.$tc('buckaroo-payment.settingsForm.titleError'),\r\n message: response.message\r\n });\r\n }\r\n that.isLoading = false;\r\n this.createdComponent();\r\n })\r\n .catch((errorResponse) => {\r\n this.$store.dispatch('notification/createNotification', {\r\n variant: 'error',\r\n title: this.$tc('buckaroo-payment.settingsForm.titleError'),\r\n message: errorResponse.response && errorResponse.response.data\r\n ? errorResponse.response.data.message\r\n : 'An error occurred'\r\n });\r\n that.isLoading = false;\r\n });\r\n }\r\n }\r\n});\r\n","const { Module } = Shopware;\r\n\r\nimport './extension/sw-order';\r\nimport './extension/sw-order-detail-base';\r\nimport './extension/sw-order-user-card';\r\nimport './extension/sw-system-config';\r\nimport './page/buckaroo-payment-detail';\r\n\r\nimport './page/buckaroo-payment-config';\r\n\r\nimport nlNL from './snippet/nl-NL.json';\r\nimport deDE from './snippet/de-DE.json';\r\nimport enGB from './snippet/en-GB.json';\r\n\r\nModule.register('buckaroo-payment', {\r\n type: 'plugin',\r\n name: 'BuckarooPayment',\r\n title: 'buckaroo-payment.general.title',\r\n description: 'buckaroo-payment.general.description',\r\n version: '1.0.0',\r\n targetVersion: '1.0.0',\r\n color: '#000000',\r\n icon: 'default-action-settings',\r\n\r\n snippets: {\r\n 'nl-NL': nlNL,\r\n 'de-DE': deDE,\r\n 'en-GB': enGB\r\n },\r\n\r\n routeMiddleware(next, currentRoute) {\r\n if (currentRoute.name === 'sw.order.detail') {\r\n currentRoute.children.push({\r\n component: 'buckaroo-payment-detail',\r\n name: 'buckaroo.payment.detail',\r\n isChildren: true,\r\n path: '/sw/order/buckaroo/detail/:id'\r\n });\r\n }\r\n next(currentRoute);\r\n },\r\n\r\n routes: {\r\n config: {\r\n component: 'buckaroo-payment-config',\r\n path: ':namespace/payment/:paymentCode',\r\n name: 'buckaroo.config.payment',\r\n meta: {\r\n parentPath:'sw.extension.config'\r\n },\r\n props: {\r\n default(route) {\r\n return { namespace: route.params.namespace };\r\n },\r\n },\r\n }\r\n }\r\n});\r\n","const { Component } = Shopware;\r\n\r\nimport template from './buckaroo-afterpay-old-tax.html.twig';\r\n\r\nComponent.register('buckaroo-afterpay-old-tax', {\r\n template,\r\n\r\n inject: ['BuckarooPaymentSettingsService'],\r\n\r\n data() {\r\n return {\r\n taxes: [],\r\n showTaxes: false,\r\n afterpayTaxes: [\r\n { name: this.$tc('buckaroo-payment.afterpay.hightTaxes'), id: 1 },\r\n { name: this.$tc('buckaroo-payment.afterpay.middleTaxes'), id: 5 },\r\n { name: this.$tc('buckaroo-payment.afterpay.lowTaxes'), id: 2 },\r\n { name: this.$tc('buckaroo-payment.afterpay.zeroTaxes'), id: 3 },\r\n { name: this.$tc('buckaroo-payment.afterpay.noTaxes'), id: 4 },\r\n ],\r\n taxAssociation: {}\r\n };\r\n },\r\n\r\n model: {\r\n prop: 'value',\r\n event: 'change',\r\n },\r\n\r\n computed: {\r\n\r\n },\r\n props: {\r\n name: {\r\n type: String,\r\n required: true,\r\n default: ''\r\n },\r\n value: {\r\n type: Object,\r\n required: false,\r\n default() {\r\n return {}\r\n }\r\n }\r\n },\r\n\r\n\r\n created() {\r\n this.BuckarooPaymentSettingsService.getTaxes()\r\n .then((result) => {\r\n this.taxes = result.taxes.map((tax) => {\r\n return {\r\n id: tax.id,\r\n name: tax.name\r\n };\r\n })\r\n });\r\n\r\n },\r\n methods: {\r\n setTaxAssociation(taxId, eventOrValue) {\r\n \r\n try {\r\n let actualValue = eventOrValue;\r\n \r\n if (eventOrValue && typeof eventOrValue === 'object') {\r\n if (eventOrValue.target) {\r\n actualValue = eventOrValue.target.value;\r\n } else if (eventOrValue.hasOwnProperty('value')) {\r\n actualValue = eventOrValue.value;\r\n } else if (eventOrValue.hasOwnProperty('id')) {\r\n actualValue = eventOrValue.id;\r\n }\r\n }\r\n this.taxAssociation[taxId] = actualValue;\r\n this.$emit('change', {...this.value, ...this.taxAssociation});\r\n \r\n } catch (error) {\r\n console.error('Error in setTaxAssociation:', error);\r\n }\r\n },\r\n getSelectValue(taxId) {\r\n if (this.value[taxId]) {\r\n return this.value[taxId];\r\n }\r\n return;\r\n }\r\n }\r\n });\r\n","const { Component } = Shopware;\r\n\r\nimport template from \"./buckaroo-main-config.html.twig\";\r\n\r\nComponent.register(\"buckaroo-main-config\", {\r\n template,\r\n props: {\r\n configSettings: {\r\n type: Array,\r\n required: false,\r\n default: () => []\r\n },\r\n value: {\r\n type: Object,\r\n required: false,\r\n default: () => ({})\r\n },\r\n elementMethods: {\r\n type: Object,\r\n required: false,\r\n default: () => ({})\r\n },\r\n isNotDefaultSalesChannel: {\r\n type: Boolean,\r\n required: false,\r\n default: false\r\n },\r\n currentSalesChannelId: {\r\n type: String,\r\n required: false,\r\n default: null\r\n }\r\n },\r\n emits: ['input'],\r\n\r\n model: {\r\n prop: 'value',\r\n event: 'input'\r\n },\r\n\r\n\r\n data() {\r\n return {\r\n selectedCard: this.$route.params?.paymentCode || 'general'\r\n }\r\n },\r\n\r\n watch: {\r\n value: {\r\n handler(newVal, oldVal) {\r\n this.$nextTick(() => {\r\n this.$forceUpdate();\r\n });\r\n },\r\n deep: true,\r\n immediate: true\r\n },\r\n $route(to) {\r\n if (to.params?.paymentCode) {\r\n this.selectedCard = to.params.paymentCode;\r\n }\r\n }\r\n },\r\n\r\n computed: {\r\n mainCard() {\r\n const card = this.configSettings.filter((card) => card.name === this.selectedCard)?.pop();\r\n return card;\r\n }\r\n },\r\n\r\n methods: {\r\n onInput(value) {\r\n this.$emit('input', value);\r\n }\r\n }\r\n\r\n})","import template from './buckaroo-config-card.html.twig';\n\nconst { Component } = Shopware;\n\nComponent.register('buckaroo-config-card', {\n template,\n\n inject: ['BuckarooPaymentSettingsService'],\n\n data() {\n return {\n shopwareVersion: null\n };\n },\n\n mounted() {\n this.fetchShopwareVersion();\n this.$nextTick(() => {\n this.$forceUpdate();\n });\n },\n watch: {\n value: {\n handler() {\n this.$nextTick(() => {\n this.$forceUpdate();\n });\n },\n deep: true,\n immediate: true\n },\n \n currentSalesChannelId: {\n handler(newChannelId, oldChannelId) {\n if (newChannelId !== oldChannelId) {\n \n this.$nextTick(() => {\n this.$forceUpdate();\n });\n }\n },\n immediate: false\n }\n },\n computed: {\n canShowCredentialTester() {\n const key = this.getValueForName('websiteKey');\n const secretKey = this.getValueForName('secretKey');\n const isGeneralConfig = this.card?.name === 'general';\n \n if (!isGeneralConfig) {\n return false;\n }\n\n const hasWebsiteKey = key !== undefined && key !== null && key !== '';\n const hasSecretKey = secretKey !== undefined && secretKey !== null && secretKey !== '';\n const canShow = hasWebsiteKey || hasSecretKey;\n return canShow;\n },\n \n hasValidConfigData() {\n return this.value && typeof this.value === 'object' && Object.keys(this.value).length > 0;\n },\n \n reactiveValue() {\n return this.value;\n }\n },\n\n emits: ['input'],\n\n model: {\n prop: 'value',\n event: 'input'\n },\n\n props: {\n card: {\n type: Object,\n required: false,\n default: () => ({ elements: [] })\n },\n configSettings: {\n type: Array,\n required: false,\n default: () => []\n },\n methods: {\n type: Object,\n required: true,\n },\n isNotDefaultSalesChannel: {\n type: Boolean,\n required: true,\n },\n currentSalesChannelId: {\n type: String,\n required: true,\n },\n value: {\n type: Object,\n required: false,\n default: () => ({})\n },\n },\n\n methods: {\n fetchShopwareVersion() {\n const service = this.BuckarooPaymentSettingsService;\n if (service && typeof service.getSupportVersion === 'function') {\n service.getSupportVersion().then((data) => {\n if (data && data.shopware_version) {\n this.shopwareVersion = data.shopware_version;\n }\n }).catch(() => {});\n }\n },\n\n /**\n * Returns true if Shopware version is >= 6.7.4.0 (label fix applies; older versions show duplicate labels if we use enhanced label logic).\n * When version is unknown, returns false to avoid duplicate labels on older Shopware.\n */\n isShopware674OrNewer() {\n if (!this.shopwareVersion || typeof this.shopwareVersion !== 'string') {\n return false;\n }\n const parts = this.shopwareVersion.split('.').map((n) => parseInt(n, 10) || 0);\n const major = parts[0] || 0;\n const minor = parts[1] || 0;\n const patch = parts[2] || 0;\n const build = parts[3] || 0;\n if (major > 6) return true;\n if (major < 6) return false;\n if (minor > 7) return true;\n if (minor < 7) return false;\n if (patch > 4) return true;\n if (patch < 4) return false;\n return build >= 0;\n },\n\n getElementBind(element, props = {}) {\n if (!this.methods || !this.methods.getElementBind) {\n const label = element.label ? this.getInlineSnippet(element.label) : null;\n return {\n name: element.name,\n type: element.type || 'text',\n config: element.config || {},\n label: label,\n value: this.getValueForName(element.name.replace('BuckarooPayments.config.', ''))\n };\n }\n \n const baseBinding = this.methods.getElementBind(element, props);\n \n const fieldName = element.name.replace('BuckarooPayments.config.', '');\n let currentValue = this.getValueForName(fieldName);\n \n // Ensure config object exists\n const config = baseBinding.config || element.config || {};\n \n // For bool fields, ensure we have a proper boolean value\n if (element.type === 'bool') {\n if (currentValue === null || currentValue === undefined) {\n currentValue = baseBinding.value !== undefined ? baseBinding.value : false;\n } else {\n // Ensure it's a proper boolean - handle string values like \"0\", \"1\", \"false\", \"true\"\n if (typeof currentValue === 'string') {\n currentValue = currentValue === '1' || currentValue === 'true' || currentValue === 'on';\n } else {\n currentValue = Boolean(currentValue);\n }\n }\n }\n \n // Extract label only for Shopware >= 6.7.4.0; in older versions baseBinding/template already show the label and our enhanced logic causes duplicate labels\n let finalLabel = null;\n const useEnhancedLabels = this.isShopware674OrNewer();\n\n if (useEnhancedLabels) {\n // For bool/select fields, prioritize configSettings since baseBinding.label is often undefined in SW 6.7.4+\n if ((element.type === 'bool' || element.type === 'single-select' || element.type === 'multi-select') && this.configSettings && Array.isArray(this.configSettings)) {\n for (const configCard of this.configSettings) {\n if (configCard.elements && Array.isArray(configCard.elements)) {\n const configElement = configCard.elements.find(el => el.name === element.name);\n if (configElement) {\n if (configElement.label) {\n let extractedLabel = this.getInlineSnippet(configElement.label);\n if (!extractedLabel || (typeof extractedLabel === 'string' && extractedLabel.trim().length === 0)) {\n if (typeof configElement.label === 'object' && configElement.label !== null) {\n const locale = this.$i18n?.locale || 'en-GB';\n extractedLabel = configElement.label[locale] || configElement.label['en-GB'] || Object.values(configElement.label)[0] || null;\n } else if (typeof configElement.label === 'string') {\n extractedLabel = configElement.label;\n }\n }\n if (extractedLabel && typeof extractedLabel === 'string' && extractedLabel.trim().length > 0) {\n finalLabel = extractedLabel;\n break;\n }\n }\n if (!finalLabel && configElement.config && configElement.config.label) {\n let extractedLabel = this.getInlineSnippet(configElement.config.label);\n if (!extractedLabel || (typeof extractedLabel === 'string' && extractedLabel.trim().length === 0)) {\n if (typeof configElement.config.label === 'object' && configElement.config.label !== null) {\n const locale = this.$i18n?.locale || 'en-GB';\n extractedLabel = configElement.config.label[locale] || configElement.config.label['en-GB'] || Object.values(configElement.config.label)[0] || null;\n } else if (typeof configElement.config.label === 'string') {\n extractedLabel = configElement.config.label;\n }\n }\n if (extractedLabel && typeof extractedLabel === 'string' && extractedLabel.trim().length > 0) {\n finalLabel = extractedLabel;\n break;\n }\n }\n }\n }\n }\n }\n\n if (!finalLabel) {\n if (baseBinding.label && typeof baseBinding.label === 'string' && baseBinding.label.trim().length > 0) {\n finalLabel = baseBinding.label;\n } else if (element.label) {\n let extractedLabel = this.getInlineSnippet(element.label);\n if (!extractedLabel || (typeof extractedLabel === 'string' && extractedLabel.trim().length === 0)) {\n if (typeof element.label === 'object' && element.label !== null) {\n const locale = this.$i18n?.locale || 'en-GB';\n extractedLabel = element.label[locale] || element.label['en-GB'] || Object.values(element.label)[0] || null;\n } else if (typeof element.label === 'string') {\n extractedLabel = element.label;\n }\n }\n if (extractedLabel && typeof extractedLabel === 'string' && extractedLabel.trim().length > 0) {\n finalLabel = extractedLabel;\n }\n } else if (this.card && this.card.elements && Array.isArray(this.card.elements)) {\n const rawElement = this.card.elements.find(el => el.name === element.name);\n if (rawElement && rawElement.label) {\n let extractedLabel = this.getInlineSnippet(rawElement.label);\n if (!extractedLabel || (typeof extractedLabel === 'string' && extractedLabel.trim().length === 0)) {\n if (typeof rawElement.label === 'object' && rawElement.label !== null) {\n const locale = this.$i18n?.locale || 'en-GB';\n extractedLabel = rawElement.label[locale] || rawElement.label['en-GB'] || Object.values(rawElement.label)[0] || null;\n } else if (typeof rawElement.label === 'string') {\n extractedLabel = rawElement.label;\n }\n }\n if (extractedLabel && typeof extractedLabel === 'string' && extractedLabel.trim().length > 0) {\n finalLabel = extractedLabel;\n }\n }\n }\n }\n if (!finalLabel && baseBinding.config && baseBinding.config.label && typeof baseBinding.config.label === 'string' && baseBinding.config.label.trim().length > 0) {\n finalLabel = baseBinding.config.label;\n }\n }\n\n // Only add label to config for SW >= 6.7.4.0 (avoids duplicate labels in older versions)\n let finalConfig = config;\n if (useEnhancedLabels && finalLabel && typeof finalLabel === 'string' && finalLabel.trim().length > 0) {\n if (element.type === 'bool' || element.type === 'single-select' || element.type === 'multi-select') {\n finalConfig = {\n ...config,\n label: finalLabel\n };\n }\n }\n\n const binding = {\n ...baseBinding,\n config: finalConfig\n };\n\n // Ensure specific fields are treated as real multi-selects in the UI\n const forcedMultiSelectFields = [\n 'allowedcreditcard',\n 'allowedcreditcards',\n 'allowedgiftcards',\n 'giftcardsPaymentmethods',\n 'payperemailAllowed'\n ];\n\n if (forcedMultiSelectFields.includes(fieldName)) {\n binding.type = 'multi-select';\n // Force Shopware to render the correct component\n binding.componentName = 'sw-multi-select';\n\n binding.config = {\n ...(binding.config || {}),\n multiple: true,\n // Prefer options coming from binding.config; fall back to element/config when needed\n options: (binding.config && binding.config.options)\n || (config && config.options)\n || element.options\n || []\n };\n\n // Debug logging to inspect how the multi-select is bound\n const sampleOption = Array.isArray(binding.config?.options) && binding.config.options.length > 0\n ? binding.config.options[0]\n : null;\n console.debug('[BuckarooConfigCard] getElementBind multi-select binding', {\n fieldName,\n bindingType: binding.type,\n componentName: binding.componentName,\n optionsCount: Array.isArray(binding.config?.options) ? binding.config.options.length : 0,\n currentValue,\n sampleOption\n });\n }\n \n // Only set binding.label for SW >= 6.7.4.0; older versions already show the label and would show duplicates\n if (useEnhancedLabels && finalLabel && typeof finalLabel === 'string' && finalLabel.trim().length > 0) {\n if (element.type === 'bool') {\n binding.label = finalLabel;\n } else if (!binding.label || (typeof binding.label === 'string' && binding.label.trim().length === 0)) {\n binding.label = finalLabel;\n }\n }\n\n if (element.type === 'bool') {\n binding.value = currentValue;\n // Only set fallback label for SW >= 6.7.4.0 to avoid duplicate labels in older versions\n if (useEnhancedLabels && (!binding.label || (typeof binding.label === 'string' && binding.label.trim().length === 0))) {\n binding.label = binding.config?.label || element.name.replace('BuckarooPayments.config.', '').replace(/([A-Z])/g, ' $1').trim();\n }\n }\n \n // Debug: Log if label is missing for bool/select fields\n if ((element.type === 'bool' || element.type === 'single-select' || element.type === 'multi-select') && (!binding.label || (typeof binding.label === 'string' && binding.label.trim().length === 0))) {\n console.warn('Missing label for field:', element.name, 'Type:', element.type, 'Element label:', element.label, 'Extracted:', finalLabel, 'BaseBinding label:', baseBinding.label, 'Final binding label:', binding.label);\n }\n \n return binding;\n },\n\n getInheritWrapperBind(element) {\n if (!this.methods || !this.methods.getInheritWrapperBind) {\n const fieldName = element.name.replace('BuckarooPayments.config.', '');\n return {\n name: element.name,\n currentValue: this.getValueForName(fieldName)\n };\n }\n \n const baseBinding = this.methods.getInheritWrapperBind(element);\n const fieldName = element.name.replace('BuckarooPayments.config.', '');\n const currentValue = this.getValueForName(fieldName);\n\n baseBinding.currentValue = currentValue;\n\n \n return baseBinding;\n },\n\n getFieldError(name) {\n if (!this.methods || !this.methods.getFieldError) {\n return null;\n }\n return this.methods.getFieldError(name);\n },\n\n kebabCase(string) {\n if (!this.methods || !this.methods.kebabCase) {\n return string ? string.toLowerCase().replace(/[A-Z]/g, '-$&').replace(/^-/, '') : '';\n }\n return this.methods.kebabCase(string);\n },\n\n getInlineSnippet(title) {\n try {\n if (typeof title === 'object' && title !== null) {\n const locale = this.$i18n?.locale || 'en-GB';\n \n if (title[locale]) {\n return title[locale];\n }\n \n if (title['en-GB']) {\n return title['en-GB'];\n }\n const firstKey = Object.keys(title)[0];\n if (firstKey && title[firstKey]) {\n return title[firstKey];\n }\n \n return JSON.stringify(title);\n }\n \n if (typeof title === 'string') {\n if (this.$t && typeof this.$t === 'function') {\n return this.$t(title);\n }\n return title;\n }\n return String(title);\n \n } catch (error) {\n console.warn('Translation error for:', title, error);\n return typeof title === 'object' ? JSON.stringify(title) : String(title);\n }\n },\n\n getInheritedValue(element) {\n if (!this.methods || !this.methods.getInheritedValue) {\n return null;\n }\n return this.methods.getInheritedValue(element);\n },\n\n getValueForName(name) {\n const currentValue = this.reactiveValue;\n \n if (!currentValue || typeof currentValue !== 'object') {\n return null;\n }\n\n let val = undefined;\n\n const keyVariations = [\n `BuckarooPayments.config.${name}`, // Full prefixed key\n name.toLowerCase(),\n name.charAt(0).toLowerCase() + name.slice(1),\n name.charAt(0).toUpperCase() + name.slice(1)\n ];\n\n for (const key of keyVariations) {\n if (currentValue[key] !== undefined) {\n val = currentValue[key];\n break;\n }\n }\n\n if (val === undefined && currentValue['BuckarooPayments.config'] && typeof currentValue['BuckarooPayments.config'] === 'object') {\n for (const key of keyVariations) {\n if (currentValue['BuckarooPayments.config'][key] !== undefined) {\n val = currentValue['BuckarooPayments.config'][key];\n break;\n }\n }\n }\n\n if (val && typeof val === 'object' && val.hasOwnProperty('_value')) {\n val = val._value;\n }\n return val;\n },\n\n canShow(element) {\n if (!element || !element.name) {\n return false;\n }\n \n const name = element.name.replace('BuckarooPayments.config.', '');\n\n const advancedToggleFields = [\n 'orderStatus',\n 'paymentSuccesStatus',\n 'automaticallyCloseOpenOrders',\n 'sendInvoiceEmail'\n ];\n if (advancedToggleFields.includes(name)) {\n const advancedConfig = this.getValueForName('advancedConfiguration');\n return Boolean(advancedConfig);\n }\n\n if (name === 'idealprocessingRenderMode') {\n return Boolean(this.getValueForName('idealprocessingShowissuers'));\n }\n\n if (name === 'idealRenderMode') {\n return Boolean(this.getValueForName('idealShowissuers'));\n }\n\n const idealFastCheckoutFields = [\n 'idealFastCheckoutEnabled',\n 'idealFastCheckoutVisibility',\n 'idealFastCheckoutLogoScheme'\n ];\n if (idealFastCheckoutFields.includes(name)) {\n return Boolean(this.getValueForName('idealFastCheckout'));\n }\n\n if (name === 'afterpayPaymentstatus') {\n return Boolean(this.getValueForName('afterpayCaptureonshippent'));\n }\n\n if (name === 'afterpayOldtax') {\n return Boolean(this.getValueForName('afterpayEnabledold'));\n }\n\n return true;\n },\n\n onInput(value) {\n this.$emit('input', value);\n },\n onFieldInput(fieldName, eventOrValue) {\n\n try {\n let actualValue = eventOrValue;\n \n if (eventOrValue && typeof eventOrValue === 'object') {\n if (eventOrValue.target) {\n const target = eventOrValue.target;\n\n if (target.type === 'checkbox' || target.type === 'radio') {\n actualValue = target.checked;\n } else if (target.tagName === 'SELECT' || target.type === 'select-one' || target.type === 'select-multiple') {\n if (target.multiple) {\n actualValue = Array.from(target.selectedOptions).map(option => option.value);\n } else {\n actualValue = target.value;\n }\n } else {\n actualValue = target.value;\n }\n } else if (eventOrValue.hasOwnProperty('value')) {\n actualValue = eventOrValue.value;\n } else if (eventOrValue.hasOwnProperty('id') && eventOrValue.hasOwnProperty('name')) {\n actualValue = eventOrValue.id;\n } else if (Array.isArray(eventOrValue)) {\n const totalCharacters = eventOrValue.filter(item => typeof item === 'string' && item.length === 1).length;\n const hasCommas = eventOrValue.some(item => item === ',');\n const hasLongStrings = eventOrValue.some(item => typeof item === 'string' && item.length > 1);\n\n const isCharacterArray = totalCharacters > 10 && hasCommas;\n\n \n if (isCharacterArray) {\n const correctValues = eventOrValue.filter(item => typeof item === 'string' && item.length > 1);\n const characterPart = eventOrValue.filter(item => typeof item === 'string' && item.length === 1);\n const rejoined = characterPart.join('');\n \n let splitValues = [];\n if (rejoined.includes(',')) {\n splitValues = rejoined.split(',').map(item => item.trim()).filter(item => item.length > 0);\n } else if (rejoined.length > 0) {\n splitValues = [rejoined];\n }\n\n actualValue = [...splitValues, ...correctValues].filter(item => item && item.length > 0);\n } else {\n actualValue = eventOrValue\n .filter(item => {\n if (item === null || item === undefined || item === '') {\n return false;\n }\n\n if (typeof item === 'string' && item.length === 1) {\n return false;\n }\n\n if (typeof item === 'string' && (item.startsWith('+') || /^\\d+$/.test(item))) {\n\n return false;\n }\n \n return true;\n })\n .map(item => {\n if (typeof item === 'object' && item !== null) {\n let extractedValue = item.id || item.value || item.code || item.key || item;\n return extractedValue;\n }\n return item;\n });\n }\n\n } else {\n const possibleKeys = ['id', 'value', 'key', 'code'];\n for (const key of possibleKeys) {\n if (eventOrValue[key] !== undefined) {\n actualValue = eventOrValue[key];\n break;\n }\n }\n }\n } else if (typeof eventOrValue === 'boolean') {\n actualValue = eventOrValue;\n } else if (typeof eventOrValue === 'string' || typeof eventOrValue === 'number') {\n actualValue = eventOrValue;\n }\n\n // Determine the element definition once so we can branch on its type\n const element = this.card?.elements?.find(\n el => el.name === fieldName\n || el.name.replace('BuckarooPayments.config.', '') === fieldName.replace('BuckarooPayments.config.', '')\n );\n\n if (actualValue === \"on\") {\n actualValue = true;\n } else if (actualValue === \"off\") {\n actualValue = false;\n }\n \n // For bool fields, ensure we always have a proper boolean\n if (element && element.type === 'bool') {\n if (typeof actualValue === 'string') {\n actualValue = actualValue === '1' || actualValue === 'true' || actualValue === 'on';\n } else {\n actualValue = Boolean(actualValue);\n }\n }\n\n // For multi-select fields, ALWAYS store an array of selected values.\n // This ensures components like sw-multi-select keep multiple selections\n // instead of degrading to a single selected option.\n if (element && element.type === 'multi-select') {\n console.debug('[BuckarooConfigCard] onFieldInput before normalize (multi-select)', {\n fieldName,\n rawEvent: eventOrValue,\n rawValue: actualValue\n });\n\n if (Array.isArray(actualValue)) {\n // Normalize array items to primitive ids / values\n actualValue = actualValue\n .filter(item => item !== null && item !== undefined && item !== '')\n .map(item => {\n if (typeof item === 'object' && item !== null) {\n return item.id || item.value || item.code || item.key || item;\n }\n return item;\n });\n } else if (typeof actualValue === 'string') {\n // Support comma-separated string values (just in case)\n actualValue = actualValue\n .split(',')\n .map(v => v.trim())\n .filter(v => v.length > 0);\n } else if (actualValue === null || actualValue === undefined) {\n actualValue = [];\n } else {\n // Fallback: wrap single primitive value into an array\n actualValue = [actualValue];\n }\n\n console.debug('[BuckarooConfigCard] onFieldInput after normalize (multi-select)', {\n fieldName,\n normalizedValue: actualValue\n });\n }\n \n const cleanFieldName = fieldName.replace('BuckarooPayments.config.', '');\n const updatedValue = { ...this.value };\n\n updatedValue[cleanFieldName] = actualValue;\n updatedValue[fieldName] = actualValue;\n\n this.$emit('input', updatedValue);\n \n } catch (error) {\n console.error('Error in onFieldInput:', error);\n console.error('Error details:', error.stack);\n }\n }\n }\n});\n","const { Component, Filter } = Shopware;\r\nimport template from \"./buckaroo-payment-list.html.twig\";\r\nimport \"./style.scss\";\r\n\r\nComponent.register(\"buckaroo-payment-list\", {\r\n template,\r\n props: {\r\n configSettings: {\r\n type: Array,\r\n required: false,\r\n default: () => []\r\n },\r\n value: {\r\n type: Object,\r\n required: false,\r\n default: () => ({})\r\n },\r\n currentSalesChannelId: {\r\n type: String,\r\n required: true\r\n }\r\n },\r\n\r\n emits: ['input'],\r\n\r\n data() {\r\n return {\r\n payments: [\r\n {\r\n code: \"Alipay\",\r\n logo: \"alipay.svg\"\r\n },\r\n {\r\n code: \"applepay\",\r\n logo: \"applepay.svg\"\r\n },\r\n {\r\n code: \"googlepay\",\r\n logo: \"googlepay.svg\"\r\n },\r\n {\r\n code: \"bancontactmrcash\",\r\n logo: \"bancontact.svg\"\r\n },\r\n {\r\n code: \"blik\",\r\n logo: \"blik.svg\"\r\n },\r\n {\r\n code: \"belfius\",\r\n logo: \"belfius.svg\"\r\n },\r\n {\r\n code: \"Billink\",\r\n logo: \"billink.svg\"\r\n },\r\n {\r\n code: \"creditcard\",\r\n logo: \"creditcards.svg\"\r\n },\r\n {\r\n code: \"creditcards\",\r\n logo: \"creditcards.svg\"\r\n },\r\n {\r\n code: \"eps\",\r\n logo: \"eps.svg\"\r\n },\r\n {\r\n code: \"giftcards\",\r\n logo: \"giftcards.svg\"\r\n },\r\n {\r\n code: \"idealqr\",\r\n logo: \"ideal-qr.svg\"\r\n },\r\n {\r\n code: \"ideal\",\r\n logo: \"ideal-wero.svg\"\r\n },\r\n {\r\n code: \"capayable\",\r\n logo: \"in3.svg\"\r\n },\r\n {\r\n code: \"KBCPaymentButton\",\r\n logo: \"kbc.svg\"\r\n },\r\n {\r\n code: \"klarna\",\r\n logo: \"klarna.svg\"\r\n },\r\n {\r\n code: \"klarnakp\",\r\n logo: \"klarna.svg\"\r\n },\r\n {\r\n code: \"knaken\",\r\n logo: \"gosettle.svg\"\r\n },\r\n {\r\n code: \"mbway\",\r\n logo: \"mbway.svg\"\r\n },\r\n {\r\n code: \"multibanco\",\r\n logo: \"multibanco.svg\"\r\n },\r\n {\r\n code: \"paybybank\",\r\n logo: \"paybybank.svg\"\r\n },\r\n {\r\n code: \"payconiq\",\r\n logo: \"payconiq.svg\"\r\n },\r\n {\r\n code: \"paypal\",\r\n logo: \"paypal.svg\"\r\n },\r\n {\r\n code: \"payperemail\",\r\n logo: \"payperemail.svg\"\r\n },\r\n {\r\n code: \"Przelewy24\",\r\n logo: \"przelewy24.svg\"\r\n },\r\n {\r\n code: \"afterpay\",\r\n logo: \"afterpay.svg\"\r\n },\r\n {\r\n code: \"sepadirectdebit\",\r\n logo: \"sepa-directdebit.svg\"\r\n },\r\n {\r\n code: \"transfer\",\r\n logo: \"sepa-credittransfer.svg\"\r\n },\r\n {\r\n code: \"Trustly\",\r\n logo: \"trustly.svg\"\r\n },\r\n {\r\n code: \"WeChatPay\",\r\n logo: \"wechatpay.svg\"\r\n },\r\n {\r\n code: \"swish\",\r\n logo: \"swish.svg\"\r\n },\r\n {\r\n code: \"bizum\",\r\n logo: \"bizum.svg\"\r\n },\r\n {\r\n code: \"twint\",\r\n logo: \"twint.svg\"\r\n },\r\n {\r\n code: \"wero\",\r\n logo: \"wero.svg\"\r\n }\r\n ]\r\n };\r\n },\r\n methods: {\r\n getPaymentTitle(code) {\r\n if (this.configSettings && Array.isArray(this.configSettings)) {\r\n const card = this.configSettings.find((card) => card.name === code);\r\n if (card && card.title) {\r\n try {\r\n if (typeof card.title === 'object' && card.title !== null) {\r\n const locale = this.$i18n?.locale || 'en-GB';\r\n\r\n if (card.title[locale]) {\r\n return card.title[locale];\r\n }\r\n if (card.title['en-GB']) {\r\n return card.title['en-GB'];\r\n }\r\n \r\n const firstKey = Object.keys(card.title)[0];\r\n if (firstKey && card.title[firstKey]) {\r\n return card.title[firstKey];\r\n }\r\n \r\n return JSON.stringify(card.title);\r\n }\r\n \r\n if (typeof card.title === 'string') {\r\n if (this.$t && typeof this.$t === 'function') {\r\n return this.$t(card.title);\r\n }\r\n return card.title;\r\n }\r\n \r\n return String(card.title);\r\n \r\n } catch (error) {\r\n console.warn('Translation error for:', card.title, error);\r\n return typeof card.title === 'object' ? JSON.stringify(card.title) : String(card.title);\r\n }\r\n }\r\n }\r\n\r\n const payment = this.payments.find(payment => payment.code === code);\r\n return payment ? payment.code : 'Unknown Payment';\r\n },\r\n assetFilter(path) {\r\n return Filter.getByName('asset')(path);\r\n }\r\n }\r\n});","const { Component } = Shopware;\r\nimport template from \"./buckaroo-test-credentials.twig\";\r\n\r\nComponent.register(\"buckaroo-test-credentials\", {\r\n template,\r\n mixins: [\r\n Shopware.Mixin.getByName('notification')\r\n ],\r\n data() {\r\n return {\r\n isLoading: false,\r\n }\r\n },\r\n inject: [ 'BuckarooPaymentSettingsService' ],\r\n\r\n props: {\r\n config: {\r\n type: Object,\r\n required: true\r\n },\r\n currentSalesChannelId: {\r\n required: true\r\n }\r\n },\r\n computed: {\r\n enabled: function() {\r\n return (this.getConfigValue('websiteKey') || '').length > 0 &&\r\n (this.getConfigValue('secretKey') || '').length > 0\r\n }\r\n },\r\n methods: {\r\n getConfigValue: function(name) {\r\n return this.config[\"BuckarooPayments.config.\"+name];\r\n },\r\n sendTestApi() {\r\n this.isLoading = true;\r\n let websiteKeyId = this.getConfigValue('websiteKey'),\r\n secretKeyId = this.getConfigValue('secretKey');\r\n this.BuckarooPaymentSettingsService.getApiTest(websiteKeyId, secretKeyId, this.currentSalesChannelId)\r\n .then((result) => {\r\n this.isLoading = false;\r\n\r\n if (result.status == 'success') {\r\n this.createNotificationSuccess({\r\n title: this.$tc('buckaroo-payment.settingsForm.titleSuccess'),\r\n message: this.$tc(result.message)\r\n });\r\n } else {\r\n this.createNotificationError({\r\n title: this.$tc('buckaroo-payment.settingsForm.titleError'),\r\n message: this.$tc(result.message)\r\n });\r\n }\r\n\r\n })\r\n .catch(() => {\r\n this.isLoading = false;\r\n });\r\n },\r\n }\r\n})","const { Component } = Shopware;\r\nimport template from \"./buckaroo-toggle-status.html.twig\";\r\nimport './style.scss'\r\n\r\nComponent.register(\"buckaroo-toggle-status\", {\r\n template,\r\n props: {\r\n method: {\r\n type: String,\r\n required: true\r\n },\r\n value: {\r\n required: true\r\n },\r\n currentSalesChannelId: {\r\n required: true,\r\n }\r\n },\r\n\r\n emits: ['input'],\r\n\r\n inject: ['systemConfigApiService'],\r\n data() {\r\n return {\r\n status: 'disabled',\r\n isLoading: false,\r\n }\r\n },\r\n\r\n mounted() {\r\n this.status = this.getStatus();\r\n },\r\n\r\n watch: {\r\n value: {\r\n handler(newVal) {\r\n this.status = this.getStatus();\r\n },\r\n deep: true,\r\n immediate: true\r\n }\r\n },\r\n methods: {\r\n getStatus() {\r\n const isActive = this.isActive();\r\n const environment = this.getEnvironment();\r\n return isActive ? environment : 'disabled';\r\n },\r\n isActive() {\r\n const enabled = this.getValueForName(`${this.method}Enabled`);\r\n if (typeof enabled === 'string') {\r\n return enabled.toLowerCase() === 'true';\r\n }\r\n return Boolean(enabled);\r\n },\r\n getEnvironment() {\r\n const env = this.getValueForName(`${this.method}Environment`);\r\n \r\n if (env === undefined || env === null || env === '') {\r\n return 'test';\r\n }\r\n const validEnvs = ['test', 'live'];\r\n return validEnvs.includes(env) ? env : 'test';\r\n },\r\n getValueForName(name) {\r\n const key = `BuckarooPayments.config.${name}`;\r\n if (!this.value || typeof this.value !== 'object') {\r\n return null;\r\n }\r\n\r\n let val = undefined;\r\n\r\n if (this.value[key] !== undefined) {\r\n val = this.value[key];\r\n }\r\n else if (this.value[name] !== undefined) {\r\n val = this.value[name];\r\n }\r\n else if (this.value['BuckarooPayments.config'] && typeof this.value['BuckarooPayments.config'] === 'object') {\r\n if (this.value['BuckarooPayments.config'][name] !== undefined) {\r\n val = this.value['BuckarooPayments.config'][name];\r\n }\r\n }\r\n else {\r\n const variations = [\r\n name,\r\n name.toLowerCase(),\r\n name.charAt(0).toLowerCase() + name.slice(1),\r\n name.charAt(0).toUpperCase() + name.slice(1)\r\n ];\r\n \r\n for (const variation of variations) {\r\n const variationKey = `BuckarooPayments.config.${variation}`;\r\n if (this.value[variationKey] !== undefined) {\r\n val = this.value[variationKey];\r\n break;\r\n }\r\n if (this.value[variation] !== undefined) {\r\n val = this.value[variation];\r\n break;\r\n }\r\n }\r\n }\r\n\r\n if (val && typeof val === 'object' && val.hasOwnProperty('_value')) {\r\n val = val._value;\r\n }\r\n \r\n return val;\r\n },\r\n setStatus(status) {\r\n this.status = status;\r\n this.saveStatus();\r\n },\r\n getClass(buttonStatus) {\r\n return this.status === buttonStatus ? 'active' : '';\r\n },\r\n async saveStatus() {\r\n const enabledKey = `BuckarooPayments.config.${this.method}Enabled`;\r\n const environmentKey = `BuckarooPayments.config.${this.method}Environment`;\r\n\r\n let data = {[enabledKey]: false};\r\n const updatedValue = { ...this.value };\r\n updatedValue[enabledKey] = false;\r\n\r\n if (['live', 'test'].indexOf(this.status) !== -1) {\r\n data = {\r\n [enabledKey]: true,\r\n [environmentKey]: this.status\r\n }\r\n updatedValue[enabledKey] = true;\r\n updatedValue[environmentKey] = this.status;\r\n }\r\n\r\n this.$emit('input', updatedValue);\r\n\r\n this.isLoading = true;\r\n try {\r\n await this.systemConfigApiService\r\n .batchSave({[this.currentSalesChannelId]: data})\r\n .finally(() => {\r\n this.isLoading = false;\r\n });\r\n this.renderSuccess();\r\n } catch (error) {\r\n this.renderError(error);\r\n }\r\n \r\n },\r\n renderSuccess() {\r\n this.$store.dispatch('notification/createNotification', {\r\n variant: 'success',\r\n message: this.$tc('sw-extension-store.component.sw-extension-config.messageSaveSuccess'),\r\n });\r\n },\r\n\r\n renderError(err) {\r\n this.$store.dispatch('notification/createNotification', {\r\n variant: 'error',\r\n message: err,\r\n });\r\n }\r\n }\r\n})"],"names":["ApiService","Shopware","Classes","BuckarooPaymentSettingsService","constructor","httpClient","loginService","apiEndpoint","super","getBasicHeaders","this","getToken","getSupportVersion","apiRoute","getApiBasePath","post","headers","then","response","handleResponse","getTaxes","getIn3Icons","getApiTest","websiteKeyId","secretKeyId","currentSalesChannelId","saleChannelId","Service","register","initContainer","Application","getContainer","BuckarooPaymentService","getBuckarooTransaction","transaction","refundPayment","transactionsToRefund","orderItems","customRefundAmount","captureOrder","createPaylink","klarnaMor","orderId","action","Component","extend","__webpack_module_cache__","__webpack_require__","moduleId","cachedModule","undefined","exports","module","__webpack_modules__","Context","Criteria","Data","override","template","data","isBuckarooPayment","isPaymentInTestMode","computed","isEditable","$route","name","showTabs","watch","deep","handler","setIsBuckarooPayment","orderRepository","repositoryFactory","create","orderCriteria","addAssociation","get","api","order","setPaymentInTestMode","transactions","length","last","paymentMethodId","immediate","methods","customFields","buckaroo_payment_in_test_mode","paymentMethod","formattedHandlerIdentifier","indexOf","inject","config","created","systemConfigApiService","getValues","values","finally","newVal","oldVal","domain","loadBuckarooConfigData","actualConfigData","processedData","Object","keys","forEach","key","value","hasOwnProperty","_value","shortKey","replace","$nextTick","$forceUpdate","catch","error","console","onConfigDataUpdate","newValue","startsWith","fullFieldName","saveAll","$super","saveBuckaroo","isLoading","batchSave","getSelectedValues","getCurrentConfigCard","code","params","paymentCode","filter","card","pop","currentConfigValues","currentPaymentCard","elements","actualConfigValues","element","cleanFieldName","buckaroo_refund_amount","buckaroo_refund_total_amount","currency","isRefundPossible","isCapturePossible","isPaylinkAvailable","isPaylinkVisible","paylinkMessage","paylink","buckarooTransactions","relatedResources","isAuthorized","isKlarnaMor","fulfillmentMessage","fulfillmentStatus","orderItemsColumns","property","label","$tc","allowResize","primary","inlineEdit","multiLine","rawData","align","transactionsToRefundColumns","relatedResourceColumns","createdComponent","recalculateOrderItems","parseFloat","toFixed","recalculateRefundItems","getCustomRefundEnabledEl","document","getElementById","getCustomRefundAmountEl","toggleCustomRefund","disabled","checked","getCustomRefundAmount","that","id","getAssociation","addSorting","sort","checkedIsAuthorized","buckarooKey","buckaroo_key","toLowerCase","includes","isAfterpayCapturePossible","getConfigValue","stateMachineState","technicalName","$emit","Array","isArray","push","quantity","quantityMax","unitPrice","totalAmount","variations","refundTotals","amount","total","amountMax","transaction_method","logo","transaction_key","total_excluding_vat","shipping_costs","vat","created_at","statuscode","errorResponse","log","buckaroo_is_authorize","refundOrder","status","$store","dispatch","variant","title","message","paylinkhref","field","Module","type","description","version","targetVersion","color","icon","snippets","routeMiddleware","next","currentRoute","children","component","isChildren","path","routes","meta","parentPath","props","default","route","namespace","taxes","showTaxes","afterpayTaxes","taxAssociation","model","prop","event","String","required","result","map","tax","setTaxAssociation","taxId","eventOrValue","actualValue","target","getSelectValue","configSettings","elementMethods","isNotDefaultSalesChannel","Boolean","emits","selectedCard","to","mainCard","onInput","shopwareVersion","mounted","fetchShopwareVersion","newChannelId","oldChannelId","canShowCredentialTester","getValueForName","secretKey","hasValidConfigData","reactiveValue","service","shopware_version","isShopware674OrNewer","parts","split","n","parseInt","major","minor","patch","build","getElementBind","getInlineSnippet","baseBinding","fieldName","currentValue","finalLabel","useEnhancedLabels","configCard","configElement","find","el","extractedLabel","trim","locale","$i18n","rawElement","finalConfig","binding","componentName","multiple","options","sampleOption","debug","bindingType","optionsCount","warn","getInheritWrapperBind","getFieldError","kebabCase","string","firstKey","JSON","stringify","$t","getInheritedValue","val","keyVariations","charAt","slice","toUpperCase","canShow","advancedConfig","onFieldInput","tagName","from","selectedOptions","option","totalCharacters","item","hasCommas","some","correctValues","rejoined","join","splitValues","test","possibleKeys","rawEvent","rawValue","v","normalizedValue","updatedValue","stack","payments","getPaymentTitle","payment","assetFilter","getByName","mixins","Mixin","enabled","sendTestApi","createNotificationSuccess","createNotificationError","method","getStatus","isActive","environment","getEnvironment","env","variation","variationKey","setStatus","saveStatus","getClass","buttonStatus","enabledKey","environmentKey","renderSuccess","renderError","err"],"sourceRoot":""} \ No newline at end of file diff --git a/src/Resources/public/buckaroo-payments.js b/src/Resources/public/buckaroo-payments.js index 4ce739c7..63d47a1f 100644 --- a/src/Resources/public/buckaroo-payments.js +++ b/src/Resources/public/buckaroo-payments.js @@ -1 +1 @@ -(()=>{"use strict";var e={735:e=>{var t=function(e){return function(e){return!!e&&"object"==typeof e}(e)&&!function(e){var t=Object.prototype.toString.call(e);return"[object RegExp]"===t||"[object Date]"===t||function(e){return e.$$typeof===n}(e)}(e)},n="function"==typeof Symbol&&Symbol.for?Symbol.for("react.element"):60103;function i(e,t){return!1!==t.clone&&t.isMergeableObject(e)?a((n=e,Array.isArray(n)?[]:{}),e,t):e;var n}function o(e,t,n){return e.concat(t).map((function(e){return i(e,n)}))}function r(e){return Object.keys(e).concat(function(e){return Object.getOwnPropertySymbols?Object.getOwnPropertySymbols(e).filter((function(t){return Object.propertyIsEnumerable.call(e,t)})):[]}(e))}function s(e,t){try{return t in e}catch(e){return!1}}function a(e,n,c){(c=c||{}).arrayMerge=c.arrayMerge||o,c.isMergeableObject=c.isMergeableObject||t,c.cloneUnlessOtherwiseSpecified=i;var l=Array.isArray(n);return l===Array.isArray(e)?l?c.arrayMerge(e,n,c):function(e,t,n){var o={};return n.isMergeableObject(e)&&r(e).forEach((function(t){o[t]=i(e[t],n)})),r(t).forEach((function(r){(function(e,t){return s(e,t)&&!(Object.hasOwnProperty.call(e,t)&&Object.propertyIsEnumerable.call(e,t))})(e,r)||(s(e,r)&&n.isMergeableObject(t[r])?o[r]=function(e,t){if(!t.customMerge)return a;var n=t.customMerge(e);return"function"==typeof n?n:a}(r,n)(e[r],t[r],n):o[r]=i(t[r],n))})),o}(e,n,c):i(n,c)}a.all=function(e,t){if(!Array.isArray(e))throw new Error("first argument should be an array");return e.reduce((function(e,n){return a(e,n,t)}),{})};var c=a;e.exports=c}},t={};function n(i){var o=t[i];if(void 0!==o)return o.exports;var r=t[i]={exports:{}};return e[i](r,r.exports,n),r.exports}n.n=e=>{var t=e&&e.__esModule?()=>e.default:()=>e;return n.d(t,{a:t}),t},n.d=(e,t)=>{for(var i in t)n.o(t,i)&&!n.o(e,i)&&Object.defineProperty(e,i,{enumerable:!0,get:t[i]})},n.o=(e,t)=>Object.prototype.hasOwnProperty.call(e,t);var i=n(735),o=n.n(i);class r{static ucFirst(e){return e.charAt(0).toUpperCase()+e.slice(1)}static lcFirst(e){return e.charAt(0).toLowerCase()+e.slice(1)}static toDashCase(e){return e.replace(/([A-Z])/g,"-$1").replace(/^-/,"").toLowerCase()}static toLowerCamelCase(e,t){const n=r.toUpperCamelCase(e,t);return r.lcFirst(n)}static toUpperCamelCase(e,t){return t?e.split(t).map((e=>r.ucFirst(e.toLowerCase()))).join(""):r.ucFirst(e.toLowerCase())}static parsePrimitive(e){try{return/^\d+(.|,)\d+$/.test(e)&&(e=e.replace(",",".")),JSON.parse(e)}catch(t){return e.toString()}}}class s{static isNode(e){return"object"==typeof e&&null!==e&&(e===document||e===window||e instanceof Node)}static hasAttribute(e,t){if(!s.isNode(e))throw new Error("The element must be a valid HTML Node!");return"function"==typeof e.hasAttribute&&e.hasAttribute(t)}static getAttribute(e,t,n=!0){if(n&&!1===s.hasAttribute(e,t))throw new Error(`The required property "${t}" does not exist!`);if("function"==typeof e.getAttribute)return e.getAttribute(t);if(n)throw new Error("This node doesn't support the getAttribute function!")}static getDataAttribute(e,t,n=!0){const i=t.replace(/^data(|-)/,""),o=r.toLowerCamelCase(i,"-");if(!s.isNode(e)){if(n)throw new Error("The passed node is not a valid HTML Node!");return}if(void 0===e.dataset){if(n)throw new Error("This node doesn't support the dataset attribute!");return}const a=e.dataset[o];if(void 0===a){if(n)throw new Error(`The required data attribute "${t}" does not exist on ${e}!`);return a}return r.parsePrimitive(a)}static querySelector(e,t,n=!0){if(n&&!s.isNode(e))throw new Error("The parent node is not a valid HTML Node!");const i=e.querySelector(t)||!1;if(n&&!1===i)throw new Error(`The required element "${t}" does not exist in parent node!`);return i}static querySelectorAll(e,t,n=!0){if(n&&!s.isNode(e))throw new Error("The parent node is not a valid HTML Node!");let i=e.querySelectorAll(t);if(0===i.length&&(i=!1),n&&!1===i)throw new Error(`At least one item of "${t}" must exist in parent node!`);return i}static getFocusableElements(e=document.body){return e.querySelectorAll('\n input:not([tabindex^="-"]):not([disabled]):not([type="hidden"]),\n select:not([tabindex^="-"]):not([disabled]),\n textarea:not([tabindex^="-"]):not([disabled]),\n button:not([tabindex^="-"]):not([disabled]),\n a[href]:not([tabindex^="-"]):not([disabled]),\n [tabindex]:not([tabindex^="-"]):not([disabled])\n ')}static getFirstFocusableElement(e=document.body){return this.getFocusableElements(e)[0]}static getLastFocusableElement(e=document){const t=this.getFocusableElements(e);return t[t.length-1]}}class a{constructor(e=document){this._el=e,e.$emitter=this,this._listeners=[]}publish(e,t={},n=!1){const i=new CustomEvent(e,{detail:t,cancelable:n});return this.el.dispatchEvent(i),i}subscribe(e,t,n={}){const i=this,o=e.split(".");let r=n.scope?t.bind(n.scope):t;if(n.once&&!0===n.once){const t=r;r=function(n){i.unsubscribe(e),t(n)}}return this.el.addEventListener(o[0],r),this.listeners.push({splitEventName:o,opts:n,cb:r}),!0}unsubscribe(e){const t=e.split(".");return this.listeners=this.listeners.reduce(((e,n)=>[...n.splitEventName].sort().toString()===t.sort().toString()?(this.el.removeEventListener(n.splitEventName[0],n.cb),e):(e.push(n),e)),[]),!0}reset(){return this.listeners.forEach((e=>{this.el.removeEventListener(e.splitEventName[0],e.cb)})),this.listeners=[],!0}get el(){return this._el}set el(e){this._el=e}get listeners(){return this._listeners}set listeners(e){this._listeners=e}}class c{constructor(e,t={},n=!1){if(!s.isNode(e))throw new Error("There is no valid element given.");this.el=e,this.$emitter=new a(this.el),this._pluginName=this._getPluginName(n),this.options=this._mergeOptions(t),this._initialized=!1,this._registerInstance(),this._init()}init(){throw new Error(`The "init" method for the plugin "${this._pluginName}" is not defined.`)}update(){}_init(){this._initialized||(this.init(),this._initialized=!0)}_update(){this._initialized&&this.update()}_mergeOptions(e){const t=r.toDashCase(this._pluginName),n=s.getDataAttribute(this.el,`data-${t}-config`,!1),i=s.getAttribute(this.el,`data-${t}-options`,!1),a=[this.constructor.options,this.options,e];n&&a.push(window.PluginConfigManager.get(this._pluginName,n));try{i&&a.push(JSON.parse(i))}catch(e){throw console.error(this.el),new Error(`The data attribute "data-${t}-options" could not be parsed to json: ${e.message}`)}return o().all(a.filter((e=>e instanceof Object&&!(e instanceof Array))).map((e=>e||{})))}_registerInstance(){window.PluginManager.getPluginInstancesFromElement(this.el).set(this._pluginName,this),window.PluginManager.getPlugin(this._pluginName,!1).get("instances").push(this)}_getPluginName(e){return e||(e=this.constructor.name),e}}class l{constructor(){this._request=null,this._errorHandlingInternal=!1}get(e,t,n="application/json"){const i=this._createPreparedRequest("GET",e,n);return this._sendRequest(i,null,t)}post(e,t,n,i="application/json"){i=this._getContentType(t,i);const o=this._createPreparedRequest("POST",e,i);return this._sendRequest(o,t,n)}delete(e,t,n,i="application/json"){i=this._getContentType(t,i);const o=this._createPreparedRequest("DELETE",e,i);return this._sendRequest(o,t,n)}patch(e,t,n,i="application/json"){i=this._getContentType(t,i);const o=this._createPreparedRequest("PATCH",e,i);return this._sendRequest(o,t,n)}abort(){if(this._request)return this._request.abort()}setErrorHandlingInternal(e){this._errorHandlingInternal=e}_registerOnLoaded(e,t){t&&(!0===this._errorHandlingInternal?(e.addEventListener("load",(()=>{t(e.responseText,e)})),e.addEventListener("abort",(()=>{console.warn(`the request to ${e.responseURL} was aborted`)})),e.addEventListener("error",(()=>{console.warn(`the request to ${e.responseURL} failed with status ${e.status}`)})),e.addEventListener("timeout",(()=>{console.warn(`the request to ${e.responseURL} timed out`)}))):e.addEventListener("loadend",(()=>{t(e.responseText,e)})))}_sendRequest(e,t,n){return this._registerOnLoaded(e,n),e.send(t),e}_getContentType(e,t){return e instanceof FormData&&(t=!1),t}_createPreparedRequest(e,t,n){return this._request=new XMLHttpRequest,this._request.open(e,t),this._request.setRequestHeader("X-Requested-With","XMLHttpRequest"),n&&this._request.setRequestHeader("Content-type",n),this._request}}class d{static iterate(e,t){if(e instanceof Map)return e.forEach(t);if(Array.isArray(e))return e.forEach(t);if(!(e instanceof FormData)){if(e instanceof NodeList)return e.forEach(t);if(e instanceof HTMLCollection)return Array.from(e).forEach(t);if(e instanceof Object)return Object.keys(e).forEach((n=>{t(e[n],n)}));throw new Error(`The element type ${typeof e} is not iterable!`)}for(var n of e.entries())t(n[1],n[0])}}class u{static serialize(e,t=!0){if("FORM"!==e.nodeName){if(t)throw new Error("The passed element is not a form!");return{}}return new FormData(e)}static serializeJson(e,t=!0){const n=u.serialize(e,t);if(0===Object.keys(n).length)return{};const i={};return d.iterate(n,((e,t)=>i[t]=e)),i}}const p={PayPayment:function(e){var t=this;this.applePayVersion=4,this.validationUrl="https://applepay.buckaroo.io/v1/request-session",this.abortSession=function(){t.session&&t.session.abort()},this.init=function(){null===document.getElementById("buckaroo-sdk-css")&&document.head.insertAdjacentHTML("beforeend",'')},this.validate=function(){if(!t.options.processCallback)throw"ApplePay: processCallback must be set";if(!t.options.storeName)throw"ApplePay: storeName is not set";if(!t.options.countryCode)throw"ApplePay: countryCode is not set";if(!t.options.currencyCode)throw"ApplePay: currencyCode is not set";if(!t.options.merchantIdentifier)throw"ApplePay: merchantIdentifier is not set"},this.beginPayment=function(){var e={countryCode:t.options.countryCode,currencyCode:t.options.currencyCode,merchantCapabilities:t.options.merchantCapabilities,supportedNetworks:t.options.supportedNetworks,lineItems:t.options.lineItems,total:t.options.totalLineItem,requiredBillingContactFields:t.options.requiredBillingContactFields,requiredShippingContactFields:t.options.requiredShippingContactFields,shippingType:t.options.shippingType,shippingMethods:t.options.shippingMethods};t.session=new ApplePaySession(t.applePayVersion,e),t.session.onvalidatemerchant=t.onValidateMerchant,t.options.shippingMethodSelectedCallback&&(t.session.onshippingmethodselected=t.onShippingMethodSelected),t.options.shippingContactSelectedCallback&&(t.session.onshippingcontactselected=t.onShippingContactSelected),t.options.cancelCallback&&(t.session.oncancel=t.onCancel),t.session.onpaymentauthorized=t.onPaymentAuthorized,t.session.begin()},this.onValidateMerchant=function(e){var n={validationUrl:e.validationURL,displayName:t.options.storeName,domainName:window.location.hostname,merchantIdentifier:t.options.merchantIdentifier};fetch(t.validationUrl,{method:"POST",body:JSON.stringify(n)}).then((e=>e.json())).then((function(e){t.session.completeMerchantValidation(e)}))},this.onPaymentAuthorized=function(e){var n=e.payment;t.options.processCallback(n).then((function(e){t.session.completePayment(e)}))},this.onShippingMethodSelected=function(e){t.options.shippingMethodSelectedCallback&&t.options.shippingMethodSelectedCallback(e.shippingMethod).then((function(e){e&&t.session.completeShippingMethodSelection(e)}))},this.onShippingContactSelected=function(e){t.options.shippingContactSelectedCallback&&t.options.shippingContactSelectedCallback(e.shippingContact).then((function(e){e&&t.session.completeShippingContactSelection(e)}))},this.onCancel=function(e){t.options.cancelCallback&&t.options.cancelCallback(e)},this.options=e,this.init(),this.validate()},PayOptions:function(e,t,n,i,o,r,s,a,c,l,d,u,p,h,m,b,y){void 0===d&&(d=null),void 0===u&&(u=null),void 0===p&&(p=["email","name","postalAddress"]),void 0===h&&(h=["email","name","postalAddress"]),void 0===m&&(m=null),void 0===b&&(b=["supports3DS","supportsCredit","supportsDebit"]),void 0===y&&(y=["masterCard","visa","maestro","vPay","cartesBancaires","privateLabel"]),this.storeName=e,this.countryCode=t,this.currencyCode=n,this.cultureCode=i,this.merchantIdentifier=o,this.lineItems=r,this.totalLineItem=s,this.shippingType=a,this.shippingMethods=c,this.processCallback=l,this.shippingMethodSelectedCallback=d,this.shippingContactSelectedCallback=u,this.requiredBillingContactFields=p,this.requiredShippingContactFields=h,this.cancelCallback=m,this.merchantCapabilities=b,this.supportedNetworks=y},checkPaySupport:async function(e){return"ApplePaySession"in window?void 0===ApplePaySession?Promise.resolve(!1):await ApplePaySession.canMakePaymentsWithActiveCard(e):Promise.resolve(!1)},getButtonClass:function(e,t){void 0===e&&(e="black"),void 0===t&&(t="plain");let n=["apple-pay","apple-pay-button"];switch(t){case"plain":n.push("apple-pay-button-type-plain");break;case"book":n.push("apple-pay-button-type-book");break;case"buy":n.push("apple-pay-button-type-buy");break;case"check-out":n.push("apple-pay-button-type-check-out");break;case"donate":n.push("apple-pay-button-type-donate");break;case"set-up":n.push("apple-pay-button-type-set-up");break;case"subscribe":n.push("apple-pay-button-type-subscribe")}switch(e){case"black":n.push("apple-pay-button-black");break;case"white":n.push("apple-pay-button-white");break;case"white-outline":n.push("apple-pay-button-white-with-line")}return n.join(" ")}},h="bk-is-mobile",m="bk-paybybank-selected",b=window.PluginManager;b.register("BuckarooPaymentValidateSubmit",class extends c{init(){try{this._registerCheckoutSubmitButton(),this._toggleApplePay(),this._getActivePayByBankLogo()}catch(e){console.log("init error",e)}}_getActivePayByBankLogo(){let e=document.querySelector(".bk-paybybank .payment-method-image"),t=document.querySelector(".bk-paybybank-active-logo");e&&t&&t.value&&t.value.length>0&&(e.src=t.value)}_toggleApplePay(){const e=document.querySelector(".payment-method.bk-applepay");if(e){const t=async function(e){return"ApplePaySession"in window?void 0===ApplePaySession?Promise.resolve(!1):await ApplePaySession.canMakePaymentsWithActiveCard(e):Promise.resolve(!1)};(async function(){const n=document.getElementById("bk-apple-merchant-id");if(n&&n.value.length>0){const i=await t(n);e.style.display=i?"block":"none"}})().catch()}}_registerCheckoutSubmitButton(){const e=document.getElementById("confirmOrderForm");e&&e.querySelector('[type="submit"]').addEventListener("click",this._handleCheckoutSubmit.bind(this))}_handleCheckoutSubmit(e){e.preventDefault(),document.$emitter.unsubscribe("buckaroo_payment_validate"),this._listenToValidation(),document.$emitter.publish("buckaroo_payment_submit")}_listenToValidation(){let e={general:this._deferred(),credicard:this._deferred()};document.$emitter.subscribe("buckaroo_payment_validate",(function(t){t.detail.type&&e[t.detail.type]&&e[t.detail.type].resolve(t.detail.valid)})),Promise.all([e.general,e.credicard]).then((function([e,t]){void 0!==document.forms.confirmOrderForm&&document.forms.confirmOrderForm.reportValidity()&&(e&&t?(void 0!==window.buckaroo_back_link&&window.history.pushState(null,null,buckaroo_back_link),window.isApplePay||document.forms.confirmOrderForm.submit()):document.getElementById("changePaymentForm").scrollIntoView())}))}_deferred(){let e,t;const n=new Promise(((n,i)=>{[e,t]=[n,i]}));return n.resolve=e,n.reject=t,n}}),b.register("BuckarooPaymentCreditcards",class extends c{init(){this._listenToSubmit(),this._createScript((()=>{const e=["creditcards_issuer","creditcards_cardholdername","creditcards_cardnumber","creditcards_expirationmonth","creditcards_expirationyear","creditcards_cvc"];for(const t of e){const e=document.getElementById(t);e&&e.addEventListener("change",this._handleInputChanged.bind(this))}const t=document.getElementById("creditcards_issuer");t&&document.getElementById("card_kind_img").setAttribute("src",t.options[t.selectedIndex].getAttribute("data-logo")),this._getEncryptedData()}))}_createScript(e){const t=document.createElement("script");t.type="text/javascript",t.src="https://static.buckaroo.nl/script/ClientSideEncryption001.js",t.addEventListener("load",e.bind(this),!1),document.head.appendChild(t)}_getEncryptedData(){const e=document.getElementById("creditcards_cardnumber"),t=document.getElementById("creditcards_expirationyear"),n=document.getElementById("creditcards_expirationmonth"),i=document.getElementById("creditcards_cvc"),o=document.getElementById("creditcards_cardholdername");var r,s,a,c,l;e&&t&&n&&i&&o&&(r=e.value,s=t.value,a=n.value,c=i.value,l=o.value,window.BuckarooClientSideEncryption.V001.encryptCardData(r,s,a,c,l,(function(e){const t=document.getElementById("encryptedCardData");t&&(t.value=e)})))}_handleInputChanged(e){const t=e.target.id,n=document.getElementById(t);"creditcards_issuer"===t?document.getElementById("card_kind_img").setAttribute("src",n.options[n.selectedIndex].getAttribute("data-logo")):this._CheckValidate(),this._getEncryptedData()}_handleCheckField(e){switch(document.getElementById(e.id+"Error").style.display="none",e.id){case"creditcards_cardnumber":if(!window.BuckarooClientSideEncryption.V001.validateCardNumber(e.value.replace(/\s+/g,"")))return document.getElementById(e.id+"Error").style.display="block",!1;break;case"creditcards_cardholdername":if(!window.BuckarooClientSideEncryption.V001.validateCardholderName(e.value))return document.getElementById(e.id+"Error").style.display="block",!1;break;case"creditcards_cvc":if(!window.BuckarooClientSideEncryption.V001.validateCvc(e.value))return document.getElementById(e.id+"Error").style.display="block",!1;break;case"creditcards_expirationmonth":if(!window.BuckarooClientSideEncryption.V001.validateMonth(e.value))return document.getElementById(e.id+"Error").style.display="block",!1;break;case"creditcards_expirationyear":if(!window.BuckarooClientSideEncryption.V001.validateYear(e.value))return document.getElementById(e.id+"Error").style.display="block",!1}return!0}_CheckValidate(){let e=!1;const t=["creditcards_cardholdername","creditcards_cardnumber","creditcards_expirationmonth","creditcards_expirationyear","creditcards_cvc"];for(const n of t){const t=document.getElementById(n);t&&(this._handleCheckField(t)||(e=!0))}return this._disableConfirmFormSubmit(e)}_disableConfirmFormSubmit(e){return document.getElementById("confirmFormSubmit")&&(document.getElementById("confirmFormSubmit").disabled=e),e}_registerCheckoutSubmitButton(){const e=document.getElementById("confirmFormSubmit");e&&e.addEventListener("click",this._handleCheckoutSubmit.bind(this))}_validateOnSubmit(e){e.preventDefault();let t=!this._CheckValidate();document.$emitter.publish("buckaroo_payment_validate",{valid:t,type:"credicard"})}_listenToSubmit(){document.$emitter.subscribe("buckaroo_payment_submit",this._validateOnSubmit.bind(this))}}),b.register("BuckarooPaymentHelper",class extends c{get buckarooInputs(){return["buckaroo_capayablein3_OrderAs"]}get buckarooMobileInputs(){return["buckarooAfterpayPhone","buckarooIn3Phone","buckarooBillinkPhone"]}get buckarooDoBInputs(){return["buckaroo_afterpay_DoB","buckaroo_capayablein3_DoB","buckaroo_billink_DoB"]}init(){try{this._registerEvents()}catch(e){console.log("init error",e)}}_registerEvents(){this._checkCompany(),this._listenToSubmit();for(const e of this.buckarooInputs){const t=document.getElementById(e);t&&t.addEventListener("change",this._handleInputChanged.bind(this))}for(const e of this.buckarooMobileInputs){const t=document.getElementById(e);t&&t.addEventListener("change",this._handleMobileInputChanged.bind(this))}for(const e of this.buckarooDoBInputs){const t=document.getElementById(e);t&&t.addEventListener("change",this._handleDoBInputChanged.bind(this))}const e=document.getElementById("P24Currency");e&&"PLN"!=e.value&&(document.getElementById("confirmFormSubmit").disabled=!0,document.getElementById("P24CurrencyError").style.display="block")}_checkCompany(){const e=document.getElementById("buckaroo_capayablein3_OrderAs");let t="none",n=!1;e&&e.selectedIndex>0&&(n=!0,t="block");const i=document.getElementById("buckaroo_capayablein3_COCNumberDiv");return i&&(i.style.display=t,document.getElementById("buckaroo_capayablein3_CompanyNameDiv").style.display=t,document.getElementById("buckaroo_capayablein3_COCNumber").required=n,document.getElementById("buckaroo_capayablein3_CompanyName").required=n),n}_handleInputChanged(e){"buckaroo_capayablein3_OrderAs"===e.target.id&&this._checkCompany()}_handleMobileInputChanged(){this._CheckValidate()}_handleDoBInputChanged(){this._CheckValidate()}_CheckValidate(){let e=!1;for(const t of this.buckarooMobileInputs){const n=document.getElementById(t);n&&(this._handleCheckMobile(n)||(e=!0))}for(const t of this.buckarooDoBInputs){const n=document.getElementById(t);n&&(this._handleCheckDoB(n)||(e=!0))}return this._disableConfirmFormSubmit(e)}_handleCheckMobile(e){return document.getElementById("buckarooMobilePhoneError").style.display="none",!!e.value.match(/^\d{10}$/)||(document.getElementById("buckarooMobilePhoneError").style.display="block",!1)}_handleCheckDoB(e){document.getElementById("buckarooDoBError").style.display="none";const t=new Date(Date.parse(e.value));return"Invalid Date"==t?(document.getElementById("buckarooDoBError").style.display="block",!1):!((new Date).getFullYear()-t.getFullYear()<18||t.getFullYear()<1900)||(document.getElementById("buckarooDoBError").style.display="block",!1)}_disableConfirmFormSubmit(e){return document.getElementById("confirmFormSubmit")&&(document.getElementById("confirmFormSubmit").disabled=e),e}_handleCompanyName(){let e=document.getElementById("buckaroo_capayablein3_CompanyNameError");return e.style.display="none",!!document.getElementById("buckaroo_capayablein3_CompanyName").value.length||(e.style.display="block",!1)}_isRadioOrCeckbox(e){return"radio"==e.type||"checkbox"==e.type}radioGroupHasRequired(e){let t=e.querySelectorAll('input[type="radio"]');return!!t&&[...t].filter((function(e){return e.checked})).length>0}isRadioGroup(e){return e.classList.contains("radio-group-required")}_handleRequired(){let e=document.getElementById("changePaymentForm").querySelectorAll("[required]");e&&e.length&&e.forEach((e=>{let t=e.parentElement;if("radio"===e.type&&(t=t.parentElement),t){let n=t.querySelector('[class="buckaroo-required"]');this.isRadioGroup(e)&&this.radioGroupHasRequired(e)||this._isRadioOrCeckbox(e)&&e.checked||!this._isRadioOrCeckbox(e)&&!this.isRadioGroup(e)&&e.value.length>0?n&&n.remove():null===n&&(n=this._createMessageElement(e),null===t.querySelector('[id$="Error"]')&&t.append(n))}}))}_createMessageElement(e){let t=buckaroo_required_message,n=e.getAttribute("required-message");null!=n&&n.length&&(t=n);let i=document.createElement("label");return i.setAttribute("for",e.id),i.classList.add("buckaroo-required"),i.style.color="red",i.style.width="100%",i.innerHTML=t,i}_validateOnSubmit(){let e=!0;this._handleRequired();let t=document.querySelectorAll(".radio-group-required");for(const n of t)e=e&&this.radioGroupHasRequired(n);for(const t of this.buckarooMobileInputs)document.getElementById(t)&&(e=e&&!this._CheckValidate());for(const t of this.buckarooDoBInputs)document.getElementById(t)&&(e=e&&!this._CheckValidate());document.$emitter.publish("buckaroo_payment_validate",{valid:e,type:"general"})}_listenToSubmit(){document.$emitter.subscribe("buckaroo_payment_submit",this._validateOnSubmit.bind(this))}}),b.register("PaypalExpressPlugin",class extends c{static options={page:"unknown",merchantId:null};httpClient=new l;url="/buckaroo";sdk;result=null;cartToken;sdkOptions={containerSelector:".buckaroo-paypal-express",buckarooWebsiteKey:this.options.websiteKey,paypalMerchantId:this.options.merchantId,currency:"EUR",amount:.1,createPaymentHandler:this.createPaymentHandler.bind(this),onShippingChangeHandler:this.onShippingChangeHandler.bind(this),onSuccessCallback:this.onSuccessCallback.bind(this),onErrorCallback:this.onErrorCallback.bind(this),onCancelCallback:this.onCancelCallback.bind(this),onClickCallback:this.onClickCallback.bind(this)};form;init(){null===this.merchantId&&alert("Merchant id is required"),document.$emitter.subscribe("buckaroo_scripts_loaded",(()=>{this.sdk=BuckarooSdk.PayPal,this.sdk.initiate(this.sdkOptions)}))}onShippingChangeHandler(e,t){return this.setShipping(e).then((e=>{if(!1===e.error)return this.cartToken=e.token,this.sdkOptions.amount=e.cart.value,t.order.patch([{op:"replace",path:"/purchase_units/@reference_id=='default'/amount",value:e.cart}]);this.displayErrorMessage(e.message),t.reject(e.message)}))}createPaymentHandler(e){return this.createTransaction(e.orderID)}onSuccessCallback(){!0===this.result.error?this.displayErrorMessage(message):this.result.redirect?window.location=this.result.redirect:this.displayErrorMessage(this.options.i18n.cannot_create_payment)}onErrorCallback(e){this.displayErrorMessage(e)}onCancelCallback(){this.displayErrorMessage(this.options.i18n.cancel_error_message)}onClickCallback(){this.result=null}createTransaction(e){let t={orderId:e};return this.cartToken&&(t.cartToken=this.cartToken),new Promise((e=>{this.httpClient.post(`${this.url}/paypal/pay`,JSON.stringify(t),(t=>{this.result=JSON.parse(t),e(JSON.parse(t))}))}))}setShipping(e){let t=null;return"product"===this.options.page&&(t=u.serializeJson(this.el.closest("form"))),new Promise((n=>{this.httpClient.post(`${this.url}/paypal/create`,JSON.stringify({form:t,customer:e,page:this.options.page}),(e=>{n(JSON.parse(e))}))}))}displayErrorMessage(e){$(".buckaroo-paypal-express-error").remove(),"object"==typeof e&&(e=this.options.i18n.cannot_create_payment);const t=`\n \n `;$(".flashbags").first().prepend(t),setTimeout((function(){$(".buckaroo-paypal-express-error").fadeOut(1e3)}),1e4)}},"[data-paypal-express]"),b.register("BuckarooIdealQrPlugin",class extends c{static options={orderId:null,pullUrl:null,interval:5e3};httpClient=new l;init(){this.pullStatus()}pullStatus(){setInterval(this.singlePullStatus.bind(this),this.options.interval)}singlePullStatus(){this.options,this.httpClient.post(this.options.pullUrl,JSON.stringify({orderId:this.options.orderId}),(e=>{const t=JSON.parse(e);void 0!==t.redirectUrl&&(window.location.href=t.redirectUrl)}))}},"[data-ideal-qr]"),b.register("BuckarooApplePayPlugin",class extends c{static options={page:"unknown",merchantId:null,cultureCode:"nl-NL"};httpClient=new l;url="/buckaroo";sdk;result=null;cartToken;init(){null===this.merchantId&&alert("Apple Pay Merchant id is required"),document.$emitter.subscribe("buckaroo_scripts_jquery_loaded",(()=>{$("#confirmFormSubmit").prop("disabled",!0),this.checkIsAvailable().then((e=>{$("#confirmFormSubmit").prop("disabled",!e),e&&this.renderButton()}))}))}renderButton(){"checkout"!==this.options.page?$(".bk-apple-pay-button").addClass(p.getButtonClass()).attr("lang",this.options.cultureCode).on("click",this.initPayment.bind(this)):(window.isApplePay=!0,$("#confirmFormSubmit").on("click",this.initPayment.bind(this)))}initPayment(e){e.preventDefault(),this.retrieveCartData().then((e=>{this.initApplePayment(e)}))}retrieveCartData(){let e=null;return"product"===this.options.page&&(e=u.serializeJson(this.el.closest("form"))),new Promise(((t,n)=>{this.httpClient.post(`${this.url}/apple/cart/get`,JSON.stringify({form:e,page:this.options.page}),(e=>{let i=JSON.parse(e);i.error?(this.displayErrorMessage(i.message),n(i.message)):(this.cartToken=i.cartToken,t(i))}))}))}initApplePayment(e){const t=this,n=new p.PayOptions(e.storeName,e.country,e.currency,t.options.cultureCode,t.options.merchantId,e.lineItems,e.totals,"shipping",t.isCheckout(e.shippingMethods,[]),t.captureFunds,t.isCheckout(t.updateCart,null),t.isCheckout(t.updateCart,null));p.PayPayment(n),p.beginPayment()}isCheckout(e,t){return"checkout"===this.options.page?t:e}captureFunds(e){return new Promise((t=>{this.httpClient.post(`${this.url}/apple/order/create`,JSON.stringify({payment:JSON.stringify(e),cartToken:this.cartToken,page:this.options.page}),(e=>{const n=JSON.parse(e);if(n.redirect)t({status:ApplePaySession.STATUS_SUCCESS,errors:[]}),window.location=n.redirect;else{let e=this.options.i18n.cannot_create_payment;n.message&&(e=n.message),this.displayErrorMessage(e),t({status:ApplePaySession.STATUS_FAILURE,errors:[e]})}}))}))}updateCart(e){let t={cartToken:this.cartToken};return void 0!==e.identifier&&(t={...t,shippingMethod:e.identifier}),void 0!==e.countryCode&&(t={...t,shippingContact:e}),new Promise((e=>{this.httpClient.post(`${this.url}/apple/cart/update`,JSON.stringify(t),(t=>{const n=JSON.parse(t);let i=ApplePaySession.STATUS_SUCCESS;n.error&&(i=ApplePaySession.STATUS_FAILURE,this.displayErrorMessage(n.message),console.warn(n.message)),e({status:i,...n})}))}))}checkIsAvailable(){return p.checkPaySupport(this.options.merchantId)}displayErrorMessage(e){$(".buckaroo-apple-error").remove(),"object"==typeof e&&(e=this.options.i18n.cannot_create_payment);const t=`\n \n\n `;$(".flashbags").first().prepend(t),setTimeout((function(){$(".buckaroo-apple-error").fadeOut(1e3)}),1e4)}},"[data-bk-applepay]"),b.register("BuckarooLoadScripts",class extends c{loadSdk(){return new Promise((e=>{var t=document.createElement("script");t.src="https://checkout.buckaroo.nl/api/buckaroosdk/script/en-US",t.async=!0,document.head.appendChild(t),t.onload=()=>{e()}}))}loadJquery(){return"undefined"==typeof jQuery||void 0===jQuery.ajax?new Promise((e=>{var t=document.createElement("script");t.src="https://code.jquery.com/jquery-3.2.1.min.js",t.async=!0,document.head.appendChild(t),t.onload=()=>{e()}})):Promise.resolve()}init(){this.loadJquery().then((()=>{document.$emitter.publish("buckaroo_scripts_jquery_loaded",{loaded:!0}),this.loadSdk().then((()=>{document.$emitter.publish("buckaroo_scripts_loaded",{loaded:!0})}))}))}}),b.register("BuckarooBanContact",class extends c{init(){this._listenToSubmit(),this._createScript((()=>{const e=["bancontactmrcash_cardholdername","bancontactmrcash_cardnumber","bancontactmrcash_expirationmonth","bancontactmrcash_expirationyear"];for(const t of e){const e=document.getElementById(t);e&&e.addEventListener("change",this._handleInputChanged.bind(this))}this._getEncryptedData()}))}_createScript(e){const t=document.createElement("script");t.type="text/javascript",t.src="https://static.buckaroo.nl/script/ClientSideEncryption001.js",t.addEventListener("load",e.bind(this),!1),document.head.appendChild(t)}_getEncryptedData(){const e=document.getElementById("bancontactmrcash_cardnumber"),t=document.getElementById("bancontactmrcash_expirationyear"),n=document.getElementById("bancontactmrcash_expirationmonth"),i=document.getElementById("bancontactmrcash_cardholdername");var o,r,s,a;e&&t&&n&&i&&(o=e.value,r=t.value,s=n.value,a=i.value,window.BuckarooClientSideEncryption.V001.encryptCardData(o,r,s,"",a,(function(e){const t=document.getElementById("encryptedCardData");t&&(t.value=e)})))}_handleInputChanged(e){this._CheckValidate(),this._getEncryptedData()}_handleCheckField(e){switch(document.getElementById(e.id+"Error").style.display="none",e.id){case"bancontactmrcash_cardnumber":if(!window.BuckarooClientSideEncryption.V001.validateCardNumber(e.value.replace(/\s+/g,"")))return document.getElementById(e.id+"Error").style.display="block",!1;break;case"bancontactmrcash_cardholdername":if(!window.BuckarooClientSideEncryption.V001.validateCardholderName(e.value))return document.getElementById(e.id+"Error").style.display="block",!1;break;case"bancontactmrcash_expirationmonth":if(!window.BuckarooClientSideEncryption.V001.validateMonth(e.value))return document.getElementById(e.id+"Error").style.display="block",!1;break;case"bancontactmrcash_expirationyear":if(!window.BuckarooClientSideEncryption.V001.validateYear(e.value))return document.getElementById(e.id+"Error").style.display="block",!1}return!0}_CheckValidate(){let e=!1;const t=["bancontactmrcash_cardholdername","bancontactmrcash_cardnumber","bancontactmrcash_expirationmonth","bancontactmrcash_expirationyear"];for(const n of t){const t=document.getElementById(n);t&&(this._handleCheckField(t)||(e=!0))}return this._disableConfirmFormSubmit(e)}_disableConfirmFormSubmit(e){return document.getElementById("confirmFormSubmit")&&(document.getElementById("confirmFormSubmit").disabled=e),e}_validateOnSubmit(e){e.preventDefault();let t=!this._CheckValidate();document.$emitter.publish("buckaroo_payment_validate",{valid:t,type:"bancontactmrcash"})}_listenToSubmit(){document.$emitter.subscribe("buckaroo_payment_submit",this._validateOnSubmit.bind(this))}}),b.register("BuckarooPayByBankSelect",class extends c{static options={issuerSelected:""};httpClient=new l;init(){this.listenToIsMobile(),this.onPageLoad(),this.listenToResize(),this.listenToIssuerChange(),this.togglePayByBankList(),this.emitSavedIssuer()}emitSavedIssuer(){"string"==typeof this.options.issuerSelected&&this.options.issuerSelected.length>0&&document.$emitter.publish(m,{code:this.options.issuerSelected,source:"other"})}onPageLoad(){document.$emitter.publish(h,{isMobile:(window.innerWidth||document.documentElement.clientWidth||document.body.clientWidth)<768})}listenToResize(){window.addEventListener("resize",function(){let e=!1;(window.innerWidth||document.documentElement.clientWidth||document.body.clientWidth)<768&&(e=!0),this.isMobile!==e&&document.$emitter.publish(h,{isMobile:e})}.bind(this))}listenToIsMobile(){document.$emitter.subscribe(h,function(e){this.isMobile=e.detail.isMobile,this.toggleInputType()}.bind(this))}toggleInputType(){const e=document.querySelector(".bk-paybybank-mobile"),t=document.querySelector(".bk-paybybank-not-mobile");this.isMobile&&e&&t?(e.style.display="block",t.style.display="none"):(e.style.display="none",t.style.display="block")}togglePayByBankList(){this._elementsToShow=document.querySelectorAll(".bk-paybybank-selector .custom-radio:nth-child(n+6)"),setTimeout((()=>{const e=localStorage.getItem("confirmOrderForm.payBybankMethod");null!==e&&document.$emitter.publish(m,{code:e,source:"other"})}),300),this.toggleElements(!1),this.el.addEventListener("click",function(e){const t=document.querySelector(".bk-toggle-wrap");if(null===t)return;const n=t.querySelector(".bk-toggle-text");if(e.target===n){const e=t.querySelector(".bk-toggle"),i=e.classList.contains("bk-toggle-down");e.classList.toggle("bk-toggle-down"),e.classList.toggle("bk-toggle-up");const o=n.getAttribute("text-less"),r=n.getAttribute("text-more");n.textContent=i?o:r,this.toggleElements(i)}}.bind(this))}listenToIssuerChange(){document.$emitter.subscribe(m,function(e){this.syncInputs(e.detail)}.bind(this)),document.querySelector("#payBybankMethod").addEventListener("change",(function(e){document.$emitter.publish(m,{code:e.target.value,source:"select"}),function(){const e=document.querySelector(".bk-toggle-wrap");if(null!==e){const t=e.querySelector(".bk-toggle-text"),n=e.querySelector(".bk-toggle"),i=n.classList.contains("bk-toggle-down"),o=t.getAttribute("text-more");i||(n.classList.toggle("bk-toggle-down"),n.classList.toggle("bk-toggle-up"),t.textContent=o)}}()})),document.querySelectorAll(".bk-paybybank-radio input").forEach((function(e){e.addEventListener("change",(function(e){document.$emitter.publish(m,{code:e.target.value,source:"radio"})}))}))}syncInputs(e){this._elementsToShow=document.querySelectorAll(`.bk-paybybank-selector .custom-radio:not(.bankMethod${e.code})`),"other"===e.source&&this.toggleElements(!1),-1!==["radio","other"].indexOf(e.source)&&(document.querySelector("#payBybankMethod").value=e.code),-1!==["select","other"].indexOf(e.source)&&(document.querySelectorAll(".bk-paybybank-radio").forEach((function(t){const n=t.querySelector("input");t.style.display="none",null!==n&&(n.checked=!1,n.value===e.code&&(n.checked=!0,t.style.display="block"))})),e.code&&0!==e.code.length||this.showDefaultsIfEmptyIssuer())}showDefaultsIfEmptyIssuer(){document.querySelectorAll(".bk-paybybank-selector .custom-radio:nth-child(-n+5)").forEach((function(e){e.style.display="block"}))}toggleElements(e,t="inline"){this._elementsToShow.forEach((function(n){n.style.display=e?t:"none"}))}},"[data-bk-select]"),b.register("BuckarooPayByBankLogo",class extends c{static options={issuerSelected:"",issuerLogos:[]};init(){this.initialLogo(),this.listenToIssuerChange()}listenToIssuerChange(){document.$emitter.subscribe("bk-paybybank-selected",function(e){this.updateLogo(e.detail.code)}.bind(this))}initialLogo(){this.updateLogo(this.options.issuerSelected)}updateLogo(e){if(this.options.issuerLogos[e]){let t=document.querySelector(".bk-paybybank .payment-method-image");t&&(t.src=this.options.issuerLogos[e])}}},"[data-bk-paybybank-logo]")})(); \ No newline at end of file +(()=>{"use strict";var e={735:e=>{var t=function(e){return function(e){return!!e&&"object"==typeof e}(e)&&!function(e){var t=Object.prototype.toString.call(e);return"[object RegExp]"===t||"[object Date]"===t||function(e){return e.$$typeof===n}(e)}(e)},n="function"==typeof Symbol&&Symbol.for?Symbol.for("react.element"):60103;function i(e,t){return!1!==t.clone&&t.isMergeableObject(e)?a((n=e,Array.isArray(n)?[]:{}),e,t):e;var n}function o(e,t,n){return e.concat(t).map((function(e){return i(e,n)}))}function r(e){return Object.keys(e).concat(function(e){return Object.getOwnPropertySymbols?Object.getOwnPropertySymbols(e).filter((function(t){return Object.propertyIsEnumerable.call(e,t)})):[]}(e))}function s(e,t){try{return t in e}catch(e){return!1}}function a(e,n,c){(c=c||{}).arrayMerge=c.arrayMerge||o,c.isMergeableObject=c.isMergeableObject||t,c.cloneUnlessOtherwiseSpecified=i;var l=Array.isArray(n);return l===Array.isArray(e)?l?c.arrayMerge(e,n,c):function(e,t,n){var o={};return n.isMergeableObject(e)&&r(e).forEach((function(t){o[t]=i(e[t],n)})),r(t).forEach((function(r){(function(e,t){return s(e,t)&&!(Object.hasOwnProperty.call(e,t)&&Object.propertyIsEnumerable.call(e,t))})(e,r)||(s(e,r)&&n.isMergeableObject(t[r])?o[r]=function(e,t){if(!t.customMerge)return a;var n=t.customMerge(e);return"function"==typeof n?n:a}(r,n)(e[r],t[r],n):o[r]=i(t[r],n))})),o}(e,n,c):i(n,c)}a.all=function(e,t){if(!Array.isArray(e))throw new Error("first argument should be an array");return e.reduce((function(e,n){return a(e,n,t)}),{})};var c=a;e.exports=c}},t={};function n(i){var o=t[i];if(void 0!==o)return o.exports;var r=t[i]={exports:{}};return e[i](r,r.exports,n),r.exports}n.n=e=>{var t=e&&e.__esModule?()=>e.default:()=>e;return n.d(t,{a:t}),t},n.d=(e,t)=>{for(var i in t)n.o(t,i)&&!n.o(e,i)&&Object.defineProperty(e,i,{enumerable:!0,get:t[i]})},n.o=(e,t)=>Object.prototype.hasOwnProperty.call(e,t);var i=n(735),o=n.n(i);class r{static ucFirst(e){return e.charAt(0).toUpperCase()+e.slice(1)}static lcFirst(e){return e.charAt(0).toLowerCase()+e.slice(1)}static toDashCase(e){return e.replace(/([A-Z])/g,"-$1").replace(/^-/,"").toLowerCase()}static toLowerCamelCase(e,t){const n=r.toUpperCamelCase(e,t);return r.lcFirst(n)}static toUpperCamelCase(e,t){return t?e.split(t).map((e=>r.ucFirst(e.toLowerCase()))).join(""):r.ucFirst(e.toLowerCase())}static parsePrimitive(e){try{return/^\d+(.|,)\d+$/.test(e)&&(e=e.replace(",",".")),JSON.parse(e)}catch(t){return e.toString()}}}class s{static isNode(e){return"object"==typeof e&&null!==e&&(e===document||e===window||e instanceof Node)}static hasAttribute(e,t){if(!s.isNode(e))throw new Error("The element must be a valid HTML Node!");return"function"==typeof e.hasAttribute&&e.hasAttribute(t)}static getAttribute(e,t,n=!0){if(n&&!1===s.hasAttribute(e,t))throw new Error(`The required property "${t}" does not exist!`);if("function"==typeof e.getAttribute)return e.getAttribute(t);if(n)throw new Error("This node doesn't support the getAttribute function!")}static getDataAttribute(e,t,n=!0){const i=t.replace(/^data(|-)/,""),o=r.toLowerCamelCase(i,"-");if(!s.isNode(e)){if(n)throw new Error("The passed node is not a valid HTML Node!");return}if(void 0===e.dataset){if(n)throw new Error("This node doesn't support the dataset attribute!");return}const a=e.dataset[o];if(void 0===a){if(n)throw new Error(`The required data attribute "${t}" does not exist on ${e}!`);return a}return r.parsePrimitive(a)}static querySelector(e,t,n=!0){if(n&&!s.isNode(e))throw new Error("The parent node is not a valid HTML Node!");const i=e.querySelector(t)||!1;if(n&&!1===i)throw new Error(`The required element "${t}" does not exist in parent node!`);return i}static querySelectorAll(e,t,n=!0){if(n&&!s.isNode(e))throw new Error("The parent node is not a valid HTML Node!");let i=e.querySelectorAll(t);if(0===i.length&&(i=!1),n&&!1===i)throw new Error(`At least one item of "${t}" must exist in parent node!`);return i}static getFocusableElements(e=document.body){return e.querySelectorAll('\n input:not([tabindex^="-"]):not([disabled]):not([type="hidden"]),\n select:not([tabindex^="-"]):not([disabled]),\n textarea:not([tabindex^="-"]):not([disabled]),\n button:not([tabindex^="-"]):not([disabled]),\n a[href]:not([tabindex^="-"]):not([disabled]),\n [tabindex]:not([tabindex^="-"]):not([disabled])\n ')}static getFirstFocusableElement(e=document.body){return this.getFocusableElements(e)[0]}static getLastFocusableElement(e=document){const t=this.getFocusableElements(e);return t[t.length-1]}}class a{constructor(e=document){this._el=e,e.$emitter=this,this._listeners=[]}publish(e,t={},n=!1){const i=new CustomEvent(e,{detail:t,cancelable:n});return this.el.dispatchEvent(i),i}subscribe(e,t,n={}){const i=this,o=e.split(".");let r=n.scope?t.bind(n.scope):t;if(n.once&&!0===n.once){const t=r;r=function(n){i.unsubscribe(e),t(n)}}return this.el.addEventListener(o[0],r),this.listeners.push({splitEventName:o,opts:n,cb:r}),!0}unsubscribe(e){const t=e.split(".");return this.listeners=this.listeners.reduce(((e,n)=>[...n.splitEventName].sort().toString()===t.sort().toString()?(this.el.removeEventListener(n.splitEventName[0],n.cb),e):(e.push(n),e)),[]),!0}reset(){return this.listeners.forEach((e=>{this.el.removeEventListener(e.splitEventName[0],e.cb)})),this.listeners=[],!0}get el(){return this._el}set el(e){this._el=e}get listeners(){return this._listeners}set listeners(e){this._listeners=e}}class c{constructor(e,t={},n=!1){if(!s.isNode(e))throw new Error("There is no valid element given.");this.el=e,this.$emitter=new a(this.el),this._pluginName=this._getPluginName(n),this.options=this._mergeOptions(t),this._initialized=!1,this._registerInstance(),this._init()}init(){throw new Error(`The "init" method for the plugin "${this._pluginName}" is not defined.`)}update(){}_init(){this._initialized||(this.init(),this._initialized=!0)}_update(){this._initialized&&this.update()}_mergeOptions(e){const t=r.toDashCase(this._pluginName),n=s.getDataAttribute(this.el,`data-${t}-config`,!1),i=s.getAttribute(this.el,`data-${t}-options`,!1),a=[this.constructor.options,this.options,e];n&&a.push(window.PluginConfigManager.get(this._pluginName,n));try{i&&a.push(JSON.parse(i))}catch(e){throw console.error(this.el),new Error(`The data attribute "data-${t}-options" could not be parsed to json: ${e.message}`)}return o().all(a.filter((e=>e instanceof Object&&!(e instanceof Array))).map((e=>e||{})))}_registerInstance(){window.PluginManager.getPluginInstancesFromElement(this.el).set(this._pluginName,this),window.PluginManager.getPlugin(this._pluginName,!1).get("instances").push(this)}_getPluginName(e){return e||(e=this.constructor.name),e}}class l{constructor(){this._request=null,this._errorHandlingInternal=!1}get(e,t,n="application/json"){const i=this._createPreparedRequest("GET",e,n);return this._sendRequest(i,null,t)}post(e,t,n,i="application/json"){i=this._getContentType(t,i);const o=this._createPreparedRequest("POST",e,i);return this._sendRequest(o,t,n)}delete(e,t,n,i="application/json"){i=this._getContentType(t,i);const o=this._createPreparedRequest("DELETE",e,i);return this._sendRequest(o,t,n)}patch(e,t,n,i="application/json"){i=this._getContentType(t,i);const o=this._createPreparedRequest("PATCH",e,i);return this._sendRequest(o,t,n)}abort(){if(this._request)return this._request.abort()}setErrorHandlingInternal(e){this._errorHandlingInternal=e}_registerOnLoaded(e,t){t&&(!0===this._errorHandlingInternal?(e.addEventListener("load",(()=>{t(e.responseText,e)})),e.addEventListener("abort",(()=>{console.warn(`the request to ${e.responseURL} was aborted`)})),e.addEventListener("error",(()=>{console.warn(`the request to ${e.responseURL} failed with status ${e.status}`)})),e.addEventListener("timeout",(()=>{console.warn(`the request to ${e.responseURL} timed out`)}))):e.addEventListener("loadend",(()=>{t(e.responseText,e)})))}_sendRequest(e,t,n){return this._registerOnLoaded(e,n),e.send(t),e}_getContentType(e,t){return e instanceof FormData&&(t=!1),t}_createPreparedRequest(e,t,n){return this._request=new XMLHttpRequest,this._request.open(e,t),this._request.setRequestHeader("X-Requested-With","XMLHttpRequest"),n&&this._request.setRequestHeader("Content-type",n),this._request}}class d{static iterate(e,t){if(e instanceof Map)return e.forEach(t);if(Array.isArray(e))return e.forEach(t);if(!(e instanceof FormData)){if(e instanceof NodeList)return e.forEach(t);if(e instanceof HTMLCollection)return Array.from(e).forEach(t);if(e instanceof Object)return Object.keys(e).forEach((n=>{t(e[n],n)}));throw new Error(`The element type ${typeof e} is not iterable!`)}for(var n of e.entries())t(n[1],n[0])}}class u{static serialize(e,t=!0){if("FORM"!==e.nodeName){if(t)throw new Error("The passed element is not a form!");return{}}return new FormData(e)}static serializeJson(e,t=!0){const n=u.serialize(e,t);if(0===Object.keys(n).length)return{};const i={};return d.iterate(n,((e,t)=>i[t]=e)),i}}const p={PayPayment:function(e){var t=this;this.applePayVersion=4,this.validationUrl="https://applepay.buckaroo.io/v1/request-session",this.abortSession=function(){t.session&&t.session.abort()},this.init=function(){null===document.getElementById("buckaroo-sdk-css")&&document.head.insertAdjacentHTML("beforeend",'')},this.validate=function(){if(!t.options.processCallback)throw"ApplePay: processCallback must be set";if(!t.options.storeName)throw"ApplePay: storeName is not set";if(!t.options.countryCode)throw"ApplePay: countryCode is not set";if(!t.options.currencyCode)throw"ApplePay: currencyCode is not set";if(!t.options.merchantIdentifier)throw"ApplePay: merchantIdentifier is not set"},this.beginPayment=function(){var e={countryCode:t.options.countryCode,currencyCode:t.options.currencyCode,merchantCapabilities:t.options.merchantCapabilities,supportedNetworks:t.options.supportedNetworks,lineItems:t.options.lineItems,total:t.options.totalLineItem,requiredBillingContactFields:t.options.requiredBillingContactFields,requiredShippingContactFields:t.options.requiredShippingContactFields,shippingType:t.options.shippingType,shippingMethods:t.options.shippingMethods};t.session=new ApplePaySession(t.applePayVersion,e),t.session.onvalidatemerchant=t.onValidateMerchant,t.options.shippingMethodSelectedCallback&&(t.session.onshippingmethodselected=t.onShippingMethodSelected),t.options.shippingContactSelectedCallback&&(t.session.onshippingcontactselected=t.onShippingContactSelected),t.options.cancelCallback&&(t.session.oncancel=t.onCancel),t.session.onpaymentauthorized=t.onPaymentAuthorized,t.session.begin()},this.onValidateMerchant=function(e){var n={validationUrl:e.validationURL,displayName:t.options.storeName,domainName:window.location.hostname,merchantIdentifier:t.options.merchantIdentifier};fetch(t.validationUrl,{method:"POST",body:JSON.stringify(n)}).then((e=>e.json())).then((function(e){t.session.completeMerchantValidation(e)}))},this.onPaymentAuthorized=function(e){var n=e.payment;t.options.processCallback(n).then((function(e){t.session.completePayment(e)}))},this.onShippingMethodSelected=function(e){t.options.shippingMethodSelectedCallback&&t.options.shippingMethodSelectedCallback(e.shippingMethod).then((function(e){e&&t.session.completeShippingMethodSelection(e)}))},this.onShippingContactSelected=function(e){t.options.shippingContactSelectedCallback&&t.options.shippingContactSelectedCallback(e.shippingContact).then((function(e){e&&t.session.completeShippingContactSelection(e)}))},this.onCancel=function(e){t.options.cancelCallback&&t.options.cancelCallback(e)},this.options=e,this.init(),this.validate()},PayOptions:function(e,t,n,i,o,r,s,a,c,l,d,u,p,h,m,b,y){void 0===d&&(d=null),void 0===u&&(u=null),void 0===p&&(p=["email","name","postalAddress"]),void 0===h&&(h=["email","name","postalAddress"]),void 0===m&&(m=null),void 0===b&&(b=["supports3DS","supportsCredit","supportsDebit"]),void 0===y&&(y=["masterCard","visa","maestro","vPay","cartesBancaires","privateLabel"]),this.storeName=e,this.countryCode=t,this.currencyCode=n,this.cultureCode=i,this.merchantIdentifier=o,this.lineItems=r,this.totalLineItem=s,this.shippingType=a,this.shippingMethods=c,this.processCallback=l,this.shippingMethodSelectedCallback=d,this.shippingContactSelectedCallback=u,this.requiredBillingContactFields=p,this.requiredShippingContactFields=h,this.cancelCallback=m,this.merchantCapabilities=b,this.supportedNetworks=y},checkPaySupport:async function(e){return"ApplePaySession"in window?void 0===ApplePaySession?Promise.resolve(!1):await ApplePaySession.canMakePaymentsWithActiveCard(e):Promise.resolve(!1)},getButtonClass:function(e,t){void 0===e&&(e="black"),void 0===t&&(t="plain");let n=["apple-pay","apple-pay-button"];switch(t){case"plain":n.push("apple-pay-button-type-plain");break;case"book":n.push("apple-pay-button-type-book");break;case"buy":n.push("apple-pay-button-type-buy");break;case"check-out":n.push("apple-pay-button-type-check-out");break;case"donate":n.push("apple-pay-button-type-donate");break;case"set-up":n.push("apple-pay-button-type-set-up");break;case"subscribe":n.push("apple-pay-button-type-subscribe")}switch(e){case"black":n.push("apple-pay-button-black");break;case"white":n.push("apple-pay-button-white");break;case"white-outline":n.push("apple-pay-button-white-with-line")}return n.join(" ")}},h="bk-is-mobile",m="bk-paybybank-selected",b=window.PluginManager;b.register("BuckarooPaymentValidateSubmit",class extends c{init(){try{this._registerCheckoutSubmitButton(),this._toggleApplePay(),this._getActivePayByBankLogo()}catch(e){console.log("init error",e)}}_getActivePayByBankLogo(){let e=document.querySelector(".bk-paybybank .payment-method-image"),t=document.querySelector(".bk-paybybank-active-logo");e&&t&&t.value&&t.value.length>0&&(e.src=t.value)}_toggleApplePay(){const e=document.querySelector(".payment-method.bk-applepay");if(e){const t=async function(e){return"ApplePaySession"in window?void 0===ApplePaySession?Promise.resolve(!1):await ApplePaySession.canMakePaymentsWithActiveCard(e):Promise.resolve(!1)};(async function(){const n=document.getElementById("bk-apple-merchant-id");if(n&&n.value.length>0){const i=await t(n);e.style.display=i?"block":"none"}})().catch()}}_registerCheckoutSubmitButton(){const e=document.getElementById("confirmOrderForm");e&&e.querySelector('[type="submit"]').addEventListener("click",this._handleCheckoutSubmit.bind(this))}_handleCheckoutSubmit(e){e.preventDefault(),document.$emitter.unsubscribe("buckaroo_payment_validate"),this._listenToValidation(),document.$emitter.publish("buckaroo_payment_submit")}_listenToValidation(){let e={general:this._deferred(),credicard:this._deferred()};document.$emitter.subscribe("buckaroo_payment_validate",(function(t){t.detail.type&&e[t.detail.type]&&e[t.detail.type].resolve(t.detail.valid)})),Promise.all([e.general,e.credicard]).then((function([e,t]){void 0!==document.forms.confirmOrderForm&&document.forms.confirmOrderForm.reportValidity()&&(e&&t?(void 0!==window.buckaroo_back_link&&window.history.pushState(null,null,buckaroo_back_link),window.isApplePay||document.forms.confirmOrderForm.submit()):document.getElementById("changePaymentForm").scrollIntoView())}))}_deferred(){let e,t;const n=new Promise(((n,i)=>{[e,t]=[n,i]}));return n.resolve=e,n.reject=t,n}}),b.register("BuckarooPaymentCreditcards",class extends c{init(){this._listenToSubmit(),this._createScript((()=>{const e=["creditcards_issuer","creditcards_cardholdername","creditcards_cardnumber","creditcards_expirationmonth","creditcards_expirationyear","creditcards_cvc"];for(const t of e){const e=document.getElementById(t);e&&e.addEventListener("change",this._handleInputChanged.bind(this))}const t=document.getElementById("creditcards_issuer");t&&document.getElementById("card_kind_img").setAttribute("src",t.options[t.selectedIndex].getAttribute("data-logo")),this._getEncryptedData()}))}_createScript(e){const t=document.createElement("script");t.type="text/javascript",t.src="https://static.buckaroo.nl/script/ClientSideEncryption001.js",t.addEventListener("load",e.bind(this),!1),document.head.appendChild(t)}_getEncryptedData(){const e=document.getElementById("creditcards_cardnumber"),t=document.getElementById("creditcards_expirationyear"),n=document.getElementById("creditcards_expirationmonth"),i=document.getElementById("creditcards_cvc"),o=document.getElementById("creditcards_cardholdername");var r,s,a,c,l;e&&t&&n&&i&&o&&(r=e.value,s=t.value,a=n.value,c=i.value,l=o.value,window.BuckarooClientSideEncryption.V001.encryptCardData(r,s,a,c,l,(function(e){const t=document.getElementById("encryptedCardData");t&&(t.value=e)})))}_handleInputChanged(e){const t=e.target.id,n=document.getElementById(t);"creditcards_issuer"===t?document.getElementById("card_kind_img").setAttribute("src",n.options[n.selectedIndex].getAttribute("data-logo")):this._CheckValidate(),this._getEncryptedData()}_handleCheckField(e){switch(document.getElementById(e.id+"Error").style.display="none",e.id){case"creditcards_cardnumber":if(!window.BuckarooClientSideEncryption.V001.validateCardNumber(e.value.replace(/\s+/g,"")))return document.getElementById(e.id+"Error").style.display="block",!1;break;case"creditcards_cardholdername":if(!window.BuckarooClientSideEncryption.V001.validateCardholderName(e.value))return document.getElementById(e.id+"Error").style.display="block",!1;break;case"creditcards_cvc":if(!window.BuckarooClientSideEncryption.V001.validateCvc(e.value))return document.getElementById(e.id+"Error").style.display="block",!1;break;case"creditcards_expirationmonth":if(!window.BuckarooClientSideEncryption.V001.validateMonth(e.value))return document.getElementById(e.id+"Error").style.display="block",!1;break;case"creditcards_expirationyear":if(!window.BuckarooClientSideEncryption.V001.validateYear(e.value))return document.getElementById(e.id+"Error").style.display="block",!1}return!0}_CheckValidate(){let e=!1;const t=["creditcards_cardholdername","creditcards_cardnumber","creditcards_expirationmonth","creditcards_expirationyear","creditcards_cvc"];for(const n of t){const t=document.getElementById(n);t&&(this._handleCheckField(t)||(e=!0))}return this._disableConfirmFormSubmit(e)}_disableConfirmFormSubmit(e){return document.getElementById("confirmFormSubmit")&&(document.getElementById("confirmFormSubmit").disabled=e),e}_registerCheckoutSubmitButton(){const e=document.getElementById("confirmFormSubmit");e&&e.addEventListener("click",this._handleCheckoutSubmit.bind(this))}_validateOnSubmit(e){e.preventDefault();let t=!this._CheckValidate();document.$emitter.publish("buckaroo_payment_validate",{valid:t,type:"credicard"})}_listenToSubmit(){document.$emitter.subscribe("buckaroo_payment_submit",this._validateOnSubmit.bind(this))}}),b.register("BuckarooPaymentHelper",class extends c{get buckarooInputs(){return["buckaroo_capayablein3_OrderAs"]}get buckarooMobileInputs(){return["buckarooAfterpayPhone","buckarooIn3Phone","buckarooBillinkPhone"]}get buckarooDoBInputs(){return["buckaroo_afterpay_DoB","buckaroo_capayablein3_DoB","buckaroo_billink_DoB"]}init(){try{this._registerEvents()}catch(e){console.log("init error",e)}}_registerEvents(){this._checkCompany(),this._listenToSubmit();for(const e of this.buckarooInputs){const t=document.getElementById(e);t&&t.addEventListener("change",this._handleInputChanged.bind(this))}for(const e of this.buckarooMobileInputs){const t=document.getElementById(e);t&&t.addEventListener("change",this._handleMobileInputChanged.bind(this))}for(const e of this.buckarooDoBInputs){const t=document.getElementById(e);t&&t.addEventListener("change",this._handleDoBInputChanged.bind(this))}const e=document.getElementById("P24Currency");e&&"PLN"!=e.value&&(document.getElementById("confirmFormSubmit").disabled=!0,document.getElementById("P24CurrencyError").style.display="block")}_checkCompany(){const e=document.getElementById("buckaroo_capayablein3_OrderAs");let t="none",n=!1;e&&e.selectedIndex>0&&(n=!0,t="block");const i=document.getElementById("buckaroo_capayablein3_COCNumberDiv");return i&&(i.style.display=t,document.getElementById("buckaroo_capayablein3_CompanyNameDiv").style.display=t,document.getElementById("buckaroo_capayablein3_COCNumber").required=n,document.getElementById("buckaroo_capayablein3_CompanyName").required=n),n}_handleInputChanged(e){"buckaroo_capayablein3_OrderAs"===e.target.id&&this._checkCompany()}_handleMobileInputChanged(){this._CheckValidate()}_handleDoBInputChanged(){this._CheckValidate()}_CheckValidate(){let e=!1;for(const t of this.buckarooMobileInputs){const n=document.getElementById(t);n&&(this._handleCheckMobile(n)||(e=!0))}for(const t of this.buckarooDoBInputs){const n=document.getElementById(t);n&&(this._handleCheckDoB(n)||(e=!0))}return this._disableConfirmFormSubmit(e)}_handleCheckMobile(e){return document.getElementById("buckarooMobilePhoneError").style.display="none",!!e.value.match(/^\d{10}$/)||(document.getElementById("buckarooMobilePhoneError").style.display="block",!1)}_handleCheckDoB(e){document.getElementById("buckarooDoBError").style.display="none";const t=new Date(Date.parse(e.value));return"Invalid Date"==t?(document.getElementById("buckarooDoBError").style.display="block",!1):!((new Date).getFullYear()-t.getFullYear()<18||t.getFullYear()<1900)||(document.getElementById("buckarooDoBError").style.display="block",!1)}_disableConfirmFormSubmit(e){return document.getElementById("confirmFormSubmit")&&(document.getElementById("confirmFormSubmit").disabled=e),e}_handleCompanyName(){let e=document.getElementById("buckaroo_capayablein3_CompanyNameError");return e.style.display="none",!!document.getElementById("buckaroo_capayablein3_CompanyName").value.length||(e.style.display="block",!1)}_isRadioOrCeckbox(e){return"radio"==e.type||"checkbox"==e.type}radioGroupHasRequired(e){let t=e.querySelectorAll('input[type="radio"]');return!!t&&[...t].filter((function(e){return e.checked})).length>0}isRadioGroup(e){return e.classList.contains("radio-group-required")}_handleRequired(){let e=document.getElementById("changePaymentForm").querySelectorAll("[required]");e&&e.length&&e.forEach((e=>{let t=e.parentElement;if("radio"===e.type&&(t=t.parentElement),t){let n=t.querySelector('[class="buckaroo-required"]');this.isRadioGroup(e)&&this.radioGroupHasRequired(e)||this._isRadioOrCeckbox(e)&&e.checked||!this._isRadioOrCeckbox(e)&&!this.isRadioGroup(e)&&e.value.length>0?n&&n.remove():null===n&&(n=this._createMessageElement(e),null===t.querySelector('[id$="Error"]')&&t.append(n))}}))}_createMessageElement(e){let t=buckaroo_required_message,n=e.getAttribute("required-message");null!=n&&n.length&&(t=n);let i=document.createElement("label");return i.setAttribute("for",e.id),i.classList.add("buckaroo-required"),i.style.color="red",i.style.width="100%",i.innerHTML=t,i}_validateOnSubmit(){let e=!0;this._handleRequired();let t=document.querySelectorAll(".radio-group-required");for(const n of t)e=e&&this.radioGroupHasRequired(n);for(const t of this.buckarooMobileInputs)document.getElementById(t)&&(e=e&&!this._CheckValidate());for(const t of this.buckarooDoBInputs)document.getElementById(t)&&(e=e&&!this._CheckValidate());document.$emitter.publish("buckaroo_payment_validate",{valid:e,type:"general"})}_listenToSubmit(){document.$emitter.subscribe("buckaroo_payment_submit",this._validateOnSubmit.bind(this))}}),b.register("PaypalExpressPlugin",class extends c{static options={page:"unknown",merchantId:null,isTestMode:!1};httpClient=new l;url="/buckaroo";sdk;result=null;cartToken;sdkOptions={containerSelector:".buckaroo-paypal-express",buckarooWebsiteKey:this.options.websiteKey,paypalMerchantId:this.options.merchantId,isTestMode:!0===this.options.isTestMode,currency:"EUR",amount:.1,createPaymentHandler:this.createPaymentHandler.bind(this),onShippingChangeHandler:this.onShippingChangeHandler.bind(this),onSuccessCallback:this.onSuccessCallback.bind(this),onErrorCallback:this.onErrorCallback.bind(this),onCancelCallback:this.onCancelCallback.bind(this),onClickCallback:this.onClickCallback.bind(this)};form;setSdkTestMode(){void 0!==BuckarooSdk.Base&&"function"==typeof BuckarooSdk.Base.setTestMode&&BuckarooSdk.Base.setTestMode(!0===this.options.isTestMode)}init(){null===this.merchantId&&alert("Merchant id is required"),document.$emitter.subscribe("buckaroo_scripts_loaded",(()=>{this.sdk=BuckarooSdk.PayPal,this.setSdkTestMode(),this.sdk.initiate(this.sdkOptions)}))}onShippingChangeHandler(e,t){return this.setShipping(e).then((e=>{if(!1===e.error)return this.cartToken=e.token,this.sdkOptions.amount=e.cart.value,t.order.patch([{op:"replace",path:"/purchase_units/@reference_id=='default'/amount",value:e.cart}]);this.displayErrorMessage(e.message),t.reject(e.message)}))}createPaymentHandler(e){return this.createTransaction(e.orderID)}onSuccessCallback(){!0===this.result.error?this.displayErrorMessage(message):this.result.redirect?window.location=this.result.redirect:this.displayErrorMessage(this.options.i18n.cannot_create_payment)}onErrorCallback(e){this.displayErrorMessage(e)}onCancelCallback(){this.displayErrorMessage(this.options.i18n.cancel_error_message)}onClickCallback(){this.result=null}createTransaction(e){let t={orderId:e};return this.cartToken&&(t.cartToken=this.cartToken),new Promise((e=>{this.httpClient.post(`${this.url}/paypal/pay`,JSON.stringify(t),(t=>{this.result=JSON.parse(t),e(JSON.parse(t))}))}))}setShipping(e){let t=null;return"product"===this.options.page&&(t=u.serializeJson(this.el.closest("form"))),new Promise((n=>{this.httpClient.post(`${this.url}/paypal/create`,JSON.stringify({form:t,customer:e,page:this.options.page}),(e=>{n(JSON.parse(e))}))}))}displayErrorMessage(e){$(".buckaroo-paypal-express-error").remove(),"object"==typeof e&&(e=this.options.i18n.cannot_create_payment);const t=`\n \n `;$(".flashbags").first().prepend(t),setTimeout((function(){$(".buckaroo-paypal-express-error").fadeOut(1e3)}),1e4)}},"[data-paypal-express]"),b.register("BuckarooIdealQrPlugin",class extends c{static options={orderId:null,pullUrl:null,interval:5e3};httpClient=new l;init(){this.pullStatus()}pullStatus(){setInterval(this.singlePullStatus.bind(this),this.options.interval)}singlePullStatus(){this.options,this.httpClient.post(this.options.pullUrl,JSON.stringify({orderId:this.options.orderId}),(e=>{const t=JSON.parse(e);void 0!==t.redirectUrl&&(window.location.href=t.redirectUrl)}))}},"[data-ideal-qr]"),b.register("BuckarooApplePayPlugin",class extends c{static options={page:"unknown",merchantId:null,cultureCode:"nl-NL"};httpClient=new l;url="/buckaroo";sdk;result=null;cartToken;init(){null===this.merchantId&&alert("Apple Pay Merchant id is required"),document.$emitter.subscribe("buckaroo_scripts_jquery_loaded",(()=>{$("#confirmFormSubmit").prop("disabled",!0),this.checkIsAvailable().then((e=>{$("#confirmFormSubmit").prop("disabled",!e),e&&this.renderButton()}))}))}renderButton(){"checkout"!==this.options.page?$(".bk-apple-pay-button").addClass(p.getButtonClass()).attr("lang",this.options.cultureCode).on("click",this.initPayment.bind(this)):(window.isApplePay=!0,$("#confirmFormSubmit").on("click",this.initPayment.bind(this)))}initPayment(e){e.preventDefault(),this.retrieveCartData().then((e=>{this.initApplePayment(e)}))}retrieveCartData(){let e=null;return"product"===this.options.page&&(e=u.serializeJson(this.el.closest("form"))),new Promise(((t,n)=>{this.httpClient.post(`${this.url}/apple/cart/get`,JSON.stringify({form:e,page:this.options.page}),(e=>{let i=JSON.parse(e);i.error?(this.displayErrorMessage(i.message),n(i.message)):(this.cartToken=i.cartToken,t(i))}))}))}initApplePayment(e){const t=this,n=new p.PayOptions(e.storeName,e.country,e.currency,t.options.cultureCode,t.options.merchantId,e.lineItems,e.totals,"shipping",t.isCheckout(e.shippingMethods,[]),t.captureFunds,t.isCheckout(t.updateCart,null),t.isCheckout(t.updateCart,null));p.PayPayment(n),p.beginPayment()}isCheckout(e,t){return"checkout"===this.options.page?t:e}captureFunds(e){return new Promise((t=>{this.httpClient.post(`${this.url}/apple/order/create`,JSON.stringify({payment:JSON.stringify(e),cartToken:this.cartToken,page:this.options.page}),(e=>{const n=JSON.parse(e);if(n.redirect)t({status:ApplePaySession.STATUS_SUCCESS,errors:[]}),window.location=n.redirect;else{let e=this.options.i18n.cannot_create_payment;n.message&&(e=n.message),this.displayErrorMessage(e),t({status:ApplePaySession.STATUS_FAILURE,errors:[e]})}}))}))}updateCart(e){let t={cartToken:this.cartToken};return void 0!==e.identifier&&(t={...t,shippingMethod:e.identifier}),void 0!==e.countryCode&&(t={...t,shippingContact:e}),new Promise((e=>{this.httpClient.post(`${this.url}/apple/cart/update`,JSON.stringify(t),(t=>{const n=JSON.parse(t);let i=ApplePaySession.STATUS_SUCCESS;n.error&&(i=ApplePaySession.STATUS_FAILURE,this.displayErrorMessage(n.message),console.warn(n.message)),e({status:i,...n})}))}))}checkIsAvailable(){return p.checkPaySupport(this.options.merchantId)}displayErrorMessage(e){$(".buckaroo-apple-error").remove(),"object"==typeof e&&(e=this.options.i18n.cannot_create_payment);const t=`\n \n\n `;$(".flashbags").first().prepend(t),setTimeout((function(){$(".buckaroo-apple-error").fadeOut(1e3)}),1e4)}},"[data-bk-applepay]"),b.register("BuckarooLoadScripts",class extends c{loadSdk(){return new Promise((e=>{var t=document.createElement("script");t.src=(function(){var n=document.querySelector("[data-paypal-express-plugin-options]");if(n)try{if(!0===JSON.parse(n.getAttribute("data-paypal-express-plugin-options")).isTestMode)return"https://testcheckout.buckaroo.nl/api/buckaroosdk/script/en-US"}catch(e){}return"https://checkout.buckaroo.nl/api/buckaroosdk/script/en-US"})(),t.async=!0,document.head.appendChild(t),t.onload=()=>{e()}}))}loadJquery(){return"undefined"==typeof jQuery||void 0===jQuery.ajax?new Promise((e=>{var t=document.createElement("script");t.src="https://code.jquery.com/jquery-3.2.1.min.js",t.async=!0,document.head.appendChild(t),t.onload=()=>{e()}})):Promise.resolve()}init(){this.loadJquery().then((()=>{document.$emitter.publish("buckaroo_scripts_jquery_loaded",{loaded:!0}),this.loadSdk().then((()=>{document.$emitter.publish("buckaroo_scripts_loaded",{loaded:!0})}))}))}}),b.register("BuckarooBanContact",class extends c{init(){this._listenToSubmit(),this._createScript((()=>{const e=["bancontactmrcash_cardholdername","bancontactmrcash_cardnumber","bancontactmrcash_expirationmonth","bancontactmrcash_expirationyear"];for(const t of e){const e=document.getElementById(t);e&&e.addEventListener("change",this._handleInputChanged.bind(this))}this._getEncryptedData()}))}_createScript(e){const t=document.createElement("script");t.type="text/javascript",t.src="https://static.buckaroo.nl/script/ClientSideEncryption001.js",t.addEventListener("load",e.bind(this),!1),document.head.appendChild(t)}_getEncryptedData(){const e=document.getElementById("bancontactmrcash_cardnumber"),t=document.getElementById("bancontactmrcash_expirationyear"),n=document.getElementById("bancontactmrcash_expirationmonth"),i=document.getElementById("bancontactmrcash_cardholdername");var o,r,s,a;e&&t&&n&&i&&(o=e.value,r=t.value,s=n.value,a=i.value,window.BuckarooClientSideEncryption.V001.encryptCardData(o,r,s,"",a,(function(e){const t=document.getElementById("encryptedCardData");t&&(t.value=e)})))}_handleInputChanged(e){this._CheckValidate(),this._getEncryptedData()}_handleCheckField(e){switch(document.getElementById(e.id+"Error").style.display="none",e.id){case"bancontactmrcash_cardnumber":if(!window.BuckarooClientSideEncryption.V001.validateCardNumber(e.value.replace(/\s+/g,"")))return document.getElementById(e.id+"Error").style.display="block",!1;break;case"bancontactmrcash_cardholdername":if(!window.BuckarooClientSideEncryption.V001.validateCardholderName(e.value))return document.getElementById(e.id+"Error").style.display="block",!1;break;case"bancontactmrcash_expirationmonth":if(!window.BuckarooClientSideEncryption.V001.validateMonth(e.value))return document.getElementById(e.id+"Error").style.display="block",!1;break;case"bancontactmrcash_expirationyear":if(!window.BuckarooClientSideEncryption.V001.validateYear(e.value))return document.getElementById(e.id+"Error").style.display="block",!1}return!0}_CheckValidate(){let e=!1;const t=["bancontactmrcash_cardholdername","bancontactmrcash_cardnumber","bancontactmrcash_expirationmonth","bancontactmrcash_expirationyear"];for(const n of t){const t=document.getElementById(n);t&&(this._handleCheckField(t)||(e=!0))}return this._disableConfirmFormSubmit(e)}_disableConfirmFormSubmit(e){return document.getElementById("confirmFormSubmit")&&(document.getElementById("confirmFormSubmit").disabled=e),e}_validateOnSubmit(e){e.preventDefault();let t=!this._CheckValidate();document.$emitter.publish("buckaroo_payment_validate",{valid:t,type:"bancontactmrcash"})}_listenToSubmit(){document.$emitter.subscribe("buckaroo_payment_submit",this._validateOnSubmit.bind(this))}}),b.register("BuckarooPayByBankSelect",class extends c{static options={issuerSelected:""};httpClient=new l;init(){this.listenToIsMobile(),this.onPageLoad(),this.listenToResize(),this.listenToIssuerChange(),this.togglePayByBankList(),this.emitSavedIssuer()}emitSavedIssuer(){"string"==typeof this.options.issuerSelected&&this.options.issuerSelected.length>0&&document.$emitter.publish(m,{code:this.options.issuerSelected,source:"other"})}onPageLoad(){document.$emitter.publish(h,{isMobile:(window.innerWidth||document.documentElement.clientWidth||document.body.clientWidth)<768})}listenToResize(){window.addEventListener("resize",function(){let e=!1;(window.innerWidth||document.documentElement.clientWidth||document.body.clientWidth)<768&&(e=!0),this.isMobile!==e&&document.$emitter.publish(h,{isMobile:e})}.bind(this))}listenToIsMobile(){document.$emitter.subscribe(h,function(e){this.isMobile=e.detail.isMobile,this.toggleInputType()}.bind(this))}toggleInputType(){const e=document.querySelector(".bk-paybybank-mobile"),t=document.querySelector(".bk-paybybank-not-mobile");this.isMobile&&e&&t?(e.style.display="block",t.style.display="none"):(e.style.display="none",t.style.display="block")}togglePayByBankList(){this._elementsToShow=document.querySelectorAll(".bk-paybybank-selector .custom-radio:nth-child(n+6)"),setTimeout((()=>{const e=localStorage.getItem("confirmOrderForm.payBybankMethod");null!==e&&document.$emitter.publish(m,{code:e,source:"other"})}),300),this.toggleElements(!1),this.el.addEventListener("click",function(e){const t=document.querySelector(".bk-toggle-wrap");if(null===t)return;const n=t.querySelector(".bk-toggle-text");if(e.target===n){const e=t.querySelector(".bk-toggle"),i=e.classList.contains("bk-toggle-down");e.classList.toggle("bk-toggle-down"),e.classList.toggle("bk-toggle-up");const o=n.getAttribute("text-less"),r=n.getAttribute("text-more");n.textContent=i?o:r,this.toggleElements(i)}}.bind(this))}listenToIssuerChange(){document.$emitter.subscribe(m,function(e){this.syncInputs(e.detail)}.bind(this)),document.querySelector("#payBybankMethod").addEventListener("change",(function(e){document.$emitter.publish(m,{code:e.target.value,source:"select"}),function(){const e=document.querySelector(".bk-toggle-wrap");if(null!==e){const t=e.querySelector(".bk-toggle-text"),n=e.querySelector(".bk-toggle"),i=n.classList.contains("bk-toggle-down"),o=t.getAttribute("text-more");i||(n.classList.toggle("bk-toggle-down"),n.classList.toggle("bk-toggle-up"),t.textContent=o)}}()})),document.querySelectorAll(".bk-paybybank-radio input").forEach((function(e){e.addEventListener("change",(function(e){document.$emitter.publish(m,{code:e.target.value,source:"radio"})}))}))}syncInputs(e){this._elementsToShow=document.querySelectorAll(`.bk-paybybank-selector .custom-radio:not(.bankMethod${e.code})`),"other"===e.source&&this.toggleElements(!1),-1!==["radio","other"].indexOf(e.source)&&(document.querySelector("#payBybankMethod").value=e.code),-1!==["select","other"].indexOf(e.source)&&(document.querySelectorAll(".bk-paybybank-radio").forEach((function(t){const n=t.querySelector("input");t.style.display="none",null!==n&&(n.checked=!1,n.value===e.code&&(n.checked=!0,t.style.display="block"))})),e.code&&0!==e.code.length||this.showDefaultsIfEmptyIssuer())}showDefaultsIfEmptyIssuer(){document.querySelectorAll(".bk-paybybank-selector .custom-radio:nth-child(-n+5)").forEach((function(e){e.style.display="block"}))}toggleElements(e,t="inline"){this._elementsToShow.forEach((function(n){n.style.display=e?t:"none"}))}},"[data-bk-select]"),b.register("BuckarooPayByBankLogo",class extends c{static options={issuerSelected:"",issuerLogos:[]};init(){this.initialLogo(),this.listenToIssuerChange()}listenToIssuerChange(){document.$emitter.subscribe("bk-paybybank-selected",function(e){this.updateLogo(e.detail.code)}.bind(this))}initialLogo(){this.updateLogo(this.options.issuerSelected)}updateLogo(e){if(this.options.issuerLogos[e]){let t=document.querySelector(".bk-paybybank .payment-method-image");t&&(t.src=this.options.issuerLogos[e])}}},"[data-bk-paybybank-logo]")})(); diff --git a/src/Resources/public/images/knaken.svg b/src/Resources/public/images/knaken.svg deleted file mode 100644 index 4eb3585e..00000000 --- a/src/Resources/public/images/knaken.svg +++ /dev/null @@ -1,22 +0,0 @@ - - - - - - - - - diff --git a/src/Resources/public/images/trustly.svg b/src/Resources/public/images/trustly.svg index d3fab7b0..cb2b0e5b 100644 --- a/src/Resources/public/images/trustly.svg +++ b/src/Resources/public/images/trustly.svg @@ -1,153 +1,19 @@ - - - - - - + + + + + + + + + + + + + + + + + + diff --git a/src/Resources/public/storefront/buckaroo/creditcards/clicktopay.svg b/src/Resources/public/storefront/buckaroo/creditcards/clicktopay.svg index e21e9eef..6b9b6880 100644 --- a/src/Resources/public/storefront/buckaroo/creditcards/clicktopay.svg +++ b/src/Resources/public/storefront/buckaroo/creditcards/clicktopay.svg @@ -1,12 +1,5 @@ - - - - - - - - - - + + + diff --git a/src/Resources/public/storefront/buckaroo/ideal/ideal-snel-bestellen-inverted.svg b/src/Resources/public/storefront/buckaroo/ideal/ideal-snel-bestellen-inverted.svg new file mode 100644 index 00000000..7dceea99 --- /dev/null +++ b/src/Resources/public/storefront/buckaroo/ideal/ideal-snel-bestellen-inverted.svg @@ -0,0 +1,2 @@ + + diff --git a/src/Resources/public/storefront/buckaroo/ideal/ideal-snel-bestellen.svg b/src/Resources/public/storefront/buckaroo/ideal/ideal-snel-bestellen.svg new file mode 100644 index 00000000..b535d908 --- /dev/null +++ b/src/Resources/public/storefront/buckaroo/ideal/ideal-snel-bestellen.svg @@ -0,0 +1,2 @@ + + diff --git a/src/Resources/public/storefront/buckaroo/idealFastCheckoutLogoDark.png b/src/Resources/public/storefront/buckaroo/idealFastCheckoutLogoDark.png deleted file mode 100644 index f94b2c0b..00000000 Binary files a/src/Resources/public/storefront/buckaroo/idealFastCheckoutLogoDark.png and /dev/null differ diff --git a/src/Resources/public/storefront/buckaroo/idealFastCheckoutLogoLight.png b/src/Resources/public/storefront/buckaroo/idealFastCheckoutLogoLight.png deleted file mode 100644 index f94b2c0b..00000000 Binary files a/src/Resources/public/storefront/buckaroo/idealFastCheckoutLogoLight.png and /dev/null differ diff --git a/src/Resources/snippet/de_DE/messages.de-DE.json b/src/Resources/snippet/de_DE/messages.de-DE.json index ca44c950..d9deabfa 100644 --- a/src/Resources/snippet/de_DE/messages.de-DE.json +++ b/src/Resources/snippet/de_DE/messages.de-DE.json @@ -31,6 +31,7 @@ "skipInformational": "Informationeller Push" }, "checkout": { + "idealFastCheckoutButtonLabel": "iDEAL Schnellkauf - Snel bestellen", "financialWarning": "Je dient minimaal 18+ te zijn om deze dienst te gebruiken. Als je op tijd betaalt, voorkom je extra kosten en zorg je dat je in de toekomst nogmaals gebruik kunt maken van de diensten van %method%. Door verder te gaan, accepteer je de Algemene Voorwaarden en bevestig je dat je de Privacyverklaring en Cookieverklaring hebt gelezen.", "CustomerEmail": "E-Mail", "CustomerFirstName": "Vorname für Rechnungsstellung", diff --git a/src/Resources/snippet/en_GB/messages.en-GB.json b/src/Resources/snippet/en_GB/messages.en-GB.json index 0c3fdd8d..95ec5ef3 100644 --- a/src/Resources/snippet/en_GB/messages.en-GB.json +++ b/src/Resources/snippet/en_GB/messages.en-GB.json @@ -34,6 +34,7 @@ "missing_data_request_key": "Klarna Data Request key is missing. Cannot execute fulfillment action." }, "checkout": { + "idealFastCheckoutButtonLabel": "iDEAL fast checkout - Snel bestellen", "financialWarning": "Je dient minimaal 18+ te zijn om deze dienst te gebruiken. Als je op tijd betaalt, voorkom je extra kosten en zorg je dat je in de toekomst nogmaals gebruik kunt maken van de diensten van %method%. Door verder te gaan, accepteer je de Algemene Voorwaarden en bevestig je dat je de Privacyverklaring en Cookieverklaring hebt gelezen.", "CustomerEmail": "Email", "CustomerFirstName": "Billing First Name", diff --git a/src/Resources/snippet/fr_FR/messages.fr-FR.json b/src/Resources/snippet/fr_FR/messages.fr-FR.json index 40004cbd..ad98cd3a 100644 --- a/src/Resources/snippet/fr_FR/messages.fr-FR.json +++ b/src/Resources/snippet/fr_FR/messages.fr-FR.json @@ -31,6 +31,7 @@ "skipInformational": "Transmission d'informations ignorée" }, "checkout": { + "idealFastCheckoutButtonLabel": "Paiement express iDEAL - Snel bestellen", "financialWarning": "Je dient minimaal 18+ te zijn om deze dienst te gebruiken. Als je op tijd betaalt, voorkom je extra kosten en zorg je dat je in de toekomst nogmaals gebruik kunt maken van de diensten van %method%. Door verder te gaan, accepteer je de Algemene Voorwaarden en bevestig je dat je de Privacyverklaring en Cookieverklaring hebt gelezen.", "CustomerEmail": "E-mail", "CustomerFirstName": "Prénom de facturation", diff --git a/src/Resources/snippet/nl_NL/messages.nl-NL.json b/src/Resources/snippet/nl_NL/messages.nl-NL.json index 17277b98..292a20d6 100644 --- a/src/Resources/snippet/nl_NL/messages.nl-NL.json +++ b/src/Resources/snippet/nl_NL/messages.nl-NL.json @@ -34,6 +34,7 @@ "missing_data_request_key": "Klarna Data Request sleutel ontbreekt. Kan de afhandelingsactie niet uitvoeren." }, "checkout": { + "idealFastCheckoutButtonLabel": "iDEAL Snel bestellen", "financialWarning": "Je dient minimaal 18+ te zijn om deze dienst te gebruiken. Als je op tijd betaalt, voorkom je extra kosten en zorg je dat je in de toekomst nogmaals gebruik kunt maken van de diensten van %method%. Door verder te gaan, accepteer je de Algemene Voorwaarden en bevestig je dat je de Privacyverklaring en Cookieverklaring hebt gelezen.", "CustomerEmail": "E-mail", "CustomerFirstName": "Voornaam", diff --git a/src/Resources/views/storefront/buckaroo/express-checkout-buttons.html.twig b/src/Resources/views/storefront/buckaroo/express-checkout-buttons.html.twig new file mode 100644 index 00000000..d6676a7d --- /dev/null +++ b/src/Resources/views/storefront/buckaroo/express-checkout-buttons.html.twig @@ -0,0 +1,65 @@ +{# + Shared markup for the Buckaroo express checkout buttons + (PayPal Express, Apple Pay, Google Pay, iDEAL/Wero fast checkout). + + Every storefront location (product detail buy widget, shopping cart, + checkout confirm page) includes this template, so the buttons share one + structure and one styling hook: .bk-express-checkout + (see app/storefront/src/scss/_express-checkout.scss). + + Parameters — a provider is skipped when its options are not passed: + - paypalOptions: plugin options for [data-paypal-express] + - applePayOptions: plugin options for [data-bk-applepay] + - googlePayOptions: plugin options for [data-bk-googlepay] + - idealOptions: plugin options for [data-bk-ideal-fast-checkout] + - idealLogo: button style for the iDEAL fast checkout button, + "light" (default) or "dark" +#} + +{% if paypalOptions ?? false %} +
+
+
+{% endif %} + +{% if applePayOptions ?? false %} +
+
+
+
+{% endif %} + +{% if googlePayOptions ?? false %} +
+
+
+{% endif %} + +{# + Only iDEAL's lockup — the express mark, the iDEAL logo and the "Snel + bestellen" wordmark — is fixed artwork. The frame around it is a plain + fill, border and radius, so it is drawn in CSS instead of being baked + into the image. That lets the button span the full column and take the + same height as the other express buttons while the lockup keeps its own + proportions. The artwork goes to the stylesheet as a custom property so + asset() keeps resolving the bundle path (and any CDN prefix) for us. +#} +{% if idealOptions ?? false %} + {% set idealVariant = (idealLogo ?? '') == 'dark' ? 'dark' : 'light' %} + {% set idealLockup = idealVariant == 'dark' ? 'ideal-snel-bestellen-inverted' : 'ideal-snel-bestellen' %} +
+ +
+{% endif %} diff --git a/src/Resources/views/storefront/buckaroo/ideal-qr.html.twig b/src/Resources/views/storefront/buckaroo/ideal-qr.html.twig index fa746b65..4778efbb 100644 --- a/src/Resources/views/storefront/buckaroo/ideal-qr.html.twig +++ b/src/Resources/views/storefront/buckaroo/ideal-qr.html.twig @@ -1,9 +1,17 @@ {% sw_extends '@Storefront/storefront/page/checkout/_page.html.twig' %} +{# Shopware renamed these blocks in 6.7 (base_header -> base_esi_header). + Both variants are declared so the minimal header/footer keep working on + 6.5/6.6 and 6.7 alike; a block the parent chain does not define is simply + never rendered, so the unused variant is inert. #} {% block base_header %} {% sw_include '@Storefront/storefront/layout/header/header-minimal.html.twig' %} {% endblock %} +{% block base_esi_header %} + {% sw_include '@Storefront/storefront/layout/header/header-minimal.html.twig' %} +{% endblock %} + {% block page_checkout_container %} {% block buckaroo_qr_display %} {% set conifg = { @@ -24,3 +32,7 @@ {% block base_footer %} {% sw_include '@Storefront/storefront/layout/footer/footer-minimal.html.twig' %} {% endblock %} + +{% block base_esi_footer %} + {% sw_include '@Storefront/storefront/layout/footer/footer-minimal.html.twig' %} +{% endblock %} diff --git a/src/Resources/views/storefront/buckaroo/payment-methods/billink.html.twig b/src/Resources/views/storefront/buckaroo/payment-methods/billink.html.twig index 81ac03ac..09f9ad18 100644 --- a/src/Resources/views/storefront/buckaroo/payment-methods/billink.html.twig +++ b/src/Resources/views/storefront/buckaroo/payment-methods/billink.html.twig @@ -1,39 +1,7 @@ {% block buckaroo_payment_method_billink %} -
-
- {% if page.extensions.buckaroo.BillinkBusiness != 'B2B' %} -
-
- - -
-
- {% endif %} -
- - - -
- {% if page.extensions.buckaroo.BillinkBusiness == 'B2B' %} + {% if page.extensions.buckaroo.BillinkBusiness == 'B2B' %} +
+
- {% endif %} - {% if page.extensions.buckaroo.BillinkBusiness != 'B2B' %} -
- - {{ "buckaroo.checkout.buckarooAfterpayDoBTitleSup"|trans }} -
- - -
-
- {% endif %} -
-
-{% endblock %} \ No newline at end of file +
+
+ {% endif %} +{% endblock %} diff --git a/src/Resources/views/storefront/buckaroo/payment-methods/creditcards.html.twig b/src/Resources/views/storefront/buckaroo/payment-methods/creditcards.html.twig index 8f9064e8..9efaa1f2 100644 --- a/src/Resources/views/storefront/buckaroo/payment-methods/creditcards.html.twig +++ b/src/Resources/views/storefront/buckaroo/payment-methods/creditcards.html.twig @@ -1,11 +1,13 @@ {% block buckaroo_payment_method_creditcards %} {% if page.extensions.buckaroo.creditcards|length > 0 %} -
+ +
-
+ +

Payment

@@ -64,7 +66,7 @@ Cancel
-
+
diff --git a/src/Resources/views/storefront/buckaroo/payment-methods/knaken.html.twig b/src/Resources/views/storefront/buckaroo/payment-methods/knaken.html.twig deleted file mode 100644 index bff1b288..00000000 --- a/src/Resources/views/storefront/buckaroo/payment-methods/knaken.html.twig +++ /dev/null @@ -1,4 +0,0 @@ -{% block buckaroo_payment_method_knaken %} -
-
-{% endblock %} \ No newline at end of file diff --git a/src/Resources/views/storefront/buckaroo/payment_methods.html.twig b/src/Resources/views/storefront/buckaroo/payment_methods.html.twig index 027750ba..ae07abba 100644 --- a/src/Resources/views/storefront/buckaroo/payment_methods.html.twig +++ b/src/Resources/views/storefront/buckaroo/payment_methods.html.twig @@ -83,8 +83,6 @@ {% sw_include '@BuckarooPayments/storefront/buckaroo/payment-methods/wechatpay.html.twig' %} {% elseif buckarooKey == 'multibanco' %} {% sw_include '@BuckarooPayments/storefront/buckaroo/payment-methods/multibanco.html.twig' %} - {% elseif buckarooKey == 'knaken' %} - {% sw_include '@BuckarooPayments/storefront/buckaroo/payment-methods/knaken.html.twig' %} {% endif %} {% endblock %} {% endblock %} diff --git a/src/Resources/views/storefront/buckaroo/payments/knaken.svg b/src/Resources/views/storefront/buckaroo/payments/knaken.svg deleted file mode 100644 index 4eb3585e..00000000 --- a/src/Resources/views/storefront/buckaroo/payments/knaken.svg +++ /dev/null @@ -1,22 +0,0 @@ - - - - - - - - - diff --git a/src/Resources/views/storefront/buckaroo/payments/trustly.svg b/src/Resources/views/storefront/buckaroo/payments/trustly.svg index d3fab7b0..cb2b0e5b 100644 --- a/src/Resources/views/storefront/buckaroo/payments/trustly.svg +++ b/src/Resources/views/storefront/buckaroo/payments/trustly.svg @@ -1,153 +1,19 @@ - - - - - - + + + + + + + + + + + + + + + + + + diff --git a/src/Resources/views/storefront/component/buy-widget/buy-widget-form.html.twig b/src/Resources/views/storefront/component/buy-widget/buy-widget-form.html.twig index 39f451f0..471d5048 100644 --- a/src/Resources/views/storefront/component/buy-widget/buy-widget-form.html.twig +++ b/src/Resources/views/storefront/component/buy-widget/buy-widget-form.html.twig @@ -3,78 +3,44 @@ {% block buy_widget_buy_form_inner %} {{ parent() }} - {% if page.extensions.buckaroo.showPaypalExpress %} -
- {% set paypalExpressOptions = { + {% if page.extensions.buckaroo %} + {% set buckaroo = page.extensions.buckaroo %} + {% set expressI18n = { + cancel_error_message: "buckaroo.checkout.cancelOrderMessage"|trans|sw_sanitize, + cannot_create_payment: "buckaroo.checkout.cannotCreatePayment"|trans|sw_sanitize + } %} + + {% sw_include '@BuckarooPayments/storefront/buckaroo/express-checkout-buttons.html.twig' with { + paypalOptions: buckaroo.showPaypalExpress ? { page: "product", - merchantId: page.extensions.buckaroo.paypalMerchantId, - websiteKey: page.extensions.buckaroo.websiteKey, - i18n: { - cancel_error_message: "buckaroo.checkout.cancelOrderMessage"|trans|sw_sanitize, - cannot_create_payment :"buckaroo.checkout.cannotCreatePayment"|trans|sw_sanitize - } - } %} - -
-
-
-
- {% endif %} - - {% if page.extensions.buckaroo.applepayHostedPaymentPage == false && page.extensions.buckaroo.applepayShowProduct %} -
- {% set applePayConfig = { + merchantId: buckaroo.paypalMerchantId, + isTestMode: buckaroo.paypalIsTestMode, + websiteKey: buckaroo.websiteKey, + i18n: expressI18n + } : null, + applePayOptions: buckaroo.applepayShowProduct ? { page: "product", - merchantId: page.extensions.buckaroo.applePayMerchantId, + productId: page.product.id, + merchantId: buckaroo.applePayMerchantId, cultureCode: page.header.activeLanguage.translationCode.code, - i18n: { - cancel_error_message: "buckaroo.checkout.cancelOrderMessage"|trans|sw_sanitize, - cannot_create_payment :"buckaroo.checkout.cannotCreatePayment"|trans|sw_sanitize - } - } %} -
-
-
- {% endif %} - - {% if page.extensions.buckaroo.googlepayShowProduct %} -
- {% set googlePayConfig = { + i18n: expressI18n + } : null, + googlePayOptions: buckaroo.googlepayShowProduct ? { page: "product", productId: page.product.id, - merchantId: page.extensions.buckaroo.googlepayMerchantId, - gatewayMerchantId: page.extensions.buckaroo.googlepayGatewayMerchantId, - merchantName: page.extensions.buckaroo.websiteKey, - buttonColor: page.extensions.buckaroo.googlepayButtonStyle, - environment: page.extensions.buckaroo.googlepayEnvironment - } %} -
-
-
-
- {% endif %} - - {% if page.extensions.buckaroo.showIdealFastCheckout %} -
- {% set idealFastCheckoutConfig = { + merchantId: buckaroo.googlepayMerchantId, + gatewayMerchantId: buckaroo.googlepayGatewayMerchantId, + merchantName: buckaroo.websiteKey, + buttonColor: buckaroo.googlepayButtonStyle, + environment: buckaroo.googlepayEnvironment + } : null, + idealOptions: buckaroo.showIdealFastCheckout ? { page: "product", - websiteKey: page.extensions.buckaroo.websiteKey, - i18n: { - cancel_error_message: "buckaroo.checkout.cancelOrderMessage"|trans|sw_sanitize, - cannot_create_payment :"buckaroo.checkout.cannotCreatePayment"|trans|sw_sanitize - } - } %} -
- -
-
+ websiteKey: buckaroo.websiteKey, + i18n: expressI18n + } : null, + idealLogo: buckaroo.idealFastCheckoutLogo + } %} {% endif %} - - -{% endblock %} \ No newline at end of file +{% endblock %} diff --git a/src/Resources/views/storefront/component/payment/payment-fields.html.twig b/src/Resources/views/storefront/component/payment/payment-fields.html.twig new file mode 100644 index 00000000..3a0fa2ab --- /dev/null +++ b/src/Resources/views/storefront/component/payment/payment-fields.html.twig @@ -0,0 +1,57 @@ +{% sw_extends '@Storefront/storefront/component/payment/payment-fields.html.twig' %} + + +{% block component_payment_method %} + {% block buckaroo_payment_globals %} + {# Carries the translated "field required" message to the storefront JS. + A data attribute (not an inline + {% endif %} + {% endblock %} + + {% set bkSelectedPayments = page.paymentMethods|filter(payment => payment.id is same as(selectedPaymentMethodId)) %} + {% set bkOtherPayments = page.paymentMethods|filter(payment => not (payment.id is same as(selectedPaymentMethodId))) %} + {% set bkSortedPayments = bkSelectedPayments|merge(bkOtherPayments) %} + + {% for payment in bkSortedPayments[:visiblePaymentMethodsLimit] %} + {% sw_include '@Storefront/storefront/component/payment/payment-method.html.twig' %} + {% endfor %} + + {% block component_payment_method_collapse %} + {% if bkSortedPayments|length > visiblePaymentMethodsLimit and visiblePaymentMethodsLimit is not same as(null) %} +
+ {% for payment in bkSortedPayments[visiblePaymentMethodsLimit:] %} + {% sw_include '@Storefront/storefront/component/payment/payment-method.html.twig' %} + {% endfor %} +
+ + {% block component_payment_method_collapse_trigger %} + + {% endblock %} + {% endif %} + {% endblock %} +{% endblock %} diff --git a/src/Resources/views/storefront/component/payment/payment-form.html.twig b/src/Resources/views/storefront/component/payment/payment-form.html.twig new file mode 100644 index 00000000..07392a0a --- /dev/null +++ b/src/Resources/views/storefront/component/payment/payment-form.html.twig @@ -0,0 +1,47 @@ +{% sw_extends '@Storefront/storefront/component/payment/payment-form.html.twig' %} + +{# Buckaroo payment-step customisations for Shopware 6.7+. + Companion to payment-fields.html.twig, which covers 6.5/6.6 - exactly one of + the two ever renders, so there is no duplicated markup: + + 6.5 core payment-form has no `component_payment_form_list`; it includes + payment-fields.html.twig -> the payment-fields override renders. + 6.6 `component_payment_form_list` exists only behind the + ACCESSIBILITY_TWEAKS feature flag; by default core still includes + payment-fields.html.twig -> the payment-fields override renders + (this override takes over when that flag is enabled). + 6.7 payment-fields.html.twig was removed and + `component_payment_form_list` is unconditional -> this override renders. + + Note core no longer passes `visiblePaymentMethodsLimit` (6.6 supplied it to + the include, 6.7 dropped it), so the old collapse behaviour is intentionally + not reimplemented here - core no longer truncates the list. #} +{% block component_payment_form_list %} + {% block buckaroo_payment_globals %} + {# Carries the translated "field required" message to the storefront JS. + A data attribute (not an inline + {% endif %} + {% endblock %} + + {# Show the currently selected payment method first. #} + {% set bkSelectedId = selectedPaymentMethodId ?? context.paymentMethod.id %} + {% set bkSelectedPayments = page.paymentMethods|filter(payment => payment.id is same as(bkSelectedId)) %} + {% set bkOtherPayments = page.paymentMethods|filter(payment => not (payment.id is same as(bkSelectedId))) %} + +
+ {% for payment in bkSelectedPayments|merge(bkOtherPayments) %} + {% block component_payment_form_method %} + {% sw_include '@Storefront/storefront/component/payment/payment-method.html.twig' %} + {% endblock %} + {% endfor %} +
+{% endblock %} diff --git a/src/Resources/views/storefront/component/payment/payment-method.html.twig b/src/Resources/views/storefront/component/payment/payment-method.html.twig index bd901624..e7822022 100644 --- a/src/Resources/views/storefront/component/payment/payment-method.html.twig +++ b/src/Resources/views/storefront/component/payment/payment-method.html.twig @@ -3,7 +3,7 @@ {% if payment.translated.customFields.is_buckaroo %}
- {% if payment.translated.customFields.buckaroo_key !== 'applepay'|| (payment.translated.customFields.buckaroo_key === 'applepay' && (page.extensions.buckaroo.applepayHostedPaymentPage && page.extensions.buckaroo.isAppleDevice)) %} + {# Apple Pay is always selectable: the official Apple Pay SDK is cross-browser and the storefront JS disables the Place Order button when Apple Pay is unavailable. #}
{% block component_payment_method_control %}
@@ -70,7 +70,6 @@
{% endblock %}
- {% endif %} {% block buckaroo_payment_method_inputs %} {% if payment.translated.customFields.is_buckaroo and payment.id is same as(selectedPaymentMethodId) %} @@ -137,8 +136,6 @@ {% sw_include '@BuckarooPayments/storefront/buckaroo/payment-methods/wechatpay.html.twig' %} {% elseif buckarooKey == 'multibanco' %} {% sw_include '@BuckarooPayments/storefront/buckaroo/payment-methods/multibanco.html.twig' %} - {% elseif buckarooKey == 'knaken' %} - {% sw_include '@BuckarooPayments/storefront/buckaroo/payment-methods/knaken.html.twig' %} {% endif %} {% endblock %}
@@ -150,7 +147,3 @@ {{ parent() }} {% endif %} {% endblock %} - -{% block component_payment_fieldset_template %} - {{ parent() }} -{% endblock %} \ No newline at end of file diff --git a/src/Resources/views/storefront/page/checkout/cart/index.html.twig b/src/Resources/views/storefront/page/checkout/cart/index.html.twig index 800b7500..96cba196 100644 --- a/src/Resources/views/storefront/page/checkout/cart/index.html.twig +++ b/src/Resources/views/storefront/page/checkout/cart/index.html.twig @@ -2,74 +2,40 @@ {% block page_checkout_cart_action_proceed %} {{ parent() }} - {% if page.extensions.buckaroo.showPaypalExpress %} -
- {% set paypalExpressOptions = { - page: "cart", - merchantId: page.extensions.buckaroo.paypalMerchantId, - websiteKey: page.extensions.buckaroo.websiteKey, - i18n: { - cancel_error_message: "buckaroo.checkout.cancelOrderMessage"|trans|sw_sanitize, - cannot_create_payment :"buckaroo.checkout.cannotCreatePayment"|trans|sw_sanitize - } - } %} - -
-
-
-
- {% endif %} + {% if page.extensions.buckaroo %} + {% set buckaroo = page.extensions.buckaroo %} + {% set expressI18n = { + cancel_error_message: "buckaroo.checkout.cancelOrderMessage"|trans|sw_sanitize, + cannot_create_payment: "buckaroo.checkout.cannotCreatePayment"|trans|sw_sanitize + } %} - {% if page.extensions.buckaroo.applepayHostedPaymentPage == false && page.extensions.buckaroo.showApplePay %} -
- {% set applePayConfig = { + {% sw_include '@BuckarooPayments/storefront/buckaroo/express-checkout-buttons.html.twig' with { + paypalOptions: buckaroo.showPaypalExpress ? { page: "cart", - merchantId: page.extensions.buckaroo.applePayMerchantId, + merchantId: buckaroo.paypalMerchantId, + isTestMode: buckaroo.paypalIsTestMode, + websiteKey: buckaroo.websiteKey, + i18n: expressI18n + } : null, + applePayOptions: buckaroo.showApplePay ? { + page: "cart", + merchantId: buckaroo.applePayMerchantId, cultureCode: page.header.activeLanguage.translationCode.code, - i18n: { - cancel_error_message: "buckaroo.checkout.cancelOrderMessage"|trans|sw_sanitize, - cannot_create_payment :"buckaroo.checkout.cannotCreatePayment"|trans|sw_sanitize - } - } %} -
-
-
- {% endif %} - - {% if page.extensions.buckaroo.showGooglePay %} -
- {% set googlePayConfig = { + i18n: expressI18n + } : null, + googlePayOptions: buckaroo.showGooglePay ? { page: "cart", - merchantId: page.extensions.buckaroo.googlepayMerchantId, - gatewayMerchantId: page.extensions.buckaroo.googlepayGatewayMerchantId, - merchantName: page.extensions.buckaroo.websiteKey, - buttonColor: page.extensions.buckaroo.googlepayButtonStyle, - environment: page.extensions.buckaroo.googlepayEnvironment - } %} -
-
-
-
- {% endif %} - - {% if page.extensions.buckaroo.showIdealFastCheckout %} -
- {% set idealFastCheckoutConfig = { + merchantId: buckaroo.googlepayMerchantId, + gatewayMerchantId: buckaroo.googlepayGatewayMerchantId, + merchantName: buckaroo.websiteKey, + buttonColor: buckaroo.googlepayButtonStyle, + environment: buckaroo.googlepayEnvironment + } : null, + idealOptions: buckaroo.showIdealFastCheckout ? { page: "cart", - i18n: { - cancel_error_message: "buckaroo.checkout.cancelOrderMessage"|trans|sw_sanitize, - cannot_create_payment :"buckaroo.checkout.cannotCreatePayment"|trans|sw_sanitize - } - } %} -
-
- iDEAL | Wero Snel bestellen -
-
-
+ i18n: expressI18n + } : null, + idealLogo: buckaroo.idealFastCheckoutLogo + } %} {% endif %} - {% endblock %} diff --git a/src/Resources/views/storefront/page/checkout/confirm/confirm-payment.html.twig b/src/Resources/views/storefront/page/checkout/confirm/confirm-payment.html.twig index a80d602f..d1a15592 100644 --- a/src/Resources/views/storefront/page/checkout/confirm/confirm-payment.html.twig +++ b/src/Resources/views/storefront/page/checkout/confirm/confirm-payment.html.twig @@ -14,8 +14,8 @@ } } %} +
-
{% endif %} {% if context.paymentMethod.formattedHandlerIdentifier == 'handler_buckaroo_googlepaypaymenthandler' %} @@ -33,43 +33,34 @@ {% endif %} - - {% if page.extensions.buckaroo.showPaypalExpress %} - {% set paypalExpressOptions = { - page: "checkout", - merchantId: page.extensions.buckaroo.paypalMerchantId, - websiteKey: page.extensions.buckaroo.websiteKey, - i18n: { - cancel_error_message: "buckaroo.checkout.cancelOrderMessage"|trans|sw_sanitize, - cannot_create_payment :"buckaroo.checkout.cannotCreatePayment"|trans|sw_sanitize - } + {% if page.extensions.buckaroo %} + {% set buckaroo = page.extensions.buckaroo %} + {% set expressI18n = { + cancel_error_message: "buckaroo.checkout.cancelOrderMessage"|trans|sw_sanitize, + cannot_create_payment: "buckaroo.checkout.cannotCreatePayment"|trans|sw_sanitize } %} -
-
-
- - {% endif %} - - {% if page.extensions.buckaroo.showIdealFastCheckout %} -
- {% set idealFastCheckoutConfig = { + {% sw_include '@BuckarooPayments/storefront/buckaroo/express-checkout-buttons.html.twig' with { + paypalOptions: buckaroo.showPaypalExpress ? { page: "checkout", - websiteKey: page.extensions.buckaroo.websiteKey, - i18n: { - cancel_error_message: "buckaroo.checkout.cancelOrderMessage"|trans|sw_sanitize, - cannot_create_payment :"buckaroo.checkout.cannotCreatePayment"|trans|sw_sanitize - } - } %} -
- -
-
+ merchantId: buckaroo.paypalMerchantId, + isTestMode: buckaroo.paypalIsTestMode, + websiteKey: buckaroo.websiteKey, + i18n: expressI18n + } : null, + applePayOptions: buckaroo.showApplePay ? { + page: "cart", + merchantId: buckaroo.applePayMerchantId, + cultureCode: page.header.activeLanguage.translationCode.code, + i18n: expressI18n + } : null, + idealOptions: buckaroo.showIdealFastCheckout ? { + page: "checkout", + websiteKey: buckaroo.websiteKey, + i18n: expressI18n + } : null, + idealLogo: buckaroo.idealFastCheckoutLogo + } %} {% endif %} {% endblock %} diff --git a/src/Resources/views/storefront/page/product-detail/buy-widget-form.html.twig b/src/Resources/views/storefront/page/product-detail/buy-widget-form.html.twig deleted file mode 100644 index ee94895d..00000000 --- a/src/Resources/views/storefront/page/product-detail/buy-widget-form.html.twig +++ /dev/null @@ -1,76 +0,0 @@ -{% sw_extends '@Storefront/storefront/page/product-detail/buy-widget-form.html.twig' %} - -{% block page_product_detail_buy_button_container %} - {{ parent() }} - {% if page.extensions.buckaroo.showPaypalExpress %} -
- {% set paypalExpressOptions = { - page: "product", - merchantId: page.extensions.buckaroo.paypalMerchantId, - websiteKey: page.extensions.buckaroo.websiteKey, - i18n: { - cancel_error_message: "buckaroo.checkout.cancelOrderMessage"|trans|sw_sanitize, - cannot_create_payment :"buckaroo.checkout.cannotCreatePayment"|trans|sw_sanitize - } - } %} - -
-
-
-
- {% endif %} - - {% if page.extensions.buckaroo.applepayShowProduct %} -
- {% set applePayConfig = { - page: "product", - merchantId: page.extensions.buckaroo.applePayMerchantId, - cultureCode: page.header.activeLanguage.translationCode.code, - i18n: { - cancel_error_message: "buckaroo.checkout.cancelOrderMessage"|trans|sw_sanitize, - cannot_create_payment :"buckaroo.checkout.cannotCreatePayment"|trans|sw_sanitize - } - } %} -
-
-
- {% endif %} - - {% if page.extensions.buckaroo.googlepayShowProduct %} -
- {% set googlePayConfig = { - page: "product", - productId: page.product.id, - merchantId: page.extensions.buckaroo.googlepayMerchantId, - gatewayMerchantId: page.extensions.buckaroo.googlepayGatewayMerchantId, - merchantName: page.extensions.buckaroo.websiteKey, - buttonColor: page.extensions.buckaroo.googlepayButtonStyle, - environment: page.extensions.buckaroo.googlepayEnvironment - } %} -
-
-
-
- {% endif %} - {% if page.extensions.buckaroo.showIdealFastCheckout %} -
- {% set idealFastCheckoutConfig = { - page: "product", - websiteKey: page.extensions.buckaroo.websiteKey, - i18n: { - cancel_error_message: "buckaroo.checkout.cancelOrderMessage"|trans|sw_sanitize, - cannot_create_payment :"buckaroo.checkout.cannotCreatePayment"|trans|sw_sanitize - } - } %} -
- -
-
- {% endif %} - -{% endblock %} diff --git a/src/Service/AsyncPaymentService.php b/src/Service/AsyncPaymentService.php index 29d6b4ba..19ece8b0 100644 --- a/src/Service/AsyncPaymentService.php +++ b/src/Service/AsyncPaymentService.php @@ -31,6 +31,8 @@ class AsyncPaymentService { + protected ?BuckarooLanguageResolver $languageResolver = null; + public function __construct( public SettingsService $settingsService, public UrlService $urlService, @@ -48,6 +50,16 @@ public function __construct( ) { } + public function setLanguageResolver(BuckarooLanguageResolver $languageResolver): void + { + $this->languageResolver = $languageResolver; + } + + public function getLanguageResolver(): ?BuckarooLanguageResolver + { + return $this->languageResolver; + } + /** diff --git a/src/Service/Buckaroo/ClientService.php b/src/Service/Buckaroo/ClientService.php index 836b1830..0911acb1 100644 --- a/src/Service/Buckaroo/ClientService.php +++ b/src/Service/Buckaroo/ClientService.php @@ -29,11 +29,13 @@ public function __construct( * * @param string $configMethodCode * @param string $salesChannelId + * @param string|null $culture culture code (ex. "nl-NL") sent to Buckaroo, + * used for the hosted payment page and payment instructions * * @return Client * @throws ClientInitException */ - public function get(string $configMethodCode, ?string $salesChannelId = null): Client + public function get(string $configMethodCode, ?string $salesChannelId = null, ?string $culture = null): Client { $mode = $this->settingsService->getEnvironment($configMethodCode, $salesChannelId); @@ -43,7 +45,8 @@ public function get(string $configMethodCode, ?string $salesChannelId = null): C $this->settingsService->getSettingAsString('secretKey', $salesChannelId), $this->getPaymentCode($configMethodCode, $salesChannelId), $mode == 'live' ? Config::LIVE_MODE : Config::TEST_MODE, - $this->shopwareVersion + $this->shopwareVersion, + $culture ); } catch (\Throwable $th) { throw new ClientInitException("Cannot initiate buckaroo sdk client", 0, $th); diff --git a/src/Service/BuckarooLanguageResolver.php b/src/Service/BuckarooLanguageResolver.php new file mode 100644 index 00000000..59385cdc --- /dev/null +++ b/src/Service/BuckarooLanguageResolver.php @@ -0,0 +1,241 @@ + 'en-US', + 'nl' => 'nl-NL', + 'de' => 'de-DE', + 'fr' => 'fr-FR', + 'es' => 'es-ES', + 'it' => 'it-IT', + ]; + + /** + * Billing country (ISO 3166-1 alpha-2) to language mapping. + */ + private const COUNTRY_LANGUAGE_MAP = [ + 'NL' => 'nl', + 'BE' => 'nl', + 'DE' => 'de', + 'AT' => 'de', + 'CH' => 'de', + 'FR' => 'fr', + 'LU' => 'fr', + 'ES' => 'es', + 'IT' => 'it', + 'GB' => 'en', + 'US' => 'en', + 'IE' => 'en', + ]; + + private SettingsService $settingsService; + + private RequestStack $requestStack; + + private EntityRepository $languageRepository; + + public function __construct( + SettingsService $settingsService, + RequestStack $requestStack, + EntityRepository $languageRepository + ) { + $this->settingsService = $settingsService; + $this->requestStack = $requestStack; + $this->languageRepository = $languageRepository; + } + + /** + * Resolve the Buckaroo culture code (ex. "nl-NL") for the current payment flow. + * + * @param SalesChannelContext $context the active sales channel context + * @param Request|null $request the current request, used for browser language + * detection (defaults to the current request stack request) + * @param OrderEntity|null $order the order, used for billing country detection + */ + public function resolveLanguage( + SalesChannelContext $context, + ?Request $request = null, + ?OrderEntity $order = null + ): string { + $mode = $this->settingsService->getSetting(self::SETTING_KEY, $context->getSalesChannelId()); + + if (!is_string($mode) || $mode === '') { + $mode = self::MODE_BROWSER; + } + + // Fixed language selected in the configuration. + if (isset(self::SUPPORTED_CULTURES[$mode])) { + return self::SUPPORTED_CULTURES[$mode]; + } + + switch ($mode) { + case self::MODE_BILLING_COUNTRY: + return $this->toCulture($this->getLanguageFromBillingCountry($context, $order)); + case self::MODE_SALES_CHANNEL: + return $this->toCulture($this->getLanguageFromSalesChannel($context)); + case self::MODE_BROWSER: + default: + return $this->toCulture( + $this->getLanguageFromBrowser($request ?? $this->requestStack->getCurrentRequest()) + ); + } + } + + /** + * Detect the language from the browser Accept-Language header. + */ + private function getLanguageFromBrowser(?Request $request): ?string + { + if ($request === null) { + return null; + } + + foreach ($request->getLanguages() as $locale) { + $language = $this->getPrimaryLanguage($locale); + if ($language !== null) { + return $language; + } + } + + return null; + } + + /** + * Detect the language from the customer's billing country. + */ + private function getLanguageFromBillingCountry(SalesChannelContext $context, ?OrderEntity $order): ?string + { + $iso = $this->getBillingCountryIso($context, $order); + + if ($iso === null) { + return null; + } + + return self::COUNTRY_LANGUAGE_MAP[strtoupper($iso)] ?? null; + } + + private function getBillingCountryIso(SalesChannelContext $context, ?OrderEntity $order): ?string + { + if ($order !== null) { + $billingAddress = $order->getBillingAddress(); + if ( + $billingAddress !== null && + $billingAddress->getCountry() !== null && + is_string($billingAddress->getCountry()->getIso()) + ) { + return $billingAddress->getCountry()->getIso(); + } + } + + $customer = $context->getCustomer(); + if ($customer !== null) { + $customerAddress = $customer->getActiveBillingAddress() ?? $customer->getDefaultBillingAddress(); + if ( + $customerAddress !== null && + $customerAddress->getCountry() !== null && + is_string($customerAddress->getCountry()->getIso()) + ) { + return $customerAddress->getCountry()->getIso(); + } + } + + return null; + } + + /** + * Detect the language configured for the active Shopware sales channel. + */ + private function getLanguageFromSalesChannel(SalesChannelContext $context): ?string + { + $languageId = $context->getSalesChannel()->getLanguageId(); + if (!is_string($languageId) || $languageId === '') { + $languageId = $context->getContext()->getLanguageId(); + } + + $localeCode = $this->getLocaleCodeByLanguageId($languageId, $context->getContext()); + if ($localeCode === null) { + return null; + } + + return $this->getPrimaryLanguage($localeCode); + } + + private function getLocaleCodeByLanguageId(string $languageId, Context $context): ?string + { + $criteria = new Criteria([$languageId]); + $criteria->addAssociation('locale'); + + /** @var LanguageEntity|null $language */ + $language = $this->languageRepository->search($criteria, $context)->first(); + + if ($language === null || $language->getLocale() === null) { + return null; + } + + return $language->getLocale()->getCode(); + } + + /** + * Extract the supported primary language subtag ("nl") from a locale ("nl-NL", "nl_BE"). + */ + private function getPrimaryLanguage(?string $locale): ?string + { + if (!is_string($locale) || $locale === '') { + return null; + } + + $primary = strtolower((string) preg_replace('/[_-].*$/', '', trim($locale))); + + return isset(self::SUPPORTED_CULTURES[$primary]) ? $primary : null; + } + + /** + * Convert a supported language to its Buckaroo culture code, with English fallback. + */ + private function toCulture(?string $language): string + { + if ($language === null) { + return self::FALLBACK_CULTURE; + } + + return self::SUPPORTED_CULTURES[$language] ?? self::FALLBACK_CULTURE; + } +} diff --git a/src/Service/CartService.php b/src/Service/CartService.php index 72be483f..1418479b 100644 --- a/src/Service/CartService.php +++ b/src/Service/CartService.php @@ -174,4 +174,15 @@ public function deleteFromCart(SalesChannelContext $salesChannelContext): void $token = $salesChannelContext->getToken(); $this->cartPersister->delete($token, $salesChannelContext); } + + /** + * Delete a persisted cart by its token. Used after an express/Apple Pay + * order has been placed: the plugin's custom order path bypasses + * Shopware's CartOrderRoute, which is where the cart would normally be + * deleted after being converted into an order. + */ + public function deleteCartByToken(string $token, SalesChannelContext $salesChannelContext): void + { + $this->cartPersister->delete($token, $salesChannelContext); + } } diff --git a/src/Service/CustomerService.php b/src/Service/CustomerService.php index 9285f523..30f641e6 100644 --- a/src/Service/CustomerService.php +++ b/src/Service/CustomerService.php @@ -17,6 +17,7 @@ use Shopware\Core\Framework\DataAbstractionLayer\Search\Criteria; use Buckaroo\Shopware6\Service\Exceptions\CreateCustomerException; use Shopware\Core\Framework\DataAbstractionLayer\EntityRepository; +use Shopware\Core\System\SalesChannel\Context\SalesChannelContextPersister; use Shopware\Core\System\SalesChannel\Context\SalesChannelContextRestorer; use Shopware\Core\Checkout\Customer\Aggregate\CustomerAddress\CustomerAddressEntity; @@ -56,13 +57,16 @@ class CustomerService */ protected $eventDispatcher; + protected SalesChannelContextPersister $contextPersister; + public function __construct( CustomerAddressService $customerAddressService, EntityRepository $customerRepository, EntityRepository $salutationRepository, EntityRepository $orderCustomerRepository, SalesChannelContextRestorer $restorer, - EventDispatcherInterface $eventDispatcher + EventDispatcherInterface $eventDispatcher, + SalesChannelContextPersister $contextPersister ) { $this->customerAddressService = $customerAddressService; $this->customerRepository = $customerRepository; @@ -70,6 +74,7 @@ public function __construct( $this->orderCustomerRepository = $orderCustomerRepository; $this->restorer = $restorer; $this->eventDispatcher = $eventDispatcher; + $this->contextPersister = $contextPersister; } /** @@ -115,8 +120,9 @@ public function createGuestCustomer(SalesChannelContext $context): CustomerEntit { $this->setSaleChannelContext($context); - $country = $context->getShippingLocation()->getCountry(); - $countryCode = $country ? $country->getIso() : 'DE'; + // ShippingLocation::getCountry() always returns a CountryEntity; + // only the ISO code itself is nullable. + $countryCode = $context->getShippingLocation()->getCountry()->getIso() ?? 'DE'; return $this->create(new DataBag([ 'paymentToken' => $context->getToken(), @@ -150,7 +156,6 @@ protected function create(DataBag $data): CustomerEntity 'salesChannelId' => $this->salesChannelContext->getSalesChannel()->getId(), 'languageId' => $this->salesChannelContext->getContext()->getLanguageId(), 'groupId' => $this->salesChannelContext->getCurrentCustomerGroup()->getId(), - 'defaultPaymentMethodId' => $this->salesChannelContext->getPaymentMethod()->getId(), 'defaultShippingAddressId' => $addressId, 'defaultBillingAddressId' => $addressId, 'salutationId' => $salutationId, @@ -162,6 +167,15 @@ protected function create(DataBag $data): CustomerEntity 'firstLogin' => new \DateTimeImmutable(), 'addresses' => [$address], ]; + + // Shopware <= 6.6 still has a default payment method on the customer entity. + // The field was removed in Shopware 6.7 (deprecated in 6.6.5.0); writing it there + // makes the DAL reject the whole payload and breaks guest express checkout + // (Apple Pay / Google Pay QR flows). + if ($this->customerRepository->getDefinition()->getFields()->get('defaultPaymentMethodId') !== null) { + $customer['defaultPaymentMethodId'] = $this->salesChannelContext->getPaymentMethod()->getId(); + } + $this->customerRepository->create( [$customer], $this->salesChannelContext->getContext() @@ -182,9 +196,22 @@ protected function create(DataBag $data): CustomerEntity */ protected function loginCreatedCustomer(CustomerEntity $customer): void { - $context = $this->restorer->restoreByCustomer($customer->getId(), $this->salesChannelContext->getContext()); + // Bind the guest customer to the CURRENT (browser) context token — the same + // thing Shopware's LoginRoute does. The previous implementation restored a + // brand-new token that never reached the browser, so the shopper's session + // stayed anonymous and /checkout/finish redirected to the empty cart page + // instead of showing the order confirmation. + $token = $this->salesChannelContext->getToken(); + + $this->contextPersister->save( + $token, + ['customerId' => $customer->getId()], + $this->salesChannelContext->getSalesChannelId(), + $customer->getId() + ); + $this->eventDispatcher->dispatch( - new CustomerLoginEvent($context, $customer, $context->getToken()) + new CustomerLoginEvent($this->salesChannelContext, $customer, $token) ); } @@ -306,6 +333,38 @@ private function validateSaleChannelContext(): void } } + /** + * Replace a guest customer's placeholder identity (name/email) with real + * data from the authorised Apple Pay contact. Updates the database record + * and keeps the in-memory entity in sync so the following order persist + * picks up the real values for the order customer. + */ + public function updateCustomerIdentity(CustomerEntity $customer, DataBag $data): void + { + $this->validateSaleChannelContext(); + + $map = [ + 'first_name' => 'firstName', + 'last_name' => 'lastName', + 'email' => 'email', + ]; + + $update = ['id' => $customer->getId()]; + foreach ($map as $key => $field) { + $value = $data->get($key); + if (is_string($value) && trim($value) !== '') { + $update[$field] = trim($value); + } + } + + if (count($update) === 1) { + return; + } + + $this->customerRepository->update([$update], $this->salesChannelContext->getContext()); + $customer->assign($update); + } + /** * Update customer entity with custom values * diff --git a/src/Service/InvoiceService.php b/src/Service/InvoiceService.php index 4ced86a2..2c9fef81 100644 --- a/src/Service/InvoiceService.php +++ b/src/Service/InvoiceService.php @@ -16,7 +16,6 @@ use Shopware\Core\Checkout\Document\Service\DocumentGenerator; use Shopware\Core\Framework\DataAbstractionLayer\Search\Criteria; use Shopware\Core\Checkout\Document\Struct\DocumentGenerateOperation; -use Shopware\Core\Checkout\Document\Exception\InvalidDocumentException; use Shopware\Core\Framework\DataAbstractionLayer\EntityRepository; use Shopware\Core\Framework\DataAbstractionLayer\Search\Filter\EqualsFilter; diff --git a/src/Service/OrderService.php b/src/Service/OrderService.php index 32defb20..5f79a954 100644 --- a/src/Service/OrderService.php +++ b/src/Service/OrderService.php @@ -137,7 +137,7 @@ public function doPayment(string $orderId, RequestDataBag $data): ?string 'HTTP_SW_CONTEXT_TOKEN' => $this->salesChannelContext->getToken(), ]); - if ($hasPay) { + if (method_exists($this->paymentService, 'pay')) { // PaymentProcessor API (Shopware 6.7+). // Depending on the exact 6.7.x version, pay() is either void or ?RedirectResponse. $this->logger->info('[GooglePay][doPayment] Calling PaymentProcessor::pay()'); @@ -165,7 +165,7 @@ public function doPayment(string $orderId, RequestDataBag $data): ?string // void / null return — use the finishUrl we supplied to the processor. return $finishUrl; - } elseif ($hasHandlePaymentByOrder) { + } elseif (method_exists($this->paymentService, 'handlePaymentByOrder')) { // PaymentService API (Shopware 6.5-6.6) — returns a RedirectResponse. $this->logger->info('[GooglePay][doPayment] Calling PaymentService::handlePaymentByOrder()'); @@ -221,7 +221,7 @@ public function persist(Cart $cart): ?OrderEntity public function getOrderById( string $orderId, array $associations = ['lineItems'], - Context $context = null + ?Context $context = null ): ?OrderEntity { if (!$context instanceof Context) { $this->validateSaleChannelContext(); @@ -257,12 +257,14 @@ private function validateSaleChannelContext(): void private function getCheckoutUrls(string $orderId, RequestDataBag $data): ?array { - // Express-checkout flows (iDEAL, Google Pay, Apple Pay) need explicit finish/error - // URLs so Shopware's PaymentProcessor can build the transaction return URL correctly. + // Express-checkout flows (iDEAL, Google Pay, Apple Pay, PayPal Express) need explicit + // finish/error URLs so Shopware's PaymentProcessor can build the transaction return + // URL correctly. if ( $data->get('idealFastCheckoutInfo') || $data->get('googlePayInfo') || - $data->get('applePayInfo') + $data->get('applePayInfo') || + $data->get('paypalExpressInfo') ) { return [ 'finishUrl' => '/checkout/finish?orderId=' . $orderId, diff --git a/src/Service/PayPalExpressCredentialsService.php b/src/Service/PayPalExpressCredentialsService.php new file mode 100644 index 00000000..a24bb082 --- /dev/null +++ b/src/Service/PayPalExpressCredentialsService.php @@ -0,0 +1,94 @@ +settingsService = $settingsService; + } + + /** + * Determine if PayPal is configured to run against the sandbox (test) environment. + * + * @param string|null $salesChannelId + * + * @return bool + */ + public function isTestMode(?string $salesChannelId = null): bool + { + return $this->settingsService->getEnvironment( + self::SETTING_ENVIRONMENT_METHOD, + $salesChannelId + ) !== 'live'; + } + + /** + * Get the environment aware PayPal Express merchant id. + * Live mode -> live merchant id (existing setting, unchanged behavior). + * Test mode -> sandbox merchant id only, never the live one. + * + * @param string|null $salesChannelId + * + * @return string|null + */ + public function getMerchantId(?string $salesChannelId = null): ?string + { + if ($this->isTestMode($salesChannelId)) { + return $this->getStringSetting(self::SETTING_SANDBOX_MERCHANT_ID, $salesChannelId); + } + + return $this->getStringSetting(self::SETTING_LIVE_MERCHANT_ID, $salesChannelId); + } + + /** + * Get all environment aware PayPal Express credentials at once. + * + * @param string|null $salesChannelId + * + * @return array{merchantId: string|null, isTestMode: bool} + */ + public function getCredentials(?string $salesChannelId = null): array + { + return [ + 'merchantId' => $this->getMerchantId($salesChannelId), + 'isTestMode' => $this->isTestMode($salesChannelId), + ]; + } + + /** + * @param string $setting + * @param string|null $salesChannelId + * + * @return string|null + */ + private function getStringSetting(string $setting, ?string $salesChannelId = null): ?string + { + $value = $this->settingsService->getSetting($setting, $salesChannelId); + if ($value !== null && is_scalar($value) && trim((string)$value) !== '') { + return trim((string)$value); + } + + return null; + } +} diff --git a/src/Service/SalesChannelContextServiceDecorator.php b/src/Service/SalesChannelContextServiceDecorator.php index dcf42423..67e53f6b 100644 --- a/src/Service/SalesChannelContextServiceDecorator.php +++ b/src/Service/SalesChannelContextServiceDecorator.php @@ -32,7 +32,9 @@ public function get(SalesChannelContextServiceParameters $parameters): SalesChan $parameters->getLanguageId(), $parameters->getCurrencyId(), $parameters->getDomainId(), - $parameters->getContext() + $parameters->getOriginalContext(), + $parameters->getCustomerId(), + $parameters->getImitatingUserId() ); } } diff --git a/src/Service/SignatureValidationService.php b/src/Service/SignatureValidationService.php index 2f3dbcb0..3781d561 100644 --- a/src/Service/SignatureValidationService.php +++ b/src/Service/SignatureValidationService.php @@ -149,14 +149,6 @@ private function decodePushValue($brq_key, $brq_value) } private function getCorrectKey(string $key): string { - if ($key === 'brq_SERVICE_knaken_Buyer_UUID') { - $key = 'brq_SERVICE_knaken_Buyer UUID'; - } - - if ($key === 'brq_SERVICE_knaken_Buyer_Name') { - $key = 'brq_SERVICE_knaken_Buyer Name'; - } - if ($key === 'brq_SERVICE_boekenbon_Additional_Info') { $key = 'brq_SERVICE_boekenbon_Additional Info'; } diff --git a/src/Service/UpdateOrderWithPaypalExpressData.php b/src/Service/UpdateOrderWithPaypalExpressData.php index fc44bf84..188ea28a 100644 --- a/src/Service/UpdateOrderWithPaypalExpressData.php +++ b/src/Service/UpdateOrderWithPaypalExpressData.php @@ -11,6 +11,7 @@ use Shopware\Core\Framework\DataAbstractionLayer\Search\Criteria; use Shopware\Core\Framework\DataAbstractionLayer\EntityRepository; use Shopware\Core\Framework\DataAbstractionLayer\Search\Filter\EqualsFilter; +use Shopware\Core\Checkout\Customer\CustomerEntity; use Shopware\Core\Checkout\Order\Aggregate\OrderCustomer\OrderCustomerEntity; class UpdateOrderWithPaypalExpressData @@ -25,12 +26,19 @@ class UpdateOrderWithPaypalExpressData */ protected $orderCustomerRepository; + /** + * @var \Shopware\Core\Framework\DataAbstractionLayer\EntityRepository + */ + protected $customerRepository; + public function __construct( EntityRepository $orderAddressRepository, - EntityRepository $orderCustomerRepository + EntityRepository $orderCustomerRepository, + EntityRepository $customerRepository ) { $this->orderAddressRepository = $orderAddressRepository; $this->orderCustomerRepository = $orderCustomerRepository; + $this->customerRepository = $customerRepository; } @@ -50,7 +58,7 @@ public function update( $saleChannelContext ); - $this->updateCustomerEmail( + $this->updateCustomerDetails( $paypalData, $order, $saleChannelContext @@ -59,7 +67,8 @@ public function update( /** - * Update paypal express customer with email + * Replace the express placeholder identity ("Unknown Customer - Buckaroo + * Payments") with the real PayPal payer name and e-mail. * * @param DataBag $paypalData * @param OrderEntity $order @@ -67,11 +76,16 @@ public function update( * * @return void */ - protected function updateCustomerEmail( + protected function updateCustomerDetails( DataBag $paypalData, OrderEntity $order, SalesChannelContext $salesChannelContext - ) { + ): void { + $details = $this->getPayerDetails($paypalData); + + if ($details === []) { + return; + } $criteria = (new Criteria())->addFilter( new EqualsFilter( @@ -80,21 +94,79 @@ protected function updateCustomerEmail( ) ); - /** @var \Shopware\Core\Checkout\Order\Aggregate\OrderCustomer\OrderCustomerEntity */ - $customer = $this->orderCustomerRepository->search( + $orderCustomer = $this->orderCustomerRepository->search( $criteria, $salesChannelContext->getContext() )->first(); - if ($customer === null) { + if (!$orderCustomer instanceof OrderCustomerEntity) { return; } $this->orderCustomerRepository->update( - [[ - "id" => $customer->getId(), - "email" => $paypalData->get('payeremail') - ]], + [array_merge(['id' => $orderCustomer->getId()], $details)], + $salesChannelContext->getContext() + ); + + $this->updateGuestCustomer( + $orderCustomer->getCustomerId(), + $details, + $salesChannelContext + ); + } + + /** + * Payer name/e-mail from the Buckaroo response. Only keys that are actually + * present are returned, so valid data is never overwritten by a placeholder. + * + * @return array + */ + private function getPayerDetails(DataBag $paypalData): array + { + $map = [ + 'payerfirstname' => 'firstName', + 'payerlastname' => 'lastName', + 'payeremail' => 'email', + ]; + + $details = []; + foreach ($map as $source => $field) { + $value = $paypalData->get($source); + if (is_string($value) && trim($value) !== '') { + $details[$field] = trim($value); + } + } + + return $details; + } + + /** + * Mirror the payer details onto the guest customer record that was created for + * the express order, so the customer list does not show the placeholder either. + * Real accounts are never overwritten with wallet data. + * + * @param array $details + */ + private function updateGuestCustomer( + ?string $customerId, + array $details, + SalesChannelContext $salesChannelContext + ): void { + if ($customerId === null) { + return; + } + + $customer = $this->customerRepository->search( + new Criteria([$customerId]), + $salesChannelContext->getContext() + )->first(); + + if (!$customer instanceof CustomerEntity || $customer->getGuest() !== true) { + return; + } + + $this->customerRepository->update( + [array_merge(['id' => $customerId], $details)], $salesChannelContext->getContext() ); } @@ -150,14 +222,26 @@ private function updateAddress( DataBag $data, SalesChannelContext $salesChannelContext ): void { - $this->orderAddressRepository->update( - [[ - 'id' => $addressId, - 'firstName' => $data->get('payerfirstname', 'Unknown'), - 'lastName' => $data->get('payerlastname', 'Paypal Express'), - 'street' => $data->get('address_line_1', 'Unknown'), - ]], - $salesChannelContext->getContext() - ); + $map = [ + 'payerfirstname' => 'firstName', + 'payerlastname' => 'lastName', + 'address_line_1' => 'street', + 'postal_code' => 'zipcode', + 'admin_area_2' => 'city', + ]; + + $update = ['id' => $addressId]; + foreach ($map as $source => $field) { + $value = $data->get($source); + if (is_string($value) && trim($value) !== '') { + $update[$field] = trim($value); + } + } + + if (count($update) === 1) { + return; + } + + $this->orderAddressRepository->update([$update], $salesChannelContext->getContext()); } } diff --git a/src/Storefront/Controller/AbstractPaymentController.php b/src/Storefront/Controller/AbstractPaymentController.php index 692fab68..91460770 100644 --- a/src/Storefront/Controller/AbstractPaymentController.php +++ b/src/Storefront/Controller/AbstractPaymentController.php @@ -66,7 +66,8 @@ public function __construct( protected function formatNumber(float $number): string { - return number_format($number, 2); + // No thousands separator: Apple Pay / Google Pay reject "1,234.56" as an amount. + return number_format($number, 2, '.', ''); } /** * Return json response with data @@ -137,7 +138,8 @@ protected function getCart(Request $request, SalesChannelContext $salesChannelCo protected function createCart(Request $request, SalesChannelContext $salesChannelContext) { $productData = $this->getProductData( - $this->getFormData($request) + $this->getFormData($request), + $request ); return $this->cartService ->setSaleChannelContext($salesChannelContext) @@ -154,10 +156,13 @@ protected function createCart(Request $request, SalesChannelContext $salesChanne */ protected function getFormData(Request $request) { - if (!$request->request->has('form')) { - throw new InvalidParameterException("Invalid payment request, form data is missing", 1); + $form = $request->request->all()['form'] ?? null; + if (!is_array($form)) { + // Tolerate a missing/empty form; the product can still be + // resolved from the top-level `productId` request parameter. + return new DataBag([]); } - return new DataBag((array)$request->request->all('form')); + return new DataBag($form); } /** @@ -167,22 +172,53 @@ protected function getFormData(Request $request) * * @return array */ - protected function getProductData(DataBag $formData) + protected function getProductData(DataBag $formData, ?Request $request = null) { $productData = []; - foreach ($formData as $key => $value) { + foreach ($formData->all() as $key => $value) { + if ($key === 'lineItems') { + // Nested structure: lineItems => [ => [id => ...]] + if ($value instanceof DataBag) { + $value = $value->all(); + } + if (is_array($value)) { + $first = reset($value); + if ($first instanceof DataBag) { + $first = $first->all(); + } + if (is_array($first)) { + $productData = array_merge($first, $productData); + } + } + continue; + } if (strpos($key, 'lineItems') !== false) { + // Flat structure: lineItems[][id] => ... $keyPars = explode("][", $key); $newKey = isset($keyPars[1]) ? str_replace("]", "", $keyPars[1]) : $key; $productData[$newKey] = $value; } } + + // Since Shopware 6.6 the quantity is a top-level 'quantity' field. + if (!isset($productData['quantity']) && $formData->has('quantity')) { + $productData['quantity'] = $formData->get('quantity'); + } + + // Fallback: build the line item from the productId the storefront sends, + // for themes/versions where the buy form has no lineItems inputs. + if ($request !== null) { + $productId = $request->request->get('productId'); + if (is_string($productId) && $productId !== '') { + $productData['id'] = $productData['id'] ?? $productId; + $productData['referencedId'] = $productData['referencedId'] ?? $productId; + $productData['type'] = $productData['type'] ?? 'product'; + } + } + $keysRequired = [ "id", - "quantity", "referencedId", - "removable", - "stackable", "type", ]; @@ -195,17 +231,17 @@ protected function getProductData(DataBag $formData) ); } - $quantity = $productData['quantity']; + $quantity = $productData['quantity'] ?? 1; if (!is_scalar($quantity)) { throw new InvalidParameterException("Invalid quantity", 1); } return [ "id" => $productData['id'], - "quantity" => (int)$quantity, + "quantity" => max(1, (int)$quantity), "referencedId" => $productData['referencedId'], - "removable" => (bool)$productData['removable'], - "stackable" => (bool)$productData['stackable'], + "removable" => isset($productData['removable']) ? (bool)$productData['removable'] : true, + "stackable" => isset($productData['stackable']) ? (bool)$productData['stackable'] : true, "type" => $productData['type'], ]; } diff --git a/src/Storefront/Controller/ApplePayController.php b/src/Storefront/Controller/ApplePayController.php index e1323aa1..ec464c30 100644 --- a/src/Storefront/Controller/ApplePayController.php +++ b/src/Storefront/Controller/ApplePayController.php @@ -14,6 +14,7 @@ use Buckaroo\Shopware6\Service\SettingsService; use Symfony\Component\Routing\Annotation\Route; use Shopware\Core\Framework\Validation\DataBag\DataBag; +use Shopware\Core\Checkout\Cart\Delivery\Struct\ShippingLocation; use Shopware\Core\Checkout\Shipping\ShippingMethodEntity; use Shopware\Core\System\SalesChannel\SalesChannelContext; use Shopware\Core\Framework\Validation\DataBag\RequestDataBag; @@ -83,7 +84,9 @@ public function getAppleCart(Request $request, SalesChannelContext $salesChannel "shippingMethods" => $this->getFormatedShippingMethods($cart, $salesChannelContext) ]); } catch (\Throwable $th) { - $this->logger->debug((string)$th); + // error level: debug is not written in production, which hides the + // real cause behind the generic "unknown error" JSON response. + $this->logger->error('[ApplePay] request failed: ' . (string)$th); return $this->response( ["message" => $this->trans("buckaroo.button_payment.unknown_error")], true @@ -95,7 +98,7 @@ public function getAppleCart(Request $request, SalesChannelContext $salesChannel * @param Request $request * @param SalesChannelContext $salesChannelContext */ - #[Route("/buckaroo/apple/cart/update", name: "frontend.action.buckaroo.appleUpdateCart", options: ["seo" => false], methods: ["POST"], defaults: ["XmlHttpRequest" => true])] + #[Route("/buckaroo/apple/cart/update", name: "frontend.action.buckaroo.appleUpdateCart", options: ["seo" => false], methods: ["POST"], defaults: ["XmlHttpRequest" => true, "_routeScope" => ["storefront"]])] public function updateCart(Request $request, SalesChannelContext $salesChannelContext): JsonResponse { if (!$request->request->has('cartToken')) { @@ -130,8 +133,11 @@ public function updateCart(Request $request, SalesChannelContext $salesChannelCo } if ($request->request->has('shippingContact')) { + // shippingContact is a nested JSON object. On Symfony 7 (Shopware 6.7) + // InputBag::get() throws BadRequestException for non-scalar values, + // so the array variant all($key) must be used here. $this->loginCustomer( - $this->getCustomerData((array)$request->request->get('shippingContact')), + $this->getCustomerData($request->request->all('shippingContact')), $salesChannelContext ); $cart = $this->cartService->calculateCart($cart, $salesChannelContext); @@ -145,7 +151,9 @@ public function updateCart(Request $request, SalesChannelContext $salesChannelCo "newShippingMethods" => $this->getFormatedShippingMethods($cart, $salesChannelContext), ]); } catch (\Throwable $th) { - $this->logger->debug((string)$th); + // error level: debug is not written in production, which hides the + // real cause behind the generic "unknown error" JSON response. + $this->logger->error('[ApplePay] request failed: ' . (string)$th); return $this->response( ["message" => $this->trans("buckaroo.button_payment.unknown_error")], true @@ -157,12 +165,16 @@ public function updateCart(Request $request, SalesChannelContext $salesChannelCo * @param Request $request * @param SalesChannelContext $salesChannelContext */ - #[Route("/buckaroo/apple/order/create", name: "frontend.action.buckaroo.appleCreateOrder", options: ["seo" => false], methods: ["POST"], defaults: ["XmlHttpRequest" => true])] + #[Route("/buckaroo/apple/order/create", name: "frontend.action.buckaroo.appleCreateOrder", options: ["seo" => false], methods: ["POST"], defaults: ["XmlHttpRequest" => true, "_routeScope" => ["storefront"]])] public function createAppleOrder(Request $request, SalesChannelContext $salesChannelContext): JsonResponse { - $this->overrideChannelPaymentMethod($salesChannelContext, 'ApplePayPaymentHandler'); try { + // Inside the try: a failure here must return JSON, not a 500 page — + // an HTML 500 leaves the Apple Pay sheet waiting for completePayment() + // until it times out (~30s) and fails on the device. + $this->overrideChannelPaymentMethod($salesChannelContext, 'ApplePayPaymentHandler'); + $redirectPath = $this->placeOrder( $this->createOrder($salesChannelContext, $request), $salesChannelContext, @@ -171,12 +183,23 @@ public function createAppleOrder(Request $request, SalesChannelContext $salesCha ]) ); + $redirect = $this->getFinishPage($redirectPath); + + if ($redirect !== null) { + // Order placed and payment initiated successfully: delete the cart. + // The custom order path bypasses Shopware's CartOrderRoute, which is + // where the cart is normally removed after checkout — without this + // the paid cart stays in the storefront. + $this->deleteCartAfterOrder($request, $salesChannelContext); + } return $this->response([ - "redirect" => $this->getFinishPage($redirectPath) + "redirect" => $redirect ]); } catch (\Throwable $th) { - $this->logger->debug((string)$th); + // error level: debug is not written in production, which hides the + // real cause behind the generic "unknown error" JSON response. + $this->logger->error('[ApplePay] request failed: ' . (string)$th); return $this->response( ["message" => $this->trans("buckaroo.button_payment.unknown_error")], true @@ -184,6 +207,27 @@ public function createAppleOrder(Request $request, SalesChannelContext $salesCha } } + /** + * Delete the cart that was just converted into an order. Deletes by the + * same token the order was created from (standard checkout and cart-page + * express use the session cart; product-page express uses its own + * temporary cart, so the shopper's session cart is left untouched there). + * Cleanup must never fail a successful payment. + */ + private function deleteCartAfterOrder(Request $request, SalesChannelContext $salesChannelContext): void + { + try { + $cartToken = $request->request->get('cartToken'); + if (!is_string($cartToken) || $cartToken === '') { + $cartToken = $salesChannelContext->getToken(); + } + + $this->cartService->deleteCartByToken($cartToken, $salesChannelContext); + } catch (\Throwable $th) { + $this->logger->warning('[ApplePay] could not delete cart after order: ' . $th->getMessage()); + } + } + /** * Create order from cart * @@ -208,10 +252,32 @@ protected function createOrder(SalesChannelContext $salesChannelContext, Request } if (in_array($request->request->get('page'), ['product', 'cart'])) { + // Express flow: the guest login performed during cart/update runs under a + // restored context token that never reaches the browser, so this request + // arrives with the original anonymous token and no customer. Create/log in + // the guest here from the full (post-authorisation) Apple Pay contact. + $this->ensureCustomer($request, $salesChannelContext); + + $paymentData = $request->request->get('payment'); + if (is_string($paymentData)) { + $paymentData = json_decode($paymentData, true); + } + + // The guest created during cart/update only had the redacted pre-auth + // contact (zip/city/country) — replace the placeholder name/email and + // shipping address with the authorised contact so the order does not + // show "Unknown Customer - Buckaroo Payments". + $this->updateGuestCustomerIdentity($paymentData, $salesChannelContext); + + $updatedCart = $this->updateCartShippingAddress($cart, $salesChannelContext, $paymentData); + if ($updatedCart !== null) { + $cart = $updatedCart; + } + $updatedCart = $this->updateCartBillingAddress( $cart, $salesChannelContext, - $request->request->get('payment') + $paymentData ); if ($updatedCart !== null) { @@ -230,6 +296,46 @@ protected function createOrder(SalesChannelContext $salesChannelContext, Request } + /** + * Make sure the sales channel context has a customer for express orders. + * Uses the authorised Apple Pay contact (shipping preferred — it carries the + * full postal address; billing as fallback) to create and log in a guest. + */ + private function ensureCustomer(Request $request, SalesChannelContext $salesChannelContext): void + { + if ($salesChannelContext->getCustomer() !== null) { + return; + } + + $paymentData = $request->request->get('payment'); + if (is_string($paymentData)) { + $paymentData = json_decode($paymentData, true); + } + + $contact = null; + if (is_array($paymentData)) { + $contact = $paymentData['shippingContact'] ?? $paymentData['billingContact'] ?? null; + + // The e-mail address is usually only present on the shipping contact; + // carry it over so the guest gets the real address either way. + if (is_array($contact) && + empty($contact['emailAddress']) && + !empty($paymentData['shippingContact']['emailAddress']) + ) { + $contact['emailAddress'] = $paymentData['shippingContact']['emailAddress']; + } + } + + if (!is_array($contact) || $contact === []) { + throw new \InvalidArgumentException('Cannot create guest customer: no Apple Pay contact available'); + } + + $this->loginCustomer( + $this->getCustomerData($contact), + $salesChannelContext + ); + } + /** * @param Cart $cart * @param mixed $shippingMethodId @@ -262,6 +368,81 @@ protected function updateCartWithSelectedShipping( ); } + /** + * Update the guest's placeholder identity (name/email) with the authorised + * Apple Pay contact. Only guests are touched — a logged-in account is never + * overwritten with wallet data. + * + * @param mixed $paymentData + */ + private function updateGuestCustomerIdentity($paymentData, SalesChannelContext $salesChannelContext): void + { + $customer = $salesChannelContext->getCustomer(); + if ($customer === null || $customer->getGuest() !== true || !is_array($paymentData)) { + return; + } + + $contact = $paymentData['shippingContact'] ?? $paymentData['billingContact'] ?? null; + if (!is_array($contact) || $contact === []) { + return; + } + + if (empty($contact['emailAddress']) && !empty($paymentData['shippingContact']['emailAddress'])) { + $contact['emailAddress'] = $paymentData['shippingContact']['emailAddress']; + } + + $this->customerService + ->setSaleChannelContext($salesChannelContext) + ->updateCustomerIdentity($customer, $this->getCustomerData($contact)); + } + + /** + * Create the shipping address from the authorised (full) Apple Pay shipping + * contact, activate it and move the context's shipping location onto it, so + * the order delivery address is the real one instead of the redacted + * pre-authorisation placeholder. + * + * @param mixed $paymentData + */ + protected function updateCartShippingAddress( + Cart $cart, + SalesChannelContext $salesChannelContext, + $paymentData + ): ?Cart { + if (is_string($paymentData)) { + $paymentData = json_decode($paymentData, true); + } + + if (!is_array($paymentData) || + !isset($paymentData['shippingContact']) || + !is_array($paymentData['shippingContact']) + ) { + return null; + } + + $customer = $salesChannelContext->getCustomer(); + if ($customer === null) { + throw new \InvalidArgumentException('Customer cannot be null'); + } + + $address = $this->customerService + ->setSaleChannelContext($salesChannelContext) + ->createAddress( + $this->getCustomerData($paymentData['shippingContact']), + $customer + ); + + if ($address !== null) { + $customer->setActiveShippingAddress($address); + $salesChannelContext->assign([ + 'shippingLocation' => ShippingLocation::createFromAddress($address) + ]); + return $this->cartService->calculateCart($cart, $salesChannelContext); + } + + return $cart; + } + /** * * @param Cart $cart @@ -367,10 +548,11 @@ public function getFormatedShippingMethods(Cart $cart, SalesChannelContext $sale )->getShippingCosts()->getTotalPrice(); $shippingMethods[] = [ - 'label' => $shippingMethod->getName(), - 'amount' => $amount, + 'label' => $shippingMethod->getName() ?? '', + // Apple Pay expects string amounts ("4.99"); null detail renders as "null" on the sheet + 'amount' => $this->formatNumber($amount), 'identifier' => $shippingMethod->getId(), - 'detail' => $shippingMethod->getDescription() + 'detail' => $shippingMethod->getDescription() ?? '' ]; } @@ -455,11 +637,27 @@ protected function getCustomerData(array $contactData) 'postalCode' => 'postal_code', 'addressLines' => 'street', 'locality' => 'city', - 'countryCode' => 'country_code' + 'countryCode' => 'country_code', + // CustomerService reads 'email' — map Apple's key so the guest gets + // the shopper's real address instead of the no-reply fallback. + 'emailAddress' => 'email' ]; $data = []; foreach ($contactData as $key => $value) { + // Apple sends addressLines as an array of street lines — the DAL + // expects a plain string for street, so flatten it here. + if ($key === 'addressLines' && is_array($value)) { + $value = trim(implode(' ', array_filter($value, 'is_string'))); + } + + // Redacted (pre-authorisation) contacts contain empty strings/arrays + // for the hidden fields; skip them so downstream defaults apply + // instead of writing empty/array values into the DAL. + if ($value === null || $value === '' || $value === []) { + continue; + } + if (isset($mappings[$key])) { $data[$mappings[$key]] = $value; } else { diff --git a/src/Storefront/Controller/IdealFastCheckoutController.php b/src/Storefront/Controller/IdealFastCheckoutController.php index 556ce25b..afea87d4 100644 --- a/src/Storefront/Controller/IdealFastCheckoutController.php +++ b/src/Storefront/Controller/IdealFastCheckoutController.php @@ -10,7 +10,7 @@ use Buckaroo\Shopware6\Service\SettingsService; use Psr\Log\LoggerInterface; use Shopware\Core\Framework\DataAbstractionLayer\EntityRepository; -use Shopware\Core\System\SalesChannel\Context\SalesChannelContextService; +use Shopware\Core\System\SalesChannel\Context\SalesChannelContextServiceInterface; use Shopware\Core\System\SalesChannel\Context\SalesChannelContextServiceParameters; use Shopware\Core\System\SalesChannel\Context\SalesChannelContextPersister; use Shopware\Core\System\SalesChannel\Entity\SalesChannelRepository; @@ -30,7 +30,7 @@ class IdealFastCheckoutController extends AbstractPaymentController { private LoggerInterface $logger; private SalesChannelContextPersister $contextPersister; - private SalesChannelContextService $contextService; + private SalesChannelContextServiceInterface $contextService; private AbstractRegisterRoute $registerRoute; /** @@ -46,7 +46,7 @@ public function __construct( SalesChannelRepository $paymentMethodRepository, LoggerInterface $logger, SalesChannelContextPersister $contextPersister, - SalesChannelContextService $contextService, + SalesChannelContextServiceInterface $contextService, AbstractRegisterRoute $registerRoute, EntityRepository $salutationRepository ) { diff --git a/src/Storefront/Controller/PaypalExpressController.php b/src/Storefront/Controller/PaypalExpressController.php index ec0272f3..71bed866 100644 --- a/src/Storefront/Controller/PaypalExpressController.php +++ b/src/Storefront/Controller/PaypalExpressController.php @@ -99,20 +99,37 @@ public function pay(Request $request, SalesChannelContext $salesChannelContext): } try { + $requestCartToken = $request->request->get('cartToken'); + $cartToken = is_string($requestCartToken) && $requestCartToken !== '' + ? $requestCartToken + : $salesChannelContext->getToken(); + $redirectPath = $this->placeOrder( - $this->createOrder($salesChannelContext, (string)$request->request->get('cartToken')), + $this->createOrder($salesChannelContext, $cartToken), $salesChannelContext, new RequestDataBag([ - "orderId" => $request->request->get('orderId') + "orderId" => $request->request->get('orderId'), + "paypalExpressInfo" => true ]) ); + $redirect = $this->getFinishPage($redirectPath); + + if ($redirect !== null) { + // Order placed and payment initiated: delete the cart. This custom + // express order path bypasses Shopware's CartOrderRoute, which is where + // the cart is normally removed after checkout - without this the paid + // cart is still there when the shopper returns to the shop. + $this->deleteCartAfterOrder($cartToken, $salesChannelContext); + } return $this->response([ - "redirect" => $this->getFinishPage($redirectPath) + "redirect" => $redirect ]); } catch (\Throwable $th) { - $this->logger->debug((string)$th); + // error level: debug is not written in production, which hides the + // real cause behind the generic "unknown error" JSON response. + $this->logger->error('[PaypalExpress] pay failed: ' . (string)$th); return $this->response( ["message" => $this->trans("buckaroo.button_payment.unknown_error")], true @@ -120,26 +137,55 @@ public function pay(Request $request, SalesChannelContext $salesChannelContext): } } + /** + * Delete the cart that was just converted into an order. The cart-page flow uses + * the session cart; the product-page flow uses its own temporary cart, so the + * shopper's session cart is left untouched there. Cleanup must never fail a + * successful payment. + */ + private function deleteCartAfterOrder(string $cartToken, SalesChannelContext $salesChannelContext): void + { + try { + $this->cartService->deleteCartByToken($cartToken, $salesChannelContext); + } catch (\Throwable $th) { + $this->logger->warning('[PaypalExpress] could not delete cart after order: ' . $th->getMessage()); + } + } + /** * Create order from cart * * @param SalesChannelContext $salesChannelContext - * @param string|null $cartToken + * @param string $cartToken * * @return \Shopware\Core\Checkout\Order\OrderEntity */ - protected function createOrder(SalesChannelContext $salesChannelContext, string $cartToken = null): OrderEntity + protected function createOrder(SalesChannelContext $salesChannelContext, string $cartToken): OrderEntity { - - if (!is_string($cartToken)) { - $cartToken = $salesChannelContext->getToken(); - } - $cart = $this->getCartByToken($cartToken, $salesChannelContext); if ($cart === null) { throw new \Exception("Cannot find cart", 1); } + + // Express flow: /buckaroo/paypal/create - and with it the guest login - only + // runs when PayPal fires a shipping change. When it does not (single saved + // address, no-shipping cart, newer SDK callback naming) this request still + // carries the anonymous context, the cart delivery has a country-only + // shipping location and OrderPersister throws + // "Delivery contains no shipping address". Create and log in a guest here; + // the real payer name/address/email is written back onto the order by + // UpdateOrderWithPaypalExpressData once Buckaroo responds. + if ($salesChannelContext->getCustomer() === null) { + $this->customerService->createGuestCustomer($salesChannelContext); + } + + // Recalculate so the delivery picks up the shipping address that was assigned + // to the context above; the persisted cart was calculated anonymously. + $cart = $this->cartService + ->setSaleChannelContext($salesChannelContext) + ->calculateCart($cart, $salesChannelContext); + $order = $this->orderService ->setSaleChannelContext($salesChannelContext) ->persist($cart); diff --git a/src/Storefront/Controller/PushController.php b/src/Storefront/Controller/PushController.php index bc16bc9e..3467bec2 100644 --- a/src/Storefront/Controller/PushController.php +++ b/src/Storefront/Controller/PushController.php @@ -18,6 +18,7 @@ use Buckaroo\Shopware6\Handlers\IdealQrPaymentHandler; use Buckaroo\Shopware6\Service\StateTransitionService; use Buckaroo\Shopware6\Helpers\Constants\ResponseStatus; +use Buckaroo\Shopware6\Helpers\KlarnaKpCaptureDetector; use Shopware\Storefront\Controller\StorefrontController; use Buckaroo\Shopware6\Service\SignatureValidationService; use Shopware\Core\System\SalesChannel\SalesChannelContext; @@ -45,6 +46,32 @@ class PushController extends StorefrontController 'I108' ]; + /** + * Payment states in which the transaction is settled. A failure push (technical + * error, validation failure 491, rejected, cancelled) must never move a transaction + * that is already in one of these states: such a push reports a rejected follow-up + * operation - a pay/capture on an already captured reservation, a declined refund - + * and not a failed payment. + * + * The refunded states matter in particular: without them a Klarna KP 491 "Pay on + * reservation ... reservation has status FullyCaptured" push arriving after a refund + * falls through to the fail/cancel fallback and flips the payment to cancelled. + * + * `authorized` is deliberately NOT in this list. An authorization is not settled, so + * a failure push against it is plausibly a real payment failure. + * + * Values are the plugin's internal status names consumed by + * StateTransitionService::getCorrectTransitionAction(). + * + * @var array + */ + public const SETTLED_PAYMENT_STATES = [ + 'paid', + 'pay_partially', + 'refunded', + 'partial_refunded', + ]; + private LoggerInterface $logger; private CheckoutHelper $checkoutHelper; @@ -352,6 +379,17 @@ public function pushBuckaroo(Request $request, SalesChannelContext $salesChannel } } } + // The engine may have paid the Klarna KP reservation itself (AutoPay) or + // it may have been paid in the Plaza. Record that, otherwise + // capture-on-shipment keeps retrying a Pay on a FullyCaptured + // reservation and Buckaroo answers 491. + if (KlarnaKpCaptureDetector::isEngineCapture($request)) { + $this->logger->info( + __METHOD__ . "|44|Klarna KP reservation already captured by the payment engine" + ); + $data['captured'] = 1; + } + $this->logger->info(__METHOD__ . "|45|", [$paymentState, $brqAmount, $totalPrice]); $this->setPaymentState( @@ -425,13 +463,15 @@ public function pushBuckaroo(Request $request, SalesChannelContext $salesChannel )) { if ( $this->stateTransitionService->isTransitionPaymentState( - ['paid', 'pay_partially'], + self::SETTLED_PAYMENT_STATES, $orderTransactionId, $context ) || $this->stateTransitionService->isOrderPaid($order) ) { - $this->logger->info(__METHOD__ . '|Push ignored because order is already paid'); + $this->logger->info( + __METHOD__ . '|Failure push ignored because the transaction is already settled' + ); return $this->response('buckaroo.messages.skippedPush'); } if ($this->stateTransitionService->canTransitionStatus('fail', $orderTransactionId, $context)) { @@ -458,7 +498,7 @@ public function pushBuckaroo(Request $request, SalesChannelContext $salesChannel if ($status === ResponseStatus::BUCKAROO_STATUSCODE_CANCELLED_BY_USER) { if ( $this->stateTransitionService->isTransitionPaymentState( - ['paid', 'pay_partially'], + self::SETTLED_PAYMENT_STATES, $orderTransactionId, $context ) || @@ -497,7 +537,7 @@ private function setStatusAuthorized( string $status ): void { if ($this->stateTransitionService->isTransitionPaymentState( - ['paid', 'pay_partially'], + self::SETTLED_PAYMENT_STATES, $orderTransactionId, $salesChannelContext->getContext() )) { diff --git a/src/Subscribers/CheckoutConfirmTemplateSubscriber.php b/src/Subscribers/CheckoutConfirmTemplateSubscriber.php index 97f2307e..fccbd861 100644 --- a/src/Subscribers/CheckoutConfirmTemplateSubscriber.php +++ b/src/Subscribers/CheckoutConfirmTemplateSubscriber.php @@ -9,6 +9,7 @@ use Buckaroo\Shopware6\Service\In3LogoService; use Buckaroo\Shopware6\Service\SettingsService; use Buckaroo\Shopware6\Service\PayByBankService; +use Buckaroo\Shopware6\Service\PayPalExpressCredentialsService; use Shopware\Core\System\Currency\CurrencyEntity; use Buckaroo\Shopware6\Service\IdealIssuerService; use Shopware\Core\Checkout\Customer\CustomerEntity; @@ -68,6 +69,7 @@ class CheckoutConfirmTemplateSubscriber implements EventSubscriberInterface protected TranslatorInterface $translator; protected PayByBankService $payByBankService; protected In3LogoService $in3LogoService; + protected PayPalExpressCredentialsService $paypalExpressCredentials; public function __construct( SalesChannelRepository $paymentMethodRepository, @@ -76,7 +78,8 @@ public function __construct( TranslatorInterface $translator, PayByBankService $payByBankService, In3LogoService $in3LogoService, - IdealIssuerService $idealIssuerService + IdealIssuerService $idealIssuerService, + PayPalExpressCredentialsService $paypalExpressCredentials ) { $this->paymentMethodRepository = $paymentMethodRepository; $this->settingsService = $settingsService; @@ -85,6 +88,7 @@ public function __construct( $this->payByBankService = $payByBankService; $this->in3LogoService = $in3LogoService; $this->idealIssuerService = $idealIssuerService; + $this->paypalExpressCredentials = $paypalExpressCredentials; } /** @@ -315,9 +319,9 @@ public function addBuckarooExtension($event): void 'showPaypalExpress' => $this->showPaypalExpress($salesChannelId, 'checkout'), 'showIdealFastCheckout' => $this->showIdealFastCheckout($salesChannelId, 'checkout'), 'paypalMerchantId' => $this->getPaypalExpressMerchantId($salesChannelId), - 'applepayHostedPaymentPage' => - $this->getSettingAsInt('applepayHostedPaymentPage', $salesChannelId) === 1, + 'paypalIsTestMode' => $this->paypalExpressCredentials->isTestMode($salesChannelId), 'applePayMerchantId' => $this->getAppleMerchantId($salesChannelId), + 'showApplePay' => $this->showApplePayExpress($salesChannelId, 'checkout'), 'isAppleDevice' => $this->isAppleDevice($request), 'googlepayMerchantId' => $this->getGoogleMerchantId($salesChannelId), 'googlepayGatewayMerchantId' => $this->getGooglepayGatewayMerchantId($salesChannelId), @@ -456,15 +460,14 @@ public function addBuckarooToCart(CheckoutCartPageLoadedEvent $event): void $request = $event->getRequest(); $struct->assign([ - 'applepayHostedPaymentPage' => - $this->getSettingAsInt('applepayHostedPaymentPage', $salesChannelId) === 1, 'showPaypalExpress' => $this->showPaypalExpress($salesChannelId, 'cart'), 'showIdealFastCheckout' => $this->showIdealFastCheckout($salesChannelId, 'cart'), 'paypalMerchantId' => $this->getPaypalExpressMerchantId($salesChannelId), + 'paypalIsTestMode' => $this->paypalExpressCredentials->isTestMode($salesChannelId), 'applePayMerchantId' => $this->getAppleMerchantId($salesChannelId), 'isAppleDevice' => $this->isAppleDevice($request), 'websiteKey' => $this->settingsService->getSetting('websiteKey', $salesChannelId), - 'showApplePay' => $this->getSettingAsBool('applepayShowCart', $salesChannelId), + 'showApplePay' => $this->showApplePayExpress($salesChannelId, 'cart'), 'showGooglePay' => $this->getSettingAsBool('googlepayShowCart', $salesChannelId), 'googlepayMerchantId' => $this->getGoogleMerchantId($salesChannelId), 'googlepayGatewayMerchantId' => $this->getGooglepayGatewayMerchantId($salesChannelId), @@ -520,13 +523,11 @@ public function addBuckarooToProductPage(ProductPageLoadedEvent $event): void $salesChannelId = $event->getSalesChannelContext()->getSalesChannelId(); $request = $event->getRequest(); $struct->assign([ - 'applepayShowProduct' => - $this->getSettingAsBool('applepayShowProduct', $salesChannelId), - 'applepayHostedPaymentPage' => - $this->getSettingAsInt('applepayHostedPaymentPage', $salesChannelId) === 1, + 'applepayShowProduct' => $this->showApplePayExpress($salesChannelId, 'product'), 'showPaypalExpress' => $this->showPaypalExpress($salesChannelId), 'showIdealFastCheckout' => $this->showIdealFastCheckout($salesChannelId), 'paypalMerchantId' => $this->getPaypalExpressMerchantId($salesChannelId), + 'paypalIsTestMode' => $this->paypalExpressCredentials->isTestMode($salesChannelId), 'applePayMerchantId' => $this->getAppleMerchantId($salesChannelId), 'isAppleDevice' => $this->isAppleDevice($request), 'websiteKey' => $this->settingsService->getSetting('websiteKey', $salesChannelId), @@ -550,13 +551,13 @@ protected function showPaypalExpress(string $salesChannelId, string $page = 'pro in_array($page, $locations) && $this->getPaypalExpressMerchantId($salesChannelId) != null; } + /** + * Get the environment aware (live/sandbox) PayPal Express merchant id. + * Credential selection is centralized in PayPalExpressCredentialsService. + */ protected function getPaypalExpressMerchantId(string $salesChannelId): ?string { - $merchantId = $this->settingsService->getSetting('paypalExpressmerchantid', $salesChannelId); - if ($merchantId !== null && is_scalar($merchantId)) { - return (string)$merchantId; - } - return null; + return $this->paypalExpressCredentials->getMerchantId($salesChannelId); } protected function showIdealFastCheckout(string $salesChannelId, string $page = 'product'): bool { @@ -571,12 +572,47 @@ protected function showIdealFastCheckout(string $salesChannelId, string $page = return false; } } - protected function getIdealFastCheckoutLogo(string $salesChannelId): ?string + /** + * Button style for the iDEAL fast checkout button: "light" (white button + * with a magenta outline, iDEAL's default) or "dark" (solid magenta). + * + * The stored setting still uses the historic idealFastCheckoutLogo* + * identifiers so existing sales channel configuration keeps working. + */ + protected function getIdealFastCheckoutLogo(string $salesChannelId): string { - $settings = $this->settingsService->getSetting('idealFastCheckoutLogoScheme', $salesChannelId); + $setting = $this->settingsService->getSetting('idealFastCheckoutLogoScheme', $salesChannelId); - return is_string($settings) ? $settings : null; + return $setting === 'idealFastCheckoutLogoDark' ? 'dark' : 'light'; } + /** + * Whether the Apple Pay express button may be rendered on a given storefront + * location. Requires a configured merchant id (guid) and the per-location + * visibility setting to be enabled. + * + * This is independent of the standard Apple Pay payment method, which is + * rendered from the selected payment method on the confirm page. + */ + protected function showApplePayExpress(string $salesChannelId, string $page = 'product'): bool + { + $merchantId = $this->getAppleMerchantId($salesChannelId); + if ($merchantId === null || trim($merchantId) === '') { + return false; + } + + $settings = [ + 'product' => 'applepayShowProduct', + 'cart' => 'applepayShowCart', + 'checkout' => 'applepayShowCheckout', + ]; + + if (!isset($settings[$page])) { + return false; + } + + return $this->getSettingAsBool($settings[$page], $salesChannelId); + } + protected function getAppleMerchantId(string $salesChannelId): ?string { $merchantId = $this->settingsService->getSetting('applepayGuid', $salesChannelId); @@ -998,14 +1034,14 @@ private function getSettingAsInt(string $key, string $salesChannelId, int $defau private function isAppleDevice($request): bool { $userAgent = $request->server->get('HTTP_USER_AGENT'); - + if (!is_string($userAgent) || empty($userAgent)) { return false; } - + // Check for Apple devices: iPhone, iPad, iPod, Macintosh, Mac OS X $applePattern = '/(iphone|ipad|ipod|macintosh|mac os x)/i'; - + return preg_match($applePattern, $userAgent) === 1; } } diff --git a/src/Subscribers/OrderDeliveryWrittenSubscriber.php b/src/Subscribers/OrderDeliveryWrittenSubscriber.php index 184d2c4d..19749cb6 100644 --- a/src/Subscribers/OrderDeliveryWrittenSubscriber.php +++ b/src/Subscribers/OrderDeliveryWrittenSubscriber.php @@ -28,9 +28,31 @@ * continues to be handled by {@see OrderStateChangeEvent}. In that path BOTH events * fire; deduplication is handled by the customFields['captured'] flag that * CaptureService persists synchronously after a successful capture. + * + * IMPORTANT: this path is opt-in per payment method, see + * self::CAPTURE_METHODS_ON_DAL_WRITE. It is deliberately NOT enabled for Klarna KP. + * A Klarna KP capture is a "Pay on reservation" call, and the reservation can already + * have been captured outside of Shopware (Buckaroo KlarnaKP AutoPay, a manual capture + * in the Payment Plaza, or a capture done by an older plugin version). In those cases + * customFields['captured'] is absent, so the canCapture* guards cannot deduplicate: + * every delivery write would retry the Pay and Buckaroo answers 491 "Pay on + * reservation ... is not possible: reservation has status FullyCaptured". That + * validation failure is pushed back to PushController and can flip an already + * refunded transaction to cancelled. Klarna KP therefore keeps the single-shot + * state_enter path only. */ class OrderDeliveryWrittenSubscriber implements EventSubscriberInterface { + /** + * Buckaroo payment methods (lowercase `brqPaymentMethod`) for which a direct DAL + * write of the shipped state may trigger capture-on-shipment. Klarna MoR only: its + * capture is guarded by customFields['captured'] and ['dataRequestKey'], both of + * which the plugin itself always writes, so repeated writes are idempotent. + * + * @var array + */ + public const CAPTURE_METHODS_ON_DAL_WRITE = ['klarna']; + private OrderStateChangeEvent $orderStateChangeEvent; private EntityRepository $orderDeliveryRepository; @@ -139,7 +161,8 @@ private function triggerCaptureForDeliveries(array $deliveryIds, Context $contex $this->orderStateChangeEvent->triggerCaptureForShippedOrder( $order->getId(), $order->getSalesChannelId(), - $context + $context, + self::CAPTURE_METHODS_ON_DAL_WRITE ); } } diff --git a/tests/Integration/Subscribers/CheckoutConfirmTemplateSubscriberTest.php b/tests/Integration/Subscribers/CheckoutConfirmTemplateSubscriberTest.php index 6372d9fb..2032a823 100644 --- a/tests/Integration/Subscribers/CheckoutConfirmTemplateSubscriberTest.php +++ b/tests/Integration/Subscribers/CheckoutConfirmTemplateSubscriberTest.php @@ -11,6 +11,7 @@ use Buckaroo\Shopware6\Service\PayByBankService; use Buckaroo\Shopware6\Service\In3LogoService; use Buckaroo\Shopware6\Service\IdealIssuerService; +use Buckaroo\Shopware6\Service\PayPalExpressCredentialsService; use Shopware\Core\System\SalesChannel\Entity\SalesChannelRepository; use Symfony\Contracts\Translation\TranslatorInterface; use Shopware\Storefront\Page\Checkout\Confirm\CheckoutConfirmPageLoadedEvent; @@ -38,6 +39,7 @@ class CheckoutConfirmTemplateSubscriberTest extends TestCase private PayByBankService $payByBankService; private In3LogoService $in3LogoService; private IdealIssuerService $idealIssuerService; + private PayPalExpressCredentialsService $paypalExpressCredentials; protected function setUp(): void { @@ -48,6 +50,7 @@ protected function setUp(): void $this->payByBankService = $this->createMock(PayByBankService::class); $this->in3LogoService = $this->createMock(In3LogoService::class); $this->idealIssuerService = $this->createMock(IdealIssuerService::class); + $this->paypalExpressCredentials = $this->createMock(PayPalExpressCredentialsService::class); $this->subscriber = new CheckoutConfirmTemplateSubscriber( $this->paymentMethodRepository, @@ -56,7 +59,8 @@ protected function setUp(): void $this->translator, $this->payByBankService, $this->in3LogoService, - $this->idealIssuerService + $this->idealIssuerService, + $this->paypalExpressCredentials ); } diff --git a/tests/Unit/Events/OrderStateChangeEventCaptureRestrictionTest.php b/tests/Unit/Events/OrderStateChangeEventCaptureRestrictionTest.php new file mode 100644 index 00000000..edf02a38 --- /dev/null +++ b/tests/Unit/Events/OrderStateChangeEventCaptureRestrictionTest.php @@ -0,0 +1,200 @@ +transactionService = $this->createMock(TransactionService::class); + $this->orderService = $this->createMock(OrderService::class); + $this->captureService = $this->createMock(CaptureService::class); + $this->settingsService = $this->createMock(SettingsService::class); + $this->context = $this->createMock(Context::class); + + $notificationServiceFactory = $this->createMock(NotificationServiceFactory::class); + $notificationServiceFactory->method('getNotificationService')->willReturn(new \stdClass()); + + $this->settingsService->method('getSetting')->willReturn(true); + + $order = new OrderEntity(); + $order->setId(self::ORDER_ID); + $order->setUniqueIdentifier(self::ORDER_ID); + $order->setSalesChannelId(self::SALES_CHANNEL_ID); + $this->orderService->method('getOrderById')->willReturn($order); + + $this->subject = new OrderStateChangeEvent( + $this->transactionService, + $this->createMock(InvoiceService::class), + $this->settingsService, + $this->orderService, + $this->createMock(LoggerInterface::class), + $this->captureService, + $notificationServiceFactory, + $this->createMock(KlarnaMorService::class), + $this->createMock(StateTransitionService::class) + ); + } + + /** + * @param array $customFields + */ + private function withCustomFields(array $customFields): void + { + $this->transactionService->method('getCustomFields')->willReturn($customFields); + } + + /** + * @return array + */ + private function klarnaKpCustomFields(): array + { + // A Klarna KP order whose reservation was captured outside of Shopware: + // reservationNumber is present, 'captured' is not. + return [ + 'brqPaymentMethod' => 'KlarnaKp', + 'serviceName' => 'klarnakp', + 'reservationNumber' => '8ff10537-f735-4485-bdc8-3b19dd50f733', + ]; + } + + /** + * @return array + */ + private function klarnaMorCustomFields(): array + { + return [ + 'brqPaymentMethod' => 'klarna', + 'serviceName' => 'klarna', + 'dataRequestKey' => '65105EB3A3704E6D8FDCF8A1DCE8DD9E', + ]; + } + + public function testDalWritePathDoesNotCaptureKlarnaKp(): void + { + $this->withCustomFields($this->klarnaKpCustomFields()); + + $this->captureService + ->expects($this->never()) + ->method('capture'); + + $this->assertFalse( + $this->subject->triggerCaptureForShippedOrder( + self::ORDER_ID, + self::SALES_CHANNEL_ID, + $this->context, + OrderDeliveryWrittenSubscriber::CAPTURE_METHODS_ON_DAL_WRITE + ) + ); + } + + public function testDalWritePathStillCapturesKlarnaMor(): void + { + $this->withCustomFields($this->klarnaMorCustomFields()); + + $this->captureService + ->expects($this->once()) + ->method('capture') + ->willReturn(['status' => true, 'message' => 'captured']); + + $this->assertTrue( + $this->subject->triggerCaptureForShippedOrder( + self::ORDER_ID, + self::SALES_CHANNEL_ID, + $this->context, + OrderDeliveryWrittenSubscriber::CAPTURE_METHODS_ON_DAL_WRITE + ) + ); + } + + /** + * No restriction (state_enter path): Klarna KP capture-on-shipment keeps working + * exactly as it did before, i.e. once per shipped transition. + */ + public function testStateMachinePathStillCapturesKlarnaKp(): void + { + $this->withCustomFields($this->klarnaKpCustomFields()); + + $this->captureService + ->expects($this->once()) + ->method('capture') + ->willReturn(['status' => true, 'message' => 'captured']); + + $this->assertTrue( + $this->subject->triggerCaptureForShippedOrder( + self::ORDER_ID, + self::SALES_CHANNEL_ID, + $this->context + ) + ); + } + + /** + * An already captured Klarna KP order must never be paid again, on either path. + */ + public function testCapturedKlarnaKpOrderIsNeverCapturedAgain(): void + { + $this->withCustomFields($this->klarnaKpCustomFields() + ['captured' => 1]); + + $this->captureService + ->expects($this->never()) + ->method('capture'); + + $this->subject->triggerCaptureForShippedOrder( + self::ORDER_ID, + self::SALES_CHANNEL_ID, + $this->context + ); + } +} diff --git a/tests/Unit/Helpers/KlarnaKpCaptureDetectorTest.php b/tests/Unit/Helpers/KlarnaKpCaptureDetectorTest.php new file mode 100644 index 00000000..36b8ef9c --- /dev/null +++ b/tests/Unit/Helpers/KlarnaKpCaptureDetectorTest.php @@ -0,0 +1,124 @@ + $post + * @dataProvider pushProvider + */ + public function testIsEngineCapture(bool $expected, array $post, string $case): void + { + $this->assertSame( + $expected, + KlarnaKpCaptureDetector::isEngineCapture(new Request([], $post)), + $case + ); + } + + /** + * @return array, 2: string}> + */ + public static function pushProvider(): array + { + return [ + 'klarnakp V610 pay push with a capture id' => [ + true, + [ + 'brq_amount' => '273.95', + 'brq_mutationtype' => 'Processing', + 'brq_SERVICE_klarnakp_CaptureId' => '7b20ed3d-bb0e-42c2-a7b8-bef3d951651a', + 'brq_statuscode' => '190', + 'brq_transaction_method' => 'KlarnaKp', + 'brq_transaction_type' => 'V610', + ], + 'the reservation was paid; captured must be recorded', + ], + 'klarnakp reserve push carrying an AutoPay transaction key' => [ + true, + [ + 'brq_primary_service' => 'KlarnaKp', + 'brq_SERVICE_klarnakp_AutoPayTransactionKey' => '13B097483CEB40A88EB85FB6AA83D71A', + 'brq_SERVICE_klarnakp_ReservationNumber' => '8ff10537-f735-4485-bdc8-3b19dd50f733', + 'brq_statuscode' => '190', + ], + 'AutoPay paid the reservation without CaptureService running', + ], + 'klarnakp V610 without a capture id still counts as a pay' => [ + true, + [ + 'brq_transaction_method' => 'klarnakp', + 'brq_transaction_type' => 'V610', + 'brq_statuscode' => '190', + ], + 'transaction type alone identifies a pay on reservation', + ], + 'klarnakp reserve push without AutoPay' => [ + false, + [ + 'brq_primary_service' => 'KlarnaKp', + 'brq_SERVICE_klarnakp_ReservationNumber' => '04dcc442-1688-4047-87c4-e8441ddec5e6', + 'brq_statuscode' => '190', + ], + 'a plain reservation is not a capture; capture-on-shipment must stay available', + ], + 'klarnakp 491 validation failure' => [ + false, + [ + 'brq_amount' => '120.95', + 'brq_mutationtype' => 'NotSet', + 'brq_statuscode' => '491', + 'brq_statusmessage' => 'Validation failure', + 'brq_transaction_method' => 'KlarnaKp', + ], + 'a rejected pay is not a capture', + ], + 'klarnakp refund push' => [ + false, + [ + 'brq_amount_credit' => '280.00', + 'brq_mutationtype' => 'Processing', + 'brq_SERVICE_klarnakp_Processed' => 'Classic', + 'brq_statuscode' => '190', + 'brq_transaction_method' => 'klarnakp', + ], + 'a refund is not a capture', + ], + 'klarna MoR push is out of scope' => [ + false, + [ + 'brq_primary_service' => 'klarna', + 'brq_SERVICE_klarna_DataRequestKey' => '65105EB3A3704E6D8FDCF8A1DCE8DD9E', + 'brq_statuscode' => '190', + ], + 'MoR has its own dataRequestKey bookkeeping', + ], + 'unrelated ideal push' => [ + false, + [ + 'brq_amount' => '138.00', + 'brq_statuscode' => '190', + 'brq_transaction_method' => 'ideal', + 'brq_transaction_type' => 'C021', + ], + 'non Klarna KP methods are never affected', + ], + 'empty push' => [ + false, + [], + 'must not blow up on a payload without a method', + ], + ]; + } +} diff --git a/tests/Unit/PaymentMethods/KnakenTest.php b/tests/Unit/PaymentMethods/KnakenTest.php deleted file mode 100644 index d3035bd3..00000000 --- a/tests/Unit/PaymentMethods/KnakenTest.php +++ /dev/null @@ -1,88 +0,0 @@ -payment = new Knaken(); - } - - public function testImplementsPaymentMethodInterface(): void - { - $this->assertInstanceOf(PaymentMethodInterface::class, $this->payment); - } - - public function testGetBuckarooKeyReturnsCorrectKey(): void - { - $this->assertSame('knaken', $this->payment->getBuckarooKey()); - } - - public function testGetVersionReturnsCorrectVersion(): void - { - $this->assertSame('1', $this->payment->getVersion()); - } - - public function testGetNameReturnsCorrectName(): void - { - $this->assertSame('goSettle', $this->payment->getName()); - } - - public function testGetDescriptionReturnsCorrectText(): void - { - $this->assertSame('Pay with goSettle', $this->payment->getDescription()); - } - - public function testGetPaymentHandlerReturnsCorrectHandler(): void - { - $this->assertSame(KnakenPaymentHandler::class, $this->payment->getPaymentHandler()); - } - - public function testGetMediaReturnsPath(): void - { - $result = $this->payment->getMedia(); - $this->assertStringContainsString('gosettle.svg', $result); - } - - public function testGetTranslationsReturnsGermanAndEnglish(): void - { - $result = $this->payment->getTranslations(); - $this->assertArrayHasKey('de-DE', $result); - $this->assertArrayHasKey('en-GB', $result); - } - - public function testGetTypeReturnsCorrectType(): void - { - $this->assertSame('redirect', $this->payment->getType()); - } - - public function testCanRefundReturnsTrue(): void - { - $this->assertTrue($this->payment->canRefund()); - } - - public function testCanCaptureReturnsFalse(): void - { - $this->assertFalse($this->payment->canCapture()); - } - - public function testGetTechnicalNameReturnsCorrectName(): void - { - $this->assertSame('buckaroo_knaken', $this->payment->getTechnicalName()); - } - - public function testGetTemplateReturnsNull(): void - { - $this->assertNull($this->payment->getTemplate()); - } -} diff --git a/tests/Unit/Service/BuckarooLanguageResolverTest.php b/tests/Unit/Service/BuckarooLanguageResolverTest.php new file mode 100644 index 00000000..7a6b0ee1 --- /dev/null +++ b/tests/Unit/Service/BuckarooLanguageResolverTest.php @@ -0,0 +1,311 @@ +settingsService = $this->createMock(SettingsService::class); + $this->languageRepository = $this->createMock(EntityRepository::class); + $this->requestStack = new RequestStack(); + + $this->resolver = new BuckarooLanguageResolver( + $this->settingsService, + $this->requestStack, + $this->languageRepository + ); + } + + private function configureMode(?string $mode): void + { + $this->settingsService + ->method('getSetting') + ->with(BuckarooLanguageResolver::SETTING_KEY, 'sales-channel-id') + ->willReturn($mode); + } + + private function getSalesChannelContext(?string $salesChannelLanguageId = null): SalesChannelContext + { + $salesChannel = new SalesChannelEntity(); + $salesChannel->setUniqueIdentifier('sales-channel-id'); + if ($salesChannelLanguageId !== null) { + $salesChannel->setLanguageId($salesChannelLanguageId); + } + + $context = $this->createMock(SalesChannelContext::class); + $context->method('getSalesChannelId')->willReturn('sales-channel-id'); + $context->method('getSalesChannel')->willReturn($salesChannel); + $context->method('getContext')->willReturn(Context::createDefaultContext()); + $context->method('getCustomer')->willReturn(null); + + return $context; + } + + private function createRequestWithAcceptLanguage(string $acceptLanguage): Request + { + $request = Request::create('/'); + $request->headers->set('Accept-Language', $acceptLanguage); + + return $request; + } + + private function createOrderWithBillingCountry(?string $iso): OrderEntity + { + $order = new OrderEntity(); + $order->setUniqueIdentifier('order-id'); + + $address = new OrderAddressEntity(); + $address->setUniqueIdentifier('address-id'); + + if ($iso !== null) { + $country = new CountryEntity(); + $country->setUniqueIdentifier('country-id'); + $country->setIso($iso); + $address->setCountry($country); + } + + $order->setBillingAddress($address); + + return $order; + } + + private function mockSalesChannelLocale(?string $localeCode): void + { + $language = null; + if ($localeCode !== null) { + $locale = new LocaleEntity(); + $locale->setUniqueIdentifier('locale-id'); + $locale->setCode($localeCode); + + $language = new LanguageEntity(); + $language->setUniqueIdentifier('language-id'); + $language->setLocale($locale); + } + + $searchResult = $this->createMock(EntitySearchResult::class); + $searchResult->method('first')->willReturn($language); + + $this->languageRepository->method('search')->willReturn($searchResult); + } + + /** + * Fixed language always wins, regardless of browser, country or sales channel. + */ + public function testFixedLanguageIsAlwaysUsed(): void + { + $this->configureMode('es'); + + $request = $this->createRequestWithAcceptLanguage('de-DE,de;q=0.9'); + $order = $this->createOrderWithBillingCountry('NL'); + + $this->assertSame( + 'es-ES', + $this->resolver->resolveLanguage($this->getSalesChannelContext(), $request, $order) + ); + } + + public function testFixedLanguageMapping(): void + { + foreach (['en' => 'en-US', 'nl' => 'nl-NL', 'de' => 'de-DE', 'fr' => 'fr-FR', 'es' => 'es-ES'] as $m => $c) { + $settingsService = $this->createMock(SettingsService::class); + $settingsService->method('getSetting')->willReturn($m); + $resolver = new BuckarooLanguageResolver($settingsService, new RequestStack(), $this->languageRepository); + + $this->assertSame($c, $resolver->resolveLanguage($this->getSalesChannelContext())); + } + } + + public function testBrowserLanguageIsResolved(): void + { + $this->configureMode('browser'); + + $request = $this->createRequestWithAcceptLanguage('de-DE,de;q=0.9,en;q=0.8'); + + $this->assertSame( + 'de-DE', + $this->resolver->resolveLanguage($this->getSalesChannelContext(), $request) + ); + } + + public function testBrowserLanguageWithRegionVariantMapsToSupportedCulture(): void + { + $this->configureMode('browser'); + + $request = $this->createRequestWithAcceptLanguage('nl-BE,nl;q=0.9'); + + $this->assertSame( + 'nl-NL', + $this->resolver->resolveLanguage($this->getSalesChannelContext(), $request) + ); + } + + public function testUnsupportedBrowserLanguageFallsBackToEnglish(): void + { + $this->configureMode('browser'); + + $request = $this->createRequestWithAcceptLanguage('pl-PL,pl;q=0.9'); + + $this->assertSame( + BuckarooLanguageResolver::FALLBACK_CULTURE, + $this->resolver->resolveLanguage($this->getSalesChannelContext(), $request) + ); + } + + public function testUnsupportedFirstBrowserLanguageUsesNextSupportedOne(): void + { + $this->configureMode('browser'); + + $request = $this->createRequestWithAcceptLanguage('pl-PL,fr-FR;q=0.8'); + + $this->assertSame( + 'fr-FR', + $this->resolver->resolveLanguage($this->getSalesChannelContext(), $request) + ); + } + + public function testMissingRequestFallsBackToEnglish(): void + { + $this->configureMode('browser'); + + $this->assertSame( + BuckarooLanguageResolver::FALLBACK_CULTURE, + $this->resolver->resolveLanguage($this->getSalesChannelContext()) + ); + } + + public function testBrowserModeIsUsedWhenSettingIsEmpty(): void + { + $this->configureMode(null); + + $request = $this->createRequestWithAcceptLanguage('nl-NL'); + + $this->assertSame( + 'nl-NL', + $this->resolver->resolveLanguage($this->getSalesChannelContext(), $request) + ); + } + + public function testBillingCountryIsResolvedFromOrder(): void + { + $this->configureMode('billing_country'); + + $order = $this->createOrderWithBillingCountry('NL'); + + $this->assertSame( + 'nl-NL', + $this->resolver->resolveLanguage($this->getSalesChannelContext(), null, $order) + ); + } + + public function testBillingCountryIgnoresBrowserLanguage(): void + { + $this->configureMode('billing_country'); + + $request = $this->createRequestWithAcceptLanguage('de-DE'); + $order = $this->createOrderWithBillingCountry('FR'); + + $this->assertSame( + 'fr-FR', + $this->resolver->resolveLanguage($this->getSalesChannelContext(), $request, $order) + ); + } + + public function testUnsupportedBillingCountryFallsBackToEnglish(): void + { + $this->configureMode('billing_country'); + + $order = $this->createOrderWithBillingCountry('JP'); + + $this->assertSame( + BuckarooLanguageResolver::FALLBACK_CULTURE, + $this->resolver->resolveLanguage($this->getSalesChannelContext(), null, $order) + ); + } + + public function testMissingBillingCountryFallsBackToEnglish(): void + { + $this->configureMode('billing_country'); + + $order = $this->createOrderWithBillingCountry(null); + + $this->assertSame( + BuckarooLanguageResolver::FALLBACK_CULTURE, + $this->resolver->resolveLanguage($this->getSalesChannelContext(), null, $order) + ); + } + + public function testEnglishSpeakingBillingCountryResolvesToEnglish(): void + { + $this->configureMode('billing_country'); + + $order = $this->createOrderWithBillingCountry('GB'); + + $this->assertSame( + 'en-US', + $this->resolver->resolveLanguage($this->getSalesChannelContext(), null, $order) + ); + } + + public function testSalesChannelLanguageIsResolved(): void + { + $this->configureMode('sales_channel'); + $this->mockSalesChannelLocale('fr-FR'); + + $this->assertSame( + 'fr-FR', + $this->resolver->resolveLanguage($this->getSalesChannelContext('language-id')) + ); + } + + public function testUnsupportedSalesChannelLanguageFallsBackToEnglish(): void + { + $this->configureMode('sales_channel'); + $this->mockSalesChannelLocale('pl-PL'); + + $this->assertSame( + BuckarooLanguageResolver::FALLBACK_CULTURE, + $this->resolver->resolveLanguage($this->getSalesChannelContext('language-id')) + ); + } + + public function testMissingSalesChannelLanguageFallsBackToEnglish(): void + { + $this->configureMode('sales_channel'); + $this->mockSalesChannelLocale(null); + + $this->assertSame( + BuckarooLanguageResolver::FALLBACK_CULTURE, + $this->resolver->resolveLanguage($this->getSalesChannelContext('language-id')) + ); + } +} diff --git a/tests/Unit/Service/PayPalExpressCredentialsServiceTest.php b/tests/Unit/Service/PayPalExpressCredentialsServiceTest.php new file mode 100644 index 00000000..311fa263 --- /dev/null +++ b/tests/Unit/Service/PayPalExpressCredentialsServiceTest.php @@ -0,0 +1,157 @@ +settingsService = $this->createMock(SettingsService::class); + $this->service = new PayPalExpressCredentialsService($this->settingsService); + } + + private function mockEnvironment(string $environment): void + { + $this->settingsService + ->method('getEnvironment') + ->with('paypal', self::SALES_CHANNEL_ID) + ->willReturn($environment); + } + + /** + * @param array $settings + */ + private function mockSettings(array $settings): void + { + $this->settingsService + ->method('getSetting') + ->willReturnCallback( + function (string $setting) use ($settings) { + return $settings[$setting] ?? null; + } + ); + } + + public function testIsTestModeWhenEnvironmentIsTest(): void + { + $this->mockEnvironment('test'); + + $this->assertTrue($this->service->isTestMode(self::SALES_CHANNEL_ID)); + } + + public function testIsNotTestModeWhenEnvironmentIsLive(): void + { + $this->mockEnvironment('live'); + + $this->assertFalse($this->service->isTestMode(self::SALES_CHANNEL_ID)); + } + + public function testLiveModeReturnsLiveMerchantId(): void + { + $this->mockEnvironment('live'); + $this->mockSettings([ + 'paypalExpressmerchantid' => 'live-merchant-id', + 'paypalExpressSandboxMerchantId' => 'sandbox-merchant-id', + ]); + + $this->assertSame( + 'live-merchant-id', + $this->service->getMerchantId(self::SALES_CHANNEL_ID) + ); + } + + public function testTestModeReturnsSandboxMerchantId(): void + { + $this->mockEnvironment('test'); + $this->mockSettings([ + 'paypalExpressmerchantid' => 'live-merchant-id', + 'paypalExpressSandboxMerchantId' => 'sandbox-merchant-id', + ]); + + $this->assertSame( + 'sandbox-merchant-id', + $this->service->getMerchantId(self::SALES_CHANNEL_ID) + ); + } + + public function testTestModeNeverReturnsLiveMerchantId(): void + { + $this->mockEnvironment('test'); + $this->mockSettings([ + 'paypalExpressmerchantid' => 'live-merchant-id', + ]); + + $this->assertNull($this->service->getMerchantId(self::SALES_CHANNEL_ID)); + } + + public function testEmptyOrWhitespaceSettingsReturnNull(): void + { + $this->mockEnvironment('test'); + $this->mockSettings([ + 'paypalExpressSandboxMerchantId' => ' ', + ]); + + $this->assertNull($this->service->getMerchantId(self::SALES_CHANNEL_ID)); + } + + public function testValuesAreTrimmed(): void + { + $this->mockEnvironment('test'); + $this->mockSettings([ + 'paypalExpressSandboxMerchantId' => ' sandbox-merchant-id ', + ]); + + $this->assertSame( + 'sandbox-merchant-id', + $this->service->getMerchantId(self::SALES_CHANNEL_ID) + ); + } + + public function testGetCredentialsInTestMode(): void + { + $this->mockEnvironment('test'); + $this->mockSettings([ + 'paypalExpressmerchantid' => 'live-merchant-id', + 'paypalExpressSandboxMerchantId' => 'sandbox-merchant-id', + ]); + + $this->assertSame( + [ + 'merchantId' => 'sandbox-merchant-id', + 'isTestMode' => true, + ], + $this->service->getCredentials(self::SALES_CHANNEL_ID) + ); + } + + public function testGetCredentialsInLiveMode(): void + { + $this->mockEnvironment('live'); + $this->mockSettings([ + 'paypalExpressmerchantid' => 'live-merchant-id', + 'paypalExpressSandboxMerchantId' => 'sandbox-merchant-id', + ]); + + $this->assertSame( + [ + 'merchantId' => 'live-merchant-id', + 'isTestMode' => false, + ], + $this->service->getCredentials(self::SALES_CHANNEL_ID) + ); + } +} diff --git a/tests/Unit/Service/SignatureValidationServiceTest.php b/tests/Unit/Service/SignatureValidationServiceTest.php index a9eaaf0c..bd65f4a8 100644 --- a/tests/Unit/Service/SignatureValidationServiceTest.php +++ b/tests/Unit/Service/SignatureValidationServiceTest.php @@ -250,66 +250,6 @@ public function testCalculateSignatureDecodesNonExemptFields(): void $this->assertTrue($result); } - /** - * Test: it handles knaken buyer UUID key transformation - */ - public function testCalculateSignatureTransformsKnakenBuyerUUID(): void - { - // Arrange - $secretKey = 'test-key'; - $postData = [ - 'brq_SERVICE_knaken_Buyer_UUID' => 'uuid-123', // Should be transformed to space - 'brq_amount' => '100.00' - ]; - - // Key should be transformed to 'brq_SERVICE_knaken_Buyer UUID' (with space) - $signatureString = 'brq_amount=100.00brq_SERVICE_knaken_Buyer UUID=uuid-123' . $secretKey; - $expectedSignature = sha1($signatureString); - $postData['brq_signature'] = $expectedSignature; - - $request = new Request([], $postData); - - $this->settingsService - ->method('getSetting') - ->willReturn($secretKey); - - // Act - $result = $this->signatureValidationService->validateSignature($request); - - // Assert - $this->assertTrue($result); - } - - /** - * Test: it handles knaken buyer name key transformation - */ - public function testCalculateSignatureTransformsKnakenBuyerName(): void - { - // Arrange - $secretKey = 'test-key'; - $postData = [ - 'brq_SERVICE_knaken_Buyer_Name' => 'John Doe', - 'brq_amount' => '100.00' - ]; - - // Key should be transformed to 'brq_SERVICE_knaken_Buyer Name' (with space) - $signatureString = 'brq_amount=100.00brq_SERVICE_knaken_Buyer Name=John Doe' . $secretKey; - $expectedSignature = sha1($signatureString); - $postData['brq_signature'] = $expectedSignature; - - $request = new Request([], $postData); - - $this->settingsService - ->method('getSetting') - ->willReturn($secretKey); - - // Act - $result = $this->signatureValidationService->validateSignature($request); - - // Assert - $this->assertTrue($result); - } - /** * Test: it skips non-scalar values in signature calculation */ diff --git a/tests/Unit/Storefront/Controller/PushControllerSettledStatesTest.php b/tests/Unit/Storefront/Controller/PushControllerSettledStatesTest.php new file mode 100644 index 00000000..5d0607a9 --- /dev/null +++ b/tests/Unit/Storefront/Controller/PushControllerSettledStatesTest.php @@ -0,0 +1,39 @@ +assertContains('refunded', PushController::SETTLED_PAYMENT_STATES); + $this->assertContains('partial_refunded', PushController::SETTLED_PAYMENT_STATES); + } + + public function testPaidStatesRemainSettled(): void + { + $this->assertContains('paid', PushController::SETTLED_PAYMENT_STATES); + $this->assertContains('pay_partially', PushController::SETTLED_PAYMENT_STATES); + } + + /** + * An authorization is not settled: a failure push against it is plausibly a real + * payment failure and must still be able to fail/cancel the transaction. + */ + public function testAuthorizedIsNotTreatedAsSettled(): void + { + $this->assertNotContains('authorize', PushController::SETTLED_PAYMENT_STATES); + $this->assertNotContains('authorized', PushController::SETTLED_PAYMENT_STATES); + } +} diff --git a/tests/Unit/Subscribers/OrderDeliveryWrittenSubscriberTest.php b/tests/Unit/Subscribers/OrderDeliveryWrittenSubscriberTest.php index e6783312..e4969c58 100644 --- a/tests/Unit/Subscribers/OrderDeliveryWrittenSubscriberTest.php +++ b/tests/Unit/Subscribers/OrderDeliveryWrittenSubscriberTest.php @@ -143,7 +143,8 @@ public function testIgnoresWritesWhenNewStateIsNotShipped(): void /** * stateId in payload resolves to "shipped": subscriber must delegate to * OrderStateChangeEvent::triggerCaptureForShippedOrder with the parent - * order's id, salesChannelId, and the same context. + * order's id, salesChannelId, the same context, and the payment-method + * allow list that applies to this trigger path. */ public function testDelegatesToOrderStateChangeEventWhenNewStateIsShipped(): void { @@ -169,12 +170,33 @@ public function testDelegatesToOrderStateChangeEventWhenNewStateIsShipped(): voi ->with( self::ORDER_ID, self::SALES_CHANNEL_ID, - $this->identicalTo($this->context) + $this->identicalTo($this->context), + OrderDeliveryWrittenSubscriber::CAPTURE_METHODS_ON_DAL_WRITE ); $this->subscriber->onOrderDeliveryWritten($event); } + /** + * The direct DAL write path is opt-in per payment method and must stay limited to + * Klarna MoR. Klarna KP must never be captured from this path: its reservation can + * already be FullyCaptured at Buckaroo without the plugin knowing, and a retried + * "Pay on reservation" returns 491, which PushController can turn into a cancelled + * payment state. + */ + public function testOnlyKlarnaMorIsEnabledForTheDalWritePath(): void + { + $this->assertSame( + ['klarna'], + OrderDeliveryWrittenSubscriber::CAPTURE_METHODS_ON_DAL_WRITE + ); + + $this->assertNotContains( + 'klarnakp', + OrderDeliveryWrittenSubscriber::CAPTURE_METHODS_ON_DAL_WRITE + ); + } + /** * Subscriber must swallow throwables from the downstream capture trigger * so the merchant's delivery write is never rolled back. The error must diff --git a/tests/e2e/helpers/shop.js b/tests/e2e/helpers/shop.js new file mode 100644 index 00000000..17ff1697 --- /dev/null +++ b/tests/e2e/helpers/shop.js @@ -0,0 +1,138 @@ +const { expect } = require('@playwright/test'); + +/** Pick the first option of a