Changeset 2635881
- Timestamp:
- 11/26/2021 02:22:43 PM (4 years ago)
- Location:
- ventipay
- Files:
-
- 4 added
- 2 deleted
- 8 edited
- 1 copied
-
tags/1.2.0 (copied) (copied from ventipay/trunk)
-
tags/1.2.0/assets/css (added)
-
tags/1.2.0/assets/css/ventipay-style.css (added)
-
tags/1.2.0/assets/images (deleted)
-
tags/1.2.0/includes/class-wc-gateway-ventipay-bnpl.php (modified) (5 diffs)
-
tags/1.2.0/includes/class-wc-gateway-ventipay.php (modified) (5 diffs)
-
tags/1.2.0/readme.txt (modified) (1 diff)
-
tags/1.2.0/ventipay.php (modified) (2 diffs)
-
trunk/assets/css (added)
-
trunk/assets/css/ventipay-style.css (added)
-
trunk/assets/images (deleted)
-
trunk/includes/class-wc-gateway-ventipay-bnpl.php (modified) (5 diffs)
-
trunk/includes/class-wc-gateway-ventipay.php (modified) (5 diffs)
-
trunk/readme.txt (modified) (1 diff)
-
trunk/ventipay.php (modified) (2 diffs)
Legend:
- Unmodified
- Added
- Removed
-
ventipay/tags/1.2.0/includes/class-wc-gateway-ventipay-bnpl.php
r2595906 r2635881 17 17 { 18 18 $this->id = 'ventipay_bnpl'; 19 $this->icon = plugin_dir_url(__FILE__) . '../assets/images/plugin-woocommerce-icon-bnpl.png';19 $this->icon = 'https://pay.ventipay.com/assets/apps/woocommerce/plugin-woocommerce-icon-bnpl.svg'; 20 20 $this->has_fields = false; 21 21 $this->method_title = __('Venti', 'ventipay'); … … 62 62 ), 63 63 'default' => __( 64 ' Paga en cuotas con débito',64 'Venti: Paga en cuotas con débito', 65 65 'ventipay' 66 66 ), … … 80 80 ], 81 81 'testmode' => [ 82 'title' => __('Habilitar modo Pruebas', 'ventipay'),83 'label' => __(' Si habilitas esta opción podrás hacer pruebas de integración sin aceptar pagos reales.', 'ventipay'),82 'title' => __('Habilitar Modo Pruebas', 'ventipay'), 83 'label' => __('Atención: Si habilitas esta opción no se realizarán cargos reales a los clientes. Habilita este modo solo si necesitas realizar pruebas de integración.', 'ventipay'), 84 84 'type' => 'checkbox', 85 85 'default' => 'yes', … … 88 88 'title' => __('Credenciales API', 'ventipay'), 89 89 'type' => 'title', 90 'description' => __('Podrás encontrar tus API Keys en la sección Desarrolladores del Dashboard', 'ventipay'),90 'description' => __('Podrás encontrar tus API Keys en la sección Desarrolladores > API del Dashboard', 'ventipay'), 91 91 ], 92 92 'test_api_key' => [ … … 237 237 public function ventipay_process_ipn() 238 238 { 239 try { 240 $order = wc_get_order($_GET['order_id']); 241 242 /** 243 * Check if it's a valid order 244 */ 245 if (!isset($order) || !$order->get_id()) { 246 header('HTTP/1.1 400 Bad Request (Order ID Not Found)'); 239 $order = wc_get_order($_GET['order_id']); 240 241 /** 242 * Check if it's a valid order 243 */ 244 if (!isset($order) || !$order->get_id()) { 245 header('HTTP/1.1 400 Bad Request (Order ID Not Found)'); 246 return; 247 } 248 249 /** 250 * The order is already paid so we redirect the user to a success page 251 */ 252 if ($order->is_paid()) { 253 header('HTTP/1.1 200 OK (Order Is Paid)'); 254 return; 255 } 256 257 /** 258 * The order is valid and it's ready to be paid 259 */ 260 if ($order->needs_payment()) { 261 /** 262 * Stored loan intent ID 263 */ 264 $meta_loan_intent_id = $order->get_meta('ventipay_loan_intent_id'); 265 266 /** 267 * Recieved loan intent ID 268 */ 269 $posted_body = json_decode(file_get_contents('php://input')); 270 $posted_loan_intent_id = isset($posted_body) && !empty($posted_body->data) && !empty($posted_body->data->id) ? $posted_body->data->id : null; 271 272 /** 273 * We check if the stored ID looks like a valid one and both (stored and received) are equal 274 * This is a simple check, however it should be enough to control MITM tampering. 275 * Eventually we could check for a valid signature just like regular webhooks 276 */ 277 if (!empty($meta_loan_intent_id) 278 && substr($meta_loan_intent_id, 0, 3) === 'li_' 279 && !empty($posted_loan_intent_id) 280 && $meta_loan_intent_id === $posted_loan_intent_id) 281 { 282 /** 283 * We retrieve the loan intent 284 */ 285 $retrieve_loan_intent = wp_remote_get( 286 self::API_ENDPOINT . '/loan-intents/' . $meta_loan_intent_id, 287 [ 288 'headers' => [ 289 'Authorization' => 'Basic ' . base64_encode($this->api_key . ':'), 290 'Content-Type' => 'application/json', 291 ], 292 'timeout' => 45, 293 ] 294 ); 295 296 if (is_wp_error($retrieve_loan_intent)) { 297 header('HTTP/1.1 400 Bad Request (Unable To Retrieve Payment)'); 298 return; 299 } 300 301 $retrieved_loan_intent = json_decode(wp_remote_retrieve_body($retrieve_loan_intent)); 302 $amount = (int) number_format($order->get_total(), 0, ',', ''); 303 304 /** 305 * We run some basic checks to make sure the order data matches the loan intent data. 306 */ 307 if (isset($retrieved_loan_intent) 308 && !empty($retrieved_loan_intent->id) 309 && !empty($retrieved_loan_intent->amount) 310 && !empty($retrieved_loan_intent->currency) 311 && !empty($order->get_currency()) 312 && !empty($retrieved_loan_intent->object) 313 && !empty($retrieved_loan_intent->status) 314 && 'loan_intent' === $retrieved_loan_intent->object 315 && $retrieved_loan_intent->id === $meta_loan_intent_id) 316 { 317 /** 318 * Does the payment looks good (status is approved and amount and currency matches)? 319 */ 320 if ('approved' === $retrieved_loan_intent->status 321 && strtolower($retrieved_loan_intent->currency) === strtolower($order->get_currency()) 322 && $retrieved_loan_intent->amount === $amount) 323 { 324 /** 325 * We attempt to authorize the approved loan intent. 326 * If it wasn't approved or it's already authorized, the API will sent an error. 327 */ 328 $authorize_loan_intent = wp_remote_post( 329 self::API_ENDPOINT . '/loan-intents/' . $meta_loan_intent_id . '/authorize', 330 [ 331 'headers' => [ 332 'Authorization' => 'Basic ' . base64_encode($this->api_key . ':'), 333 'Content-Type' => 'application/json', 334 ], 335 'timeout' => 120, 336 ] 337 ); 338 339 if (!is_wp_error($authorize_loan_intent)) { 340 /** 341 * Authorized payment data 342 */ 343 $authorized_loan_intent = json_decode(wp_remote_retrieve_body($authorize_loan_intent)); 344 345 /** 346 * Check if the payment was properly captured and authorized 347 */ 348 if (isset($authorized_loan_intent) 349 && !empty($authorized_loan_intent->status) 350 && 'authorized' === $authorized_loan_intent->status) 351 { 352 $order->payment_complete(); 353 header('HTTP/1.1 200 OK (Payment Completed)'); 354 return; 355 } else { 356 header('HTTP/1.1 400 Bad Request (Unable To Authorize'); 357 return; 358 } 359 } else { 360 header('HTTP/1.1 400 Bad Request (Unable To Authorize)'); 361 return; 362 } 363 } elseif ('authorized' === $retrieved_loan_intent->status 364 && strtolower($retrieved_loan_intent->currency) === strtolower($order->get_currency()) 365 && $retrieved_loan_intent->amount === $amount) 366 { 367 $order->payment_complete(); 368 header('HTTP/1.1 200 OK (Payment Completed)'); 369 return; 370 } else { 371 $order->update_status('failed'); 372 header('HTTP/1.1 400 Bad Request (Invalid Payment Status'); 373 return; 374 } 375 } 376 header('HTTP/1.1 400 Bad Request (Posted Payment Data Mismatch)'); 247 377 return; 248 378 } 249 250 /** 251 * The order is already paid so we redirect the user to a success page 252 */ 253 if ($order->is_paid()) { 254 header('HTTP/1.1 200 OK (Order Is Paid)'); 255 return; 256 } 257 258 /** 259 * The order is valid and it's ready to be paid 260 */ 261 if ($order->needs_payment()) { 262 /** 263 * Stored loan intent ID 264 */ 265 $meta_loan_intent_id = $order->get_meta('ventipay_loan_intent_id'); 266 267 /** 268 * Recieved loan intent ID 269 */ 270 $posted_body = json_decode(file_get_contents('php://input')); 271 $posted_loan_intent_id = isset($posted_body) && !empty($posted_body->data) && !empty($posted_body->data->id) ? $posted_body->data->id : null; 272 273 /** 274 * We check if the stored ID looks like a valid one and both (stored and received) are equal 275 * This is a simple check, however it should be enough to control MITM tampering. 276 * Eventually we could check for a valid signature just like regular webhooks 277 */ 278 if (!empty($meta_loan_intent_id) 279 && substr($meta_loan_intent_id, 0, 3) === 'li_' 280 && !empty($posted_loan_intent_id) 281 && $meta_loan_intent_id === $posted_loan_intent_id) 282 { 283 /** 284 * We retrieve the loan intent 285 */ 286 $retrieve_loan_intent = wp_remote_get( 287 self::API_ENDPOINT . '/loan-intents/' . $meta_loan_intent_id, 288 [ 289 'headers' => [ 290 'Authorization' => 'Basic ' . base64_encode($this->api_key . ':'), 291 'Content-Type' => 'application/json', 292 ], 293 'timeout' => 45, 294 ] 295 ); 296 297 if (is_wp_error($retrieve_loan_intent)) { 298 header('HTTP/1.1 400 Bad Request (Unable To Retrieve Payment)'); 299 return; 300 } 301 302 $retrieved_loan_intent = json_decode(wp_remote_retrieve_body($retrieve_loan_intent)); 303 $amount = (int) number_format($order->get_total(), 0, ',', ''); 304 305 /** 306 * We run some checks to make sure the order data matches the loan intent data. 307 */ 308 if (empty($retrieved_loan_intent) 309 || empty($retrieved_loan_intent->id) 310 || empty($retrieved_loan_intent->amount) 311 || empty($retrieved_loan_intent->currency) 312 || empty($order->get_currency()) 313 || empty($retrieved_loan_intent->object) 314 || empty($retrieved_loan_intent->status) 315 || 'loan_intent' !== $retrieved_loan_intent->object 316 || 'approved' !== $retrieved_loan_intent->status 317 || strtolower($retrieved_loan_intent->currency) !== strtolower($order->get_currency()) 318 || $retrieved_loan_intent->amount !== $amount 319 || $retrieved_loan_intent->id !== $meta_loan_intent_id) 320 { 321 $order->update_status('failed'); 322 header('HTTP/1.1 400 Bad Request (Posted Payment Data Mismatch)'); 323 return; 324 } 325 326 /** 327 * We attempt to authorize the approved loan intent. 328 * If it wasn't approved or it's already authorized, the API will sent an error. 329 */ 330 $authorize_loan_intent = wp_remote_post( 331 self::API_ENDPOINT . '/loan-intents/' . $meta_loan_intent_id . '/authorize', 332 [ 333 'headers' => [ 334 'Authorization' => 'Basic ' . base64_encode($this->api_key . ':'), 335 'Content-Type' => 'application/json', 336 ], 337 'timeout' => 120, 338 ] 339 ); 340 341 if (!is_wp_error($authorize_loan_intent)) { 342 /** 343 * Captured payment data 344 */ 345 $authorized_loan_intent = json_decode(wp_remote_retrieve_body($authorize_loan_intent)); 346 347 /** 348 * Check if the payment was properly captured 349 */ 350 if (isset($authorized_loan_intent) 351 && !empty($authorized_loan_intent->status) 352 && 'authorized' === $authorized_loan_intent->status) 353 { 354 $order->payment_complete(); 355 header('HTTP/1.1 200 OK (Payment Completed)'); 356 return; 357 } 358 } 359 header('HTTP/1.1 400 Bad Request (Unable To Authorize Payment)'); 360 return; 361 } 362 $order->update_status('failed'); 363 header('HTTP/1.1 400 Bad Request (Posted Payment ID Mismatch)'); 364 return; 365 } 366 header('HTTP/1.1 400 Bad Request (Order Not Ready To Be Paid)'); 379 header('HTTP/1.1 400 Bad Request (Posted Payment ID Mismatch)'); 367 380 return; 368 } catch (Exception $e) {369 header('HTTP/1.1 500 Server Error');370 381 } 382 header('HTTP/1.1 400 Bad Request (Order Not Ready To Be Paid)'); 383 return; 371 384 } 372 385 -
ventipay/tags/1.2.0/includes/class-wc-gateway-ventipay.php
r2595906 r2635881 17 17 { 18 18 $this->id = 'ventipay'; 19 $this->icon = plugin_dir_url(__FILE__) . '../assets/images/plugin-woocommerce-icon-cards.png';19 $this->icon = 'https://pay.ventipay.com/assets/apps/woocommerce/plugin-woocommerce-icon-cards.svg'; 20 20 $this->has_fields = false; 21 21 $this->method_title = __('Venti', 'ventipay'); … … 62 62 ), 63 63 'default' => __( 64 ' Tarjeta de Crédito/Débito/Prepago',64 'Venti: Tarjeta de Crédito/Débito/Prepago', 65 65 'ventipay' 66 66 ), … … 80 80 ], 81 81 'testmode' => [ 82 'title' => __('Habilitar modo Pruebas', 'ventipay'),83 'label' => __(' Si habilitas esta opción podrás hacer pruebas de integración sin aceptar pagos reales.', 'ventipay'),82 'title' => __('Habilitar Modo Pruebas', 'ventipay'), 83 'label' => __('Atención: Si habilitas esta opción no se realizarán cargos reales a los clientes. Habilita este modo solo si necesitas realizar pruebas de integración.', 'ventipay'), 84 84 'type' => 'checkbox', 85 85 'default' => 'yes', … … 88 88 'title' => __('Credenciales API', 'ventipay'), 89 89 'type' => 'title', 90 'description' => __('Podrás encontrar tus API Keys en la sección Desarrolladores del Dashboard', 'ventipay'),90 'description' => __('Podrás encontrar tus API Keys en la sección Desarrolladores > API del Dashboard', 'ventipay'), 91 91 ], 92 92 'test_api_key' => [ … … 233 233 public function ventipay_process_ipn() 234 234 { 235 try { 236 $order = wc_get_order($_GET['order_id']); 237 238 /** 239 * Check if it's a valid order 240 */ 241 if (!isset($order) || !$order->get_id()) { 242 header('HTTP/1.1 400 Bad Request (Order ID Not Found)'); 235 $order = wc_get_order($_GET['order_id']); 236 237 /** 238 * Check if it's a valid order 239 */ 240 if (!isset($order) || !$order->get_id()) { 241 header('HTTP/1.1 400 Bad Request (Order ID Not Found)'); 242 return; 243 } 244 245 /** 246 * The order is already paid so we redirect the user to a success page 247 */ 248 if ($order->is_paid()) { 249 header('HTTP/1.1 200 OK (Order Is Paid)'); 250 return; 251 } 252 253 /** 254 * The order is valid and it's ready to be paid 255 */ 256 if ($order->needs_payment()) { 257 /** 258 * Stored payment ID 259 */ 260 $meta_payment_id = $order->get_meta('ventipay_payment_id'); 261 262 /** 263 * Recieved payment ID 264 */ 265 $posted_body = json_decode(file_get_contents('php://input')); 266 $posted_payment_id = isset($posted_body) && !empty($posted_body->data) && !empty($posted_body->data->id) ? $posted_body->data->id : null; 267 268 /** 269 * We check if the stored ID looks like a valid one and both (stored and received) are equal 270 * This is a simple check, however it should be enough to control MITM tampering. 271 * Eventually we could check for a valid signature just like regular webhooks 272 */ 273 if (!empty($meta_payment_id) 274 && substr($meta_payment_id, 0, 4) === 'pay_' 275 && !empty($posted_payment_id) 276 && $meta_payment_id === $posted_payment_id) 277 { 278 /** 279 * We attempt to capture the payment. 280 * If it wasn't authorized or it's already captured, the API will sent an error. 281 */ 282 $capture_payment = wp_remote_post( 283 self::API_ENDPOINT . '/payments/' . $meta_payment_id . '/capture', 284 [ 285 'headers' => [ 286 'Authorization' => 'Basic ' . base64_encode($this->api_key . ':'), 287 'Content-Type' => 'application/json', 288 ], 289 'timeout' => 120, 290 ] 291 ); 292 293 if (!is_wp_error($capture_payment)) { 294 /** 295 * Captured payment data 296 */ 297 $captured_payment = json_decode(wp_remote_retrieve_body($capture_payment)); 298 299 /** 300 * Check if the payment was properly captured 301 */ 302 if (isset($captured_payment) 303 && !empty($captured_payment->status) 304 && !$captured_payment->refunded 305 && !$captured_payment->disputed 306 && 'succeeded' === $captured_payment->status) 307 { 308 $order->payment_complete(); 309 header('HTTP/1.1 200 OK (Payment Completed)'); 310 return; 311 } 312 } 313 header('HTTP/1.1 400 Bad Request (Unable To Capture Payment)'); 243 314 return; 244 315 } 245 246 /** 247 * The order is already paid so we redirect the user to a success page 248 */ 249 if ($order->is_paid()) { 250 header('HTTP/1.1 200 OK (Order Is Paid)'); 251 return; 252 } 253 254 /** 255 * The order is valid and it's ready to be paid 256 */ 257 if ($order->needs_payment()) { 258 /** 259 * Stored payment ID 260 */ 261 $meta_payment_id = $order->get_meta('ventipay_payment_id'); 262 263 /** 264 * Recieved payment ID 265 */ 266 $posted_body = json_decode(file_get_contents('php://input')); 267 $posted_payment_id = isset($posted_body) && !empty($posted_body->data) && !empty($posted_body->data->id) ? $posted_body->data->id : null; 268 269 /** 270 * We check if the stored ID looks like a valid one and both (stored and received) are equal 271 * This is a simple check, however it should be enough to control MITM tampering. 272 * Eventually we could check for a valid signature just like regular webhooks 273 */ 274 if (!empty($meta_payment_id) 275 && substr($meta_payment_id, 0, 4) === 'pay_' 276 && !empty($posted_payment_id) 277 && $meta_payment_id === $posted_payment_id) 278 { 279 /** 280 * We attempt to capture the payment. 281 * If it wasn't authorized or it's already captured, the API will sent an error. 282 */ 283 $capture_payment = wp_remote_post( 284 self::API_ENDPOINT . '/payments/' . $meta_payment_id . '/capture', 285 [ 286 'headers' => [ 287 'Authorization' => 'Basic ' . base64_encode($this->api_key . ':'), 288 'Content-Type' => 'application/json', 289 ], 290 'timeout' => 120, 291 ] 292 ); 293 294 if (!is_wp_error($capture_payment)) { 295 /** 296 * Captured payment data 297 */ 298 $captured_payment = json_decode(wp_remote_retrieve_body($capture_payment)); 299 300 /** 301 * Check if the payment was properly captured 302 */ 303 if (isset($captured_payment) 304 && !empty($captured_payment->status) 305 && !$captured_payment->refunded 306 && !$captured_payment->disputed 307 && 'succeeded' === $captured_payment->status) 308 { 309 $order->payment_complete(); 310 header('HTTP/1.1 200 OK (Payment Completed)'); 311 return; 312 } 313 } 314 header('HTTP/1.1 400 Bad Request (Unable To Capture Payment)'); 315 return; 316 } 317 $order->update_status('failed'); 318 header('HTTP/1.1 400 Bad Request (Posted Payment ID Mismatch)'); 319 return; 320 } 321 header('HTTP/1.1 400 Bad Request (Order Not Ready To Be Paid)'); 316 header('HTTP/1.1 400 Bad Request (Posted Payment ID Mismatch)'); 322 317 return; 323 } catch (Exception $e) {324 header('HTTP/1.1 500 Server Error');325 }318 } 319 header('HTTP/1.1 400 Bad Request (Order Not Ready To Be Paid)'); 320 return; 326 321 } 327 322 -
ventipay/tags/1.2.0/readme.txt
r2634782 r2635881 4 4 Requires at least: 5.7 5 5 Tested up to: 5.8 6 Stable tag: 1. 1.16 Stable tag: 1.2.0 7 7 Requires PHP: 7.0 8 8 License: MIT -
ventipay/tags/1.2.0/ventipay.php
r2634782 r2635881 6 6 * Author: VentiPay 7 7 * Author URI: https://www.ventipay.com/ 8 * Version: 1. 1.18 * Version: 1.2.0 9 9 * Requires at least: 5.7 10 10 * Tested up to: 5.8 … … 37 37 } 38 38 39 /** 40 * Hooks 41 */ 42 add_filter('woocommerce_after_add_to_cart_button' , 'venti_show_bnpl_button_in_product_page', 5); 39 43 add_filter('woocommerce_payment_gateways', 'ventipay_add_gateway_class'); 44 add_action('plugins_loaded', 'ventipay_init_gateway_class'); 45 add_action('wp_enqueue_scripts', 'ventipay_setup_scripts'); 40 46 41 add_action('plugins_loaded', 'ventipay_init_gateway_class'); 47 /** 48 * Add BNPL button in product page 49 */ 50 function venti_show_bnpl_button_in_product_page() 51 { 52 global $product; 53 $payment_gateways_obj = new WC_Payment_Gateways(); 54 $enabled_payment_gateways = $payment_gateways_obj->payment_gateways(); 55 if (isset($enabled_payment_gateways) 56 && isset($enabled_payment_gateways['ventipay_bnpl']) 57 && $enabled_payment_gateways['ventipay_bnpl']->enabled === 'yes' 58 ) { 59 $venti_min_installment_amount = ceil((int) number_format($product->get_price(), 0, ',', '') / 4); 60 if ($venti_min_installment_amount > 0) { 61 echo '<div class="ventipay-bnpl-product-button-container">'; 62 echo '<div class="ventipay-bnpl-product-button-image-container"><img src="https://pay.ventipay.com/assets/apps/woocommerce/plugin-woocommerce-icon-bnpl-button-product-page.svg" alt="Venti" border="0" /></div>'; 63 echo '<div class="ventipay-bnpl-product-button-text-container">Paga en cuotas con débito desde ' . wc_price($venti_min_installment_amount) . ' al mes</div>'; 64 echo '</div>'; 65 } 66 } 67 } 42 68 69 /** 70 * Load scripts, styles 71 */ 72 function ventipay_setup_scripts() 73 { 74 wp_register_style('ventipay', plugin_dir_url(__FILE__) . 'assets/css/ventipay-style.css'); 75 wp_enqueue_style('ventipay'); 76 } 77 78 /** 79 * Load Gateway classes 80 */ 43 81 function ventipay_init_gateway_class() 44 82 { -
ventipay/trunk/includes/class-wc-gateway-ventipay-bnpl.php
r2595906 r2635881 17 17 { 18 18 $this->id = 'ventipay_bnpl'; 19 $this->icon = plugin_dir_url(__FILE__) . '../assets/images/plugin-woocommerce-icon-bnpl.png';19 $this->icon = 'https://pay.ventipay.com/assets/apps/woocommerce/plugin-woocommerce-icon-bnpl.svg'; 20 20 $this->has_fields = false; 21 21 $this->method_title = __('Venti', 'ventipay'); … … 62 62 ), 63 63 'default' => __( 64 ' Paga en cuotas con débito',64 'Venti: Paga en cuotas con débito', 65 65 'ventipay' 66 66 ), … … 80 80 ], 81 81 'testmode' => [ 82 'title' => __('Habilitar modo Pruebas', 'ventipay'),83 'label' => __(' Si habilitas esta opción podrás hacer pruebas de integración sin aceptar pagos reales.', 'ventipay'),82 'title' => __('Habilitar Modo Pruebas', 'ventipay'), 83 'label' => __('Atención: Si habilitas esta opción no se realizarán cargos reales a los clientes. Habilita este modo solo si necesitas realizar pruebas de integración.', 'ventipay'), 84 84 'type' => 'checkbox', 85 85 'default' => 'yes', … … 88 88 'title' => __('Credenciales API', 'ventipay'), 89 89 'type' => 'title', 90 'description' => __('Podrás encontrar tus API Keys en la sección Desarrolladores del Dashboard', 'ventipay'),90 'description' => __('Podrás encontrar tus API Keys en la sección Desarrolladores > API del Dashboard', 'ventipay'), 91 91 ], 92 92 'test_api_key' => [ … … 237 237 public function ventipay_process_ipn() 238 238 { 239 try { 240 $order = wc_get_order($_GET['order_id']); 241 242 /** 243 * Check if it's a valid order 244 */ 245 if (!isset($order) || !$order->get_id()) { 246 header('HTTP/1.1 400 Bad Request (Order ID Not Found)'); 239 $order = wc_get_order($_GET['order_id']); 240 241 /** 242 * Check if it's a valid order 243 */ 244 if (!isset($order) || !$order->get_id()) { 245 header('HTTP/1.1 400 Bad Request (Order ID Not Found)'); 246 return; 247 } 248 249 /** 250 * The order is already paid so we redirect the user to a success page 251 */ 252 if ($order->is_paid()) { 253 header('HTTP/1.1 200 OK (Order Is Paid)'); 254 return; 255 } 256 257 /** 258 * The order is valid and it's ready to be paid 259 */ 260 if ($order->needs_payment()) { 261 /** 262 * Stored loan intent ID 263 */ 264 $meta_loan_intent_id = $order->get_meta('ventipay_loan_intent_id'); 265 266 /** 267 * Recieved loan intent ID 268 */ 269 $posted_body = json_decode(file_get_contents('php://input')); 270 $posted_loan_intent_id = isset($posted_body) && !empty($posted_body->data) && !empty($posted_body->data->id) ? $posted_body->data->id : null; 271 272 /** 273 * We check if the stored ID looks like a valid one and both (stored and received) are equal 274 * This is a simple check, however it should be enough to control MITM tampering. 275 * Eventually we could check for a valid signature just like regular webhooks 276 */ 277 if (!empty($meta_loan_intent_id) 278 && substr($meta_loan_intent_id, 0, 3) === 'li_' 279 && !empty($posted_loan_intent_id) 280 && $meta_loan_intent_id === $posted_loan_intent_id) 281 { 282 /** 283 * We retrieve the loan intent 284 */ 285 $retrieve_loan_intent = wp_remote_get( 286 self::API_ENDPOINT . '/loan-intents/' . $meta_loan_intent_id, 287 [ 288 'headers' => [ 289 'Authorization' => 'Basic ' . base64_encode($this->api_key . ':'), 290 'Content-Type' => 'application/json', 291 ], 292 'timeout' => 45, 293 ] 294 ); 295 296 if (is_wp_error($retrieve_loan_intent)) { 297 header('HTTP/1.1 400 Bad Request (Unable To Retrieve Payment)'); 298 return; 299 } 300 301 $retrieved_loan_intent = json_decode(wp_remote_retrieve_body($retrieve_loan_intent)); 302 $amount = (int) number_format($order->get_total(), 0, ',', ''); 303 304 /** 305 * We run some basic checks to make sure the order data matches the loan intent data. 306 */ 307 if (isset($retrieved_loan_intent) 308 && !empty($retrieved_loan_intent->id) 309 && !empty($retrieved_loan_intent->amount) 310 && !empty($retrieved_loan_intent->currency) 311 && !empty($order->get_currency()) 312 && !empty($retrieved_loan_intent->object) 313 && !empty($retrieved_loan_intent->status) 314 && 'loan_intent' === $retrieved_loan_intent->object 315 && $retrieved_loan_intent->id === $meta_loan_intent_id) 316 { 317 /** 318 * Does the payment looks good (status is approved and amount and currency matches)? 319 */ 320 if ('approved' === $retrieved_loan_intent->status 321 && strtolower($retrieved_loan_intent->currency) === strtolower($order->get_currency()) 322 && $retrieved_loan_intent->amount === $amount) 323 { 324 /** 325 * We attempt to authorize the approved loan intent. 326 * If it wasn't approved or it's already authorized, the API will sent an error. 327 */ 328 $authorize_loan_intent = wp_remote_post( 329 self::API_ENDPOINT . '/loan-intents/' . $meta_loan_intent_id . '/authorize', 330 [ 331 'headers' => [ 332 'Authorization' => 'Basic ' . base64_encode($this->api_key . ':'), 333 'Content-Type' => 'application/json', 334 ], 335 'timeout' => 120, 336 ] 337 ); 338 339 if (!is_wp_error($authorize_loan_intent)) { 340 /** 341 * Authorized payment data 342 */ 343 $authorized_loan_intent = json_decode(wp_remote_retrieve_body($authorize_loan_intent)); 344 345 /** 346 * Check if the payment was properly captured and authorized 347 */ 348 if (isset($authorized_loan_intent) 349 && !empty($authorized_loan_intent->status) 350 && 'authorized' === $authorized_loan_intent->status) 351 { 352 $order->payment_complete(); 353 header('HTTP/1.1 200 OK (Payment Completed)'); 354 return; 355 } else { 356 header('HTTP/1.1 400 Bad Request (Unable To Authorize'); 357 return; 358 } 359 } else { 360 header('HTTP/1.1 400 Bad Request (Unable To Authorize)'); 361 return; 362 } 363 } elseif ('authorized' === $retrieved_loan_intent->status 364 && strtolower($retrieved_loan_intent->currency) === strtolower($order->get_currency()) 365 && $retrieved_loan_intent->amount === $amount) 366 { 367 $order->payment_complete(); 368 header('HTTP/1.1 200 OK (Payment Completed)'); 369 return; 370 } else { 371 $order->update_status('failed'); 372 header('HTTP/1.1 400 Bad Request (Invalid Payment Status'); 373 return; 374 } 375 } 376 header('HTTP/1.1 400 Bad Request (Posted Payment Data Mismatch)'); 247 377 return; 248 378 } 249 250 /** 251 * The order is already paid so we redirect the user to a success page 252 */ 253 if ($order->is_paid()) { 254 header('HTTP/1.1 200 OK (Order Is Paid)'); 255 return; 256 } 257 258 /** 259 * The order is valid and it's ready to be paid 260 */ 261 if ($order->needs_payment()) { 262 /** 263 * Stored loan intent ID 264 */ 265 $meta_loan_intent_id = $order->get_meta('ventipay_loan_intent_id'); 266 267 /** 268 * Recieved loan intent ID 269 */ 270 $posted_body = json_decode(file_get_contents('php://input')); 271 $posted_loan_intent_id = isset($posted_body) && !empty($posted_body->data) && !empty($posted_body->data->id) ? $posted_body->data->id : null; 272 273 /** 274 * We check if the stored ID looks like a valid one and both (stored and received) are equal 275 * This is a simple check, however it should be enough to control MITM tampering. 276 * Eventually we could check for a valid signature just like regular webhooks 277 */ 278 if (!empty($meta_loan_intent_id) 279 && substr($meta_loan_intent_id, 0, 3) === 'li_' 280 && !empty($posted_loan_intent_id) 281 && $meta_loan_intent_id === $posted_loan_intent_id) 282 { 283 /** 284 * We retrieve the loan intent 285 */ 286 $retrieve_loan_intent = wp_remote_get( 287 self::API_ENDPOINT . '/loan-intents/' . $meta_loan_intent_id, 288 [ 289 'headers' => [ 290 'Authorization' => 'Basic ' . base64_encode($this->api_key . ':'), 291 'Content-Type' => 'application/json', 292 ], 293 'timeout' => 45, 294 ] 295 ); 296 297 if (is_wp_error($retrieve_loan_intent)) { 298 header('HTTP/1.1 400 Bad Request (Unable To Retrieve Payment)'); 299 return; 300 } 301 302 $retrieved_loan_intent = json_decode(wp_remote_retrieve_body($retrieve_loan_intent)); 303 $amount = (int) number_format($order->get_total(), 0, ',', ''); 304 305 /** 306 * We run some checks to make sure the order data matches the loan intent data. 307 */ 308 if (empty($retrieved_loan_intent) 309 || empty($retrieved_loan_intent->id) 310 || empty($retrieved_loan_intent->amount) 311 || empty($retrieved_loan_intent->currency) 312 || empty($order->get_currency()) 313 || empty($retrieved_loan_intent->object) 314 || empty($retrieved_loan_intent->status) 315 || 'loan_intent' !== $retrieved_loan_intent->object 316 || 'approved' !== $retrieved_loan_intent->status 317 || strtolower($retrieved_loan_intent->currency) !== strtolower($order->get_currency()) 318 || $retrieved_loan_intent->amount !== $amount 319 || $retrieved_loan_intent->id !== $meta_loan_intent_id) 320 { 321 $order->update_status('failed'); 322 header('HTTP/1.1 400 Bad Request (Posted Payment Data Mismatch)'); 323 return; 324 } 325 326 /** 327 * We attempt to authorize the approved loan intent. 328 * If it wasn't approved or it's already authorized, the API will sent an error. 329 */ 330 $authorize_loan_intent = wp_remote_post( 331 self::API_ENDPOINT . '/loan-intents/' . $meta_loan_intent_id . '/authorize', 332 [ 333 'headers' => [ 334 'Authorization' => 'Basic ' . base64_encode($this->api_key . ':'), 335 'Content-Type' => 'application/json', 336 ], 337 'timeout' => 120, 338 ] 339 ); 340 341 if (!is_wp_error($authorize_loan_intent)) { 342 /** 343 * Captured payment data 344 */ 345 $authorized_loan_intent = json_decode(wp_remote_retrieve_body($authorize_loan_intent)); 346 347 /** 348 * Check if the payment was properly captured 349 */ 350 if (isset($authorized_loan_intent) 351 && !empty($authorized_loan_intent->status) 352 && 'authorized' === $authorized_loan_intent->status) 353 { 354 $order->payment_complete(); 355 header('HTTP/1.1 200 OK (Payment Completed)'); 356 return; 357 } 358 } 359 header('HTTP/1.1 400 Bad Request (Unable To Authorize Payment)'); 360 return; 361 } 362 $order->update_status('failed'); 363 header('HTTP/1.1 400 Bad Request (Posted Payment ID Mismatch)'); 364 return; 365 } 366 header('HTTP/1.1 400 Bad Request (Order Not Ready To Be Paid)'); 379 header('HTTP/1.1 400 Bad Request (Posted Payment ID Mismatch)'); 367 380 return; 368 } catch (Exception $e) {369 header('HTTP/1.1 500 Server Error');370 381 } 382 header('HTTP/1.1 400 Bad Request (Order Not Ready To Be Paid)'); 383 return; 371 384 } 372 385 -
ventipay/trunk/includes/class-wc-gateway-ventipay.php
r2595906 r2635881 17 17 { 18 18 $this->id = 'ventipay'; 19 $this->icon = plugin_dir_url(__FILE__) . '../assets/images/plugin-woocommerce-icon-cards.png';19 $this->icon = 'https://pay.ventipay.com/assets/apps/woocommerce/plugin-woocommerce-icon-cards.svg'; 20 20 $this->has_fields = false; 21 21 $this->method_title = __('Venti', 'ventipay'); … … 62 62 ), 63 63 'default' => __( 64 ' Tarjeta de Crédito/Débito/Prepago',64 'Venti: Tarjeta de Crédito/Débito/Prepago', 65 65 'ventipay' 66 66 ), … … 80 80 ], 81 81 'testmode' => [ 82 'title' => __('Habilitar modo Pruebas', 'ventipay'),83 'label' => __(' Si habilitas esta opción podrás hacer pruebas de integración sin aceptar pagos reales.', 'ventipay'),82 'title' => __('Habilitar Modo Pruebas', 'ventipay'), 83 'label' => __('Atención: Si habilitas esta opción no se realizarán cargos reales a los clientes. Habilita este modo solo si necesitas realizar pruebas de integración.', 'ventipay'), 84 84 'type' => 'checkbox', 85 85 'default' => 'yes', … … 88 88 'title' => __('Credenciales API', 'ventipay'), 89 89 'type' => 'title', 90 'description' => __('Podrás encontrar tus API Keys en la sección Desarrolladores del Dashboard', 'ventipay'),90 'description' => __('Podrás encontrar tus API Keys en la sección Desarrolladores > API del Dashboard', 'ventipay'), 91 91 ], 92 92 'test_api_key' => [ … … 233 233 public function ventipay_process_ipn() 234 234 { 235 try { 236 $order = wc_get_order($_GET['order_id']); 237 238 /** 239 * Check if it's a valid order 240 */ 241 if (!isset($order) || !$order->get_id()) { 242 header('HTTP/1.1 400 Bad Request (Order ID Not Found)'); 235 $order = wc_get_order($_GET['order_id']); 236 237 /** 238 * Check if it's a valid order 239 */ 240 if (!isset($order) || !$order->get_id()) { 241 header('HTTP/1.1 400 Bad Request (Order ID Not Found)'); 242 return; 243 } 244 245 /** 246 * The order is already paid so we redirect the user to a success page 247 */ 248 if ($order->is_paid()) { 249 header('HTTP/1.1 200 OK (Order Is Paid)'); 250 return; 251 } 252 253 /** 254 * The order is valid and it's ready to be paid 255 */ 256 if ($order->needs_payment()) { 257 /** 258 * Stored payment ID 259 */ 260 $meta_payment_id = $order->get_meta('ventipay_payment_id'); 261 262 /** 263 * Recieved payment ID 264 */ 265 $posted_body = json_decode(file_get_contents('php://input')); 266 $posted_payment_id = isset($posted_body) && !empty($posted_body->data) && !empty($posted_body->data->id) ? $posted_body->data->id : null; 267 268 /** 269 * We check if the stored ID looks like a valid one and both (stored and received) are equal 270 * This is a simple check, however it should be enough to control MITM tampering. 271 * Eventually we could check for a valid signature just like regular webhooks 272 */ 273 if (!empty($meta_payment_id) 274 && substr($meta_payment_id, 0, 4) === 'pay_' 275 && !empty($posted_payment_id) 276 && $meta_payment_id === $posted_payment_id) 277 { 278 /** 279 * We attempt to capture the payment. 280 * If it wasn't authorized or it's already captured, the API will sent an error. 281 */ 282 $capture_payment = wp_remote_post( 283 self::API_ENDPOINT . '/payments/' . $meta_payment_id . '/capture', 284 [ 285 'headers' => [ 286 'Authorization' => 'Basic ' . base64_encode($this->api_key . ':'), 287 'Content-Type' => 'application/json', 288 ], 289 'timeout' => 120, 290 ] 291 ); 292 293 if (!is_wp_error($capture_payment)) { 294 /** 295 * Captured payment data 296 */ 297 $captured_payment = json_decode(wp_remote_retrieve_body($capture_payment)); 298 299 /** 300 * Check if the payment was properly captured 301 */ 302 if (isset($captured_payment) 303 && !empty($captured_payment->status) 304 && !$captured_payment->refunded 305 && !$captured_payment->disputed 306 && 'succeeded' === $captured_payment->status) 307 { 308 $order->payment_complete(); 309 header('HTTP/1.1 200 OK (Payment Completed)'); 310 return; 311 } 312 } 313 header('HTTP/1.1 400 Bad Request (Unable To Capture Payment)'); 243 314 return; 244 315 } 245 246 /** 247 * The order is already paid so we redirect the user to a success page 248 */ 249 if ($order->is_paid()) { 250 header('HTTP/1.1 200 OK (Order Is Paid)'); 251 return; 252 } 253 254 /** 255 * The order is valid and it's ready to be paid 256 */ 257 if ($order->needs_payment()) { 258 /** 259 * Stored payment ID 260 */ 261 $meta_payment_id = $order->get_meta('ventipay_payment_id'); 262 263 /** 264 * Recieved payment ID 265 */ 266 $posted_body = json_decode(file_get_contents('php://input')); 267 $posted_payment_id = isset($posted_body) && !empty($posted_body->data) && !empty($posted_body->data->id) ? $posted_body->data->id : null; 268 269 /** 270 * We check if the stored ID looks like a valid one and both (stored and received) are equal 271 * This is a simple check, however it should be enough to control MITM tampering. 272 * Eventually we could check for a valid signature just like regular webhooks 273 */ 274 if (!empty($meta_payment_id) 275 && substr($meta_payment_id, 0, 4) === 'pay_' 276 && !empty($posted_payment_id) 277 && $meta_payment_id === $posted_payment_id) 278 { 279 /** 280 * We attempt to capture the payment. 281 * If it wasn't authorized or it's already captured, the API will sent an error. 282 */ 283 $capture_payment = wp_remote_post( 284 self::API_ENDPOINT . '/payments/' . $meta_payment_id . '/capture', 285 [ 286 'headers' => [ 287 'Authorization' => 'Basic ' . base64_encode($this->api_key . ':'), 288 'Content-Type' => 'application/json', 289 ], 290 'timeout' => 120, 291 ] 292 ); 293 294 if (!is_wp_error($capture_payment)) { 295 /** 296 * Captured payment data 297 */ 298 $captured_payment = json_decode(wp_remote_retrieve_body($capture_payment)); 299 300 /** 301 * Check if the payment was properly captured 302 */ 303 if (isset($captured_payment) 304 && !empty($captured_payment->status) 305 && !$captured_payment->refunded 306 && !$captured_payment->disputed 307 && 'succeeded' === $captured_payment->status) 308 { 309 $order->payment_complete(); 310 header('HTTP/1.1 200 OK (Payment Completed)'); 311 return; 312 } 313 } 314 header('HTTP/1.1 400 Bad Request (Unable To Capture Payment)'); 315 return; 316 } 317 $order->update_status('failed'); 318 header('HTTP/1.1 400 Bad Request (Posted Payment ID Mismatch)'); 319 return; 320 } 321 header('HTTP/1.1 400 Bad Request (Order Not Ready To Be Paid)'); 316 header('HTTP/1.1 400 Bad Request (Posted Payment ID Mismatch)'); 322 317 return; 323 } catch (Exception $e) {324 header('HTTP/1.1 500 Server Error');325 }318 } 319 header('HTTP/1.1 400 Bad Request (Order Not Ready To Be Paid)'); 320 return; 326 321 } 327 322 -
ventipay/trunk/readme.txt
r2634782 r2635881 4 4 Requires at least: 5.7 5 5 Tested up to: 5.8 6 Stable tag: 1. 1.16 Stable tag: 1.2.0 7 7 Requires PHP: 7.0 8 8 License: MIT -
ventipay/trunk/ventipay.php
r2634782 r2635881 6 6 * Author: VentiPay 7 7 * Author URI: https://www.ventipay.com/ 8 * Version: 1. 1.18 * Version: 1.2.0 9 9 * Requires at least: 5.7 10 10 * Tested up to: 5.8 … … 37 37 } 38 38 39 /** 40 * Hooks 41 */ 42 add_filter('woocommerce_after_add_to_cart_button' , 'venti_show_bnpl_button_in_product_page', 5); 39 43 add_filter('woocommerce_payment_gateways', 'ventipay_add_gateway_class'); 44 add_action('plugins_loaded', 'ventipay_init_gateway_class'); 45 add_action('wp_enqueue_scripts', 'ventipay_setup_scripts'); 40 46 41 add_action('plugins_loaded', 'ventipay_init_gateway_class'); 47 /** 48 * Add BNPL button in product page 49 */ 50 function venti_show_bnpl_button_in_product_page() 51 { 52 global $product; 53 $payment_gateways_obj = new WC_Payment_Gateways(); 54 $enabled_payment_gateways = $payment_gateways_obj->payment_gateways(); 55 if (isset($enabled_payment_gateways) 56 && isset($enabled_payment_gateways['ventipay_bnpl']) 57 && $enabled_payment_gateways['ventipay_bnpl']->enabled === 'yes' 58 ) { 59 $venti_min_installment_amount = ceil((int) number_format($product->get_price(), 0, ',', '') / 4); 60 if ($venti_min_installment_amount > 0) { 61 echo '<div class="ventipay-bnpl-product-button-container">'; 62 echo '<div class="ventipay-bnpl-product-button-image-container"><img src="https://pay.ventipay.com/assets/apps/woocommerce/plugin-woocommerce-icon-bnpl-button-product-page.svg" alt="Venti" border="0" /></div>'; 63 echo '<div class="ventipay-bnpl-product-button-text-container">Paga en cuotas con débito desde ' . wc_price($venti_min_installment_amount) . ' al mes</div>'; 64 echo '</div>'; 65 } 66 } 67 } 42 68 69 /** 70 * Load scripts, styles 71 */ 72 function ventipay_setup_scripts() 73 { 74 wp_register_style('ventipay', plugin_dir_url(__FILE__) . 'assets/css/ventipay-style.css'); 75 wp_enqueue_style('ventipay'); 76 } 77 78 /** 79 * Load Gateway classes 80 */ 43 81 function ventipay_init_gateway_class() 44 82 {
Note: See TracChangeset
for help on using the changeset viewer.