changed plugin name to cipf

This commit is contained in:
asus
2024-03-07 22:35:39 +01:00
parent be79310404
commit 9b5e44dfd3
45 changed files with 0 additions and 0 deletions

View File

@@ -0,0 +1,26 @@
<?php
/*
* it means someone outside wp is accessing the file, in this case kill it.
*/
if (!defined('ABSPATH')) {
die('You can not access this file!');
}
include_once(PLGNTLS_class::get_path() . '/php/utils/http_errors.php');
include_once(PLGNTLS_class::get_path() . '/php/paypal/route_api_utils.php');
include_once(PLGNTLS_class::get_path() . '/php/paypal/user_can_pay.php');
include_once(PLGNTLS_class::get_path() . '/php/paypal/update_user_payment.php');
include_once(PLGNTLS_class::get_path() . '/php/paypal/shortcode.php');
include_once(PLGNTLS_class::get_path() . '/php/paypal/route_api_orders.php');
include_once(PLGNTLS_class::get_path() . '/php/paypal/route_api_orders_capture.php');
include_once(PLGNTLS_class::get_path() . '/php/paypal/routes.php');
?>

View File

@@ -0,0 +1,108 @@
<?php
/*
* it means someone outside wp is accessing the file, in this case kill it.
*/
if (!defined('ABSPATH')) {
die('You can not access this file!');
}
/**
* @see https://developer.paypal.com/docs/checkout/standard/integrate/#link-integratebackend
*/
function handle_orders_request_CIPF($request_data) {
try {
// Extract cart information from request body
//$cart = $request_data['cart'];
$can_pay = can_pay_now_CIPF();
if ($can_pay['success'] === false)
throw new HttpErrorException($can_pay['message'], 403);
// Process the order and get the response
//$order_response = create_order_CIPF($cart);
$order_response = create_order_CIPF();
$json_response = $order_response['json_response'];
$http_status_code = $order_response['http_status_code'];
update_user_payment_CIPF($json_response, 'start');
// Return response
return new WP_REST_Response($json_response, $http_status_code);
}
catch (HttpErrorException $error) {
$status_code = $error->getStatusCode();
return new WP_Error($status_code, 'Failed to create order in server :' . $error->getMessage(), array('status' => $status_code));
}
catch (Exception $error) {
return new WP_Error('500', 'Failed to create order in server :' . $error->getMessage(), array('status' => 500));
}
}
/**
* Create an order to start the transaction.
* @see https://developer.paypal.com/docs/api/orders/v2/#orders_create
*/
//function create_order_CIPF($cart)
function create_order_CIPF()
{
// use the cart information passed from the front-end to calculate the purchase unit details
$access_token = generate_access_token_CIPF();
$user_id = get_current_user_id();
$acf_id = 'user_' . $user_id;
$price = get_field('somme_a_regler', $acf_id);
$url = PAYPAL_API_BASE_URL . '/v2/checkout/orders';
$payload = array(
'intent' => "CAPTURE",
'note' => 'ERRPYO005',
'purchase_units' => array(
array(
'amount' => array(
'currency_code' => "EUR",
'value' => $price,
),
),
),
);
$headers = array(
"Content-Type: application/json",
"Authorization: Bearer " . $access_token
// Uncomment one of these to force an error for negative testing (in sandbox mode only). Documentation:
// https://developer.paypal.com/tools/sandbox/negative-testing/request-headers/
// "PayPal-Mock-Response": '{"mock_application_codes": "MISSING_REQUIRED_PARAMETER"}'
// "PayPal-Mock-Response": '{"mock_application_codes": "PERMISSION_DENIED"}'
// "PayPal-Mock-Response": '{"mock_application_codes": "INTERNAL_SERVER_ERROR"}'
);
// Initialize cURL session
$ch = curl_init();
// Set cURL options
curl_setopt($ch, CURLOPT_URL, $url);
curl_setopt($ch, CURLOPT_POST, true);
curl_setopt($ch, CURLOPT_POSTFIELDS, json_encode($payload));
curl_setopt($ch, CURLOPT_RETURNTRANSFER, true);
curl_setopt($ch, CURLOPT_HTTPHEADER, $headers);
// Execute cURL session and get the response
$response = curl_exec($ch);
if ($response === false)
throw new Exception('cURL error: ' . curl_error($ch));
// Close cURL session
curl_close($ch);
// in utils
return handle_response_CIPF($response);
};
?>

View File

@@ -0,0 +1,73 @@
<?php
/*
* it means someone outside wp is accessing the file, in this case kill it.
*/
if (!defined('ABSPATH')) {
die('You can not access this file!');
}
function handle_orders_capture_request_CIPF($request) {
$order_id = $request['orderID'];
try {
// Implement captureOrder function logic here
// Make sure you implement captureOrder function similar to the Node.js code
$response_data = capture_order_CIPF($order_id);
$http_status_code = $response_data['http_status_code'];
$json_response = $response_data['json_response'];
update_user_payment_CIPF($json_response, 'end');
return new WP_REST_Response($json_response, $http_status_code);
}
catch (Exception $e) {
return new WP_REST_Response(array('error' => 'Failed to capture order.'), 500);
}
}
/**
* Capture payment for the created order to complete the transaction.
* @see https://developer.paypal.com/docs/api/orders/v2/#orders_capture
*/
function capture_order_CIPF($orderID) {
$access_token = generate_access_token_CIPF();
$url = PAYPAL_API_BASE_URL . '/v2/checkout/orders/' . $orderID . '/capture';
$headers = array(
"Content-Type: application/json",
"Authorization: Bearer " . $access_token
// Uncomment one of these to force an error for negative testing (in sandbox mode only). Documentation:
// https://developer.paypal.com/tools/sandbox/negative-testing/request-headers/
// 'PayPal-Mock-Response: {"mock_application_codes": "INSTRUMENT_DECLINED"}',
// 'PayPal-Mock-Response: {"mock_application_codes": "TRANSACTION_REFUSED"}',
// 'PayPal-Mock-Response: {"mock_application_codes": "INTERNAL_SERVER_ERROR"}'
);
// Initialize cURL session
$ch = curl_init();
// Set cURL options
curl_setopt($ch, CURLOPT_URL, $url);
curl_setopt($ch, CURLOPT_POST, true);
curl_setopt($ch, CURLOPT_HTTPHEADER, $headers);
curl_setopt($ch, CURLOPT_RETURNTRANSFER, true);
// Execute cURL session and get the response
$response = curl_exec($ch);
if ($response === false)
throw new Exception('cURL error: ' . curl_error($ch));
// Close cURL session
curl_close($ch);
// in utils
return handle_response_CIPF($response);
};
?>

View File

@@ -0,0 +1,98 @@
<?php
/*
* it means someone outside wp is accessing the file, in this case kill it.
*/
if (!defined('ABSPATH')) {
die('You can not access this file!');
}
/**
* @see https://developer.paypal.com/docs/checkout/standard/integrate/#link-integratebackend
*/
function handle_response_CIPF($response) {
try
{
// Decode JSON response
$json_response = json_decode($response);
return array(
'json_response' => $json_response,
'http_status_code' => http_response_code()
);
}
catch (Exception $err)
{
// Get error message from response
$error_message = $response->text();
throw new Exception($error_message);
}
}
/*
async function handleResponse(response) {
try {
const jsonResponse = await response.json();
return {
jsonResponse,
httpStatusCode: response.status,
};
} catch (err) {
const errorMessage = await response.text();
throw new Error(errorMessage);
}
}
*/
/**
* Generate an OAuth 2.0 access token for authenticating with PayPal REST APIs.
* @see https://developer.paypal.com/docs/checkout/standard/integrate/#link-integratebackend
* @see https://developer.paypal.com/api/rest/authentication/
*/
function generate_access_token_CIPF()
{
try
{
if ( !PAYPAL_CLIENT_ID || !PAYPAL_CLIENT_SECRET ) {
throw new Exception( "MISSING_API_CREDENTIALS" );
}
$credentials = PAYPAL_CLIENT_ID . ":" . PAYPAL_CLIENT_SECRET;
$auth = base64_encode($credentials);
$url = PAYPAL_API_BASE_URL . '/v1/oauth2/token';
$body = http_build_query(array('grant_type' => 'client_credentials'));
// Initialize curl
$ch = curl_init();
// Set curl options
curl_setopt($ch, CURLOPT_URL, $url);
curl_setopt($ch, CURLOPT_POST, true);
curl_setopt($ch, CURLOPT_POSTFIELDS, $body);
curl_setopt($ch, CURLOPT_RETURNTRANSFER, true);
curl_setopt($ch, CURLOPT_HTTPHEADER, array(
'Authorization: Basic ' . $auth,
));
// Execute curl and get the response
$data_json = curl_exec($ch);
if ( $data_json === false)
throw new Exception('cURL error: ' . curl_error($ch));
// Close curl
curl_close($ch);
$data = json_decode($data_json);
return $data->access_token;
}
catch (Exception $error)
{
error_log("Failed to generate Access Token:");
error_log($error->getMessage());
}
};
?>

View File

@@ -0,0 +1,31 @@
<?php
/*
* it means someone outside wp is accessing the file, in this case kill it.
*/
if (!defined('ABSPATH')) {
die('You can not access this file!');
}
// handling routes and endpoints
// diff routes and endpoints : https://stackoverflow.com/q/56075017/9497573
function routes_endpoints_CIPF()
{
$base_rest_route = "cipf_plugin/api/v1";
register_rest_route($base_rest_route, '/orders', array(
'methods' => 'POST',
'callback' => 'handle_orders_request_CIPF',
));
register_rest_route($base_rest_route, '/orders/(?P<orderID>[a-zA-Z0-9]+)/capture', array(
'methods' => 'POST',
'callback' => 'handle_orders_capture_request_CIPF',
));
};
add_action('rest_api_init', 'routes_endpoints_CIPF');
?>

View File

@@ -0,0 +1,59 @@
<?php
/*
* it means someone outside wp is accessing the file, in this case kill it.
*/
if (!defined('ABSPATH')) {
die('You can not access this file!');
}
/**
* call to paypal_shortcode_content()
*/
function paypal_shortcode_content_CIPF()
{
// if (!can_pay_now_CIPF())
// return no_payment_CIPF();
$cipfcard_paypal = new PLGNTLS_class();
$pp_client_id = PAYPAL_CLIENT_ID;
$pp_sdk_currency = "EUR";
$pp_sdk_base_url = "https://www.paypal.com";
$pp_sdk_url = "{$pp_sdk_base_url}/sdk/js?client-id={$pp_client_id}&currency={$pp_sdk_currency}";
$paypal_redirection_success = PAYPAL_REDIRECTION_SUCCESS;
$paypal_redirection_failure = PAYPAL_REDIRECTION_FAILURE;
$paypal_message_success = PAYPAL_MESSAGE_SUCCESS;
$paypal_message_failure = PAYPAL_MESSAGE_FAILURE;
$added_to_front = $cipfcard_paypal->add_to_front(
array(
$pp_sdk_url,
array("js/paypal/paypal.js", 'type'=>'module'),
"html/paypal/paypal.html",
),
compact (
'paypal_redirection_success',
'paypal_redirection_failure',
'paypal_message_success',
'paypal_message_failure',
),
);
return $added_to_front;
}
add_shortcode('cipf_paypal_shortcode', 'paypal_shortcode_content_CIPF');
function no_payment_CIPF() {
return;
}
?>

View File

@@ -0,0 +1,221 @@
<?php
/*
* it means someone outside wp is accessing the file, in this case kill it.
*/
if (!defined('ABSPATH')) {
die('You can not access this file!');
}
/*
* see documentation in private 'paypal.md'
* basically it check if the user who initiate the transaction
* is the same that finish it
*
* add_user_meta('user_id', 'cipf_order_id', 'aaaaaa');
* ['aaaaaa']
* add_user_meta('user_id', 'cipf_order_id', 'bbbbbb');
* ['aaaaaa', 'bbbbbb']
* add_user_meta('user_id', 'cipf_order_id', 'bbbbbb');
* ['aaaaaa', 'bbbbbb', 'bbbbbb']
* get_user_meta('user_id', 'cipf_order_id');
* ['aaaaaa', 'bbbbbb', 'bbbbbb']
* $del_ret = delete_user_meta('user_id', 'cipf_order_id', 'bbbbbb');
* ['aaaaaa'] - $del_ret === true
* $del_ret = delete_user_meta('user_id', 'cipf_order_id', 'bbbbbb');
* ['aaaaaa'] - $del_ret === false
*
* order status : https://developer.paypal.com/docs/api/orders/v2/#orders_capture!c=201&path=status&t=response
* CREATED
* SAVED
* APPROVED ?
* VOIDED
* - COMPLETED
* PAYER_ACTION_REQUIRED
*
*/
function update_user_payment_CIPF($message, $step) {
$order_id = $message->id;
$user_id = get_current_user_id();
$status = $message->status;
// addind order_id to cipf_order_id meta field
// it can duplicate, it's not a problem : delete_user_meta will delete all
add_user_meta($user_id, 'cipf_order_id', $order_id);
// add a schedule event to delete this order_id
schedule_delete_orderid_CIPF($user_id, $order_id);
/*
* create a meta field to check states of payements on prof author page :
* - 'started' -> payement started | at order creation (if seen on author page, it means failure)
* - 'success' -> success payement | at order success (on author page, it means success, then empty it)
* - '' -> no message to output | on author page (after set to empty on author page)
*
*/
delete_user_meta($user_id, 'cipf_payement_status');
add_user_meta($user_id, 'cipf_payement_status', 'started');
// if transaction is COMPLETED, then delete order_id and update user
if ($status === 'COMPLETED') {
// find the user containing the order_id and delete this order_id
$user_id_to_update = delete_order_id_on_success_CIPF($user_id, $order_id);
// change payement status to success
update_user_meta($user_id_to_update, 'cipf_payement_status', 'success');
// proceed to validate payment for user
validate_payment_for_user_CIPF($user_id_to_update, $order_id);
}
}
/*
* const CARD_IS_VALID : acf field 'true false' [carte_est_valide](validite)
* const CARD_DATE_PURCHASE : acf field 'date picker' [date_d_achat](achat)
* const CARD_DATE_VALIDITY : acf field 'date picker' [date_fin_validite](echance)
*
* - change CARD_IS_VALID to true
* - change CARD_DATE_PURCHASE to now
* - change CARD_DATE_VALIDITY to previous value + 1 year
*
* - create scheduled emails to inform of end of validity
*
* acf uses 'Y-m-d H:i:s' format :
* -> https://www.advancedcustomfields.com/resources/date-time-picker/
*
*/
function validate_payment_for_user_CIPF($user_id, $order_id) {
$acf_card_state = PLGNTLS_class::ACF_CARD_STATE;
$acf_card_expiration = PLGNTLS_class::ACF_CARD_EXPIRATION;
$card_duration = PLGNTLS_class::CARD_VALIDITY_TIME;
$prof_is_activ = PLGNTLS_class::ACF_PROF_IS_ACTIV;
$acf_date_format = 'Y-m-d H:i:s';
$acf_id = 'user_'.$user_id;
/*
* update card validity to true
*
*/
update_field($acf_card_state, 'Renouvellement', $acf_id);
$date_now = date_create('today');
/*
* update purchase date to now
*
update_field(CARD_DATE_PURCHASE, $date_now, $acf_id);
*/
/*
* get current date limit
* if no date, use now
* if paste date, use now
*
*/
$current_date_limit_object = get_field_object($acf_card_expiration, $acf_id);
if ($current_date_limit_object === false) {
$current_date_limit = $date_now;
}
else if (empty($current_date_limit_object['value'])) {
$current_date_limit = $date_now;
}
else
{
$current_date_limit_string = $current_date_limit_object['value'];
$current_format_field = $current_date_limit_object['return_format'];
// compare 2 dates : https://stackoverflow.com/q/8722806/9497573
// also I dont use strtotime to compare 2 ints,
// because i don't know if it will fail one day (2000 bug alike)
$current_date_limit = date_create_from_format($current_format_field, $current_date_limit_string);
$date_diff = date_diff($date_now, $current_date_limit);
$date_is_in_past = $date_diff->format('%R%a') < 0;
if ($date_is_in_past)
$current_date_limit = $date_now;
}
/*
* update date limit validity to add 1 year
*
*/
$date_plus_one_year = $current_date_limit->add(date_interval_create_from_date_string('+'.$card_duration));
update_field($acf_card_expiration, $date_plus_one_year->format($acf_date_format), $acf_id);
/*
* change user profil to active
*
*/
update_field($prof_is_activ, 'Actif', $acf_id);
}
/*
* add a schedule event to delete this order_id
* after 3 days ?
* time() + 60 = one minute from now
* time() + MINUTE_IN_SECONDS = one minute from now
* -> https://codex.wordpress.org/Easier_Expression_of_Time_Constants
* -> also strtotime : https://www.php.net/manual/en/function.strtotime.php
*
*/
function schedule_delete_orderid_CIPF($user_id, $order_id)
{
$delay = time() + MINUTE_IN_SECONDS;
wp_schedule_single_event($delay, 'orderid_deletion_event_CIPF', array($user_id, $order_id));
}
/*
* action hook for the scheduled event
* TODO: ne marche pas je ne sais pas pourquoi, pas urgent a resoudre
*
*/
function delete_order_id_later_CIPF($user_id, $order_id)
{
delete_user_meta($user_id, 'cipf_order_id', $order_id);
}
add_action('orderid_deletion_event_CIPF', 'delete_order_id_later_CIPF', 5, 2);
/*
* @return mixed num - user_id
* bool false - if no match found
*
*/
function delete_order_id_on_success_CIPF($current_user_id, $order_id)
{
$del_ret = delete_user_meta($current_user_id, 'cipf_order_id', $order_id);
if ($del_ret === true)
return $current_user_id;
// it means the current user didn't have this order_id
// so we look for another user
$users = get_users();
foreach ($users as $user)
{
$user_id = $user->ID;
$del_ret = delete_user_meta($user_id, 'cipf_order_id', $order_id);
if ($del_ret === true)
return $user_id;
}
return false;
}
?>

View File

@@ -0,0 +1,95 @@
<?php
/*
* can pay in certain conditions
* default true
*/
function can_pay_now_CIPF() {
$acf_card_state = PLGNTLS_class::ACF_CARD_STATE;
$acf_card_payment_method = PLGNTLS_class::ACF_CARD_PAYMENT_METHOD;
$acf_card_price_choice = PLGNTLS_class::ACF_CARD_PRICE_CHOICE;
$acf_card_price_delivery = PLGNTLS_class::ACF_CARD_PRICE_DELIVERY;
$acf_card_price_total = PLGNTLS_class::ACF_CARD_PRICE_TOTAL;
$acf_card_expiration = PLGNTLS_class::ACF_CARD_EXPIRATION;
$card_renew_period = PLGNTLS_class::CARD_RENEW_PERIOD;
$current_user = wp_get_current_user();
$user_id = get_current_user_id();
$acf_id = 'user_' . $user_id;
/*
* check if payment is virement or immediat
*
$payement = get_field($acf_card_payment_method, $acf_id);
if (strtolower($payement) === 'virement') {
return false;
}
*/
/*
* calculate price
* update the price even if form builder already did it
* in case it was changed from admin pannel
*
*/
$tarif = (int)get_field($acf_card_price_choice, $acf_id);
$livraison = (int)get_field($acf_card_price_delivery, $acf_id);
$price = $tarif + $livraison;
update_field($acf_card_price_total, $price, $acf_id);
/*
* price is not empty or 0
*
*/
$price = get_field($acf_card_price_total, $acf_id);
if (empty($price)) {
return array('success' => false, 'message' => "error: no price selected");
}
if ($price === 0) {
return array('success' => false, 'message' => "error: price is 0, nothing to purchase");
}
/*
* date validity is empty
* or is paste
* or is less than 1 month
*
*/
$validity_field = get_field_object($acf_card_expiration, $acf_id);
if ($validity_field === false)
return array('success' => true);
$validity = $validity_field['value'];
$format_field = $validity_field['return_format'];
if (empty($validity))
return array('success' => true);
$date_validity = date_create_from_format($format_field, $validity);
$date_now = date_create('today');
$diff = date_diff($date_now, $date_validity)->format('%R%a');
if ((int)$diff <= 0) {
// date end of validity in the past
return array('success' => true);
}
else if ((int)$diff <= $card_renew_period) {
// date expiration is in less that renew period time (ex: 30 days)
return array('success' => true);
}
else {
// date end of validity is in more than renew perdio (ex: 3 month)
return array('success' => false, 'message' => "error: it's too soon to renew your card");
}
return array('success' => true);
}
?>