/*
* Plugin Name: PayXay - Payment gateway for Woocommerce
* Plugin URI: https://www.payxaf.com/plug-in/pauxaf-payment-gateway/
* Description: This plugin uses PayXaf API for mobile money payment systems.
* Author: Payxaf
* Author URI: https://www.payxaf.com/
* Version: 0.0.1
* License URL: http://www.gnu.org/licenses/gpl-2.0.txt
*/
/*
* This action hook registers our PHP class as a WooCommerce payment gateway
*/
/**
* Try to prevent direct access data leaks
*/
if (!defined('ABSPATH')) exit;
/**
* Check if WooCommerce is present and active
**/
if (!in_array('woocommerce/woocommerce.php', apply_filters('active_plugins', get_option('active_plugins')))) return;
/**
* Add Payxaf to WooCommerce available gateways
* @param array $gateways all available WooCommerce gateways
* @return array $gateways all WooCommerce gateways + Payxaf gateway
*/
function payxaf_add_to_woocommerce(array $gateways): array
{
$gateways[] = 'Payxaf_Woocommerce_Gateway';
return $gateways;
}
add_filter('woocommerce_payment_gateways', 'payxaf_add_to_woocommerce');
/**
* Called when the plugin loads
*/
function payxaf_gateway_init()
{
class Payxaf_Woocommerce_Gateway extends WC_Payment_Gateway
{
const ID = 'pay_xaf';
const API_URL = 'https://www.payxaf.com/';
const SERVER_IP = '15.236.140.89';
const CURRENCIES = ['XAF', 'EUR'];
const SUPPORTED_CURRENCIES = ['XAF' => 1, 'XOF' => 1, 'EUR' => 650, 'USD' => 550];
/**
* @var string
*/
private $public_key;
/**
* @var string
*/
private $secret_key;
/**
* @var string
*/
private $success_url;
/**
* @var bool
*/
private $autocomplete_orders;
/**
* Constructor for the gateway.
*/
public function __construct()
{
// The global ID for this Payment method
$this->id = self::ID;
// This basically defines your settings which are then loaded with init_settings()
$this->init_form_fields();
// After init_settings() is called, you can get the settings and load them into variables
$this->init_settings();
// Boolean. Can be set to true if you want payment fields to show on the checkout
$this->has_fields = false;
// Image to be displayed to the user
$image_url = $this->get_image_url();
// check if Payxaf icon image exists or not
if (@getimagesize($image_url)) {
//Show an image on the frontend
$this->icon = $image_url;
}
// Payment method name for order details and emails
$this->title = "Payxaf";
// Payment method name for admin pages
$this->method_title = "Payxaf - Payment Gateway for WooCommerce";
// The description for this Payment Gateway, shown on the actual Payment options page on the backend
$this->method_description = __(
"Secured payments made simple - designed exclusively for WooCommerce stores. Accept mtn mobile money, Orange money, credit cards, debit cards, and other popular payment methods. allows customers to conveniently checkout using our secure payment gateway",
self::ID
);
// Define user set variables
$this->order_button_text = $this->get_option('order_button_text');
$this->description = $this->get_option('description');
$this->public_key = $this->get_option('public_key');
$this->secret_key = $this->get_option('secret_key');
$this->success_url = $this->get_option('success_url');
$this->autocomplete_orders = $this->get_option('autocomplete_orders') === 'yes';
// Used to perform plugin information updated by the admin
add_action('woocommerce_update_options_payment_gateways_' . $this->id, [$this, 'process_admin_options']);
}
/**
* Generates a callback url only once
*/
private function generate_success_url()
{
if (!$this->get_option('success_url')) {
$this->update_option(
'success_url',
get_home_url() . '/wp-json/callback/' . md5(uniqid() . mt_rand())
);
}
}
/**
* Image to be displayed to the user
*/
private function get_test_mode(): string
{
$test_mode = $this->get_option('test_mode');
$url = '';
if ($test_mode === 'sand_box')
$url = 'https://app.payxaf.com/sandbox/payment/initiate';
else if ($test_mode === 'live')
$url = 'https://app.payxaf.com/payment/initiate';
return $url;
}
/**
* Image to be displayed to the user
*/
private function get_checkout_theme(): string
{
$checkout_theme = $this->get_option('dark');
$theme = '';
if ($checkout_theme === 'dark')
$theme = 'dark';
else if ($checkout_theme === 'light')
$theme = 'light';
return $theme;
}
/**
* Image to be displayed to the user
*/
private function get_image_url(): string
{
$payment_methods = $this->get_option('payment_methods');
$image = 'payxaf_operators.png';
if ($payment_methods === 'mobile')
$image = 'payxaf_momo_om.png';
else if ($payment_methods === 'credit_card')
$image = 'payxaf_visa_master.png';
return WP_PLUGIN_URL . '/' . plugin_basename(dirname(__FILE__)) . '/images/' . $image;
}
/**
* Initializes gateway settings form
*/
public function init_form_fields()
{
// Generate a callback url
$this->generate_success_url();
$this->form_fields = apply_filters(
'payxaf_form_fields',
[
'enabled' => [
'title' => __('Enable/Disable', self::ID),
'type' => 'checkbox',
'label' => __('Enable Payxaf', self::ID),
'description' => __('Check to enable this plugin', self::ID),
'default' => 'yes',
'desc_tip' => true,
],
'test_mode' => [
'title' => __('Enabled live or test environment', self::ID),
'type' => 'select',
'description' => __('Use this payment gateway in test/sandbox mode, when testing the plugin. The tesing credentials are: Test Mode eMail: test_mode@mail.com Test Mode Verification Code: 222666', self::ID),
'default' => "sandbox",
'options' => [
"sand_box" => __("Sandbox", self::ID),
"live" => __("Live", self::ID),
],
'desc_tip' => true,
],
'checkout_theme' => [
'title' => __('Select the the theme on the checkout of your shop.', self::ID),
'type' => 'select',
'description' => __('Choose either a dark or light theme for the checkout form.', self::ID),
'default' => "sandbox",
'options' => [
"sand_box" => __("Sandbox", self::ID),
"live" => __("Live", self::ID),
],
'desc_tip' => true,
],
'success_url' => [
'title' => __('Callback URL', self::ID),
'type' => 'hidden',
'description' => __('Copy the URL below and paste it in settings of your application in Payxaf
' . $this->get_option('success_url') . '
', self::ID),
],
'description' => [
'title' => __('Description', self::ID),
'type' => 'textarea',
'description' => __('Payment method description, visible by customers on your checkout page', self::ID),
'default' => __('Pay safely using Orange Money, MTN Mobile Money, VISA, MasterCard or Payxaf Wallet', self::ID),
'desc_tip' => true,
],
'public_key' => [
'title' => __('Public key', self::ID),
'type' => 'text',
'description' => __('Copy and paste the public key from your mechant account on Payxaf', self::ID),
'default' => '',
'desc_tip' => true,
],
'secret_key' => [
'title' => __('Secret key', self::ID),
'type' => 'text',
'description' => __('Copy and paste the secret key from your mechant account on Payxaf', self::ID),
'default' => '',
'desc_tip' => true,
],
'payment_methods' => [
'title' => __('Enabled payment methods', self::ID),
'type' => 'select',
'description' => __('This will change operators logos displayed on your checkout page', self::ID),
'default' => "all",
'options' => [
"all" => __("All", self::ID),
"mobile" => "Mobile Money (OM + MoMo)",
"credit_card" => __("Credit Card (VISA + MasterCard)", self::ID),
],
'desc_tip' => true,
],
'order_button_text' => [
'title' => __('Payment button text', self::ID),
'type' => 'text',
'description' => __('Text of the payment button on which customers click to make the payment', self::ID),
'default' => __('Pay with Payxaf', self::ID),
'desc_tip' => true,
],
'currency' => [
'title' => __('Payxaf currency', self::ID),
'type' => 'select',
'description' => __('This is the currency that your customers will see on payment page. If you choose Euro, only card payment will be available on payment page', self::ID),
'default' => "default",
'options' => [
"default" => __("Same as on WooCommerce", self::ID),
"XAF" => "CFA Franc (FCFA)",
"EUR" => __("Euro (€)", self::ID),
"USD" => __("Dollar ($)", self::ID),
],
'desc_tip' => true,
],
'autocomplete_orders' => array(
'title' => __('Autocomplete orders', self::ID),
'label' => __('Autocomplete orders on payment success', self::ID),
'type' => 'checkbox',
'description' => __('If enabled, orders statuses will go directly to complete after successful payment', self::ID),
'default' => 'no',
'desc_tip' => true,
),
]);
}
public function get_public_key(): string
{
return $this->public_key;
}
public function get_secret_key(): string
{
return $this->secret_key;
}
public function get_success_url(): string
{
return $this->success_url;
}
public function get_autocomplete_orders(): bool
{
return $this->autocomplete_orders;
}
/**
* Get order amount and currency for Payxaf
* @throws Exception
*/
private function get_order_amount_currency(WC_Order $order): array
{
$woocommerce_currency = get_woocommerce_currency();
// Throws an exception when currency is not defined in PAYXAF_CURRENCIES
if (!isset(self::SUPPORTED_CURRENCIES[$woocommerce_currency]))
throw new Exception("Currency '$woocommerce_currency' is not currently supported. Please, try using one of the following: " . implode(', ', array_keys(self::SUPPORTED_CURRENCIES)));
$currency = $this->get_option('currency');
if (!in_array($currency, self::CURRENCIES))
$currency = $woocommerce_currency;
$amount = $order->get_total();
if ($currency !== $woocommerce_currency)
$amount *= self::SUPPORTED_CURRENCIES[$woocommerce_currency] / self::SUPPORTED_CURRENCIES[$currency];
return compact('amount', 'currency');
}
/**
* Checks if billing country is CM and billing phone is a valid Mobile Money phone
*/
private function is_order_from_cameroon(WC_Order $order): bool
{
return $order->get_billing_country() === 'CM'
&& preg_match(
'/^((\+|00)?237)?6[5789][0-9]{7}$/',
preg_replace('/[^0-9]/', '', $order->get_billing_phone()) // Ignore non numeric
);
}
/**
* Returns user's locale
*/
private function get_locale(): string
{
return strpos('fr_FR', get_locale()) != false ? 'fr' : 'en';
}
/**
* This function handles the processing of the order, telling WooCommerce
* what status the order should have and where customers go after it’s used.
*/
public function process_payment($order_id)
{
global $woocommerce;
$order = new WC_Order( $order_id );
// Mark as on-hold (we're awaiting the cheque)
$order->update_status('on-hold', __( 'Awaiting cheque payment', 'woocommerce' ));
//$order = wc_get_order($order_id);
/* try {
$order_desc = implode(
', ',
array_map(
function (WC_Order_Item $item) {
return $item->get_name();
},
$order->get_items()
)
); */
$amount_currency = $this->get_order_amount_currency($order);
$body = [
"transaction_amount" => $amount_currency['amount'],
"transaction_currency" => $amount_currency['currency'],
"transaction_reason" => substr($order_desc, 0, 255), // Get first 255 chars
"app_transaction_ref" => $order->get_order_key(),
"customer_name" => $order->get_formatted_billing_full_name(),
"customer_email" => $order->get_billing_email(),
"customer_lang" => $this->get_locale()
];
if ($this->is_order_from_cameroon($order))
$body['customer_phone_number'] = preg_replace('/[^0-9]/', '', $order->get_billing_phone()); // Ignore non numeric
$mode = get_test_mode(); //<------------ Change to TEST for test server, PROD for production-->
/* $parameters = [
'identifier' => $identifier,
'currency' => $currency,
'amount' => $amount,
'details' => $details,
'ipn_url' => $ipn_url,
'cancel_url' => $cancel_url,
'success_url' => $success_url,
'payxaf_public_key' => $payxaf_public_key,
'site_logo' => $site_logo,
'checkout_theme' => $checkout_theme,
'customer_name' => $customer_name,
'customer_email' => $customer_email,
];
*/
$url = get_test_mode();
// Get payment link from Payxaf
$result = wp_remote_post($url, array(
/* str_replace('{public_key}', $this->public_key, self::API_URL),
["body" => $body, "sslverify" => false] */ //byme
// Passing variables from form page
$identifier = uniqid(),
$payxaf_public_key = "get_public_key()",
$site_logo= "https://app.payxaf.com/assets/images/logoIcon/logo.png",
$checkout_theme = "get_checkout_theme()",
$currency = $this->get_option('currency'),
$amount = $this->get_option('amount'),
$details = "testing",
$ipn_url = "www.one.com",
$cancel_url = "www.two.com",
$success_url = "www.three.com",
$customer_name = $order->get_formatted_billing_full_name(),
$customer_email = $order->get_billing_email(),
));
if(!is_wp_error($result))
{
$response_body = wp_remote_retrieve_body($result);
$resp_array = json_decode($response_body);
if(isset($resp_array->status))
return $resp_array->status;
if(!isset($resp_array->status) && isset($resp_array->message))
return; //wc_add_notice( $resp_array->message, 'error' ); by me
}
else
wc_add_notice( 'Failed to initiate transaction please try again later', 'error' );
}
/*
$ch = curl_init();
curl_setopt($ch, CURLOPT_SSL_VERIFYHOST, false);
curl_setopt($ch, CURLOPT_URL, $url);
curl_setopt($ch, CURLOPT_POSTFIELDS, $parameters);
curl_setopt($ch, CURLOPT_RETURNTRANSFER, true);
$result = curl_exec($ch);
curl_close($ch); */
//$result contains the response back.
//echo $result;
/*$_SESSION['result'] = $result;
$data = json_decode($result, false);
$success = $data->success;
$_SESSION['success'] = $success;
$_SESSION['details'] = $details;
$_SESSION['identifier'] = $identifier;
$_SESSION['currency'] = $currency;
$_SESSION['amount'] = $amount; */
//echo $success;
//echo $details;
// $data = json_decode( $resul, false);
// $success = $data->success;
// header("Location: $data->url");
// echo $result;
// Get raw response
/// $raw_response = wp_remote_retrieve_body($result);
// Parse response
/* $response = json_decode($raw_response, true);
if (!(isset($response["success"]) && $response["success"] === "ok")) {
throw new Exception($response["message"] ?? "An error has occurred. Please try again later");
} else { /*
$order->set_transaction_id($response['message']);
$order->add_order_note('Payxaf payment initiated with reference: ' . $response['message']);
// Clear cart
WC()->cart->empty_cart();
return [
'result' => 'success',
'redirect' => $response['payment_url']
]; */
} /* catch (Exception $ex) {
$order->add_order_note("Payxaf payment init failed with message: " . $ex->getMessage());
wc_add_notice(__('Payment error : ', 'woothemes') . $ex->getMessage(), 'error');
if (isset($result)) {
payxaf_log_data('Request <-----');
payxaf_log_data($result);
}
if (isset($raw_response)) {
payxaf_log_data('Raw response <-----');
payxaf_log_data($raw_response);
}
if (isset($response)) {
payxaf_log_data('Response <-----');
payxaf_log_data($response);
}
return;
} */
}
// }
/* ============================================ INCLUDE OTHER FILE =========================================== */
// including the callback
include 'include/payxaf_callback.php';
// including the order_key in wc admin order list
include 'include/payxaf_hooks.php';
/*=========================================================================================================== */
//}
add_action('plugins_loaded', 'payxaf_gateway_init', 0);
How to become a full stack developer? – OCASET – Online Centre for Art Sciences Engineering and Technology
Full Stack Development – This might sound a bit overwhelming but it’s not. If you would have searched for this term recently – you must have read the terms like HTML, CSS, PHP and MySQL. Full Stack Developers are jack of all trades of the industry where comprehensive programming knowledge is demanded.
A full-stack developer is a software expert who is qualified and skilled to work on both the front end (which users see) and back end (behind the applications) of websites and mobile applications. The front-end refers to the visible part of the application with which users interact (user interface) and the back-end is where all the actual functioning of the system happens. The combination of front-end and back-end is called the Full Stack. This means full stack developers can be considered as software experts who are equally proficient in front-end (client-side) as well as back-end (server-side) development for online applications. Full Stack Developers have strong skill sets and knowledge bases in the IT domain. They are highly valued by both large companies and small startups.
Let’s explore more about how to become a full stack developer?
To become a full-stack developer, one has to be familiar with two basic web development concepts. The front-end, also known as the client-side, refers to all the elements of an online application that users directly interact with. Whereas the back-end comprises the entire programming and structure that can compute and analyze data, fulfill user response, and handle real-time information.
Full-stack developers are expected to be multi-taskers in the sense that they are professionals capable of addressing both the front-end and back-end of web applications. As a part of front-end development, they optimize the visible parts to design a user-friendly and engaging site. On the other hand, in the back-end, they build the structure of internal software that handles databases, servers, and specific software. Full-stack developers make the front-end of applications visually appealing and easily accessible by users, while continuously working on the server-side of the application and exchanging information between the browser and back-end databases to refine and update for better performance. A person who is a full-stack developer is responsible for the development and functioning of a site or application’s front-end and back-end architecture.
Full-stack developers need to have special technical knowledge for combining various components into a packaged application that goes into the making of a software product. They know the functionality of each tool and can manipulate the back-end components accordingly to produce desired results at the front-end. Full-stack developers contribute to the overall quality of the software application and are therefore considered as unparalleled assets in a technical team. The full stack developer job description in an organization generally includes:
Working with a website design from start to completion
Developing and updating features of websites along with user interface teams
Designing better user interactions through robust front-end architecture
Managing database, server administration, and Application Programming Interface
Communicating with end-users to evaluate product responsiveness
Some key technical responsibilities for an entry-level to experienced full stack developer include studying project requirements and creating solutions by working on databases and servers and using the methodical testing process to debug and modify codes for problem-solving.
Full Stack Development Courses
Full-stack developers need to learn basic design and database management skills and must have knowledge of programming languages. Many full-stack web development courses help aspiring candidates to learn necessary skills and significantly increase their chances of getting hired by a reputed company. Four-year degree programs have proved to be one of the most beneficial paths for aspiring developers. These courses provide comprehensive knowledge and a broad view that enhances the competency of professionals. Additionally, it allows building an impressive portfolio, receiving internships, and improving valuable connections. There are a lot of online courses to provide knowledge about the latest in web application development and keep them updated. These online courses offer classes, tutorials and certifications as per the requirement of working professionals. The courses focus on teaching the most updated technologies through project-based learning.
Knowledge of Web Architecture
Full Stack Developers must have a thorough knowledge of web architecture. Their primary responsibility is to work with software applications from scratch and develop them into a structured form. For this, they need to know how to structure the code, categorize the data in databases, and perform the necessary computational tasks. The web application architecture is a highly responsive medium that facilitates communication between different users and technical interaction between different systems. The full-stack developers apply knowledge of web architecture to design software modules as well as promotion and commercialization of the web application.
Salary of a Full Stack Developer
In recent years, the role of the full-stack developer has become significantly important. Employers understand the benefits of having a full stack developer in their team who has an effective contribution to a project for successful implementation. Because of the demand, the full stack developer salary in Cameroon is quite high. Full-stack developers in Cameroon earn an average salary of around 6,000,000FCFA per annum. At the entry-level, the salary starts with around 2,400,000FCFA per annum. An employee with mid-level experience can secure a yearly package of about 4,000,000FCFA.