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