$form->id,
+ 'action' => 'edit',
+ ),
+ admin_url( 'post.php' )
+ );
+
+ return wp_kses_post(
+ sprintf(
+ /* translators: %1$s Opening anchor tag, do not translate. %2$s Closing anchor tag, do not translate. */
+ __( 'Attention: The payment form does not have prices configured. %1$sAdd price options%2$s to collect payments.', 'stripe' ),
+ '',
+ ''
+ )
+ );
+ }
+
+ return;
+ }
+
ob_start();
$form->html();
diff --git a/includes/core/class-simplepay.php b/includes/core/class-simplepay.php
index b028a592..c48704d9 100644
--- a/includes/core/class-simplepay.php
+++ b/includes/core/class-simplepay.php
@@ -220,9 +220,6 @@ public function load_admin() {
require_once( SIMPLE_PAY_INC . 'core/admin/functions/notices.php' );
require_once( SIMPLE_PAY_INC . 'core/admin/functions/plugin-upgrade-notice.php' );
- // Promos (Lite-only).
- require_once( SIMPLE_PAY_INC . 'core/admin/notices/promos.php' );
-
// Usage tracking functionality.
require_once( SIMPLE_PAY_INC . 'core/admin/usage-tracking/functions.php' );
diff --git a/includes/core/forms/class-default-form.php b/includes/core/forms/class-default-form.php
index 7a68288e..1a0c7826 100644
--- a/includes/core/forms/class-default-form.php
+++ b/includes/core/forms/class-default-form.php
@@ -297,6 +297,7 @@ function( $price ) {
$custom_fields = simpay_get_saved_meta( $this->id, '_custom_fields' );
$payment_text = __( 'Pay with Card', 'stripe' );
+ $payment_trial_text = __( 'Start Trial', 'stripe' );
$payment_loading_text = __( 'Please Wait...', 'stripe' );
// Payment Button (Embed + Stripe Checkout).
@@ -309,6 +310,11 @@ function( $price ) {
$payment_text = $payment_button['text'];
}
+ // Trial.
+ if ( ! empty( $payment_button['trial_text'] ) ) {
+ $payment_trial_text = $payment_button['trial_text'];
+ }
+
// Processing.
if ( ! empty( $payment_button['processing_text'] ) ) {
$payment_loading_text = $payment_button['processing_text'];
@@ -321,6 +327,7 @@ function( $price ) {
$strings['strings'] = array(
'paymentButtonText' => esc_html( $payment_text ),
+ 'paymentButtonTrialText' => esc_html( $payment_trial_text ),
'paymentButtonLoadingText' => esc_html( $payment_loading_text ),
);
diff --git a/includes/core/forms/functions.php b/includes/core/forms/functions.php
index f7c4af6c..ec2d0db3 100644
--- a/includes/core/forms/functions.php
+++ b/includes/core/forms/functions.php
@@ -140,7 +140,8 @@ function __unstable_simpay_get_payment_form_prices_subscription_price( $prices )
* @since 4.1.0
*
* @param \SimplePay\Core\PaymentForm\PriceOption[] $prices Prices list.
- * @return \SimplePay\Core\PaymentForm\PriceOption Default price, or first price.
+ * @return false|\SimplePay\Core\PaymentForm\PriceOption Default price, or first price.
+ * False if no prices are found.
*/
function simpay_get_payment_form_default_price( $prices ) {
$price = current(
@@ -280,6 +281,10 @@ function simpay_payment_form_add_missing_custom_fields(
(
isset( $payment_methods['stripe-elements']['sepa-debit'] ) &&
isset( $payment_methods['stripe-elements']['sepa-debit']['id'] )
+ ) ||
+ (
+ isset( $payment_methods['stripe-elements']['afterpay-clearpay'] ) &&
+ isset( $payment_methods['stripe-elements']['afterpay-clearpay']['id'] )
)
)
) {
@@ -304,6 +309,44 @@ function simpay_payment_form_add_missing_custom_fields(
$count++;
}
+ // Ensure "Address" exists and is required if using Klarna.
+ if (
+ ! isset( $fields['address'] ) &&
+ (
+ (
+ isset( $payment_methods['stripe-elements']['klarna'] ) &&
+ isset( $payment_methods['stripe-elements']['klarna']['id'] )
+ ) ||
+ (
+ isset( $payment_methods['stripe-elements']['afterpay-clearpay'] ) &&
+ isset( $payment_methods['stripe-elements']['afterpay-clearpay']['id'] )
+ )
+ )
+ ) {
+ $args = array(
+ 'uid' => $count,
+ 'id' => 'simpay_' . $form_id . '_address',
+ 'billing-container-label' => 'Billing Address',
+ 'label-street' => 'Street Address',
+ 'label-city' => 'City',
+ 'label-state' => 'State',
+ 'label-zip' => 'Postal Code',
+ 'label-country' => 'Country',
+ 'required' => 'yes',
+ );
+
+ if (
+ isset( $payment_methods['stripe-elements']['afterpay-clearpay'] ) &&
+ isset( $payment_methods['stripe-elements']['afterpay-clearpay']['id'] )
+ ) {
+ $args['collect-shipping'] = 'yes';
+ }
+
+ $fields['address'][] = $args;
+
+ $count++;
+ }
+
// Ensure "Payment Methods" exist.
if ( ! isset( $fields['card'] ) ) {
$fields['card'][] = array(
@@ -408,6 +451,7 @@ function simpay_payment_form_add_missing_custom_fields(
array(
'customer_name',
'email',
+ 'address',
'plan_select',
'custom_amount',
'recurring_amount_toggle',
diff --git a/includes/core/functions/admin.php b/includes/core/functions/admin.php
index 2f6b8a54..fed81bad 100644
--- a/includes/core/functions/admin.php
+++ b/includes/core/functions/admin.php
@@ -285,13 +285,19 @@ function simpay_ga_url( $base_url, $utm_medium, $utm_content = false ) {
* @since 3.0.0
*
* @param string $utm_medium utm_medium parameter.
+ * @param string $utm_content Optional. utm_content parameter.
* @return string
*/
-function simpay_pro_upgrade_url( $utm_medium ) {
+function simpay_pro_upgrade_url( $utm_medium, $utm_content = '' ) {
return apply_filters(
'simpay_upgrade_link',
- simpay_ga_url( 'https://wpsimplepay.com/lite-vs-pro', $utm_medium ),
- $utm_medium
+ simpay_ga_url(
+ 'https://wpsimplepay.com/lite-vs-pro',
+ $utm_medium,
+ $utm_content
+ ),
+ $utm_medium,
+ $utm_content
);
}
@@ -319,13 +325,13 @@ function simpay_docs_link( $text, $slug, $utm_medium, $plain = false ) {
// Add GA campaign params in both cases.
if ( $plain ) {
- return simpay_ga_url( $url, $utm_medium );
+ return simpay_ga_url( $url, $utm_medium, $text );
} else {
$html = '';
$html .= '';
diff --git a/includes/core/functions/shared.php b/includes/core/functions/shared.php
index 7dfaaa04..b482e332 100644
--- a/includes/core/functions/shared.php
+++ b/includes/core/functions/shared.php
@@ -12,6 +12,7 @@
exit;
}
+use SimplePay\Core\License;
use SimplePay\Core\Utils;
use SimplePay\Core\Forms\Default_Form;
use SimplePay\Core\Post_Types\Simple_Pay\Edit_Form;
@@ -124,23 +125,35 @@ function simpay_update_setting( $setting, $value ) {
}
/**
- * Check the user's license to see if subscriptions are enabled or not
+ * Returns the current license.
*
- * @return bool
+ * @since 4.4.4
+ *
+ * @return \SimplePay\Core\License\License
*/
-function simpay_subscriptions_enabled() {
-
- $license_data = get_option( 'simpay_license_data' );
+function simpay_get_license() {
+ if ( true === defined( 'SIMPLE_PAY_LICENSE_KEY' ) ) {
+ $key = SIMPLE_PAY_LICENSE_KEY; // @phpstan-ignore-line
+ } else {
+ $key = get_option( 'simpay_license_key', '' );
+ }
- if ( ! empty( $license_data ) && 'valid' === $license_data->license ) {
- $price_id = $license_data->price_id;
+ /** @var string $key */
+ $key = trim( $key );
- if ( '1' !== $price_id ) {
- return true;
- }
- }
+ return new License\License( $key );
+}
- return false;
+/**
+ * Check the user's license to see if subscriptions are enabled or not
+ *
+ * @since 3.0.0
+ * @since 4.4.4 Deprecated. Use simpay_get_license()->is_subscriptions_enabled() instead.
+ *
+ * @return bool
+ */
+function simpay_subscriptions_enabled() {
+ return simpay_get_license()->is_subscriptions_enabled();
}
/**
@@ -1353,9 +1366,10 @@ function simpay_get_payment_form_setting(
function __unstable_simpay_get_form_template_category_name( $category_slug ) {
$categories = array(
- 'business' => __( 'Business', 'stripe' ),
- 'non-profit' => __( 'Non-Profit', 'stripe' ),
- 'recurring' => __( 'Subscriptions', 'stripe' ),
+ 'business' => __( 'Business', 'stripe' ),
+ 'non-profit' => __( 'Non-Profit', 'stripe' ),
+ 'recurring' => __( 'Subscriptions', 'stripe' ),
+ 'alternative' => __( 'Alternative Payment Methods', 'stripe' ),
);
return isset( $categories[ $category_slug ] )
@@ -1390,6 +1404,28 @@ function __unstable_simpay_get_payment_form_templates() {
continue;
}
+ // Adjust licenses if needed.
+ // Templates that utilize "enhanced" subscription functionality should only continue to be available
+ // for "Plus" license holders if they have been grandfathered in.
+ $enhanced_subscription_functionality = array(
+ 'product-installment-plan-form',
+ 'recurring-service-trial-period-form',
+ 'recurring-service-setup-fee-form',
+ );
+
+ if (
+ in_array( $data['slug'], $enhanced_subscription_functionality, true ) &&
+ false === simpay_get_license()->is_enhanced_subscriptions_enabled()
+ ) {
+ $plus = array_search( 'plus', $data['license'], true );
+
+ if ( false !== $plus ) {
+ unset( $data['license'][ $plus ] );
+ }
+
+ $data['license'] = array_values( $data['license'] );
+ }
+
// Pull category names.
if ( isset( $data['categories'] ) ) {
$categories = $data['categories'];
@@ -1405,8 +1441,18 @@ function __unstable_simpay_get_payment_form_templates() {
// Use the store currency if one is not set.
foreach ( $data['data']['prices'] as $k => $price ) {
+ // Top level amounts.
if ( ! isset( $price['currency'] ) ) {
- $price['data'][ $k ]['currency'] = $currency;
+ $data['data']['prices'][ $k ]['currency'] = $currency;
+ }
+
+ // Line items.
+ if ( isset( $data['data']['prices'][ $k ]['line_items'] ) ) {
+ foreach ( $data['data']['prices'][ $k ]['line_items'] as $line_k => $line_item ) {
+ if ( ! isset( $line_item['currency'] ) ) {
+ $data['data']['prices'][ $k ]['line_items'][ $line_k ]['currency'] = $currency;
+ }
+ }
}
}
diff --git a/includes/core/payments/payment-confirmation-template-tags.php b/includes/core/payments/payment-confirmation-template-tags.php
index f6919485..e9902344 100644
--- a/includes/core/payments/payment-confirmation-template-tags.php
+++ b/includes/core/payments/payment-confirmation-template-tags.php
@@ -560,7 +560,7 @@ function __unstable_print_tag_list( $description, $tags ) { // phpcs:ignore PHPC
sprintf(
/* translators: %1$s Opening anchor tag for template tag documentation, do not translate. %2$s Closing anchor tag, do not translate. */
__( 'Have questions about template tags? %1$sView the template tags documentation%2$s', 'stripe' ),
- '',
+ '',
Utils\get_external_link_markup() . ''
)
);
diff --git a/includes/core/payments/paymentintent.php b/includes/core/payments/paymentintent.php
index 763550de..369ff172 100644
--- a/includes/core/payments/paymentintent.php
+++ b/includes/core/payments/paymentintent.php
@@ -404,3 +404,51 @@ function( $tax, $tax_rate ) use ( $post_inclusive_unit_amount ) {
'currency' => $currency,
);
}
+
+/**
+ * Sets the customer's default payment method to the card used to make the payment.
+ *
+ * Only applies to card payments made on-site. This is to maintain backwards compatibility
+ * with previous versions that force-set the default payment method on customer creation.
+ *
+ * @since 4.4.4
+ *
+ * @param \SimplePay\Vendor\Stripe\Event $event Webhook event.
+ * @param \SimplePay\Vendor\Stripe\PaymentIntent $paymentintent PaymentIntent.
+ * @return void
+ */
+function set_card_default_payment_method( $event, $payment_intent ) {
+ $form_id = isset( $payment_intent->metadata->simpay_form_id )
+ ? $payment_intent->metadata->simpay_form_id
+ : 0;
+ $form = simpay_get_form( $form_id );
+
+ if ( false === $form ) {
+ return;
+ }
+
+ $pm_types = $payment_intent->payment_method_types;
+
+ if (
+ 'stripe_checkout' === $form->get_display_type() ||
+ ! in_array( 'card', $pm_types, true )
+ ) {
+ return;
+ }
+
+ API\Customers\update(
+ $payment_intent->customer->id,
+ array(
+ 'invoice_settings' => array(
+ 'default_payment_method' => $payment_intent->payment_method,
+ ),
+ ),
+ $form->get_api_request_args()
+ );
+}
+add_action(
+ 'simpay_webhook_payment_intent_succeeded',
+ __NAMESPACE__ . '\\set_card_default_payment_method',
+ 5,
+ 2
+);
diff --git a/includes/core/post-types/simple-pay/actions.php b/includes/core/post-types/simple-pay/actions.php
index b5d7a715..dd3d2c41 100644
--- a/includes/core/post-types/simple-pay/actions.php
+++ b/includes/core/post-types/simple-pay/actions.php
@@ -236,11 +236,25 @@ function save_product( $post_id, $post, $form ) {
} else {
$product_args['description'] = sanitize_text_field( $description );
- $product = API\Products\update(
- $form_product,
- $product_args,
- $form->get_api_request_args()
- );
+ // Try to update an existing product.
+ try {
+ $product = API\Products\update(
+ $form_product,
+ $product_args,
+ $form->get_api_request_args()
+ );
+
+ // Create a new one if the previous cannot be updated.
+ } catch ( \Exception $e ) {
+ $product = API\Products\create(
+ $product_args,
+ $form->get_api_request_args()
+ );
+
+ update_post_meta( $form->id, $product_key, $product->id );
+
+ $form_product = $product->id;
+ }
}
} catch ( ApiErrorException $e ) {
$error->add(
diff --git a/includes/core/post-types/simple-pay/edit-form-custom-fields.php b/includes/core/post-types/simple-pay/edit-form-custom-fields.php
index 7fc36211..b5c7a5ba 100644
--- a/includes/core/post-types/simple-pay/edit-form-custom-fields.php
+++ b/includes/core/post-types/simple-pay/edit-form-custom-fields.php
@@ -127,7 +127,7 @@ function get_custom_field_types() {
'repeatable' => false,
),
'card' => array(
- 'label' => esc_html__( 'Payment Methods (Card, ACH, etc)', 'stripe' ),
+ 'label' => esc_html__( 'Payment Methods', 'stripe' ),
'type' => 'card',
'category' => 'payment',
'active' => true,
@@ -459,4 +459,8 @@ function add_custom_fields( $post_id ) {
*/
do_action( 'simpay_admin_after_custom_fields' );
}
-add_action( 'simpay_form_settings_meta_payment_options_panel', __NAMESPACE__ . '\\add_custom_fields' );
+add_action(
+ 'simpay_form_settings_meta_payment_options_panel',
+ __NAMESPACE__ . '\\add_custom_fields',
+ 15
+);
diff --git a/includes/core/post-types/simple-pay/edit-form-payment-options.php b/includes/core/post-types/simple-pay/edit-form-payment-options.php
index 368877f7..0bfd6fb1 100644
--- a/includes/core/post-types/simple-pay/edit-form-payment-options.php
+++ b/includes/core/post-types/simple-pay/edit-form-payment-options.php
@@ -408,7 +408,10 @@ function __add_tax_rates_upsell() {
',
+ '',
Utils\get_external_link_markup() . ''
)
);
diff --git a/includes/core/rest-api/v2/class-customer-controller.php b/includes/core/rest-api/v2/class-customer-controller.php
index 1c77b7d2..c153deff 100644
--- a/includes/core/rest-api/v2/class-customer-controller.php
+++ b/includes/core/rest-api/v2/class-customer-controller.php
@@ -100,6 +100,13 @@ public function create_item_permissions_check( $request ) {
*/
public function create_item( $request ) {
try {
+ // Do not proceed if attempting to set the PaymentMethod or Source (legacy flow).
+ if ( isset( $request['payment_method_id'], $request['source_id' ] ) ) {
+ throw new \Exception(
+ __( 'Unable to complete payment.', 'stripe' )
+ );
+ }
+
// Locate form.
if ( ! isset( $request['form_id'] ) ) {
throw new \Exception(
@@ -107,15 +114,6 @@ public function create_item( $request ) {
);
}
- // Gather Payment Method information.
- $source_id = isset( $request['source_id'] )
- ? $request['source_id']
- : null;
-
- $payment_method_id = isset( $request['payment_method_id'] )
- ? $request['payment_method_id']
- : null;
-
// Gather |