diff --git a/inc/functions.php b/inc/functions.php index 2539327..90e1ed7 100755 --- a/inc/functions.php +++ b/inc/functions.php @@ -7,6 +7,9 @@ * @since 0.18.01 */ +use Osen\Woocommerce\Mpesa\STK; +use Osen\Woocommerce\Mpesa\C2B; + function wc_mpesa_post_id_by_meta_key_and_value($key, $value) { global $wpdb; @@ -33,7 +36,7 @@ function wc_mpesa_process_order($order) add_action('woocommerce_thankyou_mpesa', function ($order_id) { $mpesa = get_option('woocommerce_mpesa_settings'); - $idtype = Osen\Woocommerce\Mpesa\C2B::$type; + $idtype = C2B::$type; $url = home_url('?pesaipn&order='); if (wc_get_order($order_id)) { @@ -88,6 +91,18 @@ function wc_mpesa_process_order($order)

Confirming receipt, please wait

+ + + + + + +
+
" method="POST" id="renitiate-form"> + + +
+
@@ -121,14 +136,6 @@ function wc_mpesa_process_order($order) - - -
" mhod="POST" id="renitiate-form"> - - -
- - @@ -234,13 +241,13 @@ function wc_mpesa_process_ipn() $first_name = $order->get_billing_first_name(); $last_name = $order->get_billing_last_name(); - $result = Osen\Woocommerce\Mpesa\STK::request($phone, $total, $order_id, get_bloginfo('name') . ' Purchase', 'WCMPesa'); + $result = STK::request($phone, $total, $order_id, get_bloginfo('name') . ' Purchase', 'WCMPesa'); wp_send_json($result); break; case "validate": exit(wp_send_json( - Osen\Woocommerce\Mpesa\STK::validate() + STK::validate() )); break; @@ -309,7 +316,7 @@ function wc_mpesa_process_ipn() update_post_meta($post, '_order_status', 'complete'); $headers = 'From: ' . get_bloginfo('name') . ' <' . get_bloginfo('admin_email') . '>' . "\r\n"; - wp_mail($order["billing_address"], 'Your Mpesa payment', 'We acknowledge receipt of your payment via MPesa of KSh. ' . $amount . ' on ' . $transactionDate . 'with receipt Number ' . $mpesaReceiptNumber . '.', $headers); + wp_mail($order->get_billing_email(), 'Your Mpesa payment', 'We acknowledge receipt of your payment via MPesa of KSh. ' . $amount . ' on ' . $transactionDate . 'with receipt Number ' . $mpesaReceiptNumber . '.', $headers); } elseif ($ipn_balance < 0) { $currency = get_woocommerce_currency(); $order->update_status((isset($mpesa['completion']) ? $mpesa['completion'] : 'completed'), __("{$phone} has overpayed by {$currency} {$ipn_balance}. Receipt Number {$mpesaReceiptNumber}")); @@ -329,11 +336,11 @@ function wc_mpesa_process_ipn() update_post_meta($post, '_order_id', $order_id); update_post_meta($post, '_receipt', $mpesaReceiptNumber); - exit(wp_send_json(Osen\Woocommerce\Mpesa\STK::confirm())); + exit(wp_send_json(STK::confirm())); break; case "register": - Osen\Woocommerce\Mpesa\C2B::register(function ($response) { + C2B::register(function ($response) { $status = isset($response['ResponseDescription']) ? 'success' : 'fail'; if ($status == 'fail') { $message = isset($response['errorMessage']) ? $response['errorMessage'] : 'Could not register M-PESA URLs, try again later.'; @@ -396,7 +403,7 @@ function wc_mpesa_process_ipn() $order->update_status((isset($mpesa['completion']) ? $mpesa['completion'] : 'completed'), __("Full MPesa Payment Received From {$phone}. Receipt Number {$mpesaReceiptNumber}")); $headers[] = 'From: ' . get_bloginfo('name') . ' <' . get_bloginfo('admin_email') . '>' . "\r\n"; - wp_mail($order["billing_address"], 'Your Mpesa payment', 'We acknowledge receipt of your payment via MPesa of KSh. ' . $amount . ' on ' . $transactionDate . '. Receipt number ' . $mpesaReceiptNumber, $headers); + wp_mail($order->get_billing_email(), 'Your Mpesa payment', 'We acknowledge receipt of your payment via MPesa of KSh. ' . $amount . ' on ' . $transactionDate . '. Receipt number ' . $mpesaReceiptNumber, $headers); } elseif ($ipn_balance < 0) { $currency = get_woocommerce_currency(); $order->update_status((isset($mpesa['completion']) ? $mpesa['completion'] : 'completed'), __("{$phone} has overpayed by {$currency} {$ipn_balance}. Receipt Number {$mpesaReceiptNumber}")); @@ -420,9 +427,9 @@ function wc_mpesa_process_ipn() $order->add_order_note(__("MPesa Error {$resultCode}: {$resultDesc}")); } - exit(wp_send_json(Osen\Woocommerce\Mpesa\STK::reconcile())); + exit(wp_send_json(STK::reconcile())); } else { - exit(wp_send_json(Osen\Woocommerce\Mpesa\STK::reconcile(function () { + exit(wp_send_json(STK::reconcile(function () { return false; }))); } @@ -430,7 +437,7 @@ function wc_mpesa_process_ipn() case "status": $transaction = $_POST['transaction']; - exit(wp_send_json(Osen\Woocommerce\Mpesa\STK::status($transaction))); + exit(wp_send_json(STK::status($transaction))); break; case "result": @@ -466,7 +473,7 @@ function wc_mpesa_process_ipn() $ReferenceData = $result['ReferenceData']; $ReferenceItem = $ReferenceData['ReferenceItem']; $Occasion = $ReferenceItem[0]['Value']; - exit(wp_send_json(Osen\Woocommerce\Mpesa\STK::validate())); + exit(wp_send_json(STK::validate())); break; case "timeout": @@ -493,10 +500,10 @@ function wc_mpesa_process_ipn() $order->add_order_note(__("MPesa Payment Timed Out", 'woocommerce')); } - exit(wp_send_json(Osen\Woocommerce\Mpesa\STK::timeout())); + exit(wp_send_json(STK::timeout())); break; default: - exit(wp_send_json(Osen\Woocommerce\Mpesa\C2B::register())); + exit(wp_send_json(C2B::register())); } } diff --git a/inc/wc_mpesa_gateway.php b/inc/wc_mpesa_gateway.php index 77c9dd2..8089862 100755 --- a/inc/wc_mpesa_gateway.php +++ b/inc/wc_mpesa_gateway.php @@ -2,7 +2,7 @@ /** * @package MPesa For WooCommerce - * @subpackage WooCommerce Functions + * @subpackage WooCommerce Mpesa Gateway * @author Osen Concepts < hi@osen.co.ke > * @since 0.18.01 */ @@ -47,26 +47,26 @@ class WC_MPESA_Gateway extends WC_Payment_Gateway * Constructor for the gateway. */ public function __construct() - { + { $this->id = 'mpesa'; $this->icon = apply_filters('woocommerce_mpesa_icon', plugins_url('mpesa.png', __FILE__)); - $this->method_title = __('Lipa Na MPesa', 'woocommerce'); - + $this->method_title = __('Lipa Na MPesa', 'woocommerce'); + // Load settings $this->init_form_fields(); - $this->init_settings(); - + $this->init_settings(); + $env = $this->get_option('env', 'sandbox'); $b2c_settings = ($this->get_option('enable_b2c', 'no') == 'yes') - ? 'These settings are for Customer-2-Business payments. Click here to Setup Business-2-Customer.' - : ''; + ? 'These settings are for Customer-2-Business payments. Click here to Setup Business-2-Customer.' + : ''; $test_cred = ($env == 'sandbox') - ? '
  • You can get sandbox test credentials here.
  • ' - : ''; + ? '
  • You can get sandbox test credentials here.
  • ' + : ''; $color = isset($_GET['reg-state']) ? $_GET['reg-state'] : 'black'; $register = isset($_GET['mpesa-urls-registered']) ? "
    {$_GET['mpesa-urls-registered']}
    " : ''; - - $this->method_description = $register . (($env == 'live') ? __('Receive payments via Safaricom M-PESA', 'woocommerce') : __('

    IMPORTANT!

    ' . $b2c_settings . '
  • Please create an app on Daraja if you haven\'t. If yoou already have a production app, fill in the app\'s consumer key and secret below.
  • Ensure you have access to the MPesa Web Portal. You\'ll need this for when you go LIVE.
  • For security purposes, and for the MPesa Instant Payment Notification to work, ensure your site is running over https(SSL).
  • ' . $test_cred) . '
  • We have a nice tutorial here on migrating from Sandbox(test) environment, to Production(live) environment.
    We offer the service at a fiat fee of KSh 4000. Call +254204404993 or email hi@osen.co.ke if you need help.
  • '); + + $this->method_description = $register . (($env == 'live') ? __('Receive payments via Safaricom M-PESA', 'woocommerce') : __('

    IMPORTANT!

    ' . $b2c_settings . '
  • Please create an app on Daraja if you haven\'t. If yoou already have a production app, fill in the app\'s consumer key and secret below.
  • Ensure you have access to the MPesa Web Portal. You\'ll need this for when you go LIVE.
  • For security purposes, and for the MPesa Instant Payment Notification to work, ensure your site is running over https(SSL).
  • ' . $test_cred) . '
  • We have a nice tutorial here on migrating from Sandbox(test) environment, to Production(live) environment.
    We offer the service at a fiat fee of KSh 4000. Call +254204404993 or email hi@osen.co.ke if you need help.
  • '); $this->has_fields = false; // Get settings @@ -75,7 +75,7 @@ public function __construct() $this->instructions = $this->get_option('instructions'); $this->enable_for_methods = $this->get_option('enable_for_methods', array()); $this->enable_for_virtual = $this->get_option('enable_for_virtual', 'yes') === 'yes' ? true : false; - $this->debug = $this->get_option('debug', 'no') === 'yes' ? true : false; + $this->debug = $this->get_option('debug', 'no') === 'yes' ? true : false; add_action('woocommerce_thankyou_' . $this->id, array($this, 'thankyou_page')); @@ -248,7 +248,7 @@ public function init_form_fields() 'title' => __('Manual Payments', 'woocommerce'), 'label' => __('Enable C2B API(Offline Payments)', 'woocommerce'), 'type' => 'checkbox', - 'description' => '' . (($this->get_option('idtype', 4) == 4) ? 'This requires C2B Validation, which is an optional feature that needs to be activated on M-Pesa.
    Request for activation by sending an email to apisupport@safaricom.co.ke, or through a chat on the developer portal.
    ' : '') . 'Once enabled, click here to register confirmation & validation URLs

    Kindly note that if this is disabled, the user can still resend an STK push if the first one fails.

    ', + 'description' => 'This requires C2B Validation, which is an optional feature that needs to be activated on M-Pesa.
    Request for activation by sending an email to apisupport@safaricom.co.ke, or through a chat on the developer portal.

    Once enabled, click here to register confirmation & validation URLs
    Kindly note that if this is disabled, the user can still resend an STK push if the first one fails.
    ', 'default' => 'no', ), // 'enable_b2c' => array( @@ -260,10 +260,10 @@ public function init_form_fields() // ), 'debug' => array( 'title' => __('Debug Mode', 'woocommerce'), - 'label' => __('Check to enable debug mode and show request body', 'woocommerce').$this->get_option('debug'), + 'label' => __('Check to enable debug mode and show request body', 'woocommerce'), 'type' => 'checkbox', 'default' => 'no', - 'description' => '' .__('Show Request Body(to send to Daraja on request)', 'woocommerce').'' + 'description' => '' . __('Show Request Body(to send to Daraja team on request)', 'woocommerce') . '' ) ); } @@ -335,17 +335,18 @@ public function process_payment($order_id) $total = $order->get_total(); $phone = $order->get_billing_phone(); $first_name = $order->get_billing_first_name(); - $last_name = $order->get_billing_last_name(); - - $c2b = get_option('woocommerce_mpesa_settings'); + $last_name = $order->get_billing_last_name(); + + $c2b = get_option('woocommerce_mpesa_settings'); if (($c2b['debug'] ?? 'no') == 'yes') { $result = STK::request($phone, $total, $order_id, get_bloginfo('name') . ' Purchase', 'WCMPesa', true); - WC()->session->set('mpesa_request', json_encode($result['requested'])); + $message = json_encode($result['requested']); + WC()->session->set('mpesa_request', $message); } else { $result = STK::request($phone, $total, $order_id, get_bloginfo('name') . ' Purchase', 'WCMPesa'); - } - + } + if ($result) { $request_id = $result['MerchantRequestID']; diff --git a/inc/woocommerce.php b/inc/woocommerce.php index 5411eaa..2030141 100755 --- a/inc/woocommerce.php +++ b/inc/woocommerce.php @@ -16,7 +16,7 @@ function wcmpesa_new_order_column($columns) /** * Render custom column content within edit.php table on event post types. - * + * * @access public * @param string $column The name of the column being acted upon * @return void @@ -30,11 +30,11 @@ function shop_order_payments_table_column_content($column_id, $post_id) case 'mpesa': $statuses = array( "processing" => "This Order Is Processing", - "on-hold" => "This Order Is On Hold", - "complete" => "This Order Is Complete", - "cancelled" => "This Order Is Cancelled", - "refunded" => "This Order Is Refunded", - "failed" => "This Order Failed" + "on-hold" => "This Order Is On Hold", + "complete" => "This Order Is Complete", + "cancelled" => "This Order Is Cancelled", + "refunded" => "This Order Is Refunded", + "failed" => "This Order Failed", ); echo ($value = get_post_meta($post_id, '_order_status', true)) ? '' . esc_attr($statuses[$value]) . '') : 'Set Status'; @@ -78,7 +78,7 @@ function woocommerce_emails_attach_downloadables($attachments, $status, $order) echo '

    Mpesa request body

    - '.WC()->session->get('mpesa_request').' + ' . WC()->session->get('mpesa_request') . '
    '; } -}); \ No newline at end of file +}); diff --git a/osen-wc-mpesa.php b/osen-wc-mpesa.php index 85b1879..acb2ec5 100755 --- a/osen-wc-mpesa.php +++ b/osen-wc-mpesa.php @@ -1,27 +1,27 @@ - * @version 1.20.79 + * @version 1.20.99 * - * Plugin Name: MPesa For WooCommerce + * Plugin Name: MPesa for WooCommerce * Plugin URI: https://wc-mpesa.osen.co.ke/ * Description: This plugin extends WordPress and WooCommerce functionality to integrate Mpesa for making and receiving online payments. * Author: Osen Concepts Kenya < hi@osen.co.ke > - * Version: 1.20.79 + * Version: 1.20.99 * Author URI: https://osen.co.ke/ * * Requires at least: 4.6 - * Tested up to: 5.4 - * + * Tested up to: 5.5 + * * WC requires at least: 3.5.0 - * WC tested up to: 4.3 - * + * WC tested up to: 4.4 + * * License: GPLv3 * License URI: http://www.gnu.org/licenses/gpl-3.0.html - * Copyright 2020 Osen Concepts + * Copyright 2020 Osen Concepts * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License, version 3, as @@ -39,12 +39,12 @@ // Exit if accessed directly. if (!defined('ABSPATH')) { - exit; + exit; } -define('WCM_VER', '1.20.7'); +define('WCM_VER', '1.20.99'); if (!defined('WCM_PLUGIN_FILE')) { - define('WCM_PLUGIN_FILE', __FILE__); + define('WCM_PLUGIN_FILE', __FILE__); } require_once plugin_dir_path(__FILE__) . 'vendor/autoload.php'; @@ -52,75 +52,75 @@ register_activation_hook(__FILE__, 'wc_mpesa_activation_check'); function wc_mpesa_activation_check() { - if (!get_option('wc_mpesa_flush_rewrite_rules_flag')) { - add_option('wc_mpesa_flush_rewrite_rules_flag', true); - } + if (!get_option('wc_mpesa_flush_rewrite_rules_flag')) { + add_option('wc_mpesa_flush_rewrite_rules_flag', true); + } - if (!is_plugin_active('woocommerce/woocommerce.php')) { - deactivate_plugins(plugin_basename(__FILE__)); + if (!is_plugin_active('woocommerce/woocommerce.php')) { + deactivate_plugins(plugin_basename(__FILE__)); - add_action('admin_notices', function () { - $class = 'notice notice-error is-dismissible'; - $message = __('Please Install/Activate WooCommerce for this extension to work..', 'woocommerce'); + add_action('admin_notices', function () { + $class = 'notice notice-error is-dismissible'; + $message = __('Please Install/Activate WooCommerce for this extension to work..', 'woocommerce'); - printf('

    %2$s

    ', esc_attr($class), esc_html($message)); - }); - } + printf('

    %2$s

    ', esc_attr($class), esc_html($message)); + }); + } } add_action('init', 'wc_mpesa_flush_rewrite_rules_maybe', 20); function wc_mpesa_flush_rewrite_rules_maybe() { - if (get_option('wc_mpesa_flush_rewrite_rules_flag')) { - flush_rewrite_rules(); - delete_option('wc_mpesa_flush_rewrite_rules_flag'); - } + if (get_option('wc_mpesa_flush_rewrite_rules_flag')) { + flush_rewrite_rules(); + delete_option('wc_mpesa_flush_rewrite_rules_flag'); + } } add_action('activated_plugin', 'wc_mpesa_detect_plugin_activation', 10, 2); function wc_mpesa_detect_plugin_activation($plugin, $network_activation) { - flush_rewrite_rules(); - if ($plugin == 'osen-wc-mpesa/osen-wc-mpesa.php') { - exit(wp_redirect(admin_url('admin.php?page=wc-settings&tab=checkout§ion=mpesa'))); - } + flush_rewrite_rules(); + if ($plugin == 'osen-wc-mpesa/osen-wc-mpesa.php') { + exit(wp_redirect(admin_url('admin.php?page=wc-settings&tab=checkout§ion=mpesa'))); + } } add_action('deactivated_plugin', 'wc_mpesa_detect_woocommerce_deactivation', 10, 2); function wc_mpesa_detect_woocommerce_deactivation($plugin, $network_activation) { - if ($plugin == 'woocommerce/woocommerce.php') { - deactivate_plugins(plugin_basename(__FILE__)); - } + if ($plugin == 'woocommerce/woocommerce.php') { + deactivate_plugins(plugin_basename(__FILE__)); + } } add_filter('plugin_action_links_' . plugin_basename(__FILE__), 'mpesa_action_links'); function mpesa_action_links($links) { - return array_merge( - $links, - array( - ' STK & C2B Setup', - // ' B2C' - ) - ); + return array_merge( + $links, + array( + ' STK & C2B Setup', + // ' B2C' + ) + ); } add_filter('plugin_row_meta', 'mpesa_row_meta', 10, 2); function mpesa_row_meta($links, $file) { - $plugin = plugin_basename(__FILE__); + $plugin = plugin_basename(__FILE__); - if ($plugin == $file) { - $row_meta = array( - 'github' => '' . esc_html__('Github', 'woocommerce') . '', - 'apidocs' => '' . esc_html__('API docs', 'woocommerce') . '' - ); + if ($plugin == $file) { + $row_meta = array( + 'github' => '' . esc_html__('Github', 'woocommerce') . '', + 'apidocs' => '' . esc_html__('API docs', 'woocommerce') . '', + ); - return array_merge($links, $row_meta); - } + return array_merge($links, $row_meta); + } - return (array) $links; + return (array) $links; } /** @@ -148,63 +148,63 @@ function mpesa_row_meta($links, $file) // Stk $c2b = get_option('woocommerce_mpesa_settings'); Osen\Woocommerce\Mpesa\STK::set( - array( - 'env' => isset($c2b['env']) ? $c2b['env'] : 'sandbox', - 'appkey' => isset($c2b['key']) ? $c2b['key'] : 'bclwIPkcRqw61yUt', - 'appsecret' => isset($c2b['secret']) ? $c2b['secret'] : '9v38Dtu5u2BpsITPmLcXNWGMsjZRWSTG', - 'headoffice' => isset($c2b['headoffice']) ? $c2b['headoffice'] : '174379', - 'shortcode' => isset($c2b['shortcode']) ? $c2b['shortcode'] : '174379', - 'type' => isset($c2b['idtype']) ? $c2b['idtype'] : 4, - 'passkey' => isset($c2b['passkey']) ? $c2b['passkey'] : 'bfb279f9aa9bdbcf158e97dd71a467cd2e0c893059b10f78e6b72ada1ed2c919', - 'validate' => home_url('lipwa/validate/'), - 'confirm' => home_url('lipwa/confirm/'), - 'reconcile' => home_url('lipwa/reconcile/'), - 'timeout' => home_url('lipwa/timeout/') - ) + array( + 'env' => isset($c2b['env']) ? $c2b['env'] : 'sandbox', + 'appkey' => isset($c2b['key']) ? $c2b['key'] : 'bclwIPkcRqw61yUt', + 'appsecret' => isset($c2b['secret']) ? $c2b['secret'] : '9v38Dtu5u2BpsITPmLcXNWGMsjZRWSTG', + 'headoffice' => isset($c2b['headoffice']) ? $c2b['headoffice'] : '174379', + 'shortcode' => isset($c2b['shortcode']) ? $c2b['shortcode'] : '174379', + 'type' => isset($c2b['idtype']) ? $c2b['idtype'] : 4, + 'passkey' => isset($c2b['passkey']) ? $c2b['passkey'] : 'bfb279f9aa9bdbcf158e97dd71a467cd2e0c893059b10f78e6b72ada1ed2c919', + 'validate' => home_url('lipwa/validate/'), + 'confirm' => home_url('lipwa/confirm/'), + 'reconcile' => home_url('lipwa/reconcile/'), + 'timeout' => home_url('lipwa/timeout/'), + ) ); // c2b Osen\Woocommerce\Mpesa\C2B::set( - array( - 'env' => isset($c2b['env']) ? $c2b['env'] : 'sandbox', - 'appkey' => isset($c2b['key']) ? $c2b['key'] : '9v38Dtu5u2BpsITPmLcXNWGMsjZRWSTG', - 'appsecret' => isset($c2b['secret']) ? $c2b['secret'] : '9v38Dtu5u2BpsITPmLcXNWGMsjZRWSTG', - 'headoffice' => isset($c2b['headoffice']) ? $c2b['headoffice'] : '174379', - 'shortcode' => isset($c2b['shortcode']) ? $c2b['shortcode'] : '174379', - 'type' => isset($c2b['idtype']) ? $c2b['idtype'] : 4, - 'passkey' => isset($c2b['passkey']) ? $c2b['passkey'] : 'bfb279f9aa9bdbcf158e97dd71a467cd2e0c893059b10f78e6b72ada1ed2c919', - 'validate' => home_url('lipwa/validate/'), - 'confirm' => home_url('lipwa/confirm/'), - 'reconcile' => home_url('lipwa/reconcile/'), - 'timeout' => home_url('lipwa/timeout/') - ) + array( + 'env' => isset($c2b['env']) ? $c2b['env'] : 'sandbox', + 'appkey' => isset($c2b['key']) ? $c2b['key'] : '9v38Dtu5u2BpsITPmLcXNWGMsjZRWSTG', + 'appsecret' => isset($c2b['secret']) ? $c2b['secret'] : '9v38Dtu5u2BpsITPmLcXNWGMsjZRWSTG', + 'headoffice' => isset($c2b['headoffice']) ? $c2b['headoffice'] : '174379', + 'shortcode' => isset($c2b['shortcode']) ? $c2b['shortcode'] : '174379', + 'type' => isset($c2b['idtype']) ? $c2b['idtype'] : 4, + 'passkey' => isset($c2b['passkey']) ? $c2b['passkey'] : 'bfb279f9aa9bdbcf158e97dd71a467cd2e0c893059b10f78e6b72ada1ed2c919', + 'validate' => home_url('lipwa/validate/'), + 'confirm' => home_url('lipwa/confirm/'), + 'reconcile' => home_url('lipwa/reconcile/'), + 'timeout' => home_url('lipwa/timeout/'), + ) ); //b2c // $b2c = get_option('b2c_wcmpesa_options'); // Osen\Woocommerce\Mpesa\B2C::set( -// array( -// 'env' => isset($b2c['env']) ? $b2c['env'] : 'sandbox', -// 'appkey' => isset($b2c['key']) ? $b2c['key'] : '', -// 'appsecret' => isset($b2c['secret']) ? $b2c['secret'] : '', -// 'headoffice' => isset($b2c['headoffice']) ? $b2c['headoffice'] : '', -// 'shortcode' => isset($b2c['shortcode']) ? $b2c['shortcode'] : '', -// 'type' => isset($b2c['idtype']) ? $b2c['idtype'] : 4, -// 'passkey' => isset($b2c['passkey']) ? $b2c['passkey'] : '', -// 'username' => isset($b2c['username']) ? $b2c['username'] : '', -// 'password' => isset($b2c['password']) ? $b2c['password'] : '', -// 'validate' => home_url('lipwa/validate/'), -// 'confirm' => home_url('lipwa/confirm/'), -// 'reconcile' => home_url('lipwa/reconcile/'), -// 'timeout' => home_url('lipwa/timeout/') -// ) +// array( +// 'env' => isset($b2c['env']) ? $b2c['env'] : 'sandbox', +// 'appkey' => isset($b2c['key']) ? $b2c['key'] : '', +// 'appsecret' => isset($b2c['secret']) ? $b2c['secret'] : '', +// 'headoffice' => isset($b2c['headoffice']) ? $b2c['headoffice'] : '', +// 'shortcode' => isset($b2c['shortcode']) ? $b2c['shortcode'] : '', +// 'type' => isset($b2c['idtype']) ? $b2c['idtype'] : 4, +// 'passkey' => isset($b2c['passkey']) ? $b2c['passkey'] : '', +// 'username' => isset($b2c['username']) ? $b2c['username'] : '', +// 'password' => isset($b2c['password']) ? $b2c['password'] : '', +// 'validate' => home_url('lipwa/validate/'), +// 'confirm' => home_url('lipwa/confirm/'), +// 'reconcile' => home_url('lipwa/reconcile/'), +// 'timeout' => home_url('lipwa/timeout/') +// ) // ); /** * Load Custom Plugin Functions */ foreach (glob(plugin_dir_path(__FILE__) . 'inc/*.php') as $filename) { - require_once $filename; + require_once $filename; } /** @@ -212,7 +212,7 @@ function mpesa_row_meta($links, $file) */ require __DIR__ . '/updates/plugin-update-checker.php'; $myUpdateChecker = Puc_v4_Factory::buildUpdateChecker( - 'https://raw.githubusercontent.com/osenco/osen-wc-mpesa/master/updates.json', - __FILE__, - 'wc-mpesa' + 'https://raw.githubusercontent.com/osenco/osen-wc-mpesa/master/updates.json', + __FILE__, + 'wc-mpesa' ); diff --git a/src/Mpesa/STK.php b/src/Mpesa/STK.php index de2b800..92c3d72 100755 --- a/src/Mpesa/STK.php +++ b/src/Mpesa/STK.php @@ -85,10 +85,6 @@ class STK */ public static $credentials; - public function __construct() - { - } - /** * @param array $config - Key-value pairs of settings */ @@ -242,11 +238,7 @@ public static function request($phone, $amount, $reference, $trxdesc = 'WooComme */ public static function reconcile($callback = null, $data = null) { - if (is_null($data)) { - $response = json_decode(file_get_contents('php://input'), true); - } else { - $response = $data; - } + $response = is_null($data) ? json_decode(file_get_contents('php://input'), true) : $data; return is_null($callback) ? array('resultCode' => 0, 'resultDesc' => 'Reconciliation successful') diff --git a/src/Post/Metaboxes/C2B.php b/src/Post/Metaboxes/C2B.php index 8c7dbe2..92c44ae 100755 --- a/src/Post/Metaboxes/C2B.php +++ b/src/Post/Metaboxes/C2B.php @@ -21,7 +21,7 @@ public static function mpesa_mb_sm() add_meta_box('c2b-payment-customer_details', 'Customer Details', [new self, 'customer_details'], ['mpesaipn', 'b2c_payment'], 'normal', 'high'); add_meta_box('c2b-payment-order_details', 'Order Details', [new self, 'order_details'], ['mpesaipn', 'b2c_payment'], 'normal', 'high'); add_meta_box('c2b-payment-payment_details', 'Payment Details', [new self, 'payment_details'], ['mpesaipn', 'b2c_payment'], 'side', 'high'); - //add_meta_box('c2b-payment-payment_status', 'Incase MPesa timed out', [new self, 'mpesa_status'], [ 'mpesaipn', 'shop_order' ], 'side', 'low'); + add_meta_box('c2b-payment-payment_status', 'Incase MPesa timed out', [new self, 'mpesa_status'], ['mpesaipn', 'shop_order'], 'side', 'low'); add_meta_box('woocommerce-order-notes', 'Payment Order Notes', [new self, 'order_notes'], 'mpesaipn', 'normal', 'default'); add_meta_box('c2b-payment-payment_create', 'Paid For Via MPesa?', [new self, 'mpesa_payment'], 'shop_order', 'side', 'low'); } @@ -44,16 +44,18 @@ public static function mpesa_payment($post) public static function mpesa_status($post) { - $status = ($value = get_post_meta($post->ID, '_order_status', true)) ? $value : 'complete'; + $id = wc_mpesa_post_id_by_meta_key_and_value('_order_id', $post->ID); + $post = get_post($id); + $status = ($value = get_post_meta($post->ID, '_order_status', true)) ? $value : 'complete'; $request = ($value = get_post_meta($post->ID, '_request', true)) ? $value : 0; $statuses = array( - "processing" => "This Order Is Processing", - "on-hold" => "This Order Is On Hold", - "complete" => "This Order Is Complete", - "cancelled" => "This Order Is Cancelled", - "refunded" => "This Order Is Refunded", - "failed" => "This Order Failed" + "processing" => "This Order Is Processing", + "on-hold" => "This Order Is On Hold", + "complete" => "This Order Is Complete", + "cancelled" => "This Order Is Cancelled", + "refunded" => "This Order Is Refunded", + "failed" => "This Order Failed", ); echo ' @@ -64,7 +66,8 @@ public static function mpesa_status($post)
    - + ' . (($status == 'complete') + ? ' + ' + : ' + '). '
    '; @@ -82,15 +96,15 @@ public static function mpesa_status($post) public static function customer_details($post) { - $customer = get_post_meta($post->ID, '_customer', true); - $phone = get_post_meta($post->ID, '_phone', true); + $customer = get_post_meta($post->ID, '_customer', true); + $phone = get_post_meta($post->ID, '_phone', true); if (isset($_GET['order'])) { - $order = new \WC_Order($_GET['order']); - $total = wc_format_decimal($order->get_total(), 2); - $phone = $order->get_billing_phone(); + $order = new \WC_Order($_GET['order']); + $total = wc_format_decimal($order->get_total(), 2); + $phone = $order->get_billing_phone(); $first_name = $order->get_billing_first_name(); - $last_name = $order->get_billing_last_name(); - $customer = "{$first_name} {$last_name}"; + $last_name = $order->get_billing_last_name(); + $customer = "{$first_name} {$last_name}"; } // Remove the plus sign before the customer's phone number @@ -117,19 +131,19 @@ public static function customer_details($post) public static function order_details($post) { - $order = ($value = get_post_meta($post->ID, '_order_id', true)) ? $value : $post->ID; - $order = isset($_GET['order']) ? $_GET['order'] : $order; - $amount = get_post_meta($post->ID, '_amount', true); - $paid = get_post_meta($post->ID, '_paid', true); - $balance = get_post_meta($post->ID, '_balance', true); + $order = ($value = get_post_meta($post->ID, '_order_id', true)) ? $value : $post->ID; + $order = isset($_GET['order']) ? $_GET['order'] : $order; + $amount = get_post_meta($post->ID, '_amount', true); + $paid = get_post_meta($post->ID, '_paid', true); + $balance = get_post_meta($post->ID, '_balance', true); if (isset($_GET['order'])) { - $order_details = new \WC_Order($_GET['order']); - $amount = wc_format_decimal($order_details->get_total(), 2); - $phone = $order_details->get_billing_phone(); - $first_name = $order_details->get_billing_first_name(); - $last_name = $order_details->get_billing_last_name(); - $customer = "{$first_name} {$last_name}"; + $order_details = new \WC_Order($_GET['order']); + $amount = wc_format_decimal($order_details->get_total(), 2); + $phone = $order_details->get_billing_phone(); + $first_name = $order_details->get_billing_first_name(); + $last_name = $order_details->get_billing_last_name(); + $customer = "{$first_name} {$last_name}"; } $new = wc_get_order($order) ? '' : ' Add New Manual Order'; @@ -162,17 +176,17 @@ public static function order_notes($post) public static function payment_details($post) { - $status = ($value = get_post_meta($post->ID, '_order_status', true)) ? $value : 'complete'; - $request = get_post_meta($post->ID, '_request_id', true); - $receipt = get_post_meta($post->ID, '_receipt', true); - - $statuses = array( - "processing" => "This Order Is Processing", - "on-hold" => "This Order Is On Hold", - "complete" => "This Order Is Complete", - "cancelled" => "This Order Is Cancelled", - "refunded" => "This Order Is Refunded", - "failed" => "This Order Failed" + $status = ($value = get_post_meta($post->ID, '_order_status', true)) ? $value : 'complete'; + $request = get_post_meta($post->ID, '_request_id', true); + $receipt = get_post_meta($post->ID, '_receipt', true); + + $statuses = array( + "processing" => "This Order Is Processing", + "on-hold" => "This Order Is On Hold", + "complete" => "This Order Is Complete", + "cancelled" => "This Order Is Cancelled", + "refunded" => "This Order Is Refunded", + "failed" => "This Order Failed", ); ?>

    Add here the MPesa confirmation code received and set the appropriate order status for Request ID: .

    MPesa Receipt Number

    '; ?> @@ -191,16 +205,14 @@ public static function payment_details($post) public static function mpesaipn_save_meta($post_id) { if (isset($_POST['save_meta'])) { - $customer = trim($_POST['customer']); - $phone = trim($_POST['phone']); - $order_id = trim($_POST['order_id']); - $order_status = trim($_POST['status']); - $order_note = trim($_POST['order_note']); - - $amount = trim($_POST['amount']); - $paid = trim($_POST['paid']); - - $receipt = trim($_POST['receipt']); + $customer = trim($_POST['customer']); + $phone = trim($_POST['phone']); + $order_id = trim($_POST['order_id']); + $order_status = trim($_POST['status']); + $order_note = trim($_POST['order_note']); + $amount = trim($_POST['amount']); + $paid = trim($_POST['paid']); + $receipt = trim($_POST['receipt']); update_post_meta($post_id, '_customer', strip_tags($customer)); update_post_meta($post_id, '_phone', strip_tags($phone)); diff --git a/src/Settings/B2C.php b/src/Settings/B2C.php index 4b68b86..29ff7cf 100755 --- a/src/Settings/B2C.php +++ b/src/Settings/B2C.php @@ -1,5 +1,6 @@ 'env', - 'class' => 'b2c_row', + 'label_for' => 'env', + 'class' => 'b2c_row', 'b2c_custom_data' => 'custom', ] ); - + add_settings_field( 'shortcode', __('Mpesa Shortcode', 'woocommerce'), - [new self, 'b2c_fields_b2c_mpesa_shortcode_cb'], + [ + new self, 'b2c_fields_b2c_mpesa_shortcode_cb'], 'wcmpesab2c', 'b2c_section_mpesa', [ - 'label_for' => 'shortcode', - 'class' => 'b2c_row', + 'label_for' => 'shortcode', + 'class' => 'b2c_row', 'b2c_custom_data' => 'custom', ] ); - + add_settings_field( 'username', __('Mpesa Username', 'woocommerce'), @@ -54,12 +57,12 @@ function b2c_settings_init() { 'wcmpesab2c', 'b2c_section_mpesa', [ - 'label_for' => 'username', - 'class' => 'b2c_row', + 'label_for' => 'username', + 'class' => 'b2c_row', 'b2c_custom_data' => 'custom', ] ); - + add_settings_field( 'password', __('Mpesa Password', 'woocommerce'), @@ -67,12 +70,12 @@ function b2c_settings_init() { 'wcmpesab2c', 'b2c_section_mpesa', [ - 'label_for' => 'password', - 'class' => 'b2c_row', + 'label_for' => 'password', + 'class' => 'b2c_row', 'b2c_custom_data' => 'custom', ] ); - + add_settings_field( 'appkey', __('App Consumer Key', 'woocommerce'), @@ -80,8 +83,8 @@ function b2c_settings_init() { 'wcmpesab2c', 'b2c_section_mpesa', [ - 'label_for' => 'appkey', - 'class' => 'b2c_row', + 'label_for' => 'appkey', + 'class' => 'b2c_row', 'b2c_custom_data' => 'custom', ] ); @@ -93,12 +96,12 @@ function b2c_settings_init() { 'wcmpesab2c', 'b2c_section_mpesa', [ - 'label_for' => 'appsecret', - 'class' => 'b2c_row', + 'label_for' => 'appsecret', + 'class' => 'b2c_row', 'b2c_custom_data' => 'custom', ] ); - + add_settings_field( 'passkey', __('Online Passkey', 'woocommerce'), @@ -106,12 +109,12 @@ function b2c_settings_init() { 'wcmpesab2c', 'b2c_section_mpesa', [ - 'label_for' => 'passkey', - 'class' => 'b2c_row', + 'label_for' => 'passkey', + 'class' => 'b2c_row', 'b2c_custom_data' => 'custom', ] ); - + add_settings_field( 'instructions', __('Withdrawal Instructions', 'woocommerce'), @@ -119,17 +122,17 @@ function b2c_settings_init() { 'wcmpesab2c', 'b2c_section_mpesa', [ - 'label_for' => 'instructions', - 'class' => 'b2c_row', + 'label_for' => 'instructions', + 'class' => 'b2c_row', 'b2c_custom_data' => 'custom', ] ); - + } - function b2c_section_b2c_mpesa_cb($args) + public function b2c_section_b2c_mpesa_cb($args) { - $options = get_option('b2c_wcmpesa_options', ['env'=>'sandbox']); ?> + $options = get_option('b2c_wcmpesa_options', ['env' => 'sandbox']);?>
    Before You Proceed,
  • Please create an app on Daraja if you haven't. @@ -139,142 +142,142 @@ function b2c_section_b2c_mpesa_cb($args)
  • You can generate sandbox test credentials here.
  • + $options = get_option('b2c_wcmpesa_options');?>

    - +

    + $options = get_option('b2c_wcmpesa_options');?>

    - +

    + $options = get_option('b2c_wcmpesa_options');?>

    - +

    + $options = get_option('b2c_wcmpesa_options');?>

    - +

    + $options = get_option('b2c_wcmpesa_options');?>

    - +

    + $options = get_option('b2c_wcmpesa_options');?>

    - +

    + $options = get_option('b2c_wcmpesa_options');?> + class="large-text code">

    - +

    + $options = get_option('b2c_wcmpesa_options');?> + class="large-text code">

    - +

    @@ -282,16 +285,16 @@ function wc_mpesa_b2c_settings()

    +// output security fields for the registered setting "wcmpesab2c" + settings_fields('wcmpesab2c'); + // output setting sections and their fields + // (sections are registered for "wcmpesab2c", each field is registered to a specific section) + do_settings_sections('wcmpesab2c'); + // output save settings button + submit_button('Save C2B Settings'); + ?>
    'phone', - 'class' => 'wcmpesab2cw_row', - 'wcmpesab2cw_custom_data' => 'custom', + 'label_for' => 'phone', + 'class' => 'wcmpesab2cw_row', + 'wcmpesab2cw_custom_data' => 'custom', ] ); - + add_settings_field( 'amount', __('Amount', 'woocommerce'), @@ -44,75 +46,72 @@ public static function wcmpesab2cw_settings_init() 'wcmpesab2cw', 'wcmpesab2cw_section_mpesa', [ - 'label_for' => 'amount', - 'class' => 'wcmpesab2cw_row', - 'wcmpesab2cw_custom_data' => 'custom', + 'label_for' => 'amount', + 'class' => 'wcmpesab2cw_row', + 'wcmpesab2cw_custom_data' => 'custom', ] ); - } - public static function wcmpesab2cw_section_wcmpesab2cw_mpesa_cb($args) + public static function wcmpesab2cw_section_wcmpesab2cw_mpesa_cb($args) { - $options = get_option('b2c_wcmpesa_options'); + $options = get_option('b2c_wcmpesa_options'); $instructions = isset($options['instructions']) ? $options['instructions'] : 'Crosscheck values before submission'; ?>

    - - + public static function wcmpesab2cw_fields_wcmpesab2cw_mpesa_shortcode_cb($args) + { + $options = get_option('wcmpesab2cw_options'); + ?> +

    - - + public static function wcmpesab2cw_fields_wcmpesab2cw_mpesa_username_cb($args) + { + $options = get_option('wcmpesab2cw_options'); + ?> +

    -

    + wp_nonce_field('process_wcmpesab2cw_form', 'wcmpesab2cw_form_nonce'); + ?>
    -
    - 'The form is not valid' ])); + if (!isset($_POST['wcmpesab2cw_form_nonce']) || !wp_verify_nonce($_POST['wcmpesab2cw_form_nonce'], 'process_wcmpesab2cw_form')) { + exit(wp_send_json(['errorCode' => 'The form is not valid'])); } - $Amount = trim($_POST['amount']); - $phone = trim($_POST['phone']); - $Ref = trim($_POST['ref']); + $Amount = trim($_POST['amount']); + $phone = trim($_POST['phone']); + $Ref = trim($_POST['ref']); $PhoneNumber = str_replace("+", "", $phone); $PhoneNumber = preg_replace('/^0/', '254', $phone); exit(wp_send_json(Osen\Woocommerce\Mpesa\B2C::request($PhoneNumber, $Amount, $Ref))); } -} \ No newline at end of file +} diff --git a/updates.json b/updates.json index b5a9c93..503bb0b 100644 --- a/updates.json +++ b/updates.json @@ -1,12 +1,12 @@ { "name": "Mpesa for Woocommerce", - "version": "1.20.79", - "download_url": "https://github.com/osenco/osen-wc-mpesa/archive/v1.20.79.zip", + "version": "1.20.99", + "download_url": "https://github.com/osenco/osen-wc-mpesa/archive/v1.20.99.zip", "homepage": "https://wc-mpesa.osen.co.ke/", "requires": "4.5", - "tested": "5.4", - "last_updated": "2020-07-24 02:20:00", + "tested": "5.5", + "last_updated": "2020-09-09 06:20:00", "upgrade_notice": "Debug Mode", "author": "Osen Concepts",