PluginProbe
Fluent Forms – Customizable Contact Forms, Survey, Quiz, & Conversational Form Builder / 6.2.13
Fluent Forms – Customizable Contact Forms, Survey, Quiz, & Conversational Form Builder v6.2.13
6.2.14 6.2.13 6.2.12 6.2.10 6.2.11 6.2.9 6.2.8 6.2.7 6.2.6 6.2.5 6.2.4 6.2.3 6.2.2 3.6.22 3.6.31 3.6.40 3.6.41 3.6.42 3.6.50 3.6.51 3.6.60 3.6.61 3.6.62 3.6.64 3.6.65 All 196 releases
fluentform / app / Modules / Payments / PaymentMethods / Stripe / ConnectConfig.php

ConnectConfig.php in Fluent Forms – Customizable Contact Forms, Survey, Quiz, & Conversational Form Builder 6.2.13, at app/Modules/Payments/PaymentMethods/Stripe/ConnectConfig.php

252 lines 8.6 KB
No matching file
Up and down to move Enter to open Esc to close
Raw Download Zip
1 <?php
2
3 namespace FluentForm\App\Modules\Payments\PaymentMethods\Stripe;
4
5 use FluentForm\App\Helpers\Helper;
6 use FluentForm\Framework\Helpers\ArrayHelper;
7 use FluentForm\App\Modules\Payments\PaymentMethods\Stripe\API\Account;
8
9 if (!defined('ABSPATH')) {
10 exit; // Exit if accessed directly.
11 }
12
13 class ConnectConfig
14 {
15 private static $connectBase = 'https://apiv2.wpmanageninja.com/fluentform/';
16
17 public static function getConnectConfig()
18 {
19 $configBase = self::$connectBase . 'stripe-connect';
20 // SECURITY (FINDING-24): the fluentforms.com connect proxy sets its own OAuth `state`, so
21 // our nonce can't ride there. Carry it in url_base — the proxy must redirect back to
22 // url_base, so the nonce returns to us intact as ff_connect_nonce for CSRF verification.
23 $hash = wp_create_nonce('ff_stripe_connect');
24 $urlBase = rawurlencode(admin_url('admin.php?page=fluent_forms_settings&ff_connect_nonce=' . $hash));
25
26 $liveArgs = [
27 'url_base' => $urlBase,
28 'mode' => 'live',
29 'hash' => $hash
30 ];
31
32 $testArgs = [
33 'url_base' => $urlBase,
34 'mode' => 'test',
35 'hash' => $hash
36 ];
37
38 $settings = StripeSettings::getSettings();
39
40 $data = [
41 'connect_config' => [
42 'live_redirect' => add_query_arg($liveArgs, $configBase),
43 'test_redirect' => add_query_arg($testArgs, $configBase),
44 'image_url' => fluentformMix('img/payment/stripe-connect.png'),
45 'should_apply_application_fee' => !Helper::hasPro(),
46 ],
47 'test_account' => self::getAccountInfo($settings, 'test'),
48 'live_account' => self::getAccountInfo($settings, 'live')
49 ];
50
51 if ($settings['test_secret_key']) {
52 $settings['test_secret_key'] = 'ENCRYPTED_KEY';
53 }
54
55 if ($settings['live_secret_key']) {
56 $settings['live_secret_key'] = 'ENCRYPTED_KEY';
57 }
58
59 $data['settings'] = $settings;
60
61 return $data;
62 }
63
64 public static function verifyAuthorizeSuccess($data)
65 {
66 // SECURITY (FINDING-24): require the settings-manager capability and a valid connect nonce
67 // before exchanging the code. Otherwise a settings manager could be tricked (CSRF) into
68 // loading a callback carrying the attacker's Stripe code, overwriting the site's live
69 // Stripe credentials so all future payments settle into the attacker's account.
70 if (!current_user_can('fluentform_settings_manager')) {
71 return;
72 }
73 // The nonce is carried in url_base (see getConnectConfig) and returns as ff_connect_nonce,
74 // not in the proxy-controlled `state`.
75 // phpcs:ignore WordPress.Security.NonceVerification.Recommended -- this IS the nonce check
76 $connectNonce = isset($_GET['ff_connect_nonce']) ? sanitize_text_field(wp_unslash($_GET['ff_connect_nonce'])) : '';
77 if (!$connectNonce || !wp_verify_nonce($connectNonce, 'ff_stripe_connect')) {
78 echo '<div class="ff_message ff_message_error">' . esc_html__('Invalid or expired Stripe Connect request. Please start the connection again.', 'fluentform') . '</div>';
79 return;
80 }
81
82 // SECURITY (FINDING-24 / PRO-10): enable TLS verification on the exchange that returns the
83 // live Stripe secret key so a network-position attacker cannot read or substitute it.
84 $response = wp_remote_post(self::$connectBase . 'stripe-verify-code', [
85 'method' => 'POST',
86 'timeout' => 45,
87 'redirection' => 5,
88 'httpversion' => '1.0',
89 'sslverify' => true,
90 'blocking' => true,
91 'headers' => array(),
92 'body' => $data,
93 'cookies' => array()
94 ]);
95
96 if (is_wp_error($response)) {
97 $message = $response->get_error_message();
98 echo '<div class="ff_message ff_message_error">' . esc_html($message) . '</div>';
99 return;
100 }
101
102 $response = json_decode(wp_remote_retrieve_body($response), true);
103
104 if (empty($response['stripe_user_id'])) {
105 $message = ArrayHelper::get($response, 'message');
106 if (!$message) {
107 $message = __('Invalid Stripe Request. Please configure stripe payment gateway again', 'fluentform');
108 }
109 echo '<div class="ff_message ff_message_error">' . esc_html($message) . '</div>';
110 return;
111 }
112
113 $settings = StripeSettings::getSettings();
114 $settings['provider'] = 'connect';
115
116 $settings['is_active'] = 'yes';
117
118 if (!empty($response['livemode'])) {
119 $settings['payment_mode'] = 'live';
120 $settings['live_account_id'] = $response['stripe_user_id'];
121 $settings['live_publishable_key'] = $response['stripe_publishable_key'];
122 $settings['live_secret_key'] = $response['access_token'];
123 } else {
124 $settings['payment_mode'] = 'test';
125 $settings['test_account_id'] = $response['stripe_user_id'];
126 $settings['test_publishable_key'] = $response['stripe_publishable_key'];
127 $settings['test_secret_key'] = $response['access_token'];
128 }
129
130 StripeSettings::updateSettings($settings);
131
132 ?>
133 <script type="text/javascript">
134 window.location = "<?php echo esc_url(admin_url('admin.php?page=fluent_forms_settings#payments/payment_methods')); ?>"
135 </script>
136 <?php
137
138 }
139
140 private static function getAccountInfo($settings, $mode)
141 {
142
143 if ($settings['is_active'] != 'yes') {
144 return false;
145 }
146
147 if ($settings['provider'] != 'connect') {
148 return false;
149 }
150
151 $apiKey = $settings[$mode . '_secret_key'];
152
153 $accountId = ArrayHelper::get($settings, $mode . '_account_id');
154
155 if (!$accountId) {
156 return false;
157 }
158
159 $account = Account::retrive($accountId, $apiKey);
160
161 if (is_wp_error($account)) {
162 return [
163 'error' => $account->get_error_message()
164 ];
165 }
166
167 // Find the email.
168 $email = isset($account->email)
169 ? esc_html($account->email)
170 : '';
171
172 // Find a Display Name.
173 $display_name = isset($account->display_name)
174 ? esc_html($account->display_name)
175 : '';
176
177 if (
178 empty($display_name) &&
179 isset($account->settings) &&
180 isset($account->settings->dashboard) &&
181 isset($account->settings->dashboard->display_name)
182 ) {
183 $display_name = esc_html($account->settings->dashboard->display_name);
184 }
185
186 if (empty($display_name)) {
187 return [
188 'error' => __('Unable to find connected display name', 'fluentform')
189 ];
190 }
191
192 return [
193 'account_id' => $accountId,
194 'display_name' => $display_name,
195 'email' => $email
196 ];
197
198 }
199
200 public static function disconnect($data, $sendResponse = false)
201 {
202 $mode = ArrayHelper::get($data, 'mode');
203 $stripeSettings = StripeSettings::getSettings();
204
205 if($stripeSettings['is_active'] != 'yes') {
206 if($sendResponse) {
207 wp_send_json_error([
208 'message' => __('Stripe mode is not active', 'fluentform')
209 ], 423);
210 }
211 return false;
212 }
213
214 if(empty($stripeSettings[$mode.'_account_id'])) {
215 if($sendResponse) {
216 wp_send_json_error([
217 'message' => __('Selected Account does not exist', 'fluentform')
218 ], 423);
219 }
220 return false;
221 }
222
223 $stripeSettings[$mode.'_account_id'] = '';
224 $stripeSettings[$mode.'_publishable_key'] = '';
225 $stripeSettings[$mode.'_secret_key'] = '';
226
227 if($mode == 'live') {
228 $alternateMode = 'test';
229 } else {
230 $alternateMode = 'live';
231 }
232
233 if(empty($stripeSettings[$alternateMode.'_account_id'])) {
234 $stripeSettings['is_active'] = 'no';
235 $stripeSettings['payment_mode'] = 'test';
236 } else {
237 $stripeSettings['payment_mode'] = $alternateMode;
238 }
239
240 StripeSettings::updateSettings($stripeSettings);
241
242 if($sendResponse) {
243 wp_send_json_success([
244 'message' => __('Stripe settings has been disconnected', 'fluentform'),
245 'settings' => $stripeSettings
246 ], 200);
247 }
248
249 return true;
250 }
251 }
252