PluginProbe ʕ •ᴥ•ʔ
Appointment Booking Plugin – LatePoint | Calendar & Scheduling for WordPress / 5.1.2
Appointment Booking Plugin – LatePoint | Calendar & Scheduling for WordPress v5.1.2
5.6.8 5.6.7 5.6.6 5.6.5 5.6.4 5.6.3 5.6.2 5.6.1 5.6.0 5.5.2 5.5.1 5.5.0 5.4.2 trunk 5.1.0 5.1.1 5.1.2 5.1.3 5.1.4 5.1.5 5.1.6 5.1.7 5.1.8 5.1.9 5.1.91 5.1.92 5.1.93 5.1.94 5.2.0 5.2.1 5.2.10 5.2.11 5.2.2 5.2.3 5.2.4 5.2.5 5.2.6 5.2.7 5.2.8 5.2.9 5.3.0 5.3.1 5.3.2 5.4.0 5.4.1
latepoint / lib / helpers / stripe_connect_helper.php
latepoint / lib / helpers Last commit date
activities_helper.php 1 year ago agent_helper.php 1 year ago auth_helper.php 1 year ago blocks_helper.php 1 year ago booking_helper.php 1 year ago bricks_helper.php 1 year ago bundles_helper.php 1 year ago calendar_helper.php 1 year ago carts_helper.php 1 year ago connector_helper.php 1 year ago csv_helper.php 1 year ago customer_helper.php 1 year ago database_helper.php 1 year ago debug_helper.php 1 year ago defaults_helper.php 1 year ago elementor_helper.php 1 year ago email_helper.php 1 year ago encrypt_helper.php 1 year ago events_helper.php 1 year ago form_helper.php 1 year ago icalendar_helper.php 1 year ago image_helper.php 1 year ago invoices_helper.php 1 year ago license_helper.php 1 year ago location_helper.php 1 year ago marketing_systems_helper.php 1 year ago meeting_systems_helper.php 1 year ago menu_helper.php 1 year ago meta_helper.php 1 year ago migrations_helper.php 1 year ago money_helper.php 1 year ago notifications_helper.php 1 year ago order_intent_helper.php 1 year ago orders_helper.php 1 year ago pages_helper.php 1 year ago params_helper.php 1 year ago payments_helper.php 1 year ago price_breakdown_helper.php 1 year ago process_jobs_helper.php 1 year ago processes_helper.php 1 year ago replacer_helper.php 1 year ago resource_helper.php 1 year ago roles_helper.php 1 year ago router_helper.php 1 year ago service_helper.php 1 year ago sessions_helper.php 1 year ago settings_helper.php 1 year ago shortcodes_helper.php 1 year ago sms_helper.php 1 year ago steps_helper.php 1 year ago stripe_connect_helper.php 1 year ago styles_helper.php 1 year ago support_topics_helper.php 1 year ago time_helper.php 1 year ago timeline_helper.php 1 year ago transaction_intent_helper.php 1 year ago util_helper.php 1 year ago version_specific_updates_helper.php 1 year ago work_periods_helper.php 1 year ago wp_datetime.php 1 year ago wp_user_helper.php 1 year ago
stripe_connect_helper.php
710 lines
1 <?php
2
3 class OsStripeConnectHelper {
4 public static $default_currency_iso_code = 'usd';
5 public static $error = false;
6
7 public static $stripe = false;
8 public static $processor_code = 'stripe_connect';
9
10
11 public static function add_all_payment_methods_to_payment_times(array $payment_times): array {
12 $payment_methods = self::get_supported_payment_methods();
13 foreach ($payment_methods as $payment_method_code => $payment_method_info) {
14 $payment_times[LATEPOINT_PAYMENT_TIME_NOW][$payment_method_code][self::$processor_code] = $payment_method_info;
15 }
16 return $payment_times;
17 }
18
19 public static function add_enabled_payment_methods_to_payment_times(array $payment_times): array {
20 if (OsPaymentsHelper::is_payment_processor_enabled(self::$processor_code)) {
21 $payment_times = self::add_all_payment_methods_to_payment_times($payment_times);
22 }
23 return $payment_times;
24 }
25
26 /**
27 * @param OsTransactionModel $transaction
28 *
29 * @return void
30 */
31 public static function output_refund_button_for_transaction(OsTransactionModel $transaction) {
32 if($transaction->is_new_record()) return;
33 if($transaction->processor != self::$processor_code) return;
34 if($transaction->is_fully_refunded()) return;
35
36 echo '<div class="transaction-refund-settings">';
37 echo '<div class="refund-settings-heading"><div>'.esc_html__('Refund Amount', 'latepoint').'</div><div class="refund-settings-close"><i class="latepoint-icon latepoint-icon-x"></i></div></div>';
38 echo '<div class="refund-settings-fields">';
39 $full_amount_label = sprintf( __( 'Full [%s]' ), OsMoneyHelper::format_price( ($transaction->amount - $transaction->get_total_refunded_amount()), true, false ) );
40 echo OsFormHelper::select_field( 'transaction_refund[portion]', false, ['full' => $full_amount_label, 'custom' => __('Custom', 'latepoint')], 'full', [ 'class' => 'size-small refund-portion-selector', 'theme' => 'simple' ] );
41 echo '<div class="custom-charge-amount-wrapper" style="display: none;">';
42 echo OsFormHelper::money_field( 'transaction_refund[custom_amount]', false, ($transaction->amount - $transaction->get_total_refunded_amount()), [ 'class' => 'size-small', 'theme' => 'simple' ] );
43 echo OsFormHelper::hidden_field( 'transaction_refund[transaction_id]', $transaction->id );
44 echo '</div>';
45 echo '<a href="#" class="latepoint-btn latepoint-btn-primary latepoint-btn-sm transaction-refund-submit-button" data-os-prompt="'.esc_attr__('Are you sure you want to refund this transaction?', 'latepoint').'" data-route="'.esc_attr(OsRouterHelper::build_route_name('stripe_connect', 'refund_transaction')).'">'.esc_html__('Submit', 'latepoint').'</a>';
46 echo '</div>';
47 echo '</div>';
48 echo '<div class="transaction-refund-button-w">';
49 echo '<a href="#" class="latepoint-btn latepoint-btn-sm latepoint-btn-danger transaction-refund-settings-button" title="'.esc_attr__('Refund Transaction', 'latepoint').'" >'.esc_html__('Issue a Refund', 'latepoint').'</a>';
50 echo '</div>';
51 }
52
53 public static function refund_transaction(OsTransactionModel $transaction, $custom_amount = null) : OsTransactionRefundModel {
54 if($transaction->is_new_record() || $transaction->processor != self::$processor_code) throw new Exception('Invalid Transaction');
55 $refund_data = [
56 'payment_intent_id' => $transaction->token,
57 ];
58 if($custom_amount) $refund_data['custom_amount'] = self::convert_amount_to_specs($custom_amount);
59 $response = self::do_account_request('refunds', OsSettingsHelper::get_payments_environment(), '', 'POST', $refund_data);
60 if(empty($response['data'])){
61 throw new Exception(__('Error Refunding', 'latepoint'));
62 }
63 $transaction_refund = new OsTransactionRefundModel();
64 $transaction_refund->transaction_id = $transaction->id;
65 $transaction_refund->amount = self::convert_amount_back_from_specs_to_db_format($response['data']['amount']);
66 $transaction_refund->token = $response['data']['id'];
67 if($transaction_refund->save()){
68 /**
69 * Transaction refund was issued
70 *
71 * @param {OsTransactionRefundModel} $transaction_refund instance of transaction refund model that was issued
72 *
73 * @since 5.1.0
74 * @hook latepoint_transaction_refund_created
75 *
76 */
77 do_action( 'latepoint_transaction_refund_created', $transaction_refund );
78 return $transaction_refund;
79 }else{
80 throw new Exception(implode(', ', $transaction_refund->get_error_messages()));
81 }
82 }
83
84 public static function output_stripe_link_on_customer_quick_form(OsCustomerModel $customer) {
85 $stripe_customer_id = self::get_stripe_customer_id($customer);
86 if ($stripe_customer_id) echo '<div class="payment-processor-customer-link-wrapper">' . esc_html__('Stripe Customer', 'latepoint') . '<a target="_blank" href="' . esc_url(self::build_customer_profile_link($stripe_customer_id, OsSettingsHelper::is_env_payments_dev())) . '">' . esc_html__('Open in Stripe', 'latepoint') . '</a></div>';
87 }
88
89
90 public static function process_payment_for_transaction_intent( $result, OsTransactionIntentModel $transaction_intent ) {
91 if ( OsPaymentsHelper::should_processor_handle_payment_for_transaction_intent( self::$processor_code, $transaction_intent ) ) {
92 switch ( $transaction_intent->get_payment_data_value( 'method' ) ) {
93 case 'payment_element':
94 if ( $transaction_intent->get_payment_data_value( 'token' ) ) {
95 // since the payment is already processed on the frontend - we need to retrieve payment intent and verify if its paid
96 $payment_intent_data = self::retrieve_payment_intent( $transaction_intent->get_payment_data_value( 'token' ) );
97 if ( in_array( $payment_intent_data['status'], [ 'succeeded', 'requires_capture' ] ) ) {
98 // success
99 $result['status'] = LATEPOINT_STATUS_SUCCESS;
100 $result['processor'] = self::$processor_code;
101 $result['charge_id'] = $payment_intent_data['id'];
102 $result['amount'] = $payment_intent_data['total'];
103 $result['kind'] = $payment_intent_data['status'] == 'requires_capture' ? LATEPOINT_TRANSACTION_KIND_AUTHORIZATION : LATEPOINT_TRANSACTION_KIND_CAPTURE;
104 } else {
105 // payment error
106 $result['status'] = LATEPOINT_STATUS_ERROR;
107 $result['message'] = __( 'Payment Error', 'latepoint' );
108 $transaction_intent->add_error( 'send_to_step', $result['message'], 'payment' );
109 }
110 } else {
111 // payment token missing
112 $result['status'] = LATEPOINT_STATUS_ERROR;
113 $result['message'] = __( 'Payment Error 23JDF38', 'latepoint' );
114 $transaction_intent->add_error( 'payment_error', $result['message'] );
115 }
116 break;
117 }
118 }
119
120 return $result;
121 }
122
123
124 public static function process_payment($result, OsOrderIntentModel $order_intent) {
125 if (OsPaymentsHelper::should_processor_handle_payment_for_order_intent(self::$processor_code, $order_intent)) {
126 switch ($order_intent->get_payment_data_value('method')) {
127 case 'payment_element':
128 if ($order_intent->get_payment_data_value('token')) {
129 // since the payment is already processed on the frontend - we need to retrieve payment intent and verify if its paid
130 $payment_intent_data = self::retrieve_payment_intent($order_intent->get_payment_data_value('token'));
131 if (in_array($payment_intent_data['status'], ['succeeded', 'requires_capture'])) {
132 // success
133 $result['status'] = LATEPOINT_STATUS_SUCCESS;
134 $result['processor'] = self::$processor_code;
135 $result['charge_id'] = $payment_intent_data['id'];
136 $result['amount'] = $payment_intent_data['total'];
137 $result['kind'] = $payment_intent_data['status'] == 'requires_capture' ? LATEPOINT_TRANSACTION_KIND_AUTHORIZATION : LATEPOINT_TRANSACTION_KIND_CAPTURE;
138 } else {
139 // payment error
140 $result['status'] = LATEPOINT_STATUS_ERROR;
141 $result['message'] = __('Payment Error', 'latepoint');
142 $order_intent->add_error('payment_error', $result['message']);
143 $order_intent->add_error('send_to_step', $result['message'], 'payment');
144 }
145 } else {
146 // payment token missing
147 $result['status'] = LATEPOINT_STATUS_ERROR;
148 $result['message'] = __('Payment Error 23JDF38', 'latepoint');
149 $order_intent->add_error('payment_error', $result['message']);
150 }
151 break;
152 }
153 }
154 return $result;
155 }
156
157
158 public static function convert_charge_amount_to_requirements($charge_amount, OsCartModel $cart) {
159 if (OsPaymentsHelper::should_processor_handle_payment_for_cart(self::$processor_code, $cart)) {
160 $charge_amount = self::convert_amount_to_specs($charge_amount);
161 }
162 return $charge_amount;
163 }
164
165 public static function convert_amount_to_specs($charge_amount){
166 $iso_code = self::get_currency_iso_code();
167 if (in_array($iso_code, self::zero_decimal_currencies_list())) {
168 $charge_amount = round($charge_amount);
169 } else {
170 $number_of_decimals = OsSettingsHelper::get_settings_value('number_of_decimals', '2');
171 $charge_amount = number_format((float)$charge_amount, $number_of_decimals, '.', '') * pow(10, $number_of_decimals);
172 }
173 return $charge_amount;
174 }
175
176 /**
177 * Converts amount from Stripe to database format
178 *
179 * @param $charge_amount
180 *
181 * @return mixed|string
182 */
183 public static function convert_amount_back_from_specs_to_db_format($charge_amount){
184 $iso_code = self::get_currency_iso_code();
185 $number_of_decimals = OsSettingsHelper::get_settings_value('number_of_decimals', '2');
186 if (!in_array($iso_code, self::zero_decimal_currencies_list()) && !empty($number_of_decimals)) {
187 $charge_amount = $charge_amount / pow(10, $number_of_decimals);
188 $charge_amount = number_format((float)$charge_amount, 4, '.', '');
189 }else{
190 $charge_amount = OsMoneyHelper::pad_to_db_format($charge_amount);
191 }
192 return $charge_amount;
193 }
194
195
196 public static function output_order_payment_pay_contents(OsTransactionIntentModel $transaction_intent) {
197 if (!OsPaymentsHelper::should_processor_handle_payment_for_transaction_intent(self::$processor_code, $transaction_intent)) return;
198 echo '<div class="lp-payment-method-content" data-payment-method="payment_element">';
199 echo '<div class="lp-payment-method-content-i">';
200 echo '<div class="stripe-payment-element"></div>';
201 echo '</div>';
202 echo '</div>';
203 }
204
205 public static function output_payment_step_contents(OsCartModel $cart) {
206 if (!OsPaymentsHelper::should_processor_handle_payment_for_cart(self::$processor_code, $cart)) return;
207 echo '<div class="lp-payment-method-content" data-payment-method="payment_element">';
208 echo '<div class="lp-payment-method-content-i">';
209 echo '<div class="stripe-payment-element"></div>';
210 echo '</div>';
211 echo '</div>';
212 }
213
214
215 public static function get_supported_payment_methods() : array{
216 return [
217 'payment_element' => [
218 'name' => __('Payment Element', 'latepoint'),
219 'label' => __('Credit Card', 'latepoint'),
220 'image_url' => LATEPOINT_IMAGES_URL . 'payment_cards.png',
221 ]
222 ];
223 }
224
225 public static function register_payment_processor(array $payment_processors) : array {
226 $payment_processors[self::$processor_code] = [
227 'code' => self::$processor_code,
228 'name' => __('Stripe Connect', 'latepoint'),
229 'front_name' => __('Stripe', 'latepoint'),
230 'image_url' => LATEPOINT_IMAGES_URL . 'processor-stripe-connect.png'
231 ];
232 return $payment_processors;
233 }
234
235 public static function add_settings_fields($processor_code) {
236 if ($processor_code != self::$processor_code) return false; ?>
237 <div class="sub-section-row">
238 <div class="sub-section-label">
239 <h3><?php esc_html_e('Connect (Live)', 'latepoint'); ?></h3>
240 </div>
241 <div class="sub-section-content">
242 <div data-env="<?php echo esc_attr(LATEPOINT_PAYMENTS_ENV_LIVE); ?>"
243 class="payment-processor-connect-status-wrapper stripe-connect-status-wrapper"
244 data-route-name="<?php echo esc_attr(OsRouterHelper::build_route_name('stripe_connect', 'check_connect_status')); ?>">
245 <div class="os-loading-spinner"></div>
246 </div>
247 </div>
248 </div>
249 <div class="sub-section-row">
250 <div class="sub-section-label">
251 <h3><?php esc_html_e('Connect (Dev)', 'latepoint'); ?></h3>
252 </div>
253 <div class="sub-section-content">
254 <div data-env="<?php echo esc_attr(LATEPOINT_PAYMENTS_ENV_DEV); ?>"
255 class="payment-processor-connect-status-wrapper stripe-connect-status-wrapper"
256 data-route-name="<?php echo esc_attr(OsRouterHelper::build_route_name('stripe_connect', 'check_connect_status')); ?>">
257 <div class="os-loading-spinner"></div>
258 </div>
259 </div>
260 </div>
261 <div class="sub-section-row">
262 <div class="sub-section-label">
263 <h3><?php esc_html_e('Other Settings', 'latepoint'); ?></h3>
264 </div>
265 <div class="sub-section-content">
266 <?php
267 $selected_stripe_country_code = OsSettingsHelper::get_settings_value('stripe_connect_country_code', 'US');
268 $selected_stripe_currency_iso_code = OsSettingsHelper::get_settings_value('stripe_connect_currency_iso_code', 'usd'); ?>
269 <div class="os-row os-mb-2">
270 <div class="os-col-6">
271 <?php echo OsFormHelper::select_field('settings[stripe_connect_country_code]', __('Country', 'latepoint'), self::load_countries_list(), $selected_stripe_country_code); ?>
272 </div>
273 <div class="os-col-6">
274 <?php echo OsFormHelper::select_field('settings[stripe_connect_currency_iso_code]', __('Currency Code', 'latepoint'), OsStripeConnectHelper::load_all_currencies_list(), $selected_stripe_currency_iso_code); ?>
275 </div>
276 </div>
277 </div>
278 </div>
279 <?php
280 }
281
282 public static function get_stripe_customer_id(OsCustomerModel $customer) {
283 return $customer->get_meta_by_key(OsSettingsHelper::append_payment_env_key('stripe_connect_customer_id'), '');
284 }
285
286 public static function save_stripe_customer_id(OsCustomerModel $customer, string $stripe_customer_id) {
287 return $customer->save_meta_by_key(OsSettingsHelper::append_payment_env_key('stripe_connect_customer_id'), $stripe_customer_id);
288 }
289
290
291 public static function get_customer($stripe_customer_id): \LatePoint\Misc\StripeConnectCustomer {
292 $response = self::do_account_request("customers/{$stripe_customer_id}");
293 $stripe_connect_customer = new \LatePoint\Misc\StripeConnectCustomer();
294 $stripe_connect_customer->id = $response['data']['id'];
295 return $stripe_connect_customer;
296 }
297
298 public static function update_customer($stripe_customer_id, $customer, $values_to_update = array()) {
299 $stripe_customer = self::get_customer($stripe_customer_id);
300 if ($stripe_customer && $values_to_update) {
301 foreach ($values_to_update as $key => $value) {
302 if (in_array($key, self::get_properties_allowed_to_update())) {
303 $stripe_customer->$key = $value;
304 }
305 }
306 $stripe_customer->save();
307 }
308 return $stripe_customer;
309 }
310
311 public static function create_customer($customer) {
312 $customer_data = [
313 'email' => $customer->email,
314 'name' => $customer->full_name
315 ];
316 $response = self::do_account_request('customers', OsSettingsHelper::get_payments_environment(), '', 'POST', $customer_data);
317 $result = ['id' => $response['data']['customer_id']];
318 return $result;
319 }
320
321
322 public static function get_currency_iso_code() {
323 return OsSettingsHelper::get_settings_value('stripe_connect_currency_iso_code', self::$default_currency_iso_code);
324 }
325
326 public static function get_server_token(string $force_env = ''): string {
327 $key = OsSettingsHelper::append_payment_env_key('server_token_for_stripe_connect', $force_env);
328 $server_token = OsSettingsHelper::get_settings_value($key, '');
329 if (empty($server_token)) {
330 $server_token = OsUtilHelper::generate_uuid();
331 OsSettingsHelper::save_setting_by_name($key, $server_token);
332 }
333 return $server_token;
334 }
335
336 public static function get_connect_url(string $env = '') {
337 $url = LATEPOINT_STRIPE_CONNECT_URL . '/wp/stripe-connection/' . $env . '/start/';
338 $url .= self::get_server_token($env) . '/' . base64_encode(implode('|||', [get_bloginfo('name'), get_site_icon_url(), OsUtilHelper::get_site_url()]));
339 return $url;
340 }
341
342
343 public static function do_account_request(string $path, string $env = '', string $connection_data = '', string $method = 'GET', array $vars = [], array $headers = []) {
344 if (empty($env)) $env = OsSettingsHelper::get_payments_environment();
345 $path = self::get_connect_account_id($env) . '/' . $path;
346 try{
347 return self::do_request($path, $connection_data, $method, $vars, $headers);
348 }catch(\Exception $e){
349 OsDebugHelper::log('Error processing request to Stripe: '.$e->getMessage(), 'stripe_connect_error');
350 return [];
351 }
352 }
353
354 public static function do_request(string $path, string $connection_data = '', string $method = 'GET', array $vars = [], array $headers = [], string $force_env = '') {
355
356 $default_vars = [];
357 $default_headers = [
358 'latepoint-version' => LATEPOINT_VERSION,
359 'latepoint-domain' => OsUtilHelper::get_site_url(),
360 'latepoint-license-key' => OsLicenseHelper::get_license_key()
361 ];
362
363 if (!empty($connection_data)) {
364 $default_headers['connection-data'] = $connection_data;
365 }
366
367
368 $args = array(
369 'timeout' => 15,
370 'headers' => array_merge($default_headers, $headers),
371 'body' => array_merge($default_vars, $vars),
372 'sslverify' => false,
373 'method' => $method
374 );
375
376
377 // in our connect server we use test/live, while latepoint plugin uses dev/live
378 if(!empty($force_env) && in_array($force_env, [LATEPOINT_PAYMENTS_ENV_DEV, LATEPOINT_PAYMENTS_ENV_LIVE])){
379 $env = ($force_env == LATEPOINT_PAYMENTS_ENV_DEV) ? 'test' : 'live';
380 }else{
381 $env = (OsSettingsHelper::is_env_payments_dev() ? 'test' : 'live');
382 }
383 $url = LATEPOINT_STRIPE_CONNECT_URL . "/api/wp/v1/stripe-connect/{$env}/{$path}";
384
385 $response = wp_remote_request($url, $args);
386
387 if (!is_wp_error($response)) {
388 $data = json_decode(wp_remote_retrieve_body($response), true);
389 $data['status'] = $response['response'];
390 return $data;
391 } else {
392 $error_message = $response->get_error_message();
393 throw new Exception($error_message);
394 }
395 }
396
397
398 public static function get_connection_buttons_and_status(string $env = '') {
399 $stripe_connect_account_id = OsSettingsHelper::get_settings_value(OsSettingsHelper::append_payment_env_key('stripe_connect_account_id', $env), false);
400 $html = '';
401 if ($stripe_connect_account_id) {
402 $charges_enabled = OsSettingsHelper::is_on(OsSettingsHelper::append_payment_env_key('stripe_connect_charges_enabled', $env));
403 $disconnect_link = '<a class="payment-processor-disconnect-link" href="#"
404 data-os-pass-response="yes"
405 data-os-pass-this="yes"
406 data-os-before-after="none"
407 data-os-after-call="latepointStripeConnectAdmin.reload_connect_status_wrapper"
408 data-os-params="' . OsUtilHelper::build_os_params(['env' => $env]) . '"
409 data-os-action="' . OsRouterHelper::build_route_name('stripe_connect', 'disconnect_connect_account') . '"
410 ><i class="latepoint-icon latepoint-icon-x"></i><span>' . __('disconnect', 'latepoint') . '</span></a>';
411 if ($charges_enabled) {
412 $html .= '<div class="payment-processor-status-connected"><i class="latepoint-icon latepoint-icon-check"></i><span>' . __('Connected', 'latepoint') . '</span></div>';
413 $html .= $disconnect_link;
414 $html .= '<div class="stripe-connect-account-info">' . $stripe_connect_account_id . '</div>';
415 } else {
416 $html .= '<div class="payment-processor-status-charges-disabled"><i class="latepoint-icon latepoint-icon-clock"></i><span>' . __('Pending Action', 'latepoint') . '</span></div>';
417 $html .= '<a data-env="' . $env . '" data-route-name="' . OsRouterHelper::build_route_name('stripe_connect', 'start_connect_process') . '" href="#" class="payment-start-connecting"><span>' . __('Continue Setup', 'latepoint') . '</span><i class="latepoint-icon latepoint-icon-arrow-right"></i></a>';
418 $html .= '<div class="stripe-connect-account-info">';
419 $html .= '<div>' . $stripe_connect_account_id . '</div>';
420 $html .= $disconnect_link;
421 $html .= '</div>';
422 }
423
424 } else {
425 $html .= '<a data-env="' . $env . '" data-route-name="' . OsRouterHelper::build_route_name('stripe_connect', 'start_connect_process') . '" href="#" class="payment-start-connecting"><span>' . __('Start Connecting', 'latepoint') . '</span><i class="latepoint-icon latepoint-icon-arrow-right"></i></a>';
426 }
427 return $html;
428 }
429
430 public static function retrieve_payment_intent(string $payment_intent_id): array {
431 $payment_request_data = self::do_account_request('payment-intents/' . $payment_intent_id, OsSettingsHelper::get_payments_environment());
432 $result = ['id' => $payment_request_data['data']['id'], 'status' => $payment_request_data['data']['status'], 'total' => $payment_request_data['data']['total']];
433 return $result;
434 }
435
436 private static function get_properties_allowed_to_update($roles = 'admin') {
437 return array('source', 'email', 'name');
438 }
439
440 public static function get_connect_publishable_key(): string {
441 $key = OsSettingsHelper::get_settings_value(OsSettingsHelper::append_payment_env_key('stripe_connect_publishable_key'), '');
442 if (empty($key)) {
443 $response = self::do_request('public-key/');
444 $key = $response['data']['key'];
445 OsSettingsHelper::save_setting_by_name(OsSettingsHelper::append_payment_env_key('stripe_connect_publishable_key'), $key);
446 }
447 return $key;
448 }
449
450 public static function zero_decimal_currencies_list() {
451 return array('bif', 'clp', 'djf', 'gnf', 'jpy', 'kmf', 'krw', 'mga', 'pyg', 'rwf', 'ugx', 'vnd', 'vuv', 'xaf', 'xof', 'xpf');
452 }
453
454
455 public static function load_countries_list() {
456 $country_codes = ['AU' => 'Australia',
457 'AT' => 'Austria',
458 'BE' => 'Belgium',
459 'BR' => 'Brazil',
460 'BG' => 'Bulgaria',
461 'CA' => 'Canada',
462 'HR' => 'Croatia',
463 'CY' => 'Cyprus',
464 'CZ' => 'Czech Republic',
465 'DK' => 'Denmark',
466 'EE' => 'Estonia',
467 'FI' => 'Finland',
468 'FR' => 'France',
469 'DE' => 'Germany',
470 'GI' => 'Gibraltar',
471 'GR' => 'Greece',
472 'HK' => 'Hong Kong',
473 'HU' => 'Hungary',
474 'IN' => 'India',
475 'IE' => 'Ireland',
476 'IT' => 'Italy',
477 'JP' => 'Japan',
478 'LV' => 'Latvia',
479 'LI' => 'Liechtenstein',
480 'LT' => 'Lithuania',
481 'LU' => 'Luxembourg',
482 'MY' => 'Malaysia',
483 'MT' => 'Malta',
484 'MX' => 'Mexico',
485 'NL' => 'Netherlands',
486 'NZ' => 'New Zealand',
487 'NO' => 'Norway',
488 'PL' => 'Poland',
489 'PT' => 'Portugal',
490 'RO' => 'Romania',
491 'SG' => 'Singapore',
492 'SK' => 'Slovakia',
493 'SI' => 'Slovenia',
494 'ES' => 'Spain',
495 'SE' => 'Sweden',
496 'CH' => 'Switzerland',
497 'TH' => 'Thailand',
498 'AE' => 'United Arab Emirates',
499 'GB' => 'United Kingdom',
500 'US' => 'United States'];
501 return $country_codes;
502 }
503
504
505 public static function load_all_currencies_list(): array {
506 return ['usd' => 'United States Dollar',
507 'aed' => 'United Arab Emirates Dirham',
508 'afn' => 'Afghan Afghani',
509 'all' => 'Albanian Lek',
510 'amd' => 'Armenian Dram',
511 'ang' => 'Netherlands Antillean Guilder',
512 'aoa' => 'Angolan Kwanza',
513 'ars' => 'Argentine Peso',
514 'aud' => 'Australian Dollar',
515 'awg' => 'Aruban Florin',
516 'azn' => 'Azerbaijani Manat',
517 'bam' => 'Bosnia-Herzegovina Convertible Mark',
518 'bbd' => 'Barbadian Dollar',
519 'bdt' => 'Bangladeshi Taka',
520 'bgn' => 'Bulgarian Lev',
521 'bif' => 'Burundian Franc',
522 'bmd' => 'Bermudian Dollar',
523 'bnd' => 'Brunei Dollar',
524 'bob' => 'Bolivian Boliviano',
525 'brl' => 'Brazilian Real',
526 'bsd' => 'Bahamian Dollar',
527 'bwp' => 'Botswana Pula',
528 'bzd' => 'Belize Dollar',
529 'cad' => 'Canadian Dollar',
530 'cdf' => 'Congolese Franc',
531 'chf' => 'Swiss Franc',
532 'clp' => 'Chilean Peso',
533 'cny' => 'Chinese Yuan',
534 'cop' => 'Colombian Peso',
535 'crc' => 'Costa Rican Colón',
536 'cve' => 'Cape Verdean Escudo',
537 'czk' => 'Czech Koruna',
538 'djf' => 'Djiboutian Franc',
539 'dkk' => 'Danish Krone',
540 'dop' => 'Dominican Peso',
541 'dzd' => 'Algerian Dinar',
542 'egp' => 'Egyptian Pound',
543 'etb' => 'Ethiopian Birr',
544 'eur' => 'Euro',
545 'fjd' => 'Fijian Dollar',
546 'fkp' => 'Falkland Islands Pound',
547 'gbp' => 'British Pound Sterling',
548 'gel' => 'Georgian Lari',
549 'gip' => 'Gibraltar Pound',
550 'gmd' => 'Gambian Dalasi',
551 'gnf' => 'Guinean Franc',
552 'gtq' => 'Guatemalan Quetzal',
553 'gyd' => 'Guyanese Dollar',
554 'hkd' => 'Hong Kong Dollar',
555 'hnl' => 'Honduran Lempira',
556 'hrk' => 'Croatian Kuna',
557 'htg' => 'Haitian Gourde',
558 'huf' => 'Hungarian Forint',
559 'idr' => 'Indonesian Rupiah',
560 'ils' => 'Israeli New Shekel',
561 'inr' => 'Indian Rupee',
562 'isk' => 'Icelandic Króna',
563 'jmd' => 'Jamaican Dollar',
564 'jpy' => 'Japanese Yen',
565 'kes' => 'Kenyan Shilling',
566 'kgs' => 'Kyrgyzstani Som',
567 'khr' => 'Cambodian Riel',
568 'kmf' => 'Comorian Franc',
569 'krw' => 'South Korean Won',
570 'kyd' => 'Cayman Islands Dollar',
571 'kzt' => 'Kazakhstani Tenge',
572 'lak' => 'Lao Kip',
573 'lbp' => 'Lebanese Pound',
574 'lkr' => 'Sri Lankan Rupee',
575 'lrd' => 'Liberian Dollar',
576 'lsl' => 'Lesotho Loti',
577 'mad' => 'Moroccan Dirham',
578 'mdl' => 'Moldovan Leu',
579 'mga' => 'Malagasy Ariary',
580 'mkd' => 'Macedonian Denar',
581 'mmk' => 'Myanmar Kyat',
582 'mnt' => 'Mongolian Tögrög',
583 'mop' => 'Macanese Pataca',
584 'mro' => 'Mauritanian Ouguiya (pre-2018)',
585 'mur' => 'Mauritian Rupee',
586 'mvr' => 'Maldivian Rufiyaa',
587 'mwk' => 'Malawian Kwacha',
588 'mxn' => 'Mexican Peso',
589 'myr' => 'Malaysian Ringgit',
590 'mzn' => 'Mozambican Metical',
591 'nad' => 'Namibian Dollar',
592 'ngn' => 'Nigerian Naira',
593 'nio' => 'Nicaraguan Córdoba',
594 'nok' => 'Norwegian Krone',
595 'npr' => 'Nepalese Rupee',
596 'nzd' => 'New Zealand Dollar',
597 'pab' => 'Panamanian Balboa',
598 'pen' => 'Peruvian Sol',
599 'pgk' => 'Papua New Guinean Kina',
600 'php' => 'Philippine Peso',
601 'pkr' => 'Pakistani Rupee',
602 'pln' => 'Polish Złoty',
603 'pyg' => 'Paraguayan Guarani',
604 'qar' => 'Qatari Riyal',
605 'ron' => 'Romanian Leu',
606 'rsd' => 'Serbian Dinar',
607 'rub' => 'Russian Ruble',
608 'rwf' => 'Rwandan Franc',
609 'sar' => 'Saudi Riyal',
610 'sbd' => 'Solomon Islands Dollar',
611 'scr' => 'Seychellois Rupee',
612 'sek' => 'Swedish Krona',
613 'sgd' => 'Singapore Dollar',
614 'shp' => 'Saint Helena Pound',
615 'sll' => 'Sierra Leonean Leone',
616 'sos' => 'Somali Shilling',
617 'srd' => 'Surinamese Dollar',
618 'std' => 'São Tomé and Príncipe Dobra (pre-2018)',
619 'svc' => 'Salvadoran Colón',
620 'szl' => 'Swazi Lilangeni',
621 'thb' => 'Thai Baht',
622 'tjs' => 'Tajikistani Somoni',
623 'top' => 'Tongan Paʻanga',
624 'try' => 'Turkish Lira',
625 'ttd' => 'Trinidad and Tobago Dollar',
626 'twd' => 'New Taiwan Dollar',
627 'tzs' => 'Tanzanian Shilling',
628 'uah' => 'Ukrainian Hryvnia',
629 'ugx' => 'Ugandan Shilling',
630 'uyu' => 'Uruguayan Peso',
631 'uzs' => 'Uzbekistani Som',
632 'vnd' => 'Vietnamese Đồng',
633 'vuv' => 'Vanuatu Vatu',
634 'wst' => 'Samoan Tālā',
635 'xaf' => 'Central African CFA Franc',
636 'xcd' => 'East Caribbean Dollar',
637 'xof' => 'West African CFA Franc',
638 'xpf' => 'CFP Franc',
639 'yer' => 'Yemeni Rial',
640 'zar' => 'South African Rand',
641 'zmw' => 'Zambian Kwacha'];
642 }
643
644
645 public static function get_connect_account_id(string $env = '') {
646 if (empty($env)) $env = OsSettingsHelper::get_payments_environment();
647 return OsSettingsHelper::get_settings_value(OsSettingsHelper::append_payment_env_key('stripe_connect_account_id', $env), '');
648 }
649
650 public static function generate_payment_intent_id_and_secret_for_transaction_intent(OsTransactionIntentModel $transaction_intent): array {
651 $order = new OsOrderModel($transaction_intent->order_id);
652 $customer_data = ['name' => $order->customer->full_name, 'email' => $order->customer->email];
653 $options = [
654 'amount' => $transaction_intent->specs_charge_amount,
655 'currency' => self::get_currency_iso_code(),
656 'stripe_customer_id' => self::get_stripe_customer_id($order->customer),
657 'transaction_description' => esc_html__('Payment for Appointment', 'latepoint'),
658 'metadata' => [
659 'transaction_intent_key' => $transaction_intent->intent_key
660 ]
661 ];
662
663
664 // pass customer data in case it needs to be created
665 $result = self::do_account_request('payment-intents', OsSettingsHelper::get_payments_environment(), '', 'POST', ['payment_intent_options' => $options, 'customer_data' => $customer_data]);
666 if (empty($result['data'])) {
667 // translators: %s is the payment error
668 $error_message = !empty($result['error']) ? sprintf(__('Payment Error: %s', 'latepoint'), esc_html($result['error'])) : __('Payment error', 'latepoint');
669 OsDebugHelper::log($error_message);
670 throw new Exception($error_message);
671 } else {
672 // make sure we use correct stripe customer id in case the one that was passed is invalid - a valid one will be returned in this call
673 if ($result['data']['stripe_customer_id'] != self::get_stripe_customer_id($order->customer)) self::save_stripe_customer_id($order->customer, $result['data']['stripe_customer_id']);
674
675 return ['id' => $result['data']['id'], 'client_secret' => $result['data']['client_secret']];
676 }
677 }
678
679 public static function generate_payment_intent_id_and_secret_for_order_intent(OsOrderIntentModel $order_intent): array {
680 $customer_data = ['name' => $order_intent->customer->full_name, 'email' => $order_intent->customer->email];
681 $options = [
682 'amount' => $order_intent->specs_charge_amount,
683 'currency' => self::get_currency_iso_code(),
684 'stripe_customer_id' => self::get_stripe_customer_id($order_intent->customer),
685 'transaction_description' => esc_html__('Payment for Appointment', 'latepoint'),
686 'metadata' => [
687 'order_intent_key' => $order_intent->intent_key
688 ]
689 ];
690
691
692 // pass customer data in case it needs to be created
693 $result = self::do_account_request('payment-intents', OsSettingsHelper::get_payments_environment(), '', 'POST', ['payment_intent_options' => $options, 'customer_data' => $customer_data]);
694 if (empty($result['data'])) {
695 // translators: %s is the payment error
696 $error_message = !empty($result['error']) ? sprintf(__('Payment Error: %s', 'latepoint'), esc_html($result['error'])) : __('Payment error', 'latepoint');
697 OsDebugHelper::log($error_message);
698 throw new Exception($error_message);
699 } else {
700 // make sure we use correct stripe customer id in case the one that was passed is invalid - a valid one will be returned in this call
701 if ($result['data']['stripe_customer_id'] != self::get_stripe_customer_id($order_intent->customer)) self::save_stripe_customer_id($order_intent->customer, $result['data']['stripe_customer_id']);
702
703 return ['id' => $result['data']['id'], 'client_secret' => $result['data']['client_secret']];
704 }
705 }
706
707 public static function build_customer_profile_link(string $stripe_customer_id, bool $test_env = false): string {
708 return 'https://dashboard.stripe.com/' . ($test_env ? 'test/' : '') . 'customers/' . $stripe_customer_id;
709 }
710 }