Support » Plugin: GiveWP - Donation Plugin and Fundraising Platform » Multi-currency and multi-language

  • Resolved coppermill

    (@coppermill)


    I would like to add a second page for another donation is a second currency is this possible?

    Also can the plugin support multi languages too?

Viewing 15 replies - 1 through 15 (of 19 total)
  • Thread Starter coppermill

    (@coppermill)

    Wondering if anyone had any answers to this?

    +1

    I would really like to set-up a form in a second language/currency.

    Not sure if this will help, Coppermill, but I found this: https://givewp.com/documentation/resources/translating-give/

    Plugin Author Devin Walker

    (@dlocc)

    Hey @coppermill – We’re working on a currency switcher add-on which will allow users to switch to their preferred currency within the donation form. Though, it sounds like you want an entirely separate currency per form. I attempted to create an snippet for you but it looks like we’ll need to make some adjustments to the plugin prior to this working exactly how it should.

    I have created an issue for the per form currency request: https://github.com/WordImpress/Give/issues/1307 Please follow along on the development of the feature there.

    My apologies for the delay getting to this answer. Our entire team was out of town for WCUS. Please let me know if you have any questions!

    Thread Starter coppermill

    (@coppermill)

    Thank you Devin for getting back to me, I’ll watch GitHub with interest and see what happens

    Plugin Author Devin Walker

    (@dlocc)

    Sounds good @coppermill – Ping me if you have any additional questions 🙂

    Any progress on this? I’d love a plugin like this

    Hi there, thank you for a great plugin! I’m in desperate need of the “currency selection per form” functionality as well. Is there any chance of an eta perhaps?

    When you say “desperate”, how desperate are we talking? Because I currently have a client site of mine, cfoicheartland.com, accepting donations with Give in multiple currencies from both PayPal and credit cards, but it’s a crazy hack.

    As someone who has gotten this working, I can tell you that Give is 100% absolutely not built for multiple currencies right now. Adding a currency switcher broke a lot of Give’s functionality, and I only coded fixes for the specific features that I knew my client would care about – e-mails, transaction records, donation totals, PayPal Pro. So I have no idea how, say, donor totals are working right now, but it’s a safe bet they’re broken because I haven’t tested them. And I can’t verify that any payment gateways work with this except for PayPal Standard, PayPal Payments Pro and PayPal Website Payments Pro (REST API). As for other kinds of add-ons, your guess is as good as mine.

    I’ve also filtered the result of Give’s core give_currency() function. It was the only way to get PayPal Standard to acknowledge the chosen currency. So anywhere the templates use give_currency() to grab the currency from the options, I’ve replaced the function call with a hard-coded ‘USD’. You’d have to do something similar, to prevent all the currency symbols in your template denoting fixed amounts of money from changing after you’ve made a donation.

    Still, the bottom line is it works. (As of Give 1.8.5.) Donors choose a currency, pay in that currency, the e-mails that were relevant to my client’s needs correctly indicate which currency was used, and then a conversion to USD is made for the purposes of internal record-keeping, i.e. correct donation totals and transaction records, with a note indicating what the transaction’s value was in the original currency. So if you need this functionality now, you can look over what I’ve done.

    This code relies on functions from the plugin Open Currency Converter (https://wordpress.org/plugins/artiss-currency-converter/), so that would need to be installed.

    Anyway, here’s the code I’m using, which is specific to my client’s theme and needs but might have something you can co-opt:

    <?php
    define('ACCEPTED_CURRENCIES', serialize(array(
    	'USD',
    	'GBP',
    	'AUD',
    	'CAD',
    	'EUR'
    )));
    
    add_action('give_after_donation_levels', 'give_choose_currency_field', 10, 1);
    add_filter('give_currency', 'give_use_chosen_currency');
    
    function give_choose_currency_field($form_id){
    	//Add field to Give donation form to let user choose currency
    	?>
    		<a class="give-currency-link" href="javascript: void(0);" onclick='jQuery(this).next().animate({opacity:"toggle", height: "toggle"});'>Donate in another currency</a>
    		<div class="give-currency-wrap">
    			<div>
    				<?php foreach (unserialize(ACCEPTED_CURRENCIES) as $key => $cc) : ?>
    					<input type="radio" class="give-radio" name="give_currency" id="give_currency_<?php echo strtolower( $cc ); ?>" data-symbol="<?php echo give_currency_symbol($cc); ?>" value="<?php echo $cc; ?>"<?php if($key == 0) echo ' checked="checked"'; ?>>
    					<label class="give-label" for="give_currency_<?php echo strtolower( $cc ); ?>">
    						<?php
    							$flag_dir = get_stylesheet_directory_uri().'/images/flags/';
    						    $flag_file = strtolower( $cc ) . '.png';
    						    $flag_name = __( 'Flag', 'artiss-currency-converter' );
    						    if ( $codes_array[ $cc ] != '' ) { $flag_name = sprintf( __( 'Flag for %s', 'artiss-currency-converter' ), $codes_array[ $cc ] ); }
    
    						    echo '<img src="' . $flag_dir . $flag_file . '" alt="' . $flag_name . '" title="' . $flag_name . '" width="16px" height="11px">';
    					    	
    					    	echo give_currency_symbol($cc);
    					    	echo $cc;
    					    ?>
    					</label>
    				<?php endforeach; ?>
    			</div>
    		</div>
    		<script type="text/javascript">
    			var currency_symbol = jQuery('.give-currency-wrap input:checked').data('symbol');
    			jQuery('.give-currency-symbol').html(currency_symbol);
    			function give_fix_final_total_symbol(){
    				var currency_name = jQuery('.give-currency-wrap input:checked').val();
    				var final_amount = jQuery('.give-final-total-amount');
    				final_amount.html(currency_symbol+final_amount.data('total')+' '+currency_name);
    			}
    			jQuery('.give-currency-wrap input').change(function(){currency_symbol = jQuery(this).data('symbol'); jQuery('.give-currency-symbol').html(currency_symbol); give_fix_final_total_symbol();});
    			jQuery(document).on('give_gateway_loaded', give_fix_final_total_symbol);
    			jQuery(give_fix_final_total_symbol);
    		</script>
    	<?php
    }
    
    function give_use_chosen_currency($currency){
    	//Let the currency that the user chose in give_choose_currency_field() override the default.
    	//This affects the communication with the payment gateway (which makes it essential), but also
    	//a lot more, e.g. the currency sign in donation totals in the default templates.
    	$session = give_get_purchase_session();
    	if(!empty($session) && isset($session['post_data']['give_currency']) && (in_array($session['post_data']['give_currency'], unserialize(ACCEPTED_CURRENCIES)))){
    		$currency = $session['post_data']['give_currency'];
    	}
    	return $currency;
    }
    
    add_filter('give_paypalpro_rest_payment_args', 'give_use_chosen_currency_for_rest');
    function give_use_chosen_currency_for_rest($args){
    	//The PayPal REST API handles the data a little bit differently than the other payment methods.
    
    	$args['currency_code'] = give_use_chosen_currency($args['currency_code']);
    	return $args;
    
    }
    
    function give_insert_with_chosen_currency($payment_id, $payment_data){
    	$currency = give_use_chosen_currency($payment_data['currency']);
    	if($payment_data['currency'] != $currency){
    		$payment = new Give_Payment($payment_id);
    		$payment->currency = $currency;
    		$payment->save();
    	}
    }
    add_action('give_insert_payment', 'give_insert_with_chosen_currency', 1, 2);
    
    add_action( 'give_pre_complete_purchase', 'give_correct_form_earnings_from_foreign_currencies', 10, 1 );
    
    function give_correct_form_earnings_from_foreign_currencies($payment_id){
    	/*  There aren't any hooks (as of Give 1.6.3) on the amount the earnings are increased by,
    		so no matter what is done here,	Give is going to be adding the wrong amount to the earnings
    		whenever a payment in a foreign currency comes in. For instance, if someone donates £100 GBP,
    		and the exchange rate is £1.24 GBP = $1 USD, the give_complete_donation() function is going to
    		use the default currency and add $100 USD to the earnings. So what this function does is add the
    		difference. In our example, the earnings will be off by $24, so this adds those $24.	*/
    
    	if(!function_exists('get_conversion')){ //This relies on Artiss Open Currency Converter.
    		if(is_admin() && function_exists('occ_rates')){
    			//The only reason we don't have the functions is because we're in admin. Load them:
    			if(is_file(WP_PLUGIN_DIR . '/artiss-currency-converter/includes/functions.php') &&
    			   is_file(WP_PLUGIN_DIR . '/artiss-currency-converter/includes/shortcodes.php')){
    				include_once(WP_PLUGIN_DIR . '/artiss-currency-converter/includes/functions.php');
    				include_once(WP_PLUGIN_DIR . '/artiss-currency-converter/includes/shortcodes.php');
    			}
    			else{
    				return;
    			}
    		}
    		else{
    			return;
    		}
    	}
    
    	$payment = new Give_Payment($payment_id);
    	$customer = new Give_Customer($payment->customer_id);
    
    	if($payment->currency == 'USD') return; //No conversion necessary.
    
    	$usdvalue = get_conversion('number='.$payment->total.'&from='.$payment->currency.'&to=usd');
    	$difference = $usdvalue - $payment->total;
    
    	give_increase_earnings( $payment->form_id, $difference );
    	$customer->increase_value( $difference );
    	give_increase_total_earnings( $difference );
    
    	$payment->update_meta('usd_value', $usdvalue);
    	$payment->update_meta('real_value',give_currency_symbol($payment->currency).$payment->total.' '.$payment->currency);
    }
    
    add_action( 'give_complete_donation', 'give_withhold_total', 1 );
    
    function give_withhold_total($payment_id){
    	/*	For the purposes of clean record-keeping, the donation will be saved in USD. This cannot be
    		done until after the last $payment->save() is initiated by the payment gateway - otherwise,
    		the gateway will revert our changes. Therefore (and apologies for the hackiness) we're going
    		to erase the total completely, and when it re-emerges (because the payment gateway is
    		overwriting the change) we will know it is safe to set the correct USD amount.
    	*/
    
    	if(!function_exists('get_conversion')) return; //This relies on Artiss Open Currency Converter.
    
    	$payment = new Give_Payment($payment_id);
    
    	if($payment->currency == 'USD') return;
    	
    	update_post_meta($payment_id, '_give_payment_total', 0);
    }
    
    add_action('give_setup_payment', 'give_use_usd_value_for_records');
    
    function give_use_usd_value_for_records($payment){
    
    	if($payment->currency == 'USD') {
    		//This is already in USD, so no change is needed.
    		return;
    	}
    
    	if(!isset($payment->completed_date)){
    		//The process has not yet been completed.
    		return;
    	}
    
    	if($payment->old_status != 'pending'){
    		//This is a newer version of the Give_Payment object than the gateway's.
    		//(If there is a flaw in my hacky logic, it is probably here.)
    		return;
    	}
    
    	if($payment->total == 0){
    		//The process has officially completed, but the gateway hasn't rewritten the object yet.
    		return;
    	}
    
    	$usd_value = $payment->get_meta('usd_value');
    	$real_value = $payment->get_meta('real_value');
    
    	$payment->add_note('This donation was made in a foreign currency: '.$real_value);
    
    	$payment->subtotal = $usd_value;
    	$payment->total = $payment->subtotal + $payment->fees_total;
    	$payment->currency = 'USD';
    	$payment->save();
    }
    
    add_filter('give_donation_receipt', 'give_correct_receipt_email_value', 10, 3);
    
    function give_correct_receipt_email_value($email_body, $payment_id, $payment_data){
    	if($payment_data['currency'] != 'USD'){
    		$real_value = get_post_meta($payment_id, 'real_value', true) ?: '';
    		$email_body = str_replace(array('{price}', '{amount}'), html_entity_decode($real_value, ENT_COMPAT, 'UTF-8'), $email_body);
    	}
    	return $email_body;
    }
    
    add_filter('give_donation_notification', 'give_correct_notification_email_value', 10, 3);
    
    function give_correct_notification_email_value($email_body, $payment_id, $payment_data){
    	if($payment_data['currency'] == 'USD'){
    		$email_body = str_replace('{real_price}', '$' . give_format_amount( give_get_payment_amount( $payment_id ) ) , $email_body) . 'USD';
    	}
    	else{
    		$real_value = get_post_meta($payment_id, 'real_value', true) ?: '';
    		$usd_value = get_post_meta($payment_id, 'usd_value', true) ?: '';
    		$email_body = str_replace('{real_price}', html_entity_decode($real_value, ENT_COMPAT, 'UTF-8') . ' ($' . html_entity_decode(give_format_amount($usd_value), ENT_COMPAT, 'UTF-8') . ' USD)' , $email_body);
    	}
    	return $email_body;
    }
    
    /**
     * Donation Amount Field.
     *
     * Outputs the donation amount field that appears at the top of the donation forms. If the user has custom amount
     * enabled the field will output as a customizable input.
     *
     * @since  1.0
     *
     * @param  int   $form_id The form ID.
     * @param  array $args    An array of form arguments.
     *
     * @return void
     */
    function give_output_modified_donation_amount_top( $form_id = 0, $args = array() ) {
    
    	$give_options        = give_get_settings();
    	$variable_pricing    = give_has_variable_prices( $form_id );
    	$allow_custom_amount = get_post_meta( $form_id, '_give_custom_amount', true );
    	$currency_position   = isset( $give_options['currency_position'] ) ? $give_options['currency_position'] : 'before';
    
    	//This line is the modified part of this function:
    	$symbol              = '$';
    
    	$currency_output     = '<span class="give-currency-symbol give-currency-position-' . $currency_position . '">' . $symbol . '</span>';
    	$default_amount      = give_format_amount( give_get_default_form_amount( $form_id ) );
    	$custom_amount_text  = get_post_meta( $form_id, '_give_custom_amount_text', true );
    
    	/**
    	 * Fires while displaying donation form, before donation level fields.
    	 *
    	 * @since 1.0
    	 *
    	 * @param int   $form_id The form ID.
    	 * @param array $args    An array of form arguments.
    	 */
    	do_action( 'give_before_donation_levels', $form_id, $args );
    
    	//Set Price, No Custom Amount Allowed means hidden price field
    	if ( ! give_is_setting_enabled( $allow_custom_amount ) ) {
    		?>
            <label class="give-hidden" for="give-amount-hidden"><?php esc_html_e( 'Donation Amount:', 'give' ); ?></label>
            <input id="give-amount" class="give-amount-hidden" type="hidden" name="give-amount"
                   value="<?php echo $default_amount; ?>" required aria-required="true"/>
            <div class="set-price give-donation-amount form-row-wide">
    			<?php if ( $currency_position == 'before' ) {
    				echo $currency_output;
    			} ?>
                <span id="give-amount-text" class="give-text-input give-amount-top"><?php echo $default_amount; ?></span>
    			<?php if ( $currency_position == 'after' ) {
    				echo $currency_output;
    			} ?>
            </div>
    		<?php
    	} else {
    		//Custom Amount Allowed.
    		?>
            <div class="give-total-wrap">
                <div class="give-donation-amount form-row-wide">
    				<?php if ( $currency_position == 'before' ) {
    					echo $currency_output;
    				} ?>
                    <label class="give-hidden" for="give-amount"><?php esc_html_e( 'Donation Amount:', 'give' ); ?></label>
                    <input class="give-text-input give-amount-top" id="give-amount" name="give-amount" type="tel"
                           placeholder="" value="<?php echo $default_amount; ?>" autocomplete="off">
    				<?php if ( $currency_position == 'after' ) {
    					echo $currency_output;
    				} ?>
                </div>
            </div>
    	<?php }
    
    	/**
    	 * Fires while displaying donation form, after donation amounf field(s).
    	 *
    	 * @since 1.0
    	 *
    	 * @param int   $form_id The form ID.
    	 * @param array $args    An array of form arguments.
    	 */
    	do_action( 'give_after_donation_amount', $form_id, $args );
    
    	//Custom Amount Text
    	if ( ! $variable_pricing && give_is_setting_enabled( $allow_custom_amount ) && ! empty( $custom_amount_text ) ) { ?>
            <p class="give-custom-amount-text"><?php echo $custom_amount_text; ?></p>
    	<?php }
    
    	//Output Variable Pricing Levels.
    	if ( $variable_pricing ) {
    		give_output_levels( $form_id );
    	}
    
    	/**
    	 * Fires while displaying donation form, after donation level fields.
    	 *
    	 * @since 1.0
    	 *
    	 * @param int   $form_id The form ID.
    	 * @param array $args    An array of form arguments.
    	 */
    	do_action( 'give_after_donation_levels', $form_id, $args );
    }
    
    remove_action( 'give_checkout_form_top', 'give_output_donation_amount_top', 10, 2 );
    add_action( 'give_checkout_form_top', 'give_output_modified_donation_amount_top', 10, 2 );
    ?>
    • This reply was modified 4 years, 6 months ago by buxner.

    Since you’re looking for a per-form currency setting rather than giving users the option, you could replace the inputs in give_choose_currency_field() with a hidden field that grabs the currency from post meta, and make a meta box to set that currency on a per-post basis.

    Plugin Author Matt Cromwell

    (@webdevmattcrom)

    Thanks @buxner and @jefjones for chiming in on this issue. I’d like to hear your perspectives on why submitting donations in different currencies is important to you and/or your clients. Generally speaking, you can display whatever currency you want on the form, but in the end it’s up to your payment gateway to support that currency and to either convert it to your banks currency or accept it directly.

    For example, if you are in the U.S. and show that you accept donations in US Dollars or Canadian dollars, and you are using PayPal, if the donor chooses Canadian dollars you will still end up receiving US Dollars because that is the currency your PayPal account is setup with.

    With that in mind, please clarify if you are wanting to support multiple currencies at the Gateway level (which would depend 100% on gateway support) or simply display and accept the amount in different currencies on the fly.

    Thanks!

    Thread Starter coppermill

    (@coppermill)

    The issue this would resolve is that on a multi-language website it is important to show the currency for that country. Many of our people wanting to give donations question when it is not in their currency.

    With regards to the gateway, ie PayPal, this accepts payment in whichever currency has been chosen.

    Also, I have found that changing currency in the setting, just changes the currency notation and any values that already stored in the Donation section switch to that currency, but the value remains the same.

    Plugin Author Matt Cromwell

    (@webdevmattcrom)

    Thanks for your feedback @coppermill we’ll take it into account as we work on this feature.

    Hi Matt,

    Apart from multi-language sites (as @coppermill suggests) it is also useful to hold money in a PayPal a/c in multiple currencies for using those currencies – for ‘foreign’ expenses, purchases, transfers etc. – rather than exchanging to the local currency. We hold donations as USD, GBP and our local currency EUR. Since we started using Give for donations via PayPal we have of course not received any other currency donations which has been noted – people like to donate in their local currency and we like to receive their donation in the currency they choose. It also has ‘tax effective giving’ consequences.

    Éamonn

    shezarsrpm

    (@shezarsrpm)

    @coppermill & @webdevmattcrom, do you have an answer to the Multi currency feature that I am looking for – https://wordpress.org/support/topic/multi-currency-in-donation/?

Viewing 15 replies - 1 through 15 (of 19 total)
  • The topic ‘Multi-currency and multi-language’ is closed to new replies.