WooCommerce

Woocommerce中文货币符号错误如何解决

Woocommerce对中文有那么一点支持,至少货币中可以找到我们的Chinese Yuan。不过讽刺的是,当你选择了人民币作为默认货币符号时,前台显示的确是英镑符号。

Note:该错误已经在Woocommerce 1.6.3版中修复,请升级到最新版本

为什么中文符号错误

这是个很小的错误,不知道为什么这么优秀的插件会犯这种简单的错误。

在woocommerce-core-functions.php中定义的get_woocommerce_currency_symbol()函数用来获取当前选择的货币的符号。并不复杂,只是一段简单的switch代码。

function get_woocommerce_currency_symbol( $currency = '' ) {
	if ( ! $currency ) $currency = get_woocommerce_currency();
	$currency_symbol = '';
	switch ($currency) :
		case 'BRL' : $currency_symbol = 'R$'; break;
		case 'AUD' : $currency_symbol = '$'; break;
		case 'CAD' : $currency_symbol = '$'; break;
		case 'MXN' : $currency_symbol = '$'; break;
		case 'NZD' : $currency_symbol = '$'; break;
		case 'HKD' : $currency_symbol = '$'; break;
		case 'SGD' : $currency_symbol = '$'; break;
		case 'USD' : $currency_symbol = '$'; break;
		case 'EUR' : $currency_symbol = '€'; break;
		case 'CNY' : $currency_symbol = '¥'; break;
		case 'JPY' : $currency_symbol = '¥'; break;
		case 'TRY' : $currency_symbol = 'TL'; break;
		case 'NOK' : $currency_symbol = 'kr'; break;
		case 'ZAR' : $currency_symbol = 'R'; break;
		case 'CZK' : $currency_symbol = 'Kč'; break;
		case 'MYR' : $currency_symbol = 'RM'; break;
		case 'DKK' : $currency_symbol = 'kr'; break;
		case 'HUF' : $currency_symbol = 'Ft'; break;
		case 'ILS' : $currency_symbol = '₪'; break;
		case 'PHP' : $currency_symbol = '₱'; break;
		case 'PLN' : $currency_symbol = 'zł'; break;
		case 'SEK' : $currency_symbol = 'kr'; break;
		case 'CHF' : $currency_symbol = 'CHF'; break;
		case 'TWD' : $currency_symbol = 'NT$'; break;
		case 'THB' : $currency_symbol = '฿'; break;
		case 'GBP' : $currency_symbol = '£'; break;
		default    : $currency_symbol = '£'; break;
	endswitch;
	return apply_filters( 'woocommerce_currency_symbol', $currency_symbol, $currency );
}

注意下面这行,就是定义人民币符号的,这里看不出有什么错误。

case 'CNY' : $currency_symbol = '¥'; break;

但在woocommerce/admin/settings/settings-init.php中定义的人民币代号并不是CNY,而是RMB

'RMB' => __( 'Chinese Yuan (¥)', 'woocommerce' ),

于是乎,当你选择人民币时,数据库存的其实是“RMB“而不是”CNY“,get_woocommerce_currency_symbol()函数找不到RMB这个东西,只好返回了默认符号英镑。

解决方法

知道错误的原因,解决方法也就一目了然了,把下面代码放到主题的functions.php中即可

if ( in_array( 'woocommerce/woocommerce.php', apply_filters( 'active_plugins', get_option( 'active_plugins' ) ) ) ) {

	add_filter('woocommerce_currency_symbol', 'fix_cn_currency_symbol', 10, 2);
	
	function fix_cn_currency_symbol( $currency_symbol, $currency ) {
		 if( $currency == 'RMB') return "&yen";
		 else return $currency_symbol;
	}
}

估计以后的版本会修正这个问题,但愿如此。

35条评论

  1. 我打印了woocommerce的classes\class-wc-checkout.php文件中$this->posted,发现里面所有的参数都为空,如下:
    Array ( [shiptobilling] => 0 [terms] => 0 [createaccount] => 0 [payment_method] => [shipping_method] => [billing_country] => [billing_first_name] => [billing_last_name] => [billing_company] => [billing_address_1] => [billing_address_2] => [billing_city] => [billing_state] => [billing_postcode] => [billing_email] => [billing_phone] => [account_username] => [account_password] => [account_password-2] => [order_comments] => ) Array ( [result] => failure [messages] =>

    但是抓包看,提交的时候确实带了这些参数,如下:
    billing_country=ST&billing_first_name=123123&billing_last_name=123123123123&billing_company=123123&billing_address_1=123123123123&billing_address_2=123123&billing_city=123123&billing_state=123123&billing_postcode=123123&billing_email=adf%40asdf.com&billing_phone=123123&payment_method=mycred&_n=a139a8438e&_wp_http_referer=%2Fwp37%2Fwp-admin%2Fadmin-ajax.php

    1. 貌似找到原因了,在mycred的gateway中,支付成功的时候会返回一个数组,如下:

      // Return the good news
      				return array(
      					'result'   => 'success',
      					'redirect' => $this->get_return_url( $order )
      				);
      

      注释掉这个的时候,上面的$this->posted就会有值了,但是还不能成功支付,继续找原因。

      1. 发现mycred确实是成功支付了,在class-wc-checkout.php的下面:

        					// Redirect to success/confirmation/payment page
        					if ( $result['result'] == 'success' ) {
        
        						$result = apply_filters('woocommerce_payment_successful_result', $result );
        
        						if ( is_ajax() ) {
        							echo '<!--WC_START-->' . json_encode( $result ) . '<!--WC_END-->';
        							exit;
        						} else {
        							wp_redirect( $result['redirect'] );
        							exit;
        						}
        
        					}
        

        当把

        $result = apply_filters('woocommerce_payment_successful_result', $result );
        

        改成:

        $result = "test";
        

        确实能打印test出来,可以看到是到woocommerce这边才出现的问题,而且应该是这个支付成功之后的感谢页面的问题,后面的woocommerce已经设置了感谢页的。奇怪。。

        1. 我装mycred试了,支付没有问题,订单状态成功变为processing。我的测试环境是
          php 5.2.9 (没到5.3,没有max_post_vars的问题)
          WordPress 3.7.1
          WooCommerce 2.0.20

          既然我这里正常,那就说明核心代码没有问题。或许跟服务器配置,你网站具体配置(插件主题etc.)有关,甚至可能是数据库有问题,这个不太好说。
          你看过WooCommerce的system status选项吗,有没有红色警告之类的?
          你提交订单以后,订单状态是否变成processing?
          Mycred的log中是否正确记录的订单?

          另外,订单是ajax方式提交的,你没有手动添加阻止普通用户访问后台的功能吧?

        2. 我也试了,问题可能是出现在wp_users里面,我现在wp_users里面有几千个用户,比如说有4000个,我删除了2000个,就能正常支付。

          我看了下system status选项,有两个红色告警:

          WP内存限制: 40 MB – We recommend setting memory to at least 64MB.
          WC 日志: 日志目录 (woocommerce/logs/)不可写入。日志将无法创建。

          不知道是不是这个原因,现在登不了服务器,待会看看。

          提交订单以后,订单状态是等待中,但是在Mycred的log中有订单的记录,并且mycred的积分减少了。

        3. 另外,订单是ajax方式提交的,你没有手动添加阻止普通用户访问后台的功能吧?

          没阻止,我是admin用户测试的。

        4. php 版本是5.3.24,难道是你说的max_post_vars的问题?想想应该不会,因为我删除了wp_users里面一些数据,就能支付了。

      2. 这个是payment gateway的正常写法,不应该注释掉,我好像没问你支付不成功的具体报错是什么?我装个mycred试试,我记得之前用没遇到过支付不成功的问题。

        1. 支付不成功报错如下:

          Array ( [result] => failure [messages] =>
          动作失败。请刷新页面然后重试。
          国家 为必填项
          名 为必填项
          姓 为必填项
          地址 为必填项
          Town / City 为必填项
          State / County 为必填项
          Postcode / Zip 为必填项
          Email 地址 为必填项
          电话 为必填项
          无效的支付方式。
          [refresh] => false )

      3. 建议你把内存增加到128m以上试试,数据库查询量大是很耗内存的,内存不足天知道哪里会出错。日志可不可写我想应该没啥影响。max_post_vars指一次可提交的变量数,默认的1000对你应该足够了。

        1. 测试将内存添加到128m,还是报一样的错,悲剧啊。怀疑是这句的问题

          $result = apply_filters(‘woocommerce_payment_successful_result’, $result );

        2. 我个人感觉不大可能,因为这句话对所有的payment gateway都有效,而且出问题的只是你站点的mycred支付网关。你应该先缩小一下范围,新装wordpress测试,没问题再导入你的用户测试,按照你说的2000个用户没错,4000个就有错,不是应该先从这里着手么。
          而且这只是一个filter,除非有函数使用了这个filter,否则它就是把result原样返回罢了。
          我觉得在怀疑核心代码之前,应该先逐步排除掉自己站点的因素,比如插件,主题,数据库等等。在新装环境下重现错误,就能解决。毕竟woocommerce是经过大量测试的,这句话出问题的概率基本不可能。

        3. 我再测试下,目前是两套系统,线上一套,线下一套,线下的全新装的wp,3.7.1,任何插件没有安装,如果本地只有一个admin用户的话,支付是不会存在任何问题,但是一导入线上wp_users里面的数据,支付的时候就会报错。悲哀啊。

        4. 也就是说基本可以把问题锁定在wp_users表的数据上了,你修复过这个表吗,有可能是数据太多有错误。

        5. 还有你只导了wp_user表吗,那个usermeta表导入了吗,最好两个都修复一下,导入。

        6. 可以到phpmyadmin里点repaire database
          看这张图http://www.themepremium.com/wp-content/uploads/2012/12/repair-wordpress-database-from-phpmyadmin.png

          也可以通过修改wp-config.php实现,看这里http://www.caopeng.net/2010/08/wordpress-comes-with-new-features-repair-and-optimize-the-database/

          但一定要先备份数据!你可以先修复你测试站上的数据试试。

        7. 有道理,可能是这个原因,晚上回去我再测试下,有结果了来告诉你,感谢sola姐。

        8. 怎么看,你把数据库发给我?客户信息属于敏感数据吧,但问题又好像是出在数据库上

  2. 没写程序,用的原来的。支付使用的是mycred,测试了半天,发现wp_users里面有下面两条数据,在支付的时候就会报错,奇怪:

    1. 什么数据?貌似被过滤掉了,麻烦点回复再发一遍。是只用mycred付款时出错,还是所有支付接口都报错?有在线的测试站吗

      1. 奇怪,老是被过滤了,只有用mycred付款时报错,其他接口都正常,sola姐有邮箱吗?我邮件与您联系。多谢sola姐。

        1. 那有可能是mycred的问题,你可以去这插件的论坛问问,作者回复的不慢。我的邮箱只能提供给客户,抱歉。如果可以,我希望通过博客交流,算是对我努力回答问题的一点安慰吧,希望你理解。

  3. 请问下只要user表里面有中文用户名,在支付的时候就会报错,这种情况咋解决啊,谢谢。

    1. 我想这是因为woocommerce的用户名不支持中文,用中文注册账户时会提示用户名非法。

      1. 了解,我在官网问了,还没人答复,还是sola姐姐给力,那这种有办法解决么,因为我网站里面很多都是中文用户名的。

        1. 官方客服好像是付费的哦。其实这个应该不是woocommerce的问题,因为wordpress用户名就不支持中文。
          解决的方法是让wordpress支持中文用户名,代码看露兜的文章http://www.ludou.org/wordpress-allowing-chinese-in-registration.html

        2. 感谢sola姐,我测试下来,发现又不是中文的问题,跟wp_users里面的数据有关系,比如我数据库有5000个用户,删除前面2500个用户,可以正常提交,然后利用拆半法定位出某个用户,但是数据库里面单独存放这个用户,也可以提交,报错如下:
          Array ( [result] => failure [messages] =>
          动作失败。请刷新页面然后重试。
          国家 为必填项
          名 为必填项
          姓 为必填项
          地址 为必填项
          Town / City 为必填项
          State / County 为必填项
          Postcode / Zip 为必填项
          Email 地址 为必填项
          电话 为必填项
          无效的支付方式。
          [refresh] => false )

          感觉像是country、first_name这些值没传递过去,但是抓包看,POST数据包里面确实有这些数据,奇怪啊。折腾一天了。。

评论已关闭。