PluginProbe
Templately – Elementor & Gutenberg Template Library: 6500+ Free & Pro Ready Templates And Cloud! / 3.7.3
Templately – Elementor & Gutenberg Template Library: 6500+ Free & Pro Ready Templates And Cloud! v3.7.3
3.7.5 3.7.4 3.7.3 3.7.2 1-final 3.7.1 3.7.0 3.6.8 3.6.7 3.6.6 3.6.5 3.6.4 3.6.3 3.6.2 3.6.1 3.0.3 3.0.4 3.0.5 3.0.6 3.0.7 3.0.8 3.0.9 3.1.0 3.1.1 3.1.10 All 111 releases
templately / includes / API / Checkout.php

Checkout.php in Templately – Elementor & Gutenberg Template Library: 6500+ Free & Pro Ready Templates And Cloud! 3.7.3, at includes/API/Checkout.php

91 lines 3.3 KB
No matching file
Up and down to move Enter to open Esc to close
Raw Download Zip
1 <?php
2
3 namespace Templately\API;
4
5 /**
6 * Plugin-initiated checkout.
7 *
8 * Asks the backend for a frontend checkout URL carrying a short-lived login
9 * token bound to the connected api_key account (no front-end re-login), and
10 * hands it back to the React app, which redirects the buyer to it. After
11 * payment the frontend returns the buyer to `return_url` with
12 * `templately_purchase`.
13 */
14 class Checkout extends API {
15
16 public function register_routes() {
17 $this->post( 'checkout', [ $this, 'checkout' ] );
18 }
19
20 public function checkout() {
21 $purchase_type = $this->get_param( 'purchase_type', 'template' );
22
23 /**
24 * Buying a template is a content decision any contributor may make, but a
25 * subscription is bought *for the account* and changes what everyone on it
26 * pays. The base gate is `delete_posts`, so without this a Contributor
27 * could start a plan purchase against the site owner's account.
28 */
29 if ( 'subscription' === $purchase_type && ! current_user_can( 'manage_options' ) ) {
30 return $this->error(
31 'insufficient_permission',
32 __( 'Only administrators can change the subscription.', 'templately' ),
33 'checkout',
34 rest_authorization_required_code()
35 );
36 }
37 $id = $this->get_param( 'id', 0, 'intval' );
38 $return_url = $this->get_param( 'return_url', admin_url( 'admin.php?page=templately' ), 'esc_url_raw' );
39
40 if ( empty( $id ) ) {
41 return $this->error( 'invalid_checkout_item', __( 'No item selected for purchase.', 'templately' ), 'checkout', 422 );
42 }
43
44 $funcArgs = [
45 'api_key' => $this->api_key,
46 'purchase_type' => $purchase_type,
47 'id' => $id,
48 'return_url' => $return_url,
49 ];
50
51 foreach ( [ 'item_type', 'billing_interval', 'coupon' ] as $optional ) {
52 $value = $this->get_param( $optional, '' );
53 if ( ! empty( $value ) ) {
54 $funcArgs[ $optional ] = $value;
55 }
56 }
57
58 $response = $this->http()->mutation( 'pluginCheckout', 'status, message, data', $funcArgs )->post();
59
60 if ( is_wp_error( $response ) ) {
61 return $this->error( 'invalid_checkout_response', $response->get_error_message(), 'checkout' );
62 }
63
64 $data = ! empty( $response['data'] ) ? json_decode( $response['data'], true ) : [];
65
66 // Frontend checkout URL created — the app redirects the buyer to it.
67 if ( ! empty( $data['url'] ) ) {
68 /**
69 * The client assigns this straight to `window.location.href`, so verify
70 * it is an https URL on a Templately host before handing it over. The
71 * response is our own API's, but a redirect target that arrives over the
72 * wire and is followed unchecked is an open redirect waiting to happen.
73 */
74 $url = esc_url_raw( $data['url'] );
75 $host = wp_parse_url( $url, PHP_URL_HOST );
76
77 $allowed = $host && ( 'templately.com' === $host || 'templately.dev' === $host || str_ends_with( $host, '.templately.com' ) || str_ends_with( $host, '.templately.dev' ) );
78
79 if ( ! $allowed || 'https' !== wp_parse_url( $url, PHP_URL_SCHEME ) ) {
80 return $this->error( 'invalid_checkout_url', __( 'The checkout could not be verified. Please try again.', 'templately' ), 'checkout' );
81 }
82
83 return $this->success( [ 'url' => $url ] );
84 }
85
86 $message = ! empty( $response['message'] ) ? $response['message'] : __( 'Could not start the checkout. Please try again.', 'templately' );
87
88 return $this->error( 'checkout_failed', $message, 'checkout' );
89 }
90 }
91