From a015a12f3258fbd58ffb30a42ce56130e786c8c3 Mon Sep 17 00:00:00 2001 From: Mauko Maunde Date: Mon, 25 May 2020 01:32:01 +0300 Subject: [PATCH] Indentation, clear errors, optimized code, et al --- inc/functions.php | 14 +- inc/wc_mpesa_gateway.php | 93 +++---- osen-wc-mpesa.php | 4 +- src/Menus/Menu.php | 260 +++++++++--------- src/Mpesa/B2C.php | 331 ++++++++++++----------- src/Mpesa/C2B.php | 526 ++++++++++++++++++------------------- src/Mpesa/STK.php | 110 ++++---- src/Post/Metaboxes/C2B.php | 119 +++++---- src/Post/Types/B2C.php | 105 ++++---- src/Post/Types/C2B.php | 25 +- updates.json | 6 +- 11 files changed, 793 insertions(+), 800 deletions(-) diff --git a/inc/functions.php b/inc/functions.php index 7c26316..b737643 100755 --- a/inc/functions.php +++ b/inc/functions.php @@ -22,8 +22,7 @@ function wc_mpesa_post_id_by_meta_key_and_value($key, $value) } } -add_action('woocommerce_thankyou_mpesa', function ($order_id) -{ +add_action('woocommerce_thankyou_mpesa', function ($order_id) { $mpesa = get_option('woocommerce_mpesa_settings'); $idtype = Osen\Mpesa\C2B::$type; $url = home_url('?pesaipn&order='); @@ -104,8 +103,8 @@ function wc_mpesa_post_id_by_meta_key_and_value($key, $value)
  • Select Lipa na M-PESA.
  • Select .
  • -
  • Enter as Account no.
  • Enter as business no.
  • +
  • Enter as Account no.
  • Enter as till no.
  • @@ -119,7 +118,7 @@ function wc_mpesa_post_id_by_meta_key_and_value($key, $value) - @@ -164,17 +163,12 @@ function wc_mpesa_post_id_by_meta_key_and_value($key, $value) ); $("#missed_stk").hide(); - - location.reload(); - clearInterval(checker); - return false; } }); } } - }, 3000); }); @@ -485,4 +479,4 @@ function wc_mpesa_process_ipn() exit(wp_send_json($response)); } -} \ No newline at end of file +} diff --git a/inc/wc_mpesa_gateway.php b/inc/wc_mpesa_gateway.php index 27f26ad..a4cfbbc 100755 --- a/inc/wc_mpesa_gateway.php +++ b/inc/wc_mpesa_gateway.php @@ -1,4 +1,5 @@ These settings are for Customer-2-Business payments. Click here to Setup Business-2-Customer.' + $b2c_settings = (isset(get_option('woocommerce_mpesa_settings')['enable_b2c']) && get_option('woocommerce_mpesa_settings')['enable_b2c'] == 'yes') + ? '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.
  • ' - : + $test_cred = ($env == 'sandbox') + ? '
  • 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']}
    " : ''; - //unset($_SESSION['mpesa_url_registration']); + $color = isset($_GET['reg-state']) ? $_GET['reg-state'] : 'black'; + $register = isset($_GET['mpesa-urls-registered']) ? "
    {$_GET['mpesa-urls-registered']}
    " : ''; + //unset($_SESSION['mpesa_url_registration']); $this->id = 'mpesa'; $this->icon = apply_filters('woocommerce_mpesa_icon', plugins_url('mpesa.png', __FILE__)); $this->method_title = __('Lipa Na MPesa', 'woocommerce'); - $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; // Load settings @@ -77,7 +78,7 @@ public function __construct() $this->enable_for_virtual = $this->get_option('enable_for_virtual', 'yes') === 'yes' ? true : false; add_action('woocommerce_thankyou_' . $this->id, array($this, 'thankyou_page')); - + add_filter('woocommerce_payment_complete_order_status', array($this, 'change_payment_complete_order_status'), 10, 3); // Customer Emails @@ -93,14 +94,14 @@ public function init_form_fields() { $shipping_methods = array(); - foreach (WC()->shipping()->load_shipping_methods() as $method){ - $shipping_methods[ $method->id ] = $method->get_method_title(); + foreach (WC()->shipping()->load_shipping_methods() as $method) { + $shipping_methods[$method->id] = $method->get_method_title(); } $this->form_fields = array( 'enabled' => array( 'title' => __('Enable/Disable', 'woocommerce'), - 'label' => __('Enable '.$this->method_title, 'woocommerce'), + 'label' => __('Enable ' . $this->method_title, 'woocommerce'), 'type' => 'checkbox', 'description' => '', 'default' => 'yes', @@ -116,9 +117,9 @@ public function init_form_fields() 'title' => __('Environment', 'woocommerce'), 'type' => 'select', 'options' => array( - 'sandbox' => __('Sandbox', 'woocommerce'), - 'live' => __('Live', 'woocommerce'), - ), + 'sandbox' => __('Sandbox', 'woocommerce'), + 'live' => __('Live', 'woocommerce'), + ), 'description' => __('MPesa Environment', 'woocommerce'), 'desc_tip' => true, ), @@ -126,15 +127,15 @@ public function init_form_fields() 'title' => __('Identifier Type', 'woocommerce'), 'type' => 'select', 'options' => array( - /**1 => __('MSISDN', 'woocommerce'),*/ - 4 => __('Paybill Number', 'woocommerce'), - 2 => __('Till Number', 'woocommerce') - ), + /**1 => __('MSISDN', 'woocommerce'),*/ + 4 => __('Paybill Number', 'woocommerce'), + 2 => __('Till Number', 'woocommerce') + ), 'description' => __('MPesa Identifier Type', 'woocommerce'), 'desc_tip' => true, ), 'headoffice' => array( - 'title' => __('Head Office Number', 'woocommerce'), + 'title' => __('Store Number/Paybill', 'woocommerce'), 'type' => 'text', 'description' => __('Store Number (for Till) or Paybill Number. Use "Online Shortcode" in Sandbox', 'woocommerce'), 'default' => __('174379', 'woocommerce'), @@ -204,9 +205,9 @@ public function init_form_fields() 'title' => __('Order Status on Payment', 'woocommerce'), 'type' => 'select', 'options' => array( - 'completed' => __('Mark order as completed', 'woocommerce'), - 'processing' => __('Mark order as processing', 'woocommerce') - ), + 'completed' => __('Mark order as completed', 'woocommerce'), + 'processing' => __('Mark order as processing', 'woocommerce') + ), 'description' => __('What status to set the order after Mpesa payment has been received', 'woocommerce'), 'desc_tip' => true, ), @@ -233,7 +234,7 @@ public function init_form_fields() 'title' => __('Manual Payments', 'woocommerce'), 'label' => __('Enable C2B API', 'woocommerce'), 'type' => 'checkbox', - 'description' => ''.(($this->get_option('idtype') == 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
    ', + 'description' => '' . (($this->get_option('idtype') == 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
    ', 'default' => 'no', ), // 'enable_b2c' => array( @@ -266,7 +267,7 @@ public function is_available() // Test if order needs shipping. if (0 < sizeof($order->get_items())) { foreach ($order->get_items() as $item) { - $_product = $item->get_product(); + $_product = wc_get_product($item['product_id']);; if ($_product && $_product->needs_shipping()) { $needs_shipping = true; break; @@ -278,12 +279,12 @@ public function is_available() $needs_shipping = apply_filters('woocommerce_cart_needs_shipping', $needs_shipping); // Virtual order, with virtual disabled - if (! $this->enable_for_virtual && ! $needs_shipping) { + if (!$this->enable_for_virtual && !$needs_shipping) { return false; } // Only apply if all packages are being shipped via chosen method, or order is virtual. - if (! empty($this->enable_for_methods) && $needs_shipping) { + if (!empty($this->enable_for_methods) && $needs_shipping) { $chosen_shipping_methods = array(); if (is_object($order)) { @@ -309,19 +310,19 @@ public function is_available() public function process_payment($order_id) { $order = new WC_Order($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(); - $result = Osen\Mpesa\STK::request($phone, $total, $order_id, get_bloginfo('name').' Purchase', 'WCMPesa'); + $result = Osen\Mpesa\STK::request($phone, $total, $order_id, get_bloginfo('name') . ' Purchase', 'WCMPesa'); - if($result){ + if ($result) { $request_id = $result['MerchantRequestID']; if (isset($result['errorCode'])) { - $error_message = 'MPesa Error '.$result['errorCode'].': '.$result['errorMessage']; + $error_message = 'MPesa Error ' . $result['errorCode'] . ': ' . $result['errorMessage']; $order->update_status('failed', __($error_message, 'woocommerce')); wc_add_notice(__('Failed! ', 'woocommerce') . $error_message, 'error'); return array( @@ -332,7 +333,7 @@ public function process_payment($order_id) /** * Temporarily set status as "on-hold", incase the MPesa API times out before processing our request */ - $order->update_status('on-hold', __('Awaiting MPesa confirmation of payment from '.$phone.'.', 'woocommerce')); + $order->update_status('on-hold', __('Awaiting MPesa confirmation of payment from ' . $phone . '.', 'woocommerce')); /** * Reduce stock levels @@ -342,17 +343,17 @@ public function process_payment($order_id) /** * Remove contents from cart */ - WC()->cart->empty_cart(); + WC()->cart->empty_cart(); // Insert the payment into the database $post_id = wp_insert_post( array( 'post_title' => 'Checkout', - 'post_content' => "Response: ".json_encode($result), + 'post_content' => "Response: " . json_encode($result), 'post_status' => 'publish', 'post_type' => 'mpesaipn', 'post_author' => is_user_logged_in() ? get_current_user_id() : $this->get_option('accountant'), - ) + ) ); update_post_meta($post_id, '_customer', "{$first_name} {$last_name}"); @@ -365,13 +366,13 @@ public function process_payment($order_id) update_post_meta($post_id, '_receipt', 'N/A'); update_post_meta($post_id, '_order_status', 'on-hold'); - $this->instructions .= '

    Awaiting MPesa confirmation of payment from '.$phone.' for request '.$request_id.'. Check your phone for the STK Prompt.

    '; + $this->instructions .= '

    Awaiting MPesa confirmation of payment from ' . $phone . ' for request ' . $request_id . '. Check your phone for the STK Prompt.

    '; // Return thankyou redirect - return array( + return array( 'result' => 'success', 'redirect' => $this->get_return_url($order), - ); + ); } } else { $error_message = __('Could not connect to Daraja', 'woocommerce'); @@ -395,7 +396,7 @@ public function thankyou_page() // echo wpautop(wptexturize($this->instructions)); // } } - + /** * Add content to the WC emails. * @@ -406,9 +407,9 @@ public function thankyou_page() */ public function email_instructions($order, $sent_to_admin, $plain_text = false) { - if ($this->instructions && ! $sent_to_admin && $this->id === $order->get_payment_method()) { + if ($this->instructions && !$sent_to_admin && $this->id === $order->get_payment_method()) { echo wpautop(wptexturize($this->instructions)) . PHP_EOL; } } } -} \ No newline at end of file +} diff --git a/osen-wc-mpesa.php b/osen-wc-mpesa.php index 0d11507..4a3934a 100755 --- a/osen-wc-mpesa.php +++ b/osen-wc-mpesa.php @@ -3,13 +3,13 @@ /** * @package Mpesa For WooCommerce * @author Osen Concepts < hi@osen.co.ke > - * @version 1.20.5 + * @version 1.20.56 * * 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.5 + * Version: 1.20.56 * Author URI: https://osen.co.ke/ * * Requires at least: 4.6 diff --git a/src/Menus/Menu.php b/src/Menus/Menu.php index e3acb06..48aca09 100755 --- a/src/Menus/Menu.php +++ b/src/Menus/Menu.php @@ -1,4 +1,5 @@ -
    -

    About M-Pesa for WooCommerce

    - -

    The Plugin

    -
    -

    This plugin seeks to provide a simple plug-n-play implementation for integrating M-Pesa Payments into online - stores built with WooCommerce and WordPress.

    -
    - -

    Pre-requisites

    -
    -
      -
    1. Please create an app on Daraja if you - haven"t. Fill in the app"s consumer key and secret below.
    2. -
    3. Ensure you have access to the M-Pesa Web Portal. You"ll need this for - when you go LIVE.
    4. -
    5. For security purposes, and for the M-Pesa Instant Payment Notification to work, ensure your site is - running over https(SSL).
    6. -
    7. You can get sandbox test - credentials here.
    8. -
    -
    - -

    Integration(Going Live)

    -
    -

    - While we have made all efforts to ensure this plugin works out of the box - with minimum configuration - required - the service provider requires that the user go through a certain ardous process to migrate from - sandbox(test) environment to production. -

    -

    - We have made a tutorial here to walk you through the - process. We however have a team ready on call to assist you in this are, at a fiat fee of KSh 4000 one-off, - should you find it difficult. -

    -
    - -

    C2B Confirmation and Validation URLs

    -
    -

    Whenever M-Pesa receives a transaction on your shortcode, a validation request is sent to the validation URL - registered above. M-Pesa completes or cancels the transaction depending on the validation response it - receives.

    -

    These URLs must be HTTPS in production. Validation is an optional feature that needs to be activated on - M-Pesa, the owner of the shortcode needs to make this request for activation. This can be done by sending an - email to apisupport@safaricom.co.ke, or through a chat on - the developer portal.

    -
    - -

    Development & Contribution

    - - -

    Contact

    -

    Get in touch with us either via email (hi@osen.co.ke) or via phone(+254204404993)

    - - "> -
    +

    About M-Pesa for WooCommerce

    + +

    The Plugin

    +
    +

    This plugin seeks to provide a simple plug-n-play implementation for integrating M-Pesa Payments into online + stores built with WooCommerce and WordPress.

    +
    + +

    Pre-requisites

    +
    +
      +
    1. Please create an app on Daraja if you + haven"t. Fill in the app"s consumer key and secret below.
    2. +
    3. Ensure you have access to the M-Pesa Web Portal. You"ll need this for + when you go LIVE.
    4. +
    5. For security purposes, and for the M-Pesa Instant Payment Notification to work, ensure your site is + running over https(SSL).
    6. +
    7. You can get sandbox test + credentials here.
    8. +
    +
    + +

    Integration(Going Live)

    +
    +

    + While we have made all efforts to ensure this plugin works out of the box - with minimum configuration + required - the service provider requires that the user go through a certain ardous process to migrate from + sandbox(test) environment to production. +

    +

    + We have made a tutorial here to walk you through the + process. We however have a team ready on call to assist you in this are, at a fiat fee of KSh 4000 one-off, + should you find it difficult. +

    +
    + +

    C2B Confirmation and Validation URLs

    +
    +

    Whenever M-Pesa receives a transaction on your shortcode, a validation request is sent to the validation URL + registered above. M-Pesa completes or cancels the transaction depending on the validation response it + receives.

    +

    These URLs must be HTTPS in production. Validation is an optional feature that needs to be activated on + M-Pesa, the owner of the shortcode needs to make this request for activation. This can be done by sending an + email to apisupport@safaricom.co.ke, or through a chat on + the developer portal.

    +
    + +

    Development & Contribution

    +
    +

    To help improve and support our effort to make such solutions as this one, you can start by contributing + here:

    +
    +
  • This Plugin"s Github Repo
  • +
  • M-Pesa PHP SDK
  • +
  • M-Pesa For Open Cart
  • +
  • M-Pesa For PrestaShop
  • +
    +
    + +

    Contact

    +

    Get in touch with us either via email (hi@osen.co.ke) or via phone(+254204404993)

    + + "> + "mpesaipn"]) as $post) { - \setup_postdata($post); - for ($i=1; $i <= 12 ; $i++) { - if (date("Y", strtotime($post->post_date)) == date("Y")) { - if(date("m", strtotime($post->post_date)) == $i){ - $months[$i][] = (int)get_post_meta( $post->ID, "_amount", true ); - } else { - $months[$i][] = 0; + public static function wc_mpesa_menu_analytics() + { + $payments = array(); + $months = array(); + $monthly = array(); + + foreach (get_posts(["post_type" => "mpesaipn"]) as $post) { + \setup_postdata($post); + for ($i = 1; $i <= 12; $i++) { + if (date("Y", strtotime($post->post_date)) == date("Y")) { + if (date("m", strtotime($post->post_date)) == $i) { + $months[$i][] = (int) get_post_meta($post->ID, "_amount", true); + } else { + $months[$i][] = 0; + } + } } + + array_push($monthly, date("m", strtotime($post->post_date))); } - } - array_push($monthly, date("m", strtotime($post->post_date))); + foreach ($months as $month => $values) { + $payments[$month] = array_sum($values); + } - } + $ms = ["Jan", "Feb", "Mar", "Apr", "May", "Jun", "Jul", "Aug", "Sep", "Oct", "Nov", "Dec"]; + $ps = array_values($payments); - foreach ($months as $month => $values) { - $payments[$month] = array_sum($values); - } - - $ms = ["Jan", "Feb", "Mar", "Apr", "May", "Jun", "Jul", "Aug", "Sep", "Oct", "Nov", "Dec"]; - $ps = array_values($payments); - - wp_enqueue_style("c3", plugins_url("assets/c3/c3.min.css", __FILE__)); - wp_enqueue_script("c3", plugins_url("assets/c3/c3.bundle.js", __FILE__)); - - $date = date("Y"); - $cols = json_encode(array_merge(["data1"], $ps)); - $categories = json_encode(array_unique($ms)); - - echo '
    + wp_enqueue_style("c3", plugins_url("assets/c3/c3.min.css", __FILE__)); + wp_enqueue_script("c3", plugins_url("assets/c3/c3.bundle.js", __FILE__)); + + $date = date("Y"); + $cols = json_encode(array_merge(["data1"], $ps)); + $categories = json_encode(array_unique($ms)); + + echo '

    Payments Analytics

    -

    Total monthly payments received via MPESA for the year '.$date.'

    +

    Total monthly payments received via MPESA for the year ' . $date . '


    '; - } + } - public static function wc_mpesa_menu_settings() - { - wp_redirect(admin_url("admin.php?page=wc-settings&tab=checkout§ion=mpesa")); - } + public static function wc_mpesa_menu_settings() + { + wp_redirect(admin_url("admin.php?page=wc-settings&tab=checkout§ion=mpesa")); + } - public static function wc_mpesa_b2c_settings() - { - wp_redirect(admin_url("admin.php?post_type=b2c_payment&page=wcmpesab2c")); - } + public static function wc_mpesa_b2c_settings() + { + wp_redirect(admin_url("admin.php?post_type=b2c_payment&page=wcmpesab2c")); + } - public static function wc_mpesa_menu_b2c() - { - wp_redirect(admin_url("edit.php?post_type=b2c_payment")); - } -} \ No newline at end of file + public static function wc_mpesa_menu_b2c() + { + wp_redirect(admin_url("edit.php?post_type=b2c_payment")); + } + } diff --git a/src/Mpesa/B2C.php b/src/Mpesa/B2C.php index 33a85f4..8c96ad4 100755 --- a/src/Mpesa/B2C.php +++ b/src/Mpesa/B2C.php @@ -1,4 +1,5 @@ $value) { - self::$$key = $value; - } - } - - /** - * Function to generate access token - * @return string/mixed - */ - public static function token() - { - $endpoint = (self::$env == 'live') ? 'https://api.safaricom.co.ke/oauth/v1/generate?grant_type=client_credentials' : 'https://sandbox.safaricom.co.ke/oauth/v1/generate?grant_type=client_credentials'; - - $credentials = base64_encode(self::$appkey.':'.self::$appsecret); - $response = wp_remote_get( - $endpoint, - array( - 'headers' => array( - 'Authorization' => 'Basic ' . $credentials - ) - ) - ); - - return is_wp_error($response) - ? 'Invalid' - : json_decode($response['body'])->access_token; - } - - /** - * Function to process response data for validation - * @param callable $callback - Optional callable function to process the response - must return boolean - * @return array - */ - public static function validate($callback = null, $data = []) - { - if(is_null($callback) || empty($callback)){ - return array( - 'ResultCode' => 0, - 'ResultDesc' => 'Success', - 'ThirdPartyTransID' => isset($data['transID']) ? $data['transID'] : 0 - ); - } else { - if (!call_user_func_array($callback, array($data))) { - return array( - 'ResultCode' => 1, - 'ResultDesc' => 'Failed', - 'ThirdPartyTransID' => isset($data['transID']) ? $data['transID'] : 0 - ); - } else { - return array( - 'ResultCode' => 0, - 'ResultDesc' => 'Success', - 'ThirdPartyTransID' => isset($data['transID']) ? $data['transID'] : 0 - ); - } - } - } - - /** - * Function to process response data for confirmation - * @param callable $callback - Optional callable function to process the response - must return boolean - * @return array - */ - public static function confirm($callback = null, $data = []) - { - if(is_null($callback) || empty($callback)){ - return array( - 'ResultCode' => 0, - 'ResultDesc' => 'Success', - 'ThirdPartyTransID' => isset($data['transID']) ? $data['transID'] : 0 - ); - } else { - if (!call_user_func_array($callback, array($data))) { - return array( - 'ResultCode' => 1, - 'ResultDesc' => 'Failed', - 'ThirdPartyTransID' => isset($data['transID']) ? $data['transID'] : 0 - ); - } else { - return array( - 'ResultCode' => 0, - 'ResultDesc' => 'Success', - 'ThirdPartyTransID' => isset($data['transID']) ? $data['transID'] : 0 - ); - } - } - } - - - /** - * - */ - public static function request($phone, $amount, $reference, $trxdesc = '', $remark = '') - { - $phone = str_replace("+", "", $phone); - $phone = preg_replace('/^0/', '254', $phone); - $token = self::token(); - $endpoint = (self::$env == 'live') ? 'https://api.safaricom.co.ke/mpesa/b2c/v1/paymentrequest' : 'https://sandbox.safaricom.co.ke/mpesa/b2c/v1/paymentrequest'; - $timestamp = date('YmdHis'); - $env = self::$env; - $plaintext = self::$password; - $publicKey = file_get_contents('cert/'.$env.'/cert.cr'); - - openssl_public_encrypt($plaintext, $encrypted, $publicKey, OPENSSL_PKCS1_PADDING); - - $password = base64_encode($encrypted); - - $curl_post_data = array( - 'InitiatorName' => self::$username, - 'SecurityCredential' => $password, - 'CommandID' => (self::$type == 4) ? 'CustomerPayBillOnline' : 'BuyGoodsOnline', - 'Amount' => round($amount), - 'PartyA' => self::$shortcode, - 'PartyB' => $phone, - 'Remarks' => $remark, - 'QueueTimeOutURL' => self::$timeout, - 'ResultURL' => self::$reconcile, - 'Occasion' => $reference - ); - - $data_string = json_encode($curl_post_data); - - $response = wp_remote_post( - $endpoint, - array( - 'headers' => array( - 'Content-Type' => 'application/json', - 'Authorization' => 'Bearer ' . self::token() - ), - 'body' => $data_string - ) - ); - return is_wp_error($response) - ? array('errorCode' => 1, 'errorMessage' => 'Could not connect to Daraja') - : json_decode($response['body'], true); - } - - /** - * - */ - public static function reconcile($callback, $data) - { - $response = is_null($data) ? json_decode(file_get_contents('php://input'), true) : $data; - - return is_null($callback) ? array('resultCode' => 0, 'resultDesc' => 'Success') : call_user_func_array($callback, array($response)); - } -} \ No newline at end of file + public static $env = 'sandbox'; + public static $username; + public static $password; + public static $appkey; + public static $appsecret; + public static $passkey; + public static $shortcode; + public static $headoffice; + public static $type = 4; + public static $validate; + public static $confirm; + public static $reconcile; + public static $timeout; + + public static function set($config) + { + foreach ($config as $key => $value) { + self::$$key = $value; + } + } + + /** + * Function to generate access token + * @return string/mixed + */ + public static function token() + { + $endpoint = (self::$env == 'live') ? 'https://api.safaricom.co.ke/oauth/v1/generate?grant_type=client_credentials' : 'https://sandbox.safaricom.co.ke/oauth/v1/generate?grant_type=client_credentials'; + + $credentials = base64_encode(self::$appkey . ':' . self::$appsecret); + $response = wp_remote_get( + $endpoint, + array( + 'headers' => array( + 'Authorization' => 'Basic ' . $credentials, + ), + ) + ); + + return is_wp_error($response) + ? 'Invalid' + : json_decode($response['body'])->access_token; + } + + /** + * Function to process response data for validation + * @param callable $callback - Optional callable function to process the response - must return boolean + * @return array + */ + public static function validate($callback = null, $data = []) + { + if (is_null($callback) || empty($callback)) { + return array( + 'ResultCode' => 0, + 'ResultDesc' => 'Success', + 'ThirdPartyTransID' => isset($data['transID']) ? $data['transID'] : 0, + ); + } else { + if (!call_user_func_array($callback, array($data))) { + return array( + 'ResultCode' => 1, + 'ResultDesc' => 'Failed', + 'ThirdPartyTransID' => isset($data['transID']) ? $data['transID'] : 0, + ); + } else { + return array( + 'ResultCode' => 0, + 'ResultDesc' => 'Success', + 'ThirdPartyTransID' => isset($data['transID']) ? $data['transID'] : 0, + ); + } + } + } + + /** + * Function to process response data for confirmation + * @param callable $callback - Optional callable function to process the response - must return boolean + * @return array + */ + public static function confirm($callback = null, $data = []) + { + if (is_null($callback) || empty($callback)) { + return array( + 'ResultCode' => 0, + 'ResultDesc' => 'Success', + 'ThirdPartyTransID' => isset($data['transID']) ? $data['transID'] : 0, + ); + } else { + if (!call_user_func_array($callback, array($data))) { + return array( + 'ResultCode' => 1, + 'ResultDesc' => 'Failed', + 'ThirdPartyTransID' => isset($data['transID']) ? $data['transID'] : 0, + ); + } else { + return array( + 'ResultCode' => 0, + 'ResultDesc' => 'Success', + 'ThirdPartyTransID' => isset($data['transID']) ? $data['transID'] : 0, + ); + } + } + } + + /** + * + */ + public static function request($phone, $amount, $reference, $trxdesc = '', $remark = '') + { + $phone = str_replace("+", "", $phone); + $phone = preg_replace('/^0/', '254', $phone); + $token = self::token(); + $endpoint = (self::$env == 'live') ? 'https://api.safaricom.co.ke/mpesa/b2c/v1/paymentrequest' : 'https://sandbox.safaricom.co.ke/mpesa/b2c/v1/paymentrequest'; + $timestamp = date('YmdHis'); + $env = self::$env; + $plaintext = self::$password; + $publicKey = file_get_contents('cert/' . $env . '/cert.cer'); + + openssl_public_encrypt($plaintext, $encrypted, $publicKey, OPENSSL_PKCS1_PADDING); + + $password = base64_encode($encrypted); + + $curl_post_data = array( + 'InitiatorName' => self::$username, + 'SecurityCredential' => $password, + 'CommandID' => (self::$type == 4) ? 'CustomerPayBillOnline' : 'BuyGoodsOnline', + 'Amount' => round($amount), + 'PartyA' => self::$shortcode, + 'PartyB' => $phone, + 'Remarks' => $remark, + 'QueueTimeOutURL' => self::$timeout, + 'ResultURL' => self::$reconcile, + 'Occasion' => $reference, + ); + + $data_string = json_encode($curl_post_data); + + $response = wp_remote_post( + $endpoint, + array( + 'headers' => array( + 'Content-Type' => 'application/json', + 'Authorization' => 'Bearer ' . self::token(), + ), + 'body' => $data_string, + ) + ); + return is_wp_error($response) + ? array('errorCode' => 1, 'errorMessage' => 'Could not connect to Daraja') + : json_decode($response['body'], true); + } + + /** + * + */ + public static function reconcile($callback, $data) + { + $response = is_null($data) ? json_decode(file_get_contents('php://input'), true) : $data; + + return is_null($callback) ? array('resultCode' => 0, 'resultDesc' => 'Success') : call_user_func_array($callback, array($response)); + } +} diff --git a/src/Mpesa/C2B.php b/src/Mpesa/C2B.php index 114dd04..38f8aff 100755 --- a/src/Mpesa/C2B.php +++ b/src/Mpesa/C2B.php @@ -1,4 +1,5 @@ $value) { - self::$$key = $value; + /** + * @param string | Environment in use | live/sandbox + */ + public static $env = 'sandbox'; + + /** + * @param string | Daraja App Consumer Key | lipia/validate + */ + public static $appkey; + + /** + * @param string | Daraja App Consumer Secret | lipia/validate + */ + public static $appsecret; + + /** + * @param string | Online Passkey | lipia/validate + */ + public static $passkey; + + /** + * @param string | Head Office Shortcode | 123456 + */ + public static $headoffice; + + /** + * @param string | Business Paybill/Till | 123456 + */ + public static $shortcode; + + /** + * @param integer | Identifier Type | 1(MSISDN)/2(Till)/4(Paybill) + */ + public static $type = 4; + + /** + * @param string | Validation URI | lipia/validate + */ + public static $validate; + + /** + * @param string | Confirmation URI | lipia/confirm + */ + public static $confirm; + + /** + * @param string | Reconciliation URI | lipia/reconcile + */ + public static $reconcile; + + /** + * @param string | Timeout URI | lipia/reconcile + */ + public static $timeout; + + public function __construct() + { + } + + /** + * @param array $config - Key-value pairs of settings + */ + public static function set($config) + { + foreach ($config as $key => $value) { + self::$$key = $value; + } } - } - - /** - * Function to generate access token - * @return string/mixed - */ - public static function token() - { - $endpoint = (self::$env == 'live') ? 'https://api.safaricom.co.ke/oauth/v1/generate?grant_type=client_credentials' : 'https://sandbox.safaricom.co.ke/oauth/v1/generate?grant_type=client_credentials'; - - $credentials = base64_encode(self::$appkey.':'.self::$appsecret); - $response = wp_remote_get( - $endpoint, - array( - 'headers' => array( - 'Authorization' => 'Basic ' . $credentials - ) - ) - ); - - $return = is_wp_error($response) ? 'null' : json_decode($response['body']); - - return is_null($return) ? '' : (isset($return->access_token) ? $return->access_token : ''); - } - - /** - * Function to process response data for validation - * @param callable $callback - Optional callable function to process the response - must return boolean - * @return array - */ - public static function validate($callback, $data) - { - if(is_null($callback) || empty($callback)){ - return array( - 'ResultCode' => 0, - 'ResultDesc' => 'Success' - ); - } else { - if (!call_user_func_array($callback, array($data))) { - return array( - 'ResultCode' => 1, - 'ResultDesc' => 'Failed' - ); + + /** + * Function to generate access token + * @return string/mixed + */ + public static function token() + { + $endpoint = (self::$env == 'live') ? 'https://api.safaricom.co.ke/oauth/v1/generate?grant_type=client_credentials' : 'https://sandbox.safaricom.co.ke/oauth/v1/generate?grant_type=client_credentials'; + + $credentials = base64_encode(self::$appkey . ':' . self::$appsecret); + $response = wp_remote_get( + $endpoint, + array( + 'headers' => array( + 'Authorization' => 'Basic ' . $credentials, + ), + ) + ); + + $return = is_wp_error($response) ? 'null' : json_decode($response['body']); + + return is_null($return) ? '' : (isset($return->access_token) ? $return->access_token : ''); + } + + /** + * Function to process response data for validation + * @param callable $callback - Optional callable function to process the response - must return boolean + * @return array + */ + public static function validate($callback, $data) + { + if (is_null($callback) || empty($callback)) { + return array( + 'ResultCode' => 0, + 'ResultDesc' => 'Success', + ); } else { - return array( - 'ResultCode' => 0, - 'ResultDesc' => 'Success' - ); + if (!call_user_func_array($callback, array($data))) { + return array( + 'ResultCode' => 1, + 'ResultDesc' => 'Failed', + ); + } else { + return array( + 'ResultCode' => 0, + 'ResultDesc' => 'Success', + ); + } } } - } - - /** - * Function to process response data for confirmation - * @param callable $callback - Optional callable function to process the response - must return boolean - * @return array - */ - public static function confirm($callback, $data) - { - if(is_null($callback) || empty($callback)){ - return array( - 'ResultCode' => 0, - 'ResultDesc' => 'Success' - ); - } else { - if (!call_user_func_array($callback, array($data))) { - return array( - 'ResultCode' => 1, - 'ResultDesc' => 'Failed' + + /** + * Function to process response data for confirmation + * @param callable $callback - Optional callable function to process the response - must return boolean + * @return array + */ + public static function confirm($callback, $data) + { + if (is_null($callback) || empty($callback)) { + return array( + 'ResultCode' => 0, + 'ResultDesc' => 'Success', + ); + } else { + if (!call_user_func_array($callback, array($data))) { + return array( + 'ResultCode' => 1, + 'ResultDesc' => 'Failed', + ); + } else { + return array( + 'ResultCode' => 0, + 'ResultDesc' => 'Success', + ); + } + } + } + + /** + * Function to register validation and confirmation URLs + * @param string $env - Environment for which to register URLs + * @return bool/array + */ + public static function register($callback = null) + { + $endpoint = (self::$env == 'live') + ? 'https://api.safaricom.co.ke/mpesa/c2b/v1/registerurl' + : 'https://sandbox.safaricom.co.ke/mpesa/c2b/v1/registerurl'; + $post_data = array( + 'ShortCode' => self::$shortcode, + 'ResponseType' => 'Cancelled', + 'ConfirmationURL' => self::$confirm, + 'ValidationURL' => self::$validate, ); - } else { - return array( - 'ResultCode' => 0, - 'ResultDesc' => 'Success' + $data_string = json_encode($post_data); + + $response = wp_remote_post( + $endpoint, + array( + 'headers' => array( + 'Content-Type' => 'application/json', + 'Authorization' => 'Bearer ' . self::token(), + ), + 'body' => $data_string, + ) ); - } + $result = is_wp_error($response) + ? array('errorCode' => 1, 'errorMessage' => 'Could not connect to Daraja') + : json_decode($response['body'], true); + + return is_null($callback) + ? $result + : call_user_func($callback, $result); } - } - - /** - * Function to register validation and confirmation URLs - * @param string $env - Environment for which to register URLs - * @return bool/array - */ - public static function register($callback = null) - { - $endpoint = (self::$env == 'live') - ? 'https://api.safaricom.co.ke/mpesa/c2b/v1/registerurl' - : 'https://sandbox.safaricom.co.ke/mpesa/c2b/v1/registerurl'; - $post_data = array( - 'ShortCode' => self::$shortcode, - 'ResponseType' => 'Cancelled', - 'ConfirmationURL' => self::$confirm, - 'ValidationURL' => self::$validate - ); - $data_string = json_encode($post_data); - - $response = wp_remote_post( - $endpoint, - array( - 'headers' => array( - 'Content-Type' => 'application/json', - 'Authorization' => 'Bearer ' . self::token() - ), - 'body' => $data_string - ) - ); - $result = is_wp_error($response) - ? array('errorCode' => 1, 'errorMessage' => 'Could not connect to Daraja') - : json_decode($response['body'], true); - - return is_null($callback) - ? $result - : call_user_func($callback, $result); - } - - /** - * Function to process request for payment - * @param string $phone - Phone Number to send STK Prompt Request to - * @param string $amount - Amount of money to charge - * @param string $reference - Account to show in STK Prompt - * @param string $trxdesc - Transaction Description(optional) - * @param string $remark - Remarks about transaction(optional) - * @return array - */ - public static function request($phone, $amount, $reference, $trxdesc = 'WooCommerce Payment', $remark = 'WooCommerce Payment') - { - $phone = preg_replace('/^0/', '254', str_replace("+", "", $phone)); - - $endpoint = (self::$env == 'live') ? 'https://api.safaricom.co.ke/mpesa/stkpush/v1/processrequest' : 'https://sandbox.safaricom.co.ke/mpesa/stkpush/v1/processrequest'; - - $timestamp = date('YmdHis'); - $password = base64_encode(self::$headoffice.self::$passkey.$timestamp); - - $post_data = array( - 'BusinessShortCode' => self::$headoffice, - 'Password' => $password, - 'Timestamp' => $timestamp, - 'TransactionType' => (self::$type == 4) ? 'CustomerPayBillOnline' : 'BuyGoodsOnline', - 'Amount' => round($amount), - 'PartyA' => $phone, - 'PartyB' => self::$shortcode, - 'PhoneNumber' => $phone, - 'CallBackURL' => self::$reconcile, - 'AccountReference' => $reference, - 'TransactionDesc' => $trxdesc, - 'Remark' => $remark - ); - - $data_string = json_encode($post_data); - $response = wp_remote_post( - $endpoint, - array( - 'headers' => array( - 'Content-Type' => 'application/json', - 'Authorization' => 'Bearer ' . self::token() - ), - 'body' => $data_string - ) - ); - return is_wp_error($response) - ? array('errorCode' => 1, 'errorMessage' => 'Could not connect to Daraja') - : json_decode($response['body'], true); - } -/** - * Function to process response data for reconciliation - * @param callable $callback - Optional callable function to process the response - must return boolean - * @return bool/array - */ - public static function reconcile($args) - { - $callback = isset($args[0]) ? $args[0] : 'wc_mpesa_reconcile'; - $data = isset($args[1]) ? $args[1] : null; - - if(is_null($data)){ - $response = json_decode(file_get_contents('php://input'), true); - $response = isset($response['Body']) ? $response['Body'] : array(); - } else { - $response = $data; + /** + * Function to process request for payment + * @param string $phone - Phone Number to send STK Prompt Request to + * @param string $amount - Amount of money to charge + * @param string $reference - Account to show in STK Prompt + * @param string $trxdesc - Transaction Description(optional) + * @param string $remark - Remarks about transaction(optional) + * @return array + */ + public static function request($phone, $amount, $reference, $trxdesc = 'WooCommerce Payment', $remark = 'WooCommerce Payment') + { + $phone = preg_replace('/^0/', '254', str_replace("+", "", $phone)); + $endpoint = (self::$env == 'live') ? 'https://api.safaricom.co.ke/mpesa/stkpush/v1/processrequest' : 'https://sandbox.safaricom.co.ke/mpesa/stkpush/v1/processrequest'; + $timestamp = date('YmdHis'); + $password = base64_encode(self::$headoffice . self::$passkey . $timestamp); + + $post_data = array( + 'BusinessShortCode' => self::$headoffice, + 'Password' => $password, + 'Timestamp' => $timestamp, + 'TransactionType' => (self::$type == 4) ? 'CustomerPayBillOnline' : 'BuyGoodsOnline', + 'Amount' => round($amount), + 'PartyA' => $phone, + 'PartyB' => self::$shortcode, + 'PhoneNumber' => $phone, + 'CallBackURL' => self::$reconcile, + 'AccountReference' => $reference, + 'TransactionDesc' => $trxdesc, + 'Remark' => $remark, + ); + + $data_string = json_encode($post_data); + $response = wp_remote_post( + $endpoint, + array( + 'headers' => array( + 'Content-Type' => 'application/json', + 'Authorization' => 'Bearer ' . self::token(), + ), + 'body' => $data_string, + ) + ); + return is_wp_error($response) + ? array('errorCode' => 1, 'errorMessage' => 'Could not connect to Daraja') + : json_decode($response['body'], true); } - - return is_null($callback) - ? array('resultCode' => 0, 'resultDesc' => 'Reconciliation successful') - : call_user_func_array($callback, array($response)); - } - - /** - * Function to process response data if system times out - * @param callable $callback - Optional callable function to process the response - must return boolean - * @return bool/array - */ - public static function timeout($callback = null, $data = null) - { - if(is_null($data)){ - $response = json_decode(file_get_contents('php://input'), true); - $response = isset($response['Body']) ? $response['Body'] : array(); - } else { - $response = $data; + + /** + * Function to process response data for reconciliation + * @param callable $callback - Optional callable function to process the response - must return boolean + * @return bool/array + */ + public static function reconcile($args) + { + $callback = isset($args[0]) ? $args[0] : 'wc_mpesa_reconcile'; + $data = isset($args[1]) ? $args[1] : null; + + if (is_null($data)) { + $response = json_decode(file_get_contents('php://input'), true); + $response = isset($response['Body']) ? $response['Body'] : array(); + } else { + $response = $data; + } + + return is_null($callback) + ? array('resultCode' => 0, 'resultDesc' => 'Reconciliation successful') + : call_user_func_array($callback, array($response)); } - if(is_null($callback)){ - return true; - } else { - return call_user_func_array($callback, array($response)); + /** + * Function to process response data if system times out + * @param callable $callback - Optional callable function to process the response - must return boolean + * @return bool/array + */ + public static function timeout($callback = null, $data = null) + { + if (is_null($data)) { + $response = json_decode(file_get_contents('php://input'), true); + $response = isset($response['Body']) ? $response['Body'] : array(); + } else { + $response = $data; + } + + if (is_null($callback)) { + return true; + } else { + return call_user_func_array($callback, array($response)); + } } - } -} \ No newline at end of file +} diff --git a/src/Mpesa/STK.php b/src/Mpesa/STK.php index 5155688..b611a89 100755 --- a/src/Mpesa/STK.php +++ b/src/Mpesa/STK.php @@ -110,12 +110,12 @@ public static function token() : 'https://sandbox.safaricom.co.ke/oauth/v1/generate?grant_type=client_credentials'; $credentials = base64_encode(self::$appkey . ':' . self::$appsecret); - $response = wp_remote_get( + $response = wp_remote_get( $endpoint, array( 'headers' => array( - 'Authorization' => 'Basic ' . $credentials - ) + 'Authorization' => 'Basic ' . $credentials, + ), ) ); @@ -133,19 +133,19 @@ public static function validate($callback = null, $data = []) { if (is_null($callback) || empty($callback)) { return array( - 'ResultCode' => 0, - 'ResultDesc' => 'Success' + 'ResultCode' => 0, + 'ResultDesc' => 'Success', ); } else { if (!call_user_func_array($callback, array($data))) { return array( - 'ResultCode' => 1, - 'ResultDesc' => 'Failed' + 'ResultCode' => 1, + 'ResultDesc' => 'Failed', ); } else { return array( - 'ResultCode' => 0, - 'ResultDesc' => 'Success', + 'ResultCode' => 0, + 'ResultDesc' => 'Success', ); } } @@ -160,19 +160,19 @@ public static function confirm($callback = null, $data = []) { if (is_null($callback) || empty($callback)) { return array( - 'ResultCode' => 0, - 'ResultDesc' => 'Success' + 'ResultCode' => 0, + 'ResultDesc' => 'Success', ); } else { if (!call_user_func_array($callback, array($data))) { return array( - 'ResultCode' => 1, - 'ResultDesc' => 'Failed' + 'ResultCode' => 1, + 'ResultDesc' => 'Failed', ); } else { return array( - 'ResultCode' => 0, - 'ResultDesc' => 'Success' + 'ResultCode' => 0, + 'ResultDesc' => 'Success', ); } } @@ -189,39 +189,39 @@ public static function confirm($callback = null, $data = []) */ public static function request($phone, $amount, $reference, $trxdesc = 'WooCommerce Payment', $remark = 'WooCommerce Payment') { - $phone = preg_replace('/^0/', '254', str_replace("+", "", $phone)); + $phone = preg_replace('/^0/', '254', str_replace("+", "", $phone)); - $endpoint = (self::$env == 'live') + $endpoint = (self::$env == 'live') ? 'https://api.safaricom.co.ke/mpesa/stkpush/v1/processrequest' : 'https://sandbox.safaricom.co.ke/mpesa/stkpush/v1/processrequest'; - $timestamp = date('YmdHis'); - $password = base64_encode(self::$headoffice . self::$passkey . $timestamp); - - $post_data = array( - 'BusinessShortCode' => self::$headoffice, - 'Password' => $password, - 'Timestamp' => $timestamp, - 'TransactionType' => (self::$type == 4) ? 'CustomerPayBillOnline' : 'CustomerBuyGoodsOnline', - 'Amount' => round($amount), - 'PartyA' => $phone, - 'PartyB' => self::$shortcode, - 'PhoneNumber' => $phone, - 'CallBackURL' => self::$reconcile, - 'AccountReference' => $reference, - 'TransactionDesc' => $trxdesc, - 'Remark' => $remark + $timestamp = date('YmdHis'); + $password = base64_encode(self::$headoffice . self::$passkey . $timestamp); + + $post_data = array( + 'BusinessShortCode' => self::$headoffice, + 'Password' => $password, + 'Timestamp' => $timestamp, + 'TransactionType' => (self::$type == 4) ? 'CustomerPayBillOnline' : 'CustomerBuyGoodsOnline', + 'Amount' => round($amount), + 'PartyA' => $phone, + 'PartyB' => self::$shortcode, + 'PhoneNumber' => $phone, + 'CallBackURL' => self::$reconcile, + 'AccountReference' => $reference, + 'TransactionDesc' => $trxdesc, + 'Remark' => $remark, ); - $data_string = json_encode($post_data); - $response = wp_remote_post( + $data_string = json_encode($post_data); + $response = wp_remote_post( $endpoint, array( 'headers' => array( - 'Content-Type' => 'application/json', - 'Authorization' => 'Bearer ' . self::token() + 'Content-Type' => 'application/json', + 'Authorization' => 'Bearer ' . self::token(), ), - 'body' => $data_string + 'body' => $data_string, ) ); return is_wp_error($response) @@ -270,33 +270,33 @@ public static function timeout($callback = null, $data = null) public static function status($transaction, $command = 'TransactionStatusQuery', $remarks = 'Transaction Status Query', $occasion = '') { - $token = self::token(); + $token = self::token(); $endpoint = (self::$env == 'live') ? 'https://api.safaricom.co.ke/mpesa/transactionstatus/v1/query' : 'https://sandbox.safaricom.co.ke/mpesa/transactionstatus/v1/query'; $post_data = array( - 'Initiator' => self::$username, - 'SecurityCredential' => self::$credentials, - 'CommandID' => $command, - 'TransactionID' => $transaction, - 'PartyA' => self::$shortcode, - 'IdentifierType' => self::$type, - 'ResultURL' => self::$results, - 'QueueTimeOutURL' => self::$timeout, - 'Remarks' => $remarks, - 'Occasion' => $occasion + 'Initiator' => self::$username, + 'SecurityCredential' => self::$credentials, + 'CommandID' => $command, + 'TransactionID' => $transaction, + 'PartyA' => self::$shortcode, + 'IdentifierType' => self::$type, + 'ResultURL' => self::$results, + 'QueueTimeOutURL' => self::$timeout, + 'Remarks' => $remarks, + 'Occasion' => $occasion, ); - $data_string = json_encode($post_data); - $response = wp_remote_post( + $data_string = json_encode($post_data); + $response = wp_remote_post( $endpoint, array( 'headers' => array( - 'Content-Type' => 'application/json', - 'Authorization' => 'Bearer ' . self::token() + 'Content-Type' => 'application/json', + 'Authorization' => 'Bearer ' . self::token(), ), - 'body' => $data_string + 'body' => $data_string, ) ); @@ -304,4 +304,4 @@ public static function status($transaction, $command = 'TransactionStatusQuery', ? array('errorCode' => 1, 'errorMessage' => 'Could not connect to Daraja') : json_decode($response['body'], true); } -} \ No newline at end of file +} diff --git a/src/Post/Metaboxes/C2B.php b/src/Post/Metaboxes/C2B.php index fce2b29..52d100f 100755 --- a/src/Post/Metaboxes/C2B.php +++ b/src/Post/Metaboxes/C2B.php @@ -1,26 +1,28 @@ * @since 0.18.01 */ -class C2B{ - - public static function init(Type $var = null) +class C2B +{ + public static function init() { add_action('add_meta_boxes', [new self, 'mpesa_mb_sm']); add_action('save_post', [new self, 'mpesaipn_save_meta']); } - public static function mpesa_mb_sm() + 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-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('woocommerce-order-notes', 'Payment Order Notes', [new self, 'order_notes'],'mpesaipn', 'normal', 'default'); + 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'); } @@ -34,7 +36,7 @@ public static function mpesa_payment($post) - Add New MPesa Payment + Add New MPesa Payment '; @@ -57,7 +59,7 @@ public static function mpesa_status($post) echo ' @@ -67,7 +69,7 @@ public static function mpesa_status($post) jQuery(document).ready(function($){ $("#mpesaipn_status").click(function(e){ e.preventDefault(); - $.post("'.admin_url("admin-ajax.php").'", [request: '.$request.'], function(data){ + $.post("' . admin_url("admin-ajax.php") . '", [request: ' . $request . '], function(data){ $("#mpesaipn_status_result").html(data); }); }); @@ -82,17 +84,17 @@ public static function customer_details($post) { $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(); + if (isset($_GET['order'])) { + $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 - if (substr($phone, 0,1) == "+") { + if (substr($phone, 0, 1) == "+") { $phone = str_replace("+", "", $phone); } @@ -101,13 +103,13 @@ public static function customer_details($post) echo '
    - '.$statuses[$status].' + ' . $statuses[$status] . '
    - + -
    Full Names
    Phone Number + - +
    '; @@ -121,7 +123,7 @@ public static function order_details($post) $paid = get_post_meta($post->ID, '_paid', true); $balance = get_post_meta($post->ID, '_balance', true); - if(isset($_GET['order'])){ + 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(); @@ -130,18 +132,18 @@ public static function order_details($post) $customer = "{$first_name} {$last_name}"; } - $new = wc_get_order($order) ? '' : ' Add New Manual Order'; + $new = wc_get_order($order) ? '' : ' Add New Manual Order'; echo ' - +
    Order ID - '.$new.' + ' . $new . '
    Order Amount
    '; } @@ -173,49 +175,50 @@ public static function payment_details($post) "failed" => "This Order Failed" ); ?>

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

    - MPesa Receipt Number

    '; ?> + MPesa Receipt Number

    '; ?>

    Set Order(Payment) Status

    update_status(strip_tags($order_status)); - - if($order_note !== ""){ - $order->add_order_note(__(strip_tags($order_note))); + 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']); + + update_post_meta($post_id, '_customer', strip_tags($customer)); + update_post_meta($post_id, '_phone', strip_tags($phone)); + update_post_meta($post_id, '_order_id', strip_tags($order_id)); + update_post_meta($post_id, '_amount', strip_tags($amount)); + update_post_meta($post_id, '_paid', strip_tags($paid)); + update_post_meta($post_id, '_balance', strip_tags($amount - $paid)); + update_post_meta($post_id, '_receipt', strip_tags($receipt)); + update_post_meta($post_id, '_order_status', strip_tags($order_status)); + + if (wc_get_order($order_id !== false)) { + $order = new \WC_Order($order_id); + $order->update_status(strip_tags($order_status)); + + if ($order_note !== "") { + $order->add_order_note(__(strip_tags($order_note))); + } } } } } -} \ No newline at end of file diff --git a/src/Post/Types/B2C.php b/src/Post/Types/B2C.php index c44c965..6515333 100755 --- a/src/Post/Types/B2C.php +++ b/src/Post/Types/B2C.php @@ -1,5 +1,7 @@ _x('Business-Customer Payments/Refunds', 'Disbursement/Refund General Name', 'woocommerce'), @@ -48,27 +48,27 @@ public static function b2c_payments_post_type() { 'filter_items_list' => __('Filter payments list', 'woocommerce'), ); - $supports = ( get_option('woocommerce_mpesa_settings')["env"] == 'live') ? array('revisions') : array('revisions', 'editor'); - + $supports = (get_option('woocommerce_mpesa_settings')["env"] == 'live') ? array('revisions') : array('revisions', 'editor'); + $args = array( - 'label' => __('Disbursement/Refund', 'woocommerce'), - 'description' => __('Disbursement/Refund Description', 'woocommerce'), - 'labels' => $labels, - 'supports' => $supports, - 'taxonomies' => array(), - 'hierarchical' => false, - 'public' => false, - 'show_ui' => true, - 'show_in_rest' => true, - 'show_in_menu' => false, - 'show_in_admin_bar' => false, - 'show_in_nav_menus' => false, - 'can_export' => true, - 'has_archive' => false, - 'exclude_from_search' => true, - 'publicly_queryable' => false, - 'capability_type' => 'page', - 'rewrite' => false, + 'label' => __('Disbursement/Refund', 'woocommerce'), + 'description' => __('Disbursement/Refund Description', 'woocommerce'), + 'labels' => $labels, + 'supports' => $supports, + 'taxonomies' => array(), + 'hierarchical' => false, + 'public' => false, + 'show_ui' => true, + 'show_in_rest' => true, + 'show_in_menu' => false, + 'show_in_admin_bar' => false, + 'show_in_nav_menus' => false, + 'can_export' => true, + 'has_archive' => false, + 'exclude_from_search' => true, + 'publicly_queryable' => false, + 'capability_type' => 'page', + 'rewrite' => false, ); register_post_type('b2c_payment', $args); @@ -77,33 +77,34 @@ public static function b2c_payments_post_type() { /** * A filter to add custom columns and remove built-in * columns from the edit.php screen. - * + * * @access public * @param array $columns The existing columns * @return array $filtered_columns The filtered columns */ public static function filter_b2c_payments_table_columns($columns) { - $columns['title'] = "Type"; - $columns['customer'] = "Customer"; - $columns['amount'] = "Amount"; - $columns['paid'] = "Paid"; - $columns['balance'] = "Balance"; - $columns['request'] = "Request"; - $columns['receipt'] = "Receipt"; - $columns['status'] = "Status"; + $columns['title'] = "Type"; + $columns['customer'] = "Customer"; + $columns['amount'] = "Amount"; + $columns['paid'] = "Paid"; + $columns['balance'] = "Balance"; + $columns['request'] = "Request"; + $columns['receipt'] = "Receipt"; + $columns['status'] = "Status"; + unset($columns['date']); return $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 */ - function b2c_payments_table_column_content($column_id, $post_id) + public function b2c_payments_table_column_content($column_id, $post_id) { $order_id = get_post_meta($post_id, '_order_id', true); switch ($column_id) { @@ -134,34 +135,34 @@ function b2c_payments_table_column_content($column_id, $post_id) case 'status': $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" - ); - - echo ($value = get_post_meta($post_id, '_order_status', true)) ? ''.esc_attr($statuses[$value]).'') : 'Set Status'; + "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'; break; } } /** * Make custom columns sortable. - * + * * @access public * @param array $columns The original columns * @return array $columns The filtered columns */ - public static function b2c_payments_columns_sortable($columns) + public static function b2c_payments_columns_sortable($columns) { - $columns['title'] = "Type"; + $columns['title'] = "Type"; $columns['customer'] = "Customer"; - $columns['paid'] = "Paid"; - $columns['balance'] = "Balance"; - $columns['receipt'] = "Receipt"; - $columns['status'] = "Status"; + $columns['paid'] = "Paid"; + $columns['balance'] = "Balance"; + $columns['receipt'] = "Receipt"; + $columns['status'] = "Status"; + return $columns; } - -} \ No newline at end of file +} diff --git a/src/Post/Types/C2B.php b/src/Post/Types/C2B.php index b88a7ce..19048e7 100755 --- a/src/Post/Types/C2B.php +++ b/src/Post/Types/C2B.php @@ -1,5 +1,7 @@ _x('Payments', 'Payment General Name', 'woocommerce'), @@ -140,9 +138,9 @@ public static function mpesaipn_table_column_content($column_id, $post_id) "failed" => "This Order Failed" ); - echo ($value = get_post_meta($post_id, '_order_status', true)) - ? ''.esc_attr($statuses[$value]).'') - : 'Set Status'; + echo ($value = get_post_meta($post_id, '_order_status', true)) + ? '' . esc_attr($statuses[$value]) . '') + : 'Set Status'; break; } } @@ -154,13 +152,14 @@ public static function mpesaipn_table_column_content($column_id, $post_id) * @param array $columns The original columns * @return array $columns The filtered columns */ - public static function mpesaipn_columns_sortable($columns) + public static function mpesaipn_columns_sortable($columns) { $columns['title'] = "Type"; $columns['customer'] = "Customer"; $columns['reference'] = "Reference"; $columns['receipt'] = "Receipt"; $columns['status'] = "Status"; + return $columns; - } -} \ No newline at end of file + } +} diff --git a/updates.json b/updates.json index fe80470..33c5bd5 100644 --- a/updates.json +++ b/updates.json @@ -1,12 +1,12 @@ { "name": "Mpesa for Woocommerce", - "version": "1.20.55", - "download_url": "https://github.com/osenco/osen-wc-mpesa/archive/v1.20.55.zip", + "version": "1.20.56", + "download_url": "https://github.com/osenco/osen-wc-mpesa/archive/v1.20.56.zip", "homepage": "https://wc-mpesa.osen.co.ke/", "requires": "4.5", "tested": "5.4", - "last_updated": "2020-05-01 16:17:00", + "last_updated": "2020-05-24 16:17:00", "upgrade_notice": "Autoupdates from here on", "author": "Osen Concepts",