From dce4d1e399547667d548b1231cf069deff020c85 Mon Sep 17 00:00:00 2001 From: David Parker Date: Thu, 4 Apr 2024 15:08:02 -0400 Subject: [PATCH 1/4] Using abstracted checkout completion function --- .../class.pmprogateway_paypalexpress.php | 3 +- includes/checkout.php | 54 +++- includes/functions.php | 1 - preheaders/checkout.php | 265 +++--------------- 4 files changed, 78 insertions(+), 245 deletions(-) diff --git a/classes/gateways/class.pmprogateway_paypalexpress.php b/classes/gateways/class.pmprogateway_paypalexpress.php index 7b166a64db..702fd20188 100644 --- a/classes/gateways/class.pmprogateway_paypalexpress.php +++ b/classes/gateways/class.pmprogateway_paypalexpress.php @@ -406,7 +406,6 @@ static function pmpro_checkout_confirmed($pmpro_confirmed) //set up values $morder->membership_id = $pmpro_level->id; $morder->membership_name = $pmpro_level->name; - $morder->discount_code = $discount_code; $morder->InitialPayment = pmpro_round_price( $pmpro_level->initial_payment ); $morder->PaymentAmount = pmpro_round_price( $pmpro_level->billing_amount ); $morder->ProfileStartDate = date_i18n("Y-m-d\TH:i:s"); @@ -1280,7 +1279,7 @@ function PPHttpPost_DontDieOnError($methodName_, $nvpStr_, $uuid) { 'httpversion' => '1.1', 'body' => $nvpreq, 'headers' => array( - 'content-type' => 'application/json', + 'content-type' => 'application/x-www-form-urlencoded', 'PayPal-Request-Id' => $uuid, ), ) diff --git a/includes/checkout.php b/includes/checkout.php index 23cf8dfc44..fdb250a695 100644 --- a/includes/checkout.php +++ b/includes/checkout.php @@ -163,30 +163,51 @@ function pmpro_pull_checkout_data_from_order( $order ) { } /** - * Complete an asynchronous checkout. + * Complete a checkout. * - * @since 2.12.3 + * @since TBD * * @param MemberOrder $order The order to complete the checkout for. * @return bool True if the checkout was completed successfully, false otherwise. */ - function pmpro_complete_async_checkout( $order ) { + function pmpro_complete_checkout( $order ) { global $wpdb, $pmpro_level, $discount_code, $discount_code_id; // Run the pmpro_checkout_before_change_membership_level action in case add ons need to set up. do_action( 'pmpro_checkout_before_change_membership_level', $order->user_id, $order ); - //set the start date to current_time('timestamp') but allow filters (documented in preheaders/checkout.php) + /** + * Filter the start date for the membership/subscription. + * + * @since 1.8.9 + * + * @param string $startdate , datetime formatsted for MySQL (NOW() or YYYY-MM-DD) + * @param int $user_id , ID of the user checking out + * @param object $pmpro_level , object of level being checked out for + */ $startdate = apply_filters( "pmpro_checkout_start_date", "'" . current_time( 'mysql' ) . "'", $order->user_id, $pmpro_level ); //fix expiration date if ( ! empty( $pmpro_level->expiration_number ) ) { - $enddate = "'" . date_i18n( "Y-m-d", strtotime( "+ " . $pmpro_level->expiration_number . " " . $pmpro_level->expiration_period, current_time( "timestamp" ) ) ) . "'"; + if( $pmpro_level->expiration_period == 'Hour' ){ + $enddate = date( "Y-m-d H:i:s", strtotime( "+ " . $pmpro_level->expiration_number . " " . $pmpro_level->expiration_period, current_time( "timestamp" ) ) ); + } else { + $enddate = date( "Y-m-d 23:59:59", strtotime( "+ " . $pmpro_level->expiration_number . " " . $pmpro_level->expiration_period, current_time( "timestamp" ) ) ); + } } else { $enddate = "NULL"; } - //filter the enddate (documented in preheaders/checkout.php) + /** + * Filter the end date for the membership/subscription. + * + * @since 1.8.9 + * + * @param string $enddate , datetime formatsted for MySQL (YYYY-MM-DD) + * @param int $user_id , ID of the user checking out + * @param object $pmpro_level , object of level being checked out for + * @param string $startdate , startdate calculated above + */ $enddate = apply_filters( "pmpro_checkout_end_date", $enddate, $order->user_id, $pmpro_level, $startdate ); //custom level to change user to @@ -205,11 +226,6 @@ function pmpro_complete_async_checkout( $order ) { 'enddate' => $enddate ); - global $pmpro_error; - if ( ! empty( $pmpro_error ) ) { - ipnlog( $pmpro_error ); - } - //change level and continue "checkout" if ( pmpro_changeMembershipLevel( $custom_level, $order->user_id, 'changed' ) !== false ) { // Mark the order as successful. @@ -249,6 +265,10 @@ function pmpro_complete_async_checkout( $order ) { } } + if ( $pmpro_level->expiration_period == 'Hour' ){ + update_user_meta( $order->user_id, 'pmpro_disable_notifications', true ); + } + //hook do_action( "pmpro_after_checkout", $order->user_id, $order ); @@ -272,3 +292,15 @@ function pmpro_complete_async_checkout( $order ) { return false; } } + +/** + * Legacy function. + * + * @since 2.12.3 + * + * @param MemberOrder $order The order to complete the checkout for. + * @return bool True if the checkout was completed successfully, false otherwise. + */ +function pmpro_complete_async_checkout( $order ) { + return pmpro_complete_checkout( $order ); +} diff --git a/includes/functions.php b/includes/functions.php index 142c76e336..dedc9281fe 100644 --- a/includes/functions.php +++ b/includes/functions.php @@ -3878,7 +3878,6 @@ function pmpro_build_order_for_checkout() { $morder->user_id = $current_user->ID; $morder->membership_id = $pmpro_level->id; $morder->membership_name = $pmpro_level->name; - $morder->discount_code = $discount_code; $morder->InitialPayment = pmpro_round_price( $pmpro_level->initial_payment ); $morder->PaymentAmount = pmpro_round_price( $pmpro_level->billing_amount ); $morder->ProfileStartDate = date_i18n( "Y-m-d\TH:i:s", current_time( "timestamp" ) ); diff --git a/preheaders/checkout.php b/preheaders/checkout.php index 595fbedb04..893e98aa2b 100644 --- a/preheaders/checkout.php +++ b/preheaders/checkout.php @@ -479,6 +479,11 @@ //setting some cookies wp_set_current_user( $user_id, $username ); wp_set_auth_cookie( $user_id, true, apply_filters( 'pmpro_checkout_signon_secure', force_ssl_admin() ) ); + global $current_user; + if ( ! $current_user->ID && $user->ID ) { + $current_user = $user; + } //in case the user just signed up + pmpro_set_current_user(); // Skip the account fields since we just created an account. $skip_account_fields = true; @@ -559,242 +564,40 @@ //just in case this hasn't been set yet $submit = true; - do_action( 'pmpro_checkout_before_change_membership_level', $user_id, $morder ); - - if ( 'pmpro_error' !== $pmpro_msgt ) { - //start date is NOW() but filterable below - $startdate = current_time( "mysql" ); - - /** - * Filter the start date for the membership/subscription. - * - * @since 1.8.9 - * - * @param string $startdate , datetime formatsted for MySQL (NOW() or YYYY-MM-DD) - * @param int $user_id , ID of the user checking out - * @param object $pmpro_level , object of level being checked out for - */ - $startdate = apply_filters( "pmpro_checkout_start_date", $startdate, $user_id, $pmpro_level ); - - //calculate the end date - if ( ! empty( $pmpro_level->expiration_number ) ) { - if( $pmpro_level->expiration_period == 'Hour' ){ - $enddate = date( "Y-m-d H:i:s", strtotime( "+ " . $pmpro_level->expiration_number . " " . $pmpro_level->expiration_period, current_time( "timestamp" ) ) ); - } else { - $enddate = date( "Y-m-d 23:59:59", strtotime( "+ " . $pmpro_level->expiration_number . " " . $pmpro_level->expiration_period, current_time( "timestamp" ) ) ); - } - } else { - $enddate = "NULL"; - } - - /** - * Filter the end date for the membership/subscription. - * - * @since 1.8.9 - * - * @param string $enddate , datetime formatsted for MySQL (YYYY-MM-DD) - * @param int $user_id , ID of the user checking out - * @param object $pmpro_level , object of level being checked out for - * @param string $startdate , startdate calculated above - */ - $enddate = apply_filters( "pmpro_checkout_end_date", $enddate, $user_id, $pmpro_level, $startdate ); - - //check code before adding it to the order - if ( ! empty( $discount_code ) ) { - if ( isset( $pmpro_checkout_level_ids ) ) { - $code_check = pmpro_checkDiscountCode( $discount_code, $pmpro_checkout_level_ids, true ); - } else { - $code_check = pmpro_checkDiscountCode( $discount_code, $pmpro_level->id, true ); - } - - if ( $code_check[0] == false ) { - //error - $pmpro_msg = $code_check[1]; - $pmpro_msgt = "pmpro_error"; - - //don't use this code - $use_discount_code = false; - } else { - //all okay - $use_discount_code = true; - } - - //update membership_user table. - if ( ! empty( $discount_code ) && ! empty( $use_discount_code ) ) { - $discount_code_id = $wpdb->get_var( "SELECT id FROM $wpdb->pmpro_discount_codes WHERE code = '" . esc_sql( $discount_code ) . "' LIMIT 1" ); - } else { - $discount_code_id = ""; - } - } else { - $discount_code_id = ""; - } - - $custom_level = array( - 'user_id' => $user_id, - 'membership_id' => $pmpro_level->id, - 'code_id' => $discount_code_id, - 'initial_payment' => pmpro_round_price( $pmpro_level->initial_payment ), - 'billing_amount' => pmpro_round_price( $pmpro_level->billing_amount ), - 'cycle_number' => $pmpro_level->cycle_number, - 'cycle_period' => $pmpro_level->cycle_period, - 'billing_limit' => $pmpro_level->billing_limit, - 'trial_amount' => pmpro_round_price( $pmpro_level->trial_amount ), - 'trial_limit' => $pmpro_level->trial_limit, - 'startdate' => $startdate, - 'enddate' => $enddate - ); - - if ( pmpro_changeMembershipLevel( $custom_level, $user_id, 'changed' ) ) { - //we're good - //blank order for free levels - if ( empty( $morder ) ) { - $morder = new MemberOrder(); - $morder->InitialPayment = 0; - $morder->Email = $bemail; - $morder->gateway = 'free'; - $morder->status = 'success'; - $morder = apply_filters( "pmpro_checkout_order_free", $morder ); - } - - //add an item to the history table, cancel old subscriptions - if ( ! empty( $morder ) ) { - $morder->user_id = $user_id; - $morder->membership_id = $pmpro_level->id; - $morder->saveOrder(); - } - - //update the current user - global $current_user; - if ( ! $current_user->ID && $user->ID ) { - $current_user = $user; - } //in case the user just signed up - pmpro_set_current_user(); - - //add discount code use - if ( $discount_code && $use_discount_code ) { - if ( ! empty( $morder->id ) ) { - $code_order_id = $morder->id; - } else { - $code_order_id = ""; - } - - $wpdb->query( $wpdb->prepare( - "INSERT INTO $wpdb->pmpro_discount_codes_uses (code_id, user_id, order_id, timestamp) VALUES(%d, %d, %d, %s)", - $discount_code_id, - $user_id, - $code_order_id, - current_time( "mysql" ) - ) ); - - do_action( 'pmpro_discount_code_used', $discount_code_id, $user_id, $code_order_id ); - } - - //save billing info ect, as user meta - $meta_keys = array(); - $meta_values = array(); - - // Check if firstname and last name fields are set. - if ( ! empty( $bfirstname ) || ! empty( $blastname ) ) { - $meta_keys = array_merge( $meta_keys, array( - "pmpro_bfirstname", - "pmpro_blastname", - ) ); - - $meta_values = array_merge( $meta_values, array( - $bfirstname, - $blastname, - ) ); - } - - // Check if billing details are available, if not adjust the arrays. - if ( ! empty( $baddress1 ) ) { - $meta_keys = array_merge( $meta_keys, array( - "pmpro_baddress1", - "pmpro_baddress2", - "pmpro_bcity", - "pmpro_bstate", - "pmpro_bzipcode", - "pmpro_bcountry", - "pmpro_bphone", - "pmpro_bemail", - ) ); - - $meta_values = array_merge( $meta_values, array( - $baddress1, - $baddress2, - $bcity, - $bstate, - $bzipcode, - $bcountry, - $bphone, - $bemail, - ) ); - } - - pmpro_replaceUserMeta( $user_id, $meta_keys, $meta_values ); - - //save first and last name fields - if ( ! empty( $bfirstname ) ) { - $old_firstname = get_user_meta( $user_id, "first_name", true ); - if ( empty( $old_firstname ) ) { - update_user_meta( $user_id, "first_name", $bfirstname ); - } - } - if ( ! empty( $blastname ) ) { - $old_lastname = get_user_meta( $user_id, "last_name", true ); - if ( empty( $old_lastname ) ) { - update_user_meta( $user_id, "last_name", $blastname ); - } - } - - if( $pmpro_level->expiration_period == 'Hour' ){ - update_user_meta( $user_id, 'pmpro_disable_notifications', true ); - } - - //show the confirmation - $ordersaved = true; - - //hook - do_action( "pmpro_after_checkout", $user_id, $morder ); //added $morder param in v2.0 - - $sendemails = apply_filters( "pmpro_send_checkout_emails", true); - - if($sendemails) { // Send the emails only if the flag is set to true + // Make sure we have an order object. + if ( empty( $morder ) ) { + $morder = new MemberOrder(); + $morder->InitialPayment = 0; + $morder->Email = $bemail; + $morder->gateway = 'free'; + $morder->status = 'success'; + $morder = apply_filters( "pmpro_checkout_order_free", $morder ); + } - //setup some values for the emails - if ( ! empty( $morder ) ) { - $invoice = new MemberOrder( $morder->id ); - } else { - $invoice = null; - } - $current_user->membership_level = $pmpro_level; //make sure they have the right level info + //add an item to the history table, cancel old subscriptions + if ( ! empty( $morder ) ) { + $morder->user_id = $user_id; + $morder->membership_id = $pmpro_level->id; + $morder->saveOrder(); + } - //send email to member - $pmproemail = new PMProEmail(); - $pmproemail->sendCheckoutEmail( $current_user, $invoice ); + if ( pmpro_complete_async_checkout( $morder ) ) { + //redirect to confirmation + $rurl = pmpro_url( "confirmation", "?pmpro_level=" . $pmpro_level->id ); + $rurl = apply_filters( "pmpro_confirmation_url", $rurl, $user_id, $pmpro_level ); + wp_redirect( $rurl ); + exit; + } else { - //send email to admin - $pmproemail = new PMProEmail(); - $pmproemail->sendCheckoutAdminEmail( $current_user, $invoice ); - } + //uh oh. we charged them then the membership creation failed - //redirect to confirmation - $rurl = pmpro_url( "confirmation", "?pmpro_level=" . $pmpro_level->id ); - $rurl = apply_filters( "pmpro_confirmation_url", $rurl, $user_id, $pmpro_level ); - wp_redirect( $rurl ); - exit; + // test that the order object contains data + $test = (array) $morder; + if ( ! empty( $test ) && $morder->cancel() ) { + $pmpro_msg = __( "IMPORTANT: Something went wrong during membership creation. Your credit card authorized, but we cancelled the order immediately. You should not try to submit this form again. Please contact the site owner to fix this issue.", 'paid-memberships-pro' ); + $morder = null; } else { - - //uh oh. we charged them then the membership creation failed - - // test that the order object contains data - $test = (array) $morder; - if ( ! empty( $test ) && $morder->cancel() ) { - $pmpro_msg = __( "IMPORTANT: Something went wrong during membership creation. Your credit card authorized, but we cancelled the order immediately. You should not try to submit this form again. Please contact the site owner to fix this issue.", 'paid-memberships-pro' ); - $morder = null; - } else { - $pmpro_msg = __( "IMPORTANT: Something went wrong during membership creation. Your credit card was charged, but we couldn't assign your membership. You should not submit this form again. Please contact the site owner to fix this issue.", 'paid-memberships-pro' ); - } + $pmpro_msg = __( "IMPORTANT: Something went wrong during membership creation. Your credit card was charged, but we couldn't assign your membership. You should not submit this form again. Please contact the site owner to fix this issue.", 'paid-memberships-pro' ); } } } From ca57c8fa1a923bc46c89de8c5c77da5f0a4eb593 Mon Sep 17 00:00:00 2001 From: David Parker Date: Thu, 4 Apr 2024 15:10:53 -0400 Subject: [PATCH 2/4] Reverting unrelated change --- classes/gateways/class.pmprogateway_paypalexpress.php | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/classes/gateways/class.pmprogateway_paypalexpress.php b/classes/gateways/class.pmprogateway_paypalexpress.php index 702fd20188..53f0de34ec 100644 --- a/classes/gateways/class.pmprogateway_paypalexpress.php +++ b/classes/gateways/class.pmprogateway_paypalexpress.php @@ -1279,7 +1279,7 @@ function PPHttpPost_DontDieOnError($methodName_, $nvpStr_, $uuid) { 'httpversion' => '1.1', 'body' => $nvpreq, 'headers' => array( - 'content-type' => 'application/x-www-form-urlencoded', + 'content-type' => 'application/json', 'PayPal-Request-Id' => $uuid, ), ) From dcbc0a5a8be3e7f8d65c8dffd2c3b5d0e1cd7c89 Mon Sep 17 00:00:00 2001 From: David Parker Date: Wed, 3 Jul 2024 13:57:32 -0400 Subject: [PATCH 3/4] Fixing call to deprecated function --- preheaders/checkout.php | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/preheaders/checkout.php b/preheaders/checkout.php index 218cd07347..4c0dfdc4d3 100644 --- a/preheaders/checkout.php +++ b/preheaders/checkout.php @@ -584,7 +584,7 @@ $morder->saveOrder(); } - if ( pmpro_complete_async_checkout( $morder ) ) { + if ( pmpro_complete_checkout( $morder ) ) { //redirect to confirmation $rurl = pmpro_url( "confirmation", "?pmpro_level=" . $pmpro_level->id ); $rurl = apply_filters( "pmpro_confirmation_url", $rurl, $user_id, $pmpro_level ); From 5531df58f5ce0ea94df9edb71f501192cf3531b7 Mon Sep 17 00:00:00 2001 From: David Parker Date: Wed, 3 Jul 2024 15:53:15 -0400 Subject: [PATCH 4/4] Improving comment and error messge --- preheaders/checkout.php | 9 ++++----- 1 file changed, 4 insertions(+), 5 deletions(-) diff --git a/preheaders/checkout.php b/preheaders/checkout.php index 4c0dfdc4d3..3f40a1902c 100644 --- a/preheaders/checkout.php +++ b/preheaders/checkout.php @@ -592,15 +592,14 @@ exit; } else { - //uh oh. we charged them then the membership creation failed - - // test that the order object contains data + // Something went wrong with the checkout. + // If we get here, then the call to pmpro_changeMembershipLevel() returned false within pmpro_complete_checkout(). Let's try to cancel the payment. $test = (array) $morder; if ( ! empty( $test ) && $morder->cancel() ) { - $pmpro_msg = __( "IMPORTANT: Something went wrong during membership creation. Your credit card authorized, but we cancelled the order immediately. You should not try to submit this form again. Please contact the site owner to fix this issue.", 'paid-memberships-pro' ); + $pmpro_msg = __( "IMPORTANT: Something went wrong while processing your checkout. Your credit card authorized, but we cancelled the order immediately. You should not try to submit this form again. Please contact the site owner to fix this issue.", 'paid-memberships-pro' ); $morder = null; } else { - $pmpro_msg = __( "IMPORTANT: Something went wrong during membership creation. Your credit card was charged, but we couldn't assign your membership. You should not submit this form again. Please contact the site owner to fix this issue.", 'paid-memberships-pro' ); + $pmpro_msg = __( "IMPORTANT: Something went wrong while processing your checkout. Your credit card was charged, but we couldn't assign your membership. You should not submit this form again. Please contact the site owner to fix this issue.", 'paid-memberships-pro' ); } } }