diff --git a/CHANGELOG.md b/CHANGELOG.md
index 03eb0bd..d3905ae 100644
--- a/CHANGELOG.md
+++ b/CHANGELOG.md
@@ -1,5 +1,17 @@
# Release Notes - heidelpay Payment Gateway for WooCommerce
+## 1.2.0
+
+### Fixed:
+- Missing payment information for secured invoice and direct debit on success page and notification mail.
+- Invoice instruction was shown in other mails where other payment methods were used.
+- Exception that can occur in combination with other plugins.
+
+### Added
+#### Features:
+- Support for push notifications
+- A checkbox to decide whether payment information should be added to the notification mail or not.
+
## 1.1.1
### Fixed:
diff --git a/includes/abstracts/abstract-wc-heidelpay-iframe-gateway.php b/includes/abstracts/abstract-wc-heidelpay-iframe-gateway.php
index ada650c..36ea146 100644
--- a/includes/abstracts/abstract-wc-heidelpay-iframe-gateway.php
+++ b/includes/abstracts/abstract-wc-heidelpay-iframe-gateway.php
@@ -102,11 +102,10 @@ public function enqueue_assets()
*/
public function after_pay()
{
- $order_id = wc_get_order_id_by_order_key($_GET['key']);
- $order = wc_get_order($order_id);
+ $order = $this->getOrderFromKey();
- if ($order->get_payment_method() === $this->id) {
- $this->performRequest($order_id);
+ if ($order !== null && $order->get_payment_method() === $this->id) {
+ $this->performRequest($order->get_id());
}
}
@@ -145,6 +144,7 @@ protected function getIFrame( WC_Order $order)
. '" frameborder="0" scrolling="no" style="height:360px;">
';
} else {
$iFrame .= '
' . print_r($this->getErrorMessage(), 1) . ''; + $this->paymentLog($this->payMethod->getResponse()->getError()); } $iFrame .= ''; $iFrame .= ''; diff --git a/includes/abstracts/abstract-wc-heidelpay-payment-gateway.php b/includes/abstracts/abstract-wc-heidelpay-payment-gateway.php index 15f1752..a7c4cd4 100644 --- a/includes/abstracts/abstract-wc-heidelpay-payment-gateway.php +++ b/includes/abstracts/abstract-wc-heidelpay-payment-gateway.php @@ -51,15 +51,18 @@ public function __construct() $this->title = $this->get_option('title'); $this->description = $this->get_option('description'); $this->instructions = $this->get_option('instructions'); - + // Actions add_action('woocommerce_update_options_payment_gateways_' . $this->id, array($this, 'process_admin_options')); add_action('woocommerce_api_' . strtolower(get_class($this)), array($this, 'callback_handler')); + add_action('woocommerce_api_push', array($this, 'pushHandler')); add_action('wp_enqueue_scripts', array($this, 'enqueue_assets')); add_action('woocommerce_after_checkout_validation', array($this, 'checkoutValidation')); + add_action('woocommerce_email_before_order_table', array($this, 'emailInstructions'), 10, 3); // Filter add_filter('woocommerce_available_payment_gateways', array($this, 'setAvailability')); + add_filter('woocommerce_thankyou_order_received_text', array($this, 'addPayInfo')); } /** @@ -67,27 +70,14 @@ public function __construct() */ abstract protected function setPayMethod(); - /** - * Validate the customer input coming from checkout. - * @return boolean - */ - public function checkoutValidation() - { - //return true; - } - /** - * Check whether this paymethod was selected based on - * @return bool - */ - public function isGatewayActive() + public function pushHandler() { - if(!empty($_POST['payment_method'])) { - if($_POST['payment_method'] === $this->id) - return true; + if (array_key_exists('init(file_get_contents('php://input'), $this->get_option('secret')); } - - return false; + exit; } public function init_form_fields() @@ -124,7 +114,7 @@ public function init_form_fields() 'Instructions that will be added to the thank you page and emails.', 'woocommerce-heidelpay' ), - 'default' => __('The following account will be billed:', 'woocommerce-heidelpay'), + 'default' => '', 'desc_tip' => true, ), 'security_sender' => array( @@ -173,6 +163,29 @@ public function init_form_fields() ); } + /** + * Validate the customer input coming from checkout. + * @return boolean + */ + public function checkoutValidation() + { + //return true; + } + + /** + * Check whether this paymethod was selected based on + * @return bool + */ + public function isGatewayActive() + { + if (!empty($_POST['payment_method'])) { + if ($_POST['payment_method'] === $this->id) + return true; + } + + return false; + } + /** * register scripts and stylesheets for your payment gateway */ @@ -280,7 +293,7 @@ protected function setCriterions() global $wp_version; $shopType = 'WordPress: ' . $wp_version . ' - ' . 'WooCommerce: ' . wc()->version; - $this->payMethod->getRequest()->getCriterion()->set('PUSH_URL', 'push-url for testing'); //TODO insert URL + $this->payMethod->getRequest()->getCriterion()->set('PUSH_URL', get_home_url() . '/wc-api/push'); $this->payMethod->getRequest()->getCriterion()->set('SHOP.TYPE', $shopType); $this->payMethod->getRequest()->getCriterion()->set( 'SHOPMODULE.VERSION', @@ -318,6 +331,7 @@ protected function performRequest($order_id) ]; } + $this->paymentLog($this->payMethod->getResponse()->getError()); $this->addPaymentError($this->getErrorMessage()); } else { $this->addPaymentError($this->getErrorMessage()); @@ -326,7 +340,10 @@ protected function performRequest($order_id) WC_Log_Levels::ERROR, htmlspecialchars( print_r( - $this->plugin_id . ' - ' . $this->id . __(' Error: Paymentmethod was not found: ', 'woocommerce-heidelpay') . $this->bookingAction, + $this->plugin_id . ' - ' . $this->id . __( + ' Error: Paymentmethod was not found: ', + 'woocommerce-heidelpay' + ) . $this->bookingAction, 1 ) ) @@ -336,6 +353,13 @@ protected function performRequest($order_id) } } + /** + * process the Form input from customer comimg from checkout. + */ + protected function handleFormPost() + { + } + /** * @return string */ @@ -355,13 +379,6 @@ public function addPaymentError(String $message) ); } - /** - * process the Form input from customer comimg from checkout. - */ - protected function handleFormPost() - { - } - /** * Get the mapped Errormessage from Respone wich is html escaped. * If a response is given as a parameter that will determine the message. Otherwise the Response from the payMethod @@ -401,8 +418,8 @@ public function admin_options() */ public function callback_handler() { - $response = new WC_Heidelpay_Response(); if (!empty($_POST)) { + $response = new WC_Heidelpay_Response(); $response->init($_POST, $this->get_option('secret')); } exit(); @@ -436,4 +453,85 @@ protected function getBookingSelection() 'default' => 'DB' ); } + + /** + * Funktion to log Events as a notice. It has a prefix to identify that the log entry is from heidelpay and which + * function has created it. + * @param string|array $logData + */ + protected function paymentLog($logData) + { + $callers = debug_backtrace(); + wc_get_logger()->log(WC_Log_Levels::NOTICE, print_r('heidelpay - ' . + $callers [1] ['function'] .': '. print_r($logData, 1), 1)); + } + + /** + * Get the order using the Get parameter 'key' + * @return bool|WC_Order|WC_Refund + */ + public function getOrderFromKey() + { + if(isset($_GET['key'])) { + $order_id = wc_get_order_id_by_order_key($_GET['key']); + return wc_get_order($order_id); + } + + return null; + } + + /** + * "woocommerce_thankyou_order_received_text" hook to display heidelpay-paymentInfo text on the successpage after + * payment. + * @param $orderReceivedText + * @return string + */ + public function addPayInfo($orderReceivedText) + { + $order = $this->getOrderFromKey(); + + if ($order === null || $order->get_payment_method() !== $this->id) { + return $orderReceivedText; + } + + $paymentInfo = $order->get_meta('heidelpay-paymentInfo'); + + if(!empty($paymentInfo)) { + $orderReceivedText .= '
' . $paymentInfo . '
'; + } + + return $orderReceivedText; + } + + /** + * Hook - "woocommerce_email_before_order_table". Add heidelpay-paymentInfo text to "completed order" email. + * @param WC_Order $order + * @param $sent_to_admin + * @param bool $plain_text + * @return null + */ + public function emailInstructions(WC_Order $order, $sent_to_admin, $plain_text = false) + { + if ($order->get_payment_method() !== $this->id) { + return null; + } + + if ($this->instructions) { + echo wpautop(wptexturize($this->instructions)) . PHP_EOL; + } + + $status = $order->get_status(); + // defines the statuses when the mail should be send + $mailingArray = array( + 'pending', + 'on-hold', + 'processing' + ); + + if ($this->get_option('send_payment_info') === 'yes') { + if (in_array($status, $mailingArray)) { + echo $order->get_meta('heidelpay-paymentInfo'); + } + } + } } diff --git a/includes/class-wc-heidelpay-push.php b/includes/class-wc-heidelpay-push.php new file mode 100644 index 0000000..fe8701e --- /dev/null +++ b/includes/class-wc-heidelpay-push.php @@ -0,0 +1,127 @@ +getResponse(); + + try { + $response->verifySecurityHash($secret, $response->getIdentification()->getTransactionId()); + } catch (\Exception $e) { + $callers = debug_backtrace(); + wc_get_logger()->log(WC_Log_Levels::NOTICE, print_r("Heidelpay - " . + $callers [0] ['function'] . ": Invalid push hash from " . + $_SERVER ['REMOTE_ADDR'] . ", suspecting manipulation", 1)); + exit(); //error + } + $this->handlePush($response); + } + + /** + * @param Heidelpay\PhpPaymentApi\Response $response + */ + public function handlePush($response) + { + $orderID = $response->getIdentification()->getTransactionId(); + $order = wc_get_order($orderID); + $payCode = explode('.', strtoupper($response->getPayment()->getCode())); + + wc_get_logger()->log(WC_Log_Levels::DEBUG, $order->get_status()); + + if ($payCode[0] === 'IV') { + if ($response->isSuccess()) { + switch ($payCode[1]) { + case 'FI': + $order->update_status( + 'on-hold', + 'Order has been finalized' + ); + break; + case 'PA': + $order->update_status( + 'processing', + 'Reservation done' + ); + break; + } + } + } + + if ($payCode[1] === 'CP' || $payCode[1] === 'RC' || $payCode[1] === 'DB') { + if ($response->isSuccess()) { + if ($order->get_total() === $response->getPresentation()->getAmount()) { + if ($payCode[0] === 'IV') { + $order->update_status( + 'completed', + $this->getNote($response) + ); + } else { + $order->update_status( + 'processing', + $this->getNote($response) + ); + } + } else { + $order->add_order_note( + $this->getNote($response), + false + ); + } + } elseif ($response->isError()) { + if ($order->get_status() === 'pending') { + $order->update_status('failed'); + } + } + } + } + + /** + * @param Heidelpay\PhpPaymentApi\Response $response + * @return string + */ + private function getNote($response) + { + return sprintf( + __('Payment of %s %s received. Heidelpay ShortID %s', 'woocommerce-heidelpay'), + $response->getPresentation()->getAmount(), + $response->getPresentation()->getCurrency(), + $response->getIdentification()->getShortId() + ); + } +} diff --git a/includes/class-wc-heidelpay-response.php b/includes/class-wc-heidelpay-response.php index bdffd7a..206b0a1 100644 --- a/includes/class-wc-heidelpay-response.php +++ b/includes/class-wc-heidelpay-response.php @@ -25,8 +25,16 @@ class WC_Heidelpay_Response { + /** + * @var Response + */ public static $response; + /** + * Setup for Response handling and security. + * @param array $post_data + * @param $secret + */ public function init(array $post_data, $secret) { if (empty(self::$response)) { @@ -51,35 +59,38 @@ public function init(array $post_data, $secret) $this->handleResult($post_data, $order); - - //TODO: if case for distinction between result and push } /** * handle result post + * + * @param $post_data + * @param WC_Order $order */ - public function handleResult($post_data, WC_Order $order) { $uid = self::$response->getIdentification()->getUniqueId(); if (self::$response->isSuccess()) { - $payCode = explode('.', $post_data ['PAYMENT_CODE']); + $payCode = explode('.', strtoupper($post_data['PAYMENT_CODE'])); $note = ''; + $this->setPaymentInfo($order); + // If no money has been payed yet. - if (strtoupper($payCode[1]) === 'PA' or strtoupper($payCode[1]) === 'RG') { - // In not Prepayment and Invoice payment can be captured manually - if (strtoupper($payCode [0]) !== 'PP' and strtoupper($payCode [0]) !== 'IV') { + if ($payCode[0] !== 'IV' && ($payCode[1] === 'PA' || $payCode[1] === 'RG')) { + // If not Prepayment and Invoice payment can be captured manually + if ($payCode [0] !== 'PP') { $note = __( 'Payment reservation successful. Please use the hiP to check the payment.', - 'woocommerce-heidelpay.' + 'woocommerce-heidelpay' ); $order->add_order_note($note, false); } - - $order->update_status('on-hold', __('Awaiting payment.', 'woocommerce-heidelpay') - . ' ' . $note) . ' '; + $order->update_status( + 'on-hold', + __('Awaiting payment.', 'woocommerce-heidelpay') . ' ' . $note + ); } else { $order->payment_complete(); } @@ -102,17 +113,65 @@ public function handleResult($post_data, WC_Order $order) //empty cart wc()->cart->empty_cart(); - //show thank you page +//show thank you page echo $order->get_checkout_order_received_url(); } } - /* - * handle push post + /** + * Add payment information to the order if available. + * Information usually are set for invoice, direct debit and prepayment. + * @param WC_Order $order + * @return null */ + public function setPaymentInfo(WC_Order $order) + { + // Load template text for Payment information + $payInfoTemplate = $this->getInfoTemplate(); + if ($payInfoTemplate === null) { + return null; + } + + $response = self::$response; + $payInfo = $response->getConnector(); + $presentation = $response->getPresentation(); + + $paymentData = array( + '{AMOUNT}' => $presentation->getAmount(), + '{CURRENCY}' => $presentation->getCurrency(), + '{CONNECTOR_ACCOUNT_HOLDER}' => $payInfo->getAccountHolder(), + '{CONNECTOR_ACCOUNT_IBAN}' => $payInfo->getAccountIBan(), + '{CONNECTOR_ACCOUNT_BIC}' => $payInfo->getAccountBic(), + '{IDENTIFICATION_SHORTID}' => self::$response->getIdentification()->getShortId(), + '{Iban}' => $response->getAccount()->getIban(), + '{Ident}' => $response->getAccount()->getIdentification(), + '{CreditorId}' => $response->getIdentification()->getCreditorId(), + ); + + $paymentText = strtr($payInfoTemplate, $paymentData); + + $order->add_meta_data('heidelpay-paymentInfo', $paymentText); + } - public function handlePush() + /** + * Provide the template text for payment information. + * @return null|string + */ + public function getInfoTemplate() { - //TODO + $payCode = explode('.', self::$response->getPayment()->getCode()); + switch (strtoupper($payCode[0])) { + case 'IV': + return __('invoice_info', 'woocommerce-heidelpay'); + break; + case 'PP': + return __('prepayment_info', 'woocommerce-heidelpay'); + break; + case 'DD': + return __('direct_debit_info', 'woocommerce-heidelpay'); + break; + default: + return null; + } } -} \ No newline at end of file +} diff --git a/includes/gateways/class-wc-heidelpay-gateway-dd.php b/includes/gateways/class-wc-heidelpay-gateway-dd.php index 1852199..2085d9e 100644 --- a/includes/gateways/class-wc-heidelpay-gateway-dd.php +++ b/includes/gateways/class-wc-heidelpay-gateway-dd.php @@ -30,11 +30,6 @@ class WC_Gateway_HP_DD extends WC_Heidelpay_Payment_Gateway /** @var array Array of locales */ public $locale; - - - - - public function checkoutValidation() { // If gateway is not active no validation is necessary. @@ -71,6 +66,16 @@ public function init_form_fields() $this->form_fields['user_login']['default'] = '31ha07bc8142c5a171744e5aef11ffd3'; $this->form_fields['user_password']['default'] = '93167DE7'; $this->form_fields['transaction_channel']['default'] = '31HA07BC8142C5A171744F3D6D155865'; + $this->form_fields['send_payment_info'] = array( + 'title' => __('Payment information mail', 'woocommerce-heidelpay'), + 'type' => 'checkbox', + 'description' => __( + 'Add payment information to e-mail', + 'woocommerce-heidelpay' + ), + 'default' => 'yes', + 'desc_tip' => true, + ); } public function payment_fields() diff --git a/includes/gateways/class-wc-heidelpay-gateway-idl.php b/includes/gateways/class-wc-heidelpay-gateway-idl.php index d5e2898..b7909eb 100644 --- a/includes/gateways/class-wc-heidelpay-gateway-idl.php +++ b/includes/gateways/class-wc-heidelpay-gateway-idl.php @@ -78,10 +78,10 @@ public function payment_fields() $accountHolder = wc()->customer->get_billing_first_name(). ' ' . wc()->customer->get_last_name(); - if(!empty($brands)) { + if (!empty($brands)) { echo '