Changeset 3490786
- Timestamp:
- 03/25/2026 11:01:09 AM (4 days ago)
- Location:
- peachpay-for-woocommerce
- Files:
-
- 893 added
- 16 edited
-
assets (added)
-
assets/banner-1544x500.png (added)
-
assets/banner-772x250.png (added)
-
assets/convertCartBannerLarge.png (added)
-
assets/convertCartBannerSmall.png (added)
-
assets/icon-256x256.png (added)
-
assets/screenshot-1.png (added)
-
assets/screenshot-10.png (added)
-
assets/screenshot-11.png (added)
-
assets/screenshot-2.png (added)
-
assets/screenshot-3.png (added)
-
assets/screenshot-4.png (added)
-
assets/screenshot-5.png (added)
-
assets/screenshot-6.png (added)
-
assets/screenshot-7.png (added)
-
assets/screenshot-8.png (added)
-
assets/screenshot-9.png (added)
-
tags/1.120.23 (added)
-
tags/1.120.23/LICENSE (added)
-
tags/1.120.23/changelog.txt (added)
-
tags/1.120.23/compatibility (added)
-
tags/1.120.23/compatibility/booster-for-wc (added)
-
tags/1.120.23/compatibility/booster-for-wc/booster-for-wc.php (added)
-
tags/1.120.23/compatibility/booster-for-wc/booster-product-addons.php (added)
-
tags/1.120.23/compatibility/booster-for-wc/booster-shipping-description.php (added)
-
tags/1.120.23/compatibility/class-peachpay-elementor-widget.php (added)
-
tags/1.120.23/compatibility/custom-product-boxes.php (added)
-
tags/1.120.23/compatibility/essential-addons-elementor.php (added)
-
tags/1.120.23/compatibility/perfmatters.php (added)
-
tags/1.120.23/compatibility/wc-country-based-restrictions.php (added)
-
tags/1.120.23/compatibility/wc-product-addons.php (added)
-
tags/1.120.23/compatibility/wc-product-bundles.php (added)
-
tags/1.120.23/compatibility/wc-pw-gift-cards.php (added)
-
tags/1.120.23/compatibility/wc-subscribe-all-things.php (added)
-
tags/1.120.23/compatibility/wc-subscriptions.php (added)
-
tags/1.120.23/compatibility/woocommerce-bookings.php (added)
-
tags/1.120.23/compatibility/yith-product-bundles.php (added)
-
tags/1.120.23/core (added)
-
tags/1.120.23/core/abstract (added)
-
tags/1.120.23/core/abstract/class-peachpay-admin-tab.php (added)
-
tags/1.120.23/core/abstract/class-peachpay-order-data.php (added)
-
tags/1.120.23/core/abstract/class-peachpay-payment-gateway.php (added)
-
tags/1.120.23/core/admin (added)
-
tags/1.120.23/core/admin/actions (added)
-
tags/1.120.23/core/admin/actions/apple-pay-domain-registration.php (added)
-
tags/1.120.23/core/admin/actions/connect-payments-later.php (added)
-
tags/1.120.23/core/admin/actions/saved-settings-banner.php (added)
-
tags/1.120.23/core/admin/assets (added)
-
tags/1.120.23/core/admin/assets/css (added)
-
tags/1.120.23/core/admin/assets/css/account.css (added)
-
tags/1.120.23/core/admin/assets/css/admin.css (added)
-
tags/1.120.23/core/admin/assets/css/deactivation-feedback.css (added)
-
tags/1.120.23/core/admin/assets/css/payment.css (added)
-
tags/1.120.23/core/admin/assets/css/premium.css (added)
-
tags/1.120.23/core/admin/assets/img (added)
-
tags/1.120.23/core/admin/assets/img/add-ons (added)
-
tags/1.120.23/core/admin/assets/img/add-ons/address-autocomplete.svg (added)
-
tags/1.120.23/core/admin/assets/img/add-ons/bot.svg (added)
-
tags/1.120.23/core/admin/assets/img/add-ons/checkout_window.svg (added)
-
tags/1.120.23/core/admin/assets/img/add-ons/currency_switcher.svg (added)
-
tags/1.120.23/core/admin/assets/img/add-ons/field_editor.svg (added)
-
tags/1.120.23/core/admin/assets/img/add-ons/recommended_products.svg (added)
-
tags/1.120.23/core/admin/assets/img/chevron-right.svg (added)
-
tags/1.120.23/core/admin/assets/img/logo_with_text.svg (added)
-
tags/1.120.23/core/admin/assets/img/merchant_logo_default.svg (added)
-
tags/1.120.23/core/admin/assets/img/toggle-check.svg (added)
-
tags/1.120.23/core/admin/assets/img/video.svg (added)
-
tags/1.120.23/core/admin/assets/img/videoHover.svg (added)
-
tags/1.120.23/core/admin/assets/js (added)
-
tags/1.120.23/core/admin/assets/js/heap-analytics.js (added)
-
tags/1.120.23/core/admin/assets/js/settings.js (added)
-
tags/1.120.23/core/admin/class-peachpay-account-data.php (added)
-
tags/1.120.23/core/admin/class-peachpay-account-region.php (added)
-
tags/1.120.23/core/admin/class-peachpay-admin-section.php (added)
-
tags/1.120.23/core/admin/class-peachpay-admin.php (added)
-
tags/1.120.23/core/admin/class-peachpay-onboarding-tour.php (added)
-
tags/1.120.23/core/admin/plugin-deactivation.php (added)
-
tags/1.120.23/core/admin/settings-payment.php (added)
-
tags/1.120.23/core/admin/settings.php (added)
-
tags/1.120.23/core/admin/views (added)
-
tags/1.120.23/core/admin/views/html-applepay-register-domain.php (added)
-
tags/1.120.23/core/admin/views/html-bread-crumbs.php (added)
-
tags/1.120.23/core/admin/views/html-gateway-details.php (added)
-
tags/1.120.23/core/admin/views/html-gateways.php (added)
-
tags/1.120.23/core/admin/views/html-onboarding-tour-modal.php (added)
-
tags/1.120.23/core/admin/views/html-premium-modal.php (added)
-
tags/1.120.23/core/admin/views/html-premium-portal.php (added)
-
tags/1.120.23/core/admin/views/html-primary-navigation.php (added)
-
tags/1.120.23/core/admin/views/html-secondary-navigation.php (added)
-
tags/1.120.23/core/admin/views/html-side-navigation.php (added)
-
tags/1.120.23/core/admin/views/utilities.php (added)
-
tags/1.120.23/core/apple-pay.php (added)
-
tags/1.120.23/core/class-peachpay-alert-service.php (added)
-
tags/1.120.23/core/class-peachpay-capabilities.php (added)
-
tags/1.120.23/core/class-peachpay-dependency-service.php (added)
-
tags/1.120.23/core/class-peachpay-initializer.php (added)
-
tags/1.120.23/core/class-peachpay-lifecycle-analytics.php (added)
-
tags/1.120.23/core/class-peachpay-lifecycle.php (added)
-
tags/1.120.23/core/class-peachpay-test-mode-service.php (added)
-
tags/1.120.23/core/class-peachpay.php (added)
-
tags/1.120.23/core/error-reporting.php (added)
-
tags/1.120.23/core/functions.php (added)
-
tags/1.120.23/core/migrations (added)
-
tags/1.120.23/core/migrations/migrate-button-defaults.php (added)
-
tags/1.120.23/core/migrations/migrate-button-settings.php (added)
-
tags/1.120.23/core/migrations/migrate-data-retention.php (added)
-
tags/1.120.23/core/migrations/migrate-general-settings.php (added)
-
tags/1.120.23/core/migrations/migrate-paypal.php (added)
-
tags/1.120.23/core/migrations/migrate-related-product-settings.php (added)
-
tags/1.120.23/core/migrations/migrate-settings-after-reorg-expectations.php (added)
-
tags/1.120.23/core/migrations/migrate-settings-after-reorg.php (added)
-
tags/1.120.23/core/migrations/migrate-square.php (added)
-
tags/1.120.23/core/migrations/migrate-stripe.php (added)
-
tags/1.120.23/core/migrations/migration.php (added)
-
tags/1.120.23/core/modules (added)
-
tags/1.120.23/core/modules/address-autocomplete (added)
-
tags/1.120.23/core/modules/address-autocomplete/class-peachpay-address-autocomplete-settings.php (added)
-
tags/1.120.23/core/modules/address-autocomplete/class-peachpay-address-autocomplete.php (added)
-
tags/1.120.23/core/modules/address-autocomplete/functions.php (added)
-
tags/1.120.23/core/modules/address-autocomplete/hooks.php (added)
-
tags/1.120.23/core/modules/advanced-logging (added)
-
tags/1.120.23/core/modules/advanced-logging/class-peachpay-advanced-logging-settings.php (added)
-
tags/1.120.23/core/modules/advanced-logging/class-peachpay-advanced-logging.php (added)
-
tags/1.120.23/core/modules/advanced-logging/class-peachpay-log-download.php (added)
-
tags/1.120.23/core/modules/bot-protection (added)
-
tags/1.120.23/core/modules/bot-protection/class-peachpay-bot-protection-settings.php (added)
-
tags/1.120.23/core/modules/bot-protection/class-peachpay-bot-protection.php (added)
-
tags/1.120.23/core/modules/bot-protection/functions.php (added)
-
tags/1.120.23/core/modules/bot-protection/hooks.php (added)
-
tags/1.120.23/core/modules/currency-switcher (added)
-
tags/1.120.23/core/modules/currency-switcher/admin (added)
-
tags/1.120.23/core/modules/currency-switcher/admin/assets (added)
-
tags/1.120.23/core/modules/currency-switcher/admin/assets/Property_1help_isFilledTrue.svg (added)
-
tags/1.120.23/core/modules/currency-switcher/admin/assets/currency-switcher.css (added)
-
tags/1.120.23/core/modules/currency-switcher/admin/assets/warning-sign.svg (added)
-
tags/1.120.23/core/modules/currency-switcher/admin/js (added)
-
tags/1.120.23/core/modules/currency-switcher/admin/js/dropdown.js (added)
-
tags/1.120.23/core/modules/currency-switcher/admin/js/fee-editor.js (added)
-
tags/1.120.23/core/modules/currency-switcher/admin/js/remove-row.js (added)
-
tags/1.120.23/core/modules/currency-switcher/admin/settings-currency-switcher.php (added)
-
tags/1.120.23/core/modules/currency-switcher/currency-convert.php (added)
-
tags/1.120.23/core/modules/currency-switcher/util (added)
-
tags/1.120.23/core/modules/currency-switcher/util/currency-geo.php (added)
-
tags/1.120.23/core/modules/currency-switcher/util/currency-uninstall.php (added)
-
tags/1.120.23/core/modules/currency-switcher/util/peachpay-currency-arrays.php (added)
-
tags/1.120.23/core/modules/currency-switcher/widget (added)
-
tags/1.120.23/core/modules/currency-switcher/widget/class-peachpay-currency-widget.php (added)
-
tags/1.120.23/core/modules/dashboard (added)
-
tags/1.120.23/core/modules/dashboard/settings-homepage.php (added)
-
tags/1.120.23/core/modules/express-checkout (added)
-
tags/1.120.23/core/modules/express-checkout/admin (added)
-
tags/1.120.23/core/modules/express-checkout/admin/settings-express-checkout.php (added)
-
tags/1.120.23/core/modules/express-checkout/class-peachpay-express-checkout.php (added)
-
tags/1.120.23/core/modules/express-checkout/compatibility (added)
-
tags/1.120.23/core/modules/express-checkout/compatibility/breeze.php (added)
-
tags/1.120.23/core/modules/express-checkout/compatibility/woocommerce-manual-phone-orders.php (added)
-
tags/1.120.23/core/modules/express-checkout/compatibility/wp-rocket.php (added)
-
tags/1.120.23/core/modules/express-checkout/functions.php (added)
-
tags/1.120.23/core/modules/express-checkout/hooks.php (added)
-
tags/1.120.23/core/modules/express-checkout/routes (added)
-
tags/1.120.23/core/modules/express-checkout/routes/wc-ajax-calculate-cart.php (added)
-
tags/1.120.23/core/modules/express-checkout/routes/wc-ajax-change-quantity.php (added)
-
tags/1.120.23/core/modules/express-checkout/routes/wc-ajax-validate-checkout.php (added)
-
tags/1.120.23/core/modules/express-checkout/routes/wp-ajax-checkout-enable.php (added)
-
tags/1.120.23/core/modules/express-checkout/routes/wp-ajax-login.php (added)
-
tags/1.120.23/core/modules/express-checkout/sections (added)
-
tags/1.120.23/core/modules/express-checkout/sections/advanced.php (added)
-
tags/1.120.23/core/modules/express-checkout/sections/branding.php (added)
-
tags/1.120.23/core/modules/express-checkout/sections/checkout-button.php (added)
-
tags/1.120.23/core/modules/express-checkout/sections/checkout-window.php (added)
-
tags/1.120.23/core/modules/express-checkout/sections/product-recommendations.php (added)
-
tags/1.120.23/core/modules/express-checkout/shortcodes (added)
-
tags/1.120.23/core/modules/express-checkout/shortcodes/shortcode-checkout-button.php (added)
-
tags/1.120.23/core/modules/express-checkout/templates (added)
-
tags/1.120.23/core/modules/express-checkout/templates/html-express-checkout.php (added)
-
tags/1.120.23/core/modules/express-checkout/util (added)
-
tags/1.120.23/core/modules/express-checkout/util/class-peachpay-wc-checkout.php (added)
-
tags/1.120.23/core/modules/field-editor (added)
-
tags/1.120.23/core/modules/field-editor/admin (added)
-
tags/1.120.23/core/modules/field-editor/admin/assets (added)
-
tags/1.120.23/core/modules/field-editor/admin/assets/field-editor.css (added)
-
tags/1.120.23/core/modules/field-editor/admin/assets/field-editor.js (added)
-
tags/1.120.23/core/modules/field-editor/admin/settings-field-editor.php (added)
-
tags/1.120.23/core/modules/field-editor/assets (added)
-
tags/1.120.23/core/modules/field-editor/assets/css (added)
-
tags/1.120.23/core/modules/field-editor/assets/css/field-types.css (added)
-
tags/1.120.23/core/modules/field-editor/assets/js (added)
-
tags/1.120.23/core/modules/field-editor/assets/js/field-types.js (added)
-
tags/1.120.23/core/modules/field-editor/assets/js/signature_pad.min.js (added)
-
tags/1.120.23/core/modules/field-editor/field-editor.php (added)
-
tags/1.120.23/core/modules/field-editor/pp-field-editor-functions.php (added)
-
tags/1.120.23/core/modules/module.php (added)
-
tags/1.120.23/core/modules/one-click-upsell (added)
-
tags/1.120.23/core/modules/one-click-upsell/assets (added)
-
tags/1.120.23/core/modules/one-click-upsell/assets/class-peachpay-ajax-product-search.php (added)
-
tags/1.120.23/core/modules/one-click-upsell/assets/peachpay_product_search_script.js (added)
-
tags/1.120.23/core/modules/recommended-products (added)
-
tags/1.120.23/core/modules/recommended-products/admin (added)
-
tags/1.120.23/core/modules/recommended-products/admin/settings-recommended-products.php (added)
-
tags/1.120.23/core/modules/recommended-products/assets (added)
-
tags/1.120.23/core/modules/recommended-products/assets/pp-related-products.css (added)
-
tags/1.120.23/core/modules/recommended-products/includes (added)
-
tags/1.120.23/core/modules/recommended-products/includes/class-peachpay-related-products-loader.php (added)
-
tags/1.120.23/core/modules/recommended-products/includes/class-peachpay-related-products.php (added)
-
tags/1.120.23/core/modules/recommended-products/pp-related-products.php (added)
-
tags/1.120.23/core/modules/recommended-products/public (added)
-
tags/1.120.23/core/modules/recommended-products/public/class-peachpay-related-products-public.php (added)
-
tags/1.120.23/core/modules/recommended-products/public/css (added)
-
tags/1.120.23/core/modules/recommended-products/public/css/woo-related-products-public.css (added)
-
tags/1.120.23/core/modules/recommended-products/public/index.php (added)
-
tags/1.120.23/core/modules/recommended-products/public/js (added)
-
tags/1.120.23/core/modules/recommended-products/public/js/woo-related-products-public.js (added)
-
tags/1.120.23/core/modules/recommended-products/public/owl-carousel (added)
-
tags/1.120.23/core/modules/recommended-products/public/owl-carousel/AjaxLoader.gif (added)
-
tags/1.120.23/core/modules/recommended-products/public/owl-carousel/grabbing.png (added)
-
tags/1.120.23/core/modules/recommended-products/public/owl-carousel/owl.carousel.css (added)
-
tags/1.120.23/core/modules/recommended-products/public/owl-carousel/owl.carousel.js (added)
-
tags/1.120.23/core/modules/recommended-products/public/owl-carousel/owl.carousel.min.js (added)
-
tags/1.120.23/core/modules/recommended-products/public/owl-carousel/owl.theme.css (added)
-
tags/1.120.23/core/modules/recommended-products/public/owl-carousel/owl.transitions.css (added)
-
tags/1.120.23/core/payments (added)
-
tags/1.120.23/core/payments/authnet (added)
-
tags/1.120.23/core/payments/authnet/abstract (added)
-
tags/1.120.23/core/payments/authnet/abstract/class-peachpay-authnet-payment-gateway.php (added)
-
tags/1.120.23/core/payments/authnet/admin (added)
-
tags/1.120.23/core/payments/authnet/admin/assets (added)
-
tags/1.120.23/core/payments/authnet/admin/assets/img (added)
-
tags/1.120.23/core/payments/authnet/admin/assets/img/authnet-logo.svg (added)
-
tags/1.120.23/core/payments/authnet/admin/tabs (added)
-
tags/1.120.23/core/payments/authnet/admin/tabs/class-peachpay-authnet-advanced.php (added)
-
tags/1.120.23/core/payments/authnet/admin/views (added)
-
tags/1.120.23/core/payments/authnet/admin/views/html-authnet-capture-void.php (added)
-
tags/1.120.23/core/payments/authnet/admin/views/html-authnet-connect.php (added)
-
tags/1.120.23/core/payments/authnet/admin/views/html-authnet-payment-page.php (added)
-
tags/1.120.23/core/payments/authnet/admin/views/html-authnet-transaction-details.php (added)
-
tags/1.120.23/core/payments/authnet/class-peachpay-authnet-integration.php (added)
-
tags/1.120.23/core/payments/authnet/functions.php (added)
-
tags/1.120.23/core/payments/authnet/gateways (added)
-
tags/1.120.23/core/payments/authnet/gateways/class-peachpay-authnet-card-gateway.php (added)
-
tags/1.120.23/core/payments/authnet/gateways/class-peachpay-authnet-echeck-gateway.php (added)
-
tags/1.120.23/core/payments/authnet/hooks.php (added)
-
tags/1.120.23/core/payments/authnet/routes (added)
-
tags/1.120.23/core/payments/authnet/routes/authnet-webhook.php (added)
-
tags/1.120.23/core/payments/authnet/traits (added)
-
tags/1.120.23/core/payments/authnet/traits/trait-authnet-gateway-settings.php (added)
-
tags/1.120.23/core/payments/authnet/traits/trait-authnet-gateway-utilities.php (added)
-
tags/1.120.23/core/payments/authnet/utils (added)
-
tags/1.120.23/core/payments/authnet/utils/class-peachpay-authnet-order-data.php (added)
-
tags/1.120.23/core/payments/authnet/utils/class-peachpay-authnet.php (added)
-
tags/1.120.23/core/payments/class-peachpay-payment.php (added)
-
tags/1.120.23/core/payments/convesiopay (added)
-
tags/1.120.23/core/payments/convesiopay/admin (added)
-
tags/1.120.23/core/payments/convesiopay/admin/assets (added)
-
tags/1.120.23/core/payments/convesiopay/admin/assets/js (added)
-
tags/1.120.23/core/payments/convesiopay/admin/assets/js/fetch-payment-status-manually.js (added)
-
tags/1.120.23/core/payments/convesiopay/admin/assets/js/manual-capture.js (added)
-
tags/1.120.23/core/payments/convesiopay/admin/class-peachpay-admin-convesiopay-integration.php (added)
-
tags/1.120.23/core/payments/convesiopay/admin/class-peachpay-convesiopay-fetch-payment-status-manually.php (added)
-
tags/1.120.23/core/payments/convesiopay/admin/class-peachpay-convesiopay-manual-capture.php (added)
-
tags/1.120.23/core/payments/convesiopay/admin/views (added)
-
tags/1.120.23/core/payments/convesiopay/admin/views/html-convesiopay-connect.php (added)
-
tags/1.120.23/core/payments/convesiopay/assets (added)
-
tags/1.120.23/core/payments/convesiopay/assets/js (added)
-
tags/1.120.23/core/payments/convesiopay/assets/js/admin-payment-methods.js (added)
-
tags/1.120.23/core/payments/convesiopay/assets/js/applepay-blocks.js (added)
-
tags/1.120.23/core/payments/convesiopay/assets/js/applepay.js (added)
-
tags/1.120.23/core/payments/convesiopay/assets/js/blocks.js (added)
-
tags/1.120.23/core/payments/convesiopay/assets/js/btcpay-blocks.js (added)
-
tags/1.120.23/core/payments/convesiopay/assets/js/checkout.js (added)
-
tags/1.120.23/core/payments/convesiopay/assets/js/convesiopay-unified-blocks.js (added)
-
tags/1.120.23/core/payments/convesiopay/assets/js/convesiopay-unified-classic.js (added)
-
tags/1.120.23/core/payments/convesiopay/class-peachpay-convesiopay-integration.php (added)
-
tags/1.120.23/core/payments/convesiopay/functions.php (added)
-
tags/1.120.23/core/payments/convesiopay/gateways (added)
-
tags/1.120.23/core/payments/convesiopay/gateways/class-peachpay-convesiopay-applepay-gateway.php (added)
-
tags/1.120.23/core/payments/convesiopay/gateways/class-peachpay-convesiopay-btcpay-gateway.php (added)
-
tags/1.120.23/core/payments/convesiopay/gateways/class-peachpay-convesiopay-card-gateway.php (added)
-
tags/1.120.23/core/payments/convesiopay/gateways/class-peachpay-convesiopay-unified-gateway.php (added)
-
tags/1.120.23/core/payments/convesiopay/hooks.php (added)
-
tags/1.120.23/core/payments/convesiopay/includes (added)
-
tags/1.120.23/core/payments/convesiopay/includes/class-convesiopay-applepay-blocks-support.php (added)
-
tags/1.120.23/core/payments/convesiopay/includes/class-convesiopay-blocks-support.php (added)
-
tags/1.120.23/core/payments/convesiopay/includes/class-convesiopay-btcpay-blocks-support.php (added)
-
tags/1.120.23/core/payments/convesiopay/includes/class-convesiopay-unified-blocks-support.php (added)
-
tags/1.120.23/core/payments/convesiopay/includes/peachpay-functions.php (added)
-
tags/1.120.23/core/payments/convesiopay/routes (added)
-
tags/1.120.23/core/payments/convesiopay/routes/class-peachpay-convesiopay-reconciliation.php (added)
-
tags/1.120.23/core/payments/convesiopay/routes/class-peachpay-convesiopay-webhook.php (added)
-
tags/1.120.23/core/payments/nmi (added)
-
tags/1.120.23/core/payments/nmi/admin (added)
-
tags/1.120.23/core/payments/nmi/admin/assets (added)
-
tags/1.120.23/core/payments/nmi/admin/assets/css (added)
-
tags/1.120.23/core/payments/nmi/admin/assets/css/admin.css (added)
-
tags/1.120.23/core/payments/nmi/admin/class-peachpay-admin-nmi-integration.php (added)
-
tags/1.120.23/core/payments/nmi/admin/class-peachpay-nmi-manual-capture.php (added)
-
tags/1.120.23/core/payments/nmi/admin/views (added)
-
tags/1.120.23/core/payments/nmi/admin/views/html-nmi-connect.php (added)
-
tags/1.120.23/core/payments/nmi/assets (added)
-
tags/1.120.23/core/payments/nmi/assets/css (added)
-
tags/1.120.23/core/payments/nmi/assets/css/checkout.css (added)
-
tags/1.120.23/core/payments/nmi/assets/js (added)
-
tags/1.120.23/core/payments/nmi/assets/js/blocks.js (added)
-
tags/1.120.23/core/payments/nmi/assets/js/checkout.js (added)
-
tags/1.120.23/core/payments/nmi/class-peachpay-nmi-integration.php (added)
-
tags/1.120.23/core/payments/nmi/functions.php (added)
-
tags/1.120.23/core/payments/nmi/gateways (added)
-
tags/1.120.23/core/payments/nmi/gateways/class-peachpay-nmi-card-gateway.php (added)
-
tags/1.120.23/core/payments/nmi/hooks.php (added)
-
tags/1.120.23/core/payments/nmi/includes (added)
-
tags/1.120.23/core/payments/nmi/includes/class-nmi-blocks-support.php (added)
-
tags/1.120.23/core/payments/nmi/includes/class-peachpay-nmi-direct-post.php (added)
-
tags/1.120.23/core/payments/nmi/includes/peachpay-functions.php (added)
-
tags/1.120.23/core/payments/paypal (added)
-
tags/1.120.23/core/payments/paypal/abstract (added)
-
tags/1.120.23/core/payments/paypal/abstract/class-peachpay-paypal-payment-gateway.php (added)
-
tags/1.120.23/core/payments/paypal/admin (added)
-
tags/1.120.23/core/payments/paypal/admin/assets (added)
-
tags/1.120.23/core/payments/paypal/admin/assets/img (added)
-
tags/1.120.23/core/payments/paypal/admin/assets/img/paypal-logo.svg (added)
-
tags/1.120.23/core/payments/paypal/admin/tabs (added)
-
tags/1.120.23/core/payments/paypal/admin/tabs/class-peachpay-paypal-advanced.php (added)
-
tags/1.120.23/core/payments/paypal/admin/views (added)
-
tags/1.120.23/core/payments/paypal/admin/views/html-paypal-connect.php (added)
-
tags/1.120.23/core/payments/paypal/admin/views/html-paypal-payment-info.php (added)
-
tags/1.120.23/core/payments/paypal/admin/views/html-paypal-payment-page.php (added)
-
tags/1.120.23/core/payments/paypal/admin/views/html-paypal-transaction-fees.php (added)
-
tags/1.120.23/core/payments/paypal/class-peachpay-paypal-integration.php (added)
-
tags/1.120.23/core/payments/paypal/functions.php (added)
-
tags/1.120.23/core/payments/paypal/gateways (added)
-
tags/1.120.23/core/payments/paypal/gateways/class-peachpay-paypal-card-gateway.php (added)
-
tags/1.120.23/core/payments/paypal/gateways/class-peachpay-paypal-credit-gateway.php (added)
-
tags/1.120.23/core/payments/paypal/gateways/class-peachpay-paypal-paylater-gateway.php (added)
-
tags/1.120.23/core/payments/paypal/gateways/class-peachpay-paypal-venmo-gateway.php (added)
-
tags/1.120.23/core/payments/paypal/gateways/class-peachpay-paypal-wallet-gateway.php (added)
-
tags/1.120.23/core/payments/paypal/hooks.php (added)
-
tags/1.120.23/core/payments/paypal/traits (added)
-
tags/1.120.23/core/payments/paypal/traits/trait-paypal-gateway-settings.php (added)
-
tags/1.120.23/core/payments/paypal/traits/trait-paypal-gateway-utilities.php (added)
-
tags/1.120.23/core/payments/paypal/utils (added)
-
tags/1.120.23/core/payments/paypal/utils/class-peachpay-paypal-order-data.php (added)
-
tags/1.120.23/core/payments/paypal/utils/class-peachpay-paypal.php (added)
-
tags/1.120.23/core/payments/peachpay (added)
-
tags/1.120.23/core/payments/peachpay/admin (added)
-
tags/1.120.23/core/payments/peachpay/admin/class-peachpay-payments-admin-integration.php (added)
-
tags/1.120.23/core/payments/peachpay/class-peachpay-payments-integration.php (added)
-
tags/1.120.23/core/payments/peachpay/gateways (added)
-
tags/1.120.23/core/payments/peachpay/gateways/class-peachpay-purchase-order-gateway.php (added)
-
tags/1.120.23/core/payments/square (added)
-
tags/1.120.23/core/payments/square/abstract (added)
-
tags/1.120.23/core/payments/square/abstract/class-peachpay-square-payment-gateway.php (added)
-
tags/1.120.23/core/payments/square/admin (added)
-
tags/1.120.23/core/payments/square/admin/assets (added)
-
tags/1.120.23/core/payments/square/admin/assets/square-logo.png (added)
-
tags/1.120.23/core/payments/square/admin/class-peachpay-admin-square-integration.php (added)
-
tags/1.120.23/core/payments/square/admin/views (added)
-
tags/1.120.23/core/payments/square/admin/views/html-square-connect.php (added)
-
tags/1.120.23/core/payments/square/apple-developer-merchantid-domain-association (added)
-
tags/1.120.23/core/payments/square/blocks (added)
-
tags/1.120.23/core/payments/square/blocks/class-peachpay-square-ach-gateway-blocks-support.php (added)
-
tags/1.120.23/core/payments/square/blocks/class-peachpay-square-afterpay-gateway-blocks-support.php (added)
-
tags/1.120.23/core/payments/square/blocks/class-peachpay-square-card-gateway-blocks-support.php (added)
-
tags/1.120.23/core/payments/square/blocks/class-peachpay-square-googlepay-gateway-blocks-support.php (added)
-
tags/1.120.23/core/payments/square/class-peachpay-square-integration.php (added)
-
tags/1.120.23/core/payments/square/functions.php (added)
-
tags/1.120.23/core/payments/square/gateways (added)
-
tags/1.120.23/core/payments/square/gateways/class-peachpay-square-ach-gateway.php (added)
-
tags/1.120.23/core/payments/square/gateways/class-peachpay-square-afterpay-gateway.php (added)
-
tags/1.120.23/core/payments/square/gateways/class-peachpay-square-applepay-gateway.php (added)
-
tags/1.120.23/core/payments/square/gateways/class-peachpay-square-card-gateway.php (added)
-
tags/1.120.23/core/payments/square/gateways/class-peachpay-square-cashapp-gateway.php (added)
-
tags/1.120.23/core/payments/square/gateways/class-peachpay-square-googlepay-gateway.php (added)
-
tags/1.120.23/core/payments/square/hooks.php (added)
-
tags/1.120.23/core/payments/square/tokens (added)
-
tags/1.120.23/core/payments/square/tokens/class-wc-payment-token-peachpay-square-card.php (added)
-
tags/1.120.23/core/payments/square/utils (added)
-
tags/1.120.23/core/payments/square/utils/class-peachpay-square-order-data.php (added)
-
tags/1.120.23/core/payments/square/utils/class-peachpay-square.php (added)
-
tags/1.120.23/core/payments/stripe (added)
-
tags/1.120.23/core/payments/stripe/abstract (added)
-
tags/1.120.23/core/payments/stripe/abstract/class-peachpay-stripe-payment-gateway.php (added)
-
tags/1.120.23/core/payments/stripe/admin (added)
-
tags/1.120.23/core/payments/stripe/admin/assets (added)
-
tags/1.120.23/core/payments/stripe/admin/assets/img (added)
-
tags/1.120.23/core/payments/stripe/admin/assets/img/stripe-logo.svg (added)
-
tags/1.120.23/core/payments/stripe/admin/class-peachpay-admin-stripe-integration.php (added)
-
tags/1.120.23/core/payments/stripe/admin/tabs (added)
-
tags/1.120.23/core/payments/stripe/admin/tabs/class-peachpay-stripe-advanced.php (added)
-
tags/1.120.23/core/payments/stripe/admin/views (added)
-
tags/1.120.23/core/payments/stripe/admin/views/html-stripe-capture-void-form.php (added)
-
tags/1.120.23/core/payments/stripe/admin/views/html-stripe-connect.php (added)
-
tags/1.120.23/core/payments/stripe/admin/views/html-stripe-payment-info.php (added)
-
tags/1.120.23/core/payments/stripe/admin/views/html-stripe-transaction-fees.php (added)
-
tags/1.120.23/core/payments/stripe/apple-developer-merchantid-domain-association (added)
-
tags/1.120.23/core/payments/stripe/blocks (added)
-
tags/1.120.23/core/payments/stripe/blocks/class-peachpay-stripe-achdebit-payment-blocks-support.php (added)
-
tags/1.120.23/core/payments/stripe/blocks/class-peachpay-stripe-affirm-payment-blocks-support.php (added)
-
tags/1.120.23/core/payments/stripe/blocks/class-peachpay-stripe-afterpay-payment-blocks-support.php (added)
-
tags/1.120.23/core/payments/stripe/blocks/class-peachpay-stripe-bancontact-payment-blocks-support.php (added)
-
tags/1.120.23/core/payments/stripe/blocks/class-peachpay-stripe-card-payment-blocks-support.php (added)
-
tags/1.120.23/core/payments/stripe/blocks/class-peachpay-stripe-eps-payment-blocks-support.php (added)
-
tags/1.120.23/core/payments/stripe/blocks/class-peachpay-stripe-giropay-payment-blocks-support.php (added)
-
tags/1.120.23/core/payments/stripe/blocks/class-peachpay-stripe-googlepay-payment-blocks-support.php (added)
-
tags/1.120.23/core/payments/stripe/blocks/class-peachpay-stripe-ideal-payment-blocks-support.php (added)
-
tags/1.120.23/core/payments/stripe/blocks/class-peachpay-stripe-klarna-payment-blocks-support.php (added)
-
tags/1.120.23/core/payments/stripe/blocks/class-peachpay-stripe-p24-payment-blocks-support.php (added)
-
tags/1.120.23/core/payments/stripe/blocks/class-peachpay-stripe-sepadebit-gateway-blocks-support.php (added)
-
tags/1.120.23/core/payments/stripe/blocks/class-peachpay-stripe-sofort-payment-blocks-support.php (added)
-
tags/1.120.23/core/payments/stripe/class-peachpay-stripe-credentials.php (added)
-
tags/1.120.23/core/payments/stripe/class-peachpay-stripe-integration.php (added)
-
tags/1.120.23/core/payments/stripe/functions.php (added)
-
tags/1.120.23/core/payments/stripe/gateways (added)
-
tags/1.120.23/core/payments/stripe/gateways/class-peachpay-stripe-achdebit-gateway.php (added)
-
tags/1.120.23/core/payments/stripe/gateways/class-peachpay-stripe-affirm-gateway.php (added)
-
tags/1.120.23/core/payments/stripe/gateways/class-peachpay-stripe-afterpay-gateway.php (added)
-
tags/1.120.23/core/payments/stripe/gateways/class-peachpay-stripe-applepay-gateway.php (added)
-
tags/1.120.23/core/payments/stripe/gateways/class-peachpay-stripe-bancontact-gateway.php (added)
-
tags/1.120.23/core/payments/stripe/gateways/class-peachpay-stripe-card-gateway.php (added)
-
tags/1.120.23/core/payments/stripe/gateways/class-peachpay-stripe-eps-gateway.php (added)
-
tags/1.120.23/core/payments/stripe/gateways/class-peachpay-stripe-giropay-gateway.php (added)
-
tags/1.120.23/core/payments/stripe/gateways/class-peachpay-stripe-googlepay-gateway.php (added)
-
tags/1.120.23/core/payments/stripe/gateways/class-peachpay-stripe-ideal-gateway.php (added)
-
tags/1.120.23/core/payments/stripe/gateways/class-peachpay-stripe-klarna-gateway.php (added)
-
tags/1.120.23/core/payments/stripe/gateways/class-peachpay-stripe-p24-gateway.php (added)
-
tags/1.120.23/core/payments/stripe/gateways/class-peachpay-stripe-sepadebit-gateway.php (added)
-
tags/1.120.23/core/payments/stripe/gateways/class-peachpay-stripe-sofort-gateway.php (added)
-
tags/1.120.23/core/payments/stripe/hooks.php (added)
-
tags/1.120.23/core/payments/stripe/routes (added)
-
tags/1.120.23/core/payments/stripe/routes/stripe-webhook.php (added)
-
tags/1.120.23/core/payments/stripe/tokens (added)
-
tags/1.120.23/core/payments/stripe/tokens/class-wc-payment-token-peachpay-stripe-achdebit.php (added)
-
tags/1.120.23/core/payments/stripe/tokens/class-wc-payment-token-peachpay-stripe-card.php (added)
-
tags/1.120.23/core/payments/stripe/traits (added)
-
tags/1.120.23/core/payments/stripe/traits/trait-stripe-gateway-utilities.php (added)
-
tags/1.120.23/core/payments/stripe/utils (added)
-
tags/1.120.23/core/payments/stripe/utils/class-peachpay-stripe-order-data.php (added)
-
tags/1.120.23/core/payments/stripe/utils/class-peachpay-stripe.php (added)
-
tags/1.120.23/core/peachpay-default-options.php (added)
-
tags/1.120.23/core/routes (added)
-
tags/1.120.23/core/routes/class-peachpay-routes-manager.php (added)
-
tags/1.120.23/core/routes/ocu-product-data.php (added)
-
tags/1.120.23/core/routes/order-payment-status.php (added)
-
tags/1.120.23/core/routes/wc-ajax-create-transaction.php (added)
-
tags/1.120.23/core/routes/wc-ajax-update-transaction.php (added)
-
tags/1.120.23/core/traits (added)
-
tags/1.120.23/core/traits/trait-peachpay-admin-extension.php (added)
-
tags/1.120.23/core/traits/trait-peachpay-extension.php (added)
-
tags/1.120.23/core/traits/trait-peachpay-payment-integration.php (added)
-
tags/1.120.23/core/traits/trait-peachpay-singleton.php (added)
-
tags/1.120.23/core/util (added)
-
tags/1.120.23/core/util/button.php (added)
-
tags/1.120.23/core/util/cart.php (added)
-
tags/1.120.23/core/util/currency.php (added)
-
tags/1.120.23/core/util/environment.php (added)
-
tags/1.120.23/core/util/language.php (added)
-
tags/1.120.23/core/util/logger.php (added)
-
tags/1.120.23/core/util/order.php (added)
-
tags/1.120.23/core/util/plugin.php (added)
-
tags/1.120.23/core/util/product.php (added)
-
tags/1.120.23/core/util/shipping.php (added)
-
tags/1.120.23/core/util/string.php (added)
-
tags/1.120.23/core/util/translation.php (added)
-
tags/1.120.23/core/util/url.php (added)
-
tags/1.120.23/core/util/util.php (added)
-
tags/1.120.23/index.php (added)
-
tags/1.120.23/languages (added)
-
tags/1.120.23/languages/peachpay-for-woocommerce-ar.mo (added)
-
tags/1.120.23/languages/peachpay-for-woocommerce-ar.po (added)
-
tags/1.120.23/languages/peachpay-for-woocommerce-bg_BG.mo (added)
-
tags/1.120.23/languages/peachpay-for-woocommerce-bg_BG.po (added)
-
tags/1.120.23/languages/peachpay-for-woocommerce-bs_BA.mo (added)
-
tags/1.120.23/languages/peachpay-for-woocommerce-bs_BA.po (added)
-
tags/1.120.23/languages/peachpay-for-woocommerce-ca.mo (added)
-
tags/1.120.23/languages/peachpay-for-woocommerce-ca.po (added)
-
tags/1.120.23/languages/peachpay-for-woocommerce-cs_CZ.mo (added)
-
tags/1.120.23/languages/peachpay-for-woocommerce-cs_CZ.po (added)
-
tags/1.120.23/languages/peachpay-for-woocommerce-da_DK.mo (added)
-
tags/1.120.23/languages/peachpay-for-woocommerce-da_DK.po (added)
-
tags/1.120.23/languages/peachpay-for-woocommerce-de_DE.mo (added)
-
tags/1.120.23/languages/peachpay-for-woocommerce-de_DE.po (added)
-
tags/1.120.23/languages/peachpay-for-woocommerce-el.mo (added)
-
tags/1.120.23/languages/peachpay-for-woocommerce-el.po (added)
-
tags/1.120.23/languages/peachpay-for-woocommerce-es_AR.mo (added)
-
tags/1.120.23/languages/peachpay-for-woocommerce-es_AR.po (added)
-
tags/1.120.23/languages/peachpay-for-woocommerce-es_CL.mo (added)
-
tags/1.120.23/languages/peachpay-for-woocommerce-es_CL.po (added)
-
tags/1.120.23/languages/peachpay-for-woocommerce-es_CO.mo (added)
-
tags/1.120.23/languages/peachpay-for-woocommerce-es_CO.po (added)
-
tags/1.120.23/languages/peachpay-for-woocommerce-es_CR.mo (added)
-
tags/1.120.23/languages/peachpay-for-woocommerce-es_CR.po (added)
-
tags/1.120.23/languages/peachpay-for-woocommerce-es_DO.mo (added)
-
tags/1.120.23/languages/peachpay-for-woocommerce-es_DO.po (added)
-
tags/1.120.23/languages/peachpay-for-woocommerce-es_EC.mo (added)
-
tags/1.120.23/languages/peachpay-for-woocommerce-es_EC.po (added)
-
tags/1.120.23/languages/peachpay-for-woocommerce-es_ES.mo (added)
-
tags/1.120.23/languages/peachpay-for-woocommerce-es_ES.po (added)
-
tags/1.120.23/languages/peachpay-for-woocommerce-es_GT.mo (added)
-
tags/1.120.23/languages/peachpay-for-woocommerce-es_GT.po (added)
-
tags/1.120.23/languages/peachpay-for-woocommerce-es_HN.mo (added)
-
tags/1.120.23/languages/peachpay-for-woocommerce-es_HN.po (added)
-
tags/1.120.23/languages/peachpay-for-woocommerce-es_MX.mo (added)
-
tags/1.120.23/languages/peachpay-for-woocommerce-es_MX.po (added)
-
tags/1.120.23/languages/peachpay-for-woocommerce-es_PE.mo (added)
-
tags/1.120.23/languages/peachpay-for-woocommerce-es_PE.po (added)
-
tags/1.120.23/languages/peachpay-for-woocommerce-es_PR.mo (added)
-
tags/1.120.23/languages/peachpay-for-woocommerce-es_PR.po (added)
-
tags/1.120.23/languages/peachpay-for-woocommerce-es_UY.mo (added)
-
tags/1.120.23/languages/peachpay-for-woocommerce-es_UY.po (added)
-
tags/1.120.23/languages/peachpay-for-woocommerce-es_VE.mo (added)
-
tags/1.120.23/languages/peachpay-for-woocommerce-es_VE.po (added)
-
tags/1.120.23/languages/peachpay-for-woocommerce-fr_FR.mo (added)
-
tags/1.120.23/languages/peachpay-for-woocommerce-fr_FR.po (added)
-
tags/1.120.23/languages/peachpay-for-woocommerce-hi_IN.mo (added)
-
tags/1.120.23/languages/peachpay-for-woocommerce-hi_IN.po (added)
-
tags/1.120.23/languages/peachpay-for-woocommerce-it_IT.mo (added)
-
tags/1.120.23/languages/peachpay-for-woocommerce-it_IT.po (added)
-
tags/1.120.23/languages/peachpay-for-woocommerce-ja.mo (added)
-
tags/1.120.23/languages/peachpay-for-woocommerce-ja.po (added)
-
tags/1.120.23/languages/peachpay-for-woocommerce-ko_KR.mo (added)
-
tags/1.120.23/languages/peachpay-for-woocommerce-ko_KR.po (added)
-
tags/1.120.23/languages/peachpay-for-woocommerce-lb_LU.mo (added)
-
tags/1.120.23/languages/peachpay-for-woocommerce-lb_LU.po (added)
-
tags/1.120.23/languages/peachpay-for-woocommerce-nl_NL.mo (added)
-
tags/1.120.23/languages/peachpay-for-woocommerce-nl_NL.po (added)
-
tags/1.120.23/languages/peachpay-for-woocommerce-pt_PT.mo (added)
-
tags/1.120.23/languages/peachpay-for-woocommerce-pt_PT.po (added)
-
tags/1.120.23/languages/peachpay-for-woocommerce-ro_RO.mo (added)
-
tags/1.120.23/languages/peachpay-for-woocommerce-ro_RO.po (added)
-
tags/1.120.23/languages/peachpay-for-woocommerce-ru_RU.mo (added)
-
tags/1.120.23/languages/peachpay-for-woocommerce-ru_RU.po (added)
-
tags/1.120.23/languages/peachpay-for-woocommerce-sl_SI.mo (added)
-
tags/1.120.23/languages/peachpay-for-woocommerce-sl_SI.po (added)
-
tags/1.120.23/languages/peachpay-for-woocommerce-sv_SE.mo (added)
-
tags/1.120.23/languages/peachpay-for-woocommerce-sv_SE.po (added)
-
tags/1.120.23/languages/peachpay-for-woocommerce-th.mo (added)
-
tags/1.120.23/languages/peachpay-for-woocommerce-th.po (added)
-
tags/1.120.23/languages/peachpay-for-woocommerce-uk.mo (added)
-
tags/1.120.23/languages/peachpay-for-woocommerce-uk.po (added)
-
tags/1.120.23/languages/peachpay-for-woocommerce-zh-CN.mo (added)
-
tags/1.120.23/languages/peachpay-for-woocommerce-zh-CN.po (added)
-
tags/1.120.23/languages/peachpay-for-woocommerce-zh-TW.mo (added)
-
tags/1.120.23/languages/peachpay-for-woocommerce-zh-TW.po (added)
-
tags/1.120.23/languages/peachpay-for-woocommerce.pot (added)
-
tags/1.120.23/peachpay.php (added)
-
tags/1.120.23/public (added)
-
tags/1.120.23/public/dist (added)
-
tags/1.120.23/public/dist/386-02c5fdaa3b3eb9e9f003.js (added)
-
tags/1.120.23/public/dist/386-02c5fdaa3b3eb9e9f003.js.map (added)
-
tags/1.120.23/public/dist/513-ee1bffbf9d362217f8af.js (added)
-
tags/1.120.23/public/dist/513-ee1bffbf9d362217f8af.js.map (added)
-
tags/1.120.23/public/dist/581-ed96323c8b06e773164e.js (added)
-
tags/1.120.23/public/dist/581-ed96323c8b06e773164e.js.map (added)
-
tags/1.120.23/public/dist/843-b2572d02e46e651827a2.js (added)
-
tags/1.120.23/public/dist/843-b2572d02e46e651827a2.js.map (added)
-
tags/1.120.23/public/dist/add-payment-method.bundle.js (added)
-
tags/1.120.23/public/dist/add-payment-method.bundle.js.map (added)
-
tags/1.120.23/public/dist/admin.bundle.css (added)
-
tags/1.120.23/public/dist/admin.bundle.css.map (added)
-
tags/1.120.23/public/dist/admin.bundle.js (added)
-
tags/1.120.23/public/dist/admin.bundle.js.map (added)
-
tags/1.120.23/public/dist/currency-switcher-widget.bundle.js (added)
-
tags/1.120.23/public/dist/currency-switcher-widget.bundle.js.map (added)
-
tags/1.120.23/public/dist/deactivation-feedback.bundle.js (added)
-
tags/1.120.23/public/dist/deactivation-feedback.bundle.js.map (added)
-
tags/1.120.23/public/dist/express-checkout (added)
-
tags/1.120.23/public/dist/express-checkout-button.bundle.css (added)
-
tags/1.120.23/public/dist/express-checkout-button.bundle.css.map (added)
-
tags/1.120.23/public/dist/express-checkout-button.bundle.js (added)
-
tags/1.120.23/public/dist/express-checkout-button.bundle.js.map (added)
-
tags/1.120.23/public/dist/express-checkout-css.bundle.css (added)
-
tags/1.120.23/public/dist/express-checkout-css.bundle.css.map (added)
-
tags/1.120.23/public/dist/express-checkout-css.js (added)
-
tags/1.120.23/public/dist/express-checkout-js.bundle.js (added)
-
tags/1.120.23/public/dist/express-checkout-js.bundle.js.map (added)
-
tags/1.120.23/public/dist/express-checkout/block.json (added)
-
tags/1.120.23/public/dist/express-checkout/index.asset.php (added)
-
tags/1.120.23/public/dist/express-checkout/index.css (added)
-
tags/1.120.23/public/dist/express-checkout/index.css.map (added)
-
tags/1.120.23/public/dist/express-checkout/index.js (added)
-
tags/1.120.23/public/dist/express-checkout/index.js.map (added)
-
tags/1.120.23/public/dist/express-checkout/render.php (added)
-
tags/1.120.23/public/dist/img (added)
-
tags/1.120.23/public/dist/img/0565a070aa85efe45537-arrow-top-right.svg (added)
-
tags/1.120.23/public/dist/img/070ee8f2835a668d3bed-afterpay.svg (added)
-
tags/1.120.23/public/dist/img/092f83103c2ecb943508-payments.svg (added)
-
tags/1.120.23/public/dist/img/0a580c7c9daca59b189c-apple-pay.svg (added)
-
tags/1.120.23/public/dist/img/0e64fa95d48121400b9a-exclamation-point.svg (added)
-
tags/1.120.23/public/dist/img/12bea47a7191c4bc66b4-clearpay.svg (added)
-
tags/1.120.23/public/dist/img/13e395ad5ededabe25b8-hamburger-menu.svg (added)
-
tags/1.120.23/public/dist/img/165559a744e87642e227-eps.svg (added)
-
tags/1.120.23/public/dist/img/173aa60cc278bf30fb32-paypal.svg (added)
-
tags/1.120.23/public/dist/img/1a6151c695a83da246e4-info.svg (added)
-
tags/1.120.23/public/dist/img/1a65e514172655b40267-bancontact.svg (added)
-
tags/1.120.23/public/dist/img/1d3e02bf6050dce00a41-minus.svg (added)
-
tags/1.120.23/public/dist/img/234e9b87429241d12fb7-qty-plus.svg (added)
-
tags/1.120.23/public/dist/img/2598d60ef6ba61ecf216-venmo.svg (added)
-
tags/1.120.23/public/dist/img/26128239599ff24e8993-sale.svg (added)
-
tags/1.120.23/public/dist/img/2752b1c85850f5103595-express-checkout.svg (added)
-
tags/1.120.23/public/dist/img/29b34a2d06a2137a30a2-venmo.svg (added)
-
tags/1.120.23/public/dist/img/31fa826b1a682e0e2d74-bancontact.svg (added)
-
tags/1.120.23/public/dist/img/41b3f2a435bf418eabe9-transfer.svg (added)
-
tags/1.120.23/public/dist/img/4900b355ca80f8a487e6-error-circle-outline.svg (added)
-
tags/1.120.23/public/dist/img/4b8adfea7ae382a4fe7f-dot-dot-dot.svg (added)
-
tags/1.120.23/public/dist/img/4d5cdbf6137d4183a2e3-docs-icon.svg (added)
-
tags/1.120.23/public/dist/img/4e8c9723f0389f28b036-affirm.svg (added)
-
tags/1.120.23/public/dist/img/4eb6a57eeeccfe1617eb-cashapp-green.svg (added)
-
tags/1.120.23/public/dist/img/4eeb17d4bbe2c98a03dd-address-autocomplete.svg (added)
-
tags/1.120.23/public/dist/img/5101aac386b5b03b4ec0-pp-full-purple.svg (added)
-
tags/1.120.23/public/dist/img/53f15ef8d0b4e0762ec5-product-reco.svg (added)
-
tags/1.120.23/public/dist/img/5606c9a7bca3cdc32c92-klarna.svg (added)
-
tags/1.120.23/public/dist/img/58c43e10162dc5f98fe3-chevron-down-solid.svg (added)
-
tags/1.120.23/public/dist/img/6c33b0b95690ed9ee154-field-editor.svg (added)
-
tags/1.120.23/public/dist/img/6faea1b14daefea84e13-info-circle-outline.svg (added)
-
tags/1.120.23/public/dist/img/7064f0505b09684cc84b-cart-abandonment.svg (added)
-
tags/1.120.23/public/dist/img/72ce482cc43ec0d60a28-region.svg (added)
-
tags/1.120.23/public/dist/img/75a621818cd858bfa053-affirm.svg (added)
-
tags/1.120.23/public/dist/img/763094961226169e9fea-support-icon.svg (added)
-
tags/1.120.23/public/dist/img/77fb0b8ca3843d373da4-ideal.svg (added)
-
tags/1.120.23/public/dist/img/79a27066bbe0696f03ae-trashcan.svg (added)
-
tags/1.120.23/public/dist/img/7a876e56f5e19368d84b-property-help.svg (added)
-
tags/1.120.23/public/dist/img/7aba4ceea17fbd040a20-google-pay.svg (added)
-
tags/1.120.23/public/dist/img/81f46ffe483952a15cca-toggle-check.svg (added)
-
tags/1.120.23/public/dist/img/89d1a718923a143f6ec3-klarna.svg (added)
-
tags/1.120.23/public/dist/img/8a706a0d006ab43d8ac5-dashboard-icon.svg (added)
-
tags/1.120.23/public/dist/img/8b829e567bff7e3cc683-analytics-icon.svg (added)
-
tags/1.120.23/public/dist/img/8c8968a2f7f7a789c35a-paypal.svg (added)
-
tags/1.120.23/public/dist/img/8e8cb48346c7b3ba4dfd-warning-circle-outline.svg (added)
-
tags/1.120.23/public/dist/img/904e49a8efd52bd3017e-afterpay-logo.svg (added)
-
tags/1.120.23/public/dist/img/9af15025cd36f6386e42-plus-sign.svg (added)
-
tags/1.120.23/public/dist/img/9ddd7317032bd9125379-p24.svg (added)
-
tags/1.120.23/public/dist/img/9e3e5b1f64b1f965042e-bot-detection.svg (added)
-
tags/1.120.23/public/dist/img/a84d80c8021ea0cd7b28-plus.svg (added)
-
tags/1.120.23/public/dist/img/ada8dc0c2c1b82204bb3-purchase-order.svg (added)
-
tags/1.120.23/public/dist/img/b2c8b12eb49165de87d5-credit-card-regular.svg (added)
-
tags/1.120.23/public/dist/img/b6a9922efb467e7f87c3-google-pay.svg (added)
-
tags/1.120.23/public/dist/img/b92449f96707fb8f91d8-qty-minus.svg (added)
-
tags/1.120.23/public/dist/img/bb216add609679e2a388-ideal.svg (added)
-
tags/1.120.23/public/dist/img/bd83bcd063ddc44afffb-pp-short-purple.svg (added)
-
tags/1.120.23/public/dist/img/be423b9acc2611c004eb-devices.svg (added)
-
tags/1.120.23/public/dist/img/c3d4e0e7e32e04ab2bb8-account-icon.svg (added)
-
tags/1.120.23/public/dist/img/cad4a91407099c0b1e1f-paypal-paylater.svg (added)
-
tags/1.120.23/public/dist/img/cc1b70cdcd73ee9584ea-check.svg (added)
-
tags/1.120.23/public/dist/img/cd1eec17937e892cf6c2-giropay.svg (added)
-
tags/1.120.23/public/dist/img/ceae3f7fe5395fcdc780-spinner-dark.svg (added)
-
tags/1.120.23/public/dist/img/d067b36f63345d495b52-apple-pay-button.png (added)
-
tags/1.120.23/public/dist/img/d0db1eb027413f38ddb3-apple-pay.svg (added)
-
tags/1.120.23/public/dist/img/d23e626f854a0e6b44c1-data-icon.svg (added)
-
tags/1.120.23/public/dist/img/d2a66f3e82ab3efab425-card.svg (added)
-
tags/1.120.23/public/dist/img/d4044b8aea8f4aa47940-p24.svg (added)
-
tags/1.120.23/public/dist/img/d51124eb3dc1ce15ea25-chevron-right.svg (added)
-
tags/1.120.23/public/dist/img/d5f7e88664795efd1815-twitter.svg (added)
-
tags/1.120.23/public/dist/img/daf9bd0b8caf0142833a-giropay.svg (added)
-
tags/1.120.23/public/dist/img/dc5e5e43e8d7a74a5bd3-currency-switcher.svg (added)
-
tags/1.120.23/public/dist/img/e42285808085838ca833-cash.svg (added)
-
tags/1.120.23/public/dist/img/e5492ffbb6b1403b77b9-settings-icon.svg (added)
-
tags/1.120.23/public/dist/img/e7542fee9125d1af4d23-bank.svg (added)
-
tags/1.120.23/public/dist/img/eb266791f9ff285c0c67-check-circle-outline.svg (added)
-
tags/1.120.23/public/dist/img/ec3b654ae6c2c46f7282-spinner.svg (added)
-
tags/1.120.23/public/dist/img/eec3b1c4550c5cdc3982-trashcan-red.svg (added)
-
tags/1.120.23/public/dist/img/ef94cd4d5b44f46cf337-white-tick.svg (added)
-
tags/1.120.23/public/dist/img/efa03ef0d084294ce629-cashapp-green-logo-only.svg (added)
-
tags/1.120.23/public/dist/img/f3f9ab60cc7478a3451a-crown-icon.svg (added)
-
tags/1.120.23/public/dist/img/f98545e5c40ab6bbc044-eps.svg (added)
-
tags/1.120.23/public/dist/native-checkout.bundle.css (added)
-
tags/1.120.23/public/dist/native-checkout.bundle.css.map (added)
-
tags/1.120.23/public/dist/native-checkout.bundle.js (added)
-
tags/1.120.23/public/dist/native-checkout.bundle.js.map (added)
-
tags/1.120.23/public/dist/peachpay-submenu.bundle.js (added)
-
tags/1.120.23/public/dist/peachpay-submenu.bundle.js.map (added)
-
tags/1.120.23/public/dist/wordpress (added)
-
tags/1.120.23/public/dist/wordpress/checkout-blocks.asset.php (added)
-
tags/1.120.23/public/dist/wordpress/checkout-blocks.css (added)
-
tags/1.120.23/public/dist/wordpress/checkout-blocks.css.map (added)
-
tags/1.120.23/public/dist/wordpress/checkout-blocks.js (added)
-
tags/1.120.23/public/dist/wordpress/checkout-blocks.js.map (added)
-
tags/1.120.23/public/dist/wordpress/peachpay_square_ach-blocks.asset.php (added)
-
tags/1.120.23/public/dist/wordpress/peachpay_square_ach-blocks.js (added)
-
tags/1.120.23/public/dist/wordpress/peachpay_square_ach-blocks.js.map (added)
-
tags/1.120.23/public/dist/wordpress/peachpay_square_afterpay-blocks.asset.php (added)
-
tags/1.120.23/public/dist/wordpress/peachpay_square_afterpay-blocks.js (added)
-
tags/1.120.23/public/dist/wordpress/peachpay_square_afterpay-blocks.js.map (added)
-
tags/1.120.23/public/dist/wordpress/peachpay_square_card-blocks.asset.php (added)
-
tags/1.120.23/public/dist/wordpress/peachpay_square_card-blocks.js (added)
-
tags/1.120.23/public/dist/wordpress/peachpay_square_card-blocks.js.map (added)
-
tags/1.120.23/public/dist/wordpress/peachpay_square_googlepay-blocks.asset.php (added)
-
tags/1.120.23/public/dist/wordpress/peachpay_square_googlepay-blocks.js (added)
-
tags/1.120.23/public/dist/wordpress/peachpay_square_googlepay-blocks.js.map (added)
-
tags/1.120.23/public/dist/wordpress/peachpay_stripe_achdebit-blocks.asset.php (added)
-
tags/1.120.23/public/dist/wordpress/peachpay_stripe_achdebit-blocks.js (added)
-
tags/1.120.23/public/dist/wordpress/peachpay_stripe_achdebit-blocks.js.map (added)
-
tags/1.120.23/public/dist/wordpress/peachpay_stripe_affirm-blocks.asset.php (added)
-
tags/1.120.23/public/dist/wordpress/peachpay_stripe_affirm-blocks.js (added)
-
tags/1.120.23/public/dist/wordpress/peachpay_stripe_affirm-blocks.js.map (added)
-
tags/1.120.23/public/dist/wordpress/peachpay_stripe_afterpay-blocks.asset.php (added)
-
tags/1.120.23/public/dist/wordpress/peachpay_stripe_afterpay-blocks.js (added)
-
tags/1.120.23/public/dist/wordpress/peachpay_stripe_afterpay-blocks.js.map (added)
-
tags/1.120.23/public/dist/wordpress/peachpay_stripe_bancontact-blocks.asset.php (added)
-
tags/1.120.23/public/dist/wordpress/peachpay_stripe_bancontact-blocks.js (added)
-
tags/1.120.23/public/dist/wordpress/peachpay_stripe_bancontact-blocks.js.map (added)
-
tags/1.120.23/public/dist/wordpress/peachpay_stripe_card-blocks.asset.php (added)
-
tags/1.120.23/public/dist/wordpress/peachpay_stripe_card-blocks.js (added)
-
tags/1.120.23/public/dist/wordpress/peachpay_stripe_card-blocks.js.map (added)
-
tags/1.120.23/public/dist/wordpress/peachpay_stripe_eps-blocks.asset.php (added)
-
tags/1.120.23/public/dist/wordpress/peachpay_stripe_eps-blocks.js (added)
-
tags/1.120.23/public/dist/wordpress/peachpay_stripe_eps-blocks.js.map (added)
-
tags/1.120.23/public/dist/wordpress/peachpay_stripe_giropay-blocks.asset.php (added)
-
tags/1.120.23/public/dist/wordpress/peachpay_stripe_giropay-blocks.js (added)
-
tags/1.120.23/public/dist/wordpress/peachpay_stripe_giropay-blocks.js.map (added)
-
tags/1.120.23/public/dist/wordpress/peachpay_stripe_googlepay-blocks.asset.php (added)
-
tags/1.120.23/public/dist/wordpress/peachpay_stripe_googlepay-blocks.js (added)
-
tags/1.120.23/public/dist/wordpress/peachpay_stripe_googlepay-blocks.js.map (added)
-
tags/1.120.23/public/dist/wordpress/peachpay_stripe_ideal-blocks.asset.php (added)
-
tags/1.120.23/public/dist/wordpress/peachpay_stripe_ideal-blocks.js (added)
-
tags/1.120.23/public/dist/wordpress/peachpay_stripe_ideal-blocks.js.map (added)
-
tags/1.120.23/public/dist/wordpress/peachpay_stripe_klarna-blocks.asset.php (added)
-
tags/1.120.23/public/dist/wordpress/peachpay_stripe_klarna-blocks.js (added)
-
tags/1.120.23/public/dist/wordpress/peachpay_stripe_klarna-blocks.js.map (added)
-
tags/1.120.23/public/dist/wordpress/peachpay_stripe_p24-blocks.asset.php (added)
-
tags/1.120.23/public/dist/wordpress/peachpay_stripe_p24-blocks.js (added)
-
tags/1.120.23/public/dist/wordpress/peachpay_stripe_p24-blocks.js.map (added)
-
tags/1.120.23/public/dist/wordpress/peachpay_stripe_sepadebit-blocks.asset.php (added)
-
tags/1.120.23/public/dist/wordpress/peachpay_stripe_sepadebit-blocks.js (added)
-
tags/1.120.23/public/dist/wordpress/peachpay_stripe_sepadebit-blocks.js.map (added)
-
tags/1.120.23/public/dist/wordpress/peachpay_stripe_sofort-blocks.asset.php (added)
-
tags/1.120.23/public/dist/wordpress/peachpay_stripe_sofort-blocks.js (added)
-
tags/1.120.23/public/dist/wordpress/peachpay_stripe_sofort-blocks.js.map (added)
-
tags/1.120.23/public/fonts (added)
-
tags/1.120.23/public/fonts/peachpay-icons.eot (added)
-
tags/1.120.23/public/fonts/peachpay-icons.svg (added)
-
tags/1.120.23/public/fonts/peachpay-icons.ttf (added)
-
tags/1.120.23/public/fonts/peachpay-icons.woff (added)
-
tags/1.120.23/public/icon.css (added)
-
tags/1.120.23/public/img (added)
-
tags/1.120.23/public/img/ConvesioConvert-banner-version03-big.png (added)
-
tags/1.120.23/public/img/account-icon.svg (added)
-
tags/1.120.23/public/img/analytics-icon.svg (added)
-
tags/1.120.23/public/img/arrow-top-right.svg (added)
-
tags/1.120.23/public/img/baseball-ball-solid.svg (added)
-
tags/1.120.23/public/img/baseball-black.svg (added)
-
tags/1.120.23/public/img/briefcase-solid-black.svg (added)
-
tags/1.120.23/public/img/briefcase-solid.svg (added)
-
tags/1.120.23/public/img/button-alignment (added)
-
tags/1.120.23/public/img/button-alignment/button-placement-bottom.svg (added)
-
tags/1.120.23/public/img/button-alignment/button-placement-inline.svg (added)
-
tags/1.120.23/public/img/button-alignment/center-cart-page.svg (added)
-
tags/1.120.23/public/img/button-alignment/center-product-page.svg (added)
-
tags/1.120.23/public/img/button-alignment/float-button-left.svg (added)
-
tags/1.120.23/public/img/button-alignment/float-button-right.svg (added)
-
tags/1.120.23/public/img/button-alignment/full-cart-page.svg (added)
-
tags/1.120.23/public/img/button-alignment/full-product-page.svg (added)
-
tags/1.120.23/public/img/button-alignment/left-cart-page.svg (added)
-
tags/1.120.23/public/img/button-alignment/left-product-page.svg (added)
-
tags/1.120.23/public/img/button-alignment/mobile-product-default.svg (added)
-
tags/1.120.23/public/img/button-alignment/mobile-product-fixed.svg (added)
-
tags/1.120.23/public/img/button-alignment/right-cart-page.svg (added)
-
tags/1.120.23/public/img/button-alignment/right-product-page.svg (added)
-
tags/1.120.23/public/img/check-circle-outline.svg (added)
-
tags/1.120.23/public/img/check-circle-solid.svg (added)
-
tags/1.120.23/public/img/checkmark-green.svg (added)
-
tags/1.120.23/public/img/checkmark-square-solid.svg (added)
-
tags/1.120.23/public/img/chevron-circle-right-black.svg (added)
-
tags/1.120.23/public/img/chevron-circle-right-solid.svg (added)
-
tags/1.120.23/public/img/chevron-down-solid.svg (added)
-
tags/1.120.23/public/img/close-icon.svg (added)
-
tags/1.120.23/public/img/crown-icon.svg (added)
-
tags/1.120.23/public/img/dashboard-icon.svg (added)
-
tags/1.120.23/public/img/data-icon.svg (added)
-
tags/1.120.23/public/img/docs-icon.svg (added)
-
tags/1.120.23/public/img/dot-dot-dot.svg (added)
-
tags/1.120.23/public/img/error-circle-outline.svg (added)
-
tags/1.120.23/public/img/hamburger-menu.svg (added)
-
tags/1.120.23/public/img/info-circle-outline.svg (added)
-
tags/1.120.23/public/img/info.svg (added)
-
tags/1.120.23/public/img/lock-black.svg (added)
-
tags/1.120.23/public/img/lock.svg (added)
-
tags/1.120.23/public/img/marks (added)
-
tags/1.120.23/public/img/marks/amex.svg (added)
-
tags/1.120.23/public/img/marks/apple-pay.svg (added)
-
tags/1.120.23/public/img/marks/applepay-full.svg (added)
-
tags/1.120.23/public/img/marks/applepay-small-color.svg (added)
-
tags/1.120.23/public/img/marks/applepay-small-white.svg (added)
-
tags/1.120.23/public/img/marks/authnet (added)
-
tags/1.120.23/public/img/marks/authnet.png (added)
-
tags/1.120.23/public/img/marks/authnet.svg (added)
-
tags/1.120.23/public/img/marks/authnet/short.svg (added)
-
tags/1.120.23/public/img/marks/bank.svg (added)
-
tags/1.120.23/public/img/marks/bitcoin.svg (added)
-
tags/1.120.23/public/img/marks/card-small.svg (added)
-
tags/1.120.23/public/img/marks/cards.svg (added)
-
tags/1.120.23/public/img/marks/cashapp-green-logo-only.svg (added)
-
tags/1.120.23/public/img/marks/cashapp-green.svg (added)
-
tags/1.120.23/public/img/marks/cc-quad.svg (added)
-
tags/1.120.23/public/img/marks/cc-stripe-brands.svg (added)
-
tags/1.120.23/public/img/marks/convesiopay (added)
-
tags/1.120.23/public/img/marks/convesiopay/Convesio.png (added)
-
tags/1.120.23/public/img/marks/convesiopay/convesiopay.svg (added)
-
tags/1.120.23/public/img/marks/convesiopay/image.png (added)
-
tags/1.120.23/public/img/marks/credit-card-regular.svg (added)
-
tags/1.120.23/public/img/marks/diners.svg (added)
-
tags/1.120.23/public/img/marks/discover.svg (added)
-
tags/1.120.23/public/img/marks/google-pay.svg (added)
-
tags/1.120.23/public/img/marks/googlepay-full.svg (added)
-
tags/1.120.23/public/img/marks/googlepay-small-white.svg (added)
-
tags/1.120.23/public/img/marks/jcb.svg (added)
-
tags/1.120.23/public/img/marks/mastercard.svg (added)
-
tags/1.120.23/public/img/marks/mini-amex.svg (added)
-
tags/1.120.23/public/img/marks/mini-diners.svg (added)
-
tags/1.120.23/public/img/marks/mini-master.svg (added)
-
tags/1.120.23/public/img/marks/mini-visa.svg (added)
-
tags/1.120.23/public/img/marks/nmi (added)
-
tags/1.120.23/public/img/marks/nmi/amex.svg (added)
-
tags/1.120.23/public/img/marks/nmi/diners.svg (added)
-
tags/1.120.23/public/img/marks/nmi/discover.svg (added)
-
tags/1.120.23/public/img/marks/nmi/jcb.svg (added)
-
tags/1.120.23/public/img/marks/nmi/maestro.svg (added)
-
tags/1.120.23/public/img/marks/nmi/mastercard.svg (added)
-
tags/1.120.23/public/img/marks/nmi/nmi.png (added)
-
tags/1.120.23/public/img/marks/nmi/visa.svg (added)
-
tags/1.120.23/public/img/marks/paypal (added)
-
tags/1.120.23/public/img/marks/paypal-paylater.svg (added)
-
tags/1.120.23/public/img/marks/paypal.svg (added)
-
tags/1.120.23/public/img/marks/paypal/cc-quad.svg (added)
-
tags/1.120.23/public/img/marks/paypal/credit-full.svg (added)
-
tags/1.120.23/public/img/marks/paypal/credit-small-color.svg (added)
-
tags/1.120.23/public/img/marks/paypal/paylater-small-color.svg (added)
-
tags/1.120.23/public/img/marks/paypal/small-white.svg (added)
-
tags/1.120.23/public/img/marks/paypal/venmo-small-color.svg (added)
-
tags/1.120.23/public/img/marks/poynt-logo.svg (added)
-
tags/1.120.23/public/img/marks/purchase_order.svg (added)
-
tags/1.120.23/public/img/marks/purchase_order_icon.svg (added)
-
tags/1.120.23/public/img/marks/square (added)
-
tags/1.120.23/public/img/marks/square-logo.png (added)
-
tags/1.120.23/public/img/marks/square.svg (added)
-
tags/1.120.23/public/img/marks/square/cashapp-small-color.svg (added)
-
tags/1.120.23/public/img/marks/square/cashapp-small-white.svg (added)
-
tags/1.120.23/public/img/marks/square/short.svg (added)
-
tags/1.120.23/public/img/marks/stripe (added)
-
tags/1.120.23/public/img/marks/stripe.svg (added)
-
tags/1.120.23/public/img/marks/stripe/affirm-full.svg (added)
-
tags/1.120.23/public/img/marks/stripe/affirm-small-color.svg (added)
-
tags/1.120.23/public/img/marks/stripe/affirm-small-white.svg (added)
-
tags/1.120.23/public/img/marks/stripe/afterpay-full-color.svg (added)
-
tags/1.120.23/public/img/marks/stripe/afterpay-small-color.svg (added)
-
tags/1.120.23/public/img/marks/stripe/afterpay-small-white.svg (added)
-
tags/1.120.23/public/img/marks/stripe/apple-google.svg (added)
-
tags/1.120.23/public/img/marks/stripe/bancontact-full.svg (added)
-
tags/1.120.23/public/img/marks/stripe/bancontact-small-white.svg (added)
-
tags/1.120.23/public/img/marks/stripe/clearpay-full-color.svg (added)
-
tags/1.120.23/public/img/marks/stripe/clearpay-small-color.svg (added)
-
tags/1.120.23/public/img/marks/stripe/clearpay-small-white.svg (added)
-
tags/1.120.23/public/img/marks/stripe/eps-full.svg (added)
-
tags/1.120.23/public/img/marks/stripe/eps-small-white.svg (added)
-
tags/1.120.23/public/img/marks/stripe/giropay-full.svg (added)
-
tags/1.120.23/public/img/marks/stripe/giropay-small-white.svg (added)
-
tags/1.120.23/public/img/marks/stripe/ideal-full.svg (added)
-
tags/1.120.23/public/img/marks/stripe/ideal-small-white.svg (added)
-
tags/1.120.23/public/img/marks/stripe/klarna-full.svg (added)
-
tags/1.120.23/public/img/marks/stripe/klarna-small-color.svg (added)
-
tags/1.120.23/public/img/marks/stripe/klarna-small-white.svg (added)
-
tags/1.120.23/public/img/marks/stripe/p24-full.svg (added)
-
tags/1.120.23/public/img/marks/stripe/p24-small-white.svg (added)
-
tags/1.120.23/public/img/marks/stripe/short-color.svg (added)
-
tags/1.120.23/public/img/marks/stripe/sofort-small-color.svg (added)
-
tags/1.120.23/public/img/marks/stripe/sofort-small-white.svg (added)
-
tags/1.120.23/public/img/marks/unionpay.svg (added)
-
tags/1.120.23/public/img/marks/us_banks-full.svg (added)
-
tags/1.120.23/public/img/marks/us_banks-small.svg (added)
-
tags/1.120.23/public/img/marks/venmo.svg (added)
-
tags/1.120.23/public/img/marks/visa.svg (added)
-
tags/1.120.23/public/img/mountain-black.svg (added)
-
tags/1.120.23/public/img/none-icon.svg (added)
-
tags/1.120.23/public/img/peachpay-full-orange.png (added)
-
tags/1.120.23/public/img/peachpay.svg (added)
-
tags/1.120.23/public/img/plus-sign.svg (added)
-
tags/1.120.23/public/img/pp-full-gradient.svg (added)
-
tags/1.120.23/public/img/pp-full-purple.svg (added)
-
tags/1.120.23/public/img/pp-short-purple.svg (added)
-
tags/1.120.23/public/img/property-help.svg (added)
-
tags/1.120.23/public/img/recommended-products (added)
-
tags/1.120.23/public/img/recommended-products/new-user.svg (added)
-
tags/1.120.23/public/img/settings-icon.svg (added)
-
tags/1.120.23/public/img/shopping-cart-solid-black.svg (added)
-
tags/1.120.23/public/img/shopping-cart-solid.svg (added)
-
tags/1.120.23/public/img/skre.svg (added)
-
tags/1.120.23/public/img/spinner-dark.svg (added)
-
tags/1.120.23/public/img/spinner.svg (added)
-
tags/1.120.23/public/img/stripe-black.png (added)
-
tags/1.120.23/public/img/support-icon.svg (added)
-
tags/1.120.23/public/img/toggle-check.svg (added)
-
tags/1.120.23/public/img/twitter.svg (added)
-
tags/1.120.23/public/img/warning-circle-outline.svg (added)
-
tags/1.120.23/public/stripe-redirect.html (added)
-
tags/1.120.23/readme.txt (added)
-
tags/1.120.23/uninstall.php (added)
-
trunk/changelog.txt (modified) (1 diff)
-
trunk/core/modules/dashboard/settings-homepage.php (modified) (1 diff)
-
trunk/core/payments/convesiopay/admin/class-peachpay-convesiopay-fetch-payment-status-manually.php (modified) (2 diffs)
-
trunk/core/payments/convesiopay/admin/class-peachpay-convesiopay-manual-capture.php (modified) (8 diffs)
-
trunk/core/payments/convesiopay/gateways/class-peachpay-convesiopay-applepay-gateway.php (modified) (7 diffs)
-
trunk/core/payments/convesiopay/gateways/class-peachpay-convesiopay-card-gateway.php (modified) (26 diffs)
-
trunk/core/payments/convesiopay/gateways/class-peachpay-convesiopay-unified-gateway.php (modified) (17 diffs)
-
trunk/core/payments/convesiopay/routes/class-peachpay-convesiopay-reconciliation.php (modified) (33 diffs)
-
trunk/core/payments/convesiopay/routes/class-peachpay-convesiopay-webhook.php (modified) (23 diffs)
-
trunk/core/payments/stripe/abstract/class-peachpay-stripe-payment-gateway.php (modified) (19 diffs)
-
trunk/core/payments/stripe/functions.php (modified) (1 diff)
-
trunk/core/payments/stripe/hooks.php (modified) (1 diff)
-
trunk/core/payments/stripe/routes/stripe-webhook.php (modified) (13 diffs)
-
trunk/core/payments/stripe/utils/class-peachpay-stripe.php (modified) (25 diffs)
-
trunk/peachpay.php (modified) (1 diff)
-
trunk/readme.txt (modified) (2 diffs)
Legend:
- Unmodified
- Added
- Removed
-
peachpay-for-woocommerce/trunk/changelog.txt
r3486614 r3490786 1 1 *** PeachPay for WooCommerce Changelog *** 2 3 2026-03-25 - version 1.120.23 4 * **Fixed**: 5 * **Subscriptions**: Prevented duplicate subscription renewal charges across ConvesioPay and Stripe. 6 * **Stripe**: Fixed duplicate WooCommerce refunds triggered by Stripe charge.refunded webhook. 7 * **Improved**: 8 * **Logging**: Standardized payment logging between ConvesioPay and Stripe for better consistency and debugging. 9 * **NMI**: Improved homepage payment box with UI reorganization and enhanced validation. 10 * **Build**: 11 * Suppressed known CSS browser-support stylelint warnings to reduce noise in builds. 2 12 3 13 2026-03-19 - version 1.120.22 -
peachpay-for-woocommerce/trunk/core/modules/dashboard/settings-homepage.php
r3486472 r3490786 116 116 'heap_id' => 'nmi', 117 117 'hash' => '#nmi', 118 'main_logo' => PeachPay::get_asset_url( '/img/marks/ convesiopay1.svg' ),118 'main_logo' => PeachPay::get_asset_url( '/img/marks/nmi/nmi.png' ), 119 119 'connection' => (bool) peachpay_nmi_is_enabled(), 120 'description' => ' The all-in-one payment solution to maximize revenue and streamline the payment process. Make test payments following these instructions.',121 'featured' => true, // Make ConvesioPay a featured card (double width)120 'description' => 'NMI is a great fit for online merchants who want a flexible gateway with broad integration options and risk controls.', 121 'featured' => false, 122 122 'sub_logos' => array( 123 PeachPay::get_asset_url( '/img/marks/convesiopay/visa.svg' ), 124 PeachPay::get_asset_url( '/img/marks/convesiopay/amex.png' ), 125 PeachPay::get_asset_url( '/img/marks/convesiopay/Mastercard.png' ), 126 PeachPay::get_asset_url( '/img/marks/convesiopay/Apple_Pay.png' ), 127 PeachPay::get_asset_url( '/img/marks/convesiopay/Google_Pay.png' ), 128 PeachPay::get_asset_url( '/img/marks/convesiopay/bitcoin.png' ), 129 PeachPay::get_asset_url( '/img/marks/convesiopay/maestro.png' ), 130 PeachPay::get_asset_url( '/img/marks/convesiopay/discover-network.png' ), 131 PeachPay::get_asset_url( '/img/marks/convesiopay/UnionPay.png' ) 123 PeachPay::get_asset_url( '/img/marks/cards.svg' ), 124 PeachPay::get_asset_url( '/img/marks/applepay-full.svg' ), 132 125 ), 133 126 ), -
peachpay-for-woocommerce/trunk/core/payments/convesiopay/admin/class-peachpay-convesiopay-fetch-payment-status-manually.php
r3460037 r3490786 185 185 $body = wp_remote_retrieve_body( $response ); 186 186 if ( $code !== 200 ) { 187 if ( function_exists( 'peachpay_log' ) ) { 188 peachpay_log( 'error', 'PeachPay Fetch Status: GET payment HTTP ' . $code . ' for payment ' . $payment_id . ' - ' . substr( $body, 0, 500 ) ); 187 if (function_exists('peachpay_log')) { 188 peachpay_log( 189 'error', 190 'Failed to fetch payment status from ConvesioPay Api', 191 array( 192 'event' => 'payments.convesiopay_admin.payment.fetch.failed', 193 'component' => 'payments', 194 'feature' => 'convesiopay_admin', 195 'operation' => 'payment.fetch', 196 'outcome' => 'failed', 197 'method' => __METHOD__, 198 'line' => __LINE__, 199 'data' => array( 200 'details' => '', 201 'response_code' => $code, 202 'response_body' => json_decode($body, true), 203 'payment_id' => $payment_id, 204 ) 205 ) 206 ); 189 207 } 190 208 return false; … … 193 211 $data = json_decode( $body, true ); 194 212 if ( ! is_array( $data ) || empty( $data['status'] ) ) { 195 if ( function_exists( 'peachpay_log' ) ) { 196 peachpay_log( 'error', 'PeachPay Fetch Status: GET payment invalid response for ' . $payment_id . ' - missing status or invalid JSON' ); 213 if (function_exists('peachpay_log')) { 214 peachpay_log( 215 'error', 216 'Failed to fetch payment status from ConvesioPay Api', 217 array( 218 'event' => 'payments.convesiopay_admin.payment.fetch.failed', 219 'component' => 'payments', 220 'feature' => 'convesiopay_admin', 221 'operation' => 'payment.fetch', 222 'outcome' => 'failed', 223 'method' => __METHOD__, 224 'line' => __LINE__, 225 'data' => array( 226 'details' => 'The response is not a valid JSON or missing status', 227 'response_body' => json_decode($body, true), 228 'payment_id' => $payment_id, 229 ) 230 ) 231 ); 197 232 } 198 233 return false; -
peachpay-for-woocommerce/trunk/core/payments/convesiopay/admin/class-peachpay-convesiopay-manual-capture.php
r3460037 r3490786 186 186 ) ); 187 187 } else { 188 peachpay_log( 'error', 'ConvesioPay: Manual capture failed - ' . $result['message'] . ' (order ' . $order_id . ', payment ' . $payment_id . ')' );189 188 $order->add_order_note( sprintf( 190 189 'ConvesioPay capture failed: %s', … … 263 262 ) ); 264 263 } else { 265 peachpay_log( 'error', 'ConvesioPay: Manual cancel failed - ' . $result['message'] . ' (order ' . $order_id . ', payment ' . $payment_id . ')' );266 264 $order->add_order_note( sprintf( 267 265 'ConvesioPay cancel failed: %s', … … 302 300 303 301 304 peachpay_log( 'debug', 'ConvesioPay: Manual capture API request for payment ' . $payment_id . ' (amount: ' . ( $amount / 100 ) . ' ' . $currency . ')' ); 302 peachpay_log( 303 'debug', 304 'Payments: ConvesioPay Manual capture debug.', 305 array( 306 'event' => 'payments.convesiopay_admin.capture.manual.debug', 307 'component' => 'payments', 308 'feature' => 'convesiopay_admin', 309 'operation' => 'capture.manual', 310 'outcome' => 'debug', 311 'method' => __METHOD__, 312 'line' => __LINE__, 313 'data' => array( 314 'details' => 'ConvesioPay: Manual capture API request for payment ' . $payment_id . ' (amount: ' . ( $amount / 100 ) . ' ' . $currency . ')' 315 ))); 305 316 306 317 // Make API request … … 316 327 317 328 if ( is_wp_error( $response ) ) { 318 peachpay_log( 'error', 'ConvesioPay: Manual capture network error - ' . $response->get_error_message() . ' (payment ' . $payment_id . ')' ); 329 peachpay_log( 330 'error', 331 'Payments: ConvesioPay Manual capture failed.', 332 array( 333 'event' => 'payments.convesiopay_admin.capture.manual.failed', 334 'component' => 'payments', 335 'feature' => 'convesiopay_admin', 336 'operation' => 'capture.manual', 337 'outcome' => 'failed', 338 'method' => __METHOD__, 339 'line' => __LINE__, 340 'data' => array( 341 'details' => 'ConvesioPay: Manual capture network error - ' . $response->get_error_message() . ' (payment ' . $payment_id . ')' 342 ))); 319 343 return array( 'success' => false, 'message' => $response->get_error_message() ); 320 344 } … … 326 350 if ( $response_code === 200 ) { 327 351 $response_data = json_decode( $response_body, true ); 328 peachpay_log( 'info', 'ConvesioPay: Manual capture success - payment ' . $payment_id ); 352 peachpay_log( 353 'info', 354 'Payments: ConvesioPay Manual capture success.', 355 array( 356 'event' => 'payments.convesiopay_admin.capture.manual.success', 357 'component' => 'payments', 358 'feature' => 'convesiopay_admin', 359 'operation' => 'capture.manual', 360 'outcome' => 'success', 361 'method' => __METHOD__, 362 'line' => __LINE__, 363 'data' => array( 364 'details' => 'ConvesioPay: Manual capture success - payment ' . $payment_id 365 ))); 329 366 return array( 'success' => true, 'data' => $response_data ); 330 367 } else { 331 368 $error_data = json_decode( $response_body, true ); 332 369 $error_message = $error_data['message'] ?? "HTTP $response_code error"; 333 peachpay_log( 'error', 'ConvesioPay: Manual capture API error - ' . $error_message . ' (payment ' . $payment_id . ')' ); 370 peachpay_log( 371 'error', 372 'Payments: ConvesioPay Manual capture failed.', 373 array( 374 'event' => 'payments.convesiopay_admin.capture.manual.failed', 375 'component' => 'payments', 376 'feature' => 'convesiopay_admin', 377 'operation' => 'capture.manual', 378 'outcome' => 'failed', 379 'method' => __METHOD__, 380 'line' => __LINE__, 381 'data' => array( 382 'details' => 'ConvesioPay: Manual capture API error - ' . $error_message . ' (payment ' . $payment_id . ')' 383 ))); 334 384 return array( 'success' => false, 'message' => $error_message ); 335 385 } … … 359 409 $api_url = peachpay_is_test_mode() ? 'https://api-qa.convesiopay.com' : 'https://api.convesiopay.com'; 360 410 $cancel_url = $api_url . '/v1/payments/' . $payment_id . '/cancel'; 361 peachpay_log( 'debug', 'ConvesioPay: Manual cancel API request for payment ' . $payment_id ); 411 peachpay_log( 412 'debug', 413 'Payments: Manual cancel debug.', 414 array( 415 'event' => 'payments.convesiopay_admin.cancel.manual.debug', 416 'component' => 'payments', 417 'feature' => 'convesiopay_admin', 418 'operation' => 'cancel.manual', 419 'outcome' => 'debug', 420 'method' => __METHOD__, 421 'line' => __LINE__, 422 'data' => array( 423 'details' => 'ConvesioPay: Manual cancel API request for payment ' . $payment_id 424 ))); 362 425 363 426 // Make API request (no body required for cancel) … … 373 436 374 437 if ( is_wp_error( $response ) ) { 375 peachpay_log( 'error', 'ConvesioPay: Manual cancel network error - ' . $response->get_error_message() . ' (payment ' . $payment_id . ')' ); 438 peachpay_log( 439 'error', 440 'Payments: ConvesioPay Manual cancel failed.', 441 array( 442 'event' => 'payments.convesiopay_admin.cancel.manual.failed', 443 'component' => 'payments', 444 'feature' => 'convesiopay_admin', 445 'operation' => 'cancel.manual', 446 'outcome' => 'failed', 447 'method' => __METHOD__, 448 'line' => __LINE__, 449 'data' => array( 450 'details' => 'ConvesioPay: Manual cancel network error - ' . $response->get_error_message() . ' (payment ' . $payment_id . ')' 451 ))); 376 452 return array( 'success' => false, 'message' => $response->get_error_message() ); 377 453 } … … 383 459 if ( $response_code === 200 ) { 384 460 $response_data = json_decode( $response_body, true ); 385 peachpay_log( 'info', 'ConvesioPay: Manual cancel success - payment ' . $payment_id ); 461 peachpay_log( 462 'info', 463 'Payments: Manual cancel success.', 464 array( 465 'event' => 'payments.convesiopay_admin.cancel.manual.success', 466 'component' => 'payments', 467 'feature' => 'convesiopay_admin', 468 'operation' => 'cancel.manual', 469 'outcome' => 'success', 470 'method' => __METHOD__, 471 'line' => __LINE__, 472 'data' => array( 473 'details' => 'ConvesioPay: Manual cancel success - payment ' . $payment_id 474 ))); 386 475 return array( 'success' => true, 'data' => $response_data ); 387 476 } else { 388 477 $error_data = json_decode( $response_body, true ); 389 478 $error_message = $error_data['message'] ?? "HTTP $response_code error"; 390 peachpay_log( 'error', 'ConvesioPay: Manual cancel API error - ' . $error_message . ' (payment ' . $payment_id . ')' ); 479 peachpay_log( 480 'error', 481 'Payments: Manual cancel failed.', 482 array( 483 'event' => 'payments.convesiopay_admin.cancel.manual.failed', 484 'component' => 'payments', 485 'feature' => 'convesiopay_admin', 486 'operation' => 'cancel.manual', 487 'outcome' => 'failed', 488 'method' => __METHOD__, 489 'line' => __LINE__, 490 'data' => array( 491 'details' => 'ConvesioPay: Manual cancel API error - ' . $error_message . ' (payment ' . $payment_id . ')' 492 ))); 391 493 return array( 'success' => false, 'message' => $error_message ); 392 494 } -
peachpay-for-woocommerce/trunk/core/payments/convesiopay/gateways/class-peachpay-convesiopay-applepay-gateway.php
r3465799 r3490786 274 274 $amount_diff_cents = abs( $frontend_applepay_amount_cents - $order_amount_cents ); 275 275 if ( $amount_diff_cents > 1 ) { 276 peachpay_log( 'warning', 'ConvesioPay: Apple Pay frontend amount differs from order total for order ' . $order->get_order_number() . ' (order_cents: ' . $order_amount_cents . ', frontend_cents: ' . $frontend_applepay_amount_cents . '). Rejecting so user re-authorizes.' ); 276 peachpay_log( 277 'warning', 278 'Payments: Apple Pay process payment warning.', 279 array( 280 'event' => 'payments.convesiopay_gateway.applepay.payment.warning', 281 'component' => 'payments', 282 'feature' => 'convesiopay_gateway', 283 'operation' => 'applepay.payment', 284 'outcome' => 'warning', 285 'method' => __METHOD__, 286 'line' => __LINE__, 287 'data' => array( 288 'details' => 'ConvesioPay: Apple Pay frontend amount differs from order total for order ' . $order->get_order_number() . ' (order_cents: ' . $order_amount_cents . ', frontend_cents: ' . $frontend_applepay_amount_cents . '). Rejecting so user re-authorizes.' 289 ) 290 ) 291 ); 277 292 throw new Exception( __( 'Order total has changed. Please confirm the payment amount and try again.', 'peachpay-for-woocommerce' ) ); 278 293 } … … 330 345 // Prepare request body - encode array to JSON string 331 346 $request_body = wp_json_encode( $payment_data ); 332 peachpay_log( 'debug', 'ConvesioPay: Apple Pay payment API request for order ' . $order->get_order_number() . ' (amount: ' . $order_amount . ' USD, order_cents: ' . $order_amount_cents . ', request_cents: ' . $request_amount_cents . ', line_items_sum_cents: ' . $line_items_sum_cents . ', order_total_tax: ' . $order->get_total_tax() . ', order_shipping_total: ' . $order->get_shipping_total() . ', order_shipping_tax: ' . $order->get_shipping_tax() . ', session_selected_method: ' . $selected_method_session . ', frontend_applepay_amount: ' . $frontend_applepay_amount . ')' ); 347 peachpay_log( 348 'debug', 349 'Payments: Apple Pay process payment api request debug.', 350 array( 351 'event' => 'payments.convesiopay_gateway.applepay.payment.debug', 352 'component' => 'payments', 353 'feature' => 'convesiopay_gateway', 354 'operation' => 'applepay.payment', 355 'outcome' => 'debug', 356 'method' => __METHOD__, 357 'line' => __LINE__, 358 'data' => array( 359 'details' => $payment_data 360 ) 361 ) 362 ); 333 363 if ( $line_items_sum_cents !== $request_amount_cents ) { 334 peachpay_log( 'warning', 'ConvesioPay: Apple Pay request amount differs from line item sum for order ' . $order->get_order_number() . ' (request_cents: ' . $request_amount_cents . ', line_items_sum_cents: ' . $line_items_sum_cents . ')' ); 364 peachpay_log( 365 'warning', 366 'Payments: Apple Pay process payment warning.', 367 array( 368 'event' => 'payments.convesiopay_gateway.applepay.payment.warning', 369 'component' => 'payments', 370 'feature' => 'convesiopay_gateway', 371 'operation' => 'applepay.payment', 372 'outcome' => 'warning', 373 'method' => __METHOD__, 374 'line' => __LINE__, 375 'data' => array( 376 'details' => 'ConvesioPay: Apple Pay request amount differs from line item sum for order ' . $order->get_order_number() . ' (request_cents: ' . $request_amount_cents . ', line_items_sum_cents: ' . $line_items_sum_cents . ')' 377 ) 378 ) 379 ); 335 380 } 336 381 … … 349 394 350 395 if ( is_wp_error( $response ) ) { 351 peachpay_log( 'error', 'ConvesioPay: Apple Pay payment network error - ' . $response->get_error_message() . ' (order ' . $order->get_order_number() . ')' ); 352 throw new Exception( 'Network error: ' . $response->get_error_message() ); 396 throw new Exception( 'ConvesioPay: Apple Pay payment network error - ' . $response->get_error_message() . ' (order ' . $order->get_order_number() . ')' ); 353 397 } 354 398 … … 358 402 359 403 if ( $response_code !== 200 ) { 360 peachpay_log( 'debug', 'ConvesioPay: Apple Pay REQUEST (HTTP ' . $response_code . ') ' . $api_url . ' => ' . wp_json_encode( $payment_data ) );361 peachpay_log( 'debug', 'ConvesioPay: Apple Pay RESPONSE (HTTP ' . $response_code . ') => ' . $response_body );362 peachpay_log( 'error', 'ConvesioPay: Apple Pay payment API error HTTP ' . $response_code . ' (order ' . $order->get_order_number() . ')' );363 404 // Extract error message from response 364 405 $error_message = 'ConvesioPay API error (HTTP ' . $response_code . ')'; … … 378 419 379 420 if ( empty( $status ) || empty( $payment_id ) ) { 380 peachpay_log( 'error', 'ConvesioPay: Apple Pay payment invalid response - missing status or id (order ' . $order->get_order_number() . ')' ); 381 throw new Exception( 'Invalid response from ConvesioPay' ); 421 throw new Exception( 'Invalid response from ConvesioPay status: ' . $status . ', payment_id: ' . $payment_id ); 382 422 } 383 423 … … 448 488 $order->save(); 449 489 450 peachpay_log( 'info', 'ConvesioPay: Apple Pay payment success - order ' . $order->get_order_number() . ', payment_id ' . $payment_id . ', status ' . $status ); 490 $peachpay_log_type = "info"; 491 $peachpay_log_message = 'ConvesioPay ConvesioPay Apple Pay process payment success for order id - ' . $order_id; 492 if ( $status === 'Refused' || $status === 'Blocked' ) { 493 $peachpay_log_type = "error"; 494 $peachpay_log_message = 'ConvesioPay ConvesioPay Apple Pay process payment ' . strtolower($status) . ' for order id - ' . $order_id; 495 } 496 peachpay_log( 497 $peachpay_log_type, 498 $peachpay_log_message, 499 array( 500 'event' => 'payments.convesiopay_gateway.applepay.payment.' . strtolower($status), 501 'component' => 'payments', 502 'feature' => 'convesiopay_gateway', 503 'operation' => 'applepay.payment', 504 'outcome' => strtolower($status), 505 'method' => __METHOD__, 506 'line' => __LINE__, 507 'data' => array( 508 'response_data' => $response_data 509 ) 510 ) 511 ); 512 451 513 return array( 452 514 'result' => 'success', … … 454 516 ); 455 517 } else { 456 peachpay_log( 'error', 'ConvesioPay: Apple Pay payment failed - status ' . $status . ' (order ' . $order->get_order_number() . ')' );457 518 throw new Exception( 'Payment failed with status: ' . $status ); 458 519 } 459 520 } catch ( Exception $e ) { 460 peachpay_log( 'error', 'ConvesioPay: Apple Pay payment exception - ' . $e->getMessage() . ' (order ' . $order->get_order_number() . ')' ); 521 peachpay_log( 522 'error', 523 'Payments: Apple Pay process payment failed.', 524 array( 525 'event' => 'payments.convesiopay_gateway.applepay.payment.failed', 526 'component' => 'payments', 527 'feature' => 'convesiopay_gateway', 528 'operation' => 'applepay.payment', 529 'outcome' => 'failed', 530 'method' => __METHOD__, 531 'line' => __LINE__, 532 'data' => array( 533 'details' => 'ConvesioPay: Apple Pay payment exception - ' . $e->getMessage() . ' (order ' . $order->get_order_number() . ')' 534 ) 535 ) 536 ); 461 537 $order->add_order_note( 462 538 sprintf( -
peachpay-for-woocommerce/trunk/core/payments/convesiopay/gateways/class-peachpay-convesiopay-card-gateway.php
r3486614 r3490786 16 16 */ 17 17 class PeachPay_ConvesioPay_Card_Gateway extends PeachPay_Payment_Gateway { 18 /** 19 * Track whether the renewal hook has been registered. 20 * 21 * @var bool 22 */ 23 private static $renewal_hook_registered = false; 24 18 25 /** 19 26 * Track if gateway was properly initialized … … 86 93 add_action( 'admin_footer', array( $this, 'inject_admin_card_icons' ) ); 87 94 88 // Subscription renewal support 89 $gateway = $this; 90 add_action( 91 'woocommerce_scheduled_subscription_payment_' . $this->id, 92 function ( $renewal_total, $renewal_order ) use ( $gateway ) { 93 if ( ! function_exists( 'wcs_get_subscriptions_for_renewal_order' ) ) { 94 return; 95 } 96 $subscriptions = wcs_get_subscriptions_for_renewal_order( $renewal_order ); 97 $subscription = array_pop( $subscriptions ); 98 if ( ! $subscription ) { 99 return; 100 } 101 $parent_order = wc_get_order( $subscription->get_parent_id() ); 102 $gateway->process_subscription_renewal( $parent_order, $renewal_order, $renewal_total ); 103 }, 104 10, 105 2 106 ); 95 // Subscription renewal support. 96 $this->register_subscription_renewal_hook(); 107 97 108 98 // Initialize form fields … … 110 100 // Mark as initialized 111 101 $this->initialized = true; 102 } 103 104 /** 105 * Register subscription renewal hook once per request. 106 */ 107 private function register_subscription_renewal_hook() { 108 if ( self::$renewal_hook_registered ) { 109 return; 110 } 111 add_action( 112 'woocommerce_scheduled_subscription_payment_' . $this->id, 113 array( $this, 'handle_subscription_renewal_payment' ), 114 10, 115 2 116 ); 117 self::$renewal_hook_registered = true; 118 } 119 120 /** 121 * Handle scheduled subscription payment for card ConvesioPay gateway. 122 * 123 * @param float $renewal_total Renewal amount. 124 * @param WC_Order $renewal_order Renewal order. 125 */ 126 public function handle_subscription_renewal_payment( $renewal_total, $renewal_order ) { 127 if ( ! function_exists( 'wcs_get_subscriptions_for_renewal_order' ) ) { 128 peachpay_log( 129 'error', 130 'Payments: Subscription renewal failed.', 131 array( 132 'event' => 'payments.convesiopay_gateway.subscription.renewal.failed', 133 'component' => 'payments', 134 'feature' => 'convesiopay_gateway', 135 'operation' => 'subscription.renewal', 136 'outcome' => 'failed', 137 'line' => __LINE__, 138 'function' => __FUNCTION__, 139 'file' => __FILE__, 140 'class' => __CLASS__, 141 'method' => __METHOD__, 142 'data' => array( 143 'renewal_total' => $renewal_total, 144 'details' => 'function wcs_get_subscriptions_for_renewal_order not found', 145 ), 146 ) 147 ); 148 return; 149 } 150 $subscriptions = wcs_get_subscriptions_for_renewal_order( $renewal_order ); 151 $subscription = array_pop( $subscriptions ); 152 if ( ! $subscription ) { 153 peachpay_log( 154 'error', 155 'Convesiopay Card Subscription renewal failed - no subscription found for renewal order', 156 array( 157 'event' => 'payments.convesiopay_gateway.subscription.renewal.failed', 158 'component' => 'payments', 159 'feature' => 'convesiopay_gateway', 160 'operation' => 'subscription.renewal', 161 'outcome' => 'failed', 162 'line' => __LINE__, 163 'function' => __FUNCTION__, 164 'file' => __FILE__, 165 'class' => __CLASS__, 166 'method' => __METHOD__, 167 'data' => array( 168 'renewal_total' => $renewal_total, 169 'details' => 'no subscription found for renewal order', 170 ), 171 ) 172 ); 173 return; 174 } 175 $parent_order = wc_get_order( $subscription->get_parent_id() ); 176 if ( ! $parent_order ) { 177 peachpay_log( 178 'error', 179 'Convesiopay Card Subscription renewal failed - no parent order found for subscription', 180 array( 181 'event' => 'payments.convesiopay_gateway.subscription.renewal.failed', 182 'component' => 'payments', 183 'feature' => 'convesiopay_gateway', 184 'operation' => 'subscription.renewal', 185 'outcome' => 'failed', 186 'line' => __LINE__, 187 'function' => __FUNCTION__, 188 'file' => __FILE__, 189 'class' => __CLASS__, 190 'method' => __METHOD__, 191 'data' => array( 192 'renewal_total' => $renewal_total, 193 'parent_order_id' => $subscription->get_parent_id(), 194 'details' => 'no parent order found for subscription', 195 ), 196 ) 197 ); 198 return; 199 } 200 201 peachpay_log( 202 'debug', 203 'ConvesioPay Card Subscription renewal debug for subscription id - ' . $subscription->get_id(), 204 array( 205 'event' => 'payments.convesiopay_gateway.subscription.renewal.debug', 206 'component' => 'payments', 207 'feature' => 'convesiopay_gateway', 208 'operation' => 'subscription.renewal', 209 'outcome' => 'debug', 210 'line' => __LINE__, 211 'function' => __FUNCTION__, 212 'file' => __FILE__, 213 'class' => __CLASS__, 214 'method' => __METHOD__, 215 'data' => array( 216 'renewal_total' => $renewal_total 217 ), 218 ) 219 ); 220 221 $this->process_subscription_renewal( $parent_order, $renewal_order, $renewal_total ); 222 223 peachpay_log( 224 'debug', 225 'ConvesioPay Card Subscription renewal debug for subscription id - ' . $subscription->get_id() . ' completed', 226 array( 227 'event' => 'payments.convesiopay_gateway.subscription.renewal.debug', 228 'component' => 'payments', 229 'feature' => 'convesiopay_gateway', 230 'operation' => 'subscription.renewal', 231 'outcome' => 'debug', 232 'line' => __LINE__, 233 'function' => __FUNCTION__, 234 'file' => __FILE__, 235 'class' => __CLASS__, 236 'method' => __METHOD__, 237 ) 238 ); 112 239 } 113 240 … … 246 373 private function create_fallback_transaction_id() { 247 374 $transaction_id = 'cvp_card_tx_' . time() . '_' . wp_rand( 1000, 9999 ); 248 peachpay_log( 'debug', 'ConvesioPay: Local fallback transaction id - ' . $transaction_id );249 375 return $transaction_id; 250 376 } … … 739 865 // Make API call to ConvesioPay 740 866 $api_url = $config['api_url'] . '/payments'; 741 peachpay_log( 'debug', 'ConvesioPay: Card payment API request for order ' . $order->get_order_number() . ' (amount: ' . $order_amount . ' USD)' ); 867 peachpay_log( 868 'debug', 869 'ConvesioPay Card process payment debug for order id - ' . $order_id, 870 array( 871 'event' => 'payments.convesiopay_gateway.card.payment.debug', 872 'component' => 'payments', 873 'feature' => 'convesiopay_gateway', 874 'operation' => 'card.payment', 875 'outcome' => 'debug', 876 'line' => __LINE__, 877 'function' => __FUNCTION__, 878 'file' => __FILE__, 879 'class' => __CLASS__, 880 'method' => __METHOD__, 881 'data' => array( 882 'api_url' => $api_url, 883 'payment_data' => $payment_data, 884 ), 885 ) 886 ); 742 887 743 888 $response = wp_remote_post( $api_url, array( … … 752 897 753 898 if ( is_wp_error( $response ) ) { 754 peachpay_log( 'error', 'ConvesioPay: Card payment network error - ' . $response->get_error_message() . ' (order ' . $order->get_order_number() . ')' );755 899 throw new Exception( 'Network error: ' . $response->get_error_message() ); 756 900 } … … 761 905 762 906 if ( $response_code !== 200 ) { 763 peachpay_log( 'debug', 'ConvesioPay: Card REQUEST (HTTP ' . $response_code . ') ' . $api_url . ' => ' . wp_json_encode( $payment_data ) );764 peachpay_log( 'debug', 'ConvesioPay: Card RESPONSE (HTTP ' . $response_code . ') => ' . $response_body );765 peachpay_log( 'error', 'ConvesioPay: Card payment API error HTTP ' . $response_code . ' - ' . substr( $response_body, 0, 300 ) . ' (order ' . $order->get_order_number() . ')' );766 907 throw new Exception( 'ConvesioPay API error (HTTP ' . $response_code . '): ' . $response_body ); 767 908 } … … 781 922 782 923 if ( empty( $status ) || empty( $transaction_id ) ) { 783 peachpay_log( 'error', 'ConvesioPay: Card payment invalid response - missing status or id (order ' . $order->get_order_number() . ')' ); 924 peachpay_log( 925 'error', 926 'ConvesioPay Card process payment failed - invalid response for order id - ' . $order_id, 927 array( 928 'event' => 'payments.convesiopay_gateway.card.payment.failed', 929 'component' => 'payments', 930 'feature' => 'convesiopay_gateway', 931 'operation' => 'card.payment', 932 'outcome' => 'failed', 933 'method' => __METHOD__, 934 'line' => __LINE__, 935 'data' => array( 936 'response_data' => $response_data 937 ) 938 ) 939 ); 784 940 throw new Exception( 'Invalid response from ConvesioPay' ); 785 941 } … … 861 1017 $order->save(); 862 1018 863 peachpay_log( 'info', 'ConvesioPay: Card payment success - order ' . $order->get_order_number() . ', payment_id ' . $transaction_id . ', status ' . $status ); 1019 $peachpay_log_type = "info"; 1020 $peachpay_log_message = 'ConvesioPay Card process payment success for order id - ' . $order_id; 1021 if ( $status === 'Refused' || $status === 'Blocked' ) { 1022 $peachpay_log_type = "error"; 1023 $peachpay_log_message = 'ConvesioPay Card process payment ' . strtolower($status) . ' for order id - ' . $order_id; 1024 } 1025 peachpay_log( 1026 $peachpay_log_type, 1027 $peachpay_log_message, 1028 array( 1029 'event' => 'payments.convesiopay_gateway.card.payment.' . strtolower($status), 1030 'component' => 'payments', 1031 'feature' => 'convesiopay_gateway', 1032 'operation' => 'card.payment', 1033 'outcome' => strtolower($status), 1034 'method' => __METHOD__, 1035 'line' => __LINE__, 1036 'data' => array( 1037 'response_data' => $response_data 1038 ) 1039 ) 1040 ); 864 1041 return array( 865 1042 'result' => 'success', … … 867 1044 ); 868 1045 } else { 869 peachpay_log( 'error', 'ConvesioPay: Card payment failed - status ' . $status . ' (order ' . $order->get_order_number() . ')' ); 1046 peachpay_log( 1047 'error', 1048 'ConvesioPay Card process payment failed - status ' . $status . ' for order id - ' . $order_id, 1049 array( 1050 'event' => 'payments.convesiopay_gateway.card.payment.failed', 1051 'component' => 'payments', 1052 'feature' => 'convesiopay_gateway', 1053 'operation' => 'card.payment', 1054 'outcome' => 'failed', 1055 'method' => __METHOD__, 1056 'line' => __LINE__, 1057 'data' => array( 1058 'response_data' => $response_data 1059 ) 1060 ) 1061 ); 870 1062 throw new Exception( 'Payment failed with status: ' . $status ); 871 1063 } 872 1064 873 1065 } catch ( Exception $e ) { 874 peachpay_log( 'error', 'ConvesioPay: Card payment exception - ' . $e->getMessage() . ' (order ' . $order->get_order_number() . ')' ); 1066 peachpay_log( 1067 'error', 1068 'ConvesioPay Card process payment failed - exception', 1069 array( 1070 'event' => 'payments.convesiopay_gateway.card.payment.failed', 1071 'component' => 'payments', 1072 'feature' => 'convesiopay_gateway', 1073 'operation' => 'card.payment', 1074 'outcome' => 'failed', 1075 'line' => __LINE__, 1076 'function' => __FUNCTION__, 1077 'file' => __FILE__, 1078 'class' => __CLASS__, 1079 'method' => __METHOD__, 1080 'data' => array( 1081 'message' => $e->getMessage(), 1082 'code' => $e->getCode(), 1083 'file' => $e->getFile(), 1084 'line' => $e->getLine(), 1085 'trace' => $e->getTraceAsString(), 1086 ) 1087 ) 1088 ); 875 1089 $order->add_order_note( sprintf( __( 'ConvesioPay payment failed: %s', 'peachpay-for-woocommerce' ), $e->getMessage() ) ); 876 1090 wc_add_notice( __( 'Payment failed: ', 'peachpay-for-woocommerce' ) . $e->getMessage(), 'error' ); … … 954 1168 955 1169 if ( ! $payment_id ) { 956 peachpay_log( 'error', 'ConvesioPay: Refund - payment ID not found for order ' . $order->get_order_number() ); 1170 peachpay_log( 1171 'error', 1172 'ConvesioPay Card process refund failed - payment ID not found for order id - ' . $order_id, 1173 array( 1174 'event' => 'payments.convesiopay_gateway.refund.failed', 1175 'component' => 'payments', 1176 'feature' => 'convesiopay_gateway', 1177 'operation' => 'refund', 1178 'outcome' => 'failed', 1179 'method' => __METHOD__, 1180 'line' => __LINE__, 1181 ) 1182 ); 957 1183 return new WP_Error( 'convesiopay_refund_error', __( 'Payment ID not found for this order.', 'peachpay-for-woocommerce' ) ); 958 1184 } … … 976 1202 // Build refund endpoint URL 977 1203 $refund_endpoint = $config['api_url'] . '/payments/' . $payment_id . '/refund'; 978 peachpay_log( 'debug', 'ConvesioPay: Refund API request for order ' . $order->get_order_number() . ', payment ' . $payment_id . ', amount ' . $refund_data['amount'] . ' ' . $refund_data['currency'] ); 1204 peachpay_log( 1205 'debug', 1206 'ConvesioPay Card process refund debug for order id - ' . $order_id, 1207 array( 1208 'event' => 'payments.convesiopay_gateway.refund.debug', 1209 'component' => 'payments', 1210 'feature' => 'convesiopay_gateway', 1211 'operation' => 'refund', 1212 'outcome' => 'debug', 1213 'method' => __METHOD__, 1214 'line' => __LINE__, 1215 'data' => array( 1216 'api_url' => $refund_endpoint, 1217 'request_data' => $refund_data, 1218 ) 1219 ) 1220 ); 979 1221 980 1222 // Add order note for refund request … … 998 1240 999 1241 if ( is_wp_error( $response ) ) { 1000 peachpay_log( 'error', 'ConvesioPay: Refund network error - ' . $response->get_error_message() . ' (order ' . $order->get_order_number() . ', payment ' . $payment_id . ')' ); 1242 peachpay_log( 1243 'error', 1244 'ConvesioPay Card process refund failed - network error for order id - ' . $order_id, 1245 array( 1246 'event' => 'payments.convesiopay_gateway.refund.failed', 1247 'component' => 'payments', 1248 'feature' => 'convesiopay_gateway', 1249 'operation' => 'refund', 1250 'outcome' => 'failed', 1251 'line' => __LINE__, 1252 'function' => __FUNCTION__, 1253 'file' => __FILE__, 1254 'class' => __CLASS__, 1255 'method' => __METHOD__, 1256 'data' => array( 1257 'error_message' => $response->get_error_message() 1258 ) 1259 ) 1260 ); 1001 1261 $order->add_order_note( sprintf( 1002 1262 __( 'ConvesioPay refund response: Network error - %s', 'peachpay-for-woocommerce' ), … … 1012 1272 if ( $response_code !== 200 ) { 1013 1273 $error_message = isset( $response_data['message'] ) ? $response_data['message'] : 'Refund failed (HTTP ' . $response_code . ')'; 1014 peachpay_log( 'error', 'ConvesioPay: Refund API error - ' . $error_message . ' (order ' . $order->get_order_number() . ', payment ' . $payment_id . ')' ); 1274 peachpay_log( 1275 'error', 1276 'ConvesioPay Card process refund failed - API error for order id - ' . $order_id, 1277 array( 1278 'event' => 'payments.convesiopay_gateway.refund.failed', 1279 'component' => 'payments', 1280 'feature' => 'convesiopay_gateway', 1281 'operation' => 'refund', 1282 'outcome' => 'failed', 1283 'line' => __LINE__, 1284 'function' => __FUNCTION__, 1285 'file' => __FILE__, 1286 'class' => __CLASS__, 1287 'method' => __METHOD__, 1288 'line' => __LINE__, 1289 'data' => array( 1290 'error_message' => $error_message 1291 ) 1292 ) 1293 ); 1015 1294 return new WP_Error( 'convesiopay_refund_error', $error_message ); 1016 1295 } … … 1018 1297 // Refund successful - extract refund details from response 1019 1298 $refund_id = isset( $response_data['id'] ) ? $response_data['id'] : ''; 1020 peachpay_log( 'info', 'ConvesioPay: Refund success - order ' . $order->get_order_number() . ', refund_id ' . $refund_id ); 1299 peachpay_log( 1300 'info', 1301 'ConvesioPay Card process refund success for order id - ' . $order_id, 1302 array( 1303 'event' => 'payments.convesiopay_gateway.refund.success', 1304 'component' => 'payments', 1305 'feature' => 'convesiopay_gateway', 1306 'operation' => 'refund', 1307 'outcome' => 'success', 1308 'line' => __LINE__, 1309 'function' => __FUNCTION__, 1310 'file' => __FILE__, 1311 'class' => __CLASS__, 1312 'method' => __METHOD__, 1313 'data' => array( 1314 'response_data' => $response_data 1315 ) 1316 ) 1317 ); 1021 1318 1022 1319 // Add detailed order note … … 1045 1342 1046 1343 } catch ( Exception $e ) { 1047 peachpay_log( 'error', 'ConvesioPay: Refund exception - ' . $e->getMessage() . ' (order ' . $order->get_order_number() . ')' ); 1344 peachpay_log( 1345 'error', 1346 'ConvesioPay Card process refund failed - exception', 1347 array( 1348 'event' => 'payments.convesiopay_gateway.refund.failed', 1349 'component' => 'payments', 1350 'feature' => 'convesiopay_gateway', 1351 'operation' => 'refund', 1352 'outcome' => 'failed', 1353 'method' => __METHOD__, 1354 'line' => __LINE__, 1355 'function' => __FUNCTION__, 1356 'file' => __FILE__, 1357 'class' => __CLASS__, 1358 'method' => __METHOD__, 1359 'data' => array( 1360 'message' => $e->getMessage(), 1361 'code' => $e->getCode(), 1362 'file' => $e->getFile(), 1363 'line' => $e->getLine(), 1364 ) 1365 ) 1366 ); 1048 1367 return new WP_Error( 'convesiopay_refund_error', $e->getMessage() ); 1049 1368 } … … 1058 1377 */ 1059 1378 private function find_payment_by_order_number( $order_number, $config ) { 1060 peachpay_log( 'debug', 'ConvesioPay: GET /payments/list API request for order_number ' . $order_number ); 1379 peachpay_log( 1380 'debug', 1381 'ConvesioPay find payment by order number debug for order number - ' . $order_number, 1382 array( 1383 'event' => 'payments.convesiopay_gateway.event.debug', 1384 'component' => 'payments', 1385 'feature' => 'convesiopay_gateway', 1386 'operation' => 'event', 1387 'outcome' => 'debug', 1388 'method' => __METHOD__, 1389 'line' => __LINE__, 1390 'data' => array( 1391 'api_url' => $config['api_url'] . '/payments/list?orderNumber=' . urlencode( $order_number ) 1392 ))); 1061 1393 1062 1394 // Make API call to ConvesioPay to find payment by order number … … 1070 1402 1071 1403 if ( is_wp_error( $response ) ) { 1072 peachpay_log( 'error', 'ConvesioPay: GET /payments/list network error - ' . $response->get_error_message() . ' (order_number ' . $order_number . ')' ); 1404 peachpay_log( 1405 'error', 1406 'ConvesioPay find payment by order number failed - network error for order number - ' . $order_number, 1407 array( 1408 'event' => 'payments.convesiopay_gateway.find_payment_by_order_number.failed', 1409 'component' => 'payments', 1410 'feature' => 'convesiopay_gateway', 1411 'operation' => 'find_payment_by_order_number', 1412 'outcome' => 'failed', 1413 'line' => __LINE__, 1414 'function' => __FUNCTION__, 1415 'file' => __FILE__, 1416 'class' => __CLASS__, 1417 'method' => __METHOD__, 1418 'data' => array( 1419 'error_message' => $response->get_error_message() 1420 ) 1421 ) 1422 ); 1073 1423 return false; 1074 1424 } … … 1079 1429 1080 1430 if ( $response_code !== 200 || empty( $response_data['payments'] ) ) { 1081 peachpay_log( 'warning', 'ConvesioPay: GET /payments/list - HTTP ' . $response_code . ' or no payments (order_number ' . $order_number . ')' ); 1431 peachpay_log( 1432 'warning', 1433 'ConvesioPay find payment by order number warning - HTTP ' . $response_code . ' or no payments (order_number ' . $order_number . ')', 1434 array( 1435 'event' => 'payments.convesiopay_gateway.find_payment_by_order_number.warning', 1436 'component' => 'payments', 1437 'feature' => 'convesiopay_gateway', 1438 'operation' => 'find_payment_by_order_number', 1439 'outcome' => 'warning', 1440 'line' => __LINE__, 1441 'function' => __FUNCTION__, 1442 'file' => __FILE__, 1443 'class' => __CLASS__, 1444 'method' => __METHOD__, 1445 'data' => array( 1446 'response_code' => $response_code, 1447 'response_body' => $response_body, 1448 'response_data' => $response_data 1449 ) 1450 ) 1451 ); 1082 1452 return false; 1083 1453 } … … 1085 1455 $payment_id = $response_data['payments'][0]['id'] ?? false; 1086 1456 if ( $payment_id ) { 1087 peachpay_log( 'info', 'ConvesioPay: GET /payments/list found payment ' . $payment_id . ' for order_number ' . $order_number ); 1457 peachpay_log( 1458 'info', 1459 'ConvesioPay find payment by order number success for order number - ' . $order_number, 1460 array( 1461 'event' => 'payments.convesiopay_gateway.find_payment_by_order_number.success', 1462 'component' => 'payments', 1463 'feature' => 'convesiopay_gateway', 1464 'operation' => 'find_payment_by_order_number', 1465 'outcome' => 'success', 1466 'line' => __LINE__, 1467 'function' => __FUNCTION__, 1468 'file' => __FILE__, 1469 'class' => __CLASS__, 1470 'method' => __METHOD__, 1471 'data' => array( 1472 'response_data' => $response_data 1473 ) 1474 ) 1475 ); 1088 1476 } 1089 1477 return $payment_id; … … 1250 1638 // Idempotency: do not charge if this renewal order is already paid (prevents double charge from duplicate hooks or webhook + sync race). 1251 1639 if ( $renewal_order->has_status( array( 'processing', 'completed' ) ) ) { 1252 peachpay_log( 'debug', 'ConvesioPay: Stored-card renewal skipped - order ' . $renewal_order->get_order_number() . ' already paid (status: ' . $renewal_order->get_status() . ').' ); 1640 peachpay_log( 1641 'warning', 1642 'ConvesioPay Card Subscription renewal warning - renewal order id - ' . $renewal_order->get_id() . ' already paid (status: ' . $renewal_order->get_status() . ')', 1643 array( 1644 'event' => 'payments.convesiopay_gateway.subscription.renewal.warning', 1645 'component' => 'payments', 1646 'feature' => 'convesiopay_gateway', 1647 'operation' => 'subscription.renewal', 1648 'outcome' => 'warning', 1649 'line' => __LINE__, 1650 'function' => __FUNCTION__, 1651 'file' => __FILE__, 1652 'class' => __CLASS__, 1653 'method' => __METHOD__, 1654 'data' => array( 1655 'order_id' => $renewal_order->get_id(), 1656 'order_status' => $renewal_order->get_status(), 1657 'order_number' => $renewal_order->get_order_number(), 1658 'renewal_total'=> isset( $renewal_total ) ? $renewal_total : null 1659 ), 1660 ) 1661 ); 1253 1662 return; 1254 1663 } 1664 1255 1665 if ( ! empty( $renewal_order->get_meta( '_convesiopay_payment_id' ) ) ) { 1256 peachpay_log( 'debug', 'ConvesioPay: Stored-card renewal skipped - order ' . $renewal_order->get_order_number() . ' already has ConvesioPay payment ID.' ); 1666 peachpay_log( 1667 'warning', 1668 'ConvesioPay Card Subscription renewal failed - renewal order id - ' . $renewal_order->get_id() . ' already has a payment id', 1669 array( 1670 'event' => 'payments.convesiopay_gateway.subscription.renewal.failed', 1671 'component' => 'payments', 1672 'feature' => 'convesiopay_gateway', 1673 'operation' => 'subscription.renewal', 1674 'outcome' => 'failed', 1675 'line' => __LINE__, 1676 'function' => __FUNCTION__, 1677 'file' => __FILE__, 1678 'class' => __CLASS__, 1679 'method' => __METHOD__, 1680 'data' => array( 1681 'convesiopay_payment_id' => $renewal_order->get_meta( '_convesiopay_payment_id' ), 1682 'order_id' => $renewal_order->get_id(), 1683 'order_status' => $renewal_order->get_status(), 1684 'order_number' => $renewal_order->get_order_number(), 1685 'renewal_total'=> isset( $renewal_total ) ? $renewal_total : null 1686 ), 1687 ) 1688 ); 1257 1689 return; 1258 }1259 1260 // If subscription already has another completed renewal order created recently (e.g. duplicate scheduled action created two renewal orders), skip charging this one to avoid double charge.1261 if ( function_exists( 'wcs_get_subscriptions_for_renewal_order' ) ) {1262 $subscriptions = wcs_get_subscriptions_for_renewal_order( $renewal_order );1263 $subscription = is_array( $subscriptions ) ? array_pop( $subscriptions ) : null;1264 if ( $subscription && is_callable( array( $subscription, 'get_related_orders' ) ) ) {1265 $renewal_order_ids = $subscription->get_related_orders( 'ids', 'renewal' );1266 $recent_cutoff = strtotime( '-2 hours' );1267 foreach ( (array) $renewal_order_ids as $other_id ) {1268 if ( (int) $other_id === (int) $renewal_order->get_id() ) {1269 continue;1270 }1271 $other_order = wc_get_order( $other_id );1272 if ( ! $other_order || ! $other_order->has_status( array( 'processing', 'completed' ) ) ) {1273 continue;1274 }1275 $created = $other_order->get_date_created();1276 if ( $created && $created->getTimestamp() >= $recent_cutoff ) {1277 peachpay_log( 'info', 'ConvesioPay: Stored-card renewal skipped - subscription already has completed renewal order #' . $other_order->get_order_number() . ' (possible duplicate scheduled action). Order ' . $renewal_order->get_order_number() . ' not charged.' );1278 $renewal_order->add_order_note( sprintf(1279 __( 'Renewal payment skipped: subscription already has a completed renewal order #%s. This may be a duplicate; no charge was made.', 'peachpay-for-woocommerce' ),1280 $other_order->get_order_number()1281 ) );1282 return;1283 }1284 }1285 }1286 1690 } 1287 1691 … … 1291 1695 1292 1696 if ( empty( $customer_id ) || empty( $stored_payment_method_id ) ) { 1293 peachpay_log( 'error', 'ConvesioPay: Stored-card renewal - missing customer_id or stored_payment_method_id (order ' . $renewal_order->get_order_number() . ')' ); 1294 throw new Exception( __( 'Missing stored payment method for subscription renewal.', 'peachpay-for-woocommerce' ) ); 1697 peachpay_log( 1698 'error', 1699 'ConvesioPay Card Subscription renewal failed - missing customer id or stored payment method id', 1700 array( 1701 'event' => 'payments.convesiopay_gateway.subscription.renewal.failed', 1702 'component' => 'payments', 1703 'feature' => 'convesiopay_gateway', 1704 'operation' => 'subscription.renewal', 1705 'outcome' => 'failed', 1706 'line' => __LINE__, 1707 'function' => __FUNCTION__, 1708 'file' => __FILE__, 1709 'class' => __CLASS__, 1710 'method' => __METHOD__, 1711 'data' => array( 1712 'parent_order_id' => $parent_order->get_id(), 1713 'renewal_order_id' => $renewal_order->get_id(), 1714 'customer_id' => $customer_id, 1715 'stored_payment_method_id' => $stored_payment_method_id, 1716 ), 1717 ) 1718 ); 1719 throw new Exception( __( 'Missing customer id or stored payment method id for subscription renewal.', 'peachpay-for-woocommerce' ) ); 1295 1720 } 1296 1721 1297 1722 $config = $this->get_convesiopay_config(); 1298 1723 if ( empty( $config['secret_key'] ) ) { 1299 peachpay_log( 'error', 'ConvesioPay: Stored-card renewal - ConvesioPay not configured (order ' . $renewal_order->get_order_number() . ')' ); 1300 throw new Exception( __( 'ConvesioPay is not properly configured.', 'peachpay-for-woocommerce' ) ); 1724 throw new Exception( __( 'ConvesioPay is not properly configured. Missing secret key.', 'peachpay-for-woocommerce' ) ); 1301 1725 } 1302 1726 … … 1316 1740 1317 1741 // Call ConvesioPay Card On File endpoint 1318 peachpay_log( 'debug', 'ConvesioPay: POST /payments/stored-card API request for renewal order ' . $renewal_order->get_order_number() ); 1742 peachpay_log( 1743 'debug', 1744 'Convesiopay Card Subscription renewal api request debug - renewal order id - ' . $renewal_order->get_id(), 1745 array( 1746 'event' => 'payments.convesiopay_gateway.subscription.renewal.debug', 1747 'component' => 'payments', 1748 'feature' => 'convesiopay_gateway', 1749 'operation' => 'subscription.renewal', 1750 'outcome' => 'debug', 1751 'line' => __LINE__, 1752 'function' => __FUNCTION__, 1753 'file' => __FILE__, 1754 'class' => __CLASS__, 1755 'method' => __METHOD__, 1756 'data' => array( 1757 'api_url' => $config['api_url'] . '/payments/stored-card', 1758 'request_data' => $request_data, 1759 ), 1760 ) 1761 ); 1319 1762 1320 1763 $response = wp_remote_post( $config['api_url'] . '/payments/stored-card', array( … … 1328 1771 1329 1772 if ( is_wp_error( $response ) ) { 1330 peachpay_log( 'error', 'ConvesioPay: Stored-card renewal network error - ' . $response->get_error_message() . ' (order ' . $renewal_order->get_order_number() . ')' ); 1773 peachpay_log( 1774 'error', 1775 'ConvesioPay Card Subscription renewal failed - network error for renewal order id - ' . $renewal_order->get_id(), 1776 array( 1777 'event' => 'payments.convesiopay_gateway.subscription.renewal.failed', 1778 'component' => 'payments', 1779 'feature' => 'convesiopay_gateway', 1780 'operation' => 'subscription.renewal', 1781 'outcome' => 'failed', 1782 'line' => __LINE__, 1783 'function' => __FUNCTION__, 1784 'file' => __FILE__, 1785 'class' => __CLASS__, 1786 'method' => __METHOD__, 1787 'data' => array( 1788 'request_data' => $request_data, 1789 'error_message' => $response->get_error_message(), 1790 ), 1791 ) 1792 ); 1331 1793 throw new Exception( 'Network error: ' . $response->get_error_message() ); 1332 1794 } … … 1341 1803 1342 1804 if ( $response_code === 200 && in_array( $status, $success_statuses, true ) ) { 1343 peachpay_log( 'info', 'ConvesioPay: Stored-card renewal success - order ' . $renewal_order->get_order_number() . ', payment_id ' . $payment_id . ', status ' . $status ); 1805 peachpay_log( 1806 'info', 1807 'ConvesioPay Card Subscription renewal success - renewal order id - ' . $renewal_order->get_id(), 1808 array( 1809 'event' => 'payments.convesiopay_gateway.subscription.renewal.success', 1810 'component' => 'payments', 1811 'feature' => 'convesiopay_gateway', 1812 'operation' => 'subscription.renewal', 1813 'outcome' => 'success', 1814 'method' => __METHOD__, 1815 'line' => __LINE__, 1816 'data' => array( 1817 'response' => $response_data 1818 ) 1819 ) 1820 ); 1344 1821 // Payment successful 1345 1822 $renewal_order->update_meta_data( '_convesiopay_payment_id', $payment_id ); … … 1354 1831 } else { 1355 1832 $error_message = $response_data['message'] ?? $response_data['body']['message'] ?? 'Unknown error'; 1356 peachpay_log( 'error', 'ConvesioPay: Stored-card renewal failed - HTTP ' . $response_code . ' - ' . $error_message . ' (order ' . $renewal_order->get_order_number() . ')' ); 1833 peachpay_log( 1834 'error', 1835 'ConvesioPay Card Subscription renewal failed - renewal order id - ' . $renewal_order->get_id(), 1836 array( 1837 'event' => 'payments.convesiopay_gateway.subscription.renewal.failed', 1838 'component' => 'payments', 1839 'feature' => 'convesiopay_gateway', 1840 'operation' => 'subscription.renewal', 1841 'outcome' => 'failed', 1842 'line' => __LINE__, 1843 'function' => __FUNCTION__, 1844 'file' => __FILE__, 1845 'class' => __CLASS__, 1846 'method' => __METHOD__, 1847 'data' => array( 1848 'request_data' => $request_data, 1849 'response_data' => $response_data, 1850 ), 1851 ) 1852 ); 1357 1853 throw new Exception( 'Renewal payment failed: ' . $error_message ); 1358 1854 } 1359 1855 } catch ( Exception $e ) { 1360 peachpay_log( 'error', 'ConvesioPay: Stored-card renewal exception - ' . $e->getMessage() . ' (order ' . $renewal_order->get_order_number() . ')' ); 1361 $renewal_order->update_status( 'failed', sprintf( 1362 __( 'ConvesioPay renewal failed: %s', 'peachpay-for-woocommerce' ), 1363 $e->getMessage() 1364 ) ); 1856 peachpay_log( 1857 'error', 1858 'ConvesioPay Card Subscription renewal failed - exception', 1859 array( 1860 'event' => 'payments.convesiopay_gateway.subscription.renewal.failed', 1861 'component' => 'payments', 1862 'feature' => 'convesiopay_gateway', 1863 'operation' => 'subscription.renewal', 1864 'outcome' => 'failed', 1865 'line' => __LINE__, 1866 'function' => __FUNCTION__, 1867 'file' => __FILE__, 1868 'class' => __CLASS__, 1869 'method' => __METHOD__, 1870 'data' => array( 1871 'message' => $e->getMessage(), 1872 'code' => $e->getCode(), 1873 'file' => $e->getFile(), 1874 'line' => $e->getLine(), 1875 'trace' => $e->getTraceAsString(), 1876 ) 1877 ) 1878 ); 1879 1880 // Keep renewal order state consistent on failure for retries/reporting. 1881 if ( $renewal_order instanceof WC_Order && ! $renewal_order->has_status( array( 'processing', 'completed' ) ) ) { 1882 $failure_note = sprintf( 1883 /* translators: %s: failure message */ 1884 __( 'ConvesioPay subscription renewal failed: %s', 'peachpay-for-woocommerce' ), 1885 $e->getMessage() 1886 ); 1887 $renewal_order->update_status( 'failed', $failure_note ); 1888 } 1365 1889 } 1366 1890 } -
peachpay-for-woocommerce/trunk/core/payments/convesiopay/gateways/class-peachpay-convesiopay-unified-gateway.php
r3471281 r3490786 17 17 */ 18 18 class PeachPay_ConvesioPay_Unified_Gateway extends PeachPay_Payment_Gateway { 19 /** 20 * Track whether the renewal hook has been registered. 21 * 22 * @var bool 23 */ 24 private static $renewal_hook_registered = false; 25 19 26 /** 20 27 * Track if gateway was properly initialized … … 93 100 add_action( 'admin_head', array( $this, 'hide_gateway_with_css' ) ); 94 101 95 // Subscription renewal support - route to Card Gateway 96 add_action( 97 'woocommerce_scheduled_subscription_payment_' . $this->id, 98 function ( $renewal_total, $renewal_order ) { 99 if ( ! function_exists( 'wcs_get_subscriptions_for_renewal_order' ) ) { 100 return; 101 } 102 $gateways = WC()->payment_gateways->payment_gateways(); 103 if ( isset( $gateways['peachpay_convesiopay_card'] ) ) { 104 $subscriptions = wcs_get_subscriptions_for_renewal_order( $renewal_order ); 105 $subscription = array_pop( $subscriptions ); 106 if ( ! $subscription ) { 107 return; 108 } 109 $parent_order = wc_get_order( $subscription->get_parent_id() ); 110 $gateways['peachpay_convesiopay_card']->process_subscription_renewal( $parent_order, $renewal_order, $renewal_total ); 111 } else { 112 $renewal_order->update_status( 'failed', __( 'ConvesioPay Card gateway not found.', 'peachpay-for-woocommerce' ) ); 113 } 114 }, 115 10, 116 2 117 ); 102 // Subscription renewal support - route to Card Gateway. 103 $this->register_subscription_renewal_hook(); 118 104 119 105 // Hook into checkout update to read selected method from POST … … 137 123 // Mark as initialized 138 124 $this->initialized = true; 125 } 126 127 /** 128 * Register subscription renewal hook once per request. 129 */ 130 private function register_subscription_renewal_hook() { 131 if ( self::$renewal_hook_registered ) { 132 return; 133 } 134 add_action( 135 'woocommerce_scheduled_subscription_payment_' . $this->id, 136 array( $this, 'handle_subscription_renewal_payment' ), 137 10, 138 2 139 ); 140 self::$renewal_hook_registered = true; 141 } 142 143 /** 144 * Handle scheduled subscription payment for unified ConvesioPay gateway. 145 * 146 * @param float $renewal_total Renewal amount. 147 * @param WC_Order $renewal_order Renewal order. 148 */ 149 public function handle_subscription_renewal_payment( $renewal_total, $renewal_order ) { 150 if ( ! function_exists( 'wcs_get_subscriptions_for_renewal_order' ) ) { 151 peachpay_log( 152 'error', 153 'ConvesioPay Unified Subscription renewal failed - wcs_get_subscriptions_for_renewal_order() unavailable.', 154 array( 155 'event' => 'payments.convesiopay_gateway.subscription.renewal.failed', 156 'component' => 'payments', 157 'feature' => 'convesiopay_gateway', 158 'operation' => 'subscription.renewal', 159 'outcome' => 'failed', 160 'line' => __LINE__, 161 'function' => __FUNCTION__, 162 'file' => __FILE__, 163 'class' => __CLASS__, 164 'method' => __METHOD__, 165 'data' => array( 166 'renewal_total' => $renewal_total, 167 ), 168 ) 169 ); 170 return; 171 } 172 173 $gateways = WC()->payment_gateways->payment_gateways(); 174 if ( ! isset( $gateways['peachpay_convesiopay_card'] ) ) { 175 $renewal_order->update_status( 'failed', __( 'ConvesioPay Card gateway not found.', 'peachpay-for-woocommerce' ) ); 176 return; 177 } 178 179 $subscriptions = wcs_get_subscriptions_for_renewal_order( $renewal_order ); 180 $subscription = array_pop( $subscriptions ); 181 if ( ! $subscription ) { 182 peachpay_log( 183 'error', 184 'ConvesioPay Unified Subscription renewal failed - no subscription found for renewal order.', 185 array( 186 'event' => 'payments.convesiopay_gateway.subscription.renewal.failed', 187 'component' => 'payments', 188 'feature' => 'convesiopay_gateway', 189 'operation' => 'subscription.renewal', 190 'outcome' => 'failed', 191 'line' => __LINE__, 192 'function' => __FUNCTION__, 193 'file' => __FILE__, 194 'class' => __CLASS__, 195 'method' => __METHOD__, 196 'data' => array( 197 'renewal_total' => $renewal_total, 198 ), 199 ) 200 ); 201 return; 202 } 203 204 $parent_order = wc_get_order( $subscription->get_parent_id() ); 205 if ( ! $parent_order ) { 206 peachpay_log( 207 'error', 208 'ConvesioPay Unified Subscription renewal failed - parent order not found.', 209 array( 210 'event' => 'payments.convesiopay_gateway.subscription.renewal.failed', 211 'component' => 'payments', 212 'feature' => 'convesiopay_gateway', 213 'operation' => 'subscription.renewal', 214 'outcome' => 'failed', 215 'line' => __LINE__, 216 'function' => __FUNCTION__, 217 'file' => __FILE__, 218 'class' => __CLASS__, 219 'method' => __METHOD__, 220 ) 221 ); 222 return; 223 } 224 225 peachpay_log( 226 'debug', 227 'ConvesioPay Unified Subscription renewal debug - delegating to card gateway.', 228 array( 229 'event' => 'payments.convesiopay_gateway.subscription.renewal.debug', 230 'component' => 'payments', 231 'feature' => 'convesiopay_gateway', 232 'operation' => 'subscription.renewal', 233 'outcome' => 'debug', 234 'line' => __LINE__, 235 'function' => __FUNCTION__, 236 'file' => __FILE__, 237 'class' => __CLASS__, 238 'method' => __METHOD__, 239 'data' => array( 240 'renewal_total' => $renewal_total, 241 ), 242 ) 243 ); 244 $gateways['peachpay_convesiopay_card']->process_subscription_renewal( $parent_order, $renewal_order, $renewal_total ); 245 peachpay_log( 246 'debug', 247 'ConvesioPay Unified Subscription renewal debug - card gateway delegation completed.', 248 array( 249 'event' => 'payments.convesiopay_gateway.subscription.renewal.debug', 250 'component' => 'payments', 251 'feature' => 'convesiopay_gateway', 252 'operation' => 'subscription.renewal', 253 'outcome' => 'debug', 254 'line' => __LINE__, 255 'function' => __FUNCTION__, 256 'file' => __FILE__, 257 'class' => __CLASS__, 258 'method' => __METHOD__, 259 ) 260 ); 139 261 } 140 262 … … 301 423 WC()->session->set( 'convesiopay_selected_method', $selected_method ); 302 424 if ( $previous_method !== $selected_method ) { 303 peachpay_log( 'debug', 'ConvesioPay: Unified checkout synced selected method on checkout_process => ' . $selected_method ); 425 peachpay_log( 426 'debug', 427 'Payments: Checkout method sync debug.', 428 array( 429 'event' => 'payments.convesiopay_gateway.checkout.method_sync.debug', 430 'component' => 'payments', 431 'feature' => 'convesiopay_gateway', 432 'operation' => 'checkout.method_sync', 433 'outcome' => 'debug', 434 'method' => __METHOD__, 435 'line' => __LINE__, 436 'data' => array( 437 'selected_method' => $selected_method, 438 'previous_method' => $previous_method, 439 ), 440 ) 441 ); 304 442 } 305 443 } … … 632 770 633 771 } catch ( Exception $e ) { 634 peachpay_log( 'error', 'ConvesioPay: Unified payment processing failed - ' . $e->getMessage() . ' (order ' . ( $order ? $order->get_order_number() : $order_id ) . ')' ); 772 peachpay_log( 773 'error', 774 'Payments: Unified process payment failed.', 775 array( 776 'event' => 'payments.convesiopay_gateway.process_payment.failed', 777 'component' => 'payments', 778 'feature' => 'convesiopay_gateway', 779 'operation' => 'process_payment', 780 'outcome' => 'failed', 781 'method' => __METHOD__, 782 'line' => __LINE__, 783 'data' => array( 784 'order_id' => $order_id, 785 'order_number' => ( $order && is_a( $order, 'WC_Order' ) ) ? $order->get_order_number() : $order_id, 786 'error_message' => $e->getMessage(), 787 ), 788 ) 789 ); 635 790 return array( 636 791 'result' => 'failure', … … 1066 1221 $status = $payment_data['status']; 1067 1222 1068 peachpay_log( 'info', 'ConvesioPay: Generic payment received - order ' . $order->get_order_number() . ', payment_id ' . $payment_id . ', method ' . $payment_method . ', status ' . $status ); 1223 peachpay_log( 1224 'info', 1225 'Payments: Generic payment received.', 1226 array( 1227 'event' => 'payments.convesiopay_gateway.generic_payment.received', 1228 'component' => 'payments', 1229 'feature' => 'convesiopay_gateway', 1230 'operation' => 'generic_payment.received', 1231 'outcome' => 'success', 1232 'method' => __METHOD__, 1233 'line' => __LINE__, 1234 'data' => array( 1235 'order_id' => $order->get_id(), 1236 'order_number' => $order->get_order_number(), 1237 'payment_id' => $payment_id, 1238 'payment_method' => $payment_method, 1239 'status' => $status, 1240 ), 1241 ) 1242 ); 1069 1243 1070 1244 // Set order transaction ID … … 1091 1265 $order->save(); 1092 1266 1093 peachpay_log( 'info', 'ConvesioPay: Generic payment completed - order ' . $order->get_order_number() . ', payment_id ' . $payment_id ); 1267 peachpay_log( 1268 'info', 1269 'Payments: Generic payment completed.', 1270 array( 1271 'event' => 'payments.convesiopay_gateway.generic_payment.completed', 1272 'component' => 'payments', 1273 'feature' => 'convesiopay_gateway', 1274 'operation' => 'generic_payment.completed', 1275 'outcome' => 'success', 1276 'method' => __METHOD__, 1277 'line' => __LINE__, 1278 'data' => array( 1279 'order_id' => $order->get_id(), 1280 'order_number' => $order->get_order_number(), 1281 'payment_id' => $payment_id, 1282 'payment_method' => $payment_method, 1283 'status' => $status, 1284 ), 1285 ) 1286 ); 1094 1287 return array( 1095 1288 'result' => 'success', … … 1312 1505 1313 1506 if ( ! $payment_id ) { 1314 peachpay_log( 'error', 'ConvesioPay: Refund - payment ID not found for order ' . $order->get_order_number() ); 1507 peachpay_log( 1508 'error', 1509 'Payments: Refund failed.', 1510 array( 1511 'event' => 'payments.convesiopay_gateway.refund.failed', 1512 'component' => 'payments', 1513 'feature' => 'convesiopay_gateway', 1514 'operation' => 'refund', 1515 'outcome' => 'failed', 1516 'method' => __METHOD__, 1517 'line' => __LINE__, 1518 'data' => array( 1519 'details' => 'ConvesioPay: Refund - payment ID not found for order ' . $order->get_order_number() 1520 ))); 1315 1521 return new WP_Error( 'convesiopay_refund_error', __( 'Payment ID not found for this order.', 'peachpay-for-woocommerce' ) ); 1316 1522 } … … 1334 1540 // Build refund endpoint URL 1335 1541 $refund_endpoint = $config['api_url'] . '/payments/' . $payment_id . '/refund'; 1336 peachpay_log( 'debug', 'ConvesioPay: Refund API request for order ' . $order->get_order_number() . ', payment ' . $payment_id . ', amount ' . $refund_data['amount'] . ' ' . $refund_data['currency'] ); 1542 peachpay_log( 1543 'debug', 1544 'Payments: Refund debug.', 1545 array( 1546 'event' => 'payments.convesiopay_gateway.refund.debug', 1547 'component' => 'payments', 1548 'feature' => 'convesiopay_gateway', 1549 'operation' => 'refund', 1550 'outcome' => 'debug', 1551 'method' => __METHOD__, 1552 'line' => __LINE__, 1553 'data' => array( 1554 'details' => 'ConvesioPay: Refund API request for order ' . $order->get_order_number() . ', payment ' . $payment_id . ', amount ' . $refund_data['amount'] . ' ' . $refund_data['currency'] 1555 ))); 1337 1556 1338 1557 // Add order note for refund request … … 1356 1575 1357 1576 if ( is_wp_error( $response ) ) { 1358 peachpay_log( 'error', 'ConvesioPay: Refund network error - ' . $response->get_error_message() . ' (order ' . $order->get_order_number() . ', payment ' . $payment_id . ')' ); 1577 peachpay_log( 1578 'error', 1579 'Payments: Refund failed.', 1580 array( 1581 'event' => 'payments.convesiopay_gateway.refund.failed', 1582 'component' => 'payments', 1583 'feature' => 'convesiopay_gateway', 1584 'operation' => 'refund', 1585 'outcome' => 'failed', 1586 'method' => __METHOD__, 1587 'line' => __LINE__, 1588 'data' => array( 1589 'details' => 'ConvesioPay: Refund network error - ' . $response->get_error_message() . ' (order ' . $order->get_order_number() . ', payment ' . $payment_id . ')' 1590 ))); 1359 1591 $order->add_order_note( sprintf( 1360 1592 __( 'ConvesioPay refund response: Network error - %s', 'peachpay-for-woocommerce' ), … … 1370 1602 if ( $response_code !== 200 ) { 1371 1603 $error_message = isset( $response_data['message'] ) ? $response_data['message'] : 'Refund failed (HTTP ' . $response_code . ')'; 1372 peachpay_log( 'error', 'ConvesioPay: Refund API error - ' . $error_message . ' (order ' . $order->get_order_number() . ', payment ' . $payment_id . ')' ); 1604 peachpay_log( 1605 'error', 1606 'Payments: Refund failed.', 1607 array( 1608 'event' => 'payments.convesiopay_gateway.refund.failed', 1609 'component' => 'payments', 1610 'feature' => 'convesiopay_gateway', 1611 'operation' => 'refund', 1612 'outcome' => 'failed', 1613 'method' => __METHOD__, 1614 'line' => __LINE__, 1615 'data' => array( 1616 'details' => 'ConvesioPay: Refund API error - ' . $error_message . ' (order ' . $order->get_order_number() . ', payment ' . $payment_id . ')' 1617 ))); 1373 1618 return new WP_Error( 'convesiopay_refund_error', $error_message ); 1374 1619 } … … 1376 1621 // Refund successful - extract refund details from response 1377 1622 $refund_id = isset( $response_data['id'] ) ? $response_data['id'] : ''; 1378 peachpay_log( 'info', 'ConvesioPay: Refund success - order ' . $order->get_order_number() . ', refund_id ' . $refund_id ); 1623 peachpay_log( 1624 'info', 1625 'Payments: Refund success.', 1626 array( 1627 'event' => 'payments.convesiopay_gateway.refund.success', 1628 'component' => 'payments', 1629 'feature' => 'convesiopay_gateway', 1630 'operation' => 'refund', 1631 'outcome' => 'success', 1632 'method' => __METHOD__, 1633 'line' => __LINE__, 1634 'data' => array( 1635 'details' => 'ConvesioPay: Refund success - order ' . $order->get_order_number() . ', refund_id ' . $refund_id 1636 ))); 1379 1637 1380 1638 // Add detailed order note … … 1413 1671 1414 1672 } catch ( Exception $e ) { 1415 peachpay_log( 'error', 'ConvesioPay: Refund exception - ' . $e->getMessage() . ' (order ' . $order->get_order_number() . ')' ); 1673 peachpay_log( 1674 'error', 1675 'Payments: Refund failed.', 1676 array( 1677 'event' => 'payments.convesiopay_gateway.refund.failed', 1678 'component' => 'payments', 1679 'feature' => 'convesiopay_gateway', 1680 'operation' => 'refund', 1681 'outcome' => 'failed', 1682 'method' => __METHOD__, 1683 'line' => __LINE__, 1684 'data' => array( 1685 'details' => 'ConvesioPay: Refund exception - ' . $e->getMessage() . ' (order ' . $order->get_order_number() . ')' 1686 ))); 1416 1687 return new WP_Error( 'convesiopay_refund_error', $e->getMessage() ); 1417 1688 } … … 1426 1697 */ 1427 1698 private function find_payment_by_order_number( $order_number, $config ) { 1428 peachpay_log( 'debug', 'ConvesioPay: GET /payments/list API request for order_number ' . $order_number ); 1699 peachpay_log( 1700 'debug', 1701 'Payments: Find payment by order number debug.', 1702 array( 1703 'event' => 'payments.convesiopay_gateway.find_payment_by_order_number.debug', 1704 'component' => 'payments', 1705 'feature' => 'convesiopay_gateway', 1706 'operation' => 'find_payment_by_order_number', 1707 'outcome' => 'debug', 1708 'method' => __METHOD__, 1709 'line' => __LINE__, 1710 'data' => array( 1711 'order_number' => $order_number, 1712 'api_url' => $config['api_url'] . '/payments/list', 1713 ), 1714 ) 1715 ); 1429 1716 1430 1717 // Make API call to ConvesioPay to find payment by order number … … 1438 1725 1439 1726 if ( is_wp_error( $response ) ) { 1440 peachpay_log( 'error', 'ConvesioPay: GET /payments/list network error - ' . $response->get_error_message() . ' (order_number ' . $order_number . ')' ); 1727 peachpay_log( 1728 'error', 1729 'Payments: Find payment by order number failed.', 1730 array( 1731 'event' => 'payments.convesiopay_gateway.find_payment_by_order_number.failed', 1732 'component' => 'payments', 1733 'feature' => 'convesiopay_gateway', 1734 'operation' => 'find_payment_by_order_number', 1735 'outcome' => 'failed', 1736 'method' => __METHOD__, 1737 'line' => __LINE__, 1738 'data' => array( 1739 'order_number' => $order_number, 1740 'error_message' => $response->get_error_message(), 1741 ), 1742 ) 1743 ); 1441 1744 return false; 1442 1745 } … … 1447 1750 1448 1751 if ( $response_code !== 200 || empty( $response_data['payments'] ) ) { 1449 peachpay_log( 'warning', 'ConvesioPay: GET /payments/list - HTTP ' . $response_code . ' or no payments (order_number ' . $order_number . ')' ); 1752 peachpay_log( 1753 'warning', 1754 'Payments: Find payment by order number warning.', 1755 array( 1756 'event' => 'payments.convesiopay_gateway.find_payment_by_order_number.warning', 1757 'component' => 'payments', 1758 'feature' => 'convesiopay_gateway', 1759 'operation' => 'find_payment_by_order_number', 1760 'outcome' => 'warning', 1761 'method' => __METHOD__, 1762 'line' => __LINE__, 1763 'data' => array( 1764 'order_number' => $order_number, 1765 'response_code' => $response_code, 1766 'payments_count' => isset( $response_data['payments'] ) && is_array( $response_data['payments'] ) ? count( $response_data['payments'] ) : 0, 1767 ), 1768 ) 1769 ); 1450 1770 return false; 1451 1771 } … … 1453 1773 $payment_id = $response_data['payments'][0]['id'] ?? false; 1454 1774 if ( $payment_id ) { 1455 peachpay_log( 'info', 'ConvesioPay: GET /payments/list found payment ' . $payment_id . ' for order_number ' . $order_number ); 1775 peachpay_log( 1776 'info', 1777 'Payments: Find payment by order number success.', 1778 array( 1779 'event' => 'payments.convesiopay_gateway.find_payment_by_order_number.success', 1780 'component' => 'payments', 1781 'feature' => 'convesiopay_gateway', 1782 'operation' => 'find_payment_by_order_number', 1783 'outcome' => 'success', 1784 'method' => __METHOD__, 1785 'line' => __LINE__, 1786 'data' => array( 1787 'order_number' => $order_number, 1788 'payment_id' => $payment_id, 1789 ), 1790 ) 1791 ); 1456 1792 } 1457 1793 return $payment_id; -
peachpay-for-woocommerce/trunk/core/payments/convesiopay/routes/class-peachpay-convesiopay-reconciliation.php
r3460037 r3490786 124 124 } 125 125 126 peachpay_log( 'info', 'PeachPay Reconciliation: Cron started' ); 126 peachpay_log( 127 'info', 128 'ConvesioPay Reconciliation cron callback - started.', 129 array( 130 'event' => 'payments.convesiopay_reconciliation.cron_callback.started', 131 'component' => 'payments', 132 'feature' => 'convesiopay_reconciliation', 133 'operation' => 'cron_callback', 134 'outcome' => 'started', 135 'method' => __METHOD__, 136 'line' => __LINE__, 137 ) 138 ); 127 139 128 140 // Get eligible orders for reconciliation … … 131 143 $order_ids = array( 0 ); 132 144 if ( empty( $orders ) ) { 133 peachpay_log( 'info', 'PeachPay Reconciliation: Cron finished (no eligible orders)' ); 145 peachpay_log( 146 'info', 147 'ConvesioPay Reconciliation cron callback - no eligible orders.', 148 array( 149 'event' => 'payments.convesiopay_reconciliation.reconciliation.success', 150 'component' => 'payments', 151 'feature' => 'convesiopay_reconciliation', 152 'operation' => 'reconciliation', 153 'outcome' => 'success', 154 'method' => __METHOD__, 155 'line' => __LINE__, 156 ) 157 ); 134 158 return; 135 159 } … … 147 171 $order->update_status( 'failed', 'ConvesioPay reconciliation failed after multiple attempts.' ); 148 172 $order->save(); 149 peachpay_log( 'info', 'PeachPay Reconciliation: Order #' . $order->get_id() . ' marked failed (max attempts in loop)' ); 173 peachpay_log( 174 'info', 175 'ConvesioPay Reconciliation order processing - max attempts reached.', 176 array( 177 'event' => 'payments.convesiopay_reconciliation.reconciliation.success', 178 'component' => 'payments', 179 'feature' => 'convesiopay_reconciliation', 180 'operation' => 'reconciliation', 181 'outcome' => 'success', 182 'method' => __METHOD__, 183 'line' => __LINE__, 184 'data' => array( 185 'details' => 'PeachPay Reconciliation: Order #' . $order->get_id() . ' marked failed (max attempts in loop)' 186 ))); 150 187 continue; 151 188 } … … 158 195 } 159 196 160 peachpay_log( 'info', 'PeachPay Reconciliation: Cron finished for orders: ' . implode(', ', $order_ids) ); 197 peachpay_log( 198 'info', 199 'ConvesioPay Reconciliation cron callback - completed.', 200 array( 201 'event' => 'payments.convesiopay_reconciliation.reconciliation.success', 202 'component' => 'payments', 203 'feature' => 'convesiopay_reconciliation', 204 'operation' => 'reconciliation', 205 'outcome' => 'success', 206 'method' => __METHOD__, 207 'line' => __LINE__, 208 'data' => array( 209 'details' => 'PeachPay Reconciliation: Cron finished for orders: ' . implode(', ', $order_ids) 210 ))); 161 211 } catch ( \Throwable $e ) { 162 212 $this->log_reconciliation_error( 'run_reconciliation', $e ); … … 217 267 218 268 $count = count( $orders ); 219 peachpay_log( 'info', 'PeachPay Reconciliation: ' . $count . ' eligible orders' ); 269 peachpay_log( 270 'info', 271 'ConvesioPay Reconciliation eligible orders fetch - completed.', 272 array( 273 'event' => 'payments.convesiopay_reconciliation.reconciliation.success', 274 'component' => 'payments', 275 'feature' => 'convesiopay_reconciliation', 276 'operation' => 'reconciliation', 277 'outcome' => 'success', 278 'method' => __METHOD__, 279 'line' => __LINE__, 280 'data' => array( 281 'details' => 'PeachPay Reconciliation: ' . $count . ' eligible orders' 282 ))); 220 283 return array_values( $orders ); 221 284 } catch ( \Throwable $e ) { … … 237 300 try { 238 301 if ( get_transient( $lock_key ) ) { 239 peachpay_log( 'info', 'PeachPay Reconciliation: Order #' . $order_id . ' already being processed by another cron run' ); 302 peachpay_log( 303 'info', 304 'ConvesioPay Reconciliation order processing - skipped (already locked).', 305 array( 306 'event' => 'payments.convesiopay_reconciliation.reconciliation.success', 307 'component' => 'payments', 308 'feature' => 'convesiopay_reconciliation', 309 'operation' => 'reconciliation', 310 'outcome' => 'success', 311 'method' => __METHOD__, 312 'line' => __LINE__, 313 'data' => array( 314 'details' => 'PeachPay Reconciliation: Order #' . $order_id . ' already being processed by another cron run' 315 ))); 240 316 return; 241 317 } … … 243 319 set_transient( $lock_key, 1, PEACHPAY_CONVESIOPAY_RECONCILE_LOCK_TTL ); 244 320 245 peachpay_log( 'info', 'PeachPay Reconciliation: Processing order #' . $order_id ); 321 peachpay_log( 322 'info', 323 'ConvesioPay Reconciliation order processing - started for order #' . $order_id, 324 array( 325 'event' => 'payments.convesiopay_reconciliation.reconciliation.success', 326 'component' => 'payments', 327 'feature' => 'convesiopay_reconciliation', 328 'operation' => 'reconciliation', 329 'outcome' => 'success', 330 'method' => __METHOD__, 331 'line' => __LINE__, 332 'data' => array( 333 'details' => 'PeachPay Reconciliation: Processing order #' . $order_id 334 ))); 246 335 247 336 $order = wc_get_order( $order_id ); … … 249 338 if ( ! $order || ! $order->has_status( 'pending' ) ) { 250 339 delete_transient( $lock_key ); 251 peachpay_log( 'info', 'PeachPay Reconciliation: Order #' . $order_id . ' no longer pending' ); 340 peachpay_log( 341 'info', 342 'ConvesioPay Reconciliation order processing - skipped (order not pending) , order #' . $order_id, 343 array( 344 'event' => 'payments.convesiopay_reconciliation.reconciliation.success', 345 'component' => 'payments', 346 'feature' => 'convesiopay_reconciliation', 347 'operation' => 'reconciliation', 348 'outcome' => 'success', 349 'method' => __METHOD__, 350 'line' => __LINE__, 351 'data' => array( 352 'details' => 'PeachPay Reconciliation: Order #' . $order_id . ' no longer pending' 353 ))); 252 354 return; 253 355 } … … 261 363 $this->increment_reconcile_attempt_and_maybe_fail( $order ); 262 364 delete_transient($lock_key); 263 peachpay_log( 'info', 'PeachPay Reconciliation: Order #' . $order_id . ' no payment ID (' . $debug . ')' ); 365 peachpay_log( 366 'info', 367 'ConvesioPay Reconciliation order processing - skipped (missing payment ID) , order #' . $order_id, 368 array( 369 'event' => 'payments.convesiopay_reconciliation.reconciliation.success', 370 'component' => 'payments', 371 'feature' => 'convesiopay_reconciliation', 372 'operation' => 'reconciliation', 373 'outcome' => 'success', 374 'method' => __METHOD__, 375 'line' => __LINE__, 376 'data' => array( 377 'details' => 'PeachPay Reconciliation: Order #' . $order_id . ' no payment ID (' . $debug . ')' 378 ))); 264 379 return; 265 380 } … … 274 389 if ($poll_result === false) { 275 390 $this->increment_reconcile_attempt_and_maybe_fail( $order ); 276 peachpay_log( 'info', 'PeachPay Reconciliation: Order #' . $order_id . ' poll result false' ); 391 peachpay_log( 392 'info', 393 'ConvesioPay Reconciliation order processing - poll failed, order #' . $order_id, 394 array( 395 'event' => 'payments.convesiopay_reconciliation.reconciliation.success', 396 'component' => 'payments', 397 'feature' => 'convesiopay_reconciliation', 398 'operation' => 'reconciliation', 399 'outcome' => 'success', 400 'method' => __METHOD__, 401 'line' => __LINE__, 402 'data' => array( 403 'details' => 'PeachPay Reconciliation: Order #' . $order_id . ' poll result false' 404 ))); 277 405 return; 278 406 } … … 298 426 $order->update_meta_data('_convesiopay_reconcile_last_poll_at', time()); 299 427 $order->save(); 300 peachpay_log( 'info', 'PeachPay Reconciliation: Order #' . $order_id . ' still pending (status: ' . $status . '), will retry' ); 428 peachpay_log( 429 'info', 430 'ConvesioPay Reconciliation order processing - pending retry, order #' . $order_id, 431 array( 432 'event' => 'payments.convesiopay_reconciliation.reconciliation.success', 433 'component' => 'payments', 434 'feature' => 'convesiopay_reconciliation', 435 'operation' => 'reconciliation', 436 'outcome' => 'success', 437 'method' => __METHOD__, 438 'line' => __LINE__, 439 'data' => array( 440 'details' => 'PeachPay Reconciliation: Order #' . $order_id . ' still pending (status: ' . $status . '), will retry' 441 ))); 301 442 } 302 443 } catch ( \Throwable $e ) { … … 317 458 if ( $attempts >= PEACHPAY_CONVESIOPAY_RECONCILE_MAX_ATTEMPTS ) { 318 459 $order->update_status( 'failed', 'ConvesioPay reconciliation failed after multiple attempts.' ); 319 peachpay_log( 'info', 'PeachPay Reconciliation: Order #' . $order->get_id() . ' marked failed (max attempts reached)' ); 460 peachpay_log( 461 'info', 462 'ConvesioPay Reconciliation retry attempts - max reached.', 463 array( 464 'event' => 'payments.convesiopay_reconciliation.reconciliation.success', 465 'component' => 'payments', 466 'feature' => 'convesiopay_reconciliation', 467 'operation' => 'reconciliation', 468 'outcome' => 'success', 469 'method' => __METHOD__, 470 'line' => __LINE__, 471 'data' => array( 472 'details' => 'PeachPay Reconciliation: Order #' . $order->get_id() . ' marked failed (max attempts reached)' 473 ))); 320 474 } 321 475 $order->save(); … … 366 520 // Check if the API request failed 367 521 if (is_wp_error($response)) { 368 peachpay_log( 'error', 'PeachPay Reconciliation: GET payment failed - ' . $response->get_error_message() ); 522 peachpay_log( 523 'error', 524 'ConvesioPay Reconciliation fetch payment status - failed.', 525 array( 526 'event' => 'payments.convesiopay_reconciliation.reconciliation.failed', 527 'component' => 'payments', 528 'feature' => 'convesiopay_reconciliation', 529 'operation' => 'reconciliation', 530 'outcome' => 'failed', 531 'method' => __METHOD__, 532 'line' => __LINE__, 533 'data' => array( 534 'details' => 'PeachPay Reconciliation: GET payment failed - ' . $response->get_error_message() 535 ))); 369 536 return false; 370 537 } … … 373 540 374 541 if ( $code !== 200 ) { 375 peachpay_log( 'error', 'PeachPay Reconciliation: GET payment HTTP ' . $code . ' for payment ' . $payment_id . ' - ' . $body ); 542 peachpay_log( 543 'error', 544 'ConvesioPay Reconciliation fetch payment status - failed.', 545 array( 546 'event' => 'payments.convesiopay_reconciliation.reconciliation.failed', 547 'component' => 'payments', 548 'feature' => 'convesiopay_reconciliation', 549 'operation' => 'reconciliation', 550 'outcome' => 'failed', 551 'method' => __METHOD__, 552 'line' => __LINE__, 553 'data' => array( 554 'details' => 'PeachPay Reconciliation: GET payment HTTP ' . $code . ' for payment ' . $payment_id . ' - ' . $body 555 ))); 376 556 return false; 377 557 } 378 558 379 peachpay_log( 'debug', 'PeachPay CPay API: GET /payments/' . $payment_id . ' - HTTP ' . $code . ' - ' . $body ); 559 peachpay_log( 560 'debug', 561 'ConvesioPay Reconciliation fetch payment status - debug.', 562 array( 563 'event' => 'payments.convesiopay_reconciliation.fetch_payment_status.debug', 564 'component' => 'payments', 565 'feature' => 'convesiopay_reconciliation', 566 'operation' => 'fetch_payment_status', 567 'outcome' => 'debug', 568 'method' => __METHOD__, 569 'line' => __LINE__, 570 'data' => array( 571 'details' => 'PeachPay CPay API: GET /payments/' . $payment_id . ' - HTTP ' . $code . ' - ' . $body 572 ))); 380 573 381 574 // Decode the response body … … 384 577 // Check if the response body is not valid JSON or does not have a status 385 578 if (! is_array($data) || empty($data['status'])) { 386 peachpay_log( 'error', 'PeachPay Reconciliation: GET payment invalid response for ' . $payment_id . ' - missing status or invalid JSON' ); 579 peachpay_log( 580 'error', 581 'ConvesioPay Reconciliation fetch payment status - invalid response.', 582 array( 583 'event' => 'payments.convesiopay_reconciliation.reconciliation.failed', 584 'component' => 'payments', 585 'feature' => 'convesiopay_reconciliation', 586 'operation' => 'reconciliation', 587 'outcome' => 'failed', 588 'method' => __METHOD__, 589 'line' => __LINE__, 590 'data' => array( 591 'details' => 'PeachPay Reconciliation: GET payment invalid response for ' . $payment_id . ' - missing status or invalid JSON' 592 ))); 387 593 return false; 388 594 } … … 412 618 413 619 if ( empty( $api_url ) || empty( $secret ) ) { 414 peachpay_log( 'error', 'PeachPay Reconciliation: List payments skipped - missing api_url or secret_key' ); 620 peachpay_log( 621 'error', 622 'ConvesioPay Reconciliation list payments fetch - config missing.', 623 array( 624 'event' => 'payments.convesiopay_reconciliation.reconciliation.failed', 625 'component' => 'payments', 626 'feature' => 'convesiopay_reconciliation', 627 'operation' => 'reconciliation', 628 'outcome' => 'failed', 629 'method' => __METHOD__, 630 'line' => __LINE__, 631 ) 632 ); 415 633 return $map; 416 634 } … … 471 689 472 690 if ( is_wp_error( $response ) ) { 473 peachpay_log( 'error', 'PeachPay Reconciliation: List payments failed - ' . $response->get_error_message() ); 691 peachpay_log( 692 'error', 693 'ConvesioPay Reconciliation list payments fetch - failed.', 694 array( 695 'event' => 'payments.convesiopay_reconciliation.reconciliation.failed', 696 'component' => 'payments', 697 'feature' => 'convesiopay_reconciliation', 698 'operation' => 'reconciliation', 699 'outcome' => 'failed', 700 'method' => __METHOD__, 701 'line' => __LINE__, 702 'data' => array( 703 'details' => 'PeachPay Reconciliation: List payments failed - ' . $response->get_error_message() 704 ))); 474 705 break; 475 706 } … … 478 709 if ( $code !== 200 ) { 479 710 $body = wp_remote_retrieve_body( $response ); 480 peachpay_log( 'error', 'PeachPay Reconciliation: List payments HTTP ' . $code . ' - ' . $body ); 711 peachpay_log( 712 'error', 713 'ConvesioPay Reconciliation list payments fetch - failed.', 714 array( 715 'event' => 'payments.convesiopay_reconciliation.reconciliation.failed', 716 'component' => 'payments', 717 'feature' => 'convesiopay_reconciliation', 718 'operation' => 'reconciliation', 719 'outcome' => 'failed', 720 'method' => __METHOD__, 721 'line' => __LINE__, 722 'data' => array( 723 'details' => 'PeachPay Reconciliation: List payments HTTP ' . $code . ' - ' . $body 724 ))); 481 725 break; 482 726 } … … 501 745 } while ( $page <= $pages ); 502 746 503 peachpay_log( 'debug', 'PeachPay Reconciliation: List API returned ' . count( $map ) . ' payments' ); 747 peachpay_log( 748 'debug', 749 'ConvesioPay Reconciliation list payments fetch - debug.', 750 array( 751 'event' => 'payments.convesiopay_reconciliation.reconciliation.debug', 752 'component' => 'payments', 753 'feature' => 'convesiopay_reconciliation', 754 'operation' => 'reconciliation', 755 'outcome' => 'debug', 756 'method' => __METHOD__, 757 'line' => __LINE__, 758 'data' => array( 759 'details' => 'PeachPay Reconciliation: List API returned ' . count( $map ) . ' payments' 760 ))); 504 761 505 762 } catch ( \Throwable $e ) { … … 546 803 case 'cancelled': // ConvesioPay documentation status 547 804 $this->handle_payment_cancelled( $order, $payment_id ); 548 peachpay_log( 'info', 'PeachPay Reconciliation: Order #' . $order_id . ' → Cancelled' ); 805 peachpay_log( 806 'info', 807 'ConvesioPay Reconciliation status apply - cancelled handled.', 808 array( 809 'event' => 'payments.convesiopay_reconciliation.reconciliation.success', 810 'component' => 'payments', 811 'feature' => 'convesiopay_reconciliation', 812 'operation' => 'reconciliation', 813 'outcome' => 'success', 814 'method' => __METHOD__, 815 'line' => __LINE__, 816 'data' => array( 817 'details' => 'PeachPay Reconciliation: Order #' . $order_id . ' → Cancelled' 818 ))); 549 819 break; 550 820 … … 553 823 case 'disputed': // ConvesioPay documentation status 554 824 $this->handle_payment_failure( $order, $payment_id, $payment_data ); 555 peachpay_log( 'info', 'PeachPay Reconciliation: Order #' . $order_id . ' → Failed (' . $status . ')' ); 825 peachpay_log( 826 'info', 827 'ConvesioPay Reconciliation status apply - failure handled.', 828 array( 829 'event' => 'payments.convesiopay_reconciliation.reconciliation.success', 830 'component' => 'payments', 831 'feature' => 'convesiopay_reconciliation', 832 'operation' => 'reconciliation', 833 'outcome' => 'success', 834 'method' => __METHOD__, 835 'line' => __LINE__, 836 'data' => array( 837 'details' => 'PeachPay Reconciliation: Order #' . $order_id . ' → Failed (' . $status . ')' 838 ))); 556 839 break; 557 840 558 841 case 'refunded': // ConvesioPay documentation status - handle as refund 559 842 $this->handle_payment_refund( $order, $payment_id, $payment_data ); 560 peachpay_log( 'info', 'PeachPay Reconciliation: Order #' . $order_id . ' → Refunded' ); 843 peachpay_log( 844 'info', 845 'ConvesioPay Reconciliation status apply - refund handled.', 846 array( 847 'event' => 'payments.convesiopay_reconciliation.refund.success', 848 'component' => 'payments', 849 'feature' => 'convesiopay_reconciliation', 850 'operation' => 'refund', 851 'outcome' => 'success', 852 'method' => __METHOD__, 853 'line' => __LINE__, 854 'data' => array( 855 'details' => 'PeachPay Reconciliation: Order #' . $order_id . ' → Refunded' 856 ))); 561 857 break; 562 858 … … 584 880 // Check if order is already completed or refunded 585 881 if ($order->has_status(array('processing', 'completed', 'refunded'))) { 586 peachpay_log( 'info', 'PeachPay Reconciliation: Order #' . $order->get_id() . ' already completed or refunded' ); 882 peachpay_log( 883 'info', 884 'ConvesioPay Reconciliation payment success handler - skipped (already processed).', 885 array( 886 'event' => 'payments.convesiopay_reconciliation.refund.success', 887 'component' => 'payments', 888 'feature' => 'convesiopay_reconciliation', 889 'operation' => 'refund', 890 'outcome' => 'success', 891 'method' => __METHOD__, 892 'line' => __LINE__, 893 'data' => array( 894 'details' => 'PeachPay Reconciliation: Order #' . $order->get_id() . ' already completed or refunded' 895 ))); 587 896 return; 588 897 } … … 672 981 673 982 $order->save(); 674 peachpay_log( 'info', 'PeachPay Reconciliation: Order #' . $order->get_id() . ' handled payment success' ); 983 peachpay_log( 984 'info', 985 'ConvesioPay Reconciliation payment success handler - completed.', 986 array( 987 'event' => 'payments.convesiopay_reconciliation.reconciliation.success', 988 'component' => 'payments', 989 'feature' => 'convesiopay_reconciliation', 990 'operation' => 'reconciliation', 991 'outcome' => 'success', 992 'method' => __METHOD__, 993 'line' => __LINE__, 994 'data' => array( 995 'details' => 'PeachPay Reconciliation: Order #' . $order->get_id() . ' handled payment success' 996 ))); 675 997 } 676 998 … … 705 1027 $order->save(); 706 1028 707 peachpay_log( 'info', 'PeachPay Reconciliation: Order #' . $order->get_id() . ' handled payment cancelled' ); 1029 peachpay_log( 1030 'info', 1031 'ConvesioPay Reconciliation payment cancellation handler - note added.', 1032 array( 1033 'event' => 'payments.convesiopay_reconciliation.reconciliation.success', 1034 'component' => 'payments', 1035 'feature' => 'convesiopay_reconciliation', 1036 'operation' => 'reconciliation', 1037 'outcome' => 'success', 1038 'method' => __METHOD__, 1039 'line' => __LINE__, 1040 'data' => array( 1041 'details' => 'PeachPay Reconciliation: Order #' . $order->get_id() . ' handled payment cancelled' 1042 ))); 708 1043 return; 709 1044 } … … 733 1068 734 1069 $order->save(); 735 peachpay_log( 'info', 'PeachPay Reconciliation: Order #' . $order->get_id() . ' handled payment cancelled' ); 1070 peachpay_log( 1071 'info', 1072 'ConvesioPay Reconciliation payment cancellation handler - completed.', 1073 array( 1074 'event' => 'payments.convesiopay_reconciliation.reconciliation.success', 1075 'component' => 'payments', 1076 'feature' => 'convesiopay_reconciliation', 1077 'operation' => 'reconciliation', 1078 'outcome' => 'success', 1079 'method' => __METHOD__, 1080 'line' => __LINE__, 1081 'data' => array( 1082 'details' => 'PeachPay Reconciliation: Order #' . $order->get_id() . ' handled payment cancelled' 1083 ))); 736 1084 } 737 1085 … … 767 1115 $order->add_order_note( $note . ' (Ignored - order already processed)' ); 768 1116 $order->save(); 769 peachpay_log( 'info', 'PeachPay Reconciliation: Order #' . $order->get_id() . ' handled payment failure (Ignored - order already processed)' ); 1117 peachpay_log( 1118 'info', 1119 'ConvesioPay Reconciliation payment failure handler - ignored.', 1120 array( 1121 'event' => 'payments.convesiopay_reconciliation.reconciliation.success', 1122 'component' => 'payments', 1123 'feature' => 'convesiopay_reconciliation', 1124 'operation' => 'reconciliation', 1125 'outcome' => 'success', 1126 'method' => __METHOD__, 1127 'line' => __LINE__, 1128 'data' => array( 1129 'details' => 'PeachPay Reconciliation: Order #' . $order->get_id() . ' handled payment failure (Ignored - order already processed)' 1130 ))); 770 1131 return; 771 1132 } … … 776 1137 $order->save(); 777 1138 778 peachpay_log( 'info', 'PeachPay Reconciliation: Order #' . $order->get_id() . ' handled payment failure' ); 1139 peachpay_log( 1140 'info', 1141 'ConvesioPay Reconciliation payment failure handler - completed.', 1142 array( 1143 'event' => 'payments.convesiopay_reconciliation.reconciliation.success', 1144 'component' => 'payments', 1145 'feature' => 'convesiopay_reconciliation', 1146 'operation' => 'reconciliation', 1147 'outcome' => 'success', 1148 'method' => __METHOD__, 1149 'line' => __LINE__, 1150 'data' => array( 1151 'details' => 'PeachPay Reconciliation: Order #' . $order->get_id() . ' handled payment failure' 1152 ))); 779 1153 } 780 1154 … … 897 1271 898 1272 if ( ! $order ) { 899 peachpay_log( 'info', 'PeachPay Reconciliation: Order #' . $order_id . ' handled payment refund (order not found after refresh)' ); 1273 peachpay_log( 1274 'info', 1275 'ConvesioPay Reconciliation refund handler - order refresh missing.', 1276 array( 1277 'event' => 'payments.convesiopay_reconciliation.refund.success', 1278 'component' => 'payments', 1279 'feature' => 'convesiopay_reconciliation', 1280 'operation' => 'refund', 1281 'outcome' => 'success', 1282 'method' => __METHOD__, 1283 'line' => __LINE__, 1284 'data' => array( 1285 'details' => 'PeachPay Reconciliation: Order #' . $order_id . ' handled payment refund (order not found after refresh)' 1286 ))); 900 1287 return; 901 1288 } … … 909 1296 // Full refund - update order status to refunded 910 1297 $order->update_status( 'refunded', 'Order fully refunded via ConvesioPay Dashboard.' ); 911 peachpay_log( 'info', 'PeachPay Reconciliation: Order #' . $order->get_id() . ' handled payment refund (Full refund)' ); 1298 peachpay_log( 1299 'info', 1300 'ConvesioPay Reconciliation refund handler - full refund applied.', 1301 array( 1302 'event' => 'payments.convesiopay_reconciliation.refund.success', 1303 'component' => 'payments', 1304 'feature' => 'convesiopay_reconciliation', 1305 'operation' => 'refund', 1306 'outcome' => 'success', 1307 'method' => __METHOD__, 1308 'line' => __LINE__, 1309 'data' => array( 1310 'details' => 'PeachPay Reconciliation: Order #' . $order->get_id() . ' handled payment refund (Full refund)' 1311 ))); 912 1312 } else { 913 1313 // Partial refund - add informative note … … 921 1321 $refund_percentage 922 1322 ) ); 923 peachpay_log( 'info', 'PeachPay Reconciliation: Order #' . $order->get_id() . ' handled payment refund (Partial refund)' ); 1323 peachpay_log( 1324 'info', 1325 'ConvesioPay Reconciliation refund handler - partial refund applied.', 1326 array( 1327 'event' => 'payments.convesiopay_reconciliation.refund.success', 1328 'component' => 'payments', 1329 'feature' => 'convesiopay_reconciliation', 1330 'operation' => 'refund', 1331 'outcome' => 'success', 1332 'method' => __METHOD__, 1333 'line' => __LINE__, 1334 'data' => array( 1335 'details' => 'PeachPay Reconciliation: Order #' . $order->get_id() . ' handled payment refund (Partial refund)' 1336 ))); 924 1337 } 925 1338 … … 1004 1417 $message = 'PeachPay Reconciliation: Exception - ' . $context . ' - ' . $e->getMessage(); 1005 1418 $message .= ' in ' . $e->getFile() . ':' . $e->getLine(); 1006 peachpay_log( 'error', $message . "\n" . $e->getTraceAsString() ); 1419 peachpay_log( 1420 'error', 1421 'ConvesioPay Reconciliation exception handler - failed.', 1422 array( 1423 'event' => 'payments.convesiopay_reconciliation.reconciliation_error.failed', 1424 'component' => 'payments', 1425 'feature' => 'convesiopay_reconciliation', 1426 'operation' => 'reconciliation_error', 1427 'outcome' => 'failed', 1428 'method' => __METHOD__, 1429 'line' => __LINE__, 1430 'data' => array( 1431 'details' => $message . "\n" . $e->getTraceAsString() 1432 ))); 1007 1433 } 1008 1434 … … 1016 1442 $timestamp = wp_next_scheduled(PEACHPAY_CONVESIOPAY_RECONCILE_CRON_HOOK); 1017 1443 wp_unschedule_event($timestamp, PEACHPAY_CONVESIOPAY_RECONCILE_CRON_HOOK); 1018 peachpay_log( 'info', 'PeachPay Reconciliation: Unscheduled cron event' ); 1444 peachpay_log( 1445 'info', 1446 'ConvesioPay Reconciliation cron unschedule - completed.', 1447 array( 1448 'event' => 'payments.convesiopay_reconciliation.reconciliation.success', 1449 'component' => 'payments', 1450 'feature' => 'convesiopay_reconciliation', 1451 'operation' => 'reconciliation', 1452 'outcome' => 'success', 1453 'method' => __METHOD__, 1454 'line' => __LINE__, 1455 ) 1456 ); 1019 1457 } 1020 1458 } catch ( \Throwable $e ) { 1021 1459 $message = 'PeachPay Reconciliation: unschedule_cron - ' . $e->getMessage(); 1022 1460 $message .= ' in ' . $e->getFile() . ':' . $e->getLine(); 1023 peachpay_log( 'error', $message . "\n" . $e->getTraceAsString() ); 1461 peachpay_log( 1462 'error', 1463 'ConvesioPay Reconciliation cron unschedule - failed.', 1464 array( 1465 'event' => 'payments.convesiopay_reconciliation.reconciliation_error.failed', 1466 'component' => 'payments', 1467 'feature' => 'convesiopay_reconciliation', 1468 'operation' => 'reconciliation_error', 1469 'outcome' => 'failed', 1470 'method' => __METHOD__, 1471 'line' => __LINE__, 1472 'data' => array( 1473 'details' => $message . "\n" . $e->getTraceAsString() 1474 ))); 1024 1475 } 1025 1476 } … … 1032 1483 { 1033 1484 PeachPay_ConvesioPay_Reconciliation::unschedule_cron(); 1034 peachpay_log( 'info', 'PeachPay Reconciliation: Unscheduled cron event on plugin deactivation' ); 1485 peachpay_log( 1486 'info', 1487 'ConvesioPay Reconciliation deactivation unschedule - completed.', 1488 array( 1489 'event' => 'payments.convesiopay_reconciliation.reconciliation.success', 1490 'component' => 'payments', 1491 'feature' => 'convesiopay_reconciliation', 1492 'operation' => 'reconciliation', 1493 'outcome' => 'success', 1494 'method' => __METHOD__, 1495 'line' => __LINE__, 1496 ) 1497 ); 1035 1498 } 1036 1499 -
peachpay-for-woocommerce/trunk/core/payments/convesiopay/routes/class-peachpay-convesiopay-webhook.php
r3486472 r3490786 107 107 } catch ( \Throwable $e ) { 108 108 error_log( '[PP-WEBHOOK] PeachPay Webhook: Failed to get config - ' . $e->getMessage() ); 109 peachpay_log( 'error', 'PeachPay Webhook: Failed to get config - ' . $e->getMessage() ); 109 peachpay_log( 110 'error', 111 'ConvesioPay Webhook config load - failed.', 112 array( 113 'event' => 'webhooks.convesiopay.webhook.process.failed', 114 'component' => 'webhooks', 115 'feature' => 'convesiopay', 116 'operation' => 'webhook.process', 117 'outcome' => 'failed', 118 'method' => __METHOD__, 119 'line' => __LINE__, 120 'data' => array( 121 'details' => 'PeachPay Webhook: Failed to get config - ' . $e->getMessage() 122 ) 123 ) 124 ); 110 125 return new WP_REST_Response( 111 126 array( … … 152 167 153 168 154 peachpay_log( 'debug', 'PeachPay Webhook: Received event=' . $event_type . ' order_number=' . $order_number . ' payment_id=' . $payment_id ); 169 peachpay_log( 170 'debug', 171 'ConvesioPay Webhook request received - debug.', 172 array( 173 'event' => 'webhooks.convesiopay.webhook.process.debug', 174 'component' => 'webhooks', 175 'feature' => 'convesiopay', 176 'operation' => 'webhook.process', 177 'outcome' => 'debug', 178 'method' => __METHOD__, 179 'line' => __LINE__, 180 'data' => array( 181 'details' => 'PeachPay Webhook: Received event=' . $event_type . ' order_number=' . $order_number . ' payment_id=' . $payment_id 182 ) 183 ) 184 ); 155 185 156 186 // Validate webhook signature (ConvesioPay documentation requirement) 157 187 if ( ! $this->validate_webhook_signature( $request ) ) { 158 188 error_log( '[PP-WEBHOOK] PeachPay Webhook: Invalid signature' ); 159 peachpay_log( 'error', 'PeachPay Webhook: Invalid signature' ); 189 peachpay_log( 190 'error', 191 'ConvesioPay Webhook signature validation - failed.', 192 array( 193 'event' => 'webhooks.convesiopay.webhook.process.failed', 194 'component' => 'webhooks', 195 'feature' => 'convesiopay', 196 'operation' => 'webhook.process', 197 'outcome' => 'failed', 198 'method' => __METHOD__, 199 'line' => __LINE__, 200 ) 201 ); 160 202 return new WP_REST_Response( array( 'error' => 'Invalid signature' ), 401 ); 161 203 } 162 peachpay_log( 'info', 'PeachPay Webhook: Signature valid for event=' . $event_type . ' order_number=' . $order_number );163 204 164 205 // Validate webhook (basic validation) 165 206 if ( empty( $webhook_data ) ) { 166 error_log( '[PP-WEBHOOK] PeachPay Webhook: Invalid webhook data' ); 167 peachpay_log( 'error', 'PeachPay Webhook: Invalid webhook data' ); 207 peachpay_log( 208 'error', 209 'ConvesioPay Webhook payload validation - failed.', 210 array( 211 'event' => 'webhooks.convesiopay.webhook.process.failed', 212 'component' => 'webhooks', 213 'feature' => 'convesiopay', 214 'operation' => 'webhook.process', 215 'outcome' => 'failed', 216 'method' => __METHOD__, 217 'line' => __LINE__, 218 ) 219 ); 168 220 return new WP_REST_Response( array( 'error' => 'Invalid webhook data' ), 400 ); 169 221 } … … 171 223 // Check for duplicate events (ConvesioPay documentation requirement) 172 224 if ( $this->is_duplicate_event( $webhook_data ) ) { 173 peachpay_log( 'info', 'PeachPay Webhook: Duplicate event skipped' ); 225 peachpay_log( 226 'info', 227 'ConvesioPay Webhook duplicate event check - already processed.', 228 array( 229 'event' => 'webhooks.convesiopay.webhook.process.success', 230 'component' => 'webhooks', 231 'feature' => 'convesiopay', 232 'operation' => 'webhook.process', 233 'outcome' => 'success', 234 'method' => __METHOD__, 235 'line' => __LINE__, 236 'data' => array( 237 'details' => 'PeachPay Webhook: Duplicate event found for event=' . $event_type . ' order_number=' . $order_number, 238 'webhook_data' => $webhook_data 239 ) 240 ) 241 ); 174 242 return new WP_REST_Response( array( 'status' => 'duplicate_skipped' ), 200 ); 175 243 } … … 208 276 if ( ! $order ) { 209 277 error_log( '[PP-WEBHOOK] PeachPay Webhook: Order not found for orderNumber ' . $order_number ); 210 peachpay_log( 'error', 'PeachPay Webhook: Order not found for orderNumber ' . $order_number ); 278 peachpay_log( 279 'error', 280 'ConvesioPay Webhook order lookup - failed.', 281 array( 282 'event' => 'webhooks.convesiopay.webhook.process.failed', 283 'component' => 'webhooks', 284 'feature' => 'convesiopay', 285 'operation' => 'webhook.process', 286 'outcome' => 'failed', 287 'method' => __METHOD__, 288 'line' => __LINE__, 289 'data' => array( 290 'details' => 'PeachPay Webhook: Order not found for orderNumber ' . $order_number 291 ) 292 ) 293 ); 211 294 return new WP_REST_Response( array( 'error' => 'Order not found' ), 404 ); 212 295 } 213 peachpay_log( 'debug', 'PeachPay Webhook: Order found for orderNumber ' . $order_number . ' => order #' . $order->get_id() . ' (display number ' . $order->get_order_number() . ')' ); 296 297 peachpay_log( 298 'debug', 299 'ConvesioPay Webhook order lookup - order found.', 300 array( 301 'event' => 'webhooks.convesiopay.webhook.process.debug', 302 'component' => 'webhooks', 303 'feature' => 'convesiopay', 304 'operation' => 'webhook.process', 305 'outcome' => 'debug', 306 'method' => __METHOD__, 307 'line' => __LINE__, 308 'data' => array( 309 'details' => 'PeachPay Webhook: Order found for orderNumber ' . $order_number . ' => order #' . $order->get_id() . ' (display number ' . $order->get_order_number() . ')' 310 ) 311 ) 312 ); 214 313 215 314 // SECURITY: Validate that the order belongs to ConvesioPay before processing … … 222 321 if ( (string) $stored_payment_id === (string) $payment_id ) { 223 322 $is_convesiopay = true; 224 peachpay_log( 'debug', 'PeachPay Webhook: Order #' . $order->get_id() . ' accepted via fallback (webhook paymentId matches _convesiopay_payment_id)' ); 323 peachpay_log( 324 'debug', 325 'ConvesioPay Webhook order validation fallback - payment ID matched.', 326 array( 327 'event' => 'webhooks.convesiopay.webhook.process.debug', 328 'component' => 'webhooks', 329 'feature' => 'convesiopay', 330 'operation' => 'webhook.process', 331 'outcome' => 'debug', 332 'method' => __METHOD__, 333 'line' => __LINE__, 334 'data' => array( 335 'details' => 'PeachPay Webhook: Order #' . $order->get_id() . ' accepted via fallback (webhook paymentId matches _convesiopay_payment_id)' 336 ) 337 ) 338 ); 225 339 } else { 226 peachpay_log( 'debug', 'PeachPay Webhook: Order #' . $order->get_id() . ' fallback did not match: stored _convesiopay_payment_id=' . (string) $stored_payment_id . ' webhook paymentId=' . (string) $payment_id ); 340 peachpay_log( 341 'debug', 342 'ConvesioPay Webhook order validation fallback - payment ID mismatch.', 343 array( 344 'event' => 'webhooks.convesiopay.webhook.process.debug', 345 'component' => 'webhooks', 346 'feature' => 'convesiopay', 347 'operation' => 'webhook.process', 348 'outcome' => 'debug', 349 'method' => __METHOD__, 350 'line' => __LINE__, 351 'data' => array( 352 'details' => 'PeachPay Webhook: Order #' . $order->get_id() . ' fallback did not match: stored _convesiopay_payment_id=' . (string) $stored_payment_id . ' webhook paymentId=' . (string) $payment_id 353 ) 354 ) 355 ); 227 356 } 228 357 } else { 229 peachpay_log( 'debug', 'PeachPay Webhook: Order #' . $order->get_id() . ' fallback skipped: _convesiopay_payment_id empty or non-scalar, webhook paymentId=' . (string) $payment_id ); 358 peachpay_log( 359 'debug', 360 'ConvesioPay Webhook order validation fallback - skipped.', 361 array( 362 'event' => 'webhooks.convesiopay.webhook.process.debug', 363 'component' => 'webhooks', 364 'feature' => 'convesiopay', 365 'operation' => 'webhook.process', 366 'outcome' => 'debug', 367 'method' => __METHOD__, 368 'line' => __LINE__, 369 'data' => array( 370 'details' => 'PeachPay Webhook: Order #' . $order->get_id() . ' fallback skipped: _convesiopay_payment_id empty or non-scalar, webhook paymentId=' . (string) $payment_id 371 ) 372 ) 373 ); 230 374 } 231 375 } 232 376 if ( ! $is_convesiopay ) { 233 peachpay_log( 'warning', 'PeachPay Webhook: Rejected - non-ConvesioPay order #' . $order->get_id() . ' (order_number=' . $order_number . ' payment_id=' . $payment_id . '). Check is_convesiopay_order() logs above for reason.' ); 377 peachpay_log( 378 'warning', 379 'ConvesioPay Webhook order validation - rejected non-ConvesioPay order.', 380 array( 381 'event' => 'webhooks.convesiopay.webhook.process.warning', 382 'component' => 'webhooks', 383 'feature' => 'convesiopay', 384 'operation' => 'webhook.process', 385 'outcome' => 'warning', 386 'method' => __METHOD__, 387 'line' => __LINE__, 388 'data' => array( 389 'details' => 'PeachPay Webhook: Rejected - non-ConvesioPay order #' . $order->get_id() . ' (order_number=' . $order_number . ' payment_id=' . $payment_id . '). Check is_convesiopay_order() logs above for reason.' 390 ) 391 ) 392 ); 234 393 return new WP_REST_Response( array( 'error' => 'Order does not belong to ConvesioPay' ), 403 ); 235 394 } … … 242 401 } catch ( \Throwable $e ) { 243 402 error_log( '[PP-WEBHOOK] PeachPay Webhook: Failed to process - ' . $e->getMessage() ); 244 peachpay_log( 'error', 'PeachPay Webhook: Failed to process - ' . $e->getMessage() ); 403 peachpay_log( 404 'error', 405 'ConvesioPay Webhook processing - failed.', 406 array( 407 'event' => 'webhooks.convesiopay.webhook.process.failed', 408 'component' => 'webhooks', 409 'feature' => 'convesiopay', 410 'operation' => 'webhook.process', 411 'outcome' => 'failed', 412 'method' => __METHOD__, 413 'line' => __LINE__, 414 'data' => array( 415 'details' => 'PeachPay Webhook: Failed to process - ' . $e->getMessage() 416 ) 417 ) 418 ); 245 419 return new WP_REST_Response( array( 'error' => 'Webhook processing failed' ), 500 ); 246 420 } … … 256 430 if ( ! $order ) { 257 431 error_log( '[PP-WEBHOOK] PeachPay Webhook: is_convesiopay_order() failed - order is null/empty' ); 258 peachpay_log( 'error', 'PeachPay Webhook: is_convesiopay_order() failed - order is null/empty' );259 432 return false; 260 433 } … … 265 438 if ( ! $parent_id ) { 266 439 error_log( '[PP-WEBHOOK] PeachPay Webhook: is_convesiopay_order() failed - refund order #' . $order->get_id() . ' has no parent_id' ); 267 peachpay_log( 'error', 'PeachPay Webhook: is_convesiopay_order() failed - refund order #' . $order->get_id() . ' has no parent_id' ); 440 peachpay_log( 441 'error', 442 'ConvesioPay Webhook refund validation - missing parent order id.', 443 array( 444 'event' => 'webhooks.convesiopay.refund.failed', 445 'component' => 'webhooks', 446 'feature' => 'convesiopay', 447 'operation' => 'refund', 448 'outcome' => 'failed', 449 'method' => __METHOD__, 450 'line' => __LINE__, 451 'data' => array( 452 'details' => 'PeachPay Webhook: is_convesiopay_order() failed - refund order #' . $order->get_id() . ' has no parent_id' 453 ) 454 ) 455 ); 268 456 return false; 269 457 } … … 271 459 if ( ! $order ) { 272 460 error_log( '[PP-WEBHOOK] PeachPay Webhook: is_convesiopay_order() failed - parent order #' . $parent_id . ' not found' ); 273 peachpay_log( 'error', 'PeachPay Webhook: is_convesiopay_order() failed - parent order #' . $parent_id . ' not found' ); 461 peachpay_log( 462 'error', 463 'ConvesioPay Webhook order validation - missing parent order.', 464 array( 465 'event' => 'webhooks.convesiopay.webhook.process.failed', 466 'component' => 'webhooks', 467 'feature' => 'convesiopay', 468 'operation' => 'webhook.process', 469 'outcome' => 'failed', 470 'method' => __METHOD__, 471 'line' => __LINE__, 472 'data' => array( 473 'details' => 'PeachPay Webhook: is_convesiopay_order() failed - parent order #' . $parent_id . ' not found' 474 ) 475 ) 476 ); 274 477 return false; 275 478 } … … 285 488 // Log once with all key values so we can see why the order passed or failed 286 489 $log_payment_id = ( is_scalar( $convesiopay_payment_id ) && (string) $convesiopay_payment_id !== '' ) ? (string) $convesiopay_payment_id : '(empty)'; 287 peachpay_log( 'debug', 'PeachPay Webhook: is_convesiopay_order() order #' . $order_id . ' payment_method=' . ( $payment_method !== '' ? $payment_method : '(empty)' ) . ' _original_payment_method=' . ( is_string( $original_payment_method ) && $original_payment_method !== '' ? $original_payment_method : '(empty)' ) . ' _convesiopay_payment_id=' . $log_payment_id ); 490 peachpay_log( 491 'debug', 492 'ConvesioPay Webhook order validation - inspect order context.', 493 array( 494 'event' => 'webhooks.convesiopay.webhook.process.debug', 495 'component' => 'webhooks', 496 'feature' => 'convesiopay', 497 'operation' => 'webhook.process', 498 'outcome' => 'debug', 499 'method' => __METHOD__, 500 'line' => __LINE__, 501 'data' => array( 502 'details' => 'PeachPay Webhook: is_convesiopay_order() order #' . $order_id . ' payment_method=' . ( $payment_method !== '' ? $payment_method : '(empty)' ) . ' _original_payment_method=' . ( is_string( $original_payment_method ) && $original_payment_method !== '' ? $original_payment_method : '(empty)' ) . ' _convesiopay_payment_id=' . $log_payment_id 503 ) 504 ) 505 ); 288 506 289 507 // Check if the payment method is a ConvesioPay gateway 290 508 if ( class_exists( 'PeachPay_ConvesioPay_Integration' ) && method_exists( 'PeachPay_ConvesioPay_Integration', 'is_payment_gateway' ) ) { 291 509 if ( PeachPay_ConvesioPay_Integration::is_payment_gateway( $payment_method ) ) { 292 peachpay_log( 'debug', 'PeachPay Webhook: is_convesiopay_order() order #' . $order_id . ' => true (payment_method is ConvesioPay gateway)' ); 510 peachpay_log( 511 'debug', 512 'ConvesioPay Webhook order validation - payment method matched.', 513 array( 514 'event' => 'webhooks.convesiopay.webhook.process.debug', 515 'component' => 'webhooks', 516 'feature' => 'convesiopay', 517 'operation' => 'webhook.process', 518 'outcome' => 'debug', 519 'method' => __METHOD__, 520 'line' => __LINE__, 521 'data' => array( 522 'details' => 'PeachPay Webhook: is_convesiopay_order() order #' . $order_id . ' => true (payment_method is ConvesioPay gateway)' 523 ) 524 ) 525 ); 293 526 return true; 294 527 } 295 528 // Unified checkout may store original gateway before redirecting to card/btcpay/applepay 296 529 if ( is_string( $original_payment_method ) && $original_payment_method !== '' && PeachPay_ConvesioPay_Integration::is_payment_gateway( $original_payment_method ) ) { 297 peachpay_log( 'debug', 'PeachPay Webhook: is_convesiopay_order() order #' . $order_id . ' => true (_original_payment_method is ConvesioPay gateway)' ); 530 peachpay_log( 531 'debug', 532 'ConvesioPay Webhook order validation - original payment method matched.', 533 array( 534 'event' => 'webhooks.convesiopay.webhook.process.debug', 535 'component' => 'webhooks', 536 'feature' => 'convesiopay', 537 'operation' => 'webhook.process', 538 'outcome' => 'debug', 539 'method' => __METHOD__, 540 'line' => __LINE__, 541 'data' => array( 542 'details' => 'PeachPay Webhook: is_convesiopay_order() order #' . $order_id . ' => true (_original_payment_method is ConvesioPay gateway)' 543 ) 544 ) 545 ); 298 546 return true; 299 547 } … … 302 550 // Check if order has ConvesioPay payment ID stored 303 551 if ( is_string( $convesiopay_payment_id ) && $convesiopay_payment_id !== '' ) { 304 peachpay_log( 'debug', 'PeachPay Webhook: is_convesiopay_order() order #' . $order_id . ' => true (_convesiopay_payment_id meta set)' ); 552 peachpay_log( 553 'debug', 554 'ConvesioPay Webhook order validation - payment meta matched.', 555 array( 556 'event' => 'webhooks.convesiopay.webhook.process.debug', 557 'component' => 'webhooks', 558 'feature' => 'convesiopay', 559 'operation' => 'webhook.process', 560 'outcome' => 'debug', 561 'method' => __METHOD__, 562 'line' => __LINE__, 563 'data' => array( 564 'details' => 'PeachPay Webhook: is_convesiopay_order() order #' . $order_id . ' => true (_convesiopay_payment_id meta set)' 565 ) 566 ) 567 ); 305 568 return true; 306 569 } 307 570 if ( is_numeric( $convesiopay_payment_id ) && (string) $convesiopay_payment_id !== '' ) { 308 peachpay_log( 'debug', 'PeachPay Webhook: is_convesiopay_order() order #' . $order_id . ' => true (_convesiopay_payment_id meta set)' ); 571 peachpay_log( 572 'debug', 573 'ConvesioPay Webhook order validation - numeric payment meta matched.', 574 array( 575 'event' => 'webhooks.convesiopay.webhook.process.debug', 576 'component' => 'webhooks', 577 'feature' => 'convesiopay', 578 'operation' => 'webhook.process', 579 'outcome' => 'debug', 580 'method' => __METHOD__, 581 'line' => __LINE__, 582 'data' => array( 583 'details' => 'PeachPay Webhook: is_convesiopay_order() order #' . $order_id . ' => true (_convesiopay_payment_id meta set)' 584 ) 585 ) 586 ); 309 587 return true; 310 588 } … … 315 593 if ( class_exists( 'PeachPay_ConvesioPay_Integration' ) && method_exists( 'PeachPay_ConvesioPay_Integration', 'connected' ) ) { 316 594 $connected = PeachPay_ConvesioPay_Integration::connected(); 317 peachpay_log( 'debug', 'PeachPay Webhook: is_convesiopay_order() order #' . $order_id . ' => ' . ( $connected ? 'true' : 'false' ) . ' (empty payment_method, ConvesioPay connected=' . ( $connected ? 'yes' : 'no' ) . ')' ); 595 peachpay_log( 596 'debug', 597 'ConvesioPay Webhook order validation - connected fallback check.', 598 array( 599 'event' => 'webhooks.convesiopay.webhook.process.debug', 600 'component' => 'webhooks', 601 'feature' => 'convesiopay', 602 'operation' => 'webhook.process', 603 'outcome' => 'debug', 604 'method' => __METHOD__, 605 'line' => __LINE__, 606 'data' => array( 607 'details' => 'PeachPay Webhook: is_convesiopay_order() order #' . $order_id . ' => ' . ( $connected ? 'true' : 'false' ) . ' (empty payment_method, ConvesioPay connected=' . ( $connected ? 'yes' : 'no' ) . ')' 608 ) 609 ) 610 ); 318 611 return $connected; 319 612 } 320 613 } 321 322 peachpay_log( 'debug', 'PeachPay Webhook: is_convesiopay_order() order #' . $order_id . ' => false (no ConvesioPay gateway, no _convesiopay_payment_id, empty payment_method or ConvesioPay not connected)' );323 614 return false; 324 615 } … … 339 630 $hpos_active_bool = ( class_exists( \Automattic\WooCommerce\Utilities\OrderUtil::class ) && \Automattic\WooCommerce\Utilities\OrderUtil::custom_orders_table_usage_is_enabled() ); 340 631 $hpos_active = $hpos_active_bool ? 'yes' : 'no'; 341 peachpay_log( 'info', 'PeachPay Webhook [find_order_by_number]: called with order_number=' . $order_number . ', payment_id=' . ( ! empty( $payment_id ) ? $payment_id : '(none)' ) . ', HPOS=' . $hpos_active ); 632 peachpay_log( 633 'info', 634 'ConvesioPay Webhook order lookup - started.', 635 array( 636 'event' => 'webhooks.convesiopay.webhook.process.success', 637 'component' => 'webhooks', 638 'feature' => 'convesiopay', 639 'operation' => 'webhook.process', 640 'outcome' => 'success', 641 'method' => __METHOD__, 642 'line' => __LINE__, 643 'data' => array( 644 'details' => 'PeachPay Webhook [find_order_by_number]: called with order_number=' . $order_number . ', payment_id=' . ( ! empty( $payment_id ) ? $payment_id : '(none)' ) . ', HPOS=' . $hpos_active 645 ) 646 ) 647 ); 342 648 $order_id_int = (int) $order_number; 343 649 $is_numeric = ( (string) $order_id_int === $order_number_str && $order_id_int > 0 ); … … 361 667 ); 362 668 if ( ! empty( $orders ) ) { 363 peachpay_log( 'debug', 'PeachPay Webhook: find_order_by_number(' . $order_number . ') resolved by _convesiopay_payment_id meta => order #' . $orders[0]->get_id() ); 669 peachpay_log( 670 'debug', 671 'ConvesioPay Webhook order lookup - payment ID matched order.', 672 array( 673 'event' => 'webhooks.convesiopay.webhook.process.debug', 674 'component' => 'webhooks', 675 'feature' => 'convesiopay', 676 'operation' => 'webhook.process', 677 'outcome' => 'debug', 678 'method' => __METHOD__, 679 'line' => __LINE__, 680 'data' => array( 681 'details' => 'PeachPay Webhook: find_order_by_number(' . $order_number . ') resolved by _convesiopay_payment_id meta => order #' . $orders[0]->get_id() 682 ) 683 ) 684 ); 364 685 return $orders[0]; 365 686 } 366 peachpay_log( 'info', 'PeachPay Webhook [find_order_by_number]: Step 0 found no match for payment_id=' . $payment_id . '; falling through to Step 1' ); 687 peachpay_log( 688 'info', 689 'ConvesioPay Webhook order lookup - payment ID step no match.', 690 array( 691 'event' => 'webhooks.convesiopay.webhook.process.success', 692 'component' => 'webhooks', 693 'feature' => 'convesiopay', 694 'operation' => 'webhook.process', 695 'outcome' => 'success', 696 'method' => __METHOD__, 697 'line' => __LINE__, 698 'data' => array( 699 'details' => 'PeachPay Webhook [find_order_by_number]: Step 0 found no match for payment_id=' . $payment_id . '; falling through to Step 1' 700 ) 701 ) 702 ); 367 703 } else { 368 704 $skip_reason = empty( $payment_id ) ? 'no payment_id provided' : 'HPOS disabled'; 369 peachpay_log( 'info', 'PeachPay Webhook [find_order_by_number]: Step 0 skipped — ' . $skip_reason . '; falling through to Step 1' ); 705 peachpay_log( 706 'info', 707 'ConvesioPay Webhook order lookup - payment ID step skipped.', 708 array( 709 'event' => 'webhooks.convesiopay.webhook.process.success', 710 'component' => 'webhooks', 711 'feature' => 'convesiopay', 712 'operation' => 'webhook.process', 713 'outcome' => 'success', 714 'method' => __METHOD__, 715 'line' => __LINE__, 716 'data' => array( 717 'details' => 'PeachPay Webhook [find_order_by_number]: Step 0 skipped — ' . $skip_reason . '; falling through to Step 1' 718 ) 719 ) 720 ); 370 721 } 371 722 … … 380 731 $candidate = $orders[0]; 381 732 if ( strval( $candidate->get_order_number() ) === $order_number_str ) { 382 peachpay_log( 'debug', 'PeachPay Webhook: find_order_by_number(' . $order_number . ') resolved by order_number param (display) => order #' . $candidate->get_id() ); 733 peachpay_log( 734 'debug', 735 'ConvesioPay Webhook order lookup - display number matched order.', 736 array( 737 'event' => 'webhooks.convesiopay.webhook.process.debug', 738 'component' => 'webhooks', 739 'feature' => 'convesiopay', 740 'operation' => 'webhook.process', 741 'outcome' => 'debug', 742 'method' => __METHOD__, 743 'line' => __LINE__, 744 'data' => array( 745 'details' => 'PeachPay Webhook: find_order_by_number(' . $order_number . ') resolved by order_number param (display) => order #' . $candidate->get_id() 746 ) 747 ) 748 ); 383 749 return $candidate; 384 750 } 385 peachpay_log( 'debug', 'PeachPay Webhook: find_order_by_number(' . $order_number . ') order_number param returned order #' . $candidate->get_id() . ' (display ' . $candidate->get_order_number() . ') – no match' ); 386 peachpay_log( 'info', 'PeachPay Webhook [find_order_by_number]: Step 1 found no display-number match; falling through to Step 2' ); 751 peachpay_log( 752 'debug', 753 'ConvesioPay Webhook order lookup - display number mismatch.', 754 array( 755 'event' => 'webhooks.convesiopay.webhook.process.debug', 756 'component' => 'webhooks', 757 'feature' => 'convesiopay', 758 'operation' => 'webhook.process', 759 'outcome' => 'debug', 760 'method' => __METHOD__, 761 'line' => __LINE__, 762 'data' => array( 763 'details' => 'PeachPay Webhook: find_order_by_number(' . $order_number . ') order_number param returned order #' . $candidate->get_id() . ' (display ' . $candidate->get_order_number() . ') – no match' 764 ) 765 ) 766 ); 387 767 } else { 388 peachpay_log( 'info', 'PeachPay Webhook [find_order_by_number]: Step 1 returned no orders; falling through to Step 2' ); 768 peachpay_log( 769 'info', 770 'ConvesioPay Webhook order lookup - wc_get_order step no match.', 771 array( 772 'event' => 'webhooks.convesiopay.webhook.process.success', 773 'component' => 'webhooks', 774 'feature' => 'convesiopay', 775 'operation' => 'webhook.process', 776 'outcome' => 'success', 777 'method' => __METHOD__, 778 'line' => __LINE__, 779 ) 780 ); 389 781 } 390 782 … … 405 797 } 406 798 if ( strval( $check_order->get_order_number() ) === $order_number_str ) { 407 peachpay_log( 'debug', 'PeachPay Webhook: find_order_by_number(' . $order_number . ') resolved by get_order_number() => order #' . $check_order->get_id() ); 799 peachpay_log( 800 'debug', 801 'ConvesioPay Webhook order lookup - recent orders match found.', 802 array( 803 'event' => 'webhooks.convesiopay.webhook.process.debug', 804 'component' => 'webhooks', 805 'feature' => 'convesiopay', 806 'operation' => 'webhook.process', 807 'outcome' => 'debug', 808 'method' => __METHOD__, 809 'line' => __LINE__, 810 'data' => array( 811 'details' => 'PeachPay Webhook: find_order_by_number(' . $order_number . ') resolved by get_order_number() => order #' . $check_order->get_id() 812 ))); 408 813 return $check_order; 409 814 } 410 815 } 411 peachpay_log( 'info', 'PeachPay Webhook [find_order_by_number]: Step 2 exhausted after checking ' . count( $recent_order_ids ) . ' orders; no match found' ); 816 817 peachpay_log( 818 'info', 819 'ConvesioPay Webhook order lookup - no match found.', 820 array( 821 'event' => 'webhooks.convesiopay.webhook.process.success', 822 'component' => 'webhooks', 823 'feature' => 'convesiopay', 824 'operation' => 'webhook.process', 825 'outcome' => 'success', 826 'method' => __METHOD__, 827 'line' => __LINE__, 828 'data' => array( 829 'details' => 'PeachPay Webhook [find_order_by_number]: Step 2 exhausted after checking ' . count( $recent_order_ids ) . ' orders; no match found' 830 ) 831 ) 832 ); 412 833 413 834 // 3) Fallback: treat as order ID (e.g. stored-card renewal sends get_id()). … … 415 836 $order_by_id = wc_get_order( $order_id_int ); 416 837 if ( $order_by_id && is_a( $order_by_id, 'WC_Order' ) && ! is_a( $order_by_id, 'WC_Order_Refund' ) ) { 417 peachpay_log( 'debug', 'PeachPay Webhook: find_order_by_number(' . $order_number . ') resolved by order ID => order #' . $order_by_id->get_id() ); 838 peachpay_log( 839 'debug', 840 'ConvesioPay Webhook order lookup - order ID matched order.', 841 array( 842 'event' => 'webhooks.convesiopay.webhook.process.debug', 843 'component' => 'webhooks', 844 'feature' => 'convesiopay', 845 'operation' => 'webhook.process', 846 'outcome' => 'debug', 847 'method' => __METHOD__, 848 'line' => __LINE__, 849 'data' => array( 850 'details' => 'PeachPay Webhook: find_order_by_number(' . $order_number . ') resolved by order ID => order #' . $order_by_id->get_id() 851 ) 852 ) 853 ); 418 854 return $order_by_id; 419 855 } 420 856 } 421 857 422 peachpay_log( 'debug', 'PeachPay Webhook: find_order_by_number(' . $order_number . ') no order found' ); 858 peachpay_log( 859 'debug', 860 'ConvesioPay Webhook order lookup - no order found.', 861 array( 862 'event' => 'webhooks.convesiopay.webhook.process.debug', 863 'component' => 'webhooks', 864 'feature' => 'convesiopay', 865 'operation' => 'webhook.process', 866 'outcome' => 'debug', 867 'method' => __METHOD__, 868 'line' => __LINE__, 869 'data' => array( 870 'details' => 'PeachPay Webhook: find_order_by_number(' . $order_number . ') no order found' 871 ) 872 ) 873 ); 423 874 return false; 424 875 } … … 1123 1574 if ( empty( $convesiopay_timestamp ) || empty( $convesiopay_signature ) ) { 1124 1575 error_log( '[PP-WEBHOOK] PeachPay Webhook: Missing required signature headers - rejecting webhook' ); 1125 peachpay_log( 'error', 'PeachPay Webhook: Missing required signature headers - rejecting webhook' ); 1576 peachpay_log( 1577 'error', 1578 'ConvesioPay Webhook signature headers - missing.', 1579 array( 1580 'event' => 'webhooks.convesiopay.webhook.process.failed', 1581 'component' => 'webhooks', 1582 'feature' => 'convesiopay', 1583 'operation' => 'webhook.process', 1584 'outcome' => 'failed', 1585 'method' => __METHOD__, 1586 'line' => __LINE__, 1587 ) 1588 ); 1126 1589 return false; 1127 1590 } … … 1135 1598 if ( empty( $webhook_signature_key ) ) { 1136 1599 error_log( '[PP-WEBHOOK] PeachPay Webhook: No webhook signature key configured - rejecting webhook for security' ); 1137 peachpay_log( 'error', 'PeachPay Webhook: No webhook signature key configured - rejecting webhook for security' ); 1600 peachpay_log( 1601 'error', 1602 'ConvesioPay Webhook signature key - missing.', 1603 array( 1604 'event' => 'webhooks.convesiopay.webhook.process.failed', 1605 'component' => 'webhooks', 1606 'feature' => 'convesiopay', 1607 'operation' => 'webhook.process', 1608 'outcome' => 'failed', 1609 'method' => __METHOD__, 1610 'line' => __LINE__, 1611 ) 1612 ); 1138 1613 return false; 1139 1614 } … … 1148 1623 if ( ! $is_valid ) { 1149 1624 error_log( '[PP-WEBHOOK] PeachPay Webhook: Invalid signature - rejecting webhook' ); 1150 peachpay_log( 'error', 'PeachPay Webhook: Invalid signature - rejecting webhook' ); 1625 peachpay_log( 1626 'error', 1627 'ConvesioPay Webhook signature validation - mismatch.', 1628 array( 1629 'event' => 'webhooks.convesiopay.webhook.process.failed', 1630 'component' => 'webhooks', 1631 'feature' => 'convesiopay', 1632 'operation' => 'webhook.process', 1633 'outcome' => 'failed', 1634 'method' => __METHOD__, 1635 'line' => __LINE__, 1636 ) 1637 ); 1151 1638 } 1152 1639 … … 1167 1654 if ( empty( $payment_id ) || empty( $event_type ) ) { 1168 1655 error_log( '[PP-WEBHOOK] PeachPay Webhook: Missing payment ID or event type inside is_duplicate_event() Line : ' . __LINE__ ); 1169 peachpay_log( 'error', 'PeachPay Webhook: Missing payment ID or event type inside is_duplicate_event() Line : ' . __LINE__ ); 1656 peachpay_log( 1657 'error', 1658 'ConvesioPay Webhook duplicate event check - missing identifiers.', 1659 array( 1660 'event' => 'webhooks.convesiopay.webhook.process.failed', 1661 'component' => 'webhooks', 1662 'feature' => 'convesiopay', 1663 'operation' => 'webhook.process', 1664 'outcome' => 'failed', 1665 'method' => __METHOD__, 1666 'line' => __LINE__, 1667 'data' => array( 1668 'details' => 'PeachPay Webhook: Missing payment ID or event type inside is_duplicate_event() Line : ' . __LINE__ 1669 ))); 1170 1670 return false; 1171 1671 } … … 1179 1679 1180 1680 if ( $existing_event ) { 1181 peachpay_log( 'debug', 'PeachPay Webhook: Duplicate event found inside is_duplicate_event() Line : ' . __LINE__ ); 1681 peachpay_log( 1682 'debug', 1683 'ConvesioPay Webhook duplicate event check - duplicate found.', 1684 array( 1685 'event' => 'webhooks.convesiopay.webhook.process.debug', 1686 'component' => 'webhooks', 1687 'feature' => 'convesiopay', 1688 'operation' => 'webhook.process', 1689 'outcome' => 'debug', 1690 'method' => __METHOD__, 1691 'line' => __LINE__, 1692 'data' => array( 1693 'details' => 'PeachPay Webhook: Duplicate event found inside is_duplicate_event() Line : ' . __LINE__ 1694 ))); 1182 1695 return true; 1183 1696 } … … 1189 1702 } 1190 1703 1191 peachpay_log( 'debug', 'PeachPay Webhook: No duplicate event found inside is_duplicate_event() Line : ' . __LINE__ ); 1704 peachpay_log( 1705 'debug', 1706 'ConvesioPay Webhook duplicate event check - no duplicate found.', 1707 array( 1708 'event' => 'webhooks.convesiopay.webhook.process.debug', 1709 'component' => 'webhooks', 1710 'feature' => 'convesiopay', 1711 'operation' => 'webhook.process', 1712 'outcome' => 'debug', 1713 'method' => __METHOD__, 1714 'line' => __LINE__, 1715 'data' => array( 1716 'details' => 'PeachPay Webhook: No duplicate event found inside is_duplicate_event() Line : ' . __LINE__ 1717 ))); 1192 1718 return false; 1193 1719 } -
peachpay-for-woocommerce/trunk/core/payments/stripe/abstract/class-peachpay-stripe-payment-gateway.php
r3486614 r3490786 19 19 use PeachPay_Stripe_Gateway_Utilities; 20 20 21 /** 22 * Track registered renewal hooks by hook name. 23 * 24 * @var array<string, bool> 25 */ 26 private static $renewal_hooks_registered = array(); 27 21 28 public $payment_provider = 'Stripe'; 22 29 public $min_amount = 0.50; … … 44 51 45 52 // Subscription support. 46 $gateway = $this; 53 $this->register_subscription_renewal_hook(); 54 55 add_filter( 'woocommerce_gateway_title', array( $this, 'handle_payment_method_title_filter' ), 10, 2 ); 56 } 57 58 /** 59 * Register subscription renewal hook once per request per gateway ID. 60 */ 61 private function register_subscription_renewal_hook() { 62 $hook_name = 'woocommerce_scheduled_subscription_payment_' . $this->id; 63 if ( isset( self::$renewal_hooks_registered[ $hook_name ] ) ) { 64 return; 65 } 47 66 add_action( 48 'woocommerce_scheduled_subscription_payment_' . $this->id, 49 function ( $renewal_total, $renewal_order ) use ( $gateway ) { 50 $subscriptions = wcs_get_subscriptions_for_renewal_order( $renewal_order ); 51 $subscription = array_pop( $subscriptions ); 52 $parent_order = wc_get_order( $subscription->get_parent_id() ); 53 54 $gateway->process_subscription_renewal( $parent_order, $renewal_order, $renewal_total ); 55 }, 67 $hook_name, 68 array( $this, 'handle_subscription_renewal_payment' ), 56 69 10, 57 70 2 58 71 ); 59 60 add_filter( 'woocommerce_gateway_title', array( $this, 'handle_payment_method_title_filter' ), 10, 2 ); 72 self::$renewal_hooks_registered[ $hook_name ] = true; 73 } 74 75 /** 76 * Handle scheduled subscription renewal payment. 77 * 78 * @param float $renewal_total Renewal amount. 79 * @param WC_Order $renewal_order Renewal order. 80 */ 81 public function handle_subscription_renewal_payment( $renewal_total, $renewal_order ) { 82 if ( ! function_exists( 'wcs_get_subscriptions_for_renewal_order' ) ) { 83 return; 84 } 85 86 $subscriptions = wcs_get_subscriptions_for_renewal_order( $renewal_order ); 87 $subscription = array_pop( $subscriptions ); 88 if ( ! $subscription ) { 89 return; 90 } 91 92 $parent_order = wc_get_order( $subscription->get_parent_id() ); 93 if ( ! $parent_order ) { 94 return; 95 } 96 97 $this->process_subscription_renewal( $parent_order, $renewal_order, $renewal_total ); 61 98 } 62 99 … … 246 283 $stripe_customer = $this->get_stripe_customer( $user_id ); 247 284 if ( $this->is_subscription_checkout_order( $order ) && empty( $stripe_customer ) ) { 248 peachpay_log( 'warning', 'Stripe.subscription.checkout_customer_missing | ' . json_encode( array( 'order_id' => $order->get_id(), 'order_number' => $order->get_order_number(), 'stripe_mode' => $stripe_mode ) ) ); 285 peachpay_log( 286 'warning', 287 'Stripe Subscription checkout customer missing - warning.', 288 array( 289 'event' => 'stripe.subscription.checkout_customer_missing', 290 'component' => 'payments', 291 'feature' => 'subscription', 292 'operation' => 'checkout_customer_missing', 293 'outcome' => 'warning', 294 'method' => __METHOD__, 295 'line' => __LINE__, 296 'data' => array( 'order_id' => $order->get_id(), 'order_number' => $order->get_order_number(), 'stripe_mode' => $stripe_mode ), 297 ) 298 ); 249 299 $stripe_customer = $this->maybe_create_stripe_customer_for_order( $order, $stripe_mode ); 250 300 if ( empty( $stripe_customer ) ) { 251 peachpay_log( 'error', 'Stripe.subscription.checkout_customer_resolution_failed | ' . json_encode( array( 'order_id' => $order->get_id(), 'order_number' => $order->get_order_number(), 'stripe_mode' => $stripe_mode ) ) ); 301 peachpay_log( 302 'error', 303 'Stripe Subscription checkout customer resolution - failed.', 304 array( 305 'event' => 'stripe.subscription.checkout_customer_resolution_failed', 306 'component' => 'payments', 307 'feature' => 'subscription', 308 'operation' => 'checkout_customer_resolution_failed', 309 'outcome' => 'failed', 310 'method' => __METHOD__, 311 'line' => __LINE__, 312 'data' => array( 'order_id' => $order->get_id(), 'order_number' => $order->get_order_number(), 'stripe_mode' => $stripe_mode ), 313 ) 314 ); 252 315 } 253 316 } … … 299 362 300 363 if ( ! $result ) { 301 peachpay_log( 'error', 'Stripe.checkout.create_payment_returned_null | ' . json_encode( array( 'order_id' => $order->get_id(), 'order_number' => $order->get_order_number(), 'stripe_mode' => $stripe_mode ) ) ); 364 peachpay_log( 365 'error', 366 'Stripe Checkout create payment returned null - failed.', 367 array( 368 'event' => 'stripe.checkout.create_payment_returned_null', 369 'component' => 'payments', 370 'feature' => 'checkout', 371 'operation' => 'create_payment_returned_null', 372 'outcome' => 'failed', 373 'method' => __METHOD__, 374 'line' => __LINE__, 375 'data' => array( 'order_id' => $order->get_id(), 'order_number' => $order->get_order_number(), 'stripe_mode' => $stripe_mode ), 376 ) 377 ); 302 378 return array( 303 379 'result' => 'failed', … … 344 420 ); 345 421 } catch ( Exception $exception ) { 346 peachpay_log( 'error', 'Stripe.checkout.process_payment_exception | ' . json_encode( array( 'order_id' => isset( $order ) && $order instanceof WC_Order ? $order->get_id() : $order_id, 'order_number' => isset( $order ) && $order instanceof WC_Order ? $order->get_order_number() : $order_id, 'error_message' => $exception->getMessage() ) ) ); 422 peachpay_log( 423 'error', 424 'Stripe Checkout process payment exception - failed.', 425 array( 426 'event' => 'stripe.checkout.process_payment_exception', 427 'component' => 'payments', 428 'feature' => 'checkout', 429 'operation' => 'process_payment_exception', 430 'outcome' => 'failed', 431 'method' => __METHOD__, 432 'line' => __LINE__, 433 'data' => array( 'order_id' => isset( $order ) && $order instanceof WC_Order ? $order->get_id() : $order_id, 'order_number' => isset( $order ) && $order instanceof WC_Order ? $order->get_order_number() : $order_id, 'error_message' => $exception->getMessage() ), 434 ) 435 ); 347 436 $message = __( 'Error: ', 'peachpay-for-woocommerce' ) . $exception->getMessage(); 348 437 if ( function_exists( 'wc_add_notice' ) ) { … … 379 468 // Idempotency: do not charge if this renewal order is already paid (prevents double charge from duplicate hooks or webhook + sync race). 380 469 if ( $renewal_order->has_status( array( 'processing', 'completed' ) ) ) { 381 peachpay_log( 'debug', 'Stripe: Subscription renewal skipped - order ' . $renewal_order->get_order_number() . ' already paid (status: ' . $renewal_order->get_status() . ').' ); 470 peachpay_log( 471 'debug', 472 'Stripe Subscription renewal - debug.', 473 array( 474 'event' => 'payments.stripe.subscription.renewal.debug', 475 'component' => 'payments', 476 'feature' => 'stripe', 477 'operation' => 'subscription.renewal', 478 'outcome' => 'debug', 479 'method' => __METHOD__, 480 'line' => __LINE__, 481 'data' => array( 482 'details' => 'Stripe: Subscription renewal skipped - order ' . $renewal_order->get_order_number() . ' already paid (status: ' . $renewal_order->get_status() . ').', 483 ), 484 ) 485 ); 382 486 return null; 383 487 } 384 488 if ( ! empty( $renewal_order->get_transaction_id() ) ) { 385 peachpay_log( 'debug', 'Stripe: Subscription renewal skipped - order ' . $renewal_order->get_order_number() . ' already has transaction ID.' ); 489 peachpay_log( 490 'debug', 491 'Stripe Subscription renewal - debug.', 492 array( 493 'event' => 'payments.stripe.subscription.renewal.debug', 494 'component' => 'payments', 495 'feature' => 'stripe', 496 'operation' => 'subscription.renewal', 497 'outcome' => 'debug', 498 'method' => __METHOD__, 499 'line' => __LINE__, 500 'data' => array( 501 'details' => 'Stripe: Subscription renewal skipped - order ' . $renewal_order->get_order_number() . ' already has transaction ID.', 502 ), 503 ) 504 ); 386 505 return null; 387 }388 389 // If subscription already has another completed renewal order created recently (e.g. duplicate scheduled action), skip to avoid double charge.390 if ( function_exists( 'wcs_get_subscriptions_for_renewal_order' ) ) {391 $subscriptions = wcs_get_subscriptions_for_renewal_order( $renewal_order );392 $subscription = is_array( $subscriptions ) ? array_pop( $subscriptions ) : null;393 if ( $subscription && is_callable( array( $subscription, 'get_related_orders' ) ) ) {394 $renewal_order_ids = $subscription->get_related_orders( 'ids', 'renewal' );395 $recent_cutoff = strtotime( '-2 hours' );396 foreach ( (array) $renewal_order_ids as $other_id ) {397 if ( (int) $other_id === (int) $renewal_order->get_id() ) {398 continue;399 }400 $other_order = wc_get_order( $other_id );401 if ( ! $other_order || ! $other_order->has_status( array( 'processing', 'completed' ) ) ) {402 continue;403 }404 $created = $other_order->get_date_created();405 if ( $created && $created->getTimestamp() >= $recent_cutoff ) {406 peachpay_log( 'info', 'Stripe: Subscription renewal skipped - subscription already has completed renewal order #' . $other_order->get_order_number() . ' (possible duplicate scheduled action). Order ' . $renewal_order->get_order_number() . ' not charged.' );407 $renewal_order->add_order_note( sprintf(408 __( 'Renewal payment skipped: subscription already has a completed renewal order #%s. This may be a duplicate; no charge was made.', 'peachpay-for-woocommerce' ),409 $other_order->get_order_number()410 ) );411 return null;412 }413 }414 }415 506 } 416 507 … … 423 514 if ( empty( $payment_method_id ) ) { 424 515 $message = __( 'Stripe reusable payment method details missing from subscription order.', 'peachpay-for-woocommerce' ); 425 peachpay_log( 'error', 'Stripe.subscription.renewal_missing_payment_method | ' . json_encode( array( 'parent_order_id' => $parent_order->get_id(), 'parent_order_number' => $parent_order->get_order_number(), 'renewal_order_id' => $renewal_order->get_id(), 'renewal_order_number' => $renewal_order->get_order_number(), 'stripe_mode' => $stripe_mode ) ) ); 516 peachpay_log( 517 'error', 518 'Stripe Subscription renewal missing payment method - failed.', 519 array( 520 'event' => 'stripe.subscription.renewal_missing_payment_method', 521 'component' => 'payments', 522 'feature' => 'subscription', 523 'operation' => 'renewal_missing_payment_method', 524 'outcome' => 'failed', 525 'method' => __METHOD__, 526 'line' => __LINE__, 527 'data' => array( 'parent_order_id' => $parent_order->get_id(), 'parent_order_number' => $parent_order->get_order_number(), 'renewal_order_id' => $renewal_order->get_id(), 'renewal_order_number' => $renewal_order->get_order_number(), 'stripe_mode' => $stripe_mode ), 528 ) 529 ); 426 530 $renewal_order->update_status( 'failed', $message ); 427 531 return null; … … 430 534 if ( empty( $customer_id ) ) { 431 535 $message = __( 'Stripe customer details missing from subscription order.', 'peachpay-for-woocommerce' ); 432 peachpay_log( 'error', 'Stripe.subscription.renewal_missing_customer | ' . json_encode( array( 'parent_order_id' => $parent_order->get_id(), 'parent_order_number' => $parent_order->get_order_number(), 'renewal_order_id' => $renewal_order->get_id(), 'renewal_order_number' => $renewal_order->get_order_number(), 'stripe_mode' => $stripe_mode ) ) ); 536 peachpay_log( 537 'error', 538 'Stripe Subscription renewal missing customer - failed.', 539 array( 540 'event' => 'stripe.subscription.renewal_missing_customer', 541 'component' => 'payments', 542 'feature' => 'subscription', 543 'operation' => 'renewal_missing_customer', 544 'outcome' => 'failed', 545 'method' => __METHOD__, 546 'line' => __LINE__, 547 'data' => array( 'parent_order_id' => $parent_order->get_id(), 'parent_order_number' => $parent_order->get_order_number(), 'renewal_order_id' => $renewal_order->get_id(), 'renewal_order_number' => $renewal_order->get_order_number(), 'stripe_mode' => $stripe_mode ), 548 ) 549 ); 433 550 $renewal_order->update_status( 'failed', $message ); 434 551 return null; … … 608 725 if ( ! $result['success'] ) { 609 726 return new \WP_Error( 'wc_' . $order_id . '_refund_failed', 'Refund error:' . $result['message'] ); 727 } 728 729 if ( ! empty( $result['refund_id'] ) ) { 730 PeachPay_Stripe::set_pending_wc_refund_id( $order->get_id(), $result['refund_id'] ); 610 731 } 611 732 … … 819 940 private function maybe_create_stripe_customer_for_order( $order, $stripe_mode ) { 820 941 if ( ! class_exists( 'PeachPay_Stripe_Credentials' ) ) { 821 peachpay_log( 'error', 'Stripe.subscription.customer_create_missing_credentials_class | ' . json_encode( array( 'order_id' => $order->get_id(), 'order_number' => $order->get_order_number(), 'stripe_mode' => $stripe_mode ) ) ); 942 peachpay_log( 943 'error', 944 'Stripe Customer create missing credentials class - failed.', 945 array( 946 'event' => 'stripe.subscription.customer_create_missing_credentials_class', 947 'component' => 'payments', 948 'feature' => 'subscription', 949 'operation' => 'customer_create_missing_credentials_class', 950 'outcome' => 'failed', 951 'method' => __METHOD__, 952 'line' => __LINE__, 953 'data' => array( 'order_id' => $order->get_id(), 'order_number' => $order->get_order_number(), 'stripe_mode' => $stripe_mode ), 954 ) 955 ); 822 956 return null; 823 957 } … … 825 959 $stripe = PeachPay_Stripe_Credentials::get_stripe_client( $stripe_mode ); 826 960 if ( ! $stripe ) { 827 peachpay_log( 'error', 'Stripe.subscription.customer_create_missing_client | ' . json_encode( array( 'order_id' => $order->get_id(), 'order_number' => $order->get_order_number(), 'stripe_mode' => $stripe_mode ) ) ); 961 peachpay_log( 962 'error', 963 'Stripe Customer create missing client - failed.', 964 array( 965 'event' => 'stripe.subscription.customer_create_missing_client', 966 'component' => 'payments', 967 'feature' => 'subscription', 968 'operation' => 'customer_create_missing_client', 969 'outcome' => 'failed', 970 'method' => __METHOD__, 971 'line' => __LINE__, 972 'data' => array( 'order_id' => $order->get_id(), 'order_number' => $order->get_order_number(), 'stripe_mode' => $stripe_mode ), 973 ) 974 ); 828 975 return null; 829 976 } … … 843 990 $customer = $stripe->customers->create( $args ); 844 991 if ( ! isset( $customer->id ) || empty( $customer->id ) ) { 845 peachpay_log( 'error', 'Stripe.subscription.customer_create_empty_id | ' . json_encode( array( 'order_id' => $order->get_id(), 'order_number' => $order->get_order_number(), 'stripe_mode' => $stripe_mode ) ) ); 992 peachpay_log( 993 'error', 994 'Stripe Customer create empty id - failed.', 995 array( 996 'event' => 'stripe.subscription.customer_create_empty_id', 997 'component' => 'payments', 998 'feature' => 'subscription', 999 'operation' => 'customer_create_empty_id', 1000 'outcome' => 'failed', 1001 'method' => __METHOD__, 1002 'line' => __LINE__, 1003 'data' => array( 'order_id' => $order->get_id(), 'order_number' => $order->get_order_number(), 'stripe_mode' => $stripe_mode ), 1004 ) 1005 ); 846 1006 return null; 847 1007 } … … 852 1012 } 853 1013 854 peachpay_log( 'info', 'Stripe.subscription.customer_created | ' . json_encode( array( 'order_id' => $order->get_id(), 'order_number' => $order->get_order_number(), 'customer_id' => $customer->id, 'user_id' => $user_id, 'stripe_mode' => $stripe_mode ) ) ); 1014 peachpay_log( 1015 'info', 1016 'Stripe Customer create - success.', 1017 array( 1018 'event' => 'stripe.subscription.customer_created', 1019 'component' => 'payments', 1020 'feature' => 'subscription', 1021 'operation' => 'customer_created', 1022 'outcome' => 'success', 1023 'method' => __METHOD__, 1024 'line' => __LINE__, 1025 'data' => array( 'order_id' => $order->get_id(), 'order_number' => $order->get_order_number(), 'customer_id' => $customer->id, 'user_id' => $user_id, 'stripe_mode' => $stripe_mode ), 1026 ) 1027 ); 855 1028 return $customer->id; 856 1029 } catch ( Exception $e ) { 857 peachpay_log( 'error', 'Stripe.subscription.customer_create_exception | ' . json_encode( array( 'order_id' => $order->get_id(), 'order_number' => $order->get_order_number(), 'stripe_mode' => $stripe_mode, 'error_message' => $e->getMessage() ) ) ); 1030 peachpay_log( 1031 'error', 1032 'Stripe Customer create exception - failed.', 1033 array( 1034 'event' => 'stripe.subscription.customer_create_exception', 1035 'component' => 'payments', 1036 'feature' => 'subscription', 1037 'operation' => 'customer_create_exception', 1038 'outcome' => 'failed', 1039 'method' => __METHOD__, 1040 'line' => __LINE__, 1041 'data' => array( 'order_id' => $order->get_id(), 'order_number' => $order->get_order_number(), 'stripe_mode' => $stripe_mode, 'error_message' => $e->getMessage() ), 1042 ) 1043 ); 858 1044 return null; 859 1045 } … … 870 1056 $customer_id = PeachPay_Stripe_Order_Data::get_payment_method( $parent_order, 'customer' ); 871 1057 if ( ! empty( $customer_id ) ) { 872 peachpay_log( 'debug', 'Stripe.subscription.renewal_customer_resolved | ' . json_encode( array( 'parent_order_id' => $parent_order->get_id(), 'parent_order_number' => $parent_order->get_order_number(), 'customer_id' => $customer_id, 'source' => 'payment_method_details', 'peachpay_mode' => $peachpay_mode ) ) ); 1058 peachpay_log( 1059 'debug', 1060 'Stripe Subscription renewal customer resolved - debug.', 1061 array( 1062 'event' => 'stripe.subscription.renewal_customer_resolved', 1063 'component' => 'payments', 1064 'feature' => 'subscription', 1065 'operation' => 'renewal_customer_resolved', 1066 'outcome' => 'debug', 1067 'method' => __METHOD__, 1068 'line' => __LINE__, 1069 'data' => array( 'parent_order_id' => $parent_order->get_id(), 'parent_order_number' => $parent_order->get_order_number(), 'customer_id' => $customer_id, 'source' => 'payment_method_details', 'peachpay_mode' => $peachpay_mode ), 1070 ) 1071 ); 873 1072 return $customer_id; 874 1073 } … … 876 1075 $customer_id = PeachPay_Stripe_Order_Data::get_payment_intent( $parent_order, 'customer' ); 877 1076 if ( ! empty( $customer_id ) ) { 878 peachpay_log( 'debug', 'Stripe.subscription.renewal_customer_resolved | ' . json_encode( array( 'parent_order_id' => $parent_order->get_id(), 'parent_order_number' => $parent_order->get_order_number(), 'customer_id' => $customer_id, 'source' => 'payment_intent_details', 'peachpay_mode' => $peachpay_mode ) ) ); 1077 peachpay_log( 1078 'debug', 1079 'Stripe Subscription renewal customer resolved - debug.', 1080 array( 1081 'event' => 'stripe.subscription.renewal_customer_resolved', 1082 'component' => 'payments', 1083 'feature' => 'subscription', 1084 'operation' => 'renewal_customer_resolved', 1085 'outcome' => 'debug', 1086 'method' => __METHOD__, 1087 'line' => __LINE__, 1088 'data' => array( 'parent_order_id' => $parent_order->get_id(), 'parent_order_number' => $parent_order->get_order_number(), 'customer_id' => $customer_id, 'source' => 'payment_intent_details', 'peachpay_mode' => $peachpay_mode ), 1089 ) 1090 ); 879 1091 return $customer_id; 880 1092 } … … 884 1096 $customer_id = PeachPay_Stripe::get_customer( $user_id, $peachpay_mode ); 885 1097 if ( ! empty( $customer_id ) ) { 886 peachpay_log( 'debug', 'Stripe.subscription.renewal_customer_resolved | ' . json_encode( array( 'parent_order_id' => $parent_order->get_id(), 'parent_order_number' => $parent_order->get_order_number(), 'customer_id' => $customer_id, 'source' => 'user_meta', 'user_id' => $user_id, 'peachpay_mode' => $peachpay_mode ) ) ); 1098 peachpay_log( 1099 'debug', 1100 'Stripe Subscription renewal customer resolved - debug.', 1101 array( 1102 'event' => 'stripe.subscription.renewal_customer_resolved', 1103 'component' => 'payments', 1104 'feature' => 'subscription', 1105 'operation' => 'renewal_customer_resolved', 1106 'outcome' => 'debug', 1107 'method' => __METHOD__, 1108 'line' => __LINE__, 1109 'data' => array( 'parent_order_id' => $parent_order->get_id(), 'parent_order_number' => $parent_order->get_order_number(), 'customer_id' => $customer_id, 'source' => 'user_meta', 'user_id' => $user_id, 'peachpay_mode' => $peachpay_mode ), 1110 ) 1111 ); 887 1112 return $customer_id; 888 1113 } … … 903 1128 private function ensure_payment_method_attached_to_customer( $payment_method_id, $customer_id, $stripe_mode, $renewal_order ) { 904 1129 if ( ! class_exists( 'PeachPay_Stripe_Credentials' ) ) { 905 peachpay_log( 'error', 'Stripe.subscription.renewal_pm_attach_missing_credentials_class | ' . json_encode( array( 'renewal_order_id' => $renewal_order->get_id(), 'renewal_order_number' => $renewal_order->get_order_number(), 'payment_method_id' => $payment_method_id, 'customer_id' => $customer_id, 'stripe_mode' => $stripe_mode ) ) ); 1130 peachpay_log( 1131 'error', 1132 'Stripe Subscription renewal payment method attach missing credentials class - failed.', 1133 array( 1134 'event' => 'stripe.subscription.renewal_pm_attach_missing_credentials_class', 1135 'component' => 'payments', 1136 'feature' => 'subscription', 1137 'operation' => 'renewal_pm_attach_missing_credentials_class', 1138 'outcome' => 'failed', 1139 'method' => __METHOD__, 1140 'line' => __LINE__, 1141 'data' => array( 'renewal_order_id' => $renewal_order->get_id(), 'renewal_order_number' => $renewal_order->get_order_number(), 'payment_method_id' => $payment_method_id, 'customer_id' => $customer_id, 'stripe_mode' => $stripe_mode ), 1142 ) 1143 ); 906 1144 return false; 907 1145 } … … 909 1147 $stripe = PeachPay_Stripe_Credentials::get_stripe_client( $stripe_mode ); 910 1148 if ( ! $stripe ) { 911 peachpay_log( 'error', 'Stripe.subscription.renewal_pm_attach_missing_client | ' . json_encode( array( 'renewal_order_id' => $renewal_order->get_id(), 'renewal_order_number' => $renewal_order->get_order_number(), 'payment_method_id' => $payment_method_id, 'customer_id' => $customer_id, 'stripe_mode' => $stripe_mode ) ) ); 1149 peachpay_log( 1150 'error', 1151 'Stripe Subscription renewal payment method attach missing client - failed.', 1152 array( 1153 'event' => 'stripe.subscription.renewal_pm_attach_missing_client', 1154 'component' => 'payments', 1155 'feature' => 'subscription', 1156 'operation' => 'renewal_pm_attach_missing_client', 1157 'outcome' => 'failed', 1158 'method' => __METHOD__, 1159 'line' => __LINE__, 1160 'data' => array( 'renewal_order_id' => $renewal_order->get_id(), 'renewal_order_number' => $renewal_order->get_order_number(), 'payment_method_id' => $payment_method_id, 'customer_id' => $customer_id, 'stripe_mode' => $stripe_mode ), 1161 ) 1162 ); 912 1163 return false; 913 1164 } … … 922 1173 array( 'customer' => $customer_id ) 923 1174 ); 924 peachpay_log( 'info', 'Stripe.subscription.renewal_pm_attached | ' . json_encode( array( 'renewal_order_id' => $renewal_order->get_id(), 'renewal_order_number' => $renewal_order->get_order_number(), 'payment_method_id' => $payment_method_id, 'customer_id' => $customer_id, 'stripe_mode' => $stripe_mode ) ) ); 1175 peachpay_log( 1176 'info', 1177 'Stripe Subscription renewal payment method attached - success.', 1178 array( 1179 'event' => 'stripe.subscription.renewal_pm_attached', 1180 'component' => 'payments', 1181 'feature' => 'subscription', 1182 'operation' => 'renewal_pm_attached', 1183 'outcome' => 'success', 1184 'method' => __METHOD__, 1185 'line' => __LINE__, 1186 'data' => array( 'renewal_order_id' => $renewal_order->get_id(), 'renewal_order_number' => $renewal_order->get_order_number(), 'payment_method_id' => $payment_method_id, 'customer_id' => $customer_id, 'stripe_mode' => $stripe_mode ), 1187 ) 1188 ); 925 1189 return true; 926 1190 } 927 1191 928 1192 if ( $attached_to !== $customer_id ) { 929 peachpay_log( 'error', 'Stripe.subscription.renewal_pm_attached_to_different_customer | ' . json_encode( array( 'renewal_order_id' => $renewal_order->get_id(), 'renewal_order_number' => $renewal_order->get_order_number(), 'payment_method_id' => $payment_method_id, 'expected_customer_id' => $customer_id, 'actual_customer_id' => $attached_to, 'stripe_mode' => $stripe_mode ) ) ); 1193 peachpay_log( 1194 'error', 1195 'Stripe Subscription renewal payment method attached to different customer - failed.', 1196 array( 1197 'event' => 'stripe.subscription.renewal_pm_attached_to_different_customer', 1198 'component' => 'payments', 1199 'feature' => 'subscription', 1200 'operation' => 'renewal_pm_attached_to_different_customer', 1201 'outcome' => 'failed', 1202 'method' => __METHOD__, 1203 'line' => __LINE__, 1204 'data' => array( 'renewal_order_id' => $renewal_order->get_id(), 'renewal_order_number' => $renewal_order->get_order_number(), 'payment_method_id' => $payment_method_id, 'expected_customer_id' => $customer_id, 'actual_customer_id' => $attached_to, 'stripe_mode' => $stripe_mode ), 1205 ) 1206 ); 930 1207 return false; 931 1208 } 932 1209 933 peachpay_log( 'debug', 'Stripe.subscription.renewal_pm_already_attached | ' . json_encode( array( 'renewal_order_id' => $renewal_order->get_id(), 'renewal_order_number' => $renewal_order->get_order_number(), 'payment_method_id' => $payment_method_id, 'customer_id' => $customer_id, 'stripe_mode' => $stripe_mode ) ) ); 1210 peachpay_log( 1211 'debug', 1212 'Stripe Subscription renewal payment method already attached - debug.', 1213 array( 1214 'event' => 'stripe.subscription.renewal_pm_already_attached', 1215 'component' => 'payments', 1216 'feature' => 'subscription', 1217 'operation' => 'renewal_pm_already_attached', 1218 'outcome' => 'debug', 1219 'method' => __METHOD__, 1220 'line' => __LINE__, 1221 'data' => array( 'renewal_order_id' => $renewal_order->get_id(), 'renewal_order_number' => $renewal_order->get_order_number(), 'payment_method_id' => $payment_method_id, 'customer_id' => $customer_id, 'stripe_mode' => $stripe_mode ), 1222 ) 1223 ); 934 1224 return true; 935 1225 } catch ( Exception $e ) { 936 peachpay_log( 'error', 'Stripe.subscription.renewal_pm_attach_exception | ' . json_encode( array( 'renewal_order_id' => $renewal_order->get_id(), 'renewal_order_number' => $renewal_order->get_order_number(), 'payment_method_id' => $payment_method_id, 'customer_id' => $customer_id, 'stripe_mode' => $stripe_mode, 'error_message' => $e->getMessage() ) ) ); 1226 peachpay_log( 1227 'error', 1228 'Stripe Subscription renewal payment method attach exception - failed.', 1229 array( 1230 'event' => 'stripe.subscription.renewal_pm_attach_exception', 1231 'component' => 'payments', 1232 'feature' => 'subscription', 1233 'operation' => 'renewal_pm_attach_exception', 1234 'outcome' => 'failed', 1235 'method' => __METHOD__, 1236 'line' => __LINE__, 1237 'data' => array( 'renewal_order_id' => $renewal_order->get_id(), 'renewal_order_number' => $renewal_order->get_order_number(), 'payment_method_id' => $payment_method_id, 'customer_id' => $customer_id, 'stripe_mode' => $stripe_mode, 'error_message' => $e->getMessage() ), 1238 ) 1239 ); 937 1240 return false; 938 1241 } -
peachpay-for-woocommerce/trunk/core/payments/stripe/functions.php
r3485577 r3490786 186 186 187 187 /** 188 * Links a WooCommerce refund record to a Stripe refund ID for admin-initiated refunds. 189 * 190 * @param int $refund_id WooCommerce refund ID. 191 * @param array $args Refund creation arguments. 192 */ 193 function peachpay_stripe_handle_wc_refund_created( $refund_id, $args ) { 194 if ( empty( $args['refund_payment'] ) || empty( $args['order_id'] ) ) { 195 return; 196 } 197 198 $order = wc_get_order( $args['order_id'] ); 199 if ( ! $order || ! PeachPay_Stripe_Integration::is_payment_gateway( $order->get_payment_method() ) ) { 200 return; 201 } 202 203 if ( ! class_exists( 'PeachPay_Stripe' ) || ! method_exists( 'PeachPay_Stripe', 'consume_pending_wc_refund_id' ) ) { 204 return; 205 } 206 207 $stripe_refund_id = PeachPay_Stripe::consume_pending_wc_refund_id( $order->get_id() ); 208 if ( empty( $stripe_refund_id ) ) { 209 return; 210 } 211 212 $refund = wc_get_order( $refund_id ); 213 if ( ! $refund || ! is_a( $refund, 'WC_Order_Refund' ) ) { 214 return; 215 } 216 217 $refund->update_meta_data( '_pp_stripe_refund_id', $stripe_refund_id ); 218 $refund->save(); 219 } 220 221 /** 188 222 * Captures the payment if the order payment was authorized and not captured immediately. 189 223 * -
peachpay-for-woocommerce/trunk/core/payments/stripe/hooks.php
r3485577 r3490786 27 27 add_action( 'woocommerce_order_status_cancelled', 'peachpay_stripe_handle_order_cancelled', 10, 1 ); 28 28 add_action( 'woocommerce_order_status_changed', 'peachpay_stripe_handle_order_processing', 10, 4 ); 29 add_action( 'woocommerce_refund_created', 'peachpay_stripe_handle_wc_refund_created', 10, 2 ); 29 30 30 31 // Public ajax routes -
peachpay-for-woocommerce/trunk/core/payments/stripe/routes/stripe-webhook.php
r3485577 r3490786 34 34 $event = \Stripe\Webhook::constructEvent( $payload, $sig_header, $webhook_secret ); 35 35 } catch ( \UnexpectedValueException $e ) { 36 peachpay_log( 'error', 'Stripe.webhook.invalid_payload | ' . json_encode( array( 'error_message' => $e->getMessage() ) ) ); 36 peachpay_log( 37 'error', 38 'Stripe Webhook invalid payload - failed.', 39 array( 40 'event' => 'stripe.webhook.invalid_payload', 41 'component' => 'webhooks', 42 'feature' => 'stripe', 43 'operation' => 'invalid_payload', 44 'outcome' => 'failed', 45 'method' => __METHOD__, 46 'line' => __LINE__, 47 'data' => array( 'error_message' => $e->getMessage() ), 48 ) 49 ); 37 50 wp_send_json_error( 'Invalid payload', 400 ); 38 51 return; 39 52 } catch ( \Stripe\Exception\SignatureVerificationException $e ) { 40 peachpay_log( 'error', 'Stripe.webhook.invalid_signature | ' . json_encode( array( 'error_message' => $e->getMessage() ) ) ); 53 peachpay_log( 54 'error', 55 'Stripe Webhook invalid signature - failed.', 56 array( 57 'event' => 'stripe.webhook.invalid_signature', 58 'component' => 'webhooks', 59 'feature' => 'stripe', 60 'operation' => 'invalid_signature', 61 'outcome' => 'failed', 62 'method' => __METHOD__, 63 'line' => __LINE__, 64 'data' => array( 'error_message' => $e->getMessage() ), 65 ) 66 ); 41 67 wp_send_json_error( 'Invalid signature', 400 ); 42 68 return; 43 69 } 44 70 45 peachpay_log( 'debug', 'Stripe.webhook.verified_event_received | ' . json_encode( array( 'event_type' => $event->type, 'event_id' => $event->id ) ) ); 46 // Process the verified event. 47 return peachpay_process_stripe_webhook_event( $event ); 71 $site_mode = ! peachpay_is_test_mode(); 72 if ( isset( $event->livemode ) && (bool) $event->livemode !== (bool) $site_mode ) { 73 peachpay_log( 74 'warning', 75 'Stripe Webhook mode mismatch: The recieved Stripe event was ignored because its mode (live/test) does not match the current PeachPay site mode. This helps ensure events are processed only in the appropriate environment and prevents accidental cross-environment actions.', 76 array( 77 'event' => 'stripe.webhook.mode_mismatch', 78 'component' => 'webhooks', 79 'feature' => 'stripe', 80 'operation' => 'mode_validation', 81 'outcome' => 'ignored', 82 'method' => __METHOD__, 83 'line' => __LINE__, 84 'data' => array( 85 'event_livemode' => (bool) $event->livemode, 86 'site_mode' => (bool) $site_mode, 87 'event_id' => ! empty( $event->id ) ? (string) $event->id : '', 88 ), 89 ) 90 ); 91 wp_send_json_success( 92 array( 93 'ignored' => true, 94 'message' => sprintf( 95 'The Stripe event was not processed because its mode (%s) did not match the current PeachPay site mode (%s). No action taken.', 96 (isset($event->livemode) && $event->livemode) ? 'live' : 'test', 97 $site_mode ? 'live' : 'test' 98 ), 99 'webhook_mode' => (isset($event->livemode) && $event->livemode) ? 'live' : 'test', 100 'current_mode' => $site_mode ? 'live' : 'test', 101 ) 102 ); 103 return; 104 } 105 106 107 $event_id = ! empty( $event->id ) ? (string) $event->id : ''; 108 $transient_key = ''; 109 if ( '' !== $event_id ) { 110 $transient_key = 'pp_stripe_event_' . $event_id; 111 if ( false !== get_transient( $transient_key ) ) { 112 peachpay_log( 113 'debug', 114 'Stripe Webhook duplicate event skipped - event type: ' . $event->type . ' event id: ' . $event_id, 115 array( 116 'event' => 'stripe.webhook.duplicate_event_skipped', 117 'component' => 'webhooks', 118 'feature' => 'stripe', 119 'operation' => 'duplicate_event_skipped', 120 'outcome' => 'debug', 121 'method' => __METHOD__, 122 'line' => __LINE__, 123 'data' => array( 124 'payload' => json_decode($payload, true) 125 ), 126 ) 127 ); 128 wp_send_json_error( 129 array( 130 'received' => true, 131 'duplicate' => true, 132 ) 133 ); 134 return; 135 } 136 137 set_transient( $transient_key, true, DAY_IN_SECONDS ); 138 } 139 140 try { 141 peachpay_log( 142 'debug', 143 'Stripe Webhook verified event received - event type: ' . $event->type . ' event id: ' . $event->id, 144 array( 145 'event' => 'stripe.webhook.verified_event_received', 146 'component' => 'webhooks', 147 'feature' => 'stripe', 148 'operation' => 'verified_event_received', 149 'outcome' => 'debug', 150 'method' => __METHOD__, 151 'line' => __LINE__, 152 'data' => array( 153 'payload' => json_decode($payload, true) 154 ), 155 ) 156 ); 157 // Process the verified event. 158 return peachpay_process_stripe_webhook_event( $event ); 159 } catch ( \Throwable $e ) { 160 if ( '' !== $transient_key ) { 161 delete_transient( $transient_key ); 162 } 163 164 peachpay_log( 165 'error', 166 'Stripe Webhook processing failed - transient released for retry.', 167 array( 168 'event' => 'stripe.webhook.processing_failed', 169 'component' => 'webhooks', 170 'feature' => 'stripe', 171 'operation' => 'processing_failed', 172 'outcome' => 'failed', 173 'method' => __METHOD__, 174 'line' => __LINE__, 175 'data' => array( 176 'event_id' => $event_id, 177 'event_type' => $event->type ?? '', 178 'error_message' => $e->getMessage(), 179 ), 180 ) 181 ); 182 183 wp_send_json_error( 184 array( 185 'received' => false, 186 'error' => 'Webhook processing failed', 187 ), 188 500 189 ); 190 return; 191 } 48 192 } 49 193 50 194 // Fallback: Handle legacy webhook format (from PeachPay server proxy). 51 195 // This maintains backward compatibility during transition. 52 $order = wc_get_order( $request['order_id'] );53 196 $params = $request instanceof WP_REST_Request ? $request->get_params() : (array) $request; 54 197 $order_id = $params['order_id'] ?? null; 55 198 $event_type = $params['type'] ?? 'unknown'; 56 199 57 peachpay_log( 'info', 'Stripe.webhook.legacy_event_received | ' . json_encode( array( 'event_type' => $event_type, 'order_id' => $order_id ) ) ); 200 peachpay_log( 201 'info', 202 'Stripe Webhook legacy event received - success.', 203 array( 204 'event' => 'stripe.webhook.legacy_event_received', 205 'component' => 'webhooks', 206 'feature' => 'stripe', 207 'operation' => 'legacy_event_received', 208 'outcome' => 'success', 209 'method' => __METHOD__, 210 'line' => __LINE__, 211 'data' => array( 'event_type' => $event_type, 'order_id' => $order_id ), 212 ) 213 ); 58 214 59 215 $order = wc_get_order( $order_id ); 60 216 if ( ! $order ) { 61 peachpay_log( 'error', 'Stripe.webhook.legacy_order_not_found | ' . json_encode( array( 'order_id' => $order_id ) ) ); 217 peachpay_log( 218 'error', 219 'Stripe Webhook legacy order not found - failed.', 220 array( 221 'event' => 'stripe.webhook.legacy_order_not_found', 222 'component' => 'webhooks', 223 'feature' => 'stripe', 224 'operation' => 'legacy_order_not_found', 225 'outcome' => 'failed', 226 'method' => __METHOD__, 227 'line' => __LINE__, 228 'data' => array( 'order_id' => $order_id ), 229 ) 230 ); 62 231 wp_send_json_error( 'Required field "order_id" was invalid or missing', 400 ); 63 232 return; … … 93 262 $type = $event->type; 94 263 $data = $event->data->object; 95 96 peachpay_log( 'debug', 'Stripe.webhook.processing_event | ' . json_encode( array( 'event_type' => $type ) ) ); 264 $livemode = $event->livemode; 265 266 peachpay_log( 267 'debug', 268 'Stripe Webhook processing event - debug.', 269 array( 270 'event' => 'stripe.webhook.processing_event', 271 'component' => 'webhooks', 272 'feature' => 'stripe', 273 'operation' => 'processing_event', 274 'outcome' => 'debug', 275 'method' => __METHOD__, 276 'line' => __LINE__, 277 'data' => array( 'event_type' => $type ), 278 ) 279 ); 97 280 switch ( $type ) { 98 281 case 'payment_intent.succeeded': 99 peachpay_handle_payment_intent_webhook( $data, 'succeeded' );282 peachpay_handle_payment_intent_webhook( $data, 'succeeded' , $livemode); 100 283 break; 101 284 102 285 case 'payment_intent.payment_failed': 103 peachpay_handle_payment_intent_webhook( $data, 'failed' );286 peachpay_handle_payment_intent_webhook( $data, 'failed' , $livemode); 104 287 break; 105 288 106 289 case 'payment_intent.canceled': 107 peachpay_handle_payment_intent_webhook( $data, 'canceled' );290 peachpay_handle_payment_intent_webhook( $data, 'canceled' , $livemode); 108 291 break; 109 292 110 293 case 'payment_intent.requires_action': 111 peachpay_handle_payment_intent_webhook( $data, 'requires_action' );294 peachpay_handle_payment_intent_webhook( $data, 'requires_action' , $livemode); 112 295 break; 113 296 114 297 case 'payment_intent.processing': 115 peachpay_handle_payment_intent_webhook( $data, 'processing' );298 peachpay_handle_payment_intent_webhook( $data, 'processing' , $livemode); 116 299 break; 117 300 … … 130 313 default: 131 314 // Unhandled event type - just acknowledge receipt. 132 peachpay_log( 'debug', 'Stripe.webhook.unhandled_event | ' . json_encode( array( 'event_type' => $type ) ) ); 315 peachpay_log( 316 'debug', 317 'Stripe Webhook unhandled event - debug.', 318 array( 319 'event' => 'stripe.webhook.unhandled_event', 320 'component' => 'webhooks', 321 'feature' => 'stripe', 322 'operation' => 'unhandled_event', 323 'outcome' => 'debug', 324 'method' => __METHOD__, 325 'line' => __LINE__, 326 'data' => array( 'event_type' => $type ), 327 ) 328 ); 133 329 break; 134 330 } … … 143 339 * @param string $status The status type. 144 340 */ 145 function peachpay_handle_payment_intent_webhook( $payment_intent, $status ) {341 function peachpay_handle_payment_intent_webhook( $payment_intent, $status, $livemode = false ) { 146 342 // Find the order by payment intent ID. 147 343 $order = peachpay_find_order_by_payment_intent( $payment_intent->id ); 148 344 149 345 if ( ! $order ) { 150 peachpay_log( 'debug', 'Stripe.webhook.payment_intent_order_not_found | ' . json_encode( array( 'payment_intent_id' => $payment_intent->id, 'event_status' => $status ) ) ); 346 peachpay_log( 347 'debug', 348 'Stripe Webhook payment intent order not found - debug.', 349 array( 350 'event' => 'stripe.webhook.payment_intent_order_not_found', 351 'component' => 'webhooks', 352 'feature' => 'stripe', 353 'operation' => 'payment_intent_order_not_found', 354 'outcome' => 'debug', 355 'method' => __METHOD__, 356 'line' => __LINE__, 357 'data' => array( 'payment_intent_id' => $payment_intent->id, 'event_status' => $status ), 358 ) 359 ); 151 360 return; 152 361 } 153 362 154 peachpay_log( 'info', 'Stripe.webhook.payment_intent_event | ' . json_encode( array( 'event_status' => $status, 'order_id' => $order->get_id(), 'order_number' => $order->get_order_number(), 'payment_intent_id' => $payment_intent->id ) ) ); 363 peachpay_log( 364 'info', 365 'Stripe Webhook payment intent event - success.', 366 array( 367 'event' => 'stripe.webhook.payment_intent_event', 368 'component' => 'webhooks', 369 'feature' => 'stripe', 370 'operation' => 'payment_intent_event', 371 'outcome' => 'success', 372 'method' => __METHOD__, 373 'line' => __LINE__, 374 'data' => array( 'event_status' => $status, 'order_id' => $order->get_id(), 'order_number' => $order->get_order_number(), 'payment_intent_id' => $payment_intent->id ), 375 ) 376 ); 155 377 $payment_details = array( 156 378 'payment_intent_details' => array( … … 160 382 'amount_capturable' => $payment_intent->amount_capturable ?? 0, 161 383 'currency' => $payment_intent->currency, 162 'mode' => 'live' === substr( $payment_intent->id, 3, 4 )? 'live' : 'test',384 'mode' => $livemode ? 'live' : 'test', 163 385 ), 164 386 ); … … 182 404 ); 183 405 } catch ( \Exception $e ) { 184 peachpay_log( 'debug', 'Stripe.webhook.payment_intent_charge_retrieve_failed | ' . json_encode( array( 'payment_intent_id' => $payment_intent->id, 'error_message' => $e->getMessage() ) ) ); 406 peachpay_log( 407 'debug', 408 'Stripe Webhook payment intent charge retrieve failed - debug.', 409 array( 410 'event' => 'stripe.webhook.payment_intent_charge_retrieve_failed', 411 'component' => 'webhooks', 412 'feature' => 'stripe', 413 'operation' => 'payment_intent_charge_retrieve_failed', 414 'outcome' => 'debug', 415 'method' => __METHOD__, 416 'line' => __LINE__, 417 'data' => array( 'payment_intent_id' => $payment_intent->id, 'error_message' => $e->getMessage() ), 418 ) 419 ); 185 420 } 186 421 } … … 211 446 212 447 if ( ! $order ) { 213 peachpay_log( 'debug', 'Stripe.webhook.charge_refunded_order_not_found | ' . json_encode( array( 'charge_id' => $charge->id ) ) ); 448 peachpay_log( 449 'debug', 450 'Stripe Webhook charge refunded order not found - debug.', 451 array( 452 'event' => 'stripe.webhook.charge_refunded_order_not_found', 453 'component' => 'webhooks', 454 'feature' => 'stripe', 455 'operation' => 'charge_refunded_order_not_found', 456 'outcome' => 'debug', 457 'method' => __METHOD__, 458 'line' => __LINE__, 459 'data' => array( 'charge_id' => $charge->id ), 460 ) 461 ); 214 462 return; 215 463 } 216 464 217 peachpay_log( 'info', 'Stripe.webhook.charge_refunded_event | ' . json_encode( array( 'order_id' => $order->get_id(), 'order_number' => $order->get_order_number(), 'charge_id' => $charge->id ) ) ); 465 peachpay_log( 466 'info', 467 'Stripe Webhook charge refunded event - success.', 468 array( 469 'event' => 'stripe.webhook.charge_refunded_event', 470 'component' => 'webhooks', 471 'feature' => 'stripe', 472 'operation' => 'charge_refunded_event', 473 'outcome' => 'success', 474 'method' => __METHOD__, 475 'line' => __LINE__, 476 'data' => array( 'order_id' => $order->get_id(), 'order_number' => $order->get_order_number(), 'charge_id' => $charge->id ), 477 ) 478 ); 218 479 $payment_details = array( 219 480 'charge_details' => array( … … 253 514 function peachpay_sync_wc_refunds_from_stripe_charge( $order, $charge ) { 254 515 if ( empty( $charge->refunds ) || empty( $charge->refunds->data ) ) { 255 peachpay_log( 'debug', 'Stripe.webhook.charge_refunded_no_refund_entries | ' . json_encode( array( 'order_id' => $order->get_id(), 'order_number' => $order->get_order_number(), 'charge_id' => $charge->id ) ) ); 516 peachpay_log( 517 'debug', 518 'Stripe Webhook charge refunded no refund entries - debug.', 519 array( 520 'event' => 'stripe.webhook.charge_refunded_no_refund_entries', 521 'component' => 'webhooks', 522 'feature' => 'stripe', 523 'operation' => 'charge_refunded_no_refund_entries', 524 'outcome' => 'debug', 525 'method' => __METHOD__, 526 'line' => __LINE__, 527 'data' => array( 'order_id' => $order->get_id(), 'order_number' => $order->get_order_number(), 'charge_id' => $charge->id ), 528 ) 529 ); 256 530 return; 257 531 } … … 263 537 } 264 538 265 $existing_refund = peachpay_find_wc_refund_by_stripe_refund_id( $order, $refund->id );539 $existing_refund = peachpay_find_wc_refund_by_stripe_refund_id( $order, $refund->id, $refund->amount ?? null, $refund->currency ?? null ); 266 540 if ( $existing_refund ) { 541 peachpay_log( 542 'debug', 543 'Stripe.webhook.refund_already_processed', 544 array( 545 'stripe_refund_id' => $refund->id, 546 'order_id' => $order->get_id(), 547 ) 548 ); 549 267 550 continue; 268 551 } … … 279 562 280 563 if ( is_wp_error( $wc_refund ) ) { 281 peachpay_log( 'error', 'Stripe.webhook.refund_sync_create_wc_refund_failed | ' . json_encode( array( 'order_id' => $order->get_id(), 'order_number' => $order->get_order_number(), 'stripe_refund_id' => $refund->id, 'error_message' => $wc_refund->get_error_message() ) ) ); 564 peachpay_log( 565 'error', 566 'Stripe Webhook refund sync create WC refund failed - failed.', 567 array( 568 'event' => 'stripe.webhook.refund_sync_create_wc_refund_failed', 569 'component' => 'webhooks', 570 'feature' => 'stripe', 571 'operation' => 'refund_sync_create_wc_refund_failed', 572 'outcome' => 'failed', 573 'method' => __METHOD__, 574 'line' => __LINE__, 575 'data' => array( 'order_id' => $order->get_id(), 'order_number' => $order->get_order_number(), 'stripe_refund_id' => $refund->id, 'error_message' => $wc_refund->get_error_message() ), 576 ) 577 ); 282 578 continue; 283 579 } … … 287 583 $created_count++; 288 584 289 peachpay_log( 'info', 'Stripe.webhook.refund_sync_created_wc_refund | ' . json_encode( array( 'order_id' => $order->get_id(), 'order_number' => $order->get_order_number(), 'wc_refund_id' => $wc_refund->get_id(), 'stripe_refund_id' => $refund->id, 'refund_amount' => $refund_amount, 'currency' => $currency ) ) ); 585 peachpay_log( 586 'info', 587 'Stripe Webhook refund sync created WC refund - success.', 588 array( 589 'event' => 'stripe.webhook.refund_sync_created_wc_refund', 590 'component' => 'webhooks', 591 'feature' => 'stripe', 592 'operation' => 'refund_sync_created_wc_refund', 593 'outcome' => 'success', 594 'method' => __METHOD__, 595 'line' => __LINE__, 596 'data' => array( 'order_id' => $order->get_id(), 'order_number' => $order->get_order_number(), 'wc_refund_id' => $wc_refund->get_id(), 'stripe_refund_id' => $refund->id, 'refund_amount' => $refund_amount, 'currency' => $currency ), 597 ) 598 ); 290 599 } 291 600 … … 311 620 * Finds an existing WooCommerce refund by Stripe refund id. 312 621 * 622 * @param WC_Order $order The WooCommerce order. 623 * @param string $stripe_refund_id The Stripe refund id. 624 * @param int|float|null $stripe_refund_amount Stripe refund amount in Stripe smallest unit. 625 * @param string|null $stripe_refund_currency Stripe refund currency code. 626 * @return WC_Order_Refund|false 627 */ 628 function peachpay_find_wc_refund_by_stripe_refund_id( $order, $stripe_refund_id, $stripe_refund_amount = null, $stripe_refund_currency = null ) { 629 $order_refunds = $order->get_refunds(); 630 631 // Primary idempotency key: exact Stripe refund id. 632 foreach ( $order_refunds as $refund ) { 633 if ( $stripe_refund_id === $refund->get_meta( '_pp_stripe_refund_id', true ) ) { 634 return $refund; 635 } 636 } 637 638 // Secondary check: some installs may already store the Stripe refund id in refund reason. 639 foreach ( $order_refunds as $refund ) { 640 $reason = (string) $refund->get_reason(); 641 if ( '' !== $reason && false !== strpos( $reason, $stripe_refund_id ) ) { 642 $refund->update_meta_data( '_pp_stripe_refund_id', $stripe_refund_id ); 643 $refund->save(); 644 return $refund; 645 } 646 } 647 648 // Webhook-only fallback for Woo-admin initiated refunds: 649 // if order notes already reference this Stripe refund id, attach it to a likely matching recent Woo refund. 650 if ( ! is_numeric( $stripe_refund_amount ) || ! peachpay_order_has_stripe_refund_note( $order, $stripe_refund_id ) ) { 651 return false; 652 } 653 654 $currency = strtoupper( $stripe_refund_currency ?? $order->get_currency() ); 655 $expected_refund_total = (float) PeachPay_Stripe::display_amount( $stripe_refund_amount, $currency ); 656 657 foreach ( $order->get_refunds() as $refund ) { 658 $refund_total = abs( (float) $refund->get_amount() ); 659 if ( abs( $refund_total - $expected_refund_total ) >= 0.01 ) { 660 continue; 661 } 662 663 $created_at = $refund->get_date_created(); 664 if ( ! $created_at || ( time() - $created_at->getTimestamp() ) > 3600 ) { 665 continue; 666 } 667 668 $refund->update_meta_data( '_pp_stripe_refund_id', $stripe_refund_id ); 669 $refund->save(); 670 return $refund; 671 } 672 673 return false; 674 } 675 676 /** 677 * Checks whether an order note already references a Stripe refund id. 678 * 313 679 * @param WC_Order $order The WooCommerce order. 314 680 * @param string $stripe_refund_id The Stripe refund id. 315 * @return WC_Order_Refund|false 316 */ 317 function peachpay_find_wc_refund_by_stripe_refund_id( $order, $stripe_refund_id ) { 318 foreach ( $order->get_refunds() as $refund ) { 319 if ( $stripe_refund_id === $refund->get_meta( '_pp_stripe_refund_id', true ) ) { 320 return $refund; 681 * @return bool 682 */ 683 function peachpay_order_has_stripe_refund_note( $order, $stripe_refund_id ) { 684 if ( empty( $stripe_refund_id ) ) { 685 return false; 686 } 687 688 $order_notes = wc_get_order_notes( 689 array( 690 'order_id' => $order->get_id(), 691 'limit' => 20, 692 'orderby' => 'date_created', 693 'order' => 'DESC', 694 ) 695 ); 696 697 foreach ( $order_notes as $note ) { 698 if ( isset( $note->content ) && false !== strpos( (string) $note->content, $stripe_refund_id ) ) { 699 return true; 321 700 } 322 701 } … … 336 715 337 716 if ( ! $order ) { 338 peachpay_log( 'debug', 'Stripe.webhook.dispute_order_not_found | ' . json_encode( array( 'action' => $action, 'charge_id' => $charge_id ) ) ); 717 peachpay_log( 718 'debug', 719 'Stripe Webhook dispute order not found - debug.', 720 array( 721 'event' => 'stripe.webhook.dispute_order_not_found', 722 'component' => 'webhooks', 723 'feature' => 'stripe', 724 'operation' => 'dispute_order_not_found', 725 'outcome' => 'debug', 726 'method' => __METHOD__, 727 'line' => __LINE__, 728 'data' => array( 'action' => $action, 'charge_id' => $charge_id ), 729 ) 730 ); 339 731 return; 340 732 } 341 733 342 peachpay_log( 'info', 'Stripe.webhook.dispute_event | ' . json_encode( array( 'action' => $action, 'order_id' => $order->get_id(), 'order_number' => $order->get_order_number(), 'charge_id' => $charge_id, 'dispute_id' => $dispute->id ) ) ); 734 peachpay_log( 735 'info', 736 'Stripe Webhook dispute event - success.', 737 array( 738 'event' => 'stripe.webhook.dispute_event', 739 'component' => 'webhooks', 740 'feature' => 'stripe', 741 'operation' => 'dispute_event', 742 'outcome' => 'success', 743 'method' => __METHOD__, 744 'line' => __LINE__, 745 'data' => array( 'action' => $action, 'order_id' => $order->get_id(), 'order_number' => $order->get_order_number(), 'charge_id' => $charge_id, 'dispute_id' => $dispute->id ), 746 ) 747 ); 343 748 $dispute_details = array( 344 749 'type' => 'charge.dispute.' . $action, -
peachpay-for-woocommerce/trunk/core/payments/stripe/utils/class-peachpay-stripe.php
r3485577 r3490786 176 176 177 177 /** 178 * In-request map of pending Stripe refund IDs keyed by WooCommerce order ID. 179 * 180 * Used to link Woo refund records to Stripe refund IDs during admin-initiated refunds. 181 * 182 * @var array<int,string> 183 */ 184 private static $pending_wc_refund_ids = array(); 185 186 /** 187 * Stores a pending Stripe refund ID for a WooCommerce order in the current request. 188 * 189 * @param int $order_id WooCommerce order ID. 190 * @param string $refund_id Stripe refund ID. 191 */ 192 public static function set_pending_wc_refund_id( $order_id, $refund_id ) { 193 $order_id = absint( $order_id ); 194 $refund_id = is_string( $refund_id ) ? trim( $refund_id ) : ''; 195 196 if ( 0 === $order_id || '' === $refund_id ) { 197 return; 198 } 199 200 self::$pending_wc_refund_ids[ $order_id ] = $refund_id; 201 } 202 203 /** 204 * Gets and clears a pending Stripe refund ID for a WooCommerce order. 205 * 206 * @param int $order_id WooCommerce order ID. 207 * @return string|null 208 */ 209 public static function consume_pending_wc_refund_id( $order_id ) { 210 $order_id = absint( $order_id ); 211 if ( 0 === $order_id || ! isset( self::$pending_wc_refund_ids[ $order_id ] ) ) { 212 return null; 213 } 214 215 $refund_id = self::$pending_wc_refund_ids[ $order_id ]; 216 unset( self::$pending_wc_refund_ids[ $order_id ] ); 217 218 return $refund_id; 219 } 220 221 /** 178 222 * Formats a stripe amount for displaying to merchants/customers. 179 223 * … … 264 308 */ 265 309 public static function create_payment( $order, $payment_intent_params, $order_details, $mode ) { 266 peachpay_log( 'debug', 'Stripe.payment_intent.create.request | ' . json_encode( array( 'order_id' => $order->get_id(), 'order_number' => $order->get_order_number(), 'mode' => $mode ) ) ); 310 peachpay_log( 311 'debug', 312 'Stripe Payment intent create request - debug.', 313 array( 314 'event' => 'stripe.payment_intent.create.request', 315 'component' => 'payments', 316 'feature' => 'payment_intent', 317 'operation' => 'create.request', 318 'outcome' => 'debug', 319 'method' => __METHOD__, 320 'line' => __LINE__, 321 'data' => array( 'order_id' => $order->get_id(), 'order_number' => $order->get_order_number(), 'mode' => $mode ), 322 ) 323 ); 267 324 268 325 try { … … 270 327 271 328 if ( ! $stripe ) { 272 peachpay_log( 'error', 'Stripe.payment_intent.create.not_configured | ' . json_encode( array( 'order_id' => $order->get_id(), 'order_number' => $order->get_order_number(), 'mode' => $mode ) ) ); 329 peachpay_log( 330 'error', 331 'Stripe Payment intent create not configured - failed.', 332 array( 333 'event' => 'stripe.payment_intent.create.not_configured', 334 'component' => 'payments', 335 'feature' => 'payment_intent', 336 'operation' => 'create.not_configured', 337 'outcome' => 'failed', 338 'method' => __METHOD__, 339 'line' => __LINE__, 340 'data' => array( 'order_id' => $order->get_id(), 'order_number' => $order->get_order_number(), 'mode' => $mode ), 341 ) 342 ); 273 343 $order->update_status( 'failed', __( 'Stripe is not configured. Please add your API keys.', 'peachpay-for-woocommerce' ) ); 274 344 return null; … … 333 403 self::calculate_payment_state( $order, $payment_details ); 334 404 335 peachpay_log( 'info', 'Stripe.payment_intent.create.success | ' . json_encode( array( 'order_id' => $order->get_id(), 'order_number' => $order->get_order_number(), 'payment_intent_id' => $payment_intent->id, 'status' => $payment_intent->status, 'mode' => $mode ) ) ); 405 peachpay_log( 406 'info', 407 'Stripe Payment intent create - success.', 408 array( 409 'event' => 'stripe.payment_intent.create.success', 410 'component' => 'payments', 411 'feature' => 'payment_intent', 412 'operation' => 'create', 413 'outcome' => 'success', 414 'method' => __METHOD__, 415 'line' => __LINE__, 416 'data' => array( 'order_id' => $order->get_id(), 'order_number' => $order->get_order_number(), 'payment_intent_id' => $payment_intent->id, 'status' => $payment_intent->status, 'mode' => $mode ), 417 ) 418 ); 336 419 return $payment_details['payment_intent_details']; 337 420 338 421 } catch ( \Stripe\Exception\CardException $e ) { 339 422 $error_message = $e->getMessage(); 340 peachpay_log( 'error', 'Stripe.payment_intent.create.card_exception | ' . json_encode( array( 'order_id' => $order->get_id(), 'order_number' => $order->get_order_number(), 'error_message' => $error_message, 'mode' => $mode ) ) ); 423 peachpay_log( 424 'error', 425 'Stripe Payment intent create card exception - failed.', 426 array( 427 'event' => 'stripe.payment_intent.create.card_exception', 428 'component' => 'payments', 429 'feature' => 'payment_intent', 430 'operation' => 'create.card_exception', 431 'outcome' => 'failed', 432 'method' => __METHOD__, 433 'line' => __LINE__, 434 'data' => array( 'order_id' => $order->get_id(), 'order_number' => $order->get_order_number(), 'error_message' => $error_message, 'mode' => $mode ), 435 ) 436 ); 341 437 if ( function_exists( 'wc_add_notice' ) ) { 342 438 wc_add_notice( __( 'Payment error: ', 'peachpay-for-woocommerce' ) . $error_message, 'error' ); … … 350 446 } catch ( \Stripe\Exception\ApiErrorException $e ) { 351 447 $error_message = $e->getMessage(); 352 peachpay_log( 'error', 'Stripe.payment_intent.create.api_exception | ' . json_encode( array( 'order_id' => $order->get_id(), 'order_number' => $order->get_order_number(), 'error_message' => $error_message, 'mode' => $mode ) ) ); 448 peachpay_log( 449 'error', 450 'Stripe Payment intent create API exception - failed.', 451 array( 452 'event' => 'stripe.payment_intent.create.api_exception', 453 'component' => 'payments', 454 'feature' => 'payment_intent', 455 'operation' => 'create.api_exception', 456 'outcome' => 'failed', 457 'method' => __METHOD__, 458 'line' => __LINE__, 459 'data' => array( 'order_id' => $order->get_id(), 'order_number' => $order->get_order_number(), 'error_message' => $error_message, 'mode' => $mode ), 460 ) 461 ); 353 462 if ( function_exists( 'wc_add_notice' ) ) { 354 463 wc_add_notice( __( 'Payment error: ', 'peachpay-for-woocommerce' ) . $error_message, 'error' ); … … 362 471 } catch ( \Exception $e ) { 363 472 $error_message = $e->getMessage(); 364 peachpay_log( 'error', 'Stripe.payment_intent.create.exception | ' . json_encode( array( 'order_id' => $order->get_id(), 'order_number' => $order->get_order_number(), 'error_message' => $error_message, 'mode' => $mode ) ) ); 473 peachpay_log( 474 'error', 475 'Stripe Payment intent create exception - failed.', 476 array( 477 'event' => 'stripe.payment_intent.create.exception', 478 'component' => 'payments', 479 'feature' => 'payment_intent', 480 'operation' => 'create', 481 'outcome' => 'exception', 482 'method' => __METHOD__, 483 'line' => __LINE__, 484 'data' => array( 'order_id' => $order->get_id(), 'order_number' => $order->get_order_number(), 'error_message' => $error_message, 'mode' => $mode ), 485 ) 486 ); 365 487 if ( function_exists( 'wc_add_notice' ) ) { 366 488 wc_add_notice( __( 'Payment error: ', 'peachpay-for-woocommerce' ) . $error_message, 'error' ); … … 381 503 */ 382 504 public static function capture_payment( $order, $capture_amount ) { 383 peachpay_log( 'debug', 'Stripe.payment_intent.capture.request | ' . json_encode( array( 'order_id' => $order->get_id(), 'order_number' => $order->get_order_number(), 'capture_amount' => $capture_amount ) ) ); 505 peachpay_log( 506 'debug', 507 'Stripe Payment intent capture request - debug.', 508 array( 509 'event' => 'stripe.payment_intent.capture.request', 510 'component' => 'payments', 511 'feature' => 'payment_intent', 512 'operation' => 'capture.request', 513 'outcome' => 'debug', 514 'method' => __METHOD__, 515 'line' => __LINE__, 516 'data' => array( 'order_id' => $order->get_id(), 'order_number' => $order->get_order_number(), 'capture_amount' => $capture_amount ), 517 ) 518 ); 384 519 385 520 try { … … 388 523 389 524 if ( ! $stripe ) { 390 peachpay_log( 'error', 'Stripe.payment_intent.capture.not_configured | ' . json_encode( array( 'order_id' => $order->get_id(), 'order_number' => $order->get_order_number(), 'mode' => $mode ) ) ); 525 peachpay_log( 526 'error', 527 'Stripe Payment intent capture not configured - failed.', 528 array( 529 'event' => 'stripe.payment_intent.capture.not_configured', 530 'component' => 'payments', 531 'feature' => 'payment_intent', 532 'operation' => 'capture.not_configured', 533 'outcome' => 'failed', 534 'method' => __METHOD__, 535 'line' => __LINE__, 536 'data' => array( 'order_id' => $order->get_id(), 'order_number' => $order->get_order_number(), 'mode' => $mode ), 537 ) 538 ); 391 539 return array( 392 540 'success' => false, … … 429 577 self::calculate_payment_state( $order, $payment_details ); 430 578 431 peachpay_log( 'info', 'Stripe.payment_intent.capture.success | ' . json_encode( array( 'order_id' => $order->get_id(), 'order_number' => $order->get_order_number(), 'payment_intent_id' => $payment_intent_id, 'mode' => $mode ) ) ); 579 peachpay_log( 580 'info', 581 'Stripe Payment intent capture - success.', 582 array( 583 'event' => 'stripe.payment_intent.capture.success', 584 'component' => 'payments', 585 'feature' => 'payment_intent', 586 'operation' => 'capture', 587 'outcome' => 'success', 588 'method' => __METHOD__, 589 'line' => __LINE__, 590 'data' => array( 'order_id' => $order->get_id(), 'order_number' => $order->get_order_number(), 'payment_intent_id' => $payment_intent_id, 'mode' => $mode ), 591 ) 592 ); 432 593 return array( 433 594 'success' => true, … … 436 597 437 598 } catch ( \Stripe\Exception\ApiErrorException $e ) { 438 peachpay_log( 'error', 'Stripe.payment_intent.capture.api_exception | ' . json_encode( array( 'order_id' => $order->get_id(), 'order_number' => $order->get_order_number(), 'error_message' => $e->getMessage() ) ) ); 599 peachpay_log( 600 'error', 601 'Stripe Payment intent capture API exception - failed.', 602 array( 603 'event' => 'stripe.payment_intent.capture.api_exception', 604 'component' => 'payments', 605 'feature' => 'payment_intent', 606 'operation' => 'capture.api_exception', 607 'outcome' => 'failed', 608 'method' => __METHOD__, 609 'line' => __LINE__, 610 'data' => array( 'order_id' => $order->get_id(), 'order_number' => $order->get_order_number(), 'error_message' => $e->getMessage() ), 611 ) 612 ); 439 613 return array( 440 614 'success' => false, … … 442 616 ); 443 617 } catch ( \Exception $e ) { 444 peachpay_log( 'error', 'Stripe.payment_intent.capture.exception | ' . json_encode( array( 'order_id' => $order->get_id(), 'order_number' => $order->get_order_number(), 'error_message' => $e->getMessage() ) ) ); 618 peachpay_log( 619 'error', 620 'Stripe Payment intent capture exception - failed.', 621 array( 622 'event' => 'stripe.payment_intent.capture.exception', 623 'component' => 'payments', 624 'feature' => 'payment_intent', 625 'operation' => 'capture', 626 'outcome' => 'exception', 627 'method' => __METHOD__, 628 'line' => __LINE__, 629 'data' => array( 'order_id' => $order->get_id(), 'order_number' => $order->get_order_number(), 'error_message' => $e->getMessage() ), 630 ) 631 ); 445 632 return array( 446 633 'success' => false, … … 457 644 */ 458 645 public static function void_payment( $order, $cancellation_reason = null ) { 459 peachpay_log( 'debug', 'Stripe.payment_intent.void.request | ' . json_encode( array( 'order_id' => $order->get_id(), 'order_number' => $order->get_order_number(), 'cancellation_reason' => $cancellation_reason ) ) ); 646 peachpay_log( 647 'debug', 648 'Stripe Payment intent void request - debug.', 649 array( 650 'event' => 'stripe.payment_intent.void.request', 651 'component' => 'payments', 652 'feature' => 'payment_intent', 653 'operation' => 'void.request', 654 'outcome' => 'debug', 655 'method' => __METHOD__, 656 'line' => __LINE__, 657 'data' => array( 'order_id' => $order->get_id(), 'order_number' => $order->get_order_number(), 'cancellation_reason' => $cancellation_reason ), 658 ) 659 ); 460 660 461 661 try { … … 464 664 465 665 if ( ! $stripe ) { 466 peachpay_log( 'error', 'Stripe.payment_intent.void.not_configured | ' . json_encode( array( 'order_id' => $order->get_id(), 'order_number' => $order->get_order_number(), 'mode' => $mode ) ) ); 666 peachpay_log( 667 'error', 668 'Stripe Payment intent void not configured - failed.', 669 array( 670 'event' => 'stripe.payment_intent.void.not_configured', 671 'component' => 'payments', 672 'feature' => 'payment_intent', 673 'operation' => 'void.not_configured', 674 'outcome' => 'failed', 675 'method' => __METHOD__, 676 'line' => __LINE__, 677 'data' => array( 'order_id' => $order->get_id(), 'order_number' => $order->get_order_number(), 'mode' => $mode ), 678 ) 679 ); 467 680 return array( 468 681 'success' => false, … … 491 704 self::calculate_payment_state( $order, $payment_details ); 492 705 493 peachpay_log( 'info', 'Stripe.payment_intent.void.success | ' . json_encode( array( 'order_id' => $order->get_id(), 'order_number' => $order->get_order_number(), 'payment_intent_id' => $payment_intent_id, 'mode' => $mode ) ) ); 706 peachpay_log( 707 'info', 708 'Stripe Payment intent void - success.', 709 array( 710 'event' => 'stripe.payment_intent.void.success', 711 'component' => 'payments', 712 'feature' => 'payment_intent', 713 'operation' => 'void', 714 'outcome' => 'success', 715 'method' => __METHOD__, 716 'line' => __LINE__, 717 'data' => array( 'order_id' => $order->get_id(), 'order_number' => $order->get_order_number(), 'payment_intent_id' => $payment_intent_id, 'mode' => $mode ), 718 ) 719 ); 494 720 return array( 495 721 'success' => true, … … 498 724 499 725 } catch ( \Stripe\Exception\ApiErrorException $e ) { 500 peachpay_log( 'error', 'Stripe.payment_intent.void.api_exception | ' . json_encode( array( 'order_id' => $order->get_id(), 'order_number' => $order->get_order_number(), 'error_message' => $e->getMessage() ) ) ); 726 peachpay_log( 727 'error', 728 'Stripe Payment intent void API exception - failed.', 729 array( 730 'event' => 'stripe.payment_intent.void.api_exception', 731 'component' => 'payments', 732 'feature' => 'payment_intent', 733 'operation' => 'void.api_exception', 734 'outcome' => 'failed', 735 'method' => __METHOD__, 736 'line' => __LINE__, 737 'data' => array( 'order_id' => $order->get_id(), 'order_number' => $order->get_order_number(), 'error_message' => $e->getMessage() ), 738 ) 739 ); 501 740 return array( 502 741 'success' => false, … … 504 743 ); 505 744 } catch ( \Exception $e ) { 506 peachpay_log( 'error', 'Stripe.payment_intent.void.exception | ' . json_encode( array( 'order_id' => $order->get_id(), 'order_number' => $order->get_order_number(), 'error_message' => $e->getMessage() ) ) ); 745 peachpay_log( 746 'error', 747 'Stripe Payment intent void exception - failed.', 748 array( 749 'event' => 'stripe.payment_intent.void.exception', 750 'component' => 'payments', 751 'feature' => 'payment_intent', 752 'operation' => 'void', 753 'outcome' => 'exception', 754 'method' => __METHOD__, 755 'line' => __LINE__, 756 'data' => array( 'order_id' => $order->get_id(), 'order_number' => $order->get_order_number(), 'error_message' => $e->getMessage() ), 757 ) 758 ); 507 759 return array( 508 760 'success' => false, … … 520 772 */ 521 773 public static function refund_payment( $order, $amount = null, $reason = null ) { 522 peachpay_log( 'debug', 'Stripe.payment_intent.refund.request | ' . json_encode( array( 'order_id' => $order->get_id(), 'order_number' => $order->get_order_number(), 'amount' => $amount, 'reason' => $reason ) ) ); 774 peachpay_log( 775 'debug', 776 'Stripe Payment intent refund request - debug.', 777 array( 778 'event' => 'stripe.payment_intent.refund.request', 779 'component' => 'payments', 780 'feature' => 'payment_intent', 781 'operation' => 'refund.request', 782 'outcome' => 'debug', 783 'method' => __METHOD__, 784 'line' => __LINE__, 785 'data' => array( 'order_id' => $order->get_id(), 'order_number' => $order->get_order_number(), 'amount' => $amount, 'reason' => $reason ), 786 ) 787 ); 523 788 524 789 try { … … 527 792 528 793 if ( ! $stripe ) { 529 peachpay_log( 'error', 'Stripe.payment_intent.refund.not_configured | ' . json_encode( array( 'order_id' => $order->get_id(), 'order_number' => $order->get_order_number(), 'mode' => $mode ) ) ); 794 peachpay_log( 795 'error', 796 'Stripe Payment intent refund not configured - failed.', 797 array( 798 'event' => 'stripe.payment_intent.refund.not_configured', 799 'component' => 'payments', 800 'feature' => 'payment_intent', 801 'operation' => 'refund.not_configured', 802 'outcome' => 'failed', 803 'method' => __METHOD__, 804 'line' => __LINE__, 805 'data' => array( 'order_id' => $order->get_id(), 'order_number' => $order->get_order_number(), 'mode' => $mode ), 806 ) 807 ); 530 808 return array( 531 809 'success' => false, … … 589 867 $order->add_order_note( sprintf( __( 'Stripe %1$s payment refunded %2$s (Refund Id: %3$s)', 'peachpay-for-woocommerce' ), $order->get_payment_method_title(), $refund_amount_display, $refund->id ) ); 590 868 591 peachpay_log( 'info', 'Stripe.payment_intent.refund.success | ' . json_encode( array( 'order_id' => $order->get_id(), 'order_number' => $order->get_order_number(), 'payment_intent_id' => $payment_intent_id, 'refund_id' => $refund->id, 'refund_amount' => $refund->amount, 'refund_currency' => $refund->currency, 'mode' => $mode ) ) ); 869 peachpay_log( 870 'info', 871 'Stripe Payment intent refund - success.', 872 array( 873 'event' => 'stripe.payment_intent.refund.success', 874 'component' => 'payments', 875 'feature' => 'payment_intent', 876 'operation' => 'refund', 877 'outcome' => 'success', 878 'method' => __METHOD__, 879 'line' => __LINE__, 880 'data' => array( 'order_id' => $order->get_id(), 'order_number' => $order->get_order_number(), 'payment_intent_id' => $payment_intent_id, 'refund_id' => $refund->id, 'refund_amount' => $refund->amount, 'refund_currency' => $refund->currency, 'mode' => $mode ), 881 ) 882 ); 592 883 return array( 593 884 'success' => true, 594 885 'message' => 'Success.', 886 'refund_id' => $refund->id, 595 887 ); 596 888 597 889 } catch ( \Stripe\Exception\ApiErrorException $e ) { 598 peachpay_log( 'error', 'Stripe.payment_intent.refund.api_exception | ' . json_encode( array( 'order_id' => $order->get_id(), 'order_number' => $order->get_order_number(), 'error_message' => $e->getMessage() ) ) ); 890 peachpay_log( 891 'error', 892 'Stripe Payment intent refund API exception - failed.', 893 array( 894 'event' => 'stripe.payment_intent.refund.api_exception', 895 'component' => 'payments', 896 'feature' => 'payment_intent', 897 'operation' => 'refund.api_exception', 898 'outcome' => 'failed', 899 'method' => __METHOD__, 900 'line' => __LINE__, 901 'data' => array( 'order_id' => $order->get_id(), 'order_number' => $order->get_order_number(), 'error_message' => $e->getMessage() ), 902 ) 903 ); 599 904 return array( 600 905 'success' => false, … … 602 907 ); 603 908 } catch ( \Exception $e ) { 604 peachpay_log( 'error', 'Stripe.payment_intent.refund.exception | ' . json_encode( array( 'order_id' => $order->get_id(), 'order_number' => $order->get_order_number(), 'error_message' => $e->getMessage() ) ) ); 909 peachpay_log( 910 'error', 911 'Stripe Payment intent refund exception - failed.', 912 array( 913 'event' => 'stripe.payment_intent.refund.exception', 914 'component' => 'payments', 915 'feature' => 'payment_intent', 916 'operation' => 'refund', 917 'outcome' => 'exception', 918 'method' => __METHOD__, 919 'line' => __LINE__, 920 'data' => array( 'order_id' => $order->get_id(), 'order_number' => $order->get_order_number(), 'error_message' => $e->getMessage() ), 921 ) 922 ); 605 923 return array( 606 924 'success' => false, … … 755 1073 */ 756 1074 public static function setup_payment( $session_id, $setup_intent_params ) { 757 peachpay_log( 'debug', 'Stripe.setup_intent.create.request | ' . json_encode( array( 'session_id' => $session_id ) ) ); 1075 peachpay_log( 1076 'debug', 1077 'Stripe Setup intent create request - debug.', 1078 array( 1079 'event' => 'stripe.setup_intent.create.request', 1080 'component' => 'payments', 1081 'feature' => 'setup_intent', 1082 'operation' => 'create.request', 1083 'outcome' => 'debug', 1084 'method' => __METHOD__, 1085 'line' => __LINE__, 1086 'data' => array( 'session_id' => $session_id ), 1087 ) 1088 ); 758 1089 759 1090 try { … … 762 1093 763 1094 if ( ! $stripe ) { 764 peachpay_log( 'error', 'Stripe.setup_intent.create.not_configured | ' . json_encode( array( 'session_id' => $session_id, 'mode' => $mode ) ) ); 1095 peachpay_log( 1096 'error', 1097 'Stripe Setup intent create not configured - failed.', 1098 array( 1099 'event' => 'stripe.setup_intent.create.not_configured', 1100 'component' => 'payments', 1101 'feature' => 'setup_intent', 1102 'operation' => 'create.not_configured', 1103 'outcome' => 'failed', 1104 'method' => __METHOD__, 1105 'line' => __LINE__, 1106 'data' => array( 'session_id' => $session_id, 'mode' => $mode ), 1107 ) 1108 ); 765 1109 return array( 766 1110 'success' => false, … … 828 1172 } 829 1173 830 peachpay_log( 'info', 'Stripe.setup_intent.create.success | ' . json_encode( array( 'session_id' => $session_id, 'setup_intent_id' => $setup_intent->id, 'customer_id' => $setup_intent->customer, 'status' => $setup_intent->status, 'mode' => $mode ) ) ); 1174 peachpay_log( 1175 'info', 1176 'Stripe Setup intent create - success.', 1177 array( 1178 'event' => 'stripe.setup_intent.create.success', 1179 'component' => 'payments', 1180 'feature' => 'setup_intent', 1181 'operation' => 'create', 1182 'outcome' => 'success', 1183 'method' => __METHOD__, 1184 'line' => __LINE__, 1185 'data' => array( 'session_id' => $session_id, 'setup_intent_id' => $setup_intent->id, 'customer_id' => $setup_intent->customer, 'status' => $setup_intent->status, 'mode' => $mode ), 1186 ) 1187 ); 831 1188 return array( 832 1189 'success' => true, … … 835 1192 836 1193 } catch ( \Stripe\Exception\ApiErrorException $e ) { 837 peachpay_log( 'error', 'Stripe.setup_intent.create.api_exception | ' . json_encode( array( 'session_id' => $session_id, 'error_message' => $e->getMessage() ) ) ); 1194 peachpay_log( 1195 'error', 1196 'Stripe Setup intent create API exception - failed.', 1197 array( 1198 'event' => 'stripe.setup_intent.create.api_exception', 1199 'component' => 'payments', 1200 'feature' => 'setup_intent', 1201 'operation' => 'create.api_exception', 1202 'outcome' => 'failed', 1203 'method' => __METHOD__, 1204 'line' => __LINE__, 1205 'data' => array( 'session_id' => $session_id, 'error_message' => $e->getMessage() ), 1206 ) 1207 ); 838 1208 return array( 839 1209 'success' => false, … … 841 1211 ); 842 1212 } catch ( \Exception $e ) { 843 peachpay_log( 'error', 'Stripe.setup_intent.create.exception | ' . json_encode( array( 'session_id' => $session_id, 'error_message' => $e->getMessage() ) ) ); 1213 peachpay_log( 1214 'error', 1215 'Stripe Setup intent create exception - failed.', 1216 array( 1217 'event' => 'stripe.setup_intent.create.exception', 1218 'component' => 'payments', 1219 'feature' => 'setup_intent', 1220 'operation' => 'create', 1221 'outcome' => 'exception', 1222 'method' => __METHOD__, 1223 'line' => __LINE__, 1224 'data' => array( 'session_id' => $session_id, 'error_message' => $e->getMessage() ), 1225 ) 1226 ); 844 1227 return array( 845 1228 'success' => false, -
peachpay-for-woocommerce/trunk/peachpay.php
r3486614 r3490786 4 4 * Plugin URI: https://woocommerce.com/products/peachpay 5 5 * Description: Connect and manage all your payment methods, offer shoppers a beautiful Express Checkout, and reduce cart abandonment. 6 * Version: 1.120.2 26 * Version: 1.120.23 7 7 * Text Domain: peachpay-for-woocommerce 8 8 * Domain Path: /languages -
peachpay-for-woocommerce/trunk/readme.txt
r3486614 r3490786 4 4 Requires at least: 5.8 5 5 Tested up to: 6.9.1 6 Stable tag: 1.120.2 26 Stable tag: 1.120.23 7 7 Requires PHP: 7.0 8 8 License: GPLv2 or later … … 262 262 263 263 == Changelog == 264 265 = 1.120.23 = 266 * **Fixed**: 267 * **Subscriptions**: Prevented duplicate subscription renewal charges across ConvesioPay and Stripe. 268 * **Stripe**: Fixed duplicate WooCommerce refunds triggered by Stripe charge.refunded webhook. 269 * **Improved**: 270 * **Logging**: Standardized payment logging between ConvesioPay and Stripe for better consistency and debugging. 271 * **NMI**: Improved homepage payment box with UI reorganization and enhanced validation. 272 * **Build**: 273 * Suppressed known CSS browser-support stylelint warnings to reduce noise in builds. 264 274 265 275 = 1.120.22 =
Note: See TracChangeset
for help on using the changeset viewer.