| 1 |
<?php |
| 2 |
/** |
| 3 |
* Ebook Store - PayPal settings tab. |
| 4 |
* |
| 5 |
* PayPal is the free, always-available gateway, so nothing on this tab is |
| 6 |
* Pro-gated. The tab is included inside a plain <div class="ebook-settings-panel"> |
| 7 |
* wrapper, so it emits <section> blocks only - never table rows. |
| 8 |
* |
| 9 |
* PHP 7.4 compatible. |
| 10 |
* |
| 11 |
* @package EbookStore |
| 12 |
*/ |
| 13 |
|
| 14 |
if ( ! defined( 'ABSPATH' ) ) { |
| 15 |
exit; |
| 16 |
} |
| 17 |
|
| 18 |
settings_fields( 'ebook-settings-group-paypal' ); |
| 19 |
do_settings_sections( 'ebook-settings-group-paypal' ); |
| 20 |
|
| 21 |
/* |
| 22 |
* Saved values. |
| 23 |
* |
| 24 |
* The toggles below write either '1' or an empty string, so '1' is the only |
| 25 |
* value that means "on". The sandbox flag is the one exception: the checkout |
| 26 |
* form in functions.php treats anything that is not an empty string as sandbox, |
| 27 |
* so we mirror that rule here to make sure the screen never claims the store is |
| 28 |
* live while checkout is actually pointing at PayPal's test servers. |
| 29 |
*/ |
| 30 |
$paypal_account = trim( (string) get_option( 'paypal_account', '' ) ); |
| 31 |
$paypal_enabled = (string) get_option( 'paypal_integration_enabled', '1' ); |
| 32 |
$paypal_language = (string) get_option( 'paypal_language', '' ); |
| 33 |
$paypal_sandbox = (string) get_option( 'paypal_sandbox', '' ); |
| 34 |
$verify_transactions = (string) get_option( 'paypal_verify_transactions', '' ); |
| 35 |
$allow_echeck = (string) get_option( 'ebook_store_allow_echeck', '' ); |
| 36 |
$require_shipping = (string) get_option( 'ebook_store_require_shipping', '0' ); |
| 37 |
|
| 38 |
$default_return_button_text = ( isset( $op ) && is_object( $op ) && isset( $op->paypal_return_button_text ) ) |
| 39 |
? (string) $op->paypal_return_button_text |
| 40 |
: 'Click here to go to download page'; |
| 41 |
$paypal_return_button_text = (string) get_option( 'paypal_return_button_text', $default_return_button_text ); |
| 42 |
|
| 43 |
$paypal_is_enabled = ( $paypal_enabled === '1' ); |
| 44 |
$paypal_is_sandbox = ( $paypal_sandbox != '' ); // phpcs:ignore WordPress.PHP.StrictComparisons.LooseComparison -- matches the checkout form. |
| 45 |
// "Never configured" counts as on, matching what the handler actually does. |
| 46 |
$paypal_is_verified = function_exists( 'ebook_store_paypal_verification_enabled' ) |
| 47 |
? ebook_store_paypal_verification_enabled() |
| 48 |
: ( $verify_transactions === '1' ); |
| 49 |
$paypal_echeck_on = ( $allow_echeck === '1' ); |
| 50 |
$paypal_has_account = ( $paypal_account !== '' ); |
| 51 |
|
| 52 |
/* |
| 53 |
* PayPal REST (Orders API v2). Once a Client ID and Secret are saved the |
| 54 |
* checkout uses them and the deprecated Standard form / IPN are no longer |
| 55 |
* involved; the account email is then only informational. |
| 56 |
*/ |
| 57 |
$paypal_rest_client_id = trim( (string) get_option( 'paypal_rest_client_id', '' ) ); |
| 58 |
$paypal_rest_secret = trim( (string) get_option( 'paypal_rest_client_secret', '' ) ); |
| 59 |
$paypal_rest_webhook_id = trim( (string) get_option( 'paypal_rest_webhook_id', '' ) ); |
| 60 |
$paypal_rest_configured = ( $paypal_rest_client_id !== '' && $paypal_rest_secret !== '' ); |
| 61 |
$paypal_rest_webhook_url = function_exists( 'ebook_store_paypal_rest_get_webhook_url' ) ? ebook_store_paypal_rest_get_webhook_url() : rest_url( 'ebook-store/v1/paypal-webhook' ); |
| 62 |
$paypal_can_pay = ( $paypal_rest_configured || $paypal_has_account ); |
| 63 |
|
| 64 |
/* |
| 65 |
* PayPal's own country/language codes for the checkout screen. The list lives in |
| 66 |
* ebook_options.php; fall back to a "let PayPal decide" single entry if this file |
| 67 |
* is ever rendered without it. |
| 68 |
*/ |
| 69 |
$paypal_language_options = ( isset( $lc ) && is_array( $lc ) ) ? $lc : array( '' => '' ); |
| 70 |
$paypal_language_options[''] = __( 'Let PayPal choose automatically (recommended)', 'ebook-store' ); |
| 71 |
|
| 72 |
/* PayPal's no_shipping parameter: 0 = ask but skippable, 1 = never ask, 2 = required. */ |
| 73 |
$shipping_options = array( |
| 74 |
'0' => __( 'Ask for a shipping address, but let the buyer skip it', 'ebook-store' ), |
| 75 |
'1' => __( 'Do not ask for a shipping address (recommended for ebooks)', 'ebook-store' ), |
| 76 |
'2' => __( 'Require a shipping address', 'ebook-store' ), |
| 77 |
); |
| 78 |
|
| 79 |
$general_tab_url = function_exists( 'ebook_store_get_settings_tab_url' ) ? ebook_store_get_settings_tab_url( 'General' ) : ''; |
| 80 |
$templates_tab_url = function_exists( 'ebook_store_get_settings_tab_url' ) ? ebook_store_get_settings_tab_url( 'Templates' ) : ''; |
| 81 |
|
| 82 |
ebook_store_render_hero( |
| 83 |
array( |
| 84 |
'eyebrow' => __( 'PayPal', 'ebook-store' ), |
| 85 |
'title' => __( 'Take payments for your ebooks through PayPal', 'ebook-store' ), |
| 86 |
'intro' => __( 'Tell Ebook Store which PayPal account should receive the money, choose what buyers see on the button and on PayPal\'s pages, and decide how carefully each payment is checked before the download is released.', 'ebook-store' ), |
| 87 |
'aside' => function () use ( $paypal_is_enabled, $paypal_has_account, $paypal_account, $paypal_is_sandbox, $paypal_is_verified, $paypal_echeck_on, $paypal_rest_configured, $paypal_rest_webhook_id, $paypal_can_pay ) { |
| 88 |
?> |
| 89 |
<aside class="ebook-settings-status-card"> |
| 90 |
<h4><?php echo esc_html__( 'Current status', 'ebook-store' ); ?></h4> |
| 91 |
<ul class="ebook-settings-status-list"> |
| 92 |
<?php |
| 93 |
ebook_store_status_row( |
| 94 |
__( 'PayPal button', 'ebook-store' ), |
| 95 |
$paypal_is_enabled ? ( $paypal_can_pay ? 'ok' : 'warn' ) : 'muted', |
| 96 |
$paypal_is_enabled |
| 97 |
? ( $paypal_can_pay |
| 98 |
? __( 'Buyers can see and use the PayPal button.', 'ebook-store' ) |
| 99 |
: __( 'Turned on, but no REST credentials and no PayPal account email are saved yet.', 'ebook-store' ) ) |
| 100 |
: __( 'Turned off. Buyers will not see a PayPal button.', 'ebook-store' ) |
| 101 |
); |
| 102 |
|
| 103 |
ebook_store_status_row( |
| 104 |
__( 'Connection', 'ebook-store' ), |
| 105 |
$paypal_rest_configured ? 'ok' : ( $paypal_has_account ? 'warn' : 'error' ), |
| 106 |
$paypal_rest_configured |
| 107 |
? __( 'REST API (current). Checkout uses your Client ID and Secret; the old Buy Now form and IPN are not used.', 'ebook-store' ) |
| 108 |
: ( $paypal_has_account |
| 109 |
? __( 'Legacy Buy Now form and IPN. PayPal has deprecated these and will switch them off in January 2027. Connect a REST app below.', 'ebook-store' ) |
| 110 |
: __( 'Not connected. Paste a REST app Client ID and Secret below.', 'ebook-store' ) ), |
| 111 |
$paypal_rest_configured |
| 112 |
? array() |
| 113 |
: array( |
| 114 |
'label' => __( 'Connect now', 'ebook-store' ), |
| 115 |
'url' => '#paypal_rest_client_id', |
| 116 |
) |
| 117 |
); |
| 118 |
|
| 119 |
if ( $paypal_rest_configured ) { |
| 120 |
ebook_store_status_row( |
| 121 |
__( 'Webhook', 'ebook-store' ), |
| 122 |
$paypal_rest_webhook_id !== '' ? 'ok' : 'warn', |
| 123 |
$paypal_rest_webhook_id !== '' |
| 124 |
? __( 'Webhook ID saved. Every notification is verified with PayPal before it is acted on.', 'ebook-store' ) |
| 125 |
: __( 'No Webhook ID saved. Buyers who return to your site still get their book, but add the webhook so a buyer who closes the tab, and refunds you make at PayPal, are handled too.', 'ebook-store' ) |
| 126 |
); |
| 127 |
} |
| 128 |
|
| 129 |
ebook_store_status_row( |
| 130 |
__( 'Receiving account', 'ebook-store' ), |
| 131 |
$paypal_has_account ? 'ok' : ( $paypal_rest_configured ? 'muted' : 'error' ), |
| 132 |
$paypal_has_account |
| 133 |
? sprintf( |
| 134 |
/* translators: %s: the PayPal account email address money is sent to. */ |
| 135 |
__( 'Money goes to %s.', 'ebook-store' ), |
| 136 |
$paypal_account |
| 137 |
) |
| 138 |
: ( $paypal_rest_configured |
| 139 |
? __( 'Money goes to the PayPal business account that owns the REST app.', 'ebook-store' ) |
| 140 |
: __( 'No PayPal email saved, so PayPal checkout cannot work at all.', 'ebook-store' ) ), |
| 141 |
( $paypal_has_account || $paypal_rest_configured ) |
| 142 |
? array() |
| 143 |
: array( |
| 144 |
'label' => __( 'Add it now', 'ebook-store' ), |
| 145 |
'url' => '#paypal_account', |
| 146 |
) |
| 147 |
); |
| 148 |
|
| 149 |
ebook_store_status_row( |
| 150 |
__( 'Mode', 'ebook-store' ), |
| 151 |
$paypal_is_sandbox ? 'warn' : 'ok', |
| 152 |
$paypal_is_sandbox |
| 153 |
? __( 'Sandbox. Checkout uses PayPal\'s test servers, so no real money is taken.', 'ebook-store' ) |
| 154 |
: __( 'Live. Real payments are being taken.', 'ebook-store' ) |
| 155 |
); |
| 156 |
|
| 157 |
ebook_store_status_row( |
| 158 |
__( 'Payment checking', 'ebook-store' ), |
| 159 |
$paypal_is_verified ? 'ok' : 'warn', |
| 160 |
$paypal_is_verified |
| 161 |
? __( 'Every payment message is confirmed with PayPal before a download is released.', 'ebook-store' ) |
| 162 |
: __( 'Off. Payment messages are trusted without asking PayPal to confirm them.', 'ebook-store' ) |
| 163 |
); |
| 164 |
|
| 165 |
ebook_store_status_row( |
| 166 |
__( 'eCheck payments', 'ebook-store' ), |
| 167 |
$paypal_echeck_on ? 'warn' : 'muted', |
| 168 |
$paypal_echeck_on |
| 169 |
? __( 'Accepted. Those orders can take several days to clear before delivery.', 'ebook-store' ) |
| 170 |
: __( 'Not accepted. Buyers pay with methods that clear straight away.', 'ebook-store' ) |
| 171 |
); |
| 172 |
?> |
| 173 |
</ul> |
| 174 |
</aside> |
| 175 |
<?php |
| 176 |
}, |
| 177 |
) |
| 178 |
); |
| 179 |
|
| 180 |
ebook_store_section_open( |
| 181 |
array( |
| 182 |
'eyebrow' => __( 'Connect', 'ebook-store' ), |
| 183 |
'title' => __( 'Connect your PayPal business account (REST API)', 'ebook-store' ), |
| 184 |
'intro' => __( 'PayPal has retired the old "Buy Now" button and the IPN messages this plugin used to rely on: no new IPN set-ups since the end of 2025, deprecated since January 2026, and switched off in January 2027. The replacement is PayPal\'s REST API. Create a REST app once, paste its Client ID and Secret here, and checkout, payment confirmation, webhooks and refunds all run through your app with OAuth 2.0. Nothing about your account is sent through the buyer\'s browser.', 'ebook-store' ), |
| 185 |
'id' => 'ebook-paypal-rest', |
| 186 |
) |
| 187 |
); |
| 188 |
|
| 189 |
if ( ! $paypal_rest_configured ) { |
| 190 |
ebook_store_callout( |
| 191 |
$paypal_has_account |
| 192 |
? __( 'This store is still using the deprecated Buy Now form and IPN. It keeps working for now, but PayPal has announced it will stop in January 2027 and new PayPal accounts can no longer enable IPN. Connect a REST app below; the switch is immediate and needs no change to your ebooks or pages.', 'ebook-store' ) |
| 193 |
: __( 'Paste a Client ID and Secret below to take PayPal payments. This is the only PayPal set-up new stores need.', 'ebook-store' ), |
| 194 |
'warning', |
| 195 |
__( 'Action needed:', 'ebook-store' ) |
| 196 |
); |
| 197 |
} |
| 198 |
|
| 199 |
ebook_store_grid_open( 2 ); |
| 200 |
ebook_store_field( |
| 201 |
array( |
| 202 |
'type' => 'text', |
| 203 |
'name' => 'paypal_rest_client_id', |
| 204 |
'id' => 'paypal_rest_client_id', |
| 205 |
'label' => __( 'Client ID', 'ebook-store' ), |
| 206 |
'value' => $paypal_rest_client_id, |
| 207 |
'placeholder' => 'A21AA...', |
| 208 |
'mono' => true, |
| 209 |
'wide' => true, |
| 210 |
'help' => __( 'From your REST app on the PayPal developer dashboard (Apps & Credentials). Use the Live credentials for real sales and the Sandbox credentials together with test mode below.', 'ebook-store' ), |
| 211 |
) |
| 212 |
); |
| 213 |
ebook_store_field( |
| 214 |
array( |
| 215 |
'type' => 'password', |
| 216 |
'name' => 'paypal_rest_client_secret', |
| 217 |
'id' => 'paypal_rest_client_secret', |
| 218 |
'label' => __( 'Secret', 'ebook-store' ), |
| 219 |
'value' => $paypal_rest_secret, |
| 220 |
'placeholder' => 'E...', |
| 221 |
'mono' => true, |
| 222 |
'wide' => true, |
| 223 |
'help' => __( 'Shown next to the Client ID on the same page (click "Show"). Keep it private: it lets this site create and capture payments on your account.', 'ebook-store' ), |
| 224 |
) |
| 225 |
); |
| 226 |
ebook_store_field( |
| 227 |
array( |
| 228 |
'type' => 'text', |
| 229 |
'name' => 'paypal_rest_webhook_id', |
| 230 |
'id' => 'paypal_rest_webhook_id', |
| 231 |
'label' => __( 'Webhook ID', 'ebook-store' ), |
| 232 |
'value' => $paypal_rest_webhook_id, |
| 233 |
'placeholder' => '8ML...', |
| 234 |
'mono' => true, |
| 235 |
'help' => __( 'On the same app page scroll to Webhooks, add one using the address shown below, and copy the Webhook ID PayPal assigns to it. With it saved every notification is verified with PayPal before a book is released.', 'ebook-store' ), |
| 236 |
) |
| 237 |
); |
| 238 |
ebook_store_grid_close(); |
| 239 |
|
| 240 |
ebook_store_copy_box( |
| 241 |
$paypal_rest_webhook_url, |
| 242 |
__( 'Your webhook address', 'ebook-store' ), |
| 243 |
esc_html__( 'When adding the webhook in the developer dashboard, paste this address and tick the events "Checkout order approved", "Payment capture completed", "Payment capture refunded" and "Payment capture reversed" (or simply "All events").', 'ebook-store' ) |
| 244 |
); |
| 245 |
|
| 246 |
ebook_store_steps( |
| 247 |
__( 'How to connect', 'ebook-store' ), |
| 248 |
array( |
| 249 |
sprintf( |
| 250 |
/* translators: 1: opening link tag to the PayPal developer dashboard, 2: closing link tag. */ |
| 251 |
__( 'Sign in to the %1$sPayPal developer dashboard%2$s with your business account and open Apps & Credentials.', 'ebook-store' ), |
| 252 |
'<a href="https://developer.paypal.com/dashboard/applications/live" target="_blank" rel="noopener noreferrer">', |
| 253 |
'</a>' |
| 254 |
), |
| 255 |
esc_html__( 'Switch to Live (or Sandbox for testing), click Create App, give it any name and choose the Merchant type.', 'ebook-store' ), |
| 256 |
esc_html__( 'Copy the Client ID and Secret into the fields above and save.', 'ebook-store' ), |
| 257 |
esc_html__( 'On the app page add a webhook with the address above, then copy its Webhook ID into the field above and save again.', 'ebook-store' ), |
| 258 |
esc_html__( 'Buy one of your own ebooks. The PayPal button now opens PayPal\'s current checkout and the book is delivered when you return.', 'ebook-store' ), |
| 259 |
) |
| 260 |
); |
| 261 |
|
| 262 |
if ( $paypal_rest_configured ) { |
| 263 |
ebook_store_callout( |
| 264 |
__( 'Connected. The PayPal account email and the IPN setting below are no longer used for checkout; they remain only for orders placed through the old form before you switched.', 'ebook-store' ), |
| 265 |
'soft', |
| 266 |
__( 'Legacy settings:', 'ebook-store' ) |
| 267 |
); |
| 268 |
} |
| 269 |
|
| 270 |
ebook_store_section_close(); |
| 271 |
|
| 272 |
ebook_store_section_open( |
| 273 |
array( |
| 274 |
'eyebrow' => __( 'Account', 'ebook-store' ), |
| 275 |
'title' => __( 'Where the money goes', 'ebook-store' ), |
| 276 |
'intro' => __( 'These two settings decide which PayPal account is paid and which language PayPal shows your buyers.', 'ebook-store' ), |
| 277 |
'id' => 'ebook-paypal-account', |
| 278 |
) |
| 279 |
); |
| 280 |
|
| 281 |
ebook_store_toggle_grid_open(); |
| 282 |
ebook_store_toggle( |
| 283 |
array( |
| 284 |
'name' => 'paypal_integration_enabled', |
| 285 |
'title' => __( 'Offer PayPal at checkout', 'ebook-store' ), |
| 286 |
'description' => __( 'When this is on, buyers see a PayPal button on your ebooks. Turn it off if you only want to sell through another payment method.', 'ebook-store' ), |
| 287 |
'checked' => $paypal_is_enabled ? '1' : '', |
| 288 |
) |
| 289 |
); |
| 290 |
ebook_store_toggle_grid_close(); |
| 291 |
|
| 292 |
ebook_store_grid_open( 2 ); |
| 293 |
ebook_store_field( |
| 294 |
array( |
| 295 |
'type' => 'email', |
| 296 |
'name' => 'paypal_account', |
| 297 |
'label' => __( 'PayPal account email address', 'ebook-store' ), |
| 298 |
'value' => $paypal_account, |
| 299 |
'placeholder' => 'you@example.com', |
| 300 |
'help' => __( 'The email address you use to sign in to PayPal. Every ebook payment is sent to this account. If it is empty or misspelled, buyers either see an error at PayPal or pay the wrong person, so copy it straight from your PayPal profile.', 'ebook-store' ), |
| 301 |
'note' => ( $paypal_has_account || $paypal_rest_configured ) ? '' : esc_html__( 'Needed only for the legacy Buy Now form. With REST credentials connected above this can stay empty.', 'ebook-store' ), |
| 302 |
'note_tone' => 'error', |
| 303 |
) |
| 304 |
); |
| 305 |
|
| 306 |
ebook_store_field( |
| 307 |
array( |
| 308 |
'type' => 'select', |
| 309 |
'name' => 'paypal_language', |
| 310 |
'label' => __( 'Language PayPal shows your buyers', 'ebook-store' ), |
| 311 |
'value' => $paypal_language, |
| 312 |
'options' => $paypal_language_options, |
| 313 |
'help' => __( 'Leave this on the automatic setting and PayPal will use each buyer\'s own language. Only pick a country or language if all of your customers are in one place and you want PayPal\'s pages to match your site.', 'ebook-store' ), |
| 314 |
) |
| 315 |
); |
| 316 |
ebook_store_grid_close(); |
| 317 |
|
| 318 |
if ( ! $paypal_rest_configured ) { |
| 319 |
ebook_store_callout( |
| 320 |
sprintf( |
| 321 |
/* translators: 1: opening link tag to PayPal's IPN settings, 2: closing link tag. */ |
| 322 |
__( 'Without REST credentials, Ebook Store only knows a payment succeeded because PayPal sends it a confirmation message (called IPN). %1$sTurn IPN on in your PayPal profile%2$s. You do not need to paste a URL anywhere: the plugin sends the correct address with every order. If IPN is off, buyers pay but never get their download. PayPal no longer lets new accounts enable IPN - connect a REST app above instead.', 'ebook-store' ), |
| 323 |
'<a href="https://www.paypal.com/cgi-bin/customerprofileweb?cmd=%5fprofile%2dipn%2dnotify" target="_blank" rel="noopener noreferrer">', |
| 324 |
'</a>' |
| 325 |
), |
| 326 |
'warning', |
| 327 |
__( 'Legacy set-up only:', 'ebook-store' ) |
| 328 |
); |
| 329 |
} |
| 330 |
|
| 331 |
if ( $general_tab_url !== '' ) { |
| 332 |
ebook_store_callout( |
| 333 |
sprintf( |
| 334 |
/* translators: 1: opening link tag to the General settings tab, 2: closing link tag. */ |
| 335 |
__( 'The currency buyers are charged in is not set here. It lives on the %1$sGeneral tab%2$s, together with your prices and tax rate. Make sure the currency you chose there is one your PayPal account can accept.', 'ebook-store' ), |
| 336 |
'<a href="' . esc_url( $general_tab_url ) . '">', |
| 337 |
'</a>' |
| 338 |
), |
| 339 |
'soft' |
| 340 |
); |
| 341 |
} |
| 342 |
|
| 343 |
ebook_store_section_close(); |
| 344 |
|
| 345 |
ebook_store_section_open( |
| 346 |
array( |
| 347 |
'eyebrow' => __( 'Buy button', 'ebook-store' ), |
| 348 |
'title' => __( 'What the PayPal button says', 'ebook-store' ), |
| 349 |
'intro' => __( 'This is the wording buyers click on your site to start paying. Short, clear wording sells more copies than clever wording.', 'ebook-store' ), |
| 350 |
'id' => 'ebook-paypal-button-text', |
| 351 |
) |
| 352 |
); |
| 353 |
|
| 354 |
ebook_store_advanced_open( __( 'Advanced button options', 'ebook-store' ) ); |
| 355 |
|
| 356 |
ebook_store_grid_open( 2 ); |
| 357 |
ebook_store_render_gateway_button_text( 'paypal' ); |
| 358 |
ebook_store_grid_close(); |
| 359 |
|
| 360 |
ebook_store_advanced_close(); |
| 361 |
|
| 362 |
ebook_store_section_close(); |
| 363 |
|
| 364 |
ebook_store_section_open( |
| 365 |
array( |
| 366 |
'eyebrow' => __( 'After payment', 'ebook-store' ), |
| 367 |
'title' => __( 'Sending buyers back to your site', 'ebook-store' ), |
| 368 |
'intro' => __( 'Once PayPal has taken the payment it shows a button that brings the buyer back to your download page. You choose the wording on that button.', 'ebook-store' ), |
| 369 |
'id' => 'ebook-paypal-return', |
| 370 |
) |
| 371 |
); |
| 372 |
|
| 373 |
ebook_store_advanced_open( __( 'Advanced return-button options', 'ebook-store' ) ); |
| 374 |
|
| 375 |
ebook_store_grid_open( 2 ); |
| 376 |
ebook_store_field( |
| 377 |
array( |
| 378 |
'type' => 'text', |
| 379 |
'name' => 'paypal_return_button_text', |
| 380 |
'label' => __( 'Wording on PayPal\'s return button', 'ebook-store' ), |
| 381 |
'value' => $paypal_return_button_text, |
| 382 |
'placeholder' => $default_return_button_text, |
| 383 |
'wide' => true, |
| 384 |
'help' => __( 'Tell the buyer exactly what happens next, for example "Click here to go to your download page". Keep it short: PayPal cuts off long text. Vague wording such as "Continue" is the single biggest cause of "where is my ebook?" emails.', 'ebook-store' ), |
| 385 |
) |
| 386 |
); |
| 387 |
|
| 388 |
if ( $templates_tab_url !== '' ) { |
| 389 |
ebook_store_steps( |
| 390 |
__( 'What the buyer sees', 'ebook-store' ), |
| 391 |
array( |
| 392 |
esc_html__( 'They click your PayPal button and pay on PayPal\'s website.', 'ebook-store' ), |
| 393 |
esc_html__( 'PayPal shows this button and they click it.', 'ebook-store' ), |
| 394 |
sprintf( |
| 395 |
/* translators: 1: opening link tag to the Templates settings tab, 2: closing link tag. */ |
| 396 |
__( 'They land on the download page you picked on the %1$sTemplates tab%2$s. If no page is set there, they have nowhere to land.', 'ebook-store' ), |
| 397 |
'<a href="' . esc_url( $templates_tab_url ) . '">', |
| 398 |
'</a>' |
| 399 |
), |
| 400 |
) |
| 401 |
); |
| 402 |
} |
| 403 |
ebook_store_grid_close(); |
| 404 |
|
| 405 |
ebook_store_advanced_close(); |
| 406 |
|
| 407 |
ebook_store_section_close(); |
| 408 |
|
| 409 |
ebook_store_section_open( |
| 410 |
array( |
| 411 |
'eyebrow' => __( 'Testing and safety', 'ebook-store' ), |
| 412 |
'title' => __( 'Test mode and payment checking', 'ebook-store' ), |
| 413 |
'intro' => __( 'Use test mode to try a purchase without spending real money, and leave payment checking on so downloads are only released for payments PayPal has confirmed.', 'ebook-store' ), |
| 414 |
'id' => 'ebook-paypal-testing', |
| 415 |
) |
| 416 |
); |
| 417 |
|
| 418 |
ebook_store_advanced_open( __( 'Advanced testing options', 'ebook-store' ) ); |
| 419 |
|
| 420 |
ebook_store_toggle_grid_open(); |
| 421 |
ebook_store_toggle( |
| 422 |
array( |
| 423 |
'name' => 'paypal_sandbox', |
| 424 |
'title' => __( 'Use PayPal test mode (sandbox)', 'ebook-store' ), |
| 425 |
'description' => __( 'Sends checkout to PayPal\'s practice website so you can buy your own ebook without paying. Remember to turn it back off: while it is on, real customers cannot pay you.', 'ebook-store' ), |
| 426 |
'checked' => $paypal_is_sandbox ? '1' : '', |
| 427 |
) |
| 428 |
); |
| 429 |
|
| 430 |
ebook_store_toggle( |
| 431 |
array( |
| 432 |
'name' => 'paypal_verify_transactions', |
| 433 |
'title' => __( 'Confirm every payment with PayPal', 'ebook-store' ), |
| 434 |
'description' => __( 'Before releasing a download, ask PayPal whether the payment message really came from PayPal. Leave this on. With it off, a faked payment message could unlock your ebook for free.', 'ebook-store' ), |
| 435 |
'checked' => $paypal_is_verified ? '1' : '', |
| 436 |
) |
| 437 |
); |
| 438 |
ebook_store_toggle_grid_close(); |
| 439 |
|
| 440 |
ebook_store_grid_open( 2 ); |
| 441 |
|
| 442 |
ebook_store_steps( |
| 443 |
__( 'How to run a test purchase', 'ebook-store' ), |
| 444 |
array( |
| 445 |
sprintf( |
| 446 |
/* translators: 1: opening link tag to PayPal's developer site, 2: closing link tag. */ |
| 447 |
__( 'Create free test accounts on the %1$sPayPal developer site%2$s. They are completely separate from your real PayPal account.', 'ebook-store' ), |
| 448 |
'<a href="https://developer.paypal.com/developer/accounts/" target="_blank" rel="noopener noreferrer">', |
| 449 |
'</a>' |
| 450 |
), |
| 451 |
esc_html__( 'Turn on test mode above, put your test seller email in the account field, and save.', 'ebook-store' ), |
| 452 |
esc_html__( 'Buy one of your own ebooks with the test buyer account and check that the download arrives. Test confirmations can take a few minutes longer than real ones.', 'ebook-store' ), |
| 453 |
esc_html__( 'Turn test mode back off and put your real PayPal email back before you tell customers about the store.', 'ebook-store' ), |
| 454 |
) |
| 455 |
); |
| 456 |
|
| 457 |
ebook_store_callout( |
| 458 |
__( 'Only turn payment checking off if your web host blocks outgoing connections to PayPal and paid orders are getting stuck. It is a temporary workaround, not a setting to leave off.', 'ebook-store' ), |
| 459 |
'warning', |
| 460 |
__( 'One exception:', 'ebook-store' ) |
| 461 |
); |
| 462 |
|
| 463 |
ebook_store_grid_close(); |
| 464 |
|
| 465 |
ebook_store_advanced_close(); |
| 466 |
|
| 467 |
ebook_store_section_close(); |
| 468 |
|
| 469 |
ebook_store_section_open( |
| 470 |
array( |
| 471 |
'eyebrow' => __( 'Buyer prompts', 'ebook-store' ), |
| 472 |
'title' => __( 'eCheck payments and shipping address', 'ebook-store' ), |
| 473 |
'intro' => __( 'Two choices about what PayPal asks your buyers for, and how long you wait for the money.', 'ebook-store' ), |
| 474 |
'id' => 'ebook-paypal-buyer-prompts', |
| 475 |
) |
| 476 |
); |
| 477 |
|
| 478 |
ebook_store_advanced_open( __( 'Advanced buyer-prompt options', 'ebook-store' ) ); |
| 479 |
|
| 480 |
ebook_store_toggle_grid_open(); |
| 481 |
ebook_store_toggle( |
| 482 |
array( |
| 483 |
'name' => 'ebook_store_allow_echeck', |
| 484 |
'title' => __( 'Accept eCheck payments', 'ebook-store' ), |
| 485 |
'description' => __( 'An eCheck is a bank transfer that can take several working days to clear. The buyer does not get the ebook until it clears, which often leads to complaints. Most ebook shops leave this off.', 'ebook-store' ), |
| 486 |
'checked' => $paypal_echeck_on ? '1' : '', |
| 487 |
) |
| 488 |
); |
| 489 |
ebook_store_toggle_grid_close(); |
| 490 |
|
| 491 |
ebook_store_grid_open( 2 ); |
| 492 |
ebook_store_field( |
| 493 |
array( |
| 494 |
'type' => 'select', |
| 495 |
'name' => 'ebook_store_require_shipping', |
| 496 |
'label' => __( 'Shipping address at PayPal checkout', 'ebook-store' ), |
| 497 |
'value' => $require_shipping, |
| 498 |
'options' => $shipping_options, |
| 499 |
'help' => __( 'An ebook is downloaded, never posted, so there is nothing to ship. Choosing not to ask keeps checkout short and fewer buyers give up halfway. Pick "Require a shipping address" only if your bookkeeping or tax rules need the buyer\'s address on file.', 'ebook-store' ), |
| 500 |
) |
| 501 |
); |
| 502 |
|
| 503 |
ebook_store_callout( |
| 504 |
sprintf( |
| 505 |
/* translators: 1: opening link tag to PayPal's eCheck help page, 2: closing link tag. */ |
| 506 |
__( 'Not sure about eChecks? %1$sPayPal explains how they work%2$s. The short version: the money is on its way but is not in your account yet, and your buyer is waiting for a book they have already paid for.', 'ebook-store' ), |
| 507 |
'<a href="https://www.paypal.com/us/selfhelp/article/What-is-an-eCheck-FAQ1082" target="_blank" rel="noopener noreferrer">', |
| 508 |
'</a>' |
| 509 |
), |
| 510 |
'soft' |
| 511 |
); |
| 512 |
ebook_store_grid_close(); |
| 513 |
|
| 514 |
ebook_store_advanced_close(); |
| 515 |
|
| 516 |
ebook_store_section_close(); |
| 517 |
|