diff --git a/plugins/fipfcard_plugin/fipfcard_plugin.php b/plugins/fipfcard_plugin/fipfcard_plugin.php index 3efe43a..355614f 100644 --- a/plugins/fipfcard_plugin/fipfcard_plugin.php +++ b/plugins/fipfcard_plugin/fipfcard_plugin.php @@ -8,27 +8,18 @@ Version: 1.1.0 Author URI: */ -/* -5.5 . 5.48 -59 . 58.99 -50.6 . 50.58 -38.5 . 38.53 -99.8 . 99.84 -25.2 . 25.17 -131.6 . 135 -63.7 . 63.68 -85 . 85.05 -50.2 . 50.17 -41.4 . 41.43 -18.8 . 18.82 -*/ +/** + * it means someone outside wp is accessing the file, in this case kill it. + */ +if (!defined('ABSPATH')) { + die('You can not access this file!'); +} -/* - * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * -plugin dir root -*/ +/** + * plugin dir root + */ include_once( plugin_dir_path(__FILE__) . '/utils/plugin_tools.php'); PLGNTLS_class::set_root_dir( plugin_dir_path(__FILE__), plugin_dir_url(__FILE__) ); diff --git a/plugins/fipfcard_plugin/js/paypal/paypal.js b/plugins/fipfcard_plugin/js/paypal/paypal.js index 5e720ef..82469e0 100644 --- a/plugins/fipfcard_plugin/js/paypal/paypal.js +++ b/plugins/fipfcard_plugin/js/paypal/paypal.js @@ -66,61 +66,99 @@ paypal.Buttons({ window.paypal.Buttons({ - createOrder: function(data, actions) { -// PLGNTLS_fetch("paypal_api_orders", { -// //method: "POST", -// //headers: {"Content-Type": "application/json"}, -// body: JSON.stringify({ -// cart: [ -// { -// id: "1234", -// quantity: "1", -// }, -// ], -// }), -// }) - fetch(PLGNTLS_data.fetch_url + "/fipf-plugin/v1/orders", { - method: "POST", - headers: { - "Content-Type": "application/json" - }, - body: JSON.stringify({ - cart: [ - { - id: "1234", - quantity: "1", - }, - ], - }), - }) - .then((response) => response.json()) - .then((order_data) => - { - if (order_data.id) - return order_data.id; - else - { - // https://developer.paypal.com/docs/checkout/standard/integrate/#link-integratefrontend - console.log("inside error"); + async createOrder() { + try { + const response = await fetch(PLGNTLS_data.fetch_url + "/fipf_plugin/api/v1/orders", { + method: "POST", + headers: { + "Content-Type": "application/json", + }, + // use the "body" param to optionally pass additional order information + // like product ids and quantities + body: JSON.stringify({ + cart: [ + { + id: "1234", + quantity: "1", + }, + ], + }), + }); + + const orderData = await response.json(); + + if (orderData.id) { + return orderData.id; + } else { const errorDetail = orderData?.details?.[0]; const errorMessage = errorDetail ? `${errorDetail.issue} ${errorDetail.description} (${orderData.debug_id})` : JSON.stringify(orderData); + throw new Error(errorMessage); } - }) - .catch((error) => { + } catch (error) { console.error(error); - resultMessage('Could not initiate PayPal Checkout...
(see console.log() errors)'); - }) + resultMessage(`Could not initiate PayPal Checkout...

${error}`); + } }, - + async onApprove(data, actions) { + try { + const fetch_url = PLGNTLS_data.fetch_url + "/fipf_plugin/api/v1/orders/" + data.orderID + "/capture"; + console.log("fetch_url:"); + console.log(fetch_url); + const response = await fetch(fetch_url, { + method: "POST", + headers: { + "Content-Type": "application/json", + }, + }); + + const orderData = await response.json(); + // Three cases to handle: + // (1) Recoverable INSTRUMENT_DECLINED -> call actions.restart() + // (2) Other non-recoverable errors -> Show a failure message + // (3) Successful transaction -> Show confirmation or thank you message + + const errorDetail = orderData?.details?.[0]; + + if (errorDetail?.issue === "INSTRUMENT_DECLINED") { + // (1) Recoverable INSTRUMENT_DECLINED -> call actions.restart() + // recoverable state, per https://developer.paypal.com/docs/checkout/standard/customize/handle-funding-failures/ + return actions.restart(); + } else if (errorDetail) { + // (2) Other non-recoverable errors -> Show a failure message + throw new Error(`${errorDetail.description} (${orderData.debug_id})`); + } else if (!orderData.purchase_units) { + throw new Error(JSON.stringify(orderData)); + } else { + // (3) Successful transaction -> Show confirmation or thank you message + // Or go to another URL: actions.redirect('thank_you.html'); + const transaction = + orderData?.purchase_units?.[0]?.payments?.captures?.[0] || + orderData?.purchase_units?.[0]?.payments?.authorizations?.[0]; + resultMessage( + `Transaction ${transaction.status}: ${transaction.id}

See console for all available details`, + ); + console.log( + "Capture result", + orderData, + JSON.stringify(orderData, null, 2), + ); + } + } catch (error) { + console.error(error); + resultMessage( + `Sorry, your transaction could not be processed...

${error}`, + ); + } + }, /* onApprove: function(data, actions) { console.log("--data:"); console.log(data); - PLGNTLS_fetch(`/api/orders/${data.orderID}/capture`, { + fetch(`${PLGNTLS_data.fetch_url}/fipf_plugin/api/v1/orders/${data.orderID}/capture`, { method: "POST", headers: { "Content-Type": "application/json", diff --git a/plugins/fipfcard_plugin/php/images/image-edit.php b/plugins/fipfcard_plugin/php/images/image-edit.php index 7fd11df..a11c58b 100644 --- a/plugins/fipfcard_plugin/php/images/image-edit.php +++ b/plugins/fipfcard_plugin/php/images/image-edit.php @@ -1,4 +1,13 @@ 'POST', + 'callback' => 'handle_orders_request', + )); + // https://local_fipfcard_plugin.com/wp-json/fipf_plugin/api/v1/orders/21T129305J264761D/capture + register_rest_route($base_rest_route, '/orders/(?P[a-zA-Z0-9]+)/capture', array( + 'methods' => 'POST', + 'callback' => 'handle_orders_capture_request', + )); +}; +add_action('rest_api_init', 'fipf_routes_endpoints'); + + + ?> diff --git a/plugins/fipfcard_plugin/php/paypal/route_api_orders.php b/plugins/fipfcard_plugin/php/paypal/route_api_orders.php index 8ecee1b..0d9a520 100644 --- a/plugins/fipfcard_plugin/php/paypal/route_api_orders.php +++ b/plugins/fipfcard_plugin/php/paypal/route_api_orders.php @@ -1,50 +1,17 @@ cart; - $order_response = create_order($cart); - error_log( "order_response[json_response]" ); - error_log( json_encode( $order_response['json_response'] ) ); - - wp_send_json_success($order_response['json_response'], $order_response['http_status_code']); - } - catch (Exception $err) - { - error_log('Failed to create order: ' . $err->getMessage()); - wp_send_json_error(array('error' => 'Failed to create order')); - } - -} -add_action( 'wp_ajax_paypal_api_orders', 'fipfcard_paypal_orders' ); - - - -// Endpoints for handling routes -function fipf_routes_endpoints() -{ - register_rest_route('fipf-plugin/v1', '/orders', array( - 'methods' => 'POST', - 'callback' => 'handle_orders_request', - )); -}; -add_action('rest_api_init', 'fipf_routes_endpoints'); -// Callback function for handling orders function handle_orders_request($request_data) { try { // Extract cart information from request body @@ -74,8 +41,6 @@ function create_order( $cart ) // use the cart information passed from the front-end to calculate the purchase unit details $access_token = generate_access_token(); - error_log("access_token:"); - error_log($access_token); $url = PAYPAL_API_BASE_URL . '/v2/checkout/orders'; $payload = array( @@ -90,6 +55,15 @@ function create_order( $cart ) ), ); + $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 @@ -97,15 +71,7 @@ function create_order( $cart ) 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, 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"}' - )); + curl_setopt($ch, CURLOPT_HTTPHEADER, $headers); // Execute cURL session and get the response $response = curl_exec($ch); @@ -122,51 +88,4 @@ function create_order( $cart ) -/** - * 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() -{ - 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()); - } -}; - - ?> diff --git a/plugins/fipfcard_plugin/php/paypal/route_api_orders_capture.php b/plugins/fipfcard_plugin/php/paypal/route_api_orders_capture.php new file mode 100644 index 0000000..7792809 --- /dev/null +++ b/plugins/fipfcard_plugin/php/paypal/route_api_orders_capture.php @@ -0,0 +1,71 @@ +getMessage()); + 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 captureOrder($orderID) { + $access_token = generate_access_token(); + $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(response); +}; + + + +?> diff --git a/plugins/fipfcard_plugin/php/paypal/route_api_utils.php b/plugins/fipfcard_plugin/php/paypal/route_api_utils.php index ecf0404..eebd1f1 100644 --- a/plugins/fipfcard_plugin/php/paypal/route_api_utils.php +++ b/plugins/fipfcard_plugin/php/paypal/route_api_utils.php @@ -1,5 +1,12 @@ '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()); + } +}; + ?> diff --git a/plugins/fipfcard_plugin/php/test_cache.php b/plugins/fipfcard_plugin/php/test_cache.php index 6b96bd4..62c931e 100644 --- a/plugins/fipfcard_plugin/php/test_cache.php +++ b/plugins/fipfcard_plugin/php/test_cache.php @@ -1,5 +1,14 @@