installed plugin Easy Digital Downloads
version 3.1.0.3
This commit is contained in:
wp-content/plugins/easy-digital-downloads
assets
css
admin
chosen
datepicker.scssdownloads
email-tags.scssextension-manager.scssforms
gateways
general
menu.scssnotifications
orders
promos
reports
style.scsstax-rates
upgrades
variables
vendor
images
edd-cpt-2x.pngedd-cpt.pngedd-cross-hair.pngedd-icon-2x.pngedd-icon.pngedd-logo-pdf.pngedd-logo-white-2x.pngedd-logo.pngedd-logo.svgedd-media.pngedd-peeking.png
icons
icon-arrow-down.pngicon-arrow-up.pngicon-average.pngicon-chevron-down.svgicon-gross.pngicon-megaphone.pngicon-net.pngicon-new-customers.pngicon-top-products.pngiphone.png
loading.giflogo-edd-dark.svgmedia-button.pngpromo
screenshots
17checkout.png17direct.png17quantities.png18-button-colors.png18cart-saving.png20-discount.png20-register-login.png20-sequential.png20-unlimited-downloads.png22-logs.png22-purchased-downloads.png22-purchased-downloads2.png22-quantity.png24-category-earnings.png24-checkout.png24-export.png26-customer.png26-import.png26-refund.pngbundles.pngcustomer-ui.pngedit-download.pngemail-template-21.pnggrid.pngorder-details.pngproduct-earnings.pngproduct-tax.pngpurchase-link.pngtax-rates.png
ui-icons_21759b_256x240.pngui-icons_333333_256x240.pngui-icons_999999_256x240.pngui-icons_cc0000_256x240.pngxit.gifjs
admin
components
advanced-filters
chosen
date-picker
location
notifications
promos
sortable-list
taxonomies
tooltips
user-search
vertical-sections
customers
dashboard
discounts
downloads
index.jsnotes
notices
orders
index.jslist-table.js
order-details
order-overview
_refund.js
collections
index.jsmodels
views
actions.jsbase.jscopy-download-link.jsdialog.jsform-add-order-adjustment.jsform-add-order-discount.jsform-add-order-item.jsno-order-items.jsorder-adjustment.jsorder-adjustments.jsorder-credits.jsorder-discounts-fees.jsorder-item.jsorder-items.jsorder-refund.jsorder-refunds.jsorder-subtotal.jsorder-tax.jsorder-total.jsoverview.jssummary.js
payments
reports
settings
tools
upgrades
frontend
jquery.validate.min.jspackages
paypal-checkout.jsutils
vendor
chartjs.min.jschosen.jquery.min.jsjquery.creditcardvalidator.min.jsjquery.flot.min.jsjquery.flot.pie.min.jsjquery.flot.time.min.jsjquery.payment.min.jsmoment-timezone.min.jsmoment.min.js
wp-polyfill.min.jsincludes
EDD_SL_Plugin_Updater.phpactions.phpedd-blocks.phpmime-types.phpmisc-functions.php
adjustments
admin
add-ons.php
ajax-functions.phpadjustments
admin-actions.phpadmin-bar.phpadmin-deprecated-functions.phpadmin-footer.phpadmin-pages.phpclass-api-keys-table.phpclass-edd-heartbeat.phpclass-edd-notices.phpclass-list-table.phpclass-pass-manager.phpclass-sections.phpcustomers
class-customer-addresses-table.phpclass-customer-email-addresses-table.phpclass-customer-table.phpcustomer-actions.phpcustomer-functions.phpcustomers.php
dashboard-widgets.phpdiscounts
add-discount.phpclass-discount-codes-table.phpcontextual-help.phpdiscount-actions.phpdiscount-codes.phpedit-discount.php
downloads
emails
email-summary
extensions
abstract-extension.phpclass-extension-manager.phpclass-extension-product-data.phpclass-extensions-api.php
product-education
import
class-batch-import-downloads.phpclass-batch-import-payments.phpclass-batch-import.phpimport-actions.phpimport-functions.php
installers
notes
payments
actions.phpadd-order.phpclass-order-sections.phpclass-payments-table.phpclass-refund-items-table.phpcontextual-help.phporders.phppayments-history.phprefunds.phpview-order-details.phpview-refund.php
plugins.phppromos
reporting
class-api-requests-logs-list-table.phpclass-base-logs-list-table.phpclass-categories-reports-table.phpclass-download-reports-table.phpclass-edd-graph.phpclass-edd-pie-graph.phpclass-export-customers.phpclass-export-download-history.phpclass-export-payments.phpclass-export.phpclass-file-downloads-logs-list-table.phpclass-gateway-error-logs-list-table.phpclass-gateways-reports-table.phpclass-reports-sections.phpclass-sales-logs-list-table.phpcontextual-help.php
export
class-batch-export-api-requests.phpclass-batch-export-customers.phpclass-batch-export-downloads.phpclass-batch-export-earnings-report.phpclass-batch-export-file-downloads.phpclass-batch-export-payments.phpclass-batch-export-sales-and-earnings.phpclass-batch-export-sales.phpclass-batch-export-taxed-customers.phpclass-batch-export-taxed-orders.phpclass-batch-export.phpexport-actions.phpexport-functions.php
graphing.phplogs.phpreports-callbacks.phpreports.phpsettings
thickbox.phptools.phptools
class-edd-tools-recount-all-stats.phpclass-edd-tools-recount-customer-stats.phpclass-edd-tools-recount-download-stats.phpclass-edd-tools-recount-single-customer-stats.phpclass-edd-tools-recount-store-earnings.phpclass-edd-tools-reset-stats.phplogs.phptools-actions.php
tracking.phpupgrades
upload-functions.phpviews
notifications.phptmpl-order-actions.phptmpl-order-adjustment-discount.phptmpl-order-adjustment.phptmpl-order-copy-download-link.phptmpl-order-form-add-order-adjustment.phptmpl-order-form-add-order-discount.phptmpl-order-form-add-order-item.phptmpl-order-item.phptmpl-order-no-items.phptmpl-order-refund.phptmpl-order-subtotal.phptmpl-order-tax.phptmpl-order-total.phptmpl-tax-rates-table-add.phptmpl-tax-rates-table-bulk-actions.phptmpl-tax-rates-table-meta.phptmpl-tax-rates-table-row-empty.phptmpl-tax-rates-table-row.php
api
blocks
assets
build
buy-button
cart
checkout
confirmation
downloads
login
order-history
receipt
register
terms
includes
readme.mdviews
checkout
cart
cart-discounts.phpcart-fees.phpcart-footer-row.phpcart-item.phpcart-subtotal.phpcart-taxes.phpcart-total.phpcart.phpmini.php
discount.phplogged-in.phppurchase-form
downloads
forms
orders
credits.phpdiscounts.phpfees.phpguest.phporders.phppagination.phpreceipt-files.phpreceipt-item.phpreceipt-items.phptotals.php
terms.phpcart
checkout
class-base-object.phpclass-component.phpclass-easy-digital-downloads.phpclass-edd-cache-helper.phpclass-edd-cli.phpclass-edd-cron.phpclass-edd-customer-query.phpclass-edd-customer.phpclass-edd-db-customer-meta.phpclass-edd-db-customers.phpclass-edd-db.phpclass-edd-discount.phpclass-edd-download.phpclass-edd-fees.phpclass-edd-html-elements.phpclass-edd-license-handler.phpclass-edd-logging.phpclass-edd-register-meta.phpclass-edd-roles.phpclass-edd-session.phpclass-edd-stats.phpclass-stats.phpclass-structured-data.phpclass-utilities.phpcompat-functions.phpcompat
class-base.phpclass-customer.phpclass-customermeta.phpclass-discount-query.phpclass-discount.phpclass-edd-payment-compat.phpclass-log.phpclass-payment.phpclass-tax.phpclass-template.php
component-functions.phpcountry-functions.phpcurrency
customer-functions.phpcustomers
database
NotificationsDB.phpREADME.md
date-functions.phpdeprecated-functions.phpdeprecated-hooks.phpdiscount-functions.phpdownload-functions.phpengine
class-base.phpclass-column.phpclass-compare.phpclass-date.phpclass-meta.phpclass-query.phpclass-row.phpclass-schema.phpclass-table.php
queries
class-adjustment.phpclass-customer-address.phpclass-customer-email-address.phpclass-customer.phpclass-log-api-request.phpclass-log-file-download.phpclass-log.phpclass-note.phpclass-order-address.phpclass-order-adjustment.phpclass-order-item.phpclass-order-transaction.phpclass-order.php
rows
class-adjustment.phpclass-customer-address.phpclass-customer-email-address.phpclass-customer.phpclass-log-api-request.phpclass-log-file-download.phpclass-log.phpclass-note.phpclass-order-address.phpclass-order-adjustment.phpclass-order-item.phpclass-order-transaction.phpclass-order.php
schemas
class-adjustments.phpclass-customer-addresses.phpclass-customer-email-addresses.phpclass-customers.phpclass-logs-api-requests.phpclass-logs-file-downloads.phpclass-logs.phpclass-notes.phpclass-order-addresses.phpclass-order-adjustments.phpclass-order-items.phpclass-order-transactions.phpclass-orders.php
tables
class-adjustment-meta.phpclass-adjustments.phpclass-customer-addresses.phpclass-customer-email-addresses.phpclass-customer-meta.phpclass-customers.phpclass-log-meta.phpclass-logs-api-request-meta.phpclass-logs-api-requests.phpclass-logs-file-download-meta.phpclass-logs-file-downloads.phpclass-logs.phpclass-note-meta.phpclass-notes.phpclass-order-addresses.phpclass-order-adjustment-meta.phpclass-order-adjustments.phpclass-order-item-meta.phpclass-order-items.phpclass-order-meta.phpclass-order-transactions.phpclass-orders.php
downloads
emails
actions.phpclass-edd-email-tags.phpclass-edd-emails.php
error-tracking.phpemail-summary
class-edd-email-summary-blurb.phpclass-edd-email-summary-cron.phpclass-edd-email-summary.phpedd-email-summary-template.php
functions.phptags-inserter.phptags.phptemplate.phpextensions
formatting.phpgateways
actions.phpamazon-payments.phpfunctions.php
install.phpinterface-edd-exception.phplibs
manual.phppaypal-standard.phppaypal
admin
buy-now.phpcheckout-actions.phpclass-account-status-validator.phpclass-merchant-account.phpclass-paypal-api.phpclass-token.phpdeprecated.phpexceptions
class-api-exception.phpclass-authentication-exception.phpclass-gateway-exception.phpclass-invalid-merchant-details.phpclass-missing-merchant-details.php
functions.phpgateway-filters.phpintegrations.phpipn.phppaypal.phprefunds.phpscripts.phpwebhooks
stripe
apple-developer-merchantid-domain-associationedd-stripe.phppayment-receipt.phpscripts.phptemplate-functions.php
assets
css
build
src
js
includes
admin
admin-actions.phpadmin-filters.phpclass-notices-registry.phpclass-notices.phpnotices.php
card-actions.phpclass-edd-stripe-rate-limiting.phpclass-edd-stripe.phpclass-stripe-api.phpcompat.phpdeprecated.phpelements.phpemails.phpfunctions.phpgateway-actions.phpgateway-filters.phpi18n.phpnotices
reporting
settings.phpsettings
upgrade-functions.phpintegrations
payment-actions.phppayment-methods
buy-now
payment-request
utils
class-registry.php
webhooks.phpexceptions
class-attribute-not-found.phpclass-gateway-exception.phpclass-stripe-api-unmet-requirements.phpclass-stripe-object-not-found.php
interface-static-registry.phpmodal.phpvendor
autoload.php
composer
ClassLoader.phpInstalledVersions.phpLICENSEautoload_classmap.phpautoload_namespaces.phpautoload_psr4.phpautoload_real.phpautoload_static.phpinstalled.jsoninstalled.php
stripe
stripe-php
CHANGELOG.mdCODE_OF_CONDUCT.mdLICENSEMakefileREADME.mdVERSIONbuild.phpcomposer.json
data
init.phplib
Account.phpAccountLink.phpAlipayAccount.php
phpdoc.dist.xmlphpstan-baseline.neonphpstan.neon.distupdate_certs.phpApiOperations
ApiRequestor.phpApiResource.phpApiResponse.phpApplePayDomain.phpApplicationFee.phpApplicationFeeRefund.phpBalance.phpBalanceTransaction.phpBankAccount.phpBaseStripeClient.phpBillingPortal
BitcoinReceiver.phpBitcoinTransaction.phpCapability.phpCard.phpCharge.phpCheckout
Collection.phpCountrySpec.phpCoupon.phpCreditNote.phpCreditNoteLineItem.phpCustomer.phpCustomerBalanceTransaction.phpDiscount.phpDispute.phpEphemeralKey.phpErrorObject.phpEvent.phpException
ApiConnectionException.phpApiErrorException.phpAuthenticationException.phpBadMethodCallException.phpCardException.phpExceptionInterface.phpIdempotencyException.phpInvalidArgumentException.phpInvalidRequestException.php
ExchangeRate.phpFile.phpFileLink.phpOAuth
ExceptionInterface.phpInvalidClientException.phpInvalidGrantException.phpInvalidRequestException.phpInvalidScopeException.phpOAuthErrorException.phpUnknownOAuthErrorException.phpUnsupportedGrantTypeException.phpUnsupportedResponseTypeException.php
PermissionException.phpRateLimitException.phpSignatureVerificationException.phpUnexpectedValueException.phpUnknownApiErrorException.phpHttpClient
Invoice.phpInvoiceItem.phpInvoiceLineItem.phpIssuing
LineItem.phpLoginLink.phpMandate.phpOAuth.phpOAuthErrorObject.phpOrder.phpOrderItem.phpOrderReturn.phpPaymentIntent.phpPaymentMethod.phpPayout.phpPerson.phpPlan.phpPrice.phpProduct.phpPromotionCode.phpRadar
Recipient.phpRecipientTransfer.phpRefund.phpReporting
RequestTelemetry.phpReview.phpSKU.phpService
AbstractService.phpAbstractServiceFactory.phpAccountLinkService.phpAccountService.phpApplePayDomainService.phpApplicationFeeService.phpBalanceService.phpBalanceTransactionService.php
SetupIntent.phpBillingPortal
ChargeService.phpCheckout
CoreServiceFactory.phpCountrySpecService.phpCouponService.phpCreditNoteService.phpCustomerService.phpDisputeService.phpEphemeralKeyService.phpEventService.phpExchangeRateService.phpFileLinkService.phpFileService.phpInvoiceItemService.phpInvoiceService.phpIssuing
AuthorizationService.phpCardService.phpCardholderService.phpDisputeService.phpIssuingServiceFactory.phpTransactionService.php
MandateService.phpOAuthService.phpOrderReturnService.phpOrderService.phpPaymentIntentService.phpPaymentMethodService.phpPayoutService.phpPlanService.phpPriceService.phpProductService.phpPromotionCodeService.phpRadar
RefundService.phpReporting
ReviewService.phpSetupIntentService.phpSigma
SkuService.phpSourceService.phpSubscriptionItemService.phpSubscriptionScheduleService.phpSubscriptionService.phpTaxRateService.phpTerminal
TokenService.phpTopupService.phpTransferService.phpWebhookEndpointService.phpSigma
SingletonApiResource.phpSource.phpSourceTransaction.phpStripe.phpStripeClient.phpStripeClientInterface.phpStripeObject.phpSubscription.phpSubscriptionItem.phpSubscriptionSchedule.phpTaxId.phpTaxRate.phpTerminal
ThreeDSecure.phpToken.phpTopup.phpTransfer.phpTransferReversal.phpUsageRecord.phpUsageRecordSummary.phpUtil
CaseInsensitiveArray.phpDefaultLogger.phpLoggerInterface.phpObjectTypes.phpRandomGenerator.phpRequestOptions.phpSet.phpUtil.php
Webhook.phpWebhookEndpoint.phpWebhookSignature.phplibraries
Carbon.phparray2xml.phpbrowser.phpclass-ArrayToXML.phpclass-persistent-dismissible.phpclass-recursive-arrayaccess.phpclass-wp-session.phpwp-session.php
logs
api-request-log
file-download-log
log
models
notes
orders
classes
class-order-address.phpclass-order-adjustment.phpclass-order-item.phpclass-order-transaction.phpclass-order.phpclass-refund-validator.php
functions
payments
plugin-compatibility.phppost-types.phpprivacy-functions.phpprocess-download.phpprocess-purchase.phpquery-filters.phprefund-functions.phpreports
class-init.phpclass-registry.phpclass-base-object.phpclass-chart-endpoint.phpclass-endpoint-registry.phpclass-endpoint-view-registry.phpclass-endpoint.phpclass-report-registry.phpclass-report.phpclass-table-endpoint.phpclass-tile-endpoint.php
scripts.phpshortcodes.phptax-functions.phptemplate-actions.phptemplate-functions.phptheme-compatibility.phpdata
charts
v2
customers
discounts
downloads
file-downloads
payment-gateways
taxes
exceptions
reports-functions.phptraits
user-functions.phpusers
utils
EnvironmentChecker.phpNotificationImporter.phpclass-date.phpclass-edd-exception.phpclass-registry.phpclass-tokenizer.php
widgets.phpexceptions
interface-error-logger.phpinterface-static-registry.phplanguages
license.txtreadme.txttemplates
account-pending.phpcheckout_cart.phpedd.css
uninstall.phpemails
fonts
history-downloads.phphistory-purchases.phpimages
payment-processing.phpshortcode-content-cart-button.phpshortcode-content-excerpt.phpshortcode-content-full.phpshortcode-content-image.phpshortcode-content-price.phpshortcode-content-title.phpshortcode-download.phpshortcode-login.phpshortcode-profile-editor.phpshortcode-receipt.phpshortcode-register.phpwidget-cart-checkout.phpwidget-cart-empty.phpwidget-cart-item.phpwidget-cart.php
462
wp-content/plugins/easy-digital-downloads/includes/gateways/paypal/checkout-actions.php
Normal file
462
wp-content/plugins/easy-digital-downloads/includes/gateways/paypal/checkout-actions.php
Normal file
@ -0,0 +1,462 @@
|
||||
<?php
|
||||
/**
|
||||
* PayPal Commerce Checkout Actions
|
||||
*
|
||||
* @package easy-digital-downloads
|
||||
* @subpackage Gateways\PayPal
|
||||
* @copyright Copyright (c) 2021, Sandhills Development, LLC
|
||||
* @license GPL2+
|
||||
* @since 2.11
|
||||
*/
|
||||
|
||||
namespace EDD\Gateways\PayPal;
|
||||
|
||||
use EDD\Gateways\PayPal\Exceptions\API_Exception;
|
||||
use EDD\Gateways\PayPal\Exceptions\Authentication_Exception;
|
||||
use EDD\Gateways\PayPal\Exceptions\Gateway_Exception;
|
||||
|
||||
/**
|
||||
* Removes the credit card form for PayPal Commerce
|
||||
*
|
||||
* @access private
|
||||
* @since 2.11
|
||||
*/
|
||||
add_action( 'edd_paypal_commerce_cc_form', '__return_false' );
|
||||
|
||||
/**
|
||||
* Replaces the "Submit" button with a PayPal smart button.
|
||||
*
|
||||
* @param string $button
|
||||
*
|
||||
* @since 2.11
|
||||
* @return string
|
||||
*/
|
||||
function override_purchase_button( $button ) {
|
||||
if ( 'paypal_commerce' === edd_get_chosen_gateway() && edd_get_cart_total() ) {
|
||||
ob_start();
|
||||
if ( ready_to_accept_payments() ) {
|
||||
wp_nonce_field( 'edd_process_paypal', 'edd_process_paypal_nonce' );
|
||||
$timestamp = time();
|
||||
?>
|
||||
<input type="hidden" name="edd-process-paypal-token" data-timestamp="<?php echo esc_attr( $timestamp ); ?>" data-token="<?php echo esc_attr( \EDD\Utils\Tokenizer::tokenize( $timestamp ) ); ?>" />
|
||||
<div id="edd-paypal-errors-wrap"></div>
|
||||
<div id="edd-paypal-container"></div>
|
||||
<div id="edd-paypal-spinner" style="display: none;">
|
||||
<span class="edd-loading-ajax edd-loading"></span>
|
||||
</div>
|
||||
<?php
|
||||
/**
|
||||
* Triggers right below the button container.
|
||||
*
|
||||
* @since 2.11
|
||||
*/
|
||||
do_action( 'edd_paypal_after_button_container' );
|
||||
} else {
|
||||
$error_message = current_user_can( 'manage_options' )
|
||||
? __( 'Please connect your PayPal account in the gateway settings.', 'easy-digital-downloads' )
|
||||
: __( 'Unexpected authentication error. Please contact a site administrator.', 'easy-digital-downloads' );
|
||||
?>
|
||||
<div class="edd_errors edd-alert edd-alert-error">
|
||||
<p class="edd_error">
|
||||
<?php echo esc_html( $error_message ); ?>
|
||||
</p>
|
||||
</div>
|
||||
<?php
|
||||
}
|
||||
|
||||
return ob_get_clean();
|
||||
}
|
||||
|
||||
return $button;
|
||||
}
|
||||
|
||||
add_filter( 'edd_checkout_button_purchase', __NAMESPACE__ . '\override_purchase_button', 10000 );
|
||||
|
||||
/**
|
||||
* Sends checkout error messages via AJAX.
|
||||
*
|
||||
* This overrides the normal error behaviour in `edd_process_purchase_form()` because we *always*
|
||||
* want to send errors back via JSON.
|
||||
*
|
||||
* @param array $user User data.
|
||||
* @param array $valid_data Validated form data.
|
||||
* @param array $posted Raw $_POST data.
|
||||
*
|
||||
* @since 2.11
|
||||
* @return void
|
||||
*/
|
||||
function send_ajax_errors( $user, $valid_data, $posted ) {
|
||||
if ( empty( $valid_data['gateway'] ) || 'paypal_commerce' !== $valid_data['gateway'] ) {
|
||||
return;
|
||||
}
|
||||
|
||||
$errors = edd_get_errors();
|
||||
if ( $errors ) {
|
||||
edd_clear_errors();
|
||||
|
||||
wp_send_json_error( edd_build_errors_html( $errors ) );
|
||||
}
|
||||
}
|
||||
|
||||
add_action( 'edd_checkout_user_error_checks', __NAMESPACE__ . '\send_ajax_errors', 99999, 3 );
|
||||
|
||||
/**
|
||||
* Creates a new order in PayPal and EDD.
|
||||
*
|
||||
* @param array $purchase_data
|
||||
*
|
||||
* @since 2.11
|
||||
* @return void
|
||||
*/
|
||||
function create_order( $purchase_data ) {
|
||||
edd_debug_log( 'PayPal - create_order()' );
|
||||
|
||||
if ( ! ready_to_accept_payments() ) {
|
||||
edd_record_gateway_error(
|
||||
__( 'PayPal Gateway Error', 'easy-digital-downloads' ),
|
||||
__( 'Account not ready to accept payments.', 'easy-digital-downloads' )
|
||||
);
|
||||
|
||||
$error_message = current_user_can( 'manage_options' )
|
||||
? __( 'Please connect your PayPal account in the gateway settings.', 'easy-digital-downloads' )
|
||||
: __( 'Unexpected authentication error. Please contact a site administrator.', 'easy-digital-downloads' );
|
||||
|
||||
wp_send_json_error( edd_build_errors_html( array(
|
||||
'paypal-error' => $error_message
|
||||
) ) );
|
||||
}
|
||||
|
||||
try {
|
||||
// Create pending payment in EDD.
|
||||
$payment_args = array(
|
||||
'price' => $purchase_data['price'],
|
||||
'date' => $purchase_data['date'],
|
||||
'user_email' => $purchase_data['user_email'],
|
||||
'purchase_key' => $purchase_data['purchase_key'],
|
||||
'currency' => edd_get_currency(),
|
||||
'downloads' => $purchase_data['downloads'],
|
||||
'cart_details' => $purchase_data['cart_details'],
|
||||
'user_info' => $purchase_data['user_info'],
|
||||
'status' => 'pending',
|
||||
'gateway' => 'paypal_commerce'
|
||||
);
|
||||
|
||||
$payment_id = edd_insert_payment( $payment_args );
|
||||
|
||||
if ( ! $payment_id ) {
|
||||
throw new Gateway_Exception(
|
||||
__( 'An unexpected error occurred. Please try again.', 'easy-digital-downloads' ),
|
||||
500,
|
||||
sprintf(
|
||||
'Payment creation failed before sending buyer to PayPal. Payment data: %s',
|
||||
json_encode( $payment_args )
|
||||
)
|
||||
);
|
||||
}
|
||||
|
||||
$order_data = array(
|
||||
'intent' => 'CAPTURE',
|
||||
'purchase_units' => get_order_purchase_units( $payment_id, $purchase_data, $payment_args ),
|
||||
'application_context' => array(
|
||||
//'locale' => get_locale(), // PayPal doesn't like this. Might be able to replace `_` with `-`
|
||||
'shipping_preference' => 'NO_SHIPPING',
|
||||
'user_action' => 'PAY_NOW',
|
||||
'return_url' => edd_get_checkout_uri(),
|
||||
'cancel_url' => edd_get_failed_transaction_uri( '?payment-id=' . urlencode( $payment_id ) )
|
||||
),
|
||||
'payment_instructions' => array(
|
||||
'disbursement_mode' => 'INSTANT'
|
||||
)
|
||||
);
|
||||
|
||||
// Add payer data if we have it. We won't have it when using Buy Now buttons.
|
||||
if ( ! empty( $purchase_data['user_email'] ) ) {
|
||||
$order_data['payer']['email_address'] = $purchase_data['user_email'];
|
||||
}
|
||||
if ( ! empty( $purchase_data['user_info']['first_name'] ) ) {
|
||||
$order_data['payer']['name']['given_name'] = $purchase_data['user_info']['first_name'];
|
||||
}
|
||||
if ( ! empty( $purchase_data['user_info']['last_name'] ) ) {
|
||||
$order_data['payer']['name']['surname'] = $purchase_data['user_info']['last_name'];
|
||||
}
|
||||
|
||||
/**
|
||||
* Filters the arguments sent to PayPal.
|
||||
*
|
||||
* @param array $order_data API request arguments.
|
||||
* @param array $purchase_data Purchase data.
|
||||
* @param int $payment_id ID of the EDD payment.
|
||||
*
|
||||
* @since 2.11
|
||||
*/
|
||||
$order_data = apply_filters( 'edd_paypal_order_arguments', $order_data, $purchase_data, $payment_id );
|
||||
|
||||
try {
|
||||
$api = new API();
|
||||
$response = $api->make_request( 'v2/checkout/orders', $order_data );
|
||||
|
||||
if ( ! isset( $response->id ) && _is_item_total_mismatch( $response ) ) {
|
||||
|
||||
edd_record_gateway_error(
|
||||
__( 'PayPal Gateway Warning', 'easy-digital-downloads' ),
|
||||
sprintf(
|
||||
/* Translators: %s - Original order data sent to PayPal. */
|
||||
__( 'PayPal could not complete the transaction with the itemized breakdown. Original order data sent: %s', 'easy-digital-downloads' ),
|
||||
json_encode( $order_data )
|
||||
),
|
||||
$payment_id
|
||||
);
|
||||
|
||||
// Try again without the item breakdown. That way if we have an error in our totals the whole API request won't fail.
|
||||
$order_data['purchase_units'] = array(
|
||||
get_order_purchase_units_without_breakdown( $payment_id, $purchase_data, $payment_args )
|
||||
);
|
||||
|
||||
// Re-apply the filter.
|
||||
$order_data = apply_filters( 'edd_paypal_order_arguments', $order_data, $purchase_data, $payment_id );
|
||||
|
||||
$response = $api->make_request( 'v2/checkout/orders', $order_data );
|
||||
}
|
||||
|
||||
if ( ! isset( $response->id ) ) {
|
||||
throw new Gateway_Exception(
|
||||
__( 'An error occurred while communicating with PayPal. Please try again.', 'easy-digital-downloads' ),
|
||||
$api->last_response_code,
|
||||
sprintf(
|
||||
'Unexpected response when creating order: %s',
|
||||
json_encode( $response )
|
||||
)
|
||||
);
|
||||
}
|
||||
|
||||
edd_debug_log( sprintf( '-- Successful PayPal response. PayPal order ID: %s; EDD order ID: %d', esc_html( $response->id ), $payment_id ) );
|
||||
|
||||
edd_update_payment_meta( $payment_id, 'paypal_order_id', sanitize_text_field( $response->id ) );
|
||||
|
||||
/*
|
||||
* Send successfully created order ID back.
|
||||
* We also send back a new nonce, for verification in the next step: `capture_order()`.
|
||||
* If the user was just logged into a new account, the previously sent nonce may have
|
||||
* become invalid.
|
||||
*/
|
||||
$timestamp = time();
|
||||
wp_send_json_success( array(
|
||||
'paypal_order_id' => $response->id,
|
||||
'edd_order_id' => $payment_id,
|
||||
'nonce' => wp_create_nonce( 'edd_process_paypal' ),
|
||||
'timestamp' => $timestamp,
|
||||
'token' => \EDD\Utils\Tokenizer::tokenize( $timestamp ),
|
||||
) );
|
||||
} catch ( Authentication_Exception $e ) {
|
||||
throw new Gateway_Exception( __( 'An authentication error occurred. Please try again.', 'easy-digital-downloads' ), $e->getCode(), $e->getMessage() );
|
||||
} catch ( API_Exception $e ) {
|
||||
throw new Gateway_Exception( __( 'An error occurred while communicating with PayPal. Please try again.', 'easy-digital-downloads' ), $e->getCode(), $e->getMessage() );
|
||||
}
|
||||
} catch ( Gateway_Exception $e ) {
|
||||
if ( ! isset( $payment_id ) ) {
|
||||
$payment_id = 0;
|
||||
}
|
||||
|
||||
$e->record_gateway_error( $payment_id );
|
||||
|
||||
wp_send_json_error( edd_build_errors_html( array(
|
||||
'paypal-error' => $e->getMessage()
|
||||
) ) );
|
||||
}
|
||||
}
|
||||
|
||||
add_action( 'edd_gateway_paypal_commerce', __NAMESPACE__ . '\create_order', 9 );
|
||||
|
||||
/**
|
||||
* Captures the order in PayPal
|
||||
*
|
||||
* @since 2.11
|
||||
*/
|
||||
function capture_order() {
|
||||
edd_debug_log( 'PayPal - capture_order()' );
|
||||
try {
|
||||
|
||||
$token = isset( $_POST['token'] ) ? sanitize_text_field( $_POST['token'] ) : '';
|
||||
$timestamp = isset( $_POST['timestamp'] ) ? sanitize_text_field( $_POST['timestamp'] ) : '';
|
||||
|
||||
if ( ! empty( $timestamp ) && ! empty( $token ) ) {
|
||||
if ( !\EDD\Utils\Tokenizer::is_token_valid( $token, $timestamp ) ) {
|
||||
throw new Gateway_Exception(
|
||||
__('A validation error occurred. Please try again.', 'easy-digital-downloads'),
|
||||
403,
|
||||
'Token validation failed.'
|
||||
);
|
||||
}
|
||||
} elseif ( empty( $token ) && ! empty( $_POST['edd_process_paypal_nonce'] ) ) {
|
||||
if ( ! wp_verify_nonce( $_POST['edd_process_paypal_nonce'], 'edd_process_paypal' ) ) {
|
||||
throw new Gateway_Exception(
|
||||
__( 'A validation error occurred. Please try again.', 'easy-digital-downloads' ),
|
||||
403,
|
||||
'Nonce validation failed.'
|
||||
);
|
||||
}
|
||||
} else {
|
||||
throw new Gateway_Exception(
|
||||
__( 'A validation error occurred. Please try again.', 'easy-digital-downloads' ),
|
||||
400,
|
||||
'Missing validation fields.'
|
||||
);
|
||||
}
|
||||
|
||||
if ( empty( $_POST['paypal_order_id'] ) ) {
|
||||
throw new Gateway_Exception(
|
||||
__( 'An unexpected error occurred. Please try again.', 'easy-digital-downloads' ),
|
||||
400,
|
||||
'Missing PayPal order ID during capture.'
|
||||
);
|
||||
}
|
||||
|
||||
try {
|
||||
$api = new API();
|
||||
$response = $api->make_request( 'v2/checkout/orders/' . urlencode( $_POST['paypal_order_id'] ) . '/capture' );
|
||||
|
||||
edd_debug_log( sprintf( '-- PayPal Response code: %d; order ID: %s', $api->last_response_code, esc_html( $_POST['paypal_order_id'] ) ) );
|
||||
|
||||
if ( ! in_array( $api->last_response_code, array( 200, 201 ) ) ) {
|
||||
$message = ! empty( $response->message ) ? $response->message : __( 'Failed to process payment. Please try again.', 'easy-digital-downloads' );
|
||||
|
||||
/*
|
||||
* If capture failed due to funding source, we want to send a `restart` back to PayPal.
|
||||
* @link https://developer.paypal.com/docs/checkout/integration-features/funding-failure/
|
||||
*/
|
||||
if ( ! empty( $response->details ) && is_array( $response->details ) ) {
|
||||
foreach ( $response->details as $detail ) {
|
||||
if ( isset( $detail->issue ) && 'INSTRUMENT_DECLINED' === $detail->issue ) {
|
||||
$message = __( 'Unable to complete your order with your chosen payment method. Please choose a new funding source.', 'easy-digital-downloads' );
|
||||
$retry = true;
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
throw new Gateway_Exception(
|
||||
$message,
|
||||
400,
|
||||
sprintf( 'Order capture failure. PayPal response: %s', json_encode( $response ) )
|
||||
);
|
||||
}
|
||||
|
||||
$payment = $transaction_id = false;
|
||||
if ( isset( $response->purchase_units ) && is_array( $response->purchase_units ) ) {
|
||||
foreach ( $response->purchase_units as $purchase_unit ) {
|
||||
if ( ! empty( $purchase_unit->reference_id ) ) {
|
||||
$payment = edd_get_payment_by( 'key', $purchase_unit->reference_id );
|
||||
$transaction_id = isset( $purchase_unit->payments->captures[0]->id ) ? $purchase_unit->payments->captures[0]->id : false;
|
||||
|
||||
if ( ! empty( $payment ) && isset( $purchase_unit->payments->captures[0]->status ) ) {
|
||||
if ( 'COMPLETED' === strtoupper( $purchase_unit->payments->captures[0]->status ) ) {
|
||||
$payment->status = 'complete';
|
||||
} elseif( 'DECLINED' === strtoupper( $purchase_unit->payments->captures[0]->status ) ) {
|
||||
$payment->status = 'failed';
|
||||
}
|
||||
}
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if ( ! empty( $payment ) ) {
|
||||
/**
|
||||
* Buy Now Button
|
||||
*
|
||||
* Fill in missing data when using "Buy Now". This bypasses checkout so not all information
|
||||
* was collected prior to payment. Instead, we pull it from the PayPal info.
|
||||
*/
|
||||
if ( empty( $payment->email ) ) {
|
||||
if ( ! empty( $response->payer->email_address ) ) {
|
||||
$payment->email = sanitize_text_field( $response->payer->email_address );
|
||||
}
|
||||
if ( empty( $payment->first_name ) && ! empty( $response->payer->name->given_name ) ) {
|
||||
$payment->first_name = sanitize_text_field( $response->payer->name->given_name );
|
||||
}
|
||||
if ( empty( $payment->last_name ) && ! empty( $response->payer->name->surname ) ) {
|
||||
$payment->last_name = sanitize_text_field( $response->payer->name->surname );
|
||||
}
|
||||
|
||||
if ( empty( $payment->customer_id ) && ! empty( $payment->email ) ) {
|
||||
$customer = new \EDD_Customer( $payment->email );
|
||||
|
||||
if ( $customer->id < 1 ) {
|
||||
$customer->create( array(
|
||||
'email' => $payment->email,
|
||||
'name' => trim( sprintf( '%s %s', $payment->first_name, $payment->last_name ) ),
|
||||
'user_id' => $payment->user_id
|
||||
) );
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if ( ! empty( $transaction_id ) ) {
|
||||
$payment->transaction_id = sanitize_text_field( $transaction_id );
|
||||
|
||||
edd_insert_payment_note( $payment->ID, sprintf(
|
||||
/* Translators: %s - transaction ID */
|
||||
__( 'PayPal Transaction ID: %s', 'easy-digital-downloads' ),
|
||||
esc_html( $transaction_id )
|
||||
) );
|
||||
}
|
||||
|
||||
$payment->save();
|
||||
|
||||
if ( 'failed' === $payment->status ) {
|
||||
$retry = true;
|
||||
throw new Gateway_Exception(
|
||||
__( 'Your payment was declined. Please try a new payment method.', 'easy-digital-downloads' ),
|
||||
400,
|
||||
sprintf( 'Order capture failure. PayPal response: %s', json_encode( $response ) )
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
wp_send_json_success( array( 'redirect_url' => edd_get_success_page_uri() ) );
|
||||
} catch ( Authentication_Exception $e ) {
|
||||
throw new Gateway_Exception( __( 'An authentication error occurred. Please try again.', 'easy-digital-downloads' ), $e->getCode(), $e->getMessage() );
|
||||
} catch ( API_Exception $e ) {
|
||||
throw new Gateway_Exception( __( 'An error occurred while communicating with PayPal. Please try again.', 'easy-digital-downloads' ), $e->getCode(), $e->getMessage() );
|
||||
}
|
||||
} catch ( Gateway_Exception $e ) {
|
||||
if ( ! isset( $payment_id ) ) {
|
||||
$payment_id = 0;
|
||||
}
|
||||
|
||||
$e->record_gateway_error( $payment_id );
|
||||
|
||||
wp_send_json_error( array(
|
||||
'message' => edd_build_errors_html( array(
|
||||
'paypal_capture_failure' => $e->getMessage()
|
||||
) ),
|
||||
'retry' => isset( $retry ) ? $retry : false
|
||||
) );
|
||||
}
|
||||
}
|
||||
|
||||
add_action( 'wp_ajax_nopriv_edd_capture_paypal_order', __NAMESPACE__ . '\capture_order' );
|
||||
add_action( 'wp_ajax_edd_capture_paypal_order', __NAMESPACE__ . '\capture_order' );
|
||||
|
||||
/**
|
||||
* Gets a fresh set of gateway options when a PayPal order is cancelled.
|
||||
* @link https://github.com/awesomemotive/easy-digital-downloads/issues/8883
|
||||
*
|
||||
* @since 2.11.3
|
||||
* @return void
|
||||
*/
|
||||
function cancel_order() {
|
||||
$nonces = array();
|
||||
$gateways = edd_get_enabled_payment_gateways( true );
|
||||
foreach ( $gateways as $gateway_id => $gateway ) {
|
||||
$nonces[ $gateway_id ] = wp_create_nonce( 'edd-gateway-selected-' . esc_attr( $gateway_id ) );
|
||||
}
|
||||
|
||||
wp_send_json_success(
|
||||
array(
|
||||
'nonces' => $nonces,
|
||||
)
|
||||
);
|
||||
}
|
||||
add_action( 'wp_ajax_nopriv_edd_cancel_paypal_order', __NAMESPACE__ . '\cancel_order' );
|
||||
add_action( 'wp_ajax_edd_cancel_paypal_order', __NAMESPACE__ . '\cancel_order' );
|
Reference in New Issue
Block a user