PluginProbe
Ebook Store / 6.25
Ebook Store v6.25
6.25 6.24 6.23 6.22 6.21 6.20 trunk
ebook-store / settings-Stripe.php

settings-Stripe.php in Ebook Store 6.25, at settings-Stripe.php

357 lines 16.0 KB
No matching file
Up and down to move Enter to open Esc to close
Raw Download Zip
1 <?php
2 /**
3 * Ebook Store - Stripe settings tab.
4 *
5 * Rendered inside <div class="ebook-settings-panel">, so this file emits
6 * <section> blocks only: no table rows, cells or headers.
7 *
8 * PHP 7.4 compatible.
9 *
10 * @package EbookStore
11 */
12
13 if ( ! defined( 'ABSPATH' ) ) {
14 exit;
15 }
16
17 settings_fields( 'ebook-settings-group-stripe' );
18 do_settings_sections( 'ebook-settings-group-stripe' );
19
20 $stripe_publishable_key = trim( (string) get_option( 'stripe_publishable_key', '' ) );
21 $stripe_secret_key = trim( (string) get_option( 'stripe_secret_key', '' ) );
22 $stripe_webhook_secret = trim( (string) get_option( 'stripe_webhook_secret', '' ) );
23 $stripe_cancel_url = (string) get_option( 'stripe_cancel_url', home_url() );
24 $stripe_enabled_option = (string) get_option( 'stripe_integration_enabled', '0' );
25
26 $stripe_webhook_endpoint = site_url( 'wp-json/ebook-store/v1/stripe-webhook' );
27 $stripe_general_url = function_exists( 'ebook_store_get_settings_tab_url' )
28 ? ebook_store_get_settings_tab_url( 'General' )
29 : admin_url( 'options-general.php?page=ebook_options.php' );
30 $stripe_templates_url = function_exists( 'ebook_store_get_settings_tab_url' )
31 ? ebook_store_get_settings_tab_url( 'Templates' )
32 : $stripe_general_url;
33
34 /*
35 * Which Stripe environment does each key belong to? Stripe keys carry the
36 * environment in their prefix, so a test publishable key next to a live secret
37 * key can be detected here instead of failing silently at checkout.
38 */
39 $stripe_publishable_mode = '';
40 if ( strpos( $stripe_publishable_key, 'pk_test_' ) === 0 ) {
41 $stripe_publishable_mode = 'test';
42 } elseif ( strpos( $stripe_publishable_key, 'pk_live_' ) === 0 ) {
43 $stripe_publishable_mode = 'live';
44 }
45
46 $stripe_secret_mode = '';
47 if ( strpos( $stripe_secret_key, 'sk_test_' ) === 0 || strpos( $stripe_secret_key, 'rk_test_' ) === 0 ) {
48 $stripe_secret_mode = 'test';
49 } elseif ( strpos( $stripe_secret_key, 'sk_live_' ) === 0 || strpos( $stripe_secret_key, 'rk_live_' ) === 0 ) {
50 $stripe_secret_mode = 'live';
51 }
52
53 $stripe_mode_mismatch = ( $stripe_publishable_mode !== '' && $stripe_secret_mode !== '' && $stripe_publishable_mode !== $stripe_secret_mode );
54 $stripe_mode = $stripe_mode_mismatch ? '' : ( $stripe_publishable_mode !== '' ? $stripe_publishable_mode : $stripe_secret_mode );
55
56 $stripe_is_enabled = ( $stripe_enabled_option === '1' );
57 $stripe_is_ready = ( $stripe_is_enabled && $stripe_publishable_key !== '' && $stripe_secret_key !== '' && ! $stripe_mode_mismatch );
58
59 $stripe_languages = function_exists( 'ebook_store_get_active_languages' ) ? ebook_store_get_active_languages() : array( 0 => __( 'Default', 'ebook-store' ) );
60 $stripe_language_count = count( $stripe_languages );
61
62 $stripe_mismatch_warning = __( 'Your publishable key and your secret key are from different Stripe environments (one test, one live). Stripe rejects every checkout in this state. Copy both keys again from the same place in the Stripe dashboard.', 'ebook-store' );
63
64 /**
65 * The status card shown next to the page title.
66 */
67 $stripe_status_card = function () use (
68 $stripe_is_enabled,
69 $stripe_is_ready,
70 $stripe_mode,
71 $stripe_mode_mismatch,
72 $stripe_publishable_key,
73 $stripe_secret_key,
74 $stripe_webhook_secret,
75 $stripe_language_count
76 ) {
77 // Payment-method row.
78 if ( ! $stripe_is_enabled ) {
79 $enabled_state = 'muted';
80 $enabled_detail = __( 'Off. Buyers do not see a Stripe button yet.', 'ebook-store' );
81 } elseif ( $stripe_is_ready ) {
82 $enabled_state = 'ok';
83 $enabled_detail = __( 'On. Buyers see a Stripe button on your ebooks.', 'ebook-store' );
84 } else {
85 $enabled_state = 'warn';
86 $enabled_detail = __( 'On, but something below is still missing, so checkout will fail.', 'ebook-store' );
87 }
88
89 // Test / live row.
90 if ( $stripe_mode_mismatch ) {
91 $mode_state = 'error';
92 $mode_label = __( 'Test or live mode: mismatched keys', 'ebook-store' );
93 $mode_detail = __( 'One key is a test key and the other is a live key. Stripe will refuse every payment until both come from the same environment.', 'ebook-store' );
94 } elseif ( $stripe_mode === 'test' ) {
95 $mode_state = 'warn';
96 $mode_label = __( 'Test mode', 'ebook-store' );
97 $mode_detail = __( 'Test keys are saved. No real money moves. Swap in your live keys when you are ready to sell.', 'ebook-store' );
98 } elseif ( $stripe_mode === 'live' ) {
99 $mode_state = 'ok';
100 $mode_label = __( 'Live mode', 'ebook-store' );
101 $mode_detail = __( 'Live keys are saved. Real cards will be charged.', 'ebook-store' );
102 } elseif ( $stripe_publishable_key !== '' || $stripe_secret_key !== '' ) {
103 $mode_state = 'warn';
104 $mode_label = __( 'Test or live mode: unknown', 'ebook-store' );
105 $mode_detail = __( 'The saved keys do not start with pk_test_, pk_live_, sk_test_ or sk_live_. Check for a typo or a stray space.', 'ebook-store' );
106 } else {
107 $mode_state = 'muted';
108 $mode_label = __( 'Test or live mode: not set', 'ebook-store' );
109 $mode_detail = __( 'No Stripe keys have been saved yet.', 'ebook-store' );
110 }
111 ?>
112 <aside class="ebook-settings-status-card">
113 <h4><?php echo esc_html__( 'Current status', 'ebook-store' ); ?></h4>
114 <ul class="ebook-settings-status-list">
115 <?php
116 ebook_store_status_row( __( 'Stripe payment button', 'ebook-store' ), $enabled_state, $enabled_detail );
117 ebook_store_status_row( $mode_label, $mode_state, $mode_detail );
118 ebook_store_status_row(
119 __( 'Publishable key', 'ebook-store' ),
120 $stripe_publishable_key !== '' ? 'ok' : 'warn',
121 $stripe_publishable_key !== ''
122 ? __( 'Saved.', 'ebook-store' )
123 : __( 'Not saved yet. Checkout cannot start without it.', 'ebook-store' )
124 );
125 ebook_store_status_row(
126 __( 'Secret key', 'ebook-store' ),
127 $stripe_secret_key !== '' ? 'ok' : 'warn',
128 $stripe_secret_key !== ''
129 ? __( 'Saved.', 'ebook-store' )
130 : __( 'Not saved yet. Checkout cannot start without it.', 'ebook-store' )
131 );
132 ebook_store_status_row(
133 __( 'Webhook signing secret', 'ebook-store' ),
134 $stripe_webhook_secret !== '' ? 'ok' : 'warn',
135 $stripe_webhook_secret !== ''
136 ? __( 'Saved. Paid orders can be confirmed automatically.', 'ebook-store' )
137 : __( 'Not saved yet. Buyers could pay without your store recording the order.', 'ebook-store' )
138 );
139 ebook_store_status_row(
140 __( 'Button label languages', 'ebook-store' ),
141 'muted',
142 sprintf(
143 /* translators: %d: number of languages the button label can be written in, including the default. */
144 _n(
145 'You can write the button label in %d language.',
146 'You can write the button label in %d languages.',
147 $stripe_language_count,
148 'ebook-store'
149 ),
150 $stripe_language_count
151 )
152 );
153 ?>
154 </ul>
155 </aside>
156 <?php
157 };
158
159 ebook_store_render_hero(
160 array(
161 'eyebrow' => __( 'Stripe', 'ebook-store' ),
162 'title' => __( 'Take card payments with Stripe checkout', 'ebook-store' ),
163 'intro' => __( 'Buyers are sent to a payment page hosted by Stripe, pay there, and come straight back to your store. This tab is where you switch Stripe on, paste the keys that connect your store to your Stripe account, and choose the wording on the payment button.', 'ebook-store' ),
164 'aside' => $stripe_status_card,
165 )
166 );
167
168 ebook_store_pro_banner( __( 'Stripe', 'ebook-store' ) );
169
170 if ( $stripe_mode_mismatch ) {
171 ebook_store_callout(
172 esc_html( $stripe_mismatch_warning ),
173 'warning',
174 __( 'Your two Stripe keys do not match:', 'ebook-store' )
175 );
176 }
177
178 ebook_store_section_open(
179 array(
180 'eyebrow' => __( 'Checkout', 'ebook-store' ),
181 'title' => __( 'Turn Stripe on and name the button', 'ebook-store' ),
182 'intro' => __( 'Switch Stripe on once your keys and webhook below are filled in. The label is the text buyers click to pay.', 'ebook-store' ),
183 'id' => 'ebook-stripe-checkout',
184 'pro' => true,
185 )
186 );
187
188 ebook_store_toggle_grid_open();
189 ebook_store_toggle(
190 array(
191 'name' => 'stripe_integration_enabled',
192 'id' => 'stripe_integration_enabled',
193 'title' => __( 'Show a Stripe button on my ebooks', 'ebook-store' ),
194 'description' => __( 'Leave this off until the publishable key, secret key and webhook secret below are all saved. Switching it on too early means buyers see a button that cannot complete a payment.', 'ebook-store' ),
195 'checked' => $stripe_enabled_option,
196 'pro' => true,
197 )
198 );
199 ebook_store_toggle_grid_close();
200
201 ebook_store_advanced_open( __( 'Advanced checkout options', 'ebook-store' ) );
202
203 ebook_store_render_gateway_button_text( 'stripe' );
204
205 ebook_store_advanced_close();
206
207 ebook_store_callout(
208 sprintf(
209 /* translators: 1: URL of the General settings tab, 2: URL of the Templates settings tab. */
210 wp_kses_post( __( 'Stripe charges in the store currency set on the <a href="%1$s">General tab</a>, and returns buyers to the checkout page chosen on the <a href="%2$s">Templates tab</a>. If either of those is wrong, Stripe payments will look wrong too.', 'ebook-store' ) ),
211 esc_url( $stripe_general_url ),
212 esc_url( $stripe_templates_url )
213 ),
214 'info',
215 __( 'Two settings live on other tabs:', 'ebook-store' )
216 );
217
218 ebook_store_section_close();
219
220 ebook_store_section_open(
221 array(
222 'eyebrow' => __( 'API keys', 'ebook-store' ),
223 'title' => __( 'Connect your Stripe account', 'ebook-store' ),
224 'intro' => __( 'Both keys come from the same screen in your Stripe dashboard: Developers, then API keys. Use the test pair while you try things out and the live pair when you start selling, but never mix one of each.', 'ebook-store' ),
225 'id' => 'ebook-stripe-keys',
226 'pro' => true,
227 )
228 );
229
230 ebook_store_grid_open( 2 );
231
232 ebook_store_field(
233 array(
234 'type' => 'text',
235 'name' => 'stripe_publishable_key',
236 'id' => 'stripe_publishable_key',
237 'label' => __( 'Publishable key', 'ebook-store' ),
238 'value' => $stripe_publishable_key,
239 'placeholder' => 'pk_live_... or pk_test_...',
240 'mono' => true,
241 'pro' => true,
242 'help' => __( 'Starts with pk_. Copy it from Stripe: Developers, then API keys. This one is not secret, it just tells Stripe which account the payment belongs to. If it is missing or wrong, the payment page never opens.', 'ebook-store' ),
243 'note' => $stripe_mode_mismatch ? esc_html( $stripe_mismatch_warning ) : '',
244 'note_tone' => 'error',
245 )
246 );
247
248 ebook_store_field(
249 array(
250 'type' => 'text',
251 'name' => 'stripe_secret_key',
252 'id' => 'stripe_secret_key',
253 'label' => __( 'Secret key', 'ebook-store' ),
254 'value' => $stripe_secret_key,
255 'placeholder' => 'sk_live_... or sk_test_...',
256 'mono' => true,
257 'pro' => true,
258 'help' => __( 'Starts with sk_. In Stripe you have to click "Reveal" to see it. Treat it like a password: anyone who has it can take payments and issue refunds on your account. It must be the test or live twin of the publishable key above.', 'ebook-store' ),
259 'note' => $stripe_mode_mismatch ? esc_html( $stripe_mismatch_warning ) : '',
260 'note_tone' => 'error',
261 )
262 );
263
264 ebook_store_grid_close();
265
266 ebook_store_callout(
267 esc_html__( 'Test keys let you run a full purchase with Stripe test card 4242 4242 4242 4242 without any money changing hands. Nothing is charged and no real order is created for a customer.', 'ebook-store' ),
268 'soft',
269 __( 'Trying it out first:', 'ebook-store' )
270 );
271
272 ebook_store_section_close();
273
274 ebook_store_section_open(
275 array(
276 'eyebrow' => __( 'Webhook and return page', 'ebook-store' ),
277 'title' => __( 'Let Stripe tell your store about paid orders', 'ebook-store' ),
278 'intro' => __( 'A webhook is a message Stripe sends to your site the moment a payment succeeds. Without it your store may never learn that a buyer paid, so no order and no download link are created.', 'ebook-store' ),
279 'id' => 'ebook-stripe-webhook',
280 'pro' => true,
281 )
282 );
283
284 ebook_store_copy_box(
285 $stripe_webhook_endpoint,
286 __( 'Your webhook address', 'ebook-store' ),
287 esc_html__( 'In Stripe go to Developers, then Webhooks, then Add endpoint, and paste this address. Select the events checkout.session.completed and charge.refunded. Stripe then shows you a signing secret to paste in the field below.', 'ebook-store' )
288 );
289
290 ebook_store_advanced_open( __( 'Advanced webhook settings', 'ebook-store' ) );
291
292 ebook_store_grid_open( 2 );
293
294 ebook_store_field(
295 array(
296 'type' => 'text',
297 'name' => 'stripe_webhook_secret',
298 'id' => 'stripe_webhook_secret',
299 'label' => __( 'Webhook signing secret', 'ebook-store' ),
300 'value' => $stripe_webhook_secret,
301 'placeholder' => 'whsec_...',
302 'mono' => true,
303 'pro' => true,
304 'help' => __( 'Starts with whsec_. Stripe shows it on the webhook you just created, under "Signing secret". It proves the messages really come from Stripe. If it is missing or wrong, paid orders are ignored and your buyer gets nothing.', 'ebook-store' ),
305 )
306 );
307
308 ebook_store_field(
309 array(
310 'type' => 'url',
311 'name' => 'stripe_cancel_url',
312 'id' => 'stripe_cancel_url',
313 'label' => __( 'Where to send buyers who change their mind', 'ebook-store' ),
314 'value' => $stripe_cancel_url,
315 'placeholder' => home_url(),
316 'pro' => true,
317 'help' => __( 'If someone opens the Stripe payment page and then backs out without paying, this is the page they land on. Your shop page or home page both work well. Leave it as your home page if you are unsure.', 'ebook-store' ),
318 )
319 );
320
321 ebook_store_grid_close();
322
323 ebook_store_advanced_close();
324
325 if ( $stripe_webhook_secret === '' ) {
326 ebook_store_callout(
327 esc_html__( 'No signing secret is saved yet. Until you add one, a buyer can pay Stripe successfully and still never receive their ebook.', 'ebook-store' ),
328 'warning',
329 __( 'Webhook not finished:', 'ebook-store' )
330 );
331 }
332
333 ebook_store_section_close();
334
335 ebook_store_section_open(
336 array(
337 'eyebrow' => __( 'Setup guide', 'ebook-store' ),
338 'title' => __( 'Setting Stripe up from scratch', 'ebook-store' ),
339 'intro' => __( 'Work through these in order and checkout, order confirmation and buyer redirects all work the first time.', 'ebook-store' ),
340 'id' => 'ebook-stripe-setup',
341 )
342 );
343
344 ebook_store_steps(
345 __( 'Six steps, about ten minutes', 'ebook-store' ),
346 array(
347 esc_html__( 'Create a Stripe account at stripe.com, or sign in to the one you already have.', 'ebook-store' ),
348 esc_html__( 'In Stripe open Developers, then API keys, and copy the publishable key and the secret key into the fields above.', 'ebook-store' ),
349 esc_html__( 'In Stripe open Developers, then Webhooks, and add an endpoint using the webhook address shown above.', 'ebook-store' ),
350 esc_html__( 'Copy the signing secret Stripe gives you for that webhook into the webhook signing secret field.', 'ebook-store' ),
351 esc_html__( 'Choose the page buyers return to if they cancel, then save your changes.', 'ebook-store' ),
352 esc_html__( 'Only now switch on the Stripe button, and place one test purchase to confirm the order appears in your store.', 'ebook-store' ),
353 )
354 );
355
356 ebook_store_section_close();
357