Files
formipay-public/includes/Payment/CashOnDelivery.php
2025-08-21 20:39:34 +07:00

581 lines
24 KiB
PHP
Raw Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

<?php
namespace Formipay\Payment;
use Formipay\Traits\SingletonTrait;
// Exit if accessed directly
if ( ! defined( 'ABSPATH' ) ) exit;
class CashOnDelivery extends Payment {
use SingletonTrait;
private $gateway = 'cod';
protected function __construct() {
parent::__construct();
add_filter( 'formipay/global-settings/tab:payment', [$this, 'add_settings'] );
add_filter( 'formipay/form-config/tab:payments', [$this, 'add_cod_setings'] );
add_filter( 'formipay/form-config/tab:payments/gateways', [$this, 'add_gateway'] );
add_filter( 'formipay/payment-list/cod/logo', [$this, 'set_frontend_logo'] );
add_filter( 'formipay/order/order-details', [$this, 'add_fee'], 999, 3 );
add_filter( 'formipay/order/payment-details/cod', [$this, 'render_payment_details'], 999, 4 );
add_action( 'template_redirect', [$this, 'check_parse_query'], 999 );
add_filter( 'formipay/thankyou/shortcodes', [$this, 'add_order_shortcodes'], 999, 4 );
add_action('wp_ajax_formipay_cod_confirmation', [$this, 'handle_formipay_cod_confirmation'] );
add_action('wp_ajax_nopriv_formipay_cod_confirmation', [$this, 'handle_formipay_cod_confirmation'] );
}
public function add_transaction($order_data){
return;
}
public function cancel_payment($order_id) {
return;
}
public function add_settings($settings) {
$cod = array(
$this->gateway.'_toggle' => array(
'type' => 'checkbox',
'label' => __('Activate Cash On Delivery', 'formipay'),
'submenu' => __( 'Cash On Delivery', 'formipay' )
),
$this->gateway.'_settings_group' => array(
'type' => 'group_title',
'label' => __( 'General', 'formipay' ),
'description' => __( 'Set the rule of Cash On Delivery', 'formipay' ),
'submenu' => __( 'Cash On Delivery', 'formipay' ),
'dependency' => array(
'key' => $this->gateway.'_toggle',
'value' => 'not_empty'
),
'group' => 'started'
),
$this->gateway.'_label' => array(
'type' => 'text',
'label' => __('Label', 'formipay'),
'value' => __( 'COD', 'formipay' ),
'submenu' => __( 'Cash On Delivery', 'formipay' ),
'dependency' => array(
'key' => $this->gateway.'_toggle',
'value' => 'not_empty'
)
),
$this->gateway.'_item_name' => array(
'type' => 'text',
'label' => __('Item Name', 'formipay'),
'value' => __( 'COD Fee', 'formipay' ),
'submenu' => __( 'Cash On Delivery', 'formipay' ),
'dependency' => array(
'key' => $this->gateway.'_toggle',
'value' => 'not_empty'
)
),
$this->gateway.'_icon' => array(
'type' => 'image',
'label' => __('Icon', 'formipay'),
'submenu' => __( 'Cash On Delivery', 'formipay' ),
'dependency' => array(
'key' => $this->gateway.'_toggle',
'value' => 'not_empty'
)
),
$this->gateway.'_fee_amount' => array(
'type' => 'number',
'label' => __('Fee Amount', 'formipay'),
'submenu' => __( 'Cash On Delivery', 'formipay' ),
'dependency' => array(
'key' => $this->gateway.'_toggle',
'value' => 'not_empty'
)
),
$this->gateway.'_fee_type' => array(
'type' => 'select',
'label' => __('Fee Type', 'formipay'),
'options' => array(
'fixed' => __( 'Fixed Amount', 'formipay' ),
'percentage' => __( 'Percentage', 'formipay' )
),
'submenu' => __( 'Cash On Delivery', 'formipay' ),
'dependency' => array(
'key' => $this->gateway.'_toggle',
'value' => 'not_empty'
),
'group' => 'ended'
),
$this->gateway.'_details_group' => array(
'type' => 'group_title',
'label' => __( 'Instruction', 'formipay' ),
'description' => __( 'Set instruction to buyer how to pay with COD method.', 'formipay' ),
'submenu' => __( 'Cash On Delivery', 'formipay' ),
'dependency' => array(
'key' => $this->gateway.'_toggle',
'value' => 'not_empty'
),
'group' => 'started'
),
$this->gateway.'_instruction_thankyou' => array(
'type' => 'tinymce',
'label' => __( 'Thankyou Screen', 'formipay' ),
'submenu' => __( 'Cash On Delivery', 'formipay' ),
'hints' => array(
'product_name' => __( 'Product Name', 'formipay' ),
'order_id' => __( 'Order ID', 'formipay' ),
'grand_total' => __( 'Order Total', 'formipay' ),
'confirmation_page_link' => __( 'Confirmation Page Link', 'formipay' )
),
'value' => '<p>Please prepare your cash of <span style="text-align: var(--bs-body-text-align);">{{grand_total}}&nbsp;</span><span style="text-align: var(--bs-body-text-align);">and pay it to the courier who delivers your&nbsp;</span>{{product_name}}.</p>',
'dependency' => array(
'key' => $this->gateway.'_toggle',
'value' => 'not_empty'
),
),
$this->gateway.'_instruction_whatsapp' => array(
'type' => 'hint_textarea',
'label' => __( 'WhatsApp Message', 'formipay' ),
'submenu' => __( 'Cash On Delivery', 'formipay' ),
'hints' => array(
'product_name' => __( 'Product Name', 'formipay' ),
'order_id' => __( 'Order ID', 'formipay' ),
'grand_total' => __( 'Order Total', 'formipay' ),
'confirmation_page_link' => __( 'Confirmation Page Link', 'formipay' )
),
'value' => 'Please prepare your cash of {{grand_total}} and pay it to the courier who delivers your {{product_name}}.',
'dependency' => array(
'key' => $this->gateway.'_toggle',
'value' => 'not_empty'
),
'group' => 'ended'
),
$this->gateway.'_confirmation_page_group' => array(
'type' => 'group_title',
'label' => __( 'Confirmation Page', 'formipay' ),
'description' => sprintf(
// translators: %s is the site URL.
__(
'<p>Set confirmation page for buyer to confirm that they have receive the package and pay the order to courier.</p>
<p>Confirmation magic URL: <code>%s/payment-confirm/cod/{{autogenerated_token}}</code></p>'
, 'formipay' ), site_url()),
'submenu' => __( 'Cash On Delivery', 'formipay' ),
'dependency' => array(
'key' => $this->gateway.'_toggle',
'value' => 'not_empty'
),
'group' => 'started'
),
$this->gateway.'_confirmation_page_content' => array(
'type' => 'tinymce',
'label' => __( 'Page Content', 'formipay' ),
'hints' => array(
'order_details' => __( 'Order Details', 'formipay' ),
'confirmation_form' => __( 'Confirmation Form', 'formipay' ),
),
'submenu' => __( 'Cash On Delivery', 'formipay' ),
'dependency' => array(
'key' => $this->gateway.'_toggle',
'value' => 'not_empty'
)
),
$this->gateway.'_confirmation_page_width' => array(
'type' => 'number',
'label' => __( 'Page Width', 'formipay' ),
'value' => '600',
'description' => __( 'in pixel (px)', 'formipay' ),
'submenu' => __( 'Cash On Delivery', 'formipay' ),
'dependency' => array(
'key' => $this->gateway.'_toggle',
'value' => 'not_empty'
)
),
$this->gateway.'_confirmation_table_alignment' => array(
'type' => 'radio',
'label' => __('Table Content Alignment', 'formipay'),
'value' => 'center',
'options' => array(
'left' => '<i class="bi bi-text-left"></i> Left',
'center' => '<i class="bi bi-text-center"></i> Center',
'right' => '<i class="bi bi-text-right"></i> Right',
),
'submenu' => __( 'Cash On Delivery', 'formipay' ),
'dependency' => array(
'key' => $this->gateway.'_toggle',
'value' => 'not_empty'
)
),
$this->gateway.'_confirmation_form_agreement' => array(
'type' => 'text',
'label' => __( 'Agreement', 'formipay' ),
'value' => __( 'I have receipt the package and pay as billed to the courier.', 'formipay' ),
'submenu' => __( 'Cash On Delivery', 'formipay' ),
'dependency' => array(
'key' => $this->gateway.'_toggle',
'value' => 'not_empty'
)
),
$this->gateway.'_confirmation_form_button' => array(
'type' => 'text',
'label' => __( 'Button Text', 'formipay' ),
'value' => __( 'Confirm', 'formipay' ),
'submenu' => __( 'Cash On Delivery', 'formipay' ),
'dependency' => array(
'key' => $this->gateway.'_toggle',
'value' => 'not_empty'
),
'group' => 'ended',
)
);
foreach($cod as $key => $value){
$settings[$key] = $value;
}
return $settings;
}
public function add_cod_setings($fields) {
$cod_settings = array(
$this->gateway.'_confirmation_notice_message_group' => array(
'type' => 'group_title',
'label' => __( 'Confirmation Notice Messages', 'formipay' ),
'description' => __( 'Set notice message on every condition about attempting to confirm the payment', 'formipay' ),
'submenu' => __( 'COD', 'formipay' ),
'group' => 'started'
),
$this->gateway.'_confirmation_update_to_status' => array(
'type' => 'select',
'label' => __( 'Change status order to', 'formipay' ),
'options' => formipay_order_status_list(),
'value' => 'payment-confirm',
'submenu' => __( 'COD', 'formipay' ),
),
$this->gateway.'_confirmation_message_success' => array(
'type' => 'hint_textarea',
'label' => __( 'Successfully Confirmed Message', 'formipay' ),
'hints' => array(
'order_id' => __('Order ID', 'formipay')
),
'value' => __('Successfully confirmed COD #{{order_id}}', 'formipay'),
'description' => __('When successfully change the order status to the preferred one', 'formipay'),
'submenu' => __( 'COD', 'formipay' ),
),
$this->gateway.'_confirmation_message_already_confirmed' => array(
'type' => 'hint_textarea',
'label' => __( 'Has Been Confirmed Message', 'formipay' ),
'hints' => array(
'order_id' => __('Order ID', 'formipay')
),
'value' => __('#{{order_id}} has been confirmed', 'formipay'),
'description' => __('When the order status has been the preferred one', 'formipay'),
'submenu' => __( 'COD', 'formipay' ),
),
$this->gateway.'_confirmation_message_error' => array(
'type' => 'hint_textarea',
'label' => __( 'Failed to Confirm Message', 'formipay' ),
'hints' => array(
'order_id' => __('Order ID', 'formipay'),
'system_error_message' => __('System Error Message', 'formipay')
),
'value' => __('Failed to proceed. Error: {{system_error_message}}', 'formipay'),
'description' => __('When error to change the order status to the preferred one', 'formipay'),
'submenu' => __( 'COD', 'formipay' ),
'group' => 'ended'
)
);
foreach($cod_settings as $key => $value){
$fields[$key] = $value;
}
return $fields;
}
public function add_gateway($gateways) {
$formipay_settings = get_option('formipay_settings');
if(isset($formipay_settings['cod_toggle']) && false !== $formipay_settings['cod_toggle']){
// $gateways['cod'] = __('Cash On Delivery', 'formipay');
$gateways[] = [
'id' => $this->gateway,
'gateway' => __( 'COD', 'formipay' ),
];
}
return $gateways;
}
public function set_frontend_logo($logo){
if($logo == false){
$logo = FORMIPAY_URL . 'public/assets/img/cod_default_icon.png';
}
return $logo;
}
public function add_fee($details, $form_id, $order_data){
if($order_data['payment_gateway'] == 'cod'){
$formipay_settings = get_option('formipay_settings');
$fee_amount = $formipay_settings['cod_fee_amount'];
$fee_type = $formipay_settings['cod_fee_type'];
if($fee_type == 'percentage'){
$grand_total = 0;
if(!empty($details)){
foreach($details as $detail){
$grand_total += $detail['subtotal'];
}
}
$fee_amount = $grand_total * floatval($fee_amount) / 100;
}
$details[] = [
'item' => $formipay_settings['cod_item_name'],
'amount' => $fee_amount,
'subtotal' => $fee_amount
];
}
return $details;
}
public function render_payment_details($render, $form_id, $order_data, $submit_action_type) {
if($order_data['payment_gateway'] == 'cod'){
$render = '';
$formipay_settings = get_option('formipay_settings');
$render .= ($submit_action_type == 'thankyou') ? '<div class="cod-instruction" style="text-align:'.formipay_get_post_meta($form_id, 'thankyou_screen_table_alignment').';">' : '';
$replacements = [
'{{product_name}}' => get_the_title($form_id),
'{{order_id}}' => $order_data['id'],
'{{grand_total}}' => formipay_price_format($order_data['total'], $form_id),
'{{confirmation_page_link}}' => site_url('/payment-confirm/'.$this->gateway.'/'.base64_encode($form_id.':::'.$order_data['id']))
];
$render .= strtr( $formipay_settings['cod_instruction_'.$submit_action_type], $replacements );
$render .= ($submit_action_type == 'thankyou') ? '</div>' : '';
}
return $render;
}
public function check_parse_query() {
global $wp_query;
$formipay_settings = get_option('formipay_settings');
if(is_admin()) :
return;
endif;
if(
!is_admin() &&
is_array($wp_query->query) &&
array_key_exists('formipay-payment-confirm', $wp_query->query) &&
true === boolval($wp_query->query['formipay-payment-confirm']) &&
array_key_exists('gateway', $wp_query->query) &&
'cod' === $wp_query->query['gateway']
) :
$token = explode(':::', base64_decode($wp_query->query['formipay-token']));
$form_id = $token[0];
$order_id = $token[1];
$thankyou_slug = 'thankyou';
if(!empty($formipay_settings['thankyou_link'])){
$thankyou_slug = $formipay_settings['thankyou_link'];
}
$order = formipay_get_order($order_id);
if($order['payment_gateway'] !== 'cod'){
wp_safe_redirect( site_url('/'.$thankyou_slug.'/'.$wp_query->query['formipay-token']) );
}
$button_background_color = json_decode(formipay_get_post_meta($form_id, 'button_bg_color'), true );
$button_text_color = json_decode(formipay_get_post_meta($form_id, 'button_text_color'), true );
$button_border_color = json_decode( formipay_get_post_meta($form_id, 'button_border_color'), true );
get_header();
?>
<style>
body {
--formipay-confirmation-page-width: <?php echo esc_html($formipay_settings[$this->gateway.'_confirmation_page_width']); ?>px;
--formipay-confirmation-page-table-alignment: <?php echo esc_html($formipay_settings[$this->gateway.'_confirmation_table_alignment']) ?>;
--formipay-button-submit-bg-color: <?php echo esc_html($button_background_color['regular']) ?? '#000000'; ?>;
--formipay-button-submit-bg-color-hover: <?php echo esc_html($button_background_color['hover']) ?? '#ffffff'; ?>;
--formipay-button-submit-bg-color-active: <?php echo esc_html($button_background_color['active']) ?? '#ffffff'; ?>;
--formipay-button-submit-text-color: <?php echo esc_html($button_text_color['regular']) ?? '#ffffff'; ?>;
--formipay-button-submit-text-color-hover: <?php echo esc_html($button_text_color['hover']) ?? '#000000'; ?>;
--formipay-button-submit-text-color-active: <?php echo esc_html($button_text_color['active']) ?? '#000000'; ?>;
--formipay-button-submit-border-color: <?php echo esc_html($button_border_color['regular']) ?? '#000000;' ?>;
--formipay-button-submit-border-color-hover: <?php echo esc_html($button_border_color['hover']) ?? '#ffffff'; ?>;
--formipay-button-submit-border-color-active: <?php echo esc_html($button_border_color['active']) ?? '#ffffff'; ?>;
}
</style>
<div class="formipay-container">
<div class="formipay-content-wrapper">
<?php
echo wp_kses_post(str_replace(
[
'{{order_details}}',
'{{confirmation_form}}'
],
[
$this->render_order_details_table($form_id, $order_id),
$this->render_confirmation_form($form_id, $order_id)
],
$formipay_settings[$this->gateway.'_confirmation_page_content']
))
?>
</div>
</div>
<?php
get_footer();
exit;
endif;
}
public function render_confirmation_form($form_id, $order_id){
$formipay_settings = get_option( 'formipay_settings' );
$order = formipay_get_order($order_id);
ob_start();
if($order['status'] == 'on-hold') {
?>
<form id="formipay-cod-confirmation">
<input type="hidden" id="form_id" value="<?php echo intval($form_id); ?>">
<input type="hidden" id="order_id" value="<?php echo intval($order_id); ?>">
<?php wp_nonce_field('formipay_cod_confirmation', 'formipay_nonce'); ?>
<div class="formipay-agreement">
<input id="cod_agreement" type="checkbox" class="formipay-input">
<label for="cod_agreement"><?php echo esc_html($formipay_settings['cod_confirmation_form_agreement']); ?></label>
</div>
<div class="formipay-button-wrapper">
<button type="button" id="confirm-cod-order" class="formipay-submit-button" disabled><?php echo esc_html($formipay_settings['cod_confirmation_form_button']); ?></button>
</div>
</form>
<?php
}
$content = ob_get_contents();
ob_end_clean();
return $content;
}
public function render_order_details_table($form_id, $order_id) {
ob_start();
?>
<table id="order-details">
<tbody>
<?php
$order = formipay_get_order($order_id);
if(false !== $order){
$items = maybe_unserialize($order['items']);
foreach($items as $item){
$label = ucwords(str_replace('_', ' ', $item['item']));
if(!in_array($label, ['payment', 'payment_gateway'])){
$qty = '';
if(isset($item['qty']) && !empty($item['qty'])){
$qty = ' × '.$item['qty'];
}
?>
<tr>
<th><?php echo esc_html($label) . esc_html($qty); ?></th>
<td><?php echo esc_html(formipay_price_format($item['subtotal'], $form_id)); ?></td>
</tr>
<?php
}
}
}
?>
<tr class="formipay-grand-total-row">
<th><?php echo esc_html__( 'Total', 'formipay' ); ?></th>
<td><?php echo esc_html(formipay_price_format($order['total'], $form_id)); ?></td>
</tr>
</tbody>
</table>
<?php
$content = ob_get_contents();
ob_end_clean();
return $content;
}
public function handle_formipay_cod_confirmation() {
// Check nonce
$nonce_valid = check_ajax_referer('formipay_cod_confirmation', 'formipay_nonce', false);
// Handle the valid nonce case
if ($nonce_valid) {
// Retrieve the data
$form_id = isset($_POST['form_id']) ? sanitize_text_field( wp_unslash($_POST['form_id']) ) : '';
$order_id = isset($_POST['order_id']) ? sanitize_text_field( wp_unslash($_POST['order_id']) ) : '';
$update = formipay_update_order_status([
'form_id' => $form_id,
'order_id' => $order_id,
'status' => 'payment-confirm',
'payment_gateway' => 'cod'
]);
wp_send_json( [
'success' => boolval($update['valid']),
'data' => [
'message' => $update['message'],
'icon' => (boolval($update['valid']) == true) ? 'success' : 'info'
]
] );
}
// Nonce is invalid, handle the error
wp_send_json_error([
'message' => 'Security check failed. Please try again.',
'icon' => 'error'
]);
}
public function add_order_shortcodes($shortcodes, $form_id, $order_data, $submit_action_type) {
if($order_data['payment_gateway'] == $this->gateway){
$confirmation_page_link = site_url('/payment-confirm/'.$this->gateway.'/'.base64_encode($form_id.':::'.$order_data['id']));
$shortcodes['payment_confirmation_form'] = '<a href="'.$confirmation_page_link.'" target="_blank">C.O.D Confirmation</a>';
}
return $shortcodes;
}
public function process_payment($order_data) {
return $order_data;
}
}