<?php /** * Manual Payment Gateway Class * * @package LifterLMS/Classes * * @since 3.0.0 * @version 3.30.3 */ defined( 'ABSPATH' ) || exit; /** * Manual Payment Gateway Class * * @since 3.0.0 * @since 3.30.3 Explicitly define class properties. */ class LLMS_Payment_Gateway_Manual extends LLMS_Payment_Gateway { /** * @var string * @since 3.0.0 */ public $payment_instructions; /** * Constructor * * @return void * @since 3.0.0 * @version 3.10.0 */ public function __construct() { $this->id = 'manual'; $this->admin_description = __( 'Collect manual or offline payments. Also handles any free orders during checkout.', 'lifterlms' ); $this->admin_title = __( 'Manual', 'lifterlms' ); $this->title = __( 'Manual', 'lifterlms' ); $this->description = __( 'Pay manually via check', 'lifterlms' ); $this->payment_instructions = ''; // Fields. $this->supports = array( 'checkout_fields' => false, 'refunds' => false, // Manual refunds are available always for all gateways and are not handled by this class. 'single_payments' => true, 'recurring_payments' => true, 'test_mode' => false, ); add_filter( 'llms_get_gateway_settings_fields', array( $this, 'get_settings_fields' ), 10, 2 ); add_action( 'lifterlms_before_view_order_table', array( $this, 'before_view_order_table' ) ); } /** * Output payment instructions if the order is pending * * @return void * @since 3.0.0 * @version 3.10.0 */ public function before_view_order_table() { global $wp; if ( ! empty( $wp->query_vars['orders'] ) ) { $order = new LLMS_Order( intval( $wp->query_vars['orders'] ) ); if ( 'manual' === $order->get( 'payment_gateway' ) && in_array( $order->get( 'status' ), array( 'llms-pending', 'llms-on-hold' ) ) ) { echo $this->get_payment_instructions(); } } } /** * Get fields displayed on the checkout form * * @return string * @since 3.0.0 * @version 3.7.5 */ public function get_payment_instructions() { $opt = $this->get_option( 'payment_instructions' ); if ( $opt ) { $fields = '<div class="llms-notice llms-info"><h3>' . esc_html__( 'Payment Instructions', 'lifterlms' ) . '</h3>' . wpautop( wptexturize( wp_kses_post( $opt ) ) ) . '</div>'; } else { $fields = ''; } return apply_filters( 'llms_get_payment_instructions', $fields, $this->id ); } /** * Get admin setting fields * * @param array $fields default fields * @param string $gateway_id gateway ID * @return array * @since 3.0.0 * @version 3.0.0 */ public function get_settings_fields( $fields, $gateway_id ) { if ( $this->id !== $gateway_id ) { return $fields; } $fields[] = array( 'id' => $this->get_option_name( 'payment_instructions' ), 'desc' => '<br>' . __( 'Displayed to the user when this gateway is selected during checkout. Add information here instructing the student on how to send payment.', 'lifterlms' ), 'title' => __( 'Payment Instructions', 'lifterlms' ), 'type' => 'textarea', ); return $fields; } /** * Called when the Update Payment Method form is submitted from a single order view on the student dashboard * * Gateways should do whatever the gateway needs to do to validate the new payment method and save it to the order * so that future payments on the order will use this new source * * @param obj $order Instance of the LLMS_Order * @param array $form_data Additional data passed from the submitted form (EG $_POST) * @return void * @since 3.10.0 * @version 3.10.0 */ public function handle_payment_source_switch( $order, $form_data = array() ) { $previous_gateway = $order->get( 'payment_gateway' ); if ( $this->get_id() === $previous_gateway ) { return; } $order->set( 'payment_gateway', $this->get_id() ); $order->set( 'gateway_customer_id', '' ); $order->set( 'gateway_source_id', '' ); $order->set( 'gateway_subscription_id', '' ); $order->add_note( sprintf( __( 'Payment method switched from "%1$s" to "%2$s"', 'lifterlms' ), $previous_gateway, $this->get_admin_title() ) ); } /** * Handle a Pending Order * Called by LLMS_Controller_Orders->create_pending_order() on checkout form submission * All data will be validated before it's passed to this function * * @param obj $order Instance LLMS_Order for the order being processed * @param obj $plan Instance LLMS_Access_Plan for the order being processed * @param obj $person Instance of LLMS_Student for the purchasing customer * @param obj|false $coupon Instance of LLMS_Coupon applied to the order being processed, or false when none is being used * @return void * @since 3.0.0 * @version 3.10.0 */ public function handle_pending_order( $order, $plan, $person, $coupon = false ) { // No payment (free orders). if ( floatval( 0 ) === $order->get_initial_price( array(), 'float' ) ) { // Free access plans do not generate receipts. if ( $plan->is_free() ) { $order->set( 'status', 'llms-completed' ); // Free trial, reduced to free via coupon, etc.... // We do want to record a transaction and then generate a receipt. } else { // Record a $0.00 transaction to ensure a receipt is sent. $order->record_transaction( array( 'amount' => floatval( 0 ), 'source_description' => __( 'Free', 'lifterlms' ), 'transaction_id' => uniqid(), 'status' => 'llms-txn-succeeded', 'payment_gateway' => 'manual', 'payment_type' => 'single', ) ); } $this->complete_transaction( $order ); // Payment due. } else { /** * @hooked LLMS_Notification: manual_payment_due - 10 */ do_action( 'llms_manual_payment_due', $order, $this ); // Show the user payment instructions for the order. do_action( 'lifterlms_handle_pending_order_complete', $order ); wp_redirect( $order->get_view_link() ); exit; } } /** * Called by scheduled actions to charge an order for a scheduled recurring transaction * This function must be defined by gateways which support recurring transactions * * @param obj $order Instance LLMS_Order for the order being processed * @return mixed * @since 3.10.0 * @version 3.10.0 */ public function handle_recurring_transaction( $order ) { // Switch to order on hold if it's a paid order. if ( $order->get_price( 'total', array(), 'float' ) > 0 ) { // Update status. $order->set_status( 'on-hold' ); /** * @hooked LLMS_Notification: manual_payment_due - 10 */ do_action( 'llms_manual_payment_due', $order, $this ); } } /** * Determine if the gateway is enabled according to admin settings checkbox * * @return boolean * @since 3.0.0 * @version 3.0.0 */ public function is_enabled() { return ( 'yes' === $this->get_enabled() ) ? true : false; } }