installed plugin Easy Digital Downloads version 3.1.0.3

This commit is contained in:
2022-11-27 15:03:07 +00:00
committed by Gitium
parent 555673545b
commit c5dce2cec6
1200 changed files with 238970 additions and 0 deletions

View File

@ -0,0 +1,63 @@
<?php
/**
* Buy Now: AJAX
*
* @package EDD_Stripe
* @since 2.8.0
*/
/**
* Adds a Download to the Cart on the `edds_add_to_cart` AJAX action.
*
* @since 2.8.0
*/
function edds_buy_now_ajax_add_to_cart() {
$data = $_POST;
if ( ! isset( $data['download_id'] ) || ! isset( $data['nonce'] ) ) {
return wp_send_json_error( array(
'message' => __( 'Unable to add item to cart.', 'easy-digital-downloads' ),
) );
}
$download_id = absint( $data['download_id'] );
$price_id = absint( $data['price_id'] );
$quantity = absint( $data['quantity'] );
$nonce = sanitize_text_field( $data['nonce'] );
$valid_nonce = wp_verify_nonce( $nonce, 'edd-add-to-cart-' . $download_id );
if ( false === $valid_nonce ) {
return wp_send_json_error( array(
'message' => __( 'Unable to add item to cart.', 'easy-digital-downloads' ),
) );
}
// Empty cart.
edd_empty_cart();
// Add individual item.
edd_add_to_cart( $download_id, array(
'quantity' => $quantity,
'price_id' => $price_id,
) );
return wp_send_json_success( array(
'checkout' => edds_buy_now_checkout(),
) );
}
add_action( 'wp_ajax_edds_add_to_cart', 'edds_buy_now_ajax_add_to_cart' );
add_action( 'wp_ajax_nopriv_edds_add_to_cart', 'edds_buy_now_ajax_add_to_cart' );
/**
* Empties the cart on the `edds_buy_now_empty_cart` AJAX action.
*
* @since 2.8.0
*/
function edds_buy_now_ajax_empty_cart() {
edd_empty_cart();
return wp_send_json_success();
}
add_action( 'wp_ajax_edds_empty_cart', 'edds_buy_now_ajax_empty_cart' );
add_action( 'wp_ajax_nopriv_edds_empty_cart', 'edds_buy_now_ajax_empty_cart' );

View File

@ -0,0 +1,84 @@
<?php
/**
* Buy Now: Checkout
*
* @package EDD_Stripe
* @since 2.8.0
*/
// Hook in global card validation to this flow.
add_action( 'edds_buy_now_checkout_error_checks', 'edds_process_post_data' );
/**
* Adds Buy Now-specific overrides when processing a Buy Now purchase.
*
* @since 2.8.0
*/
function edds_buy_now_process_overrides() {
if ( ! isset( $_POST ) ) {
return;
}
if ( ! isset( $_POST['edds-gateway'] ) ) {
return;
}
if ( 'buy-now' !== $_POST['edds-gateway'] ) {
return;
}
// Ensure Billing Address and Name Fields are not required.
add_filter( 'edd_require_billing_address', '__return_false' );
// Require email address.
add_filter( 'edd_purchase_form_required_fields', 'edds_buy_now_purchase_form_required_fields', 9999 );
// Remove 3rd party validations.
remove_all_actions( 'edd_checkout_error_checks' );
remove_all_actions( 'edd_checkout_user_error_checks' );
// Validate the form $_POST data.
$valid_data = edd_purchase_form_validate_fields();
/**
* Allows Buy Now-specific checkout validations.
*
* @since 2.8.0
*
* @param array $valid_data Validated checkout data.
* @param array $_POST Global $_POST data.
*/
do_action( 'edds_buy_now_checkout_error_checks', $valid_data, $_POST );
// Validate the user
$user = edd_get_purchase_form_user( $valid_data );
/**
* Allows Buy Now-specific user validations.
*
* @since 2.8.0
*
* @param array $user Validated user data.
* @param array $valid_data Validated checkout data.
* @param array $_POST Global $_POST data.
*/
do_action( 'edds_buy_now_checkout_user_error_checks', $user, $valid_data, $_POST );
}
add_action( 'edd_pre_process_purchase', 'edds_buy_now_process_overrides' );
/**
* Filters the purchase form's required field to only
* require an email address.
*
* @since 2.8.0
*
* @return array
*/
function edds_buy_now_purchase_form_required_fields() {
return array(
'edd_email' => array(
'error_id' => 'invalid_email',
'error_message' => __( 'Please enter a valid email address', 'easy-digital-downloads' )
),
);
}

View File

@ -0,0 +1,59 @@
<?php
/**
* Buy Now: Functions
*
* @package EDD_Stripe
* @since 2.8.0
*/
/**
* Checks to see if "Buy Now" is enabled.
*
* @since 2.8
* @return boolean
*/
function edds_buy_now_is_enabled() {
if ( false === edds_is_gateway_active() ) {
return false;
}
// Check if the shop supports Buy Now.
$shop_supports = edd_shop_supports_buy_now();
if ( false === $shop_supports ) {
return false;
}
// Check if guest checkout is disabled and the user is not logged in.
if ( edd_logged_in_only() && ! is_user_logged_in() ) {
return false;
}
return true;
}
/**
* Allows "Buy Now" support if `stripe` and `stripe-prb` (Express Checkout) are
* the only two active gateways and taxes are not enabled.
*
* @since 2.8
* @param boolean $supports Whether the shop supports Buy Now, as determined by EDD.
* @return boolean
*/
function edds_shop_supports_buy_now( $supports ) {
if ( edd_use_taxes() ) {
return false;
}
$gateways = edd_get_enabled_payment_gateways();
$stripe_gateways = array( 'stripe', 'stripe-prb' );
$remaining_gateways = array_diff( array_keys( $gateways ), $stripe_gateways );
if ( empty( $remaining_gateways ) ) {
return true;
}
return $supports;
}
add_filter( 'edd_shop_supports_buy_now', 'edds_shop_supports_buy_now' );

View File

@ -0,0 +1,13 @@
<?php
/**
* Buy Now
*
* @package EDD_Stripe
* @since 2.8.0
*/
require_once EDDS_PLUGIN_DIR . '/includes/payment-methods/buy-now/functions.php';
require_once EDDS_PLUGIN_DIR . '/includes/payment-methods/buy-now/ajax.php';
require_once EDDS_PLUGIN_DIR . '/includes/payment-methods/buy-now/checkout.php';
require_once EDDS_PLUGIN_DIR . '/includes/payment-methods/buy-now/template.php';
require_once EDDS_PLUGIN_DIR . '/includes/payment-methods/buy-now/shortcode.php';

View File

@ -0,0 +1,89 @@
<?php
/**
* Buy Now: Shortcode
*
* @package EDD_Stripe
* @since 2.8.0
*/
/**
* Sets the stripe-checkout parameter if the direct parameter is present in the [purchase_link] short code.
*
* @since 2.0
*
* @param array $out
* @param array $pairs
* @param array $atts
* @return array
*/
function edd_stripe_purchase_link_shortcode_atts( $out, $pairs, $atts ) {
if ( ! edds_buy_now_is_enabled() ) {
return $out;
}
$direct = false;
// [purchase_link direct=true]
if ( isset( $atts['direct'] ) && true === edds_truthy_to_bool( $atts['direct'] ) ) {
$direct = true;
// [purchase_link stripe-checkout]
} else if ( isset( $atts['stripe-checkout'] ) || false !== array_search( 'stripe-checkout', $atts, true ) ) {
$direct = true;
}
$out['direct'] = $direct;
if ( true === $direct ) {
$out['stripe-checkout'] = $direct;
} else {
unset( $out['stripe-checkout'] );
}
return $out;
}
add_filter( 'shortcode_atts_purchase_link', 'edd_stripe_purchase_link_shortcode_atts', 10, 3 );
/**
* Sets the stripe-checkout parameter if the direct parameter is present in edd_get_purchase_link()
*
* @since 2.0
* @since 2.8.0 Adds `.edds-buy-now` to the class list.
*
* @param array $arg Purchase link shortcode attributes.
* @return array
*/
function edd_stripe_purchase_link_atts( $args ) {
global $edds_has_buy_now;
if ( ! edds_buy_now_is_enabled() ) {
return $args;
}
// Don't use modal if "Free Downloads" is active and available for this download.
// https://easydigitaldownloads.com/downloads/free-downloads/
if ( function_exists( 'edd_free_downloads_use_modal' ) ) {
if ( edd_free_downloads_use_modal( $args['download_id'] ) && ! edd_has_variable_prices( $args['download_id'] ) ) {
return $args;
}
}
$direct = edds_truthy_to_bool( $args['direct'] );
$args['direct'] = $direct;
if ( true === $direct ) {
$args['stripe-checkout'] = true;
$args['class'] .= ' edds-buy-now';
if ( false === edd_item_in_cart( $args['download_id'] ) ) {
$edds_has_buy_now = $direct;
}
} else {
unset( $args['stripe-checkout'] );
}
return $args;
}
add_filter( 'edd_purchase_link_args', 'edd_stripe_purchase_link_atts', 10 );

View File

@ -0,0 +1,228 @@
<?php
/**
* Buy Now: Template
*
* @package EDD_Stripe
* @since 2.8.0
*/
/**
* Adds "Buy Now" modal markup to the bottom of the page.
*
* @since 2.8.0
*/
function edds_buy_now_modal() {
// Check if Stripe Buy Now is enabled.
global $edds_has_buy_now;
if ( true !== $edds_has_buy_now ) {
return;
}
if ( ! edds_buy_now_is_enabled() ) {
return;
}
// Enqueue core scripts.
add_filter( 'edd_is_checkout', '__return_true' );
if ( function_exists( 'edd_enqueue_scripts' ) ) {
// https://github.com/easydigitaldownloads/easy-digital-downloads/issues/7847
edd_enqueue_scripts();
edd_localize_scripts();
} else {
edd_load_scripts();
}
edd_agree_to_terms_js();
remove_filter( 'edd_is_checkout', '__return_true' );
// Enqueue scripts.
edd_stripe_js( true );
edd_stripe_css( true );
echo edds_modal( array(
'id' => 'edds-buy-now',
'title' => __( 'Buy Now', 'easy-digital-downloads' ),
'class' => array(
'edds-buy-now-modal',
),
'content' => '<span class="edd-loading-ajax edd-loading"></span>',
) ); // WPCS: XSS okay.
}
add_action( 'wp_print_footer_scripts', 'edds_buy_now_modal', 0 );
/**
* Outputs a custom "Buy Now"-specific Checkout form.
*
* @since 2.8.0
*/
function edds_buy_now_checkout() {
$total = (int) edd_get_cart_total();
$form_mode = $total > 0
? 'payment-mode=stripe'
: 'payment-mode=manual';
$form_action = edd_get_checkout_uri( $form_mode );
$existing_cards = edd_stripe_get_existing_cards( get_current_user_id() );
$customer = EDD()->session->get( 'customer' );
$customer = wp_parse_args(
$customer,
array(
'email' => '',
)
);
if ( is_user_logged_in() ) {
$user_data = get_userdata( get_current_user_id() );
foreach( $customer as $key => $field ) {
if ( 'email' == $key && empty( $field ) ) {
$customer[ $key ] = $user_data->user_email;
} elseif ( empty( $field ) ) {
$customer[ $key ] = $user_data->$key;
}
}
}
$customer = array_map( 'sanitize_text_field', $customer );
remove_action( 'edd_after_cc_fields', 'edd_default_cc_address_fields', 10 );
remove_action( 'edd_purchase_form_before_submit', 'edd_checkout_final_total', 999 );
// Filter purchase button label.
add_filter( 'edd_get_checkout_button_purchase_label', 'edds_buy_now_checkout_purchase_label' );
ob_start();
?>
<div id="edd_checkout_form_wrap">
<form
id="edd_purchase_form"
class="edd_form edds-buy-now-form"
action="<?php echo esc_url( $form_action ); ?>"
method="POST"
>
<p>
<label class="edd-label" for="edd-email">
<?php esc_html_e( 'Email Address', 'easy-digital-downloads' ); ?>
<?php if ( edd_field_is_required( 'edd_email' ) ) : ?>
<span class="edd-required-indicator">*</span>
<?php endif ?>
</label>
<input
id="edd-email"
class="edd-input required"
type="email"
name="edd_email"
value="<?php echo esc_attr( $customer['email'] ); ?>"
<?php if ( edd_field_is_required( 'edd_email' ) ) : ?>
required
<?php endif; ?>
/>
</p>
<?php if ( $total > 0 ) : ?>
<?php if ( ! empty( $existing_cards ) ) : ?>
<?php edd_stripe_existing_card_field_radio( get_current_user_id() ); ?>
<?php endif; ?>
<div
class="edd-stripe-new-card"
<?php if ( ! empty( $existing_cards ) ) : ?>
style="display: none;"
<?php endif; ?>
>
<?php do_action( 'edd_stripe_new_card_form' ); ?>
<?php do_action( 'edd_after_cc_expiration' ); ?>
</div>
<?php endif; ?>
<?php
edd_terms_agreement();
edd_privacy_agreement();
edd_checkout_hidden_fields();
?>
<div id="edd_purchase_submit">
<?php echo edds_get_tokenizer_input(); // WPCS: XSS okay. ?>
<?php echo edd_checkout_button_purchase(); // WPCS: XSS okay. ?>
</div>
<div class="edd_cart_total" style="display: none;">
<div
class="edd_cart_amount"
data-total="<?php echo edd_get_cart_total(); ?>"
data-total-currency="<?php echo edd_currency_filter( edd_format_amount( edd_get_cart_total() ) ); ?>"
>
</div>
</div>
<input type="hidden" name="edds-gateway" value="buy-now" />
</form>
</div>
<?php
return ob_get_clean();
}
/**
* Filters the label of the of the "Purchase" button in the "Buy Now" modal.
*
* @since 2.8.0
*
* @param string $label Purchase label.
* @return string
*/
function edds_buy_now_checkout_purchase_label( $label ) {
$total = edd_get_cart_total();
if ( 0 === (int) $total ) {
return $label;
}
return sprintf(
'%s - %s',
edd_currency_filter(
edd_format_amount( $total )
),
$label
);
}
/**
* Adds additional script variables needed for the Buy Now flow.
*
* @since 2.8.0
*
* @param array $vars Script variables.
* @return array
*/
function edds_buy_now_vars( $vars ) {
if ( ! isset( $vars['i18n'] ) ) {
$vars['i18n'] = array();
}
// Non-zero amount.
$label = edd_get_option( 'checkout_label', '' );
$complete_purchase = ! empty( $label )
? $label
: esc_html__( 'Purchase', 'easy-digital-downloads' );
/* This filter is documented in easy-digital-downloads/includes/checkout/template.php */
$complete_purchase = apply_filters(
'edd_get_checkout_button_purchase_label',
$complete_purchase,
$label
);
$vars['i18n']['completePurchase'] = $complete_purchase;
return $vars;
}
add_filter( 'edd_stripe_js_vars', 'edds_buy_now_vars' );

View File

@ -0,0 +1,151 @@
<?php
/**
* Payment Request Button: Settings
*
* @package EDD_Stripe
* @since 2.8.0
*/
/**
* Adds settings to the Stripe subtab.
*
* @since 2.8.0
*
* @param array $settings Gateway settings.
* @return array Filtered gateway settings.
*/
function edds_prb_add_settings( $settings ) {
// Prevent adding the extra settings if the requirements are not met.
// The `edd_settings_gateways` filter runs regardless of the short circuit
// inside of `edds_add_settings()`
if (
false === edds_has_met_requirements( 'php' ) &&
false === edds_is_pro()
) {
return $settings;
}
if ( true === edd_use_taxes() ) {
$prb_settings = array(
array(
'id' => 'stripe_prb_taxes',
'name' => __( 'Apple Pay/Google Pay', 'easy-digital-downloads' ),
'type' => 'edds_stripe_prb_taxes',
),
);
} else {
$prb_settings = array(
array(
'id' => 'stripe_prb',
'name' => __( 'Apple Pay/Google Pay', 'easy-digital-downloads' ),
'desc' => wp_kses(
(
sprintf(
/* translators: %1$s Opening anchor tag, do not translate. %2$s Opening anchor tag, do not translate. %3$s Closing anchor tag, do not translate. */
__( '"Express Checkout" via Apple Pay, Google Pay, or Microsoft Pay digital wallets. By using Apple Pay, you agree to %1$sStripe%3$s and %2$sApple\'s%3$s terms of service.', 'easy-digital-downloads' ),
'<a href="https://stripe.com/apple-pay/legal" target="_blank" rel="noopener noreferrer">',
'<a href="https://developer.apple.com/apple-pay/acceptable-use-guidelines-for-websites/" target="_blank" rel="noopener noreferrer">',
'</a>'
) . (
edd_is_test_mode()
? '<br /><strong>' . __( 'Apple Pay is not available in Test Mode.', 'easy-digital-downloads' ) . '</strong> ' . sprintf(
/* translators: %1$s Opening anchor tag, do not translate. %2$s Opening anchor tag, do not translate. */
__( 'See our %1$sdocumentation%2$s for more information.', 'easy-digital-downloads' ),
'<a href="' . esc_url( edds_documentation_route( 'stripe-express-checkout' ) ) . '" target="_blank" rel="noopener noreferrer">',
'</a>'
)
: ''
)
),
array(
'br' => true,
'strong' => true,
'a' => array(
'href' => true,
'target' => true,
'rel' => true,
),
)
),
'type' => 'multicheck',
'options' => array(
/** translators: %s Download noun */
'single' => sprintf(
__( 'Single %s', 'easy-digital-downloads' ),
edd_get_label_singular()
),
/** translators: %s Download noun */
'archive' => sprintf(
__( '%s Archive (includes <code>[downloads]</code> shortcode)', 'easy-digital-downloads' ),
edd_get_label_singular()
),
'checkout' => __( 'Checkout', 'easy-digital-downloads' ),
),
)
);
}
$position = array_search(
'stripe_statement_descriptor',
array_values( wp_list_pluck( $settings['edd-stripe'], 'id' ) ),
true
);
$settings['edd-stripe'] = array_merge(
array_slice( $settings['edd-stripe'], 0, $position + 1 ),
$prb_settings,
array_slice( $settings['edd-stripe'], $position + 1 )
);
return $settings;
}
add_filter( 'edd_settings_gateways', 'edds_prb_add_settings', 20 );
/**
* Removes multicheck options and outputs a message about "Express Checkout" incompatibility with taxes.
*
* @since 2.8.7
*/
function edd_edds_stripe_prb_taxes_callback() {
echo esc_html__(
'This feature is not available when taxes are enabled.',
'easy-digital-downloads'
) . ' ';
echo wp_kses(
sprintf(
/* translators: %1$s Opening anchor tag, do not translate. %2$s Closing anchor tag, do not translate. */
__(
'See the %1$sExpress Checkout documentation%2$s for more information.',
'easy-digital-downloads'
),
'<a href="' . esc_url( edds_documentation_route( 'stripe-express-checkout' ) ) . '#edds-prb-faqs" target="_blank" rel="noopener noreferrer">',
'</a>'
),
array(
'a' => array(
'href' => true,
'target' => true,
'rel' => true,
),
)
);
}
/**
* Force "Payment Request Buttons" to be disabled if taxes are enabled.
*
* @since 2.8.0
*
* @param mixed $value Setting value.
* @param string $key Setting key.
* @return string Setting value.
*/
function edds_prb_sanitize_setting( $value, $key ) {
if ( 'stripe_prb' === $key && edd_use_taxes() ) {
$value = array();
}
return $value;
}
add_filter( 'edd_settings_sanitize_multicheck', 'edds_prb_sanitize_setting', 10, 2 );

View File

@ -0,0 +1,253 @@
<?php
/**
* Payment Request Button: AJAX
*
* @package EDD_Stripe
* @since 2.8.0
*/
/**
* Starts the Checkout process for a Payment Request.
*
* This needs to be used instead of `_edds_process_purchase_form()` so
* Checkout form data can be shimmed or faked to prevent getting hung
* up on things like privacy policy, terms of service, etc.
*
* @since 2.8.0
*/
function edds_prb_ajax_process_checkout() {
// Clear any errors that might be used as a reason to attempt a redirect in the following action.
edd_clear_errors();
$download_id = isset( $_POST['downloadId'] )
? intval( $_POST['downloadId'] )
: 0;
$email = isset( $_POST['email'] )
? sanitize_text_field( $_POST['email'] )
: '';
$name = isset( $_POST['name'] )
? sanitize_text_field( $_POST['name'] )
: '';
$payment_method = isset( $_POST['paymentMethod'] )
? $_POST['paymentMethod']
: '';
$context = isset( $_POST['context'] )
? $_POST['context']
: 'checkout';
// Add a Download to the cart if we are not processing the full cart.
if ( 'download' === $context ) {
$price_id = isset( $_POST['priceId'] )
? intval( $_POST['priceId'] )
: false;
$quantity = isset( $_POST['quantity'] )
? intval( $_POST['quantity'] )
: 1;
// Empty cart.
edd_empty_cart();
// Add individual item.
edd_add_to_cart( $download_id, array(
'quantity' => $quantity,
'price_id' => $price_id,
) );
// Refilter guest checkout when the item is added to the cart dynamically.
// This is a duplicate of EDD_Recurring_Gateway::require_login().
if ( defined( 'EDD_RECURRING_VERSION' ) ) {
$cart_items = edd_get_cart_contents();
$has_recurring = false;
$auto_register = class_exists( 'EDD_Auto_Register' );
if ( ! empty( $cart_items ) ) {
foreach ( $cart_items as $item ) {
if ( ! isset( $item['options']['recurring'] ) ) {
continue;
}
$has_recurring = true;
}
if ( $has_recurring && ! $auto_register ) {
add_filter( 'edd_no_guest_checkout', '__return_true' );
add_filter( 'edd_logged_in_only', '__return_true' );
}
}
}
}
try {
$data = array(
// Mark "sub-gateway" for Stripe. This represents the Payment Method
// currently being used. e.g `ideal`, `wepay`, `payment-request`, etc.
//
// This is used to filter field requirements via `edd_pre_process_purchase` hook.
'edds-gateway' => 'payment-request',
'edds-prb-context' => $context,
);
// Checkout-specific data.
if ( 'checkout' === $context ) {
$form_data = isset( $_POST['form_data'] )
? $_POST['form_data']
: array();
// Use the Payment Method's billing details.
$card_name = (
! empty( $payment_method['billing_details'] ) &&
! empty( $payment_method['billing_details']['name'] )
)
? $payment_method['billing_details']['name']
: $name;
$billing_details = ! empty( $payment_method['billing_details'] )
? array(
'card_name' => $card_name,
'card_address' => $payment_method['billing_details']['address']['line1'],
'card_address_2' => $payment_method['billing_details']['address']['line2'],
'card_city' => $payment_method['billing_details']['address']['city'],
'card_zip' => $payment_method['billing_details']['address']['postal_code'],
'billing_country' => $payment_method['billing_details']['address']['country'],
'card_state' => $payment_method['billing_details']['address']['state'],
)
: array(
'card_name' => $card_name,
'card_address' => '',
'card_address_2' => '',
'card_city' => '',
'card_zip' => '',
'billing_country' => '',
'card_state' => '',
);
// Add the Payment Request's name as the card name.
$_POST['form_data'] = add_query_arg(
$billing_details,
$form_data
);
// Single-download data.
} else {
// Fake checkout form data.
$_POST['form_data'] = http_build_query(
array_merge(
$data,
array(
// Use Email from Payment Request.
'edd_email' => $email,
'edd-user-id' => get_current_user_id(),
'edd_action' => 'purchase',
'edd-gateway' => 'stripe',
'edd_agree_to_terms' => '1',
'edd_agree_to_privacy_policy' => '1',
'edd-process-checkout-nonce' => wp_create_nonce( 'edd-process-checkout' ),
)
)
);
}
$_POST['payment_method_id'] = isset( $payment_method['id'] )
? sanitize_text_field( $payment_method['id'] )
: '';
$_POST['payment_method_exists'] = false;
// Adjust PaymentIntent creation for PRB flow.
add_filter( 'edds_create_payment_intent_args', 'edds_prb_create_payment_intent_args', 20 );
add_filter( 'edds_create_setup_intent_args', 'edds_prb_create_setup_intent_args', 20 );
// This will send a JSON response.
_edds_process_purchase_form();
} catch ( \Exception $e ) {
wp_send_json_error( array(
'message' => esc_html( $e->getMessage() ),
) );
}
}
add_action( 'wp_ajax_edds_prb_ajax_process_checkout', 'edds_prb_ajax_process_checkout' );
add_action( 'wp_ajax_nopriv_edds_prb_ajax_process_checkout', 'edds_prb_ajax_process_checkout' );
/**
* Filters the arguments used when creating a PaymentIntent while
* using a Payment Request Button.
*
* @since 2.8.0
*
* @param array $args {
* PaymentIntent arguments.
*
* @link https://stripe.com/docs/api/payment_intents/create
* }
* @return array
*/
function edds_prb_create_payment_intent_args( $args ) {
$args['confirmation_method'] = 'automatic';
$args['confirm'] = false;
$args['capture_method'] = 'automatic';
$args['metadata']['edds_prb'] = '1';
return $args;
}
/**
* Filters the arguments used when creating a SetupIntent while
* using a Payment Request Button.
*
* @since 2.8.0
*
* @param array $args {
* SetupIntent arguments.
*
* @link https://stripe.com/docs/api/setup_intents/create
* }
* @return array
*/
function edds_prb_create_setup_intent_args( $args ) {
$args['confirm'] = false;
$args['metadata']['edds_prb'] = '1';
return $args;
}
/**
* Gathers Payment Request options based on the current context.
*
* @since 2.8.0
*/
function edds_prb_ajax_get_options() {
$download_id = isset( $_POST['downloadId'] )
? intval( $_POST['downloadId'] )
: 0;
// Single Download.
if ( ! empty( $download_id ) ) {
$price_id = isset( $_POST['priceId'] ) && 'false' !== $_POST['priceId']
? intval( $_POST['priceId'] )
: false;
$quantity = isset( $_POST['quantity'] )
? intval( $_POST['quantity'] )
: 1;
$data = edds_prb_get_download_data( $download_id, $price_id, $quantity );
// Handle cart eventually?
} else {
$data = edds_prb_get_cart_data();
}
// Country is not valid at this point.
// https://stripe.com/docs/js/payment_request/update
unset( $data['country'] );
wp_send_json_success( $data );
}
add_action( 'wp_ajax_edds_prb_ajax_get_options', 'edds_prb_ajax_get_options' );
add_action( 'wp_ajax_nopriv_edds_prb_ajax_get_options', 'edds_prb_ajax_get_options' );

View File

@ -0,0 +1,280 @@
<?php
/**
* Payment Request: Apple Pay
*
* @link https://stripe.com/docs/stripe-js/elements/payment-request-button#verifying-your-domain-with-apple-pay
*
* @package EDD_Stripe
* @since 2.8.0
*/
/**
* Registers admin notices.
*
* @since 2.8.0
*
* @return true|WP_Error True if all notices are registered, otherwise WP_Error.
*/
function edds_prb_apple_pay_admin_notices_register() {
$registry = edds_get_registry( 'admin-notices' );
if ( ! $registry ) {
return new WP_Error( 'edds-invalid-registry', esc_html__( 'Unable to locate registry', 'easy-digital-downloads' ) );
}
try {
// General error message.
$message = (
'<strong>' . esc_html__( 'Apple Pay domain verification error.', 'easy-digital-downloads' ) . '</strong><br />' .
edd_get_option( 'stripe_prb_apple_pay_domain_error', '' )
);
$registry->add(
'apple-pay-' . $_SERVER['HTTP_HOST'],
array(
'message' => wp_kses(
wpautop( $message ),
array(
'code' => true,
'br' => true,
'strong' => true,
'p' => true,
'a' => array(
'href' => true,
'rel' => true,
'target' => true,
),
)
),
'type' => 'error',
'dismissible' => true,
)
);
} catch( Exception $e ) {
return new WP_Error( 'edds-invalid-notices-registration', esc_html( $e->getMessage() ) );
};
return true;
}
add_action( 'admin_init', 'edds_prb_apple_pay_admin_notices_register', 30 );
/**
* Conditionally prints registered notices.
*
* @since 2.8.0
*/
function edds_prb_apple_pay_admin_notices_print() {
// Current user needs capability to dismiss notices.
if ( ! current_user_can( 'manage_options' ) ) {
return;
}
$registry = edds_get_registry( 'admin-notices' );
if ( ! $registry ) {
return;
}
$notices = new EDD_Stripe_Admin_Notices( $registry );
wp_enqueue_script( 'edds-admin-notices' );
try {
$error = edd_get_option( 'stripe_prb_apple_pay_domain_error', '' );
$test_mode = edd_is_test_mode();
if ( ! empty( $error ) && false === $test_mode ) {
$notices->output( 'apple-pay-' . $_SERVER['HTTP_HOST'] );
}
} catch( Exception $e ) {}
}
add_action( 'admin_notices', 'edds_prb_apple_pay_admin_notices_print' );
/**
* Returns information associated with the name/location of the domain verification file.
*
* @since 2.8.0
*
* @return array Domain verification file information.
*/
function edds_prb_apple_pay_get_fileinfo() {
$path = untrailingslashit( $_SERVER['DOCUMENT_ROOT'] );
$dir = '.well-known';
$file = 'apple-developer-merchantid-domain-association';
return array(
'path' => $path,
'dir' => $dir,
'file' => $file,
'fullpath' => $path . '/' . $dir . '/' . $file,
);
}
/**
* Determines if the current website is setup to use Apple Pay.
*
* @since 2.8.0
*
* @return bool True if the domain has been verified and the association file exists.
*/
function edds_prb_apple_pay_is_valid() {
return (
edds_prb_apple_pay_has_domain_verification_file() &&
edds_prb_apple_pay_has_domain_verification()
);
}
/**
* Determines if the domain verification file already exists.
*
* @since 2.8.0
*
* @return bool True if the domain verification file exists.
*/
function edds_prb_apple_pay_has_domain_verification_file() {
$fileinfo = edds_prb_apple_pay_get_fileinfo();
if ( ! @file_exists( $fileinfo['fullpath'] ) ) {
return false;
}
return true;
}
/**
* Determines if the currently verified domain matches the current site.
*
* @since 2.8.0
*
* @return bool True if the saved verified domain matches the current site.
*/
function edds_prb_apple_pay_has_domain_verification() {
return edd_get_option( 'stripe_prb_apple_pay_domain' ) === $_SERVER['HTTP_HOST'];
}
/**
* Attempts to create a directory in the server root and copy the domain verification file.
*
* @since 2.8.0
*
* @throws \Exception If the directory or file cannot be created.
*/
function edds_prb_apple_pay_create_directory_and_move_file() {
$file = edds_prb_apple_pay_has_domain_verification_file();
if ( true === $file ) {
return;
}
$fileinfo = edds_prb_apple_pay_get_fileinfo();
// Create directory if it does not exist.
if ( ! file_exists( trailingslashit( $fileinfo['path'] ) . $fileinfo['dir'] ) ) {
if ( ! @mkdir( trailingslashit( $fileinfo['path'] ) . $fileinfo['dir'], 0755 ) ) { // @codingStandardsIgnoreLine
throw new \Exception( __( 'Unable to create domain association folder in domain root.', 'easy-digital-downloads' ) );
}
}
// Move file if needed.
if ( ! edds_prb_apple_pay_has_domain_verification_file() ) {
if ( ! @copy( trailingslashit( EDDS_PLUGIN_DIR ) . $fileinfo['file'], $fileinfo['fullpath'] ) ) { // @codingStandardsIgnoreLine
throw new \Exception( __( 'Unable to copy domain association file to domain .well-known directory.', 'easy-digital-downloads' ) );
}
}
}
/**
* Checks Apple Pay domain verification if there is an existing error.
* If the domain was added to the Stripe Dashboard clear the error.
*
* @since 2.8.0
*/
function edds_prb_apple_pay_check_domain() {
$error = edd_get_option( 'stripe_prb_apple_pay_domain_error', '' );
if ( empty( $error ) ) {
return;
}
try {
$domains = edds_api_request( 'ApplePayDomain', 'all' );
foreach ( $domains->autoPagingIterator() as $domain ) {
if ( $domain->domain_name === $_SERVER['HTTP_HOST'] ) {
edd_delete_option( 'stripe_prb_apple_pay_domain_error' );
edd_update_option( 'stripe_prb_apple_pay_domain', $_SERVER['HTTP_HOST'] );
break;
}
}
} catch ( \Exception $e ) {}
}
add_action( 'admin_init', 'edds_prb_apple_pay_check_domain', 10 );
/**
* Verifies the current domain.
*
* @since 2.8.0
*/
function edds_prb_apple_pay_verify_domain() {
// Payment Request Button is not enabled, do nothing.
if ( false === edds_prb_is_enabled() ) {
return;
}
// Avoid getting caught in AJAX requests.
if ( defined( 'DOING_AJAX' ) && true === DOING_AJAX ) {
return;
}
// Must be verified in Live Mode.
if ( true === edd_is_test_mode() ) {
return;
}
// Current site is a development environment, Apple Pay won't be able to be used, do nothing.
if ( false !== edd_is_dev_environment() ) {
return;
}
// Current domain matches and the file exists, do nothing.
if ( true === edds_prb_apple_pay_is_valid() ) {
return;
}
try {
// Create directory and move file if needed.
edds_prb_apple_pay_create_directory_and_move_file();
$stripe_connect_account_id = edd_get_option( 'stripe_connect_account_id', '' );
// Automatically verify when using "real" API keys.
if ( empty( $stripe_connect_account_id ) ) {
$verification = edds_api_request(
'ApplePayDomain',
'create',
array(
'domain_name' => $_SERVER['HTTP_HOST'],
)
);
edd_update_option( 'stripe_prb_apple_pay_domain', $_SERVER['HTTP_HOST'] );
// Set an error that the domain needs to be manually added.
// Using Stripe Connect API keys does not allow this to be done automatically.
} else {
throw new \Exception(
sprintf(
/* translators: %1$s Opening anchor tag, do not translate. %2$s Closing anchor tag, do not translate. */
( __( 'Please %1$smanually add your domain%2$s %3$s to use Apple Pay.', 'easy-digital-downloads' ) . '<br />' ),
'<a href="https://dashboard.stripe.com/settings/payments/apple_pay" target="_blank" rel="noopener noreferrer">',
'</a>',
'<code>' . $_SERVER['HTTP_HOST'] . '</code>'
)
);
}
} catch ( \Exception $e ) {
// Set error if something went wrong.
edd_update_option( 'stripe_prb_apple_pay_domain_error', $e->getMessage() );
}
}
add_action( 'admin_init', 'edds_prb_apple_pay_verify_domain', 20 );

View File

@ -0,0 +1,377 @@
<?php
/**
* Payment Request Button: Checkout
*
* @package EDD_Stripe
* @since 2.8.0
*/
/**
* Registers "Express" (via Apple Pay/Google Pay) gateway.
*
* @since 2.8.0
*
* @param array $gateways Registered payment gateways.
* @return array
*/
function edds_prb_shim_gateways( $gateways ) {
// Do nothing in admin.
if ( is_admin() ) {
return $gateways;
}
// Avoid endless loops when checking if the Stripe gateway is active.
remove_filter( 'edd_payment_gateways', 'edds_prb_shim_gateways' );
remove_filter( 'edd_enabled_payment_gateways', 'edds_prb_shim_gateways' );
$enabled = true;
// Do nothing if Payment Requests are not enabled.
if ( false === edds_prb_is_enabled( 'checkout' ) ) {
$enabled = false;
}
// Track default gateway so we can resort the list.
$default_gateway_id = edd_get_default_gateway();
if ( 'stripe-prb' === $default_gateway_id ) {
$default_gateway_id = 'stripe';
}
// Avoid endless loops when checking if the Stripe gateway is active.
add_filter( 'edd_payment_gateways', 'edds_prb_shim_gateways' );
add_filter( 'edd_enabled_payment_gateways', 'edds_prb_shim_gateways' );
if ( false === $enabled ) {
return $gateways;
}
// Ensure default gateway is considered registered at this point.
if ( isset( $gateways[ $default_gateway_id ] ) ) {
$default_gateway = array(
$default_gateway_id => $gateways[ $default_gateway_id ],
);
// Fall back to first gateway in the list.
} else {
if ( function_exists( 'array_key_first' ) ) {
$first_gateway_id = array_key_first( $gateways );
} else {
$gateway_keys = array_keys( $gateways );
$first_gateway_id = reset( $gateway_keys );
}
$default_gateway = array(
$first_gateway_id => $gateways[ $first_gateway_id ],
);
}
unset( $gateways[ $default_gateway_id ] );
return array_merge(
array(
'stripe-prb' => array(
'admin_label' => __( 'Express Checkout (Apple Pay/Google Pay)', 'easy-digital-downloads' ),
'checkout_label' => __( 'Express Checkout', 'easy-digital-downloads' ),
'supports' => array(),
),
),
$default_gateway,
$gateways
);
}
add_filter( 'edd_payment_gateways', 'edds_prb_shim_gateways' );
add_filter( 'edd_enabled_payment_gateways', 'edds_prb_shim_gateways' );
/**
* Enables the shimmed `stripe-prb` gateway.
*
* @since 2.8.0
*
* @param array $gateways Enabled payment gateways.
* @return array
*/
function edds_prb_enable_shim_gateway( $gateways ) {
// Do nothing in admin.
if ( is_admin() ) {
return $gateways;
}
// Avoid endless loops when checking if the Stripe gateway is active.
remove_filter( 'edd_get_option_gateways', 'edds_prb_enable_shim_gateway' );
$enabled = true;
// Do nothing if Payment Requests are not enabled.
if ( false === edds_prb_is_enabled( 'checkout' ) ) {
$enabled = false;
}
// Avoid endless loops when checking if the Stripe gateway is active.
add_filter( 'edd_get_option_gateways', 'edds_prb_enable_shim_gateway' );
if ( false === $enabled ) {
return $gateways;
}
$gateways['stripe-prb'] = 1;
return $gateways;
}
add_filter( 'edd_get_option_gateways', 'edds_prb_enable_shim_gateway' );
/**
* Ensures the base `stripe` gateway is used as an ID _only_ when generating
* the hidden `input[name="edd-gateway"]` field.
*
* @since 2.8.0
*/
function edds_prb_shim_active_gateways() {
add_filter( 'edd_chosen_gateway', 'edds_prb_set_base_gateway' );
add_filter( 'edd_is_gateway_active', 'edds_prb_is_gateway_active', 10, 2 );
}
add_action( 'edd_purchase_form_before_submit', 'edds_prb_shim_active_gateways' );
/**
* Removes conversion of `stripe-prb` to `stripe` after the `input[name="edd-gateway"]`
* hidden input is generated.
*
* @since 2.8.0
*/
function edds_prb_unshim_active_gateways() {
remove_filter( 'edd_chosen_gateway', 'edds_prb_set_base_gateway' );
remove_filter( 'edd_is_gateway_active', 'edds_prb_is_gateway_active', 10, 2 );
}
add_action( 'edd_purchase_form_after_submit', 'edds_prb_unshim_active_gateways' );
/**
* Ensures the "Express Checkout" gateway is considered active if the setting
* is enabled.
*
* @since 2.8.0
*
* @param bool $active Determines if the gateway is considered active.
* @param string $gateway The gateway ID to check.
* @return bool
*/
function edds_prb_is_gateway_active( $active, $gateway ) {
remove_filter( 'edd_is_gateway_active', 'edds_prb_is_gateway_active', 10, 2 );
if (
'stripe-prb' === $gateway &&
true === edds_prb_is_enabled( 'checkout' )
) {
$active = true;
}
add_filter( 'edd_is_gateway_active', 'edds_prb_is_gateway_active', 10, 2 );
return $active;
}
/**
* Transforms the found active `stripe-prb` Express Checkout gateway back
* to the base `stripe` gateway ID.
*
* @param string $gateway Chosen payment gateway.
* @return string
*/
function edds_prb_set_base_gateway( $gateway ) {
if ( 'stripe-prb' === $gateway ) {
$gateway = 'stripe';
}
return $gateway;
}
/**
* Filters the default gateway.
*
* Sets the Payment Request Button (Express Checkout) as default
* when enabled for the context.
*
* @since 2.8.0
*
* @param string $default Default gateway.
* @return string
*/
function edds_prb_default_gateway( $default ) {
// Do nothing in admin.
if ( is_admin() ) {
return $default;
}
// Avoid endless loops when checking if the Stripe gateway is active.
remove_filter( 'edd_default_gateway', 'edds_prb_default_gateway' );
$enabled = true;
// Do nothing if Payment Requests are not enabled.
if ( false === edds_prb_is_enabled( 'checkout' ) ) {
$enabled = false;
}
// Avoid endless loops when checking if the Stripe gateway is active.
add_filter( 'edd_default_gateway', 'edds_prb_default_gateway' );
if ( false === $enabled ) {
return $default;
}
return 'stripe' === $default
? 'stripe-prb'
: $default;
}
add_filter( 'edd_default_gateway', 'edds_prb_default_gateway' );
/**
* Adds Payment Request-specific overrides when processing a single Download.
*
* Disables all required fields.
*
* @since 2.8.0
*/
function edds_prb_process_overrides() {
if ( ! isset( $_POST ) ) {
return;
}
if ( ! isset( $_POST['edds-gateway'] ) ) {
return;
}
if ( 'payment-request' !== $_POST['edds-gateway'] ) {
return;
}
if ( 'download' !== $_POST['edds-prb-context'] ) {
return;
}
// Ensure Billing Address and Name Fields are not required.
add_filter( 'edd_require_billing_address', '__return_false' );
// Require email address.
add_filter( 'edd_purchase_form_required_fields', 'edds_prb_purchase_form_required_fields', 9999 );
// Remove 3rd party validations.
remove_all_actions( 'edd_checkout_error_checks' );
remove_all_actions( 'edd_checkout_user_error_checks' );
}
add_action( 'edd_pre_process_purchase', 'edds_prb_process_overrides' );
/**
* Filters the purchase form's required field to only
* require an email address.
*
* @since 2.8.0
*
* @return array
*/
function edds_prb_purchase_form_required_fields() {
return array(
'edd_email' => array(
'error_id' => 'invalid_email',
'error_message' => __( 'Please enter a valid email address', 'easy-digital-downloads' )
),
);
}
/**
* Adds a note and metadata to Payments made with a Payment Request Button.
*
* @since 2.8.0
*
* @param \EDD_Payment $payment EDD Payment.
* @param \Stripe\PaymentIntent|\Stripe\SetupIntent $intent Created Stripe Intent.
*/
function edds_prb_payment_created( $payment, $intent ) {
if ( false === isset( $intent['metadata']['edds_prb'] ) ) {
return;
}
$payment->update_meta( '_edds_stripe_prb', 1 );
$payment->add_note( 'Purchase completed with Express Checkout (Apple Pay/Google Pay)' );
}
add_action( 'edds_payment_created', 'edds_prb_payment_created', 10, 2 );
/**
* Creates an empty Credit Card form to ensure core actions are still called.
*
* @since 2.8.0
*/
function edds_prb_cc_form() {
/* This action is documented in easy-digital-downloads/includes/checkout/template.php */
do_action( 'edd_before_cc_fields' );
/* This action is documented in easy-digital-downloads/includes/checkout/template.php */
do_action( 'edd_after_cc_fields' );
}
/**
* Loads the Payment Request gateway.
*
* This fires before core's callbacks to avoid firing additional
* actions (and therefore creating extra output) when using the Payment Request.
*
* @since 2.8.0
*/
function edds_prb_load_gateway() {
if ( ! isset( $_POST['nonce'] ) ) {
edd_debug_log(
__( 'Missing nonce when loading the gateway fields. Please read the following for more information: https://easydigitaldownloads.com/development/2018/07/05/important-update-to-ajax-requests-in-easy-digital-downloads-2-9-4', 'easy-digital-downloads' ),
true
);
}
if ( isset( $_POST['edd_payment_mode'] ) && isset( $_POST['nonce'] ) ) {
$payment_mode = sanitize_text_field( $_POST['edd_payment_mode'] );
$nonce = sanitize_text_field( $_POST['nonce'] );
$nonce_verified = wp_verify_nonce( $nonce, 'edd-gateway-selected-' . $payment_mode );
if ( false !== $nonce_verified ) {
// Load the "Express" gateway.
if ( 'stripe-prb' === $payment_mode ) {
// Remove credit card fields.
remove_action( 'edd_stripe_cc_form', 'edds_credit_card_form' );
remove_action( 'edd_cc_form', 'edd_get_cc_form' );
// Hide "Billing Details" which are populated by the Payment Method.
add_filter( 'edd_require_billing_address', '__return_true' );
remove_filter( 'edd_purchase_form_required_fields', 'edd_stripe_require_zip_and_country' );
remove_action( 'edd_after_cc_fields', 'edd_stripe_zip_and_country', 9 );
remove_action( 'edd_after_cc_fields', 'edd_default_cc_address_fields', 10 );
// Remove "Update billing address" checkbox. All Payment Requests create
// a new source.
remove_action( 'edd_cc_billing_top', 'edd_stripe_update_billing_address_field', 10 );
// Output a Payment Request-specific credit card form (empty).
add_action( 'edd_stripe_cc_form', 'edds_prb_cc_form' );
// Swap purchase button with Payment Request button.
add_filter( 'edd_checkout_button_purchase', 'edds_prb_checkout_button_purchase', 10000 );
/**
* Allows further adjustments to made before the "Express Checkout"
* gateway is loaded.
*
* @since 2.8.0
*/
do_action( 'edds_prb_before_purchase_form' );
}
/* This action is documented in easy-digital-downloads/includes/checkout/template.php */
do_action( 'edd_purchase_form' );
// Ensure core callbacks are fired.
add_action( 'wp_ajax_edd_load_gateway', 'edd_load_ajax_gateway' );
add_action( 'wp_ajax_nopriv_edd_load_gateway', 'edd_load_ajax_gateway' );
}
exit();
}
}
add_action( 'wp_ajax_edd_load_gateway', 'edds_prb_load_gateway', 5 );
add_action( 'wp_ajax_nopriv_edd_load_gateway', 'edds_prb_load_gateway', 5 );

View File

@ -0,0 +1,225 @@
<?php
/**
* Payment Request: Functions
*
* @package EDD_Stripe
* @since 2.8.0
*/
/**
* Determines if Payment Requests are enabled.
*
* @since 2.8.0
*
* @param array|string $context Context the Payment Request Button is being output in.
* Default empty, checks if any are enabled.
* @return bool
*/
function edds_prb_is_enabled( $context = array() ) {
// Stripe gateway is not active. Disabled.
if ( false === edd_is_gateway_active( 'stripe' ) ) {
return false;
}
// Gather allowed and enabled contexts.
$allowed_contexts = array( 'single', 'archive', 'checkout' );
$enabled_contexts = array_keys(
(array) edd_get_option( 'stripe_prb', array() )
);
if ( ! is_array( $context ) ) {
$context = array( $context );
}
// Nothing particular is being checked for; check if any values are checked.
if ( empty( $context ) ) {
return count( $enabled_contexts ) > 0;
}
// Passed context is not allowed. Disabled.
if ( 0 === count( array_intersect( $context, $allowed_contexts ) ) ) {
return false;
}
// Passed context is not enabled in setting. Disabled.
if ( 0 === count( array_intersect( $context, $enabled_contexts ) ) ) {
return false;
}
// Taxes are enabled. Disabled.
$taxes = edd_use_taxes();
if ( true === $taxes ) {
return false;
}
// Recurring is enabled and a trial is in the cart. Disabled.
//
// Disabling for cart context here to avoid further adjusting the already
// complex filtering of active gateways in checkout.php
if (
function_exists( 'edd_recurring' ) &&
edd_recurring()->cart_has_free_trial()
) {
return false;
}
return true;
}
/**
* Retrieves data for a Payment Request Button for a single Download.
*
* @since 2.8.0
*
* @param int $download_id Download ID.
* @param false|int $price_id Price ID. Default will be used if not set. Default false.
* @param int $quantity Quantity. Default 1.
* @return array Payment Request Button data.
*/
function edds_prb_get_download_data( $download_id, $price_id = false, $quantity = 1 ) {
$data = array(
'currency' => strtolower( edd_get_currency() ),
'country' => strtoupper( edd_get_shop_country() ),
'total' => array(),
'display-items' => array(),
);
$download = edd_get_download( $download_id );
// Return early if no Download can be found.
if ( ! $download ) {
return array();
}
// Hacky way to ensure we don't display quantity for Recurring
// downloads. The quantity field is output incorrectly.
//
// https://github.com/easydigitaldownloads/edd-recurring/issues/880
if ( defined( 'EDD_RECURRING_VERSION' ) ) {
$recurring = false;
if ( false !== $price_id ) {
$recurring = edd_recurring()->is_price_recurring( $download_id, $price_id );
} else {
$recurring = edd_recurring()->is_recurring( $download_id );
}
if ( true === $recurring ) {
$quantity = 1;
}
}
// Find price.
$variable_pricing = $download->has_variable_prices();
$price = 0;
if ( $variable_pricing ) {
if ( false === $price_id ) {
$price_id = edd_get_default_variable_price( $download_id );
}
$prices = $download->prices;
$price = isset( $prices[ $price_id ] )
? $prices[ $price_id ]['amount']
: false;
$name = sprintf(
'%1$s - %2$s',
$download->get_name(),
edd_get_price_option_name( $download->ID, $price_id )
);
} else {
$price = $download->price;
$name = $download->get_name();
}
if ( false === edds_is_zero_decimal_currency() ) {
$price = round( $price * 100 );
}
$price = ( $price * $quantity );
// Add total.
$data['total'] = array(
'label' => __( 'Total', 'easy-digital-downloads' ),
'amount' => $price,
);
// Add Display items.
$has_quantity = edd_item_quantities_enabled() && ! edd_download_quantities_disabled( $download_id );
$quantity = true === $has_quantity
? $quantity
: 1;
$data['display-items'][] = array(
'label' => sprintf(
'%s%s',
strip_tags( $name ),
( $quantity > 1 ? sprintf( __( ' × %d', 'easy-digital-downloads' ), $quantity ) : '' )
),
'amount' => $price,
);
return $data;
}
/**
* Retrieves data for a Payment Request Button for the cart.
*
* @since 2.8.0
*
* @return array Payment Request Button data.
*/
function edds_prb_get_cart_data() {
$data = array(
'currency' => strtolower( edd_get_currency() ),
'country' => strtoupper( edd_get_shop_country() ),
'total' => array(),
'display-items' => array(),
);
$total = edd_get_cart_total();
if ( false === edds_is_zero_decimal_currency() ) {
$total = round( $total * 100 );
}
// Add total.
$data['total'] = array(
'label' => __( 'Total', 'easy-digital-downloads' ),
'amount' => $total,
);
// Add Display items.
$cart_items = edd_get_cart_contents();
foreach ( $cart_items as $key => $item ) {
$has_quantity = edd_item_quantities_enabled() && ! edd_download_quantities_disabled( $item['id'] );
$quantity = true === $has_quantity
? edd_get_cart_item_quantity( $item['id'], $item['options'] )
: 1;
$price = edd_get_cart_item_price( $item['id'], $item['options'] );
if ( false === edds_is_zero_decimal_currency() ) {
$price = round( $price * 100 );
}
$price = ( $price * $quantity );
$data['display-items'][] = array(
'label' => sprintf(
'%s%s',
strip_tags( edd_get_cart_item_name( $item ) ),
( $quantity > 1 ? sprintf( __( ' × %d', 'easy-digital-downloads' ), $quantity ) : '' )
),
'amount' => $price,
);
}
return $data;
}

View File

@ -0,0 +1,18 @@
<?php
/**
* Payment Request Button
*
* @package EDD_Stripe
* @since 2.8.0
*/
require_once EDDS_PLUGIN_DIR . '/includes/payment-methods/payment-request/ajax.php';
require_once EDDS_PLUGIN_DIR . '/includes/payment-methods/payment-request/checkout.php';
require_once EDDS_PLUGIN_DIR . '/includes/payment-methods/payment-request/functions.php';
require_once EDDS_PLUGIN_DIR . '/includes/payment-methods/payment-request/template.php';
require_once EDDS_PLUGIN_DIR . '/includes/payment-methods/payment-request/shortcode.php';
require_once EDDS_PLUGIN_DIR . '/includes/payment-methods/payment-request/apple-pay.php';
if ( is_admin() ) {
require_once EDDS_PLUGIN_DIR . '/includes/payment-methods/payment-request/admin/settings.php';
}

View File

@ -0,0 +1,31 @@
<?php
/**
* Payment Request Button: Shortcode
*
* @package EDD_Stripe
* @since 2.8.0
*/
/**
* Allows `payment-request` to be passed to [purchase-link]
* to disable the Payment Request button.
*
* @since 2.8.0
*
* @param array $out Sanitized shortcode attributes.
* @param array $pairs Entire list of supported attributes and their defaults.
* @param array $atts User defined attributes in shortcode tag.
* @return array Combined and filtered attribute list.
*/
function edds_prb_shortcode_atts( $out, $pairs, $atts ) {
if ( false === edd_is_gateway_active( 'stripe' ) ) {
return $out;
}
if ( isset( $atts['payment-request'] ) ) {
$out['payment-request'] = $atts['payment-request'];
}
return $out;
}
add_filter( 'shortcode_atts_purchase_link', 'edds_prb_shortcode_atts', 10, 3 );

View File

@ -0,0 +1,202 @@
<?php
/**
* Payment Request Button: Template
*
* @package EDD_Stripe
* @since 2.8.0
*/
/**
* Outputs a Payment Request Button via `edd_get_purchase_link()`
* (which is implemented via [purchase_link])
*
* @since 2.8.0
*
* @param int $download_id Current Download ID.
* @param array $args Arguments for displaying the purchase link.
*/
function edds_prb_purchase_link( $download_id, $args ) {
// Don't output if context is not enabled.
$context = is_singular() && 0 === did_action( 'edd_downloads_list_before' )
? 'single'
: 'archive';
if ( false === edds_prb_is_enabled( $context ) ) {
return;
}
// Don't output if the item is free. Stripe won't process < $0.50
if ( true === edd_is_free_download( $download_id ) ) {
return;
}
// Don't output if the item is already in the cart.
if ( true === edd_item_in_cart( $download_id ) ) {
return;
}
// Don't output if `edd_get_purchase_link` is filtered to disable.
if (
isset( $args['payment-request'] ) &&
true !== edds_truthy_to_bool( $args['payment-request'] )
) {
return;
}
// Don't output if Recurring is enabled, and a free trial is present.
// @link https://github.com/easydigitaldownloads/edd-stripe/issues/594
if ( function_exists( 'edd_recurring' ) ) {
// Don't output if non-variable price has a free trial.
if ( edd_recurring()->has_free_trial( $download_id ) ) {
return;
}
// ...or if a variable price options has a free trial.
$prices = edd_get_variable_prices( $download_id );
if ( ! empty( $prices ) ) {
foreach ( $prices as $price ) {
if ( edd_recurring()->has_free_trial( $download_id, $price['index'] ) ) {
return;
}
}
}
}
// Don't output if it has been filtered off for any reason.
$enabled = true;
/**
* Filters the output of Payment Request Button in purchase links.
*
* @since 2.8.0
*
* @param bool $enabled If the Payment Request Button is enabled.
* @param int $download_id Current Download ID.
* @param array $args Purchase link arguments.
*/
$enabled = apply_filters( 'edds_prb_purchase_link_enabled', $enabled, $download_id, $args );
if ( true !== $enabled ) {
return;
}
static $instance_id = 0;
echo edds_get_prb_markup(
edds_prb_get_download_data( $download_id ),
array(
'id' => sprintf(
'edds-prb-download-%d-%d',
$download_id,
$instance_id
),
'classes' => array(
'edds-prb--download',
),
)
); // WPCS: XSS okay.
// Shim the Checkout processing nonce.
wp_nonce_field( 'edd-process-checkout', 'edd-process-checkout-nonce', false );
echo edds_get_tokenizer_input( $download_id );
$instance_id++;
}
add_action( 'edd_purchase_link_top', 'edds_prb_purchase_link', 20, 2 );
/**
* Outputs a Payment Request Button on the Checkout.
*
* @since 2.8.0
*/
function edds_prb_checkout_button_purchase( $button ) {
// Do nothing if Payment Requests are not enabled.
if ( false === edds_prb_is_enabled( 'checkout' ) ) {
return $button;
}
$tokenizer = edds_get_tokenizer_input();
$errors = '<div id="edds-prb-error-wrap"></div>';
$button = edds_get_prb_markup(
edds_prb_get_cart_data(),
array(
'id' => 'edds-prb-checkout',
'classes' => array(
'edds-prb--checkout',
),
)
);
return $tokenizer . $errors . $button;
}
/**
* Retrieves HTML used to mount a Payment Request Button.
*
* @since 2.8.0
* @see edds_prb_get_download_data()
* @link https://stripe.com/docs/js/appendix/payment_item_object
*
* @param PaymentItem[] $data {
* PaymentItems.
*
* @type int $amount The amount in the currency's subunit.
* @type string $label A name the browser shows the customer in the payment interface.
* }
* @param array $args {
* Mount arguments.
*
* @type string $id HTML ID attribute.
* @type array $classes HTML classes.
* }
* @return string
*/
function edds_get_prb_markup( $data, $args = array() ) {
$defaults = array(
'id' => '',
'classes' => array(),
);
$args = wp_parse_args( $args, $defaults );
// ID/Class
$id = $args['id'];
$class = implode(
' ',
array_merge(
$args['classes'],
array(
'edds-prb',
)
)
);
// Data
$_data = array();
foreach ( $data as $key => $value ) {
$_data[] = sprintf(
'data-%s="%s"',
esc_attr( $key ),
esc_attr( is_array( $value ) ? wp_json_encode( $value ) : $value )
);
}
$_data = implode( ' ', $_data );
edd_stripe_js( true );
edd_stripe_css( true );
return sprintf(
'<div id="%1$s" class="%2$s" %3$s>
<div class="edds-prb__button"></div>
<div class="edds-prb__or">%4$s</div>
</div>',
esc_attr( $id ),
esc_attr( $class ),
$_data,
esc_html_x( 'or', 'payment request button divider', 'easy-digital-downloads' )
);
}