[Back]
<?php

class OsStripeConnectHelper {
	public static $default_currency_iso_code = 'usd';
	public static $error = false;

	public static $stripe = false;
	public static $processor_code = 'stripe_connect';


	public static function add_all_payment_methods_to_payment_times(array $payment_times): array {
		$payment_methods = self::get_supported_payment_methods();
		foreach ($payment_methods as $payment_method_code => $payment_method_info) {
			$payment_times[LATEPOINT_PAYMENT_TIME_NOW][$payment_method_code][self::$processor_code] = $payment_method_info;
		}
		return $payment_times;
	}

	public static function add_enabled_payment_methods_to_payment_times(array $payment_times): array {
		if (OsPaymentsHelper::is_payment_processor_enabled(self::$processor_code)) {
			$payment_times = self::add_all_payment_methods_to_payment_times($payment_times);
		}
		return $payment_times;
	}


	public static function process_refund($transaction_refund, OsTransactionModel $transaction, $custom_amount = null) {
		if ($transaction->processor != self::$processor_code) return $transaction_refund;

        if(!$transaction->can_refund()) throw new Exception('Invalid Transaction');

        $refund_data = [
                'payment_intent_id' => $transaction->token,
        ];
        if($custom_amount) $refund_data['custom_amount'] = self::convert_amount_to_specs($custom_amount);

        $response = self::do_account_request('refunds', OsSettingsHelper::get_payments_environment(), '', 'POST', $refund_data);

        if(empty($response['data'])){
            throw new Exception(__('Error Refunding', 'latepoint'));
        }

        $transaction_refund = new OsTransactionRefundModel();
        $transaction_refund->transaction_id = $transaction->id;
        $transaction_refund->amount = self::convert_amount_back_from_specs_to_db_format($response['data']['amount']);
        $transaction_refund->token = $response['data']['id'];
        if($transaction_refund->save()){
            /**
             * Transaction refund was issued
             *
             * @param {OsTransactionRefundModel} $transaction_refund instance of transaction refund model that was issued
             *
             * @since 5.1.0
             * @hook latepoint_transaction_refund_created
             *
             */
            do_action( 'latepoint_transaction_refund_created', $transaction_refund );
            return $transaction_refund;
        } else {
	        throw new Exception( implode( ', ', $transaction_refund->get_error_messages() ) );
        }
    }

	public static function output_stripe_link_on_customer_quick_form(OsCustomerModel $customer) {
		$stripe_customer_id = self::get_stripe_customer_id($customer);
		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>';
	}

    public static function convert_transaction_intent_charge_amount_to_specs($amount, OsTransactionIntentModel $transaction_intent) {
        if ( OsPaymentsHelper::should_processor_handle_payment_for_transaction_intent( self::$processor_code, $transaction_intent ) ) {
	        $amount = self::convert_amount_to_specs( $amount );
        }
        return $amount;
    }

    public static function process_payment_for_transaction_intent( $result, OsTransactionIntentModel $transaction_intent ) {
        if ( OsPaymentsHelper::should_processor_handle_payment_for_transaction_intent( self::$processor_code, $transaction_intent ) ) {
            switch ( $transaction_intent->get_payment_data_value( 'method' ) ) {
                case 'payment_element':
                    if ( $transaction_intent->get_payment_data_value( 'token' ) ) {
                        // since the payment is already processed on the frontend - we need to retrieve payment intent and verify if its paid
                        $payment_intent_data = self::retrieve_payment_intent( $transaction_intent->get_payment_data_value( 'token' ) );
                        if ( in_array( $payment_intent_data['status'], [ 'succeeded', 'requires_capture' ] ) ) {
                            // success
                            $result['status']    = LATEPOINT_STATUS_SUCCESS;
                            $result['processor'] = self::$processor_code;
                            $result['charge_id'] = $payment_intent_data['id'];
                            $result['amount']    = $payment_intent_data['total'];
                            $result['kind']      = $payment_intent_data['status'] == 'requires_capture' ? LATEPOINT_TRANSACTION_KIND_AUTHORIZATION : LATEPOINT_TRANSACTION_KIND_CAPTURE;
                        } else {
                            // payment error
                            $result['status']  = LATEPOINT_STATUS_ERROR;
                            $result['message'] = __( 'Payment Error', 'latepoint' );
                            $transaction_intent->add_error( 'send_to_step', $result['message'], 'payment' );
                        }
                    } else {
                        // payment token missing
                        $result['status']  = LATEPOINT_STATUS_ERROR;
                        $result['message'] = __( 'Payment Error 23JDF38', 'latepoint' );
                        $transaction_intent->add_error( 'payment_error', $result['message'] );
                    }
                    break;
            }
        }

        return $result;
    }


	public static function process_payment($result, OsOrderIntentModel $order_intent) {
			if (OsPaymentsHelper::should_processor_handle_payment_for_order_intent(self::$processor_code, $order_intent)) {
			switch ($order_intent->get_payment_data_value('method')) {
				case 'payment_element':
					if ($order_intent->get_payment_data_value('token')) {
						// since the payment is already processed on the frontend - we need to retrieve payment intent and verify if its paid
						$payment_intent_data = self::retrieve_payment_intent($order_intent->get_payment_data_value('token'));
						if (in_array($payment_intent_data['status'], ['succeeded', 'requires_capture'])) {
							// success
							$result['status'] = LATEPOINT_STATUS_SUCCESS;
							$result['processor'] = self::$processor_code;
							$result['charge_id'] = $payment_intent_data['id'];
							$result['amount'] = $payment_intent_data['total'];
							$result['kind'] = $payment_intent_data['status'] == 'requires_capture' ? LATEPOINT_TRANSACTION_KIND_AUTHORIZATION : LATEPOINT_TRANSACTION_KIND_CAPTURE;
						} else {
							// payment error
							$result['status'] = LATEPOINT_STATUS_ERROR;
							$result['message'] = __('Payment Error', 'latepoint');
							$order_intent->add_error('payment_error', $result['message']);
							$order_intent->add_error('send_to_step', $result['message'], 'payment');
						}
					} else {
						// payment token missing
						$result['status'] = LATEPOINT_STATUS_ERROR;
						$result['message'] = __('Payment Error 23JDF38', 'latepoint');
						$order_intent->add_error('payment_error', $result['message']);
					}
					break;
			}
		}
		return $result;
	}


	public static function convert_charge_amount_to_requirements($charge_amount, OsCartModel $cart) {
		if (OsPaymentsHelper::should_processor_handle_payment_for_cart(self::$processor_code, $cart)) {
			$charge_amount = self::convert_amount_to_specs($charge_amount);
		}
		return $charge_amount;
	}

    public static function convert_amount_to_specs($charge_amount){
        $iso_code = self::get_currency_iso_code();
        if (in_array($iso_code, self::zero_decimal_currencies_list())) {
            $charge_amount = round($charge_amount);
        } else {
            $number_of_decimals = OsSettingsHelper::get_settings_value('number_of_decimals', '2');
            $charge_amount = number_format((float)$charge_amount, $number_of_decimals, '.', '') * pow(10, $number_of_decimals);
        }
        return $charge_amount;
    }

	/**
     * Converts amount from Stripe to database format
     *
	 * @param $charge_amount
	 *
	 * @return mixed|string
	 */
    public static function convert_amount_back_from_specs_to_db_format($charge_amount){
        $iso_code = self::get_currency_iso_code();
        $number_of_decimals = OsSettingsHelper::get_settings_value('number_of_decimals', '2');
        if (!in_array($iso_code, self::zero_decimal_currencies_list()) && !empty($number_of_decimals)) {
            $charge_amount = $charge_amount / pow(10, $number_of_decimals);
            $charge_amount = number_format((float)$charge_amount, 4, '.', '');
        }else{
            $charge_amount = OsMoneyHelper::pad_to_db_format($charge_amount);
        }
        return $charge_amount;
    }


	public static function output_order_payment_pay_contents(OsTransactionIntentModel $transaction_intent) {
		if (!OsPaymentsHelper::should_processor_handle_payment_for_transaction_intent(self::$processor_code, $transaction_intent)) return;
		echo '<div class="lp-payment-method-content" data-payment-method="payment_element">';
		echo '<div class="lp-payment-method-content-i">';
		echo '<div class="stripe-payment-element"></div>';
		echo '</div>';
		echo '</div>';
	}

	public static function output_payment_step_contents(OsCartModel $cart) {
		if (!OsPaymentsHelper::should_processor_handle_payment_for_cart(self::$processor_code, $cart)) return;
		echo '<div class="lp-payment-method-content" data-payment-method="payment_element">';
		echo '<div class="lp-payment-method-content-i">';
		echo '<div class="stripe-payment-element"></div>';
		echo '</div>';
		echo '</div>';
	}


	public static function get_supported_payment_methods() : array{
		return [
			'payment_element' => [
				'name' => __('Payment Element', 'latepoint'),
				'label' => __('Credit Card', 'latepoint'),
				'image_url' => LATEPOINT_IMAGES_URL . 'payment_cards.png',
			]
		];
	}

	public static function register_payment_processor(array $payment_processors) : array {
		$payment_processors[self::$processor_code] = [
			'code' => self::$processor_code,
			'name' => __('Stripe Connect', 'latepoint'),
			'front_name' => __('Stripe', 'latepoint'),
			'image_url' => LATEPOINT_IMAGES_URL . 'processor-stripe-connect.png'
		];
		return $payment_processors;
	}

	public static function add_settings_fields($processor_code) {
		if ($processor_code != self::$processor_code) return false; ?>
		<div class="sub-section-row">
			<div class="sub-section-label">
				<h3><?php esc_html_e('Connect (Live)', 'latepoint'); ?></h3>
			</div>
			<div class="sub-section-content">
				<div data-env="<?php echo esc_attr(LATEPOINT_PAYMENTS_ENV_LIVE); ?>"
				     class="payment-processor-connect-status-wrapper stripe-connect-status-wrapper"
				     data-route-name="<?php echo esc_attr(OsRouterHelper::build_route_name('stripe_connect', 'check_connect_status')); ?>">
					<div class="os-loading-spinner"></div>
				</div>
			</div>
		</div>
		<div class="sub-section-row">
			<div class="sub-section-label">
				<h3><?php esc_html_e('Connect (Dev)', 'latepoint'); ?></h3>
			</div>
			<div class="sub-section-content">
				<div data-env="<?php echo esc_attr(LATEPOINT_PAYMENTS_ENV_DEV); ?>"
				     class="payment-processor-connect-status-wrapper stripe-connect-status-wrapper"
				     data-route-name="<?php echo esc_attr(OsRouterHelper::build_route_name('stripe_connect', 'check_connect_status')); ?>">
					<div class="os-loading-spinner"></div>
				</div>
			</div>
		</div>
		<div class="sub-section-row">
			<div class="sub-section-label">
				<h3><?php esc_html_e('Other Settings', 'latepoint'); ?></h3>
			</div>
			<div class="sub-section-content">
				<?php
				$selected_stripe_country_code = OsSettingsHelper::get_settings_value('stripe_connect_country_code', 'US');
				$selected_stripe_currency_iso_code = OsSettingsHelper::get_settings_value('stripe_connect_currency_iso_code', 'usd'); ?>
				<div class="os-row os-mb-2">
					<div class="os-col-6">
						<?php echo OsFormHelper::select_field('settings[stripe_connect_country_code]', __('Country', 'latepoint'), self::load_countries_list(), $selected_stripe_country_code); ?>
					</div>
					<div class="os-col-6">
						<?php echo OsFormHelper::select_field('settings[stripe_connect_currency_iso_code]', __('Currency Code', 'latepoint'), OsStripeConnectHelper::load_all_currencies_list(), $selected_stripe_currency_iso_code); ?>
					</div>
				</div>
			</div>
		</div>
		<?php
	}

	public static function get_stripe_customer_id(OsCustomerModel $customer) {
		return $customer->get_meta_by_key(OsSettingsHelper::append_payment_env_key('stripe_connect_customer_id'), '');
	}

	public static function save_stripe_customer_id(OsCustomerModel $customer, string $stripe_customer_id) {
		return $customer->save_meta_by_key(OsSettingsHelper::append_payment_env_key('stripe_connect_customer_id'), $stripe_customer_id);
	}


	public static function get_customer($stripe_customer_id): \LatePoint\Misc\StripeConnectCustomer {
		$response = self::do_account_request("customers/{$stripe_customer_id}");
		$stripe_connect_customer = new \LatePoint\Misc\StripeConnectCustomer();
		$stripe_connect_customer->id = $response['data']['id'];
		return $stripe_connect_customer;
	}

	public static function update_customer($stripe_customer_id, $customer, $values_to_update = array()) {
		$stripe_customer = self::get_customer($stripe_customer_id);
		if ($stripe_customer && $values_to_update) {
			foreach ($values_to_update as $key => $value) {
				if (in_array($key, self::get_properties_allowed_to_update())) {
					$stripe_customer->$key = $value;
				}
			}
			$stripe_customer->save();
		}
		return $stripe_customer;
	}

	public static function create_customer($customer) {
		$customer_data = [
			'email' => $customer->email,
			'name' => $customer->full_name
		];
		$response = self::do_account_request('customers', OsSettingsHelper::get_payments_environment(), '', 'POST', $customer_data);
		$result = ['id' => $response['data']['customer_id']];
		return $result;
	}


	public static function get_currency_iso_code() {
		return OsSettingsHelper::get_settings_value('stripe_connect_currency_iso_code', self::$default_currency_iso_code);
	}

	public static function get_server_token(string $force_env = ''): string {
		$key = OsSettingsHelper::append_payment_env_key('server_token_for_stripe_connect', $force_env);
		$server_token = OsSettingsHelper::get_settings_value($key, '');
		if (empty($server_token)) {
			$server_token = OsUtilHelper::generate_uuid();
			OsSettingsHelper::save_setting_by_name($key, $server_token);
		}
		return $server_token;
	}

	public static function get_connect_url(string $env = '') {
		$url = LATEPOINT_STRIPE_CONNECT_URL . '/wp/stripe-connection/' . $env . '/start/';
		$url .= self::get_server_token($env) . '/' . base64_encode(implode('|||', [get_bloginfo('name'), get_site_icon_url(), OsUtilHelper::get_site_url()]));
		return $url;
	}


	public static function do_account_request(string $path, string $env = '', string $connection_data = '', string $method = 'GET', array $vars = [], array $headers = []) {
		if (empty($env)) $env = OsSettingsHelper::get_payments_environment();
		$path = self::get_connect_account_id($env) . '/' . $path;
        try{
            return self::do_request($path, $connection_data, $method, $vars, $headers);
        }catch(\Exception $e){
            OsDebugHelper::log('Error processing request to Stripe: '.$e->getMessage(), 'stripe_connect_error');
            return [];
        }
	}

	public static function do_request(string $path, string $connection_data = '', string $method = 'GET', array $vars = [], array $headers = [], string $force_env = '') {

		$default_vars = [];
		$default_headers = [
			'latepoint-version' => LATEPOINT_VERSION,
			'latepoint-domain' => OsUtilHelper::get_site_url(),
			'latepoint-license-key' => OsLicenseHelper::get_license_key()
		];

		if (!empty($connection_data)) {
			$default_headers['connection-data'] = $connection_data;
		}


		$args = array(
			'timeout' => 15,
			'headers' => array_merge($default_headers, $headers),
			'body' => array_merge($default_vars, $vars),
			'sslverify' => false,
			'method' => $method
		);


        // in our connect server we use test/live, while latepoint plugin uses dev/live
        if(!empty($force_env) && in_array($force_env, [LATEPOINT_PAYMENTS_ENV_DEV, LATEPOINT_PAYMENTS_ENV_LIVE])){
            $env = ($force_env == LATEPOINT_PAYMENTS_ENV_DEV) ? 'test' : 'live';
        }else{
            $env = (OsSettingsHelper::is_env_payments_dev() ? 'test' : 'live');
        }
		$url = LATEPOINT_STRIPE_CONNECT_URL . "/api/wp/v1/stripe-connect/{$env}/{$path}";

		$response = wp_remote_request($url, $args);

		if (!is_wp_error($response)) {
			$data = json_decode(wp_remote_retrieve_body($response), true);
			$data['status'] = $response['response'];
			return $data;
		} else {
			$error_message = $response->get_error_message();
			throw new Exception($error_message);
		}
	}


	public static function get_connection_buttons_and_status(string $env = '') {
		$stripe_connect_account_id = OsSettingsHelper::get_settings_value(OsSettingsHelper::append_payment_env_key('stripe_connect_account_id', $env), false);
		$html = '';
		if ($stripe_connect_account_id) {
			$charges_enabled = OsSettingsHelper::is_on(OsSettingsHelper::append_payment_env_key('stripe_connect_charges_enabled', $env));
			$disconnect_link = '<a class="payment-processor-disconnect-link" href="#"
										data-os-pass-response="yes"
										data-os-pass-this="yes"  
		                data-os-before-after="none" 
		                data-os-after-call="latepointStripeConnectAdmin.reload_connect_status_wrapper"
		                data-os-params="' . OsUtilHelper::build_os_params(['env' => $env]) . '"
										data-os-action="' . OsRouterHelper::build_route_name('stripe_connect', 'disconnect_connect_account') . '"
										><i class="latepoint-icon latepoint-icon-x"></i><span>' . __('disconnect', 'latepoint') . '</span></a>';
			if ($charges_enabled) {
				$html .= '<div class="payment-processor-status-connected"><i class="latepoint-icon latepoint-icon-check"></i><span>' . __('Connected', 'latepoint') . '</span></div>';
				$html .= $disconnect_link;
				$html .= '<div class="stripe-connect-account-info">'.__('Account: ', 'latepoint') . $stripe_connect_account_id . '</div>';
                if($env == 'live' && !empty(OsSettingsHelper::get_settings_value('stripe_connect_transaction_fee_info', ''))){
                    $html .='<div class="fee-disclosure-wrapper">
                        <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>
                    </div>';
                }
			} else {
				$html .= '<div class="payment-processor-status-charges-disabled"><i class="latepoint-icon latepoint-icon-clock"></i><span>' . __('Pending Action', 'latepoint') . '</span></div>';
				$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>';
				$html .= '<div class="stripe-connect-account-info">';
				$html .= '<div>' . $stripe_connect_account_id . '</div>';
				$html .= $disconnect_link;
				$html .= '</div>';
			}

		} else {
			$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>';
		}
		return $html;
	}

	public static function retrieve_payment_intent(string $payment_intent_id): array {
		$payment_request_data = self::do_account_request('payment-intents/' . $payment_intent_id, OsSettingsHelper::get_payments_environment());
		$result = ['id' => $payment_request_data['data']['id'], 'status' => $payment_request_data['data']['status'], 'total' => $payment_request_data['data']['total']];
		return $result;
	}

	private static function get_properties_allowed_to_update($roles = 'admin') {
		return array('source', 'email', 'name');
	}

	public static function get_connect_publishable_key(): string {
		$key = OsSettingsHelper::get_settings_value(OsSettingsHelper::append_payment_env_key('stripe_connect_publishable_key'), '');
		if (empty($key)) {
			$response = self::do_request('public-key/');
			$key = $response['data']['key'];
			OsSettingsHelper::save_setting_by_name(OsSettingsHelper::append_payment_env_key('stripe_connect_publishable_key'), $key);
		}
		return $key;
	}

	public static function zero_decimal_currencies_list() {
		return array('bif', 'clp', 'djf', 'gnf', 'jpy', 'kmf', 'krw', 'mga', 'pyg', 'rwf', 'ugx', 'vnd', 'vuv', 'xaf', 'xof', 'xpf');
	}


	public static function load_countries_list() {
		$country_codes = ['AU' => 'Australia',
			'AT' => 'Austria',
			'BE' => 'Belgium',
			'BR' => 'Brazil',
			'BG' => 'Bulgaria',
			'CA' => 'Canada',
			'HR' => 'Croatia',
			'CY' => 'Cyprus',
			'CZ' => 'Czech Republic',
			'DK' => 'Denmark',
			'EE' => 'Estonia',
			'FI' => 'Finland',
			'FR' => 'France',
			'DE' => 'Germany',
			'GI' => 'Gibraltar',
			'GR' => 'Greece',
			'HK' => 'Hong Kong',
			'HU' => 'Hungary',
			'IN' => 'India',
			'IE' => 'Ireland',
			'IT' => 'Italy',
			'JP' => 'Japan',
			'LV' => 'Latvia',
			'LI' => 'Liechtenstein',
			'LT' => 'Lithuania',
			'LU' => 'Luxembourg',
			'MY' => 'Malaysia',
			'MT' => 'Malta',
			'MX' => 'Mexico',
			'NL' => 'Netherlands',
			'NZ' => 'New Zealand',
			'NO' => 'Norway',
			'PL' => 'Poland',
			'PT' => 'Portugal',
			'RO' => 'Romania',
			'SG' => 'Singapore',
			'SK' => 'Slovakia',
			'SI' => 'Slovenia',
			'ES' => 'Spain',
			'SE' => 'Sweden',
			'CH' => 'Switzerland',
			'TH' => 'Thailand',
			'AE' => 'United Arab Emirates',
			'GB' => 'United Kingdom',
			'US' => 'United States'];
		return $country_codes;
	}


	public static function load_all_currencies_list(): array {
		return ['usd' => 'United States Dollar',
    'aed' => 'United Arab Emirates Dirham',
    'afn' => 'Afghan Afghani',
    'all' => 'Albanian Lek',
    'amd' => 'Armenian Dram',
    'ang' => 'Netherlands Antillean Guilder',
    'aoa' => 'Angolan Kwanza',
    'ars' => 'Argentine Peso',
    'aud' => 'Australian Dollar',
    'awg' => 'Aruban Florin',
    'azn' => 'Azerbaijani Manat',
    'bam' => 'Bosnia-Herzegovina Convertible Mark',
    'bbd' => 'Barbadian Dollar',
    'bdt' => 'Bangladeshi Taka',
    'bgn' => 'Bulgarian Lev',
    'bif' => 'Burundian Franc',
    'bmd' => 'Bermudian Dollar',
    'bnd' => 'Brunei Dollar',
    'bob' => 'Bolivian Boliviano',
    'brl' => 'Brazilian Real',
    'bsd' => 'Bahamian Dollar',
    'bwp' => 'Botswana Pula',
    'bzd' => 'Belize Dollar',
    'cad' => 'Canadian Dollar',
    'cdf' => 'Congolese Franc',
    'chf' => 'Swiss Franc',
    'clp' => 'Chilean Peso',
    'cny' => 'Chinese Yuan',
    'cop' => 'Colombian Peso',
    'crc' => 'Costa Rican Colón',
    'cve' => 'Cape Verdean Escudo',
    'czk' => 'Czech Koruna',
    'djf' => 'Djiboutian Franc',
    'dkk' => 'Danish Krone',
    'dop' => 'Dominican Peso',
    'dzd' => 'Algerian Dinar',
    'egp' => 'Egyptian Pound',
    'etb' => 'Ethiopian Birr',
    'eur' => 'Euro',
    'fjd' => 'Fijian Dollar',
    'fkp' => 'Falkland Islands Pound',
    'gbp' => 'British Pound Sterling',
    'gel' => 'Georgian Lari',
    'gip' => 'Gibraltar Pound',
    'gmd' => 'Gambian Dalasi',
    'gnf' => 'Guinean Franc',
    'gtq' => 'Guatemalan Quetzal',
    'gyd' => 'Guyanese Dollar',
    'hkd' => 'Hong Kong Dollar',
    'hnl' => 'Honduran Lempira',
    'hrk' => 'Croatian Kuna',
    'htg' => 'Haitian Gourde',
    'huf' => 'Hungarian Forint',
    'idr' => 'Indonesian Rupiah',
    'ils' => 'Israeli New Shekel',
    'inr' => 'Indian Rupee',
    'isk' => 'Icelandic Króna',
    'jmd' => 'Jamaican Dollar',
    'jpy' => 'Japanese Yen',
    'kes' => 'Kenyan Shilling',
    'kgs' => 'Kyrgyzstani Som',
    'khr' => 'Cambodian Riel',
    'kmf' => 'Comorian Franc',
    'krw' => 'South Korean Won',
    'kyd' => 'Cayman Islands Dollar',
    'kzt' => 'Kazakhstani Tenge',
    'lak' => 'Lao Kip',
    'lbp' => 'Lebanese Pound',
    'lkr' => 'Sri Lankan Rupee',
    'lrd' => 'Liberian Dollar',
    'lsl' => 'Lesotho Loti',
    'mad' => 'Moroccan Dirham',
    'mdl' => 'Moldovan Leu',
    'mga' => 'Malagasy Ariary',
    'mkd' => 'Macedonian Denar',
    'mmk' => 'Myanmar Kyat',
    'mnt' => 'Mongolian Tögrög',
    'mop' => 'Macanese Pataca',
    'mro' => 'Mauritanian Ouguiya (pre-2018)',
    'mur' => 'Mauritian Rupee',
    'mvr' => 'Maldivian Rufiyaa',
    'mwk' => 'Malawian Kwacha',
    'mxn' => 'Mexican Peso',
    'myr' => 'Malaysian Ringgit',
    'mzn' => 'Mozambican Metical',
    'nad' => 'Namibian Dollar',
    'ngn' => 'Nigerian Naira',
    'nio' => 'Nicaraguan Córdoba',
    'nok' => 'Norwegian Krone',
    'npr' => 'Nepalese Rupee',
    'nzd' => 'New Zealand Dollar',
    'pab' => 'Panamanian Balboa',
    'pen' => 'Peruvian Sol',
    'pgk' => 'Papua New Guinean Kina',
    'php' => 'Philippine Peso',
    'pkr' => 'Pakistani Rupee',
    'pln' => 'Polish Złoty',
    'pyg' => 'Paraguayan Guarani',
    'qar' => 'Qatari Riyal',
    'ron' => 'Romanian Leu',
    'rsd' => 'Serbian Dinar',
    'rub' => 'Russian Ruble',
    'rwf' => 'Rwandan Franc',
    'sar' => 'Saudi Riyal',
    'sbd' => 'Solomon Islands Dollar',
    'scr' => 'Seychellois Rupee',
    'sek' => 'Swedish Krona',
    'sgd' => 'Singapore Dollar',
    'shp' => 'Saint Helena Pound',
    'sll' => 'Sierra Leonean Leone',
    'sos' => 'Somali Shilling',
    'srd' => 'Surinamese Dollar',
    'std' => 'São Tomé and Príncipe Dobra (pre-2018)',
    'svc' => 'Salvadoran Colón',
    'szl' => 'Swazi Lilangeni',
    'thb' => 'Thai Baht',
    'tjs' => 'Tajikistani Somoni',
    'top' => 'Tongan Paʻanga',
    'try' => 'Turkish Lira',
    'ttd' => 'Trinidad and Tobago Dollar',
    'twd' => 'New Taiwan Dollar',
    'tzs' => 'Tanzanian Shilling',
    'uah' => 'Ukrainian Hryvnia',
    'ugx' => 'Ugandan Shilling',
    'uyu' => 'Uruguayan Peso',
    'uzs' => 'Uzbekistani Som',
    'vnd' => 'Vietnamese Đồng',
    'vuv' => 'Vanuatu Vatu',
    'wst' => 'Samoan Tālā',
    'xaf' => 'Central African CFA Franc',
    'xcd' => 'East Caribbean Dollar',
    'xof' => 'West African CFA Franc',
    'xpf' => 'CFP Franc',
    'yer' => 'Yemeni Rial',
    'zar' => 'South African Rand',
    'zmw' => 'Zambian Kwacha'];
	}


	public static function get_connect_account_id(string $env = '') {
		if (empty($env)) $env = OsSettingsHelper::get_payments_environment();
		return OsSettingsHelper::get_settings_value(OsSettingsHelper::append_payment_env_key('stripe_connect_account_id', $env), '');
	}

	public static function generate_payment_intent_id_and_secret_for_transaction_intent(OsTransactionIntentModel $transaction_intent): array {
        $order = new OsOrderModel($transaction_intent->order_id);
		$customer_data = ['name' => $order->customer->full_name, 'email' => $order->customer->email];
		$options = [
			'amount' => $transaction_intent->specs_charge_amount,
			'currency' => self::get_currency_iso_code(),
			'stripe_customer_id' => self::get_stripe_customer_id($order->customer),
            'transaction_description' => esc_html__('Payment for Appointment', 'latepoint'),
			'metadata' => [
				'transaction_intent_key' => $transaction_intent->intent_key
			]
		];


		// pass customer data in case it needs to be created
		$result = self::do_account_request('payment-intents', OsSettingsHelper::get_payments_environment(), '', 'POST', ['payment_intent_options' => $options, 'customer_data' => $customer_data]);
		if (empty($result['data'])) {
            // translators: %s is the payment error
			$error_message = !empty($result['error']) ? sprintf(__('Payment Error: %s', 'latepoint'), esc_html($result['error'])) : __('Error generating payment intent for transaction', 'latepoint');
			OsDebugHelper::log($error_message);
			throw new Exception($error_message);
		} else {
			// 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
			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']);

			return ['id' => $result['data']['id'], 'client_secret' => $result['data']['client_secret']];
		}
	}

	public static function generate_payment_intent_id_and_secret_for_order_intent(OsOrderIntentModel $order_intent): array {
		$customer_data = ['name' => $order_intent->customer->full_name, 'email' => $order_intent->customer->email];
		$options = [
			'amount' => $order_intent->specs_charge_amount,
			'currency' => self::get_currency_iso_code(),
			'stripe_customer_id' => self::get_stripe_customer_id($order_intent->customer),
            'transaction_description' => esc_html__('Payment for Appointment', 'latepoint'),
			'metadata' => [
				'order_intent_key' => $order_intent->intent_key
			]
		];


		// pass customer data in case it needs to be created
		$result = self::do_account_request('payment-intents', OsSettingsHelper::get_payments_environment(), '', 'POST', ['payment_intent_options' => $options, 'customer_data' => $customer_data]);
		if (empty($result['data'])) {
            // translators: %s is the payment error
			$error_message = !empty($result['error']) ? sprintf(__('Payment Error: %s', 'latepoint'), esc_html($result['error'])) : __('Error generating payment intent', 'latepoint');
			OsDebugHelper::log($error_message);
			throw new Exception($error_message);
		} else {
			// 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
			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']);

			return ['id' => $result['data']['id'], 'client_secret' => $result['data']['client_secret']];
		}
	}

	public static function build_customer_profile_link(string $stripe_customer_id, bool $test_env = false): string {
		return 'https://dashboard.stripe.com/' . ($test_env ? 'test/' : '') . 'customers/' . $stripe_customer_id;
	}


	public static function transaction_is_refund_available($result, OsTransactionModel $transaction_model ): bool {
		if (OsPaymentsHelper::is_payment_processor_enabled( self::$processor_code ) && $transaction_model->processor == self::$processor_code) {
			$result = true;
		}
		return $result;
	}
}