Skip to content

Commit

Permalink
Release 3.0.12
Browse files Browse the repository at this point in the history
  • Loading branch information
andrewrowanwallee committed Sep 2, 2024
1 parent df18cdf commit 7e8578a
Show file tree
Hide file tree
Showing 46 changed files with 1,682 additions and 95 deletions.
4 changes: 2 additions & 2 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -16,7 +16,7 @@ This repository contains the PostFinance Checkout plugin that enables WooCommerc

## Documentation

* [Documentation](https://plugin-documentation.postfinance-checkout.ch/pfpayments/woocommerce/3.0.11/docs/en/documentation.html)
* [Documentation](https://plugin-documentation.postfinance-checkout.ch/pfpayments/woocommerce/3.0.12/docs/en/documentation.html)

## Support

Expand All @@ -33,4 +33,4 @@ ____________________________________________________________________________

## License

Please see the [license file](https://github.com/pfpayments/woocommerce/blob/3.0.11/LICENSE) for more information.
Please see the [license file](https://github.com/pfpayments/woocommerce/blob/3.0.12/LICENSE) for more information.
9 changes: 6 additions & 3 deletions assets/css/admin.css
Original file line number Diff line number Diff line change
@@ -1,10 +1,13 @@
/**
* PostFinance Checkout WooCommerce
*
* This WooCommerce plugin enables to process payments with PostFinance Checkout (https://postfinance.ch/en/business/products/e-commerce/postfinance-checkout-all-in-one.html).
* PostFinanceCheckout
* This plugin will add support for all PostFinanceCheckout payments methods and connect the PostFinanceCheckout servers to your WooCommerce webshop (https://postfinance.ch/en/business/products/e-commerce/postfinance-checkout-all-in-one.html).
*
* @author postfinancecheckout AG (https://postfinance.ch/en/business/products/e-commerce/postfinance-checkout-all-in-one.html)
* @license http://www.apache.org/licenses/LICENSE-2.0 Apache Software License (ASL 2.0)
* @category Class
* @package PostFinanceCheckout
* @author postfinancecheckout AG (https://postfinance.ch/en/business/products/e-commerce/postfinance-checkout-all-in-one.html)
* @license http://www.apache.org/licenses/LICENSE-2.0 Apache Software License (ASL 2.0)
*/
/* Icons for status */
@font-face {
Expand Down
9 changes: 6 additions & 3 deletions assets/css/checkout.css
Original file line number Diff line number Diff line change
@@ -1,10 +1,13 @@
/**
* PostFinance Checkout WooCommerce
*
* This WooCommerce plugin enables to process payments with PostFinance Checkout (https://postfinance.ch/en/business/products/e-commerce/postfinance-checkout-all-in-one.html).
* PostFinanceCheckout
* This plugin will add support for all PostFinanceCheckout payments methods and connect the PostFinanceCheckout servers to your WooCommerce webshop (https://postfinance.ch/en/business/products/e-commerce/postfinance-checkout-all-in-one.html).
*
* @author postfinancecheckout AG (https://postfinance.ch/en/business/products/e-commerce/postfinance-checkout-all-in-one.html)
* @license http://www.apache.org/licenses/LICENSE-2.0 Apache Software License (ASL 2.0)
* @category Class
* @package PostFinanceCheckout
* @author postfinancecheckout AG (https://postfinance.ch/en/business/products/e-commerce/postfinance-checkout-all-in-one.html)
* @license http://www.apache.org/licenses/LICENSE-2.0 Apache Software License (ASL 2.0)
*/
/* Order button disabled */
#place_order.postfinancecheckout-disabled{
Expand Down
1 change: 1 addition & 0 deletions build/index.asset.php
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
<?php return array('dependencies' => array('@woocommerce/blocks-registry', 'react', 'wp-element', 'wp-polyfill'), 'version' => 'b53687c38b284a0c8c13');
1 change: 1 addition & 0 deletions build/index.css
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@

1 change: 1 addition & 0 deletions build/index.js

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

7 changes: 7 additions & 0 deletions changelog.txt
Original file line number Diff line number Diff line change
Expand Up @@ -804,3 +804,10 @@ Tested against:
- [Tested Against] Woocommerce 9.1.4
- [Tested Against] PHP SDK 4.5.0

= 3.0.12 - Aug 21 2024 =
- [Feature] Implemented the Webhook Signing Mechanism
- [Tested Against] PHP 8.0 and PHP 7.4
- [Tested Against] Wordpress 6.6
- [Tested Against] Woocommerce 9.1.4
- [Tested Against] PHP SDK 4.5.0

2 changes: 1 addition & 1 deletion docs/en/documentation.html
Original file line number Diff line number Diff line change
Expand Up @@ -23,7 +23,7 @@ <h2>Documentation</h2> </div>
</a>
</li>
<li>
<a href="https://github.com/pfpayments/woocommerce/releases/tag/3.0.11/">
<a href="https://github.com/pfpayments/woocommerce/releases/tag/3.0.12/">
Source
</a>
</li>
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -187,7 +187,7 @@ public function get_settings() {
$settings = array(
array(
'links' => array(
'https://plugin-documentation.postfinance-checkout.ch/pfpayments/woocommerce/3.0.11/docs/en/documentation.html' => __( 'Documentation', 'woo-postfinancecheckout' ),
'https://plugin-documentation.postfinance-checkout.ch/pfpayments/woocommerce/3.0.12/docs/en/documentation.html' => __( 'Documentation', 'woo-postfinancecheckout' ),
'https://checkout.postfinance.ch/en-ch/user/signup' => __( 'Sign Up', 'woo-postfinancecheckout' ),
),
'type' => 'postfinancecheckout_links',
Expand Down
11 changes: 7 additions & 4 deletions includes/class-wc-postfinancecheckout-autoloader.php
Original file line number Diff line number Diff line change
Expand Up @@ -52,7 +52,8 @@ public function __construct() {
* @return string
*/
private function get_file_name_from_class( $class ) {
return 'class-' . str_replace( '_', '-', $class ) . '.php';
$class = preg_replace( '/(?<!^)[A-Z]/', '-$0', $class );
return 'class-' . str_replace( '_', '-', strtolower( $class ) ) . '.php';
}

/**
Expand Down Expand Up @@ -91,7 +92,11 @@ public function autoload( $class ) {
} elseif ( strpos( $class, 'wc_postfinancecheckout_provider' ) === 0 ) {
$path = $this->include_path . 'provider/';
} elseif ( strpos( $class, 'wc_postfinancecheckout_webhook' ) === 0 ) {
$path = $this->include_path . 'webhook/';
if (strpos($class, 'strategy') !== false) {
$path = $this->include_path . 'webhook/strategies/';
} else {
$path = $this->include_path . 'webhook/';
}
} elseif ( strpos( $class, 'wc_postfinancecheckout_exception' ) === 0 ) {
$path = $this->include_path . 'exception/';
} elseif ( strpos( $class, 'wc_postfinancecheckout_admin' ) === 0 ) {
Expand All @@ -101,8 +106,6 @@ public function autoload( $class ) {
if ( empty( $path ) || ! $this->load_file( $path . $file ) ) {
$this->load_file( $this->include_path . $file );
}

$this->load_file( $this->include_path . $file );
}
}

Expand Down
14 changes: 12 additions & 2 deletions includes/class-wc-postfinancecheckout-migration.php
Original file line number Diff line number Diff line change
Expand Up @@ -249,7 +249,7 @@ public static function check_version() {
public static function plugin_row_meta( $links, $file ) {
if ( WC_POSTFINANCECHECKOUT_PLUGIN_BASENAME === $file ) {
$row_meta = array(
'docs' => '<a href="https://plugin-documentation.postfinance-checkout.ch/pfpayments/woocommerce/3.0.11/docs/en/documentation.html" aria-label="' . esc_attr__( 'View Documentation', 'woo-postfinancecheckout' ) . '">' . esc_html__( 'Documentation', 'woo-postfinancecheckout' ) . '</a>',
'docs' => '<a href="https://plugin-documentation.postfinance-checkout.ch/pfpayments/woocommerce/3.0.12/docs/en/documentation.html" aria-label="' . esc_attr__( 'View Documentation', 'woo-postfinancecheckout' ) . '">' . esc_html__( 'Documentation', 'woo-postfinancecheckout' ) . '</a>',
);

return array_merge( $links, $row_meta );
Expand Down Expand Up @@ -584,10 +584,20 @@ public static function update_1_0_6_shorten_table_names() {
* @return void
*/
public static function supported_payments_integration_notice(): void {
if (!class_exists( 'WooCommerce' )) {
add_action('admin_notices', function() {
?>
<div class="notice notice-error">
<p><?php _e('WooCommerce is not activated. Please activate WooCommerce to use the payment integration.', 'woo-postfinancecheckout'); ?></p>
</div>
<?php
});
return;
}
$woocommerce_data = get_plugin_data( WP_PLUGIN_DIR . '/woocommerce/woocommerce.php', false, false );

if (version_compare( $woocommerce_data['Version'], WC_POSTFINANCECHECKOUT_REQUIRED_WC_MAXIMUM_VERSION, '>' )) {
$notice_id = "postfinancecheckout-{$woocommerce_data['Version']}-not-yet-supported";
$notice_id = "postfinancecheckout-{$woocommerce_data['Version']}-not-yet-supported";
if (!WC_Admin_Notices::user_has_dismissed_notice($notice_id)) {
$message = sprintf(__( 'The plugin PostFinanceCheckout has been tested up to WooCommerce %1$s but you have installed the version %2$s. Please notice that this is not recommended.' , 'woo-postfinancecheckout'), WC_POSTFINANCECHECKOUT_REQUIRED_WC_MAXIMUM_VERSION, $woocommerce_data['Version']);
WC_Admin_Notices::add_custom_notice($notice_id, esc_html( $message ));
Expand Down
43 changes: 29 additions & 14 deletions includes/class-wc-postfinancecheckout-webhook-handler.php
Original file line number Diff line number Diff line change
Expand Up @@ -57,32 +57,47 @@ public static function handle_webhook_errors( $errno, $errstr, $errfile, $errlin
}

/**
* Process the webhook call.
* Processes incoming webhook calls.
* This method handles both signed and unsigned payloads by determining the presence of a digital signature.
* It sets an initial HTTP 500 status to indicate a failure if the process crashes unexpectedly.
*/
public static function process() {
$webhook_service = WC_PostFinanceCheckout_Service_Webhook::instance();
global $wp_filesystem;
if ( empty( $wp_filesystem ) ) {
require_once ABSPATH . '/wp-admin/includes/file.php';
WP_Filesystem();
}

// We set the status to 500, so if we encounter a state where the process crashes the webhook is marked as failed.
header( 'HTTP/1.1 500 Internal Server Error' );
$request_body = trim( file_get_contents( 'php://input' ) );
$raw_post_data = $wp_filesystem->get_contents( 'php://input' );
$signature = isset( $_SERVER['HTTP_X_SIGNATURE'] ) ? sanitize_text_field( wp_unslash( $_SERVER['HTTP_X_SIGNATURE'] ) ) : '';
set_error_handler( array( __CLASS__, 'handle_webhook_errors' ) );
try {
$request = new WC_PostFinanceCheckout_Webhook_Request( json_decode( $request_body ) );
$webhook_model = $webhook_service->get_webhook_entity_for_id( $request->get_listener_entity_id() );
if ( null === $webhook_model ) {
WooCommerce_PostFinanceCheckout::instance()->log( sprintf( 'Could not retrieve webhook model for listener entity id: %s', $request->get_listener_entity_id() ), WC_Log_Levels::ERROR );
// phpcs:ignore
echo esc_html__( sprintf( 'Could not retrieve webhook model for listener entity id: %s', $request->get_listener_entity_id() ) );
exit();
$clean_data = wp_kses_post( wp_unslash( $raw_post_data ) );
$request = new WC_PostFinanceCheckout_Webhook_Request( json_decode( $clean_data ) );
$client = WC_Wallee_Helper::instance()->get_api_client();
$webhook_service = WC_PostFinanceCheckout_Service_Webhook::instance();

// Handling of payloads without a signature (legacy method).
// Deprecated since 3.0.12
if ( empty( $signature ) ) {
$webhook_model = $webhook_service->get_webhook_entity_for_id( $request->get_listener_entity_id() );
$webhook_handler_class_name = $webhook_model->get_handler_class_name();
$webhook_handler = $webhook_handler_class_name::instance();
$webhook_handler->process( $request );
}

// Handling of payloads with a valid signature.
// This payload signed has the transaction state
if ( !empty( $signature ) && $client->getWebhookEncryptionService()->isContentValid( $signature, $clean_data ) ) {
WC_PostFinanceCheckout_Webhook_Strategy_Manager::instance()->process( $request );
}
$webhook_handler_class_name = $webhook_model->get_handler_class_name();
$webhook_handler = $webhook_handler_class_name::instance();
$webhook_handler->process( $request );

header( 'HTTP/1.1 200 OK' );
} catch ( Exception $e ) {
WooCommerce_PostFinanceCheckout::instance()->log( $e->getMessage(), WC_Log_Levels::ERROR );
// phpcs:ignore
// phpcs:ignore
echo esc_textarea($e->getMessage());
exit();
}
Expand Down
109 changes: 86 additions & 23 deletions includes/service/class-wc-postfinancecheckout-service-line-item.php
Original file line number Diff line number Diff line change
Expand Up @@ -241,16 +241,17 @@ protected function create_shipping_line_items_from_session( $packages, $chosen_m
*/
protected function create_coupons_line_items_from_session() {
$coupons = array();
$currency = get_woocommerce_currency();
$cart = WC()->cart;

if ( empty( $cart->get_applied_coupons() ) ) {
return $coupons;
}

$discount = $cart->get_discount_total() + $cart->get_discount_tax();
$line_item = $this->create_coupon_line_item( current($cart->get_coupons()), $discount );
$coupons[] = $line_item;
$line_items = $this->create_coupon_line_items( current( $cart->get_coupons() ), $discount );
if ( is_array( $line_items ) ) {
$coupons = array_merge( $coupons, $line_items );
}
return $coupons;
}

Expand All @@ -260,27 +261,86 @@ protected function create_coupons_line_items_from_session() {
* @param float $amount
* @return \PostFinanceCheckout\Sdk\Model\LineItemCreate|null
*/
private function create_coupon_line_item( $coupon, float $amount = 0 ) {
//check if the coupon is valid
private function create_coupon_line_items( $coupon, float $total_discount_amount = 0 ) {
if ( !$coupon instanceof WC_Coupon && !$coupon instanceof WC_Order_Item_Coupon ) {
return null;
return [];
}

$coupon = new WC_Coupon( $coupon->get_code() );

$amount = $amount * -1;
$sku = $this->fix_length( $coupon->get_discount_type(), 150 );
$sku = str_replace( array( "\n", "\r", ), '', $sku );

// Calculate the proportional discount amounts for each tax rate
$discounts = $this->calculate_discount_rates_proportionally( $total_discount_amount );

$line_items = [];

foreach ( $discounts as $discount ) {
$line_item = new \PostFinanceCheckout\Sdk\Model\LineItemCreate();
$line_item->setAmountIncludingTax( $discount['amount'] * -1 );
$line_item->setName( sprintf( '%s: %s (%s%% tax)', WC_PostFinanceCheckout_Packages_Coupon_Discount::COUPON, $coupon->get_code(), $discount['rate_id']) );
$line_item->setQuantity( 1 );
$line_item->setShippingRequired( false );
$line_item->setSku( $sku, 200 );
$line_item->setType( \PostFinanceCheckout\Sdk\Model\LineItemType::DISCOUNT );
$line_item->setUniqueId( 'coupon-' . $coupon->get_id() . '-' . $discount['rate_id'] );

$tax_rate = new \PostFinanceCheckout\Sdk\Model\TaxCreate([
'title' => 'Discount Tax: ' . $discount['rate_id'],
'rate' => $discount['rate_id'],
]);

$line_item->setTaxes( [$tax_rate] );

$line_items[] = $line_item;
}

return $line_items;
}

$line_item = new \PostFinanceCheckout\Sdk\Model\LineItemCreate();
$line_item->setAmountIncludingTax( $amount );
$line_item->setName( sprintf( '%s: %s', WC_PostFinanceCheckout_Packages_Coupon_Discount::COUPON, $coupon->get_code() ) );
$line_item->setQuantity( 1 );
$line_item->setShippingRequired( false );
$line_item->setSku( $sku, 200 );
$line_item->setType( \PostFinanceCheckout\Sdk\Model\LineItemType::DISCOUNT );
$line_item->setUniqueId( 'coupon-' . $coupon->get_id() );
return $line_item;
/**
* @param float $total_discount_amount
* @return array
*/
private function calculate_discount_rates_proportionally(float $total_discount_amount): array {
$cart = WC()->cart;
$tax_totals = [];
$total_amount = 0;

foreach ( $cart->get_cart() as $cart_item ) {
$product = $cart_item['data'];
$tax_class = $product->get_tax_class();
$tax_rates_class = WC_Tax::get_rates( $tax_class );

foreach ( $tax_rates_class as $rate ) {
$rate_id = $rate['rate'];
$line_total_with_tax = $cart_item['line_total'] + $cart_item['line_tax'];

if ( !isset($tax_totals[$rate_id]) ) {
$tax_totals[$rate_id] = [
'total' => 0,
'rate_percentage' => $rate_id
];
}

$tax_totals[$rate_id]['total'] += $line_total_with_tax;
$total_amount += $line_total_with_tax;
}
}

$discounts = [];

foreach ($tax_totals as $rate_id => $data) {
$proportional_discount_amount = $total_discount_amount * ($data['total'] / $total_amount);

$discounts[] = [
'rate_id' => $rate_id,
'amount' => $proportional_discount_amount,
'rate_percentage' => $rate_id,
];
}

return $discounts;
}
/**
* Returns the line items from the given cart
Expand Down Expand Up @@ -514,8 +574,11 @@ protected function create_coupons_line_items_from_order( WC_Order $order ) {
/** @var WC_Order_Item_Coupon $coupon */
$discount += (float)$coupon->get_discount() + (float)$coupon->get_discount_tax();
}
$line_item = $this->create_coupon_line_item( current($order->get_coupons()), $discount );
$coupons[] = $this->clean_line_item( $line_item );

$line_items = $this->create_coupon_line_items( current($order->get_coupons()), $discount );
foreach ($line_items as $line_item) {
$coupons[] = $this->clean_line_item( $line_item );
}
return $coupons;
}

Expand Down Expand Up @@ -568,11 +631,11 @@ protected function create_product_line_items_from_backend( array $backend_items,

//At this point, if there is a discount applied by coupon, the price already has the discount applied,
//and to be able to send the discount to the portal, it is necessary to restore the discounted amount,
//the original price must be restored before being applied, otherwise it would be discounting twice in the portal.
//the original price must be restored before being applied, otherwise it would be discounting twice in the portal.
$item_data_coupon = $item->get_meta( '_postfinancecheckout_coupon_discount_line_item_discounts' );
if ( !empty ( $item_data_coupon ) ) {
$discount_tax = $item->get_subtotal_tax() - $item->get_total_tax();
$discount_amount = $item->get_subtotal() - $item->get_total();
$discount_tax = $item->get_subtotal_tax() - $item->get_total_tax();
$discount_amount = $item->get_subtotal() - $item->get_total();
$discounts = $discount_tax + $discount_amount;
}

Expand Down
Loading

0 comments on commit 7e8578a

Please sign in to comment.