You cannot select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

580 lines
16 KiB
PHP

This file contains ambiguous Unicode characters!

This file contains ambiguous Unicode characters that may be confused with others in your current locale. If your use case is intentional and legitimate, you can safely ignore this warning. Use the Escape button to highlight these characters.

<?php
/**
* Payment related functions.
*
* @since 1.8.2
*/
/**
* Get supported currencies.
*
* @since 1.2.4
*
* @return array
*/
function wpforms_get_currencies() {
$currencies = [
'USD' => [
'name' => esc_html__( 'U.S. Dollar', 'wpforms-lite' ),
'symbol' => '&#36;',
'symbol_pos' => 'left',
'thousands_separator' => ',',
'decimal_separator' => '.',
'decimals' => 2,
],
'GBP' => [
'name' => esc_html__( 'Pound Sterling', 'wpforms-lite' ),
'symbol' => '&pound;',
'symbol_pos' => 'left',
'thousands_separator' => ',',
'decimal_separator' => '.',
'decimals' => 2,
],
'EUR' => [
'name' => esc_html__( 'Euro', 'wpforms-lite' ),
'symbol' => '&euro;',
'symbol_pos' => 'right',
'thousands_separator' => '.',
'decimal_separator' => ',',
'decimals' => 2,
],
'AUD' => [
'name' => esc_html__( 'Australian Dollar', 'wpforms-lite' ),
'symbol' => '&#36;',
'symbol_pos' => 'left',
'thousands_separator' => ',',
'decimal_separator' => '.',
'decimals' => 2,
],
'BRL' => [
'name' => esc_html__( 'Brazilian Real', 'wpforms-lite' ),
'symbol' => 'R$',
'symbol_pos' => 'left',
'thousands_separator' => '.',
'decimal_separator' => ',',
'decimals' => 2,
],
'CAD' => [
'name' => esc_html__( 'Canadian Dollar', 'wpforms-lite' ),
'symbol' => '&#36;',
'symbol_pos' => 'left',
'thousands_separator' => ',',
'decimal_separator' => '.',
'decimals' => 2,
],
'CZK' => [
'name' => esc_html__( 'Czech Koruna', 'wpforms-lite' ),
'symbol' => '&#75;&#269;',
'symbol_pos' => 'right',
'thousands_separator' => '.',
'decimal_separator' => ',',
'decimals' => 2,
],
'DKK' => [
'name' => esc_html__( 'Danish Krone', 'wpforms-lite' ),
'symbol' => 'kr.',
'symbol_pos' => 'right',
'thousands_separator' => '.',
'decimal_separator' => ',',
'decimals' => 2,
],
'HKD' => [
'name' => esc_html__( 'Hong Kong Dollar', 'wpforms-lite' ),
'symbol' => '&#36;',
'symbol_pos' => 'left',
'thousands_separator' => ',',
'decimal_separator' => '.',
'decimals' => 2,
],
'HUF' => [
'name' => esc_html__( 'Hungarian Forint', 'wpforms-lite' ),
'symbol' => 'Ft',
'symbol_pos' => 'right',
'thousands_separator' => '.',
'decimal_separator' => ',',
'decimals' => 2,
],
'ILS' => [
'name' => esc_html__( 'Israeli New Sheqel', 'wpforms-lite' ),
'symbol' => '&#8362;',
'symbol_pos' => 'left',
'thousands_separator' => ',',
'decimal_separator' => '.',
'decimals' => 2,
],
'MYR' => [
'name' => esc_html__( 'Malaysian Ringgit', 'wpforms-lite' ),
'symbol' => '&#82;&#77;',
'symbol_pos' => 'left',
'thousands_separator' => ',',
'decimal_separator' => '.',
'decimals' => 2,
],
'MXN' => [
'name' => esc_html__( 'Mexican Peso', 'wpforms-lite' ),
'symbol' => '&#36;',
'symbol_pos' => 'left',
'thousands_separator' => ',',
'decimal_separator' => '.',
'decimals' => 2,
],
'NOK' => [
'name' => esc_html__( 'Norwegian Krone', 'wpforms-lite' ),
'symbol' => 'Kr',
'symbol_pos' => 'left',
'thousands_separator' => '.',
'decimal_separator' => ',',
'decimals' => 2,
],
'NZD' => [
'name' => esc_html__( 'New Zealand Dollar', 'wpforms-lite' ),
'symbol' => '&#36;',
'symbol_pos' => 'left',
'thousands_separator' => ',',
'decimal_separator' => '.',
'decimals' => 2,
],
'PHP' => [
'name' => esc_html__( 'Philippine Peso', 'wpforms-lite' ),
'symbol' => 'Php',
'symbol_pos' => 'left',
'thousands_separator' => ',',
'decimal_separator' => '.',
'decimals' => 2,
],
'PLN' => [
'name' => esc_html__( 'Polish Zloty', 'wpforms-lite' ),
'symbol' => '&#122;&#322;',
'symbol_pos' => 'left',
'thousands_separator' => '.',
'decimal_separator' => ',',
'decimals' => 2,
],
'RUB' => [
'name' => esc_html__( 'Russian Ruble', 'wpforms-lite' ),
'symbol' => 'pyб',
'symbol_pos' => 'right',
'thousands_separator' => ' ',
'decimal_separator' => '.',
'decimals' => 2,
],
'SGD' => [
'name' => esc_html__( 'Singapore Dollar', 'wpforms-lite' ),
'symbol' => '&#36;',
'symbol_pos' => 'left',
'thousands_separator' => ',',
'decimal_separator' => '.',
'decimals' => 2,
],
'ZAR' => [
'name' => esc_html__( 'South African Rand', 'wpforms-lite' ),
'symbol' => 'R',
'symbol_pos' => 'left',
'thousands_separator' => ',',
'decimal_separator' => '.',
'decimals' => 2,
],
'SEK' => [
'name' => esc_html__( 'Swedish Krona', 'wpforms-lite' ),
'symbol' => 'Kr',
'symbol_pos' => 'right',
'thousands_separator' => '.',
'decimal_separator' => ',',
'decimals' => 2,
],
'CHF' => [
'name' => esc_html__( 'Swiss Franc', 'wpforms-lite' ),
'symbol' => 'CHF',
'symbol_pos' => 'left',
'thousands_separator' => ',',
'decimal_separator' => '.',
'decimals' => 2,
],
'TWD' => [
'name' => esc_html__( 'Taiwan New Dollar', 'wpforms-lite' ),
'symbol' => '&#36;',
'symbol_pos' => 'left',
'thousands_separator' => ',',
'decimal_separator' => '.',
'decimals' => 2,
],
'THB' => [
'name' => esc_html__( 'Thai Baht', 'wpforms-lite' ),
'symbol' => '&#3647;',
'symbol_pos' => 'left',
'thousands_separator' => ',',
'decimal_separator' => '.',
'decimals' => 2,
],
];
/**
* Filter for currencies supported in WPForms payments.
*
* @since 1.2.4
*
* @param array $currencies List of currencies.
*/
return array_change_key_case( (array) apply_filters( 'wpforms_currencies', $currencies ), CASE_UPPER );
}
/**
* Sanitize amount by stripping out thousands separators.
*
* @link https://github.com/easydigitaldownloads/easy-digital-downloads/blob/master/includes/formatting.php#L24
*
* @since 1.2.6
*
* @param string $amount Price amount.
* @param string $currency Currency ISO code (USD, EUR, etc).
*
* @return string $amount
*/
function wpforms_sanitize_amount( $amount, $currency = '' ) { // phpcs:ignore Generic.Metrics.CyclomaticComplexity.TooHigh
if ( empty( $currency ) ) {
$currency = wpforms_get_currency();
}
$currency = strtoupper( $currency );
$currencies = wpforms_get_currencies();
$thousands_sep = isset( $currencies[ $currency ]['thousands_separator'] ) ? $currencies[ $currency ]['thousands_separator'] : ',';
$decimal_sep = isset( $currencies[ $currency ]['decimal_separator'] ) ? $currencies[ $currency ]['decimal_separator'] : '.';
// Sanitize the amount.
if ( $decimal_sep === ',' && strpos( $amount, $decimal_sep ) !== false ) {
if ( ( $thousands_sep === '.' || $thousands_sep === ' ' ) && strpos( $amount, $thousands_sep ) !== false ) {
$amount = str_replace( $thousands_sep, '', $amount );
} elseif ( empty( $thousands_sep ) && strpos( $amount, '.' ) !== false ) {
$amount = str_replace( '.', '', $amount );
}
$amount = str_replace( $decimal_sep, '.', $amount );
} elseif ( $thousands_sep === ',' && strpos( $amount, $thousands_sep ) !== false ) {
$amount = str_replace( $thousands_sep, '', $amount );
}
/**
* Remove any characters that are not a digit, a decimal point, or a minus sign.
*
* E is exponent notation. Float number can be written in the form 2E-13, which means 2 * 10^-13.
* 0-9 is digits.
* . is decimal point.
* - is minus sign.
*/
$amount = (string) preg_replace( '/[^E0-9.-]/', '', $amount );
/**
* Set correct currency decimals.
*
* @since 1.6.6
*
* @param int $decimals Default number of decimals.
* @param string $amount Price amount.
*/
$decimals = (int) apply_filters(
'wpforms_sanitize_amount_decimals',
wpforms_get_currency_decimals( $currency ),
$amount
);
return number_format( (float) $amount, $decimals, '.', '' );
}
/**
* Return a nicely formatted amount.
*
* @since 1.2.6
*
* @param string $amount Price amount.
* @param bool $symbol Currency symbol ($, €).
* @param string $currency Currency ISO code (USD, EUR, etc).
*
* @return string $amount Newly formatted amount or Price Not Available
*/
function wpforms_format_amount( $amount, $symbol = false, $currency = '' ) { // phpcs:ignore Generic.Metrics.CyclomaticComplexity.TooHigh
if ( empty( $currency ) ) {
$currency = wpforms_get_currency();
}
$currency = strtoupper( $currency );
$currencies = wpforms_get_currencies();
$thousands_sep = isset( $currencies[ $currency ]['thousands_separator'] ) ? $currencies[ $currency ]['thousands_separator'] : ',';
$decimal_sep = isset( $currencies[ $currency ]['decimal_separator'] ) ? $currencies[ $currency ]['decimal_separator'] : '.';
$sep_found = ! empty( $decimal_sep ) ? strpos( $amount, $decimal_sep ) : false;
// Format the amount.
if (
$decimal_sep === ',' &&
$sep_found !== false
) {
$whole = substr( $amount, 0, $sep_found );
$part = substr( $amount, $sep_found + 1, ( strlen( $amount ) - 1 ) );
$amount = $whole . '.' . $part;
}
// Strip "," (comma) from the amount (if set as the thousands' separator).
if (
$thousands_sep === ',' &&
strpos( $amount, $thousands_sep ) !== false
) {
$amount = (float) str_replace( ',', '', $amount );
}
if ( empty( $amount ) ) {
$amount = 0;
}
/** This filter is documented in wpforms_sanitize_amount function above. */
$decimals = (int) apply_filters(
'wpforms_sanitize_amount_decimals',
wpforms_get_currency_decimals( $currency ),
$amount
);
$number = number_format( (float) $amount, $decimals, $decimal_sep, $thousands_sep );
// Display a symbol, if any.
if ( $symbol && isset( $currencies[ $currency ]['symbol_pos'] ) ) {
/**
* Filter for currency symbol padding.
*
* @since 1.2.6
*
* @param string $symbol_padding Currency symbol padding.
*/
$symbol_padding = apply_filters( 'wpforms_currency_symbol_padding', ' ' );
if ( $currencies[ $currency ]['symbol_pos'] === 'right' ) {
$number .= $symbol_padding . $currencies[ $currency ]['symbol'];
} else {
$number = $currencies[ $currency ]['symbol'] . $symbol_padding . $number;
}
}
return $number;
}
/**
* Get default number of decimals for a given currency.
* If not provided inside the currency, default value is used, which is 2.
*
* @since 1.6.6
*
* @param array|string $currency Currency data we are getting decimals for.
*
* @return int
*/
function wpforms_get_currency_decimals( $currency ) {
if ( is_string( $currency ) ) {
$currencies = wpforms_get_currencies();
$currency_code = strtoupper( $currency );
$currency = isset( $currencies[ $currency_code ] ) ? $currencies[ $currency_code ] : [];
}
/**
* Get currency decimals.
*
* @since 1.6.6
*
* @param int $decimals Default number of decimals.
* @param array|string $currency Currency data we are getting decimals for.
*/
return (int) apply_filters(
'wpforms_get_currency_decimals',
isset( $currency['decimals'] ) ? $currency['decimals'] : 2,
$currency
);
}
/**
* Get payments currency.
* If the currency not available anymore 'USD' used as default.
*
* @since 1.6.6
*
* @return string
*/
function wpforms_get_currency() {
$currency = wpforms_setting( 'currency' );
$currencies = wpforms_get_currencies();
/**
* Get payments currency.
*
* @since 1.6.6
*
* @param string $currency Payments currency.
* @param array $currencies Available currencies.
*/
return apply_filters(
'wpforms_get_currency',
isset( $currencies[ $currency ] ) ? $currency : 'USD',
$currencies
);
}
/**
* Return recognized payment field types.
*
* @since 1.0.0
*
* @return array
*/
function wpforms_payment_fields() {
/**
* Filters the recognized payment field types.
*
* @since 1.0.0
*
* @param array $fields Payment field types.
*/
return (array) apply_filters(
'wpforms_payment_fields',
[ 'payment-single', 'payment-multiple', 'payment-checkbox', 'payment-select' ]
);
}
/**
* Check if form or entry contains payment.
*
* @since 1.0.0
*
* @param string $type Either 'entry' or 'form'.
* @param array $data List of form fields.
*
* @return bool
*/
function wpforms_has_payment( $type = 'entry', $data = [] ) {
$payment = false;
$payment_fields = wpforms_payment_fields();
if ( ! empty( $data['fields'] ) ) {
$data = $data['fields'];
}
if ( empty( $data ) ) {
return false;
}
foreach ( $data as $field ) {
if ( isset( $field['type'] ) && in_array( $field['type'], $payment_fields, true ) ) {
// For entries, only return true if the payment field has an amount.
if (
$type === 'form' ||
(
$type === 'entry' &&
! empty( $field['amount'] ) &&
! empty( wpforms_sanitize_amount( $field['amount'] ) )
)
) {
$payment = true;
break;
}
}
}
return $payment;
}
/**
* Check to see if a form has an active payment gateway configured.
*
* @since 1.4.5
*
* @param array $form_data Form data and settings.
*
* @return bool
*/
function wpforms_has_payment_gateway( $form_data ) {
// PayPal Standard check.
if ( ! empty( $form_data['payments']['paypal_standard']['enable'] ) ) {
return true;
}
// Stripe Check.
if ( ! empty( $form_data['payments']['stripe']['enable'] ) ) {
return true;
}
/**
* Allow modifying whether a form has an active payment gateway.
*
* @since 1.4.5
*
* @param bool $result True if a form has an active payment gateway.
* @param array $form_data Form data and settings.
*/
return (bool) apply_filters( 'wpforms_has_payment_gateway', false, $form_data );
}
/**
* Get payment total amount from entry.
*
* @since 1.0.0
* @since 1.8.2.2 Added PHP max() function before returning a total.
*
* @param array $fields List of fields.
*
* @return string
*/
function wpforms_get_total_payment( $fields ) {
$fields = wpforms_get_payment_items( $fields );
$total = 0;
if ( empty( $fields ) ) {
return false;
}
foreach ( $fields as $field ) {
if ( ! empty( $field['amount'] ) ) {
$amount = wpforms_sanitize_amount( $field['amount'] );
$total += $amount;
}
}
$total = max( 0, $total );
return wpforms_sanitize_amount( $total );
}
/**
* Get payment fields in an entry.
*
* @since 1.0.0
*
* @param array $fields List of fields.
*
* @return array|bool False if no fields provided, otherwise array.
*/
function wpforms_get_payment_items( $fields = [] ) {
if ( empty( $fields ) ) {
return false;
}
$payment_fields = wpforms_payment_fields();
foreach ( $fields as $id => $field ) {
if (
empty( $field['type'] ) ||
empty( $field['amount'] ) ||
! in_array( $field['type'], $payment_fields, true ) ||
empty( wpforms_sanitize_amount( $field['amount'] ) )
) {
// Remove all non-payment fields as well as payment fields with no amount.
unset( $fields[ $id ] );
}
}
return $fields;
}