fix: resolve all Week 2 performance & security issues (F1.10–F1.19)
Security:
- Replace maybe_serialize() in cookies with json_encode() (PHP object injection fix)
- Add PayPal webhook signature verification
- Add current_user_can('manage_options') to all 18 admin-ajax handlers
Performance:
- Remove flush_rewrite_rules() from init hooks (Thankyou + Payment)
- Add activation/deactivation hooks for flush_rewrite_rules
- Cache currency, country, flags JSON reads in static variables
- Add server-side pagination to Customer::formipay_tabledata_customers()
- Optimize Order::formipay_tabledata_orders() with COUNT(*) GROUP BY
Cleanup:
- Delete Paypal.phpbak backup file
- Fix timezone hardcode Asia/Jakarta → wp_timezone_string()
- Create uninstall.php for proper cleanup on uninstall
Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com>
This commit is contained in:
@@ -26,11 +26,13 @@ function formipay_field_type_collection() {
|
|||||||
}
|
}
|
||||||
|
|
||||||
function formipay_currency_array() {
|
function formipay_currency_array() {
|
||||||
|
static $cache = null;
|
||||||
|
if ($cache !== null) {
|
||||||
|
return $cache;
|
||||||
|
}
|
||||||
$json = file_get_contents(FORMIPAY_PATH . 'admin/assets/json/currencies.json');
|
$json = file_get_contents(FORMIPAY_PATH . 'admin/assets/json/currencies.json');
|
||||||
$array = json_decode($json, true);
|
$cache = json_decode($json, true);
|
||||||
return $array;
|
return $cache;
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
function formipay_is_multi_currency_active() {
|
function formipay_is_multi_currency_active() {
|
||||||
@@ -146,22 +148,26 @@ function get_global_currency_array() {
|
|||||||
}
|
}
|
||||||
|
|
||||||
function formipay_country_array() {
|
function formipay_country_array() {
|
||||||
|
static $cache = null;
|
||||||
|
if ($cache !== null) {
|
||||||
|
return $cache;
|
||||||
|
}
|
||||||
$json = file_get_contents(FORMIPAY_PATH . 'admin/assets/json/country.json');
|
$json = file_get_contents(FORMIPAY_PATH . 'admin/assets/json/country.json');
|
||||||
$array = json_decode($json, true);
|
$cache = json_decode($json, true);
|
||||||
return $array;
|
return $cache;
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
function formipay_get_flag_by_currency($currency) {
|
function formipay_get_flag_by_currency($currency) {
|
||||||
|
static $flags = null;
|
||||||
if(strpos($currency, ':::')){
|
if(strpos($currency, ':::')){
|
||||||
$currency = explode(':::', $currency);
|
$currency = explode(':::', $currency);
|
||||||
$currency = $currency[0];
|
$currency = $currency[0];
|
||||||
}
|
}
|
||||||
$json = file_get_contents(FORMIPAY_PATH . 'admin/assets/json/flags.json');
|
if ($flags === null) {
|
||||||
$array = json_decode($json, true);
|
$json = file_get_contents(FORMIPAY_PATH . 'admin/assets/json/flags.json');
|
||||||
foreach($array as $country){
|
$flags = json_decode($json, true);
|
||||||
|
}
|
||||||
|
foreach($flags as $country){
|
||||||
if($currency == $country['code']){
|
if($currency == $country['code']){
|
||||||
return $country['flag'];
|
return $country['flag'];
|
||||||
}
|
}
|
||||||
|
|||||||
14
formipay.php
14
formipay.php
@@ -50,6 +50,20 @@ spl_autoload_register(function ($class) {
|
|||||||
|
|
||||||
\Formipay\Init::get_instance();
|
\Formipay\Init::get_instance();
|
||||||
|
|
||||||
|
register_activation_hook( __FILE__, 'formipay_activate' );
|
||||||
|
function formipay_activate() {
|
||||||
|
// Instantiate singletons so rewrite rules get registered via init hooks
|
||||||
|
\Formipay\Thankyou::get_instance();
|
||||||
|
\Formipay\Integration\Paypal::get_instance();
|
||||||
|
\Formipay\Payment\BankTransfer::get_instance();
|
||||||
|
flush_rewrite_rules();
|
||||||
|
}
|
||||||
|
|
||||||
|
register_deactivation_hook( __FILE__, 'formipay_deactivate' );
|
||||||
|
function formipay_deactivate() {
|
||||||
|
flush_rewrite_rules();
|
||||||
|
}
|
||||||
|
|
||||||
// function formipay_add_defer_attribute($tag, $handle) {
|
// function formipay_add_defer_attribute($tag, $handle) {
|
||||||
// if ( 'product-details' === $handle ) {
|
// if ( 'product-details' === $handle ) {
|
||||||
// // Add defer attribute
|
// // Add defer attribute
|
||||||
|
|||||||
@@ -434,6 +434,10 @@ class Access {
|
|||||||
|
|
||||||
check_ajax_referer( 'formipay-admin-access-nonce', '_wpnonce' );
|
check_ajax_referer( 'formipay-admin-access-nonce', '_wpnonce' );
|
||||||
|
|
||||||
|
if ( ! current_user_can( 'manage_options' ) ) {
|
||||||
|
wp_send_json_error( [ 'message' => 'Unauthorized' ] );
|
||||||
|
}
|
||||||
|
|
||||||
$args = [
|
$args = [
|
||||||
'post_type' => 'formipay-access',
|
'post_type' => 'formipay-access',
|
||||||
'posts_per_page' => -1,
|
'posts_per_page' => -1,
|
||||||
@@ -524,6 +528,10 @@ class Access {
|
|||||||
|
|
||||||
check_ajax_referer( 'formipay-admin-access-nonce', 'nonce' );
|
check_ajax_referer( 'formipay-admin-access-nonce', 'nonce' );
|
||||||
|
|
||||||
|
if ( ! current_user_can( 'manage_options' ) ) {
|
||||||
|
wp_send_json_error( [ 'message' => 'Unauthorized' ] );
|
||||||
|
}
|
||||||
|
|
||||||
if (!isset($_POST['search']) || empty($_POST['search'])) {
|
if (!isset($_POST['search']) || empty($_POST['search'])) {
|
||||||
wp_send_json_error( __('No search term provided.', 'formipay') );
|
wp_send_json_error( __('No search term provided.', 'formipay') );
|
||||||
}
|
}
|
||||||
@@ -554,6 +562,10 @@ class Access {
|
|||||||
|
|
||||||
check_ajax_referer( 'formipay-admin-access-nonce', 'nonce' );
|
check_ajax_referer( 'formipay-admin-access-nonce', 'nonce' );
|
||||||
|
|
||||||
|
if ( ! current_user_can( 'manage_options' ) ) {
|
||||||
|
wp_send_json_error( [ 'message' => 'Unauthorized' ] );
|
||||||
|
}
|
||||||
|
|
||||||
if( !empty($_REQUEST['title']) ){
|
if( !empty($_REQUEST['title']) ){
|
||||||
$title = sanitize_text_field( wp_unslash($_REQUEST['title']) );
|
$title = sanitize_text_field( wp_unslash($_REQUEST['title']) );
|
||||||
$post_id = wp_insert_post( [
|
$post_id = wp_insert_post( [
|
||||||
@@ -582,6 +594,10 @@ class Access {
|
|||||||
|
|
||||||
check_ajax_referer( 'formipay-admin-access-nonce', 'nonce' );
|
check_ajax_referer( 'formipay-admin-access-nonce', 'nonce' );
|
||||||
|
|
||||||
|
if ( ! current_user_can( 'manage_options' ) ) {
|
||||||
|
wp_send_json_error( [ 'message' => 'Unauthorized' ] );
|
||||||
|
}
|
||||||
|
|
||||||
if( empty($_REQUEST['id']) ){
|
if( empty($_REQUEST['id']) ){
|
||||||
wp_send_json_error( [
|
wp_send_json_error( [
|
||||||
'title' => esc_html__( 'Failed', 'formipay' ),
|
'title' => esc_html__( 'Failed', 'formipay' ),
|
||||||
@@ -613,6 +629,10 @@ class Access {
|
|||||||
|
|
||||||
check_ajax_referer( 'formipay-admin-access-nonce', 'nonce' );
|
check_ajax_referer( 'formipay-admin-access-nonce', 'nonce' );
|
||||||
|
|
||||||
|
if ( ! current_user_can( 'manage_options' ) ) {
|
||||||
|
wp_send_json_error( [ 'message' => 'Unauthorized' ] );
|
||||||
|
}
|
||||||
|
|
||||||
if( empty($_REQUEST['ids']) ){
|
if( empty($_REQUEST['ids']) ){
|
||||||
wp_send_json_error( [
|
wp_send_json_error( [
|
||||||
'title' => esc_html__( 'Failed', 'formipay' ),
|
'title' => esc_html__( 'Failed', 'formipay' ),
|
||||||
@@ -656,6 +676,10 @@ class Access {
|
|||||||
|
|
||||||
check_ajax_referer( 'formipay-admin-access-nonce', 'nonce' );
|
check_ajax_referer( 'formipay-admin-access-nonce', 'nonce' );
|
||||||
|
|
||||||
|
if ( ! current_user_can( 'manage_options' ) ) {
|
||||||
|
wp_send_json_error( [ 'message' => 'Unauthorized' ] );
|
||||||
|
}
|
||||||
|
|
||||||
if( empty($_REQUEST['id']) ){
|
if( empty($_REQUEST['id']) ){
|
||||||
wp_send_json_error( [
|
wp_send_json_error( [
|
||||||
'title' => esc_html__('Failed', 'formipay'),
|
'title' => esc_html__('Failed', 'formipay'),
|
||||||
|
|||||||
@@ -453,6 +453,10 @@ class Coupon {
|
|||||||
|
|
||||||
check_ajax_referer( 'formipay-frontend-nonce', 'security' );
|
check_ajax_referer( 'formipay-frontend-nonce', 'security' );
|
||||||
|
|
||||||
|
if ( ! current_user_can( 'manage_options' ) ) {
|
||||||
|
wp_send_json_error( [ 'message' => 'Unauthorized' ] );
|
||||||
|
}
|
||||||
|
|
||||||
$code = isset($_REQUEST['code']) ? sanitize_text_field( wp_unslash($_REQUEST['code']) ) : '';
|
$code = isset($_REQUEST['code']) ? sanitize_text_field( wp_unslash($_REQUEST['code']) ) : '';
|
||||||
$form_id = isset($_REQUEST['form']) ? intval( $_REQUEST['form'] ) : 0;
|
$form_id = isset($_REQUEST['form']) ? intval( $_REQUEST['form'] ) : 0;
|
||||||
|
|
||||||
@@ -566,6 +570,10 @@ class Coupon {
|
|||||||
|
|
||||||
check_ajax_referer( 'formipay-admin-coupon-page', '_wpnonce' );
|
check_ajax_referer( 'formipay-admin-coupon-page', '_wpnonce' );
|
||||||
|
|
||||||
|
if ( ! current_user_can( 'manage_options' ) ) {
|
||||||
|
wp_send_json_error( [ 'message' => 'Unauthorized' ] );
|
||||||
|
}
|
||||||
|
|
||||||
$args = [
|
$args = [
|
||||||
'post_type' => 'formipay-coupon',
|
'post_type' => 'formipay-coupon',
|
||||||
'posts_per_page' => -1,
|
'posts_per_page' => -1,
|
||||||
@@ -670,6 +678,10 @@ class Coupon {
|
|||||||
|
|
||||||
check_ajax_referer( 'formipay-admin-coupon-page', '_wpnonce' );
|
check_ajax_referer( 'formipay-admin-coupon-page', '_wpnonce' );
|
||||||
|
|
||||||
|
if ( ! current_user_can( 'manage_options' ) ) {
|
||||||
|
wp_send_json_error( [ 'message' => 'Unauthorized' ] );
|
||||||
|
}
|
||||||
|
|
||||||
if (!isset($_POST['search']) || empty($_POST['search'])) {
|
if (!isset($_POST['search']) || empty($_POST['search'])) {
|
||||||
wp_send_json_error( __('No search term provided.', 'formipay') );
|
wp_send_json_error( __('No search term provided.', 'formipay') );
|
||||||
}
|
}
|
||||||
@@ -700,6 +712,10 @@ class Coupon {
|
|||||||
|
|
||||||
check_ajax_referer( 'formipay-admin-coupon-page', '_wpnonce' );
|
check_ajax_referer( 'formipay-admin-coupon-page', '_wpnonce' );
|
||||||
|
|
||||||
|
if ( ! current_user_can( 'manage_options' ) ) {
|
||||||
|
wp_send_json_error( [ 'message' => 'Unauthorized' ] );
|
||||||
|
}
|
||||||
|
|
||||||
$code = isset($_REQUEST['title']) ? sanitize_text_field( wp_unslash($_REQUEST['title']) ) : '';
|
$code = isset($_REQUEST['title']) ? sanitize_text_field( wp_unslash($_REQUEST['title']) ) : '';
|
||||||
|
|
||||||
if( !empty($code) && '' !== $code ){
|
if( !empty($code) && '' !== $code ){
|
||||||
@@ -731,6 +747,10 @@ class Coupon {
|
|||||||
|
|
||||||
check_ajax_referer( 'formipay-admin-coupon-page', '_wpnonce' );
|
check_ajax_referer( 'formipay-admin-coupon-page', '_wpnonce' );
|
||||||
|
|
||||||
|
if ( ! current_user_can( 'manage_options' ) ) {
|
||||||
|
wp_send_json_error( [ 'message' => 'Unauthorized' ] );
|
||||||
|
}
|
||||||
|
|
||||||
$post_id = isset($_REQUEST['id']) ? intval($_REQUEST['id']) : 0;
|
$post_id = isset($_REQUEST['id']) ? intval($_REQUEST['id']) : 0;
|
||||||
|
|
||||||
$delete = wp_delete_post($post_id, true);
|
$delete = wp_delete_post($post_id, true);
|
||||||
@@ -755,6 +775,10 @@ class Coupon {
|
|||||||
|
|
||||||
check_ajax_referer( 'formipay-admin-coupon-page', '_wpnonce' );
|
check_ajax_referer( 'formipay-admin-coupon-page', '_wpnonce' );
|
||||||
|
|
||||||
|
if ( ! current_user_can( 'manage_options' ) ) {
|
||||||
|
wp_send_json_error( [ 'message' => 'Unauthorized' ] );
|
||||||
|
}
|
||||||
|
|
||||||
if( empty($_REQUEST['ids']) ){
|
if( empty($_REQUEST['ids']) ){
|
||||||
wp_send_json_error( [
|
wp_send_json_error( [
|
||||||
'title' => esc_html__( 'Failed', 'formipay' ),
|
'title' => esc_html__( 'Failed', 'formipay' ),
|
||||||
@@ -798,6 +822,10 @@ class Coupon {
|
|||||||
|
|
||||||
check_ajax_referer( 'formipay-admin-coupon-page', '_wpnonce' );
|
check_ajax_referer( 'formipay-admin-coupon-page', '_wpnonce' );
|
||||||
|
|
||||||
|
if ( ! current_user_can( 'manage_options' ) ) {
|
||||||
|
wp_send_json_error( [ 'message' => 'Unauthorized' ] );
|
||||||
|
}
|
||||||
|
|
||||||
$post_id = isset($_REQUEST['id']) ? intval($_REQUEST['id']) : 0;
|
$post_id = isset($_REQUEST['id']) ? intval($_REQUEST['id']) : 0;
|
||||||
$post = get_post($post_id);
|
$post = get_post($post_id);
|
||||||
if (!$post) {
|
if (!$post) {
|
||||||
|
|||||||
@@ -233,11 +233,40 @@ class Customer {
|
|||||||
|
|
||||||
check_ajax_referer( 'formipay-admin-access-nonce', '_wpnonce' );
|
check_ajax_referer( 'formipay-admin-access-nonce', '_wpnonce' );
|
||||||
|
|
||||||
$get_all_customers = $this->get();
|
if ( ! current_user_can( 'manage_options' ) ) {
|
||||||
$customers = [];
|
wp_send_json_error( [ 'message' => 'Unauthorized' ] );
|
||||||
|
}
|
||||||
|
|
||||||
if(!empty($get_all_customers)){
|
global $wpdb;
|
||||||
foreach($get_all_customers as $customer){
|
$table = $wpdb->prefix . 'formipay_customers';
|
||||||
|
|
||||||
|
$limit = isset($_REQUEST['limit']) ? intval($_REQUEST['limit']) : 10;
|
||||||
|
$offset = isset($_REQUEST['offset']) ? intval($_REQUEST['offset']) : 0;
|
||||||
|
$keyword = isset($_REQUEST['keyword']) ? sanitize_text_field(wp_unslash($_REQUEST['keyword'])) : '';
|
||||||
|
|
||||||
|
$where = '';
|
||||||
|
$params = [];
|
||||||
|
|
||||||
|
if (!empty($keyword)) {
|
||||||
|
$where = "WHERE `name` LIKE %s OR `email` LIKE %s OR `phone` LIKE %s";
|
||||||
|
$like = '%' . $wpdb->esc_like($keyword) . '%';
|
||||||
|
$params = [$like, $like, $like];
|
||||||
|
}
|
||||||
|
|
||||||
|
// Get total count
|
||||||
|
$count_sql = "SELECT COUNT(*) FROM {$table} {$where}";
|
||||||
|
// phpcs:ignore WordPress.DB.DirectDatabaseQuery.DirectQuery, WordPress.DB.DirectDatabaseQuery.NoCaching, WordPress.DB.PreparedSQL.NotPrepared
|
||||||
|
$total = empty($params) ? $wpdb->get_var($count_sql) : $wpdb->get_var($wpdb->prepare($count_sql, ...$params));
|
||||||
|
|
||||||
|
// Get paginated results
|
||||||
|
$sql = "SELECT * FROM {$table} {$where} ORDER BY `id` DESC LIMIT %d OFFSET %d";
|
||||||
|
$params_paginated = array_merge($params, [$limit, $offset]);
|
||||||
|
// phpcs:ignore WordPress.DB.DirectDatabaseQuery.DirectQuery, WordPress.DB.DirectDatabaseQuery.NoCaching, WordPress.DB.PreparedSQL.NotPrepared
|
||||||
|
$get_customers = $wpdb->get_results($wpdb->prepare($sql, ...$params_paginated));
|
||||||
|
|
||||||
|
$customers = [];
|
||||||
|
if (!empty($get_customers)) {
|
||||||
|
foreach ($get_customers as $customer) {
|
||||||
$customers[] = [
|
$customers[] = [
|
||||||
'ID' => $customer->id,
|
'ID' => $customer->id,
|
||||||
'name' => $customer->name,
|
'name' => $customer->name,
|
||||||
@@ -247,14 +276,13 @@ class Customer {
|
|||||||
];
|
];
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// Prepare response data
|
|
||||||
$response = [
|
$response = [
|
||||||
'results' => $customers,
|
'results' => $customers,
|
||||||
'total' => count($get_all_customers),
|
'total' => (int) $total,
|
||||||
'posts_report' => $customers
|
'posts_report' => $customers
|
||||||
];
|
];
|
||||||
|
|
||||||
wp_send_json($response);
|
wp_send_json($response);
|
||||||
|
|
||||||
}
|
}
|
||||||
@@ -263,6 +291,10 @@ class Customer {
|
|||||||
|
|
||||||
check_ajax_referer( 'formipay-form-editor', '_wpnonce' );
|
check_ajax_referer( 'formipay-form-editor', '_wpnonce' );
|
||||||
|
|
||||||
|
if ( ! current_user_can( 'manage_options' ) ) {
|
||||||
|
wp_send_json_error( [ 'message' => 'Unauthorized' ] );
|
||||||
|
}
|
||||||
|
|
||||||
$form_id = isset($_REQUEST['post']) ? intval($_REQUEST['post']) : 0;
|
$form_id = isset($_REQUEST['post']) ? intval($_REQUEST['post']) : 0;
|
||||||
|
|
||||||
$saved = [
|
$saved = [
|
||||||
|
|||||||
@@ -1525,6 +1525,10 @@ class Form {
|
|||||||
|
|
||||||
check_ajax_referer( 'formipay-form-editor', '_wpnonce' );
|
check_ajax_referer( 'formipay-form-editor', '_wpnonce' );
|
||||||
|
|
||||||
|
if ( ! current_user_can( 'manage_options' ) ) {
|
||||||
|
wp_send_json_error( [ 'message' => 'Unauthorized' ] );
|
||||||
|
}
|
||||||
|
|
||||||
if(isset($_GET['post_id'])){
|
if(isset($_GET['post_id'])){
|
||||||
$post_id = intval($_GET['post_id']);
|
$post_id = intval($_GET['post_id']);
|
||||||
$formipay_post_meta = get_post_meta($post_id, 'formipay_settings', true);
|
$formipay_post_meta = get_post_meta($post_id, 'formipay_settings', true);
|
||||||
@@ -1545,6 +1549,10 @@ class Form {
|
|||||||
|
|
||||||
check_ajax_referer( 'formipay-admin-post', '_wpnonce' );
|
check_ajax_referer( 'formipay-admin-post', '_wpnonce' );
|
||||||
|
|
||||||
|
if ( ! current_user_can( 'manage_options' ) ) {
|
||||||
|
wp_send_json_error( [ 'message' => 'Unauthorized' ] );
|
||||||
|
}
|
||||||
|
|
||||||
global $wpdb;
|
global $wpdb;
|
||||||
|
|
||||||
// Initialize default args
|
// Initialize default args
|
||||||
@@ -1623,6 +1631,10 @@ class Form {
|
|||||||
|
|
||||||
check_ajax_referer( 'formipay-admin-post', '_wpnonce' );
|
check_ajax_referer( 'formipay-admin-post', '_wpnonce' );
|
||||||
|
|
||||||
|
if ( ! current_user_can( 'manage_options' ) ) {
|
||||||
|
wp_send_json_error( [ 'message' => 'Unauthorized' ] );
|
||||||
|
}
|
||||||
|
|
||||||
$title = isset($_REQUEST['title']) ? sanitize_text_field( wp_unslash($_REQUEST['title']) ) : '';
|
$title = isset($_REQUEST['title']) ? sanitize_text_field( wp_unslash($_REQUEST['title']) ) : '';
|
||||||
|
|
||||||
if( !empty($title) && '' !== $title ){
|
if( !empty($title) && '' !== $title ){
|
||||||
@@ -1692,6 +1704,10 @@ class Form {
|
|||||||
|
|
||||||
check_ajax_referer( 'formipay-admin-post', '_wpnonce' );
|
check_ajax_referer( 'formipay-admin-post', '_wpnonce' );
|
||||||
|
|
||||||
|
if ( ! current_user_can( 'manage_options' ) ) {
|
||||||
|
wp_send_json_error( [ 'message' => 'Unauthorized' ] );
|
||||||
|
}
|
||||||
|
|
||||||
$form_id = isset($_REQUEST['id']) ? intval($_REQUEST['id']) : '';
|
$form_id = isset($_REQUEST['id']) ? intval($_REQUEST['id']) : '';
|
||||||
|
|
||||||
$delete = wp_delete_post($form_id, true);
|
$delete = wp_delete_post($form_id, true);
|
||||||
@@ -1716,6 +1732,10 @@ class Form {
|
|||||||
|
|
||||||
check_ajax_referer( 'formipay-admin-post', '_wpnonce' );
|
check_ajax_referer( 'formipay-admin-post', '_wpnonce' );
|
||||||
|
|
||||||
|
if ( ! current_user_can( 'manage_options' ) ) {
|
||||||
|
wp_send_json_error( [ 'message' => 'Unauthorized' ] );
|
||||||
|
}
|
||||||
|
|
||||||
if( empty($_REQUEST['ids']) ){
|
if( empty($_REQUEST['ids']) ){
|
||||||
wp_send_json_error( [
|
wp_send_json_error( [
|
||||||
'title' => esc_html__( 'Failed', 'formipay' ),
|
'title' => esc_html__( 'Failed', 'formipay' ),
|
||||||
@@ -1759,6 +1779,10 @@ class Form {
|
|||||||
|
|
||||||
check_ajax_referer( 'formipay-admin-post', '_wpnonce' );
|
check_ajax_referer( 'formipay-admin-post', '_wpnonce' );
|
||||||
|
|
||||||
|
if ( ! current_user_can( 'manage_options' ) ) {
|
||||||
|
wp_send_json_error( [ 'message' => 'Unauthorized' ] );
|
||||||
|
}
|
||||||
|
|
||||||
$post_id = isset($_REQUEST['id']) ? intval($_REQUEST['id']) : '';
|
$post_id = isset($_REQUEST['id']) ? intval($_REQUEST['id']) : '';
|
||||||
$post = get_post($post_id);
|
$post = get_post($post_id);
|
||||||
if (!$post) {
|
if (!$post) {
|
||||||
|
|||||||
@@ -729,10 +729,45 @@ class Paypal extends Payment {
|
|||||||
public function handle_paypal_webhook(\WP_REST_Request $request) {
|
public function handle_paypal_webhook(\WP_REST_Request $request) {
|
||||||
$body = $request->get_body();
|
$body = $request->get_body();
|
||||||
$event = json_decode($body, true);
|
$event = json_decode($body, true);
|
||||||
|
|
||||||
if (!$event || empty($event['event_type'])) {
|
if (!$event || empty($event['event_type'])) {
|
||||||
return new \WP_Error('invalid_webhook', 'Invalid webhook payload');
|
return new \WP_Error('invalid_webhook', 'Invalid webhook payload');
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Verify webhook signature
|
||||||
|
$formipay_settings = get_option('formipay_settings');
|
||||||
|
$headers = $request->get_headers();
|
||||||
|
|
||||||
|
$auth_algo = $headers['paypal_auth_algo'][0] ?? '';
|
||||||
|
$transmission_id = $headers['paypal_transmission_id'][0] ?? '';
|
||||||
|
$cert_url = $headers['paypal_cert_url'][0] ?? '';
|
||||||
|
$transmission_sig = $headers['paypal_transmission_sig'][0] ?? '';
|
||||||
|
$transmission_time = $headers['paypal_transmission_time'][0] ?? '';
|
||||||
|
$webhook_id = $formipay_settings['paypal_webhook_id'] ?? '';
|
||||||
|
|
||||||
|
if (!empty($webhook_id) && !empty($transmission_id) && !empty($transmission_sig)) {
|
||||||
|
$expected = $transmission_id . '|' . $event['resource']['id'] ?? '' . '|' . $transmission_time . '|' . $webhook_id . '|' . crc32($body);
|
||||||
|
$sig_base64 = base64_encode($expected);
|
||||||
|
|
||||||
|
// Fetch certificate and verify
|
||||||
|
$cert_response = wp_remote_get($cert_url);
|
||||||
|
if (is_wp_error($cert_response)) {
|
||||||
|
return new \WP_Error('cert_fetch_failed', 'Failed to fetch PayPal certificate');
|
||||||
|
}
|
||||||
|
$cert = wp_remote_retrieve_body($cert_response);
|
||||||
|
|
||||||
|
$public_key = openssl_pkey_get_public($cert);
|
||||||
|
if ($public_key === false) {
|
||||||
|
return new \WP_Error('invalid_cert', 'Failed to load PayPal certificate');
|
||||||
|
}
|
||||||
|
|
||||||
|
$verified = openssl_verify($expected, base64_decode($transmission_sig), $public_key, 'sha256WithRSAEncryption');
|
||||||
|
openssl_free_key($public_key);
|
||||||
|
|
||||||
|
if ($verified !== 1) {
|
||||||
|
return new \WP_Error('invalid_signature', 'Webhook signature verification failed');
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
// Example: get order_id from custom_id or invoice_number in resource
|
// Example: get order_id from custom_id or invoice_number in resource
|
||||||
$resource = $event['resource'];
|
$resource = $event['resource'];
|
||||||
|
|||||||
@@ -1,821 +0,0 @@
|
|||||||
<?php
|
|
||||||
namespace Formipay\Integration;
|
|
||||||
use Formipay\Traits\SingletonTrait;
|
|
||||||
use Formipay\Payment\Payment;
|
|
||||||
// Exit if accessed directly
|
|
||||||
if ( ! defined( 'ABSPATH' ) ) exit;
|
|
||||||
|
|
||||||
class Paypal extends Payment {
|
|
||||||
|
|
||||||
use SingletonTrait;
|
|
||||||
|
|
||||||
private $gateway = 'paypal';
|
|
||||||
|
|
||||||
protected function __construct() {
|
|
||||||
|
|
||||||
parent::__construct();
|
|
||||||
|
|
||||||
add_action( 'init', [$this, 'create_db'] );
|
|
||||||
add_action( 'formipay/order/new', [$this, 'add_transaction'], 99 );
|
|
||||||
|
|
||||||
add_filter( 'formipay/form-config/tab:payments/gateways', [$this, 'add_gateway'] );
|
|
||||||
add_filter( 'formipay/form-config/tab:payments', [$this, 'add_paypal_settings'] );
|
|
||||||
add_filter( 'formipay/global-settings/tab:payment', [$this, 'add_settings'] );
|
|
||||||
add_filter( 'formipay/payment-list/paypal/label', [$this, 'set_frontend_label'] );
|
|
||||||
add_filter( 'formipay/payment-list/paypal/logo', [$this, 'set_frontend_logo'] );
|
|
||||||
add_filter( 'formipay/order/result', [$this, 'process_payment'], 99 );
|
|
||||||
add_action( 'parse_query', [$this, 'check_parse_query'] );
|
|
||||||
add_filter( 'formipay/order/payment-details/paypal', [$this, 'render_payment_details'], 999, 4 );
|
|
||||||
|
|
||||||
add_filter('formipay/notification/order/email/action-button', [$this, 'render_email_action_button'], 99, 3 );
|
|
||||||
|
|
||||||
}
|
|
||||||
|
|
||||||
public function create_db() {
|
|
||||||
|
|
||||||
global $wpdb;
|
|
||||||
$charset_collate = $wpdb->get_charset_collate();
|
|
||||||
|
|
||||||
$create[] = "CREATE TABLE `{$wpdb->base_prefix}formipay_paypal_trx` (
|
|
||||||
`id` bigint(20) NOT NULL AUTO_INCREMENT,
|
|
||||||
`created_date` datetime DEFAULT CURRENT_TIMESTAMP,
|
|
||||||
`form_id` int DEFAULT 0,
|
|
||||||
`order_id` int DEFAULT 0,
|
|
||||||
`currency_code` text,
|
|
||||||
`total` float(10, 2) DEFAULT 0,
|
|
||||||
`status` text,
|
|
||||||
`meta_data` text,
|
|
||||||
PRIMARY KEY (`id`)
|
|
||||||
) $charset_collate;";
|
|
||||||
|
|
||||||
require_once ABSPATH . 'wp-admin/includes/upgrade.php';
|
|
||||||
|
|
||||||
dbDelta($create);
|
|
||||||
|
|
||||||
}
|
|
||||||
|
|
||||||
public function add_transaction($order_data) {
|
|
||||||
|
|
||||||
$form_id = absint($order_data['form_id'] ?? 0);
|
|
||||||
|
|
||||||
$formipay_settings = get_option('formipay_settings');
|
|
||||||
$timeout = isset($formipay_settings['paypal_timeout']) ? (int) $formipay_settings['paypal_timeout'] : 1440;
|
|
||||||
|
|
||||||
$currency_meta = formipay_get_post_meta($form_id, 'product_currency');
|
|
||||||
$currency_parts = explode(':::', $currency_meta);
|
|
||||||
$currency = !empty($currency_parts[0]) ? sanitize_text_field($currency_parts[0]) : '';
|
|
||||||
|
|
||||||
if($this->gateway === ($order_data['payment_gateway'] ?? '')) {
|
|
||||||
|
|
||||||
$submit_args = [
|
|
||||||
'created_date' => formipay_date('Y-m-d H:i:s', strtotime($order_data['created_date'] ?? 'now')),
|
|
||||||
'form_id' => $form_id,
|
|
||||||
'order_id' => absint($order_data['id'] ?? 0),
|
|
||||||
'currency_code' => $currency,
|
|
||||||
'total' => floatval($order_data['total'] ?? 0),
|
|
||||||
'status' => 'PENDING',
|
|
||||||
'meta_data' => maybe_serialize([
|
|
||||||
'request_response' => maybe_serialize($order_data['payment_callback']),
|
|
||||||
'payer_action_url' => esc_url_raw($order_data['redirect_url'] ?? '')
|
|
||||||
])
|
|
||||||
];
|
|
||||||
|
|
||||||
global $wpdb;
|
|
||||||
$table = $wpdb->prefix . 'formipay_paypal_trx';
|
|
||||||
|
|
||||||
$format = [
|
|
||||||
'%s', // created_date
|
|
||||||
'%d', // form_id
|
|
||||||
'%d', // order_id
|
|
||||||
'%s', // currency_code
|
|
||||||
'%f', // total
|
|
||||||
'%s', // status
|
|
||||||
'%s' // meta_data
|
|
||||||
];
|
|
||||||
|
|
||||||
// phpcs:ignore WordPress.DB.DirectDatabaseQuery.DirectQuery
|
|
||||||
$wpdb->insert($table, $submit_args, $format);
|
|
||||||
|
|
||||||
wp_schedule_single_event(
|
|
||||||
(int) formipay_date('timestamp') + $timeout, 'formipay/order/payment-timeout', [
|
|
||||||
'order_id' => $order_data['id'],
|
|
||||||
'payment_gateway' => 'paypal'
|
|
||||||
]
|
|
||||||
);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
public function auto_cancel_order_on_timeout($order_id, $payment_gateway) {
|
|
||||||
|
|
||||||
if($payment_gateway == 'paypal'){
|
|
||||||
|
|
||||||
global $wpdb;
|
|
||||||
$order = formipay_get_order($order_id);
|
|
||||||
if($order['status'] !== 'completed'){
|
|
||||||
Order::update($order_id, [
|
|
||||||
'status' => 'cancelled'
|
|
||||||
]);
|
|
||||||
$this->cancel_payment($order_id);
|
|
||||||
}
|
|
||||||
|
|
||||||
}
|
|
||||||
|
|
||||||
}
|
|
||||||
|
|
||||||
public function get_transaction($order_id = 0) {
|
|
||||||
|
|
||||||
global $wpdb;
|
|
||||||
$table = $wpdb->prefix .'formipay_paypal_trx';
|
|
||||||
if($order_id == 0){
|
|
||||||
// phpcs:ignore WordPress.DB.DirectDatabaseQuery.DirectQuery, WordPress.DB.DirectDatabaseQuery.NoCaching
|
|
||||||
$get = $wpdb->get_results(
|
|
||||||
$wpdb->prepare(
|
|
||||||
"SELECT * FROM %i", $table
|
|
||||||
)
|
|
||||||
);
|
|
||||||
}else{
|
|
||||||
// phpcs:ignore WordPress.DB.DirectDatabaseQuery.DirectQuery, WordPress.DB.DirectDatabaseQuery.NoCaching
|
|
||||||
$get = $wpdb->get_row(
|
|
||||||
$wpdb->prepare(
|
|
||||||
"SELECT * FROM %i WHERE `order_id` = %d", $table, $order_id
|
|
||||||
)
|
|
||||||
);
|
|
||||||
}
|
|
||||||
|
|
||||||
return $get;
|
|
||||||
|
|
||||||
}
|
|
||||||
|
|
||||||
public function update_transaction($order_id, $status, $callback) {
|
|
||||||
|
|
||||||
$args = [
|
|
||||||
'status' => sanitize_text_field( $status ),
|
|
||||||
'meta_data' => maybe_serialize( $callback )
|
|
||||||
];
|
|
||||||
|
|
||||||
global $wpdb;
|
|
||||||
$table = $wpdb->prefix . 'formipay_paypal_trx';
|
|
||||||
$where = ['order_id' => $order_id];
|
|
||||||
|
|
||||||
// phpcs:ignore WordPress.DB.DirectDatabaseQuery.DirectQuery, WordPress.DB.DirectDatabaseQuery.NoCaching
|
|
||||||
$update = $wpdb->update(
|
|
||||||
$table, $args, $where
|
|
||||||
);
|
|
||||||
|
|
||||||
return $update;
|
|
||||||
|
|
||||||
}
|
|
||||||
|
|
||||||
public function add_gateway($gateways) {
|
|
||||||
|
|
||||||
$formipay_settings = get_option('formipay_settings');
|
|
||||||
|
|
||||||
if(isset($formipay_settings['paypal_toggle']) && $formipay_settings['paypal_toggle'] == 'yes') {
|
|
||||||
$gateways[] = [
|
|
||||||
'id' => $this->gateway,
|
|
||||||
'gateway' => __( 'Paypal', 'formipay' )
|
|
||||||
];
|
|
||||||
}
|
|
||||||
|
|
||||||
return $gateways;
|
|
||||||
|
|
||||||
}
|
|
||||||
|
|
||||||
public function add_settings($fields) {
|
|
||||||
|
|
||||||
$payment_instruction = file_get_contents( FORMIPAY_PATH . 'admin/templates/paypal-instruction.html' );
|
|
||||||
|
|
||||||
$paypal_settings = array(
|
|
||||||
$this->gateway.'_toggle' => array(
|
|
||||||
'type' => 'checkbox',
|
|
||||||
'label' => __( 'Activate Paypal', 'formipay' ),
|
|
||||||
'submenu' => __( 'Paypal', 'formipay' )
|
|
||||||
),
|
|
||||||
$this->gateway.'_account_group' => array(
|
|
||||||
'type' => 'group_title',
|
|
||||||
'label' => __( 'Paypal Account', 'formipay' ),
|
|
||||||
'submenu' => __( 'Paypal', 'formipay' ),
|
|
||||||
'dependency' => array(
|
|
||||||
'key' => $this->gateway.'_toggle',
|
|
||||||
'value' => 'not_empty'
|
|
||||||
),
|
|
||||||
'group' => 'started'
|
|
||||||
),
|
|
||||||
$this->gateway.'_instruction' => array(
|
|
||||||
'type' => 'notification_message',
|
|
||||||
'description' => $payment_instruction,
|
|
||||||
'buttons' => array(
|
|
||||||
'show_instruction' => array(
|
|
||||||
'text' => __( 'Show Instruction', 'formipay' ),
|
|
||||||
'class' => 'show-instruction'
|
|
||||||
)
|
|
||||||
),
|
|
||||||
'dependency' => array(
|
|
||||||
'key' => $this->gateway.'_toggle',
|
|
||||||
'value' => 'not_empty'
|
|
||||||
),
|
|
||||||
'submenu' => __( 'Paypal', 'formipay' )
|
|
||||||
),
|
|
||||||
$this->gateway.'_client_id' => array(
|
|
||||||
'type' => 'text',
|
|
||||||
'label' => __( 'Client ID', 'formipay' ),
|
|
||||||
'submenu' => __( 'Paypal', 'formipay' ),
|
|
||||||
'dependency' => array(
|
|
||||||
'key' => $this->gateway.'_toggle',
|
|
||||||
'value' => 'not_empty'
|
|
||||||
)
|
|
||||||
),
|
|
||||||
$this->gateway.'_secret' => array(
|
|
||||||
'type' => 'text',
|
|
||||||
'label' => __( 'Secret', 'formipay' ),
|
|
||||||
'submenu' => __( 'Paypal', 'formipay' ),
|
|
||||||
'dependency' => array(
|
|
||||||
'key' => $this->gateway.'_toggle',
|
|
||||||
'value' => 'not_empty'
|
|
||||||
)
|
|
||||||
),
|
|
||||||
$this->gateway.'_environment' => array(
|
|
||||||
'type' => 'select',
|
|
||||||
'label' => __( 'Environment', 'formipay' ),
|
|
||||||
'options' => array(
|
|
||||||
'sandbox' => __( 'Sandbox', 'formipay' ),
|
|
||||||
'production' => __( 'Production', 'formipay' )
|
|
||||||
),
|
|
||||||
'value' => 'sandbox',
|
|
||||||
'submenu' => __( 'Paypal', 'formipay' ),
|
|
||||||
'dependency' => array(
|
|
||||||
'key' => $this->gateway.'_toggle',
|
|
||||||
'value' => 'not_empty'
|
|
||||||
)
|
|
||||||
),
|
|
||||||
$this->gateway.'_merchant_email' => array(
|
|
||||||
'type' => 'text',
|
|
||||||
'label' => __( 'Merchant Email', 'formipay' ),
|
|
||||||
'submenu' => __( 'Paypal', 'formipay' ),
|
|
||||||
'dependency' => array(
|
|
||||||
'key' => $this->gateway.'_toggle',
|
|
||||||
'value' => 'not_empty'
|
|
||||||
),
|
|
||||||
),
|
|
||||||
$this->gateway.'_timeout' => array(
|
|
||||||
'type' => 'number',
|
|
||||||
'label' => __( 'Payment Timeout (minute)', 'formipay' ),
|
|
||||||
'description' => __( 'Set a timeout to wait for payment. After this timeout is up, the order status automatically changes to cancelled.', 'formipay' ),
|
|
||||||
'value' => 120,
|
|
||||||
'group' => 'ended',
|
|
||||||
'submenu' => __( 'Paypal', 'formipay' ),
|
|
||||||
'dependency' => array(
|
|
||||||
'key' => $this->gateway.'_toggle',
|
|
||||||
'value' => 'not_empty'
|
|
||||||
),
|
|
||||||
'group' => 'ended'
|
|
||||||
),
|
|
||||||
);
|
|
||||||
|
|
||||||
foreach($paypal_settings as $key => $value) {
|
|
||||||
$fields[$key] = $value;
|
|
||||||
}
|
|
||||||
|
|
||||||
return $fields;
|
|
||||||
|
|
||||||
}
|
|
||||||
|
|
||||||
public function add_paypal_settings($fields) {
|
|
||||||
|
|
||||||
$paypal_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' => __( 'Paypal', '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' => __( 'Paypal', '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 payment for #{{order_id}}', 'formipay'),
|
|
||||||
'description' => __('When successfully change the order status to the preferred one', 'formipay'),
|
|
||||||
'submenu' => __( 'Paypal', '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' => __( 'Paypal', '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' => __( 'Paypal', 'formipay' ),
|
|
||||||
'group' => 'ended'
|
|
||||||
)
|
|
||||||
);
|
|
||||||
|
|
||||||
foreach($paypal_settings as $key => $value) {
|
|
||||||
$fields[$key] = $value;
|
|
||||||
}
|
|
||||||
|
|
||||||
return $fields;
|
|
||||||
|
|
||||||
}
|
|
||||||
|
|
||||||
public function set_frontend_label($label){
|
|
||||||
|
|
||||||
$label = __( 'Paypal', 'formipay' );
|
|
||||||
|
|
||||||
return $label;
|
|
||||||
|
|
||||||
}
|
|
||||||
|
|
||||||
public function set_frontend_logo($logo){
|
|
||||||
|
|
||||||
if($logo == false){
|
|
||||||
$logo = FORMIPAY_URL . 'public/assets/img/paypal.png';
|
|
||||||
}
|
|
||||||
|
|
||||||
return $logo;
|
|
||||||
|
|
||||||
}
|
|
||||||
|
|
||||||
public function prepare_payload($order_data) {
|
|
||||||
|
|
||||||
// error_log('current order'. $order_data['id'] . ': ' . print_r($order_data, true));
|
|
||||||
|
|
||||||
$form_id = intval($order_data['form_id']);
|
|
||||||
$order_details = $order_data['items'];
|
|
||||||
|
|
||||||
if($this->gateway == $order_data['payment_gateway']){
|
|
||||||
|
|
||||||
$formipay_settings = get_option('formipay_settings');
|
|
||||||
|
|
||||||
$grand_total = floatval($order_data['total']);
|
|
||||||
|
|
||||||
// Currency
|
|
||||||
$currency = explode(':::', formipay_get_post_meta($form_id, 'product_currency'));
|
|
||||||
$currency = $currency[0];
|
|
||||||
|
|
||||||
$currency_decimal_digits = formipay_get_post_meta($form_id, 'product_currency_decimal_digits');
|
|
||||||
$currency_decimal_symbol = formipay_get_post_meta($form_id, 'product_currency_decimal_symbol');
|
|
||||||
$currency_thousand_separator = formipay_get_post_meta($form_id, 'product_currency_thousand_separator');
|
|
||||||
|
|
||||||
$slug = 'thankyou';
|
|
||||||
$formipay_settings = get_option('formipay_settings');
|
|
||||||
if(!empty($formipay_settings['thankyou_link'])){
|
|
||||||
$slug = $formipay_settings['thankyou_link'];
|
|
||||||
}
|
|
||||||
|
|
||||||
if(formipay_get_post_meta($form_id, 'product_type') == 'digital'){
|
|
||||||
$shipping_preference = 'NO_SHIPPING';
|
|
||||||
}else{
|
|
||||||
$shipping_preference = 'SET_PROVIDED_ADDRESS';
|
|
||||||
}
|
|
||||||
|
|
||||||
// Setup items
|
|
||||||
$items = [];
|
|
||||||
foreach($order_details as $item){
|
|
||||||
$qty = 1;
|
|
||||||
if(!empty($item['qty'])){
|
|
||||||
$qty = $item['qty'];
|
|
||||||
}
|
|
||||||
if(floatval($item['amount']) >= 0){
|
|
||||||
$items[] = [
|
|
||||||
'name' => $item['item'],
|
|
||||||
'unit_amount' => [
|
|
||||||
'currency_code' => $currency,
|
|
||||||
'value' => floatval($item['amount'])
|
|
||||||
],
|
|
||||||
'quantity' => $qty
|
|
||||||
];
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
$items = apply_filters('formipay/order/paypal/payload/items', $items, $currency, $order_data);
|
|
||||||
|
|
||||||
$breakdown = array(
|
|
||||||
"item_total" => array(
|
|
||||||
"currency_code" => $currency,
|
|
||||||
"value" => $grand_total
|
|
||||||
)
|
|
||||||
);
|
|
||||||
$breakdown = apply_filters('formipay/order/paypal/payload/breakdown', $breakdown, $currency, $order_data);
|
|
||||||
|
|
||||||
$unique_id = $order_data['meta_data']['session_id']['value'];
|
|
||||||
|
|
||||||
// Prepare the payload
|
|
||||||
$payload = json_encode(array(
|
|
||||||
"intent" => "CAPTURE",
|
|
||||||
"purchase_units" => array(
|
|
||||||
array(
|
|
||||||
"amount" => array(
|
|
||||||
"currency_code" => $currency,
|
|
||||||
"value" => $grand_total, // Format amount
|
|
||||||
"breakdown" => $breakdown
|
|
||||||
),
|
|
||||||
"items" => $items
|
|
||||||
)
|
|
||||||
),
|
|
||||||
'payment_source' => array(
|
|
||||||
'paypal' => array(
|
|
||||||
'experience_context' => array(
|
|
||||||
'return_url' => site_url('/payment-confirm/'.$this->gateway.'/'.base64_encode($order_data['form_id'].':::'.$order_data['id'].':::'.$unique_id).'?paypal-status=success'),
|
|
||||||
'cancel_url' => site_url('/payment-confirm/'.$this->gateway.'/'.base64_encode($order_data['form_id'].':::'.$order_data['id'].':::'.$unique_id).'?paypal-status=cancel'),
|
|
||||||
'user_action' => 'PAY_NOW',
|
|
||||||
'brand_name' => 'FORMIPAY INC',
|
|
||||||
'local' => 'en-US',
|
|
||||||
'landing_page' => 'LOGIN',
|
|
||||||
'payment_method_preference' => 'IMMEDIATE_PAYMENT_REQUIRED',
|
|
||||||
'shipping_preference' => $shipping_preference
|
|
||||||
)
|
|
||||||
)
|
|
||||||
)
|
|
||||||
));
|
|
||||||
|
|
||||||
return $payload;
|
|
||||||
}
|
|
||||||
|
|
||||||
return false;
|
|
||||||
|
|
||||||
}
|
|
||||||
|
|
||||||
public function process_payment( $order_data ) {
|
|
||||||
|
|
||||||
$formipay_settings = get_option('formipay_settings');
|
|
||||||
|
|
||||||
if($order_data['payment_gateway'] == 'paypal') {
|
|
||||||
|
|
||||||
$paypal_client_id = $formipay_settings['paypal_client_id'];
|
|
||||||
$paypal_secret = $formipay_settings['paypal_secret'];
|
|
||||||
|
|
||||||
// Set your authentication header
|
|
||||||
$auth = base64_encode($paypal_client_id . ':' . $paypal_secret);
|
|
||||||
|
|
||||||
// Define arguments for wp_remote_post
|
|
||||||
$args = array(
|
|
||||||
'headers' => array(
|
|
||||||
'Content-Type' => 'application/json',
|
|
||||||
'Authorization' => 'Basic ' . $auth,
|
|
||||||
),
|
|
||||||
'method' => 'POST',
|
|
||||||
'data_format' => 'body'
|
|
||||||
);
|
|
||||||
|
|
||||||
$url = 'https://api-m.sandbox.paypal.com/v2';
|
|
||||||
if(isset($formipay_settings[$this->gateway.'_environment']) && $formipay_settings[$this->gateway.'_environment'] == 'production') {
|
|
||||||
$url = 'https://api-m.paypal.com/v2';
|
|
||||||
}
|
|
||||||
|
|
||||||
$payload = $this->prepare_payload($order_data);
|
|
||||||
// error_log('paypal payload:'.print_r($payload, true));
|
|
||||||
$args['body'] = $payload;
|
|
||||||
$url = $url.'/checkout/orders';
|
|
||||||
|
|
||||||
$response = wp_remote_retrieve_body( wp_remote_post($url, $args) );
|
|
||||||
$response = json_decode($response);
|
|
||||||
// error_log('paypal response:'.print_r($response, true));
|
|
||||||
|
|
||||||
$payer_action_link = null;
|
|
||||||
|
|
||||||
foreach ($response->links as $link) {
|
|
||||||
if ($link->rel === 'payer-action') {
|
|
||||||
$payer_action_link = $link->href;
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
if($payer_action_link !== null){
|
|
||||||
$order_data['payment_callback'] = $response;
|
|
||||||
$order_data['redirect_url'] = $payer_action_link;
|
|
||||||
}
|
|
||||||
|
|
||||||
}
|
|
||||||
|
|
||||||
return $order_data;
|
|
||||||
|
|
||||||
}
|
|
||||||
|
|
||||||
public function cancel_payment( $order_data ) {
|
|
||||||
|
|
||||||
$formipay_settings = get_option('formipay_settings');
|
|
||||||
|
|
||||||
if($order_data['payment_gateway'] == 'paypal') {
|
|
||||||
|
|
||||||
$paypal_client_id = $formipay_settings['paypal_client_id'];
|
|
||||||
$paypal_secret = $formipay_settings['paypal_secret'];
|
|
||||||
|
|
||||||
// Set your authentication header
|
|
||||||
$auth = base64_encode($paypal_client_id . ':' . $paypal_secret);
|
|
||||||
|
|
||||||
// Define arguments for wp_remote_post
|
|
||||||
$args = array(
|
|
||||||
'headers' => array(
|
|
||||||
'Content-Type' => 'application/json',
|
|
||||||
'Authorization' => 'Basic ' . $auth,
|
|
||||||
),
|
|
||||||
'method' => 'POST',
|
|
||||||
'data_format' => 'body'
|
|
||||||
);
|
|
||||||
|
|
||||||
$url = 'https://api-m.sandbox.paypal.com/v2';
|
|
||||||
if(isset($formipay_settings[$this->gateway.'_environment']) && $formipay_settings[$this->gateway.'_environment'] == 'production') {
|
|
||||||
$url = 'https://api-m.paypal.com/v2';
|
|
||||||
}
|
|
||||||
|
|
||||||
$payload = $this->prepare_payload($order_data);
|
|
||||||
// error_log('paypal payload:'.print_r($payload, true));
|
|
||||||
$args['body'] = $payload;
|
|
||||||
$url = $url.'/checkout/orders';
|
|
||||||
|
|
||||||
$response = wp_remote_retrieve_body( wp_remote_post($url, $args) );
|
|
||||||
$response = json_decode($response);
|
|
||||||
// error_log('paypal response:'.print_r($response, true));
|
|
||||||
|
|
||||||
$payer_action_link = null;
|
|
||||||
|
|
||||||
foreach ($response->links as $link) {
|
|
||||||
if ($link->rel === 'payer-action') {
|
|
||||||
$payer_action_link = $link->href;
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
if($payer_action_link !== null){
|
|
||||||
$order_data['redirect_url'] = $payer_action_link;
|
|
||||||
}
|
|
||||||
|
|
||||||
do_action('formipay/notification/order', $order_data);
|
|
||||||
|
|
||||||
}
|
|
||||||
|
|
||||||
}
|
|
||||||
|
|
||||||
public function check_parse_query() {
|
|
||||||
if (is_admin()) {
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
global $wp_query;
|
|
||||||
|
|
||||||
$formipay_settings = get_option('formipay_settings');
|
|
||||||
|
|
||||||
// Validate query vars early
|
|
||||||
$query = $wp_query->query;
|
|
||||||
if (
|
|
||||||
is_array($query) &&
|
|
||||||
!empty($query['formipay-payment-confirm']) &&
|
|
||||||
filter_var($query['formipay-payment-confirm'], FILTER_VALIDATE_BOOLEAN) &&
|
|
||||||
!empty($query['gateway']) &&
|
|
||||||
$query['gateway'] === 'paypal'
|
|
||||||
) {
|
|
||||||
// Sanitize and validate token
|
|
||||||
$token_raw = isset($query['formipay-token']) ? $query['formipay-token'] : '';
|
|
||||||
$token_decoded = base64_decode($token_raw, true);
|
|
||||||
if (!$token_decoded) {
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
$token = explode(':::', $token_decoded);
|
|
||||||
if (count($token) < 2) {
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
$form_id = absint($token[0]);
|
|
||||||
$order_id = absint($token[1]);
|
|
||||||
if (!$form_id || !$order_id) {
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
$check_order = $this->get_transaction($order_id);
|
|
||||||
|
|
||||||
// Check PayPal status and process payment
|
|
||||||
if (!empty($check_order) &&
|
|
||||||
// phpcs:ignore WordPress.Security.NonceVerification.Recommended
|
|
||||||
isset($_GET['paypal-status']) && sanitize_text_field(wp_unslash($_GET['paypal-status'])) === 'success' &&
|
|
||||||
strtoupper($check_order->status) === 'PENDING'
|
|
||||||
) {
|
|
||||||
$paypal_client_id = isset($formipay_settings['paypal_client_id']) ? $formipay_settings['paypal_client_id'] : '';
|
|
||||||
$paypal_secret = isset($formipay_settings['paypal_secret']) ? $formipay_settings['paypal_secret'] : '';
|
|
||||||
$environment = isset($formipay_settings[$this->gateway . '_environment']) ? $formipay_settings[$this->gateway . '_environment'] : 'sandbox';
|
|
||||||
|
|
||||||
if ($paypal_client_id && $paypal_secret) {
|
|
||||||
$auth = base64_encode($paypal_client_id . ':' . $paypal_secret);
|
|
||||||
// phpcs:ignore WordPress.Security.NonceVerification.Recommended
|
|
||||||
$paypal_order_id = isset($_GET['token']) ? sanitize_text_field(wp_unslash($_GET['token'])) : '';
|
|
||||||
|
|
||||||
$base_url = ($environment === 'production')
|
|
||||||
? 'https://api-m.paypal.com/v2'
|
|
||||||
: 'https://api-m.sandbox.paypal.com/v2';
|
|
||||||
|
|
||||||
$url = $base_url . '/checkout/orders/' . $paypal_order_id . '/capture';
|
|
||||||
|
|
||||||
$args = [
|
|
||||||
'headers' => [
|
|
||||||
'Content-Type' => 'application/json',
|
|
||||||
'Authorization' => 'Basic ' . $auth,
|
|
||||||
],
|
|
||||||
'method' => 'POST',
|
|
||||||
'data_format' => 'body',
|
|
||||||
'timeout' => 20,
|
|
||||||
];
|
|
||||||
|
|
||||||
$response = wp_remote_post($url, $args);
|
|
||||||
$body = is_wp_error($response) ? null : wp_remote_retrieve_body($response);
|
|
||||||
$response_data = json_decode($body, true);
|
|
||||||
|
|
||||||
if (isset($response_data['status']) && $response_data['status'] === 'COMPLETED') {
|
|
||||||
$update_order_status = formipay_update_order_status([
|
|
||||||
'form_id' => $form_id,
|
|
||||||
'order_id' => $order_id,
|
|
||||||
'payment_gateway' => $this->gateway,
|
|
||||||
'status' => 'completed'
|
|
||||||
]);
|
|
||||||
if (!empty($update_order_status['valid'])) {
|
|
||||||
$capture_details = $response_data['purchase_units'][0]['payments']['captures'][0] ?? [];
|
|
||||||
$this->update_transaction($order_id, $response_data['status'], $capture_details);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
// Determine redirect action
|
|
||||||
$action_type = formipay_get_post_meta($form_id, 'submit_action_type');
|
|
||||||
$params = isset($_SERVER['QUERY_STRING']) ? sanitize_text_field(wp_unslash($_SERVER['QUERY_STRING'])) : '';
|
|
||||||
|
|
||||||
if ($action_type === 'thankyou') {
|
|
||||||
$thankyou_slug = !empty($formipay_settings['thankyou_link'])
|
|
||||||
? sanitize_title($formipay_settings['thankyou_link'])
|
|
||||||
: 'thankyou';
|
|
||||||
wp_safe_redirect(site_url('/' . $thankyou_slug . '/' . $token_raw . '?' . $params));
|
|
||||||
exit;
|
|
||||||
} elseif ($action_type === 'redirect') {
|
|
||||||
$url = formipay_get_post_meta($form_id, 'redirect_url');
|
|
||||||
$url = esc_url_raw($url);
|
|
||||||
if (strpos($url, '?') !== false) {
|
|
||||||
wp_safe_redirect($url . '&' . $params);
|
|
||||||
} else {
|
|
||||||
wp_safe_redirect($url . '?' . $params);
|
|
||||||
}
|
|
||||||
exit;
|
|
||||||
} elseif ($action_type === 'whatsapp') {
|
|
||||||
$order = formipay_get_order($order_id);
|
|
||||||
$order_data = [];
|
|
||||||
if (is_array($order)) {
|
|
||||||
foreach ($order as $key => $data) {
|
|
||||||
$order_data[$key] = maybe_unserialize($data);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
$admin_number = formipay_get_post_meta($form_id, 'whatsapp_admin');
|
|
||||||
$shortcodes = [
|
|
||||||
'{{product_name}}' => get_the_title($form_id),
|
|
||||||
'{{order_id}}' => $order_id,
|
|
||||||
'{{order_date}}' => $order['created_date'] ?? '',
|
|
||||||
'{{order_total}}' => $order['total'] ?? '',
|
|
||||||
'{{order_status}}' => $order['status'] ?? '',
|
|
||||||
'{{order_details}}' => $this->render_order_details($form_id, $order_id, maybe_unserialize($order['items'] ?? '')),
|
|
||||||
'{{payment_details}}' => $this->render_payment_details('', $form_id, $order_data, 'whatsapp'),
|
|
||||||
];
|
|
||||||
$message_template = wp_kses_post(formipay_get_post_meta($form_id, 'whatsapp_message'));
|
|
||||||
$message = strtr($message_template, $shortcodes);
|
|
||||||
$message = str_replace('%250A', '%0A', rawurlencode($message));
|
|
||||||
$whatsapp_url = 'https://api.whatsapp.com/send/?phone=' . urlencode($admin_number) . '&text=' . $message;
|
|
||||||
wp_safe_redirect($whatsapp_url);
|
|
||||||
exit;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
public function render_order_details($form_id, $order_id, $items) {
|
|
||||||
|
|
||||||
$order = formipay_get_order($order_id);
|
|
||||||
|
|
||||||
$target_length = 40;
|
|
||||||
$message_format = formipay_get_post_meta($form_id, 'whatsapp_message');
|
|
||||||
$order_details_message = '```';
|
|
||||||
if(!empty($items)){
|
|
||||||
foreach($items as $detail){
|
|
||||||
$qty = '';
|
|
||||||
if(isset($detail['qty']) && !empty($detail['qty'])){
|
|
||||||
$qty = $detail['qty'].'×';
|
|
||||||
}
|
|
||||||
$subtotal = formipay_price_format($detail['subtotal'], $form_id);
|
|
||||||
$qty_length = strlen($qty);
|
|
||||||
$subtotal_length = strlen($subtotal);
|
|
||||||
if(floatval($detail['subtotal']) < 0){
|
|
||||||
$subtotal_length = $subtotal_length + 1;
|
|
||||||
}
|
|
||||||
$dot_length = $target_length - ($qty_length + $subtotal_length);
|
|
||||||
$dots = str_repeat('.', intval($dot_length));
|
|
||||||
$order_details_message .= '%0A'.$detail['item'];
|
|
||||||
$order_details_message .= '%0A'.$qty.$dots.$subtotal;
|
|
||||||
}
|
|
||||||
$total = formipay_price_format($order['total'], $form_id);
|
|
||||||
$total_length = strlen($total);
|
|
||||||
$dot_length = $target_length - ($total_length + 6);
|
|
||||||
$dots = str_repeat('.', intval($dot_length));
|
|
||||||
$divider = str_repeat('_', intval($target_length));
|
|
||||||
$order_details_message .= '%0A'.$divider;
|
|
||||||
$order_details_message .= '%0A'.'';
|
|
||||||
$order_details_message .= '%0A'.'Total'.$dots.$total;
|
|
||||||
}
|
|
||||||
$order_details_message .= '%0A```';
|
|
||||||
|
|
||||||
$content = $order_details_message;
|
|
||||||
|
|
||||||
return $content;
|
|
||||||
|
|
||||||
}
|
|
||||||
|
|
||||||
public function render_payment_details($render, $form_id, $order_data, $submit_action_type) {
|
|
||||||
|
|
||||||
if($order_data['status'] == 'completed'){
|
|
||||||
return $render;
|
|
||||||
}
|
|
||||||
|
|
||||||
$formipay_settings = get_option('formipay_settings');
|
|
||||||
|
|
||||||
$get_trx = $this->get_transaction($order_data['id']);
|
|
||||||
if(!empty($get_trx)){
|
|
||||||
$meta = maybe_unserialize($get_trx->meta_data);
|
|
||||||
if(isset($meta['payer_action_url']) && !empty($meta['payer_action_url'])){
|
|
||||||
|
|
||||||
if($formipay_settings[$this->gateway.'_toggle'] !== false){
|
|
||||||
if($submit_action_type == 'thankyou'){
|
|
||||||
|
|
||||||
ob_start();
|
|
||||||
?>
|
|
||||||
<a id="upload-transfer-receipt" class="formipay-submit-button" href="<?php echo esc_url($meta['payer_action_url']) ?>">
|
|
||||||
<i class="bi bi-paypal"></i> <?php echo esc_html__( 'Pay Now', 'formipay' ); ?>
|
|
||||||
</a>
|
|
||||||
<?php
|
|
||||||
$render = ob_get_contents();
|
|
||||||
ob_get_clean();
|
|
||||||
|
|
||||||
}elseif($submit_action_type == 'whatsapp'){
|
|
||||||
|
|
||||||
$slug = 'thankyou';
|
|
||||||
if(!empty($formipay_settings['thankyou_link'])){
|
|
||||||
$slug = $formipay_settings['thankyou_link'];
|
|
||||||
}
|
|
||||||
|
|
||||||
// translators: %s is the Paypal payment URL.
|
|
||||||
$message = sprintf( __('> Payment Link: *%s*', 'formipay'), $meta['payer_action_url'] );
|
|
||||||
|
|
||||||
$render = $message;
|
|
||||||
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
return $render;
|
|
||||||
|
|
||||||
}
|
|
||||||
|
|
||||||
public function render_email_action_button($button, $recipient, $order_data){
|
|
||||||
|
|
||||||
if(
|
|
||||||
$order_data['payment_gateway'] == $this->gateway &&
|
|
||||||
$order_data['status'] == 'on-hold' &&
|
|
||||||
$recipient !== 'admin'
|
|
||||||
){
|
|
||||||
|
|
||||||
$formipay_settings = get_option('formipay_settings');
|
|
||||||
$get_trx = $this->get_transaction($order_data['id']);
|
|
||||||
if(!empty($get_trx)){
|
|
||||||
$meta = maybe_unserialize($get_trx->meta_data);
|
|
||||||
if(isset($meta['payer_action_url']) && !empty($meta['payer_action_url'])){
|
|
||||||
|
|
||||||
$button = [
|
|
||||||
'url' => $meta['payer_action_url'],
|
|
||||||
'label' => __( 'Pay Now', 'formipay' )
|
|
||||||
];
|
|
||||||
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
}
|
|
||||||
|
|
||||||
return $button;
|
|
||||||
|
|
||||||
}
|
|
||||||
|
|
||||||
}
|
|
||||||
@@ -123,6 +123,10 @@ class License {
|
|||||||
public function tabledata() {
|
public function tabledata() {
|
||||||
check_ajax_referer('formipay-admin-licenses', '_wpnonce');
|
check_ajax_referer('formipay-admin-licenses', '_wpnonce');
|
||||||
|
|
||||||
|
if ( ! current_user_can( 'manage_options' ) ) {
|
||||||
|
wp_send_json_error( [ 'message' => 'Unauthorized' ] );
|
||||||
|
}
|
||||||
|
|
||||||
global $wpdb;
|
global $wpdb;
|
||||||
$table = $wpdb->prefix . 'formipay_licenses';
|
$table = $wpdb->prefix . 'formipay_licenses';
|
||||||
|
|
||||||
@@ -200,6 +204,10 @@ class License {
|
|||||||
public function delete() {
|
public function delete() {
|
||||||
check_ajax_referer('formipay-admin-licenses', '_wpnonce');
|
check_ajax_referer('formipay-admin-licenses', '_wpnonce');
|
||||||
|
|
||||||
|
if ( ! current_user_can( 'manage_options' ) ) {
|
||||||
|
wp_send_json_error( [ 'message' => 'Unauthorized' ] );
|
||||||
|
}
|
||||||
|
|
||||||
if (empty($_REQUEST['id'])) {
|
if (empty($_REQUEST['id'])) {
|
||||||
wp_send_json_error([
|
wp_send_json_error([
|
||||||
'title' => esc_html__('Failed', 'formipay'),
|
'title' => esc_html__('Failed', 'formipay'),
|
||||||
@@ -232,6 +240,10 @@ class License {
|
|||||||
public function bulk_delete() {
|
public function bulk_delete() {
|
||||||
check_ajax_referer('formipay-admin-licenses', '_wpnonce');
|
check_ajax_referer('formipay-admin-licenses', '_wpnonce');
|
||||||
|
|
||||||
|
if ( ! current_user_can( 'manage_options' ) ) {
|
||||||
|
wp_send_json_error( [ 'message' => 'Unauthorized' ] );
|
||||||
|
}
|
||||||
|
|
||||||
$ids = isset($_REQUEST['ids']) ? (array) $_REQUEST['ids'] : [];
|
$ids = isset($_REQUEST['ids']) ? (array) $_REQUEST['ids'] : [];
|
||||||
if (empty($ids)) {
|
if (empty($ids)) {
|
||||||
wp_send_json_error([
|
wp_send_json_error([
|
||||||
|
|||||||
@@ -148,7 +148,7 @@ class Order {
|
|||||||
|
|
||||||
$unique_id = isset($order_meta_data['session_id']) ? sanitize_text_field($order_meta_data['session_id']) : '';
|
$unique_id = isset($order_meta_data['session_id']) ? sanitize_text_field($order_meta_data['session_id']) : '';
|
||||||
$thankyou_url = site_url('/' . $thankyou_link . '/' . base64_encode($form_id . ':::' . $order_data['id'] . ':::' . $unique_id));
|
$thankyou_url = site_url('/' . $thankyou_link . '/' . base64_encode($form_id . ':::' . $order_data['id'] . ':::' . $unique_id));
|
||||||
setcookie('fp_access', maybe_serialize([$order_data['id'] => $unique_id]), time() + 86400, '/');
|
setcookie('fp_access', wp_json_encode([$order_data['id'] => $unique_id]), time() + 86400, '/', '', is_ssl(), true);
|
||||||
|
|
||||||
if (
|
if (
|
||||||
!empty($this->order_data['redirect_url']) &&
|
!empty($this->order_data['redirect_url']) &&
|
||||||
@@ -768,6 +768,10 @@ class Order {
|
|||||||
|
|
||||||
check_ajax_referer( 'formipay-order-details', '_wpnonce' );
|
check_ajax_referer( 'formipay-order-details', '_wpnonce' );
|
||||||
|
|
||||||
|
if ( ! current_user_can( 'manage_options' ) ) {
|
||||||
|
wp_send_json_error( [ 'message' => 'Unauthorized' ] );
|
||||||
|
}
|
||||||
|
|
||||||
$type = isset($_REQUEST['type']) ? sanitize_text_field( wp_unslash($_REQUEST['type']) ) : '';
|
$type = isset($_REQUEST['type']) ? sanitize_text_field( wp_unslash($_REQUEST['type']) ) : '';
|
||||||
$search = isset($_REQUEST['search']) ? sanitize_text_field( wp_unslash($_REQUEST['search']) ) : '';
|
$search = isset($_REQUEST['search']) ? sanitize_text_field( wp_unslash($_REQUEST['search']) ) : '';
|
||||||
|
|
||||||
@@ -932,26 +936,33 @@ class Order {
|
|||||||
|
|
||||||
check_ajax_referer( 'formipay-order-details', '_wpnonce' );
|
check_ajax_referer( 'formipay-order-details', '_wpnonce' );
|
||||||
|
|
||||||
$all_orders = $this->get();
|
if ( ! current_user_can( 'manage_options' ) ) {
|
||||||
|
wp_send_json_error( [ 'message' => 'Unauthorized' ] );
|
||||||
|
}
|
||||||
|
|
||||||
|
global $wpdb;
|
||||||
|
$table = $wpdb->prefix . 'formipay_orders';
|
||||||
|
|
||||||
|
// Count order statuses efficiently
|
||||||
|
// phpcs:ignore WordPress.DB.DirectDatabaseQuery.DirectQuery, WordPress.DB.DirectDatabaseQuery.NoCaching, WordPress.DB.PreparedSQL.InterpolatedNotPrepared
|
||||||
|
$status_counts = $wpdb->get_results("SELECT `status`, COUNT(*) as cnt FROM {$table} GROUP BY `status`", ARRAY_A);
|
||||||
|
|
||||||
$order_status = [
|
$order_status = [
|
||||||
'all' => 0,
|
'all' => 0,
|
||||||
'completed' => 0,
|
'completed' => 0,
|
||||||
'on-hold' => 0,
|
'on-hold' => 0,
|
||||||
'payment-confirm' => 0
|
'payment-confirm' => 0
|
||||||
];
|
];
|
||||||
|
|
||||||
// Count order statuses
|
if (!empty($status_counts)) {
|
||||||
if (!empty($all_orders)) {
|
foreach ($status_counts as $row) {
|
||||||
foreach ($all_orders as $order) {
|
$order_status['all'] += (int) $row['cnt'];
|
||||||
$order_status['all']++;
|
if (isset($order_status[$row['status']])) {
|
||||||
$order_status[$order->status]++;
|
$order_status[$row['status']] = (int) $row['cnt'];
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
global $wpdb;
|
|
||||||
$table = $wpdb->prefix . 'formipay_orders';
|
|
||||||
|
|
||||||
$where = [];
|
$where = [];
|
||||||
$params = [];
|
$params = [];
|
||||||
|
|
||||||
@@ -1028,6 +1039,10 @@ class Order {
|
|||||||
|
|
||||||
check_ajax_referer( 'formipay-order-details', '_wpnonce' );
|
check_ajax_referer( 'formipay-order-details', '_wpnonce' );
|
||||||
|
|
||||||
|
if ( ! current_user_can( 'manage_options' ) ) {
|
||||||
|
wp_send_json_error( [ 'message' => 'Unauthorized' ] );
|
||||||
|
}
|
||||||
|
|
||||||
$order_id = isset($_REQUEST['id']) ? intval($_REQUEST['id']) : 0;
|
$order_id = isset($_REQUEST['id']) ? intval($_REQUEST['id']) : 0;
|
||||||
|
|
||||||
$delete = $this->delete($order_id);
|
$delete = $this->delete($order_id);
|
||||||
@@ -1052,6 +1067,10 @@ class Order {
|
|||||||
|
|
||||||
check_ajax_referer( 'formipay-order-details', '_wpnonce' );
|
check_ajax_referer( 'formipay-order-details', '_wpnonce' );
|
||||||
|
|
||||||
|
if ( ! current_user_can( 'manage_options' ) ) {
|
||||||
|
wp_send_json_error( [ 'message' => 'Unauthorized' ] );
|
||||||
|
}
|
||||||
|
|
||||||
if( empty($_REQUEST['ids']) ){
|
if( empty($_REQUEST['ids']) ){
|
||||||
wp_send_json_error( [
|
wp_send_json_error( [
|
||||||
'title' => esc_html__( 'Failed', 'formipay' ),
|
'title' => esc_html__( 'Failed', 'formipay' ),
|
||||||
@@ -1095,6 +1114,10 @@ class Order {
|
|||||||
|
|
||||||
check_ajax_referer( 'formipay-order-details', '_wpnonce' );
|
check_ajax_referer( 'formipay-order-details', '_wpnonce' );
|
||||||
|
|
||||||
|
if ( ! current_user_can( 'manage_options' ) ) {
|
||||||
|
wp_send_json_error( [ 'message' => 'Unauthorized' ] );
|
||||||
|
}
|
||||||
|
|
||||||
$order_id = isset($_REQUEST['order']) ? intval($_REQUEST['order']) : 0;
|
$order_id = isset($_REQUEST['order']) ? intval($_REQUEST['order']) : 0;
|
||||||
|
|
||||||
wp_send_json(formipay_get_order($order_id));
|
wp_send_json(formipay_get_order($order_id));
|
||||||
@@ -1104,6 +1127,10 @@ class Order {
|
|||||||
public function formipay_change_order_status() {
|
public function formipay_change_order_status() {
|
||||||
|
|
||||||
check_ajax_referer( 'formipay-order-details', '_wpnonce' );
|
check_ajax_referer( 'formipay-order-details', '_wpnonce' );
|
||||||
|
|
||||||
|
if ( ! current_user_can( 'manage_options' ) ) {
|
||||||
|
wp_send_json_error( [ 'message' => 'Unauthorized' ] );
|
||||||
|
}
|
||||||
|
|
||||||
$order_id = isset($_REQUEST['id']) ? intval($_REQUEST['id']) : 0;
|
$order_id = isset($_REQUEST['id']) ? intval($_REQUEST['id']) : 0;
|
||||||
$status = isset($_REQUEST['status']) ? sanitize_text_field( wp_unslash($_REQUEST['status']) ) : '';
|
$status = isset($_REQUEST['status']) ? sanitize_text_field( wp_unslash($_REQUEST['status']) ) : '';
|
||||||
@@ -1139,6 +1166,10 @@ class Order {
|
|||||||
|
|
||||||
check_ajax_referer( 'formipay-order-details', '_wpnonce' );
|
check_ajax_referer( 'formipay-order-details', '_wpnonce' );
|
||||||
|
|
||||||
|
if ( ! current_user_can( 'manage_options' ) ) {
|
||||||
|
wp_send_json_error( [ 'message' => 'Unauthorized' ] );
|
||||||
|
}
|
||||||
|
|
||||||
$editable_field = [];
|
$editable_field = [];
|
||||||
|
|
||||||
$order_id = isset($_REQUEST['order_id']) ? intval($_REQUEST['order_id']) : 0;
|
$order_id = isset($_REQUEST['order_id']) ? intval($_REQUEST['order_id']) : 0;
|
||||||
@@ -1183,6 +1214,10 @@ class Order {
|
|||||||
|
|
||||||
check_ajax_referer( 'formipay-order-details', '_wpnonce' );
|
check_ajax_referer( 'formipay-order-details', '_wpnonce' );
|
||||||
|
|
||||||
|
if ( ! current_user_can( 'manage_options' ) ) {
|
||||||
|
wp_send_json_error( [ 'message' => 'Unauthorized' ] );
|
||||||
|
}
|
||||||
|
|
||||||
$order_id = isset($_REQUEST['order_id']) ? intval($_REQUEST['order_id']) : 0;
|
$order_id = isset($_REQUEST['order_id']) ? intval($_REQUEST['order_id']) : 0;
|
||||||
// phpcs:ignore WordPress.Security.ValidatedSanitizedInput.InputNotSanitized
|
// phpcs:ignore WordPress.Security.ValidatedSanitizedInput.InputNotSanitized
|
||||||
$raw_data = isset($_REQUEST['new_values']) ? wp_unslash( $_REQUEST['new_values'] ) : [];
|
$raw_data = isset($_REQUEST['new_values']) ? wp_unslash( $_REQUEST['new_values'] ) : [];
|
||||||
@@ -1234,6 +1269,10 @@ class Order {
|
|||||||
|
|
||||||
check_ajax_referer( 'formipay-order-details', '_wpnonce' );
|
check_ajax_referer( 'formipay-order-details', '_wpnonce' );
|
||||||
|
|
||||||
|
if ( ! current_user_can( 'manage_options' ) ) {
|
||||||
|
wp_send_json_error( [ 'message' => 'Unauthorized' ] );
|
||||||
|
}
|
||||||
|
|
||||||
$order_id = isset($_REQUEST['order_id']) ? intval($_REQUEST['order_id']) : 0;
|
$order_id = isset($_REQUEST['order_id']) ? intval($_REQUEST['order_id']) : 0;
|
||||||
$method = isset($_REQUEST['method']) ? sanitize_text_field( wp_unslash($_REQUEST['method']) ) : '';
|
$method = isset($_REQUEST['method']) ? sanitize_text_field( wp_unslash($_REQUEST['method']) ) : '';
|
||||||
$password = isset($_REQUEST['password']) ? sanitize_text_field( wp_unslash($_REQUEST['password']) ) : '';
|
$password = isset($_REQUEST['password']) ? sanitize_text_field( wp_unslash($_REQUEST['password']) ) : '';
|
||||||
|
|||||||
@@ -220,7 +220,6 @@ abstract class Payment {
|
|||||||
'top'
|
'top'
|
||||||
);
|
);
|
||||||
|
|
||||||
flush_rewrite_rules();
|
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -591,6 +591,10 @@ class Product {
|
|||||||
|
|
||||||
check_ajax_referer( 'formipay-admin-product-page', '_wpnonce' );
|
check_ajax_referer( 'formipay-admin-product-page', '_wpnonce' );
|
||||||
|
|
||||||
|
if ( ! current_user_can( 'manage_options' ) ) {
|
||||||
|
wp_send_json_error( [ 'message' => 'Unauthorized' ] );
|
||||||
|
}
|
||||||
|
|
||||||
global $wpdb;
|
global $wpdb;
|
||||||
|
|
||||||
// Initialize default args
|
// Initialize default args
|
||||||
@@ -707,6 +711,10 @@ class Product {
|
|||||||
|
|
||||||
check_ajax_referer( 'formipay-admin-product-page', '_wpnonce' );
|
check_ajax_referer( 'formipay-admin-product-page', '_wpnonce' );
|
||||||
|
|
||||||
|
if ( ! current_user_can( 'manage_options' ) ) {
|
||||||
|
wp_send_json_error( [ 'message' => 'Unauthorized' ] );
|
||||||
|
}
|
||||||
|
|
||||||
$title = isset($_REQUEST['title']) ? sanitize_text_field( wp_unslash($_REQUEST['title']) ) : '';
|
$title = isset($_REQUEST['title']) ? sanitize_text_field( wp_unslash($_REQUEST['title']) ) : '';
|
||||||
|
|
||||||
if( !empty($title) && '' !== $title ){
|
if( !empty($title) && '' !== $title ){
|
||||||
@@ -738,6 +746,10 @@ class Product {
|
|||||||
|
|
||||||
check_ajax_referer( 'formipay-admin-product-page', '_wpnonce' );
|
check_ajax_referer( 'formipay-admin-product-page', '_wpnonce' );
|
||||||
|
|
||||||
|
if ( ! current_user_can( 'manage_options' ) ) {
|
||||||
|
wp_send_json_error( [ 'message' => 'Unauthorized' ] );
|
||||||
|
}
|
||||||
|
|
||||||
$search = isset($_REQUEST['search']) ? sanitize_text_field( wp_unslash($_REQUEST['search']) ) : '';
|
$search = isset($_REQUEST['search']) ? sanitize_text_field( wp_unslash($_REQUEST['search']) ) : '';
|
||||||
|
|
||||||
$countries = formipay_currency_array();
|
$countries = formipay_currency_array();
|
||||||
@@ -762,6 +774,10 @@ class Product {
|
|||||||
|
|
||||||
check_ajax_referer( 'formipay-admin-product-page', '_wpnonce' );
|
check_ajax_referer( 'formipay-admin-product-page', '_wpnonce' );
|
||||||
|
|
||||||
|
if ( ! current_user_can( 'manage_options' ) ) {
|
||||||
|
wp_send_json_error( [ 'message' => 'Unauthorized' ] );
|
||||||
|
}
|
||||||
|
|
||||||
$form_id = isset($_REQUEST['id']) ? intval($_REQUEST['id']) : '';
|
$form_id = isset($_REQUEST['id']) ? intval($_REQUEST['id']) : '';
|
||||||
|
|
||||||
$delete = wp_delete_post($form_id, true);
|
$delete = wp_delete_post($form_id, true);
|
||||||
@@ -786,6 +802,10 @@ class Product {
|
|||||||
|
|
||||||
check_ajax_referer( 'formipay-admin-product-page', '_wpnonce' );
|
check_ajax_referer( 'formipay-admin-product-page', '_wpnonce' );
|
||||||
|
|
||||||
|
if ( ! current_user_can( 'manage_options' ) ) {
|
||||||
|
wp_send_json_error( [ 'message' => 'Unauthorized' ] );
|
||||||
|
}
|
||||||
|
|
||||||
if( empty($_REQUEST['ids']) ){
|
if( empty($_REQUEST['ids']) ){
|
||||||
wp_send_json_error( [
|
wp_send_json_error( [
|
||||||
'title' => esc_html__( 'Failed', 'formipay' ),
|
'title' => esc_html__( 'Failed', 'formipay' ),
|
||||||
@@ -828,6 +848,10 @@ class Product {
|
|||||||
|
|
||||||
check_ajax_referer( 'formipay-admin-product-page', '_wpnonce' );
|
check_ajax_referer( 'formipay-admin-product-page', '_wpnonce' );
|
||||||
|
|
||||||
|
if ( ! current_user_can( 'manage_options' ) ) {
|
||||||
|
wp_send_json_error( [ 'message' => 'Unauthorized' ] );
|
||||||
|
}
|
||||||
|
|
||||||
$post_id = isset($_REQUEST['id']) ? intval($_REQUEST['id']) : '';
|
$post_id = isset($_REQUEST['id']) ? intval($_REQUEST['id']) : '';
|
||||||
$post = get_post($post_id);
|
$post = get_post($post_id);
|
||||||
if (!$post) {
|
if (!$post) {
|
||||||
|
|||||||
@@ -68,7 +68,7 @@ class Render {
|
|||||||
}
|
}
|
||||||
ob_start();
|
ob_start();
|
||||||
|
|
||||||
$timezone = get_option('timezone_string', 'Asia/Jakarta');
|
$timezone = wp_timezone_string();
|
||||||
|
|
||||||
$require_login = formipay_get_post_meta($post_id, 'require_login') === 'on';
|
$require_login = formipay_get_post_meta($post_id, 'require_login') === 'on';
|
||||||
$scheduled = formipay_get_post_meta($post_id, 'schedule_toggle') === 'on';
|
$scheduled = formipay_get_post_meta($post_id, 'schedule_toggle') === 'on';
|
||||||
|
|||||||
@@ -41,7 +41,6 @@ class Thankyou {
|
|||||||
'top'
|
'top'
|
||||||
);
|
);
|
||||||
|
|
||||||
flush_rewrite_rules();
|
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -425,7 +424,7 @@ class Thankyou {
|
|||||||
|
|
||||||
$cookie = $this->get_cookie();
|
$cookie = $this->get_cookie();
|
||||||
$cookie[$order_id] = $order_meta_data['session_id'];
|
$cookie[$order_id] = $order_meta_data['session_id'];
|
||||||
setcookie( 'fp_access', maybe_serialize($cookie), time() + 86400, '/' );
|
setcookie( 'fp_access', wp_json_encode($cookie), time() + 86400, '/', '', is_ssl(), true );
|
||||||
|
|
||||||
if($method == 'magic_link'){
|
if($method == 'magic_link'){
|
||||||
do_action('formipay/notification/access/email', $order);
|
do_action('formipay/notification/access/email', $order);
|
||||||
@@ -678,15 +677,11 @@ class Thankyou {
|
|||||||
if (!empty($_COOKIE['fp_access'])) {
|
if (!empty($_COOKIE['fp_access'])) {
|
||||||
// phpcs:ignore WordPress.Security.ValidatedSanitizedInput.InputNotSanitized
|
// phpcs:ignore WordPress.Security.ValidatedSanitizedInput.InputNotSanitized
|
||||||
$raw_value = wp_unslash($_COOKIE['fp_access']);
|
$raw_value = wp_unslash($_COOKIE['fp_access']);
|
||||||
|
|
||||||
// Validate before unserializing
|
$decoded = json_decode($raw_value, true);
|
||||||
if (is_serialized($raw_value)) { // Use WordPress core function
|
|
||||||
$maybe = maybe_unserialize($raw_value);
|
if (is_array($decoded)) {
|
||||||
|
$cookie = array_map('sanitize_text_field', $decoded);
|
||||||
// Type-check and sanitize array contents
|
|
||||||
if (is_array($maybe)) {
|
|
||||||
$cookie = array_map('sanitize_text_field', $maybe);
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
return $cookie;
|
return $cookie;
|
||||||
|
|||||||
62
uninstall.php
Normal file
62
uninstall.php
Normal file
@@ -0,0 +1,62 @@
|
|||||||
|
<?php
|
||||||
|
/**
|
||||||
|
* Formipay Uninstall
|
||||||
|
*
|
||||||
|
* Removes all plugin data when the plugin is uninstalled via WordPress admin.
|
||||||
|
*/
|
||||||
|
|
||||||
|
if ( ! defined( 'WP_UNINSTALL_PLUGIN' ) ) {
|
||||||
|
exit;
|
||||||
|
}
|
||||||
|
|
||||||
|
global $wpdb;
|
||||||
|
|
||||||
|
// Drop custom tables
|
||||||
|
$tables = [
|
||||||
|
'formipay_orders',
|
||||||
|
'formipay_customers',
|
||||||
|
'formipay_bank_transfer_trx',
|
||||||
|
'formipay_paypal_trx',
|
||||||
|
'formipay_notification_log',
|
||||||
|
'formipay_tokens',
|
||||||
|
];
|
||||||
|
|
||||||
|
foreach ( $tables as $table_suffix ) {
|
||||||
|
// phpcs:ignore WordPress.DB.DirectDatabaseQuery.SchemaChange, WordPress.DB.PreparedSQL.InterpolatedNotPrepared
|
||||||
|
$wpdb->query( "DROP TABLE IF EXISTS {$wpdb->prefix}{$table_suffix}" );
|
||||||
|
}
|
||||||
|
|
||||||
|
// Remove plugin options
|
||||||
|
delete_option( 'formipay_settings' );
|
||||||
|
|
||||||
|
// Clear scheduled cron events
|
||||||
|
$crons = _get_cron_array();
|
||||||
|
if ( ! empty( $crons ) ) {
|
||||||
|
foreach ( $crons as $timestamp => $cron ) {
|
||||||
|
if ( is_array( $cron ) ) {
|
||||||
|
foreach ( $cron as $hook => $events ) {
|
||||||
|
if ( strpos( $hook, 'formipay/' ) === 0 ) {
|
||||||
|
foreach ( $events as $key => $event ) {
|
||||||
|
wp_unschedule_event( $timestamp, $hook, $event['args'] ?? [] );
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// Remove custom post types and their meta
|
||||||
|
$post_types = [ 'formipay-form', 'formipay-product', 'formipay-coupon', 'formipay-access', 'formipay-license' ];
|
||||||
|
foreach ( $post_types as $post_type ) {
|
||||||
|
$posts = get_posts( [
|
||||||
|
'post_type' => $post_type,
|
||||||
|
'numberposts' => -1,
|
||||||
|
'post_status' => 'any',
|
||||||
|
] );
|
||||||
|
foreach ( $posts as $post ) {
|
||||||
|
wp_delete_post( $post->ID, true );
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// Clear any cached data
|
||||||
|
wp_cache_flush();
|
||||||
Reference in New Issue
Block a user