| 1 | <?php |
|---|
| 2 | namespace WebinaneCommerce\Classes; |
|---|
| 3 | |
|---|
| 4 | use WebinaneCommerce\Classes\Customers; |
|---|
| 5 | use WebinaneCommerce\Classes\Session; |
|---|
| 6 | |
|---|
| 7 | class Checkout { |
|---|
| 8 | |
|---|
| 9 | static function init() { |
|---|
| 10 | |
|---|
| 11 | add_action('wp_ajax__wpcommerce_checkout_data', array(__CLASS__, 'checkout_data')); |
|---|
| 12 | add_action('wp_ajax_nopriv__wpcommerce_checkout_data', array(__CLASS__, 'checkout_data')); |
|---|
| 13 | |
|---|
| 14 | add_action('wpcm_process_checkout', array(__CLASS__, 'process_checkout')); |
|---|
| 15 | |
|---|
| 16 | add_action('wp_enqueue_scripts', array(__CLASS__, 'enqueue' ) ); |
|---|
| 17 | |
|---|
| 18 | add_filter('body_class', array(__CLASS__, 'body_class')); |
|---|
| 19 | } |
|---|
| 20 | |
|---|
| 21 | static function enqueue() { |
|---|
| 22 | $key = 'nonce_wpcm_fieldsphpwpcommerce_frontend_checkout_form_customer_info'; |
|---|
| 23 | $_post = filter_input_array(INPUT_POST, FILTER_SANITIZE_STRING); |
|---|
| 24 | |
|---|
| 25 | if( isset( $_POST[$key]) && wpcm_is_checkout_page() ) { |
|---|
| 26 | $nonce = esc_attr( webinane_set($_POST, $key ) ); |
|---|
| 27 | if( ! wp_verify_nonce( $nonce, $key ) ) { |
|---|
| 28 | wpcm_redirect_back_checkout();wp_die(); |
|---|
| 29 | } |
|---|
| 30 | do_action('wpcm_process_checkout', $_post); |
|---|
| 31 | } |
|---|
| 32 | |
|---|
| 33 | if( wpcm_is_checkout_page() ) { |
|---|
| 34 | wp_enqueue_style('wpcm-bootstrap', WNCM_URL . 'assets/css/bootstrap.min.css'); |
|---|
| 35 | wp_enqueue_style('bootstrap-datetimepicker', WNCM_URL . 'assets/css/bootstrap-datetimepicker.min.css'); |
|---|
| 36 | wp_enqueue_style('fontawesome', WNCM_URL . 'assets/css/fontawesome.min.css'); |
|---|
| 37 | wp_enqueue_style('bootstrap-touchspin', WNCM_URL . 'assets/css/jquery.bootstrap-touchspin.min.css'); |
|---|
| 38 | |
|---|
| 39 | wp_enqueue_style('wpcm_responsive', WNCM_URL . 'assets/css/responsive.css'); |
|---|
| 40 | wp_enqueue_style('wpcm_style', WNCM_URL . 'assets/css/style.css'); |
|---|
| 41 | } |
|---|
| 42 | } |
|---|
| 43 | /** |
|---|
| 44 | * Finally add to cart. |
|---|
| 45 | * |
|---|
| 46 | * @param array $args [description] |
|---|
| 47 | */ |
|---|
| 48 | static function add_to_cart($args = array() ) { |
|---|
| 49 | |
|---|
| 50 | $id = webinane_set( $args, 'item_id' ); |
|---|
| 51 | $data = Session::get_session_data_by_key('cart'); |
|---|
| 52 | |
|---|
| 53 | if ( isset( $data[ $id ] ) ) { |
|---|
| 54 | |
|---|
| 55 | $data[$id]['quantity'] += (float) webinane_set( $args, 'quantity', 1 ); |
|---|
| 56 | } else { |
|---|
| 57 | $data[$id] = array( |
|---|
| 58 | 'item_id' => $id, |
|---|
| 59 | 'quantity' => (int) webinane_set( $args, 'quantity', 1 ), |
|---|
| 60 | 'price' => (float) webinane_set( $args, 'price', 1 ) |
|---|
| 61 | ); |
|---|
| 62 | } |
|---|
| 63 | |
|---|
| 64 | Session::set_session_data('cart', $data); |
|---|
| 65 | |
|---|
| 66 | return esc_html__( 'Added to cart', 'lifeline-donation' ); |
|---|
| 67 | } |
|---|
| 68 | |
|---|
| 69 | /** |
|---|
| 70 | * Finally add to cart. |
|---|
| 71 | * |
|---|
| 72 | * @param array $args [description] |
|---|
| 73 | */ |
|---|
| 74 | static function remove_from_cart($args = array() ) { |
|---|
| 75 | |
|---|
| 76 | $id = webinane_set( $args, 'item_id' ); |
|---|
| 77 | $data = Session::get_session_data_by_key('cart'); |
|---|
| 78 | |
|---|
| 79 | if ( isset( $data[ $id ] ) ) { |
|---|
| 80 | unset($data[ $id ]); |
|---|
| 81 | } |
|---|
| 82 | |
|---|
| 83 | Session::set_session_data('cart', $data); |
|---|
| 84 | |
|---|
| 85 | return esc_html__( 'Removed from cart', 'lifeline-donation' ); |
|---|
| 86 | } |
|---|
| 87 | |
|---|
| 88 | /** |
|---|
| 89 | * [checkout_page_orders description] |
|---|
| 90 | * |
|---|
| 91 | * @return [type] [description] |
|---|
| 92 | */ |
|---|
| 93 | static function checkout_page_orders() { |
|---|
| 94 | |
|---|
| 95 | webinane_template( 'checkout/orders.php' ); |
|---|
| 96 | } |
|---|
| 97 | |
|---|
| 98 | /** |
|---|
| 99 | * [checkout_page_gateways description] |
|---|
| 100 | * |
|---|
| 101 | * @return [type] [description] |
|---|
| 102 | */ |
|---|
| 103 | static function checkout_page_gateways() { |
|---|
| 104 | $gateways = wpcm_get_active_gateways()->get_options(); |
|---|
| 105 | |
|---|
| 106 | $names = apply_filters( 'wpcm_gateways_names', array('offline_payment', 'paypal') ); |
|---|
| 107 | |
|---|
| 108 | webinane_template('checkout/gateways.php', compact('gateways', 'names')); |
|---|
| 109 | |
|---|
| 110 | } |
|---|
| 111 | |
|---|
| 112 | /** |
|---|
| 113 | * [checkout_form_button description] |
|---|
| 114 | * @return [type] [description] |
|---|
| 115 | */ |
|---|
| 116 | static function checkout_form_button() { |
|---|
| 117 | |
|---|
| 118 | webinane_template('checkout/button.php'); |
|---|
| 119 | } |
|---|
| 120 | |
|---|
| 121 | /** |
|---|
| 122 | * [process_checkout description] |
|---|
| 123 | * @return [type] [description] |
|---|
| 124 | */ |
|---|
| 125 | static function process_checkout() { |
|---|
| 126 | do_action( 'wpcm_pre_process_purchase' ); |
|---|
| 127 | |
|---|
| 128 | $_post = filter_input_array(INPUT_POST, FILTER_SANITIZE_STRING); |
|---|
| 129 | |
|---|
| 130 | $is_ajax = isset( $_post['is_ajax'] ); |
|---|
| 131 | |
|---|
| 132 | $nonce = esc_attr( webinane_set($_post, 'nonce') ); |
|---|
| 133 | |
|---|
| 134 | if ( ! wp_verify_nonce( $nonce, WPCM_GLOBAL_KEY )) { |
|---|
| 135 | wp_send_json_error( array( 'message' => esc_html__( 'Security verification failed', 'lifeline-donation' ) ) ); |
|---|
| 136 | } |
|---|
| 137 | |
|---|
| 138 | // Make sure the cart isn't empty |
|---|
| 139 | if ( ! wpcm_get_cart_content() ) { |
|---|
| 140 | $valid_data = false; |
|---|
| 141 | wp_send_json_error( array( 'empty_cart' => esc_html__( 'Your cart is empty', 'lifeline-donation' ) ) ); |
|---|
| 142 | } else { |
|---|
| 143 | // Validate the form $_POST data |
|---|
| 144 | $valid_data = self::validate_fields($_post, $is_ajax); |
|---|
| 145 | |
|---|
| 146 | // Allow themes and plugins to hook to errors |
|---|
| 147 | do_action( 'wpcm_checkout_error_checks', $valid_data, $_post ); |
|---|
| 148 | } |
|---|
| 149 | |
|---|
| 150 | if( ! is_user_logged_in() ) { |
|---|
| 151 | $email = sanitize_email( webinane_set( webinane_set( $_post, 'billing' ), 'email' ) ); |
|---|
| 152 | |
|---|
| 153 | if( ! $email ) { |
|---|
| 154 | wp_send_json_error( esc_html__( 'Please provide a valid email', 'lifeline-donation' ) ); |
|---|
| 155 | } |
|---|
| 156 | |
|---|
| 157 | $user_id = username_exists( $email ); |
|---|
| 158 | |
|---|
| 159 | if ( ! $user_id && false == email_exists( $email ) ) { |
|---|
| 160 | $random_password = wp_generate_password(); |
|---|
| 161 | $user_id = wp_create_user( $email, $random_password, $email ); |
|---|
| 162 | if( is_wp_error( $user_id ) ) { |
|---|
| 163 | wp_send_json_error( $user_id->getMessage() ); |
|---|
| 164 | } |
|---|
| 165 | wp_send_new_user_notifications( $user_id, 'both' ); |
|---|
| 166 | wp_set_auth_cookie( $user_id, true ); |
|---|
| 167 | } else { |
|---|
| 168 | $user_id = ( $user_id ) ? $user_id : email_exists( $email ); |
|---|
| 169 | |
|---|
| 170 | if( $user_id ) { |
|---|
| 171 | wp_set_auth_cookie( $user_id, true ); |
|---|
| 172 | } else { |
|---|
| 173 | wp_send_json_error( esc_html__('Something went wrong', 'lifeline-donation' ) ); |
|---|
| 174 | } |
|---|
| 175 | } |
|---|
| 176 | } |
|---|
| 177 | |
|---|
| 178 | // Validate the user |
|---|
| 179 | $user = wp_get_current_user(); |
|---|
| 180 | |
|---|
| 181 | if( ! isset( $user->ID ) ) { |
|---|
| 182 | wp_send_json_error( esc_html__( 'Please refresh the page and try again', 'lifeline-donation' ) ); |
|---|
| 183 | } |
|---|
| 184 | |
|---|
| 185 | // Let extensions validate fields after user is logged in if user has used login/registration form |
|---|
| 186 | |
|---|
| 187 | if ( false === $valid_data || ! $user ) { |
|---|
| 188 | if ( $is_ajax ) { |
|---|
| 189 | do_action( 'wpcm_ajax_checkout_errors' ); |
|---|
| 190 | wp_die(); |
|---|
| 191 | } else { |
|---|
| 192 | return false; |
|---|
| 193 | } |
|---|
| 194 | } |
|---|
| 195 | |
|---|
| 196 | $billing = webinane_set( $_post, 'billing' ); |
|---|
| 197 | $shipping = webinane_set( $_post, 'shipping' ); |
|---|
| 198 | |
|---|
| 199 | // Setup user information |
|---|
| 200 | $user_info = array( |
|---|
| 201 | 'id' => ($user->ID) ? $user->ID : 0, |
|---|
| 202 | 'email' => ($user->user_email) ? $user->user_email : sanitize_email( webinane_set( $billing, 'email') ), |
|---|
| 203 | 'first_name' => ($user->user_first) ? $user->user_first : esc_attr( webinane_set( $billing, 'first_name' ) ), |
|---|
| 204 | 'last_name' => ($user->user_last) ? $user->user_last : esc_attr( webinane_set( $billing, 'last_name' ) ), |
|---|
| 205 | 'address' => ! empty( $user->address ) ? $user->address : esc_attr(webinane_set( $billing, 'address_line_1')), |
|---|
| 206 | ); |
|---|
| 207 | |
|---|
| 208 | // Update a customer record if they have added/updated information |
|---|
| 209 | $customer = new Customers( $user_info['email'], $_post ); |
|---|
| 210 | $customer->insert_meta($customer->customer, $_post); |
|---|
| 211 | if ( $is_ajax ) { |
|---|
| 212 | } |
|---|
| 213 | |
|---|
| 214 | $auth_key = defined( 'AUTH_KEY' ) ? AUTH_KEY : ''; |
|---|
| 215 | // Set up the unique purchase key. If we are resuming a payment, we'll overwrite this with the existing key. |
|---|
| 216 | $purchase_key = strtolower( md5( $user_info['email'] . date( 'Y-m-d H:i:s' ) . $auth_key . uniqid( 'wpcm', true ) ) ); |
|---|
| 217 | |
|---|
| 218 | // Setup purchase information |
|---|
| 219 | $purchase_data = array( |
|---|
| 220 | 'items' => wpcm_get_cart_content(), |
|---|
| 221 | |
|---|
| 222 | 'subtotal' => wpcm_get_cart_subtotal(), // Amount before taxes and discounts |
|---|
| 223 | |
|---|
| 224 | 'price' => wpcm_get_cart_total(), // Amount after taxes |
|---|
| 225 | 'purchase_key' => $purchase_key, |
|---|
| 226 | 'user_email' => $user_info['email'], |
|---|
| 227 | 'date' => date( 'Y-m-d H:i:s', current_time( 'timestamp' ) ), |
|---|
| 228 | 'user_info' => stripslashes_deep( $user_info ), |
|---|
| 229 | 'post_data' => $_post, |
|---|
| 230 | 'gateway' => $valid_data['gateway'], |
|---|
| 231 | ); |
|---|
| 232 | |
|---|
| 233 | // Add the user data for hooks |
|---|
| 234 | $valid_data['user'] = $user; |
|---|
| 235 | |
|---|
| 236 | // Allow themes and plugins to hook before the gateway |
|---|
| 237 | do_action( 'wpcm_checkout_before_gateway', $_post, $user_info, $valid_data ); |
|---|
| 238 | |
|---|
| 239 | // If the total amount in the cart is 0, send to the manual gateway. This emulates a free download purchase |
|---|
| 240 | if ( !$purchase_data['price'] ) { |
|---|
| 241 | // Revert to manual |
|---|
| 242 | $purchase_data['gateway'] = 'offline'; |
|---|
| 243 | $_POST['payment-gateway'] = 'offline'; |
|---|
| 244 | } |
|---|
| 245 | |
|---|
| 246 | // Setup the data we're storing in the purchase session |
|---|
| 247 | |
|---|
| 248 | // Make sure credit card numbers are never stored in sessions |
|---|
| 249 | |
|---|
| 250 | // Used for showing download links to non logged-in users after purchase, and for other plugins needing purchase data. |
|---|
| 251 | // Send info to the gateway for payment processing |
|---|
| 252 | wpcm_send_to_gateway( $purchase_data['gateway'], $purchase_data ); |
|---|
| 253 | wp_die(); |
|---|
| 254 | } |
|---|
| 255 | |
|---|
| 256 | /** |
|---|
| 257 | * This method is used to validation the checkout form submitted data. |
|---|
| 258 | * |
|---|
| 259 | * @param array $data An array of user submitted data. |
|---|
| 260 | * @param boolean $is_ajax Whether the request is an ajax or simple. |
|---|
| 261 | * @return mix If ajax then sends the json data, throw exception or array if successful. |
|---|
| 262 | */ |
|---|
| 263 | static function validate_fields($data, $is_ajax) { |
|---|
| 264 | $rules = apply_filters( 'webinane_commerce_checkout_form_validation_rules', [ |
|---|
| 265 | 'billing.email' => 'required|email', |
|---|
| 266 | 'billing.first_name' => 'required|min:4', |
|---|
| 267 | // 'billing.last_name' => 'required|min:4', |
|---|
| 268 | 'billing.address_line_1' => 'required|min:10', |
|---|
| 269 | 'billing.city' => 'required', |
|---|
| 270 | 'billing.base_country' => 'required', |
|---|
| 271 | 'nonce' => 'required', |
|---|
| 272 | 'gateway' => 'required' |
|---|
| 273 | ] ); |
|---|
| 274 | |
|---|
| 275 | $validation = wpcm_validator()->make($data, $rules); |
|---|
| 276 | |
|---|
| 277 | // or this way: |
|---|
| 278 | $validation->setAliases([ |
|---|
| 279 | 'billing.email' => esc_html__('Billing Email', 'lifeline-donation'), |
|---|
| 280 | 'billing.first_name' => esc_html__('Billing First Name', 'lifeline-donation'), |
|---|
| 281 | 'billing.address_line_1' => esc_html__('Billing Address', 'lifeline-donation'), |
|---|
| 282 | 'billing.city' => esc_html__('Billing City', 'lifeline-donation'), |
|---|
| 283 | 'billing.base_country' => esc_html__('Billing Country', 'lifeline-donation'), |
|---|
| 284 | 'nonce' => esc_html__('Security check', 'lifeline-donation'), |
|---|
| 285 | 'gateway' => esc_html__('Payment Gateway', 'lifeline-donation'), |
|---|
| 286 | ]); |
|---|
| 287 | |
|---|
| 288 | // then validate |
|---|
| 289 | $validation->validate(); |
|---|
| 290 | |
|---|
| 291 | if ($validation->fails()) { |
|---|
| 292 | // handling errors |
|---|
| 293 | $errors = $validation->errors(); |
|---|
| 294 | if( $is_ajax ) { |
|---|
| 295 | wp_send_json_error( array('message' => implode("\n", $errors->all("<p>:message</p>")) ) ); |
|---|
| 296 | } |
|---|
| 297 | throw new \Exception($errors, 1); |
|---|
| 298 | } |
|---|
| 299 | |
|---|
| 300 | return $data; |
|---|
| 301 | } |
|---|
| 302 | |
|---|
| 303 | static function body_class($classes) { |
|---|
| 304 | |
|---|
| 305 | if( is_page() ) { |
|---|
| 306 | if( wpcm_is_checkout_page() ) { |
|---|
| 307 | $classes[] = 'wpcm-checkout-page'; |
|---|
| 308 | } |
|---|
| 309 | } |
|---|
| 310 | return $classes; |
|---|
| 311 | } |
|---|
| 312 | |
|---|
| 313 | static function checkout_data() { |
|---|
| 314 | |
|---|
| 315 | $user = wp_get_current_user(); |
|---|
| 316 | $settings = get_option('_wpcommerce_settings'); |
|---|
| 317 | |
|---|
| 318 | $countries = wpcm_countries()->toArray(); |
|---|
| 319 | |
|---|
| 320 | $symbol = webinane_currency_symbol(); |
|---|
| 321 | |
|---|
| 322 | $cart = (array) wpcm_get_cart_content(); |
|---|
| 323 | |
|---|
| 324 | $items = array(); |
|---|
| 325 | |
|---|
| 326 | if( $cart ) { |
|---|
| 327 | foreach( $cart as $c ) { |
|---|
| 328 | $collection = collect($c); |
|---|
| 329 | $items[$collection->get('item_id')] = array( |
|---|
| 330 | 'thumb' => wp_get_attachment_image_src( get_post_thumbnail_id( $collection->get('item_id') ), 'thumbnail' ), |
|---|
| 331 | 'link' => get_permalink($collection->get('item_id')), |
|---|
| 332 | 'title' => get_the_title( $collection->get('item_id')), |
|---|
| 333 | 'qty' => webinane_set( $c, 'quantity'), |
|---|
| 334 | 'price' => webinane_set( $c, 'price'), |
|---|
| 335 | ); |
|---|
| 336 | } |
|---|
| 337 | } |
|---|
| 338 | |
|---|
| 339 | $cart['symbol'] = $symbol; |
|---|
| 340 | |
|---|
| 341 | $customer = ($user->ID) ? new Customers( $user->user_email ) : array(); |
|---|
| 342 | if( $customer ) { |
|---|
| 343 | $customer = $customer->full_customer_info(); |
|---|
| 344 | } |
|---|
| 345 | wp_send_json(compact('countries', 'cart', 'customer', 'items')); |
|---|
| 346 | } |
|---|
| 347 | } |
|---|
| 348 | |
|---|