getPaymentAmountForBooking($booking); return $payment > 0; } // $payment es la cantidad a pagar que puede venir desde el widget fijada por un custom layout // si no viene es porque hay que aplicar las reglas de pago normales public function gatewayPaymentDetails($service, $booking, $payment = null) { $restaurant = $booking->restaurant; // Calculo la cantidad a pagar segun las reglas $payment_calculated = $service->getPaymentAmountForBooking($booking); // Si no hay que pagar por las reglas entonces no hay que pagar el custom layout?? // no es cierto porque puede que no haya que pagar por dos comensales segun las reglas pero sin embargo si haya que pagar por la mesa // Por eso compruebo tambien que la mesa tiene una cantidad asignada que viene en payment if (($payment == null || $payment == 0) && $payment_calculated <= 0) { return false; } // Aplicar reglas de pago, precio por asiento, etc. if ($payment == null || $payment == 0) { $payment = $payment_calculated; } // Desde la vista booking view cojo el que ya esta calculado // Solo aplica el override si la cantidad estaba ya guardada (>0). Para // reglas de offer con `percentage_of_menu`, el primer paso por // hold_booking tiene subtotal=0 y el booking->amount queda a 0; en // ese caso debemos usar el valor calculado, no el override de 0. if ($booking->status == \Alexr\Enums\BookingStatus::PENDING_PAYMENT && intval($booking->amount) > 0) { $payment = 0.01 * intval($booking->amount); //ray('STATUS => ' . $payment); } //ray('PAYMENT: ' . $payment); if ($payment > 0) { // Token needed for return url for gateways $token = \Evavel\Support\Str::upper(\Evavel\Support\Str::random(12)); $booking->gateway_token = $token; $booking->save(); $payment_gateways = []; // Woocommerce $woocommerce_args = $this->getWoocommercePaymentArgs($booking); if ($woocommerce_args) { $payment_gateways['woocommerce'] = $woocommerce_args; } // Stripe $stripe_args = $this->getStripePaymentArgs($booking); if ($stripe_args) { $payment_gateways['stripe'] = $stripe_args; } // Redsys $redsys_args = $this->getRedsysPaymentArgs($booking, $payment); if ($redsys_args) { $payment_gateways['redsys'] = $redsys_args; } // Paypal $paypal_args = $this->getPaypalPaymentArgs($booking); if ($paypal_args) { $payment_gateways['paypal'] = $paypal_args; } // MercadoPago $mercadopago_args = $this->getMercadopagoPaymentArgs($booking); if ($mercadopago_args) { $payment_gateways['mercadopago'] = $mercadopago_args; } // Mollie $mollie_args = $this->getMolliePaymentArgs($booking); if ($mollie_args) { $payment_gateways['mollie'] = $mollie_args; } // Square $square_args = $this->getSquarePaymentArgs($booking); if ($square_args) { $payment_gateways['square'] = $square_args; } // Xendit $xendit_args = $this->getXenditPaymentArgs($booking); if ($xendit_args) { $payment_gateways['xendit'] = $xendit_args; } // Upayments $upayments_args = $this->getUpaymentsPaymentArgs($booking); if ($upayments_args) { $payment_gateways['upayments'] = $upayments_args; } // Save amount required inside the booking if ($payment > 0) { $booking->amount = intval(100 * $payment); $booking->save(); } return [ 'payment_gateways' => $payment_gateways, 'required' => $payment > 0, // Define is the gateway has the option to capture cards 'is_capture_card' => $service->isPaymentToCapture(), 'amount' => $payment, 'currency' => strtolower($restaurant->currency), 'currency_symbol' => \Alexr\Enums\CurrencyType::symbolFor($restaurant->currency), 'message' => $service->getPaymentMessage(), 'return_url' => add_query_arg(['payment' => 'confirm'],evavel_view_booking_url($booking->uuid)), ]; } return false; } /** * Recompute the payment amount for a held booking after the customer * picks a menu in the offer step. Persists the offer menu selection on * the booking and returns the new `payment` payload (same shape as * `rr_hold_booking` returns). * * Expected POST/GET parameters: * - restaurantId * - uuid : holded booking uuid * - offer_id : selected offer id * - offer_rule_id : matched rule id (optional, informative) * - menu_lines : JSON-encoded array of selected items * - menu_subtotal : client-side subtotal (informative) * - nonce */ public function recompute_offer_payment() { $restaurant_id = intval($_REQUEST['restaurantId']); if (!$this->verify_nonce($restaurant_id)) { wp_send_json_error(['error' => __eva('Invalid nonce.')]); } $restaurant = \Alexr\Models\Restaurant::find($restaurant_id); if (!$restaurant) { wp_send_json_error(['error' => __eva('Restaurant not found.')]); } $uuid = isset($_REQUEST['uuid']) ? sanitize_text_field($_REQUEST['uuid']) : ''; if (!$uuid) { wp_send_json_error(['error' => __eva('Booking not found.')]); } $booking = \Alexr\Models\Booking::where('uuid', $uuid) ->where('status', '!=', \Alexr\Enums\BookingStatus::DELETED) ->first(); if (!$booking) { wp_send_json_error(['error' => __eva('Booking not found.')]); } $service = alexr_get_service($booking->shift_event_id); if (!$service) { wp_send_json_error(['error' => __eva('Service not found.')]); } // Sanity-check: the slot must currently match an offer rule. $rule = $service->getOfferRuleMatched($booking->date, $booking->time); if ($rule === null) { wp_send_json_error(['error' => __eva('No offer applies to this slot.')]); } $offer_id = isset($_REQUEST['offer_id']) ? intval($_REQUEST['offer_id']) : 0; if ($offer_id <= 0) { wp_send_json_error(['error' => __eva('Missing offer.')]); } $raw_lines = isset($_REQUEST['menu_lines']) ? $_REQUEST['menu_lines'] : null; if (is_string($raw_lines)) { $decoded = json_decode(stripslashes($raw_lines), true); $raw_lines = is_array($decoded) ? $decoded : []; } if (!is_array($raw_lines)) $raw_lines = []; // Sanitise the line items but trust the subtotal coming from the widget // (the customer reviewed it on screen before pressing Continue). $clean_lines = $service->sanitiseMenuLines($offer_id, $raw_lines); $rule_id_request = isset($_REQUEST['offer_rule_id']) ? sanitize_text_field($_REQUEST['offer_rule_id']) : null; $subtotal = isset($_REQUEST['menu_subtotal']) ? floatval($_REQUEST['menu_subtotal']) : 0; // Persist on the booking so subsequent payment endpoints (and // make_booking) can read the menu subtotal. $settings = $booking->settings; if (!is_array($settings)) $settings = []; $settings['offer_menu'] = [ 'offer_id' => $offer_id, 'offer_rule_id' => $rule_id_request, 'lines' => $clean_lines, 'subtotal' => $subtotal, ]; $booking->settings = $settings; $booking->save(); // Build the updated payment payload. // gatewayPaymentDetails reads booking->settings to derive the menu subtotal. $payment = $this->gatewayPaymentDetails($service, $booking); // gatewayPaymentDetails returns false when there's nothing to pay. if ($payment === false) { $payment = [ 'required' => false, 'amount' => 0, 'currency' => strtolower($restaurant->currency), 'currency_symbol' => \Alexr\Enums\CurrencyType::symbolFor($restaurant->currency), 'payment_gateways'=> [], 'is_capture_card' => false, 'message' => $service->getPaymentMessage(), ]; } wp_send_json_success([ 'payment' => $payment, 'menu_subtotal' => $subtotal, ]); } function get_confirmed_booking_payments() { $restaurant_id = sanitize_text_field($_REQUEST['restaurantId']); if ( ! $this->verify_nonce('stripe-'.$restaurant_id) ) { wp_send_json_error(['error' => __eva('Invalid nonce. Try to refresh the page.')]); } $restaurant = \Alexr\Models\Restaurant::find($restaurant_id); if (!$restaurant){ wp_send_json_error([ 'message' => 'Wrong restaurant' ]); } $booking_uuid = sanitize_text_field($_REQUEST['uuid']); if (!$booking_uuid) { wp_send_json_error(['error' => __eva('Booking not found.')]); } $booking = \Alexr\Models\Booking::where('uuid', $booking_uuid)->first(); if (!$booking) { wp_send_json_error(['error' => __eva('Booking not found.')]); } $payments = \Alexr\Models\Payment::where('booking_id', $booking->id)->get(); if (!$payments) { wp_send_json_success(['payments' => []]); } wp_send_json_success(['payments' => $payments->toArrayEachModel()]); } public function webhook() { // @TODO para mercadopago die(); } }