2020-07-22 15:52:52 +00:00
< ? php
if ( ! defined ( 'ABSPATH' )) {
return ;
}
if ( ! class_exists ( 'WC_Gateway_Invite_FPS_Payment_Gateway' ) ){
class WC_Gateway_Invite_FPS_Payment_Gateway extends WC_Payment_Gateway {
public function __construct () {
$this -> id = ITS_WPF_PLUGIN_ID ;
$this -> icon = plugins_url ( 'assets/fps.png' , __FILE__ );
$this -> has_fields = true ;
$this -> method_title = __ ( 'Hong Kong Faster Payment System (FPS)' , ITS_WPF_PLUGIN_ID );
$this -> method_description = __ ( " Hong Kong interbank real time transfer using account holder ids and QR codes. " , ITS_WPF_PLUGIN_ID );
$this -> supports = array (
'products'
);
$this -> init_form_fields ();
$this -> init_settings ();
$this -> title = $this -> get_option ( 'title' );
$this -> description = $this -> get_option ( 'description' );
$this -> enabled = $this -> get_option ( 'enabled' );
$this -> account_id_type = $this -> get_option ( 'account_id_type' );
$this -> account_fps_id = $this -> get_option ( 'account_fps_id' );
$this -> account_bank_code = $this -> get_option ( 'account_bank_code' );
$this -> ask_to_pay = $this -> get_option ( 'ask_to_pay' );
$this -> fps_payment_reference_guide = $this -> get_option ( 'fps_payment_reference_guide' );
2020-09-07 02:47:08 +00:00
$this -> write_qr_code_to_file = $this -> get_option ( 'write_qr_code_to_file' );
2020-07-22 15:52:52 +00:00
add_action ( 'woocommerce_update_options_payment_gateways_' . $this -> id , array ( $this , 'process_admin_options' ) );
}
public function init_form_fields () {
$this -> form_fields = array (
'enabled' => array (
'title' => __ ( 'Enable/Disable' , ITS_WPF_PLUGIN_ID ),
'label' => __ ( 'Enable Hong Kong Faster Payment System' , ITS_WPF_PLUGIN_ID ),
'type' => 'checkbox' ,
'description' => '' ,
'default' => 'no'
),
'title' => array (
'title' => __ ( 'Title' , ITS_WPF_PLUGIN_ID ),
'type' => 'text' ,
'description' => __ ( 'This controls the title which the user sees during checkout.' , ITS_WPF_PLUGIN_ID ),
'default' => __ ( 'Hong Kong FPS' , ITS_WPF_PLUGIN_ID ),
'desc_tip' => true
),
'description' => array (
'title' => __ ( 'Description' , ITS_WPF_PLUGIN_ID ),
'type' => 'textarea' ,
'description' => __ ( 'This controls the description which the user sees during checkout.' , ITS_WPF_PLUGIN_ID ),
'default' => __ ( 'Pay with HK Faster Payment System (FPS). Scan the presented QR code with your bank\'s app or enter the payee FPS id.' , ITS_WPF_PLUGIN_ID ),
),
'account_id_type' => array (
'title' => __ ( 'Account Id Type' , ITS_WPF_PLUGIN_ID ),
'type' => 'select' ,
'options' => array (
'02' => __ ( 'FPS ID' , ITS_WPF_PLUGIN_ID ),
'03' => __ ( 'Mobile Phone Number' , ITS_WPF_PLUGIN_ID ),
'04' => __ ( 'Email Address' , ITS_WPF_PLUGIN_ID )
),
'default' => '02'
),
'account_fps_id' => array (
'title' => __ ( 'Account Id' , ITS_WPF_PLUGIN_ID ),
'type' => 'text' ,
2020-07-29 10:36:19 +00:00
'description' => __ ( 'E-mail address, phone number (+852-xxxxxxxx) or specific FPS id' , ITS_WPF_PLUGIN_ID ),
2020-07-22 15:52:52 +00:00
),
'account_bank_code' => array (
'title' => __ ( 'Bank Code' , ITS_WPF_PLUGIN_ID ),
'type' => 'text' ,
2020-08-31 10:17:41 +00:00
'description' => __ ( 'Three digit Hong Kong bank code.' , ITS_WPF_PLUGIN_ID )
2020-07-22 15:52:52 +00:00
),
'fps_payment_reference_guide' => array (
'title' => __ ( 'Payment Reference Guide' , ITS_WPF_PLUGIN_ID ),
'type' => 'textarea' ,
2020-11-20 08:05:04 +00:00
'default' => __ ( 'Please use the code below as a Message to Payee when initiating the transaction in your bank\'s app.' , ITS_WPF_PLUGIN_ID ),
2020-07-22 15:52:52 +00:00
'description' => __ ( 'Instructions visible to the customer for providing payment reference number after payment. This is not visble of Ask to Pay is active.' , ITS_WPF_PLUGIN_ID )
),
'ask_to_pay' => array (
'title' => __ ( 'Ask to Pay Enabled' , ITS_WPF_PLUGIN_ID ),
'label' => __ ( 'Ask to Pay Enabled' , ITS_WPF_PLUGIN_ID ),
'type' => 'checkbox' ,
'description' => __ ( 'The ask to pay function must be enabled by your bank in order to use payment reference numbers.' , ITS_WPF_PLUGIN_ID ),
'default' => 'no'
),
);
2020-08-31 10:17:41 +00:00
}
public function validate_text_field ( $key , $value ){
switch ( $key ){
case 'account_fps_id' :
$fps_id = trim ( $value );
2020-08-31 11:19:58 +00:00
switch ( $this -> get_option ( 'account_id_type' )){
2020-08-31 10:17:41 +00:00
case '03' :
if ( preg_match ( '/^\+852\-[0-9]{8}$/' , $fps_id ) ){
return $fps_id ;
} else {
function my_error_notice () {
?>
< div class = " error notice " >
< p >< ? php _e ( 'The account id must be a HK phone number formatted: +852-xxxxxxxx.' , ITS_WPF_PLUGIN_ID ); ?> </p>
</ div >
< ? php
}
add_action ( 'admin_notices' , 'my_error_notice' );
2020-08-31 11:19:58 +00:00
function alert_border_account_id (){
?>
< script language = " javascript " >
document . querySelector ( '#woocommerce_its_wpf_payment_gateway_account_fps_id' ) . style . borderColor = 'red' ;
</ script >
< ? php
}
add_action ( 'admin_footer' , 'alert_border_account_id' );
2020-08-31 10:17:41 +00:00
return $this -> account_fps_id ;
}
break ;
case '04' :
if ( preg_match ( '/^(?!(?:(?:\x22?\x5C[\x00-\x7E]\x22?)|(?:\x22?[^\x5C\x22]\x22?)){255,})(?!(?:(?:\x22?\x5C[\x00-\x7E]\x22?)|(?:\x22?[^\x5C\x22]\x22?)){65,}@)(?:(?:[\x21\x23-\x27\x2A\x2B\x2D\x2F-\x39\x3D\x3F\x5E-\x7E]+)|(?:\x22(?:[\x01-\x08\x0B\x0C\x0E-\x1F\x21\x23-\x5B\x5D-\x7F]|(?:\x5C[\x00-\x7F]))*\x22))(?:\.(?:(?:[\x21\x23-\x27\x2A\x2B\x2D\x2F-\x39\x3D\x3F\x5E-\x7E]+)|(?:\x22(?:[\x01-\x08\x0B\x0C\x0E-\x1F\x21\x23-\x5B\x5D-\x7F]|(?:\x5C[\x00-\x7F]))*\x22)))*@(?:(?:(?!.*[^.]{64,})(?:(?:(?:xn--)?[a-z0-9]+(?:-[a-z0-9]+)*\.){1,126}){1,}(?:(?:[a-z][a-z0-9]*)|(?:(?:xn--)[a-z0-9]+))(?:-[a-z0-9]+)*)|(?:\[(?:(?:IPv6:(?:(?:[a-f0-9]{1,4}(?::[a-f0-9]{1,4}){7})|(?:(?!(?:.*[a-f0-9][:\]]){7,})(?:[a-f0-9]{1,4}(?::[a-f0-9]{1,4}){0,5})?::(?:[a-f0-9]{1,4}(?::[a-f0-9]{1,4}){0,5})?)))|(?:(?:IPv6:(?:(?:[a-f0-9]{1,4}(?::[a-f0-9]{1,4}){5}:)|(?:(?!(?:.*[a-f0-9]:){5,})(?:[a-f0-9]{1,4}(?::[a-f0-9]{1,4}){0,3})?::(?:[a-f0-9]{1,4}(?::[a-f0-9]{1,4}){0,3}:)?)))?(?:(?:25[0-5])|(?:2[0-4][0-9])|(?:1[0-9]{2})|(?:[1-9]?[0-9]))(?:\.(?:(?:25[0-5])|(?:2[0-4][0-9])|(?:1[0-9]{2})|(?:[1-9]?[0-9]))){3}))\]))$/' , $fps_id )){
return $fps_id ;
} else {
function my_error_notice () {
?>
< div class = " error notice " >
< p >< ? php _e ( 'The account id must be a valid e-mail address' , ITS_WPF_PLUGIN_ID ); ?> </p>
</ div >
< ? php
}
add_action ( 'admin_notices' , 'my_error_notice' );
2020-08-31 11:19:58 +00:00
function alert_border_account_id (){
?>
< script language = " javascript " >
document . querySelector ( '#woocommerce_its_wpf_payment_gateway_account_fps_id' ) . style . borderColor = 'red' ;
</ script >
< ? php
}
add_action ( 'admin_footer' , 'alert_border_account_id' );
2020-08-31 10:17:41 +00:00
return $this -> account_fps_id ;
}
break ;
default :
return parent :: validate_text_field ( $key , $value );
break ;
}
break ;
case 'account_bank_code' :
$account = trim ( $value );
if ( preg_match ( '/^[0-9]{3}$/' , $account ) ){
return $account ;
} else {
function my_error_notice () {
?>
< div class = " error notice " >
2020-08-31 11:19:58 +00:00
2020-08-31 10:17:41 +00:00
< p >< ? php _e ( 'The bank code must consist of three digits, including leading zeros.' , ITS_WPF_PLUGIN_ID ); ?> </p>
</ div >
< ? php
}
add_action ( 'admin_notices' , 'my_error_notice' );
2020-08-31 11:19:58 +00:00
function alert_border_bank_code (){
?>
< script language = " javascript " >
document . querySelector ( '#woocommerce_its_wpf_payment_gateway_account_bank_code' ) . style . borderColor = 'red' ;
</ script >
< ? php
}
add_action ( 'admin_footer' , 'alert_border_bank_code' );
2020-08-31 10:17:41 +00:00
return $this -> account_bank_code ;
}
break ;
default :
return parent :: validate_text_field ( $key , $value );
break ;
}
2020-07-22 15:52:52 +00:00
}
private function fps_data ( $reference ){
global $woocommerce ;
$currency_code = get_woocommerce_currency ();
//echo $currency_code . '<br>';
$fps_currencies = array (
" HKD " => " 344 " ,
" CNY " => " 156 "
);
$fps_currency = $fps_currencies [ $currency_code ] ? ? null ;
if ( ! $fps_currency )
return null ;
$data = array (
" account " => $this -> account_id_type ,
" bank_code " => $this -> account_bank_code ,
" fps_id " => $this -> account_id_type === " 02 " ? $this -> account_fps_id : " " ,
" mobile " => $this -> account_id_type === " 03 " ? $this -> account_fps_id : " " ,
" email " => $this -> account_id_type === " 04 " ? $this -> account_fps_id : " " ,
" mcc " => " 0000 " ,
" curr " => $fps_currency ,
2020-08-31 07:23:54 +00:00
" amount " => $this -> get_order_total (),
2020-07-22 15:52:52 +00:00
" reference " => $this -> ask_to_pay === 'yes' ? $reference : " "
);
return $data ;
}
private function urlencode_array ( $array ){
$url = " " ;
$delimiter = " " ;
foreach ( $array as $key => $value ) {
if ( $value !== " " ){
$url .= $delimiter . $key . '=' . urlencode ( $value );
$delimiter = " & " ;
}
}
return $url ;
}
2020-09-07 02:47:08 +00:00
2020-12-24 08:39:34 +00:00
private function qrcode_img_data ( $data_string ){
/**
* Load the PHP QRcode library
*/
2020-09-07 02:47:08 +00:00
2020-12-24 08:39:34 +00:00
if ( ! class_exists ( 'QRtools' ) ){
require_once 'libs/phpqrcode.php' ;
2020-09-07 02:47:08 +00:00
}
2020-12-24 08:39:34 +00:00
$fp = fopen ( 'php://memory' , 'r+' );
QRCode :: png ( $data_string , $fp , QR_ECLEVEL_H );
rewind ( $fp );
$qrcode = stream_get_contents ( $fp );
return $qrcode ;
2020-09-07 02:47:08 +00:00
}
2020-07-22 15:52:52 +00:00
public function payment_fields () {
global $wp ;
$fps_ref_string = $wp -> query_vars [ 'order-pay' ] ? ? $this -> random_strings ( 5 );
$fps_data = $this -> fps_data ( $fps_ref_string );
2020-07-22 16:25:32 +00:00
2020-07-22 15:52:52 +00:00
if ( ! $fps_data ){
echo __ ( " This payment method is only available for HKD payments " , ITS_WPF_PLUGIN_ID );
return ;
}
2020-07-22 16:25:32 +00:00
$fps_data [ 'currency' ] = $fps_data [ 'curr' ];
$qrcode = new ITS_FPS_QRCodeData ( $fps_data );
2020-07-22 15:52:52 +00:00
2020-12-24 08:39:34 +00:00
$qr_code_img = $this -> qrcode_img_data ( $qrcode -> getDataString ());
2020-07-22 15:52:52 +00:00
if ( $this -> description ) {
echo wpautop ( wp_kses_post ( $this -> description ) );
}
echo '<fieldset id="wc-' . esc_attr ( $this -> id ) . '-cc-form" class="wc-credit-card-form wc-payment-form" style="background:transparent;">' ;
?>
< div class = " form-row form-row-wide " >
2020-08-31 10:17:41 +00:00
< ? php __ ( " FPS id: " , ITS_WPF_PLUGIN_ID ); ?> <strong><?php echo $this->account_fps_id ?></strong>
2020-07-22 15:52:52 +00:00
</ div >
< ? php
if ( $this -> ask_to_pay === 'no' ) { ?>
< div class = " form-row form-row-wide " >
< label > FPS Payment Reference < span class = " required " >*</ span >< br >< small >< ? php echo $this -> fps_payment_reference_guide ?> </small></label>
< input id = " its_wpf_payment_ref " name = " its_wpf_payment_ref " type = " text " autocomplete = " off " value = " <?php echo $fps_ref_string ?> " >
</ div >
< ? php
} else { ?>
< input id = " its_wpf_payment_ref " name = " its_wpf_payment_ref " type = " hidden " value = " <?php echo $fps_ref_string ?> " >
< ? php
}
?>
< div class = " form-row form-row-wide " style = " text-align: center; " >
2020-12-24 08:39:34 +00:00
< img style = " margin: 0 auto; " src = " data:image/png;base64,<?php echo base64_encode( $qr_code_img ); ?> " />
2020-07-22 15:52:52 +00:00
</ div >
< ? php
echo '<div class="clear"></div></fieldset>' ;
}
public function validate_fields () {
if ( empty ( $_POST [ 'its_wpf_payment_ref' ]) ) {
wc_add_notice ( __ ( 'Payment reference is required!' , ITS_WPF_PLUGIN_ID ), 'error' );
return false ;
} else {
$trimmed = preg_replace ( '/\s+/' , '' , sanitize_text_field ( $_POST [ 'its_wpf_payment_ref' ]) );
if ( strlen ( $trimmed ) === 0 ) {
wc_add_notice ( __ ( 'Invalid payment reference!' , ITS_WPF_PLUGIN_ID ), 'error' );
return false ;
}
}
return true ;
}
public function process_payment ( $order_id ) {
global $woocommerce ;
$order = new WC_Order ( $order_id );
$order -> update_status ( 'on-hold' , __ ( 'Awaiting manual confirmation of FPS payment.' , ITS_WPF_PLUGIN_ID ));
$order -> set_transaction_id ( sanitize_text_field ( $_POST [ 'its_wpf_payment_ref' ]));
$order -> save ();
$woocommerce -> cart -> empty_cart ();
return array (
'result' => 'success' ,
'redirect' => $this -> get_return_url ( $order )
);
}
private function random_strings ( $length_of_string ) {
// md5 the timestamps and returns substring
// of specified length
return substr ( md5 ( time ()), 0 , $length_of_string );
}
}
}