WP笔记

WooCommerce 预览邮件模板

预览WooCommerce模板可以使用插件,比如Preview E-mails for WooCommerce插件,但在测试WooCommerce Print Invoices/Packing Lists插件的邮件模板时遇到了问题,preview插件不支持自定义邮件,没办法只好写代码来解决。

WooCommerce 预览邮件模板 – 代码版

代码放在主题的functions.php中。

add_action( 'init', 'sola_woocommerce_email_test' );

function sola_woocommerce_email_test(){

  $is_email_preview = $_GET['list_email'] ?? false;

  // Available for administrator
  if( current_user_can('manage_options') && $is_email_preview ){
    
    $email_class = $_GET['email_class'] ?? false;
    $order_id    = absint($_GET['order_id']) ?? false;

    // List all available emails and recent orders
    if( $is_email_preview ){
      sola_list_available_email_classes( $email_class );
      sola_list_available_orders( $order_id );
      sola_print_scripts();
    }

    if( $email_class && $order_id ){
      sola_preview_email( $email_class, $order_id );
    }
    exit;
  }
}


function sola_list_available_email_classes( $current_value ){
  $emails = wc()->mailer()->emails;
  $classes = array_keys( $emails );
  ob_start();
  ?>
  <select name="email_list" class="email_list">
    <option value="">Select a email to preview</option>
  <?php
    foreach( $classes as $class ){
      echo "<option value='$class' " .selected($class, $current_value, false) . ">$class</option>";
    }
  ?>
  </select>
  <?php
  echo ob_get_clean();
}


function sola_list_available_orders( $current_value ){
 $orders = wc_get_orders( array(
      'limit' => 30,
      'orderby' => 'date',
      'order' => 'DESC',
      'return' => 'ids',
  ) );
  ob_start();
  ?>
  <select name="order_list" class="order_list">
    <option value="">Select an order</option>
  <?php
    foreach( $orders as $order_id ){
      echo "<option value='$order_id' " .selected($order_id, $current_value, false) . ">$order_id</option>";
    }
  ?>
  </select>
  <?php
  echo ob_get_clean();
}


function sola_preview_email( $email_class, $order_id ){

  $emails = wc()->mailer()->emails;
  $email = $emails[ $email_class ];
  $order = wc_get_order($order_id);
  add_filter( 'woocommerce_email_recipient_'.$email->id , 'wetp_email_recipient_filter_function', 10, 2);
  function wetp_email_recipient_filter_function($recipient, $object) {
    return '';
  }  

  if( $email_class == 'WC_Email_Customer_Note'){
    $email->trigger( array('order_id' => $order_id) );
  } else {
    $email->trigger( $order_id );
  }
  

  echo apply_filters( 'woocommerce_mail_content', $email->style_inline( $email->get_content() ) );

  exit; 
}


function sola_print_scripts(){
  ob_start();
  ?>
  <script>
    (function(){
      const queryURl = '<?php echo site_url(); ?>' + '?list_email=1&email_class={email_class}&order_id={order_id}';

      document.body.addEventListener('change', e => {
        const { target } = e;
        if (target.matches('select')) {
          previewOrder(); // If target is an li, run callback
        }
      });

      function previewOrder(){
        const emailClass = document.querySelector('.email_list').value;
        const orderID = document.querySelector('.order_list').value;

        if( emailClass && orderID ){
          window.location.href = queryURl.replace('{email_class}', emailClass).replace('{order_id}',orderID);
        }
      }
    })();
  </script>
  <?php
  echo ob_get_clean();
}

使用时需要访问特定地址,例如:

http://localhost/wordpress/?list_email=1

选择email和order后就能看到邮件的效果,如图所示:

关于自定义邮件的写法

在编辑自定义邮件格式时,为了获得好的兼容性,最好使用table布局,将样式内联,并避免使用比较新的属性。例如flex-box里的flex-wrap:wrap会被gmail自动移除,导致样式错乱。

15条评论

  1. 抱歉,因为先前的文章关闭了评论,在这里讨论一下:

    PayPal 的 PayPal Identity Token,在申请设置的时候,需要将自动返回开启,并填写「返回 URL」,这个返回 URL 我觉得应该是动态的,每次不同的,那么具体要填什么呢?是 domain.com/check-out/order-received/ 吗?还是?

    1. 我按照 WC 官方文档 https://docs.woothemes.com/document/paypal-standard/ 的描述,填写了 xxx.com/check-out/order-received/ 试了好几次,都是浅黄色提示「我们无法验证您输入的URL。请检查您输入的内容,然后重试。」而链接是可以打开「已经收到您的订单」的页面的。
      按文档添加 IPN 为 http://example.com/?wc-api=WC_Gateway_Paypal 也是相同的黄色提示。如果直接打开的话,是「PayPal IPN Request Failure」。

    2. 不是太明白为何要写paypal的返回地址,这个woocommerce不是处理好了吗?
      返回地址确实是动态的,要带一些订单的东西,所以绝不可能去paypal网站填写,要在自己站点动态生成这个地址再传给paypal,一般由集成paypal的插件来解决,不需要自己填写。

      xxx.com/check-out/order-received/是订单已收到页面,没有订单信息时默认显示谢谢,没有任何实际作用。

      1. 因为 WC 内需要填写 Identity Token,填了这个就会回调的。但是申请 Identity Token 的时候,网页上需要输入返回 URL。WC 的官方文档也有说明,写的那个地址。但是我填进去,就返回浅黄色提示。另一个是 IPN 的通告 URL,也是返回相同提示。

        1. 你用的paypal不是woocommerce自带那个是吗。我记得identity token是给paypal PDT使用的,那么申请的时候填网站地址就可以了,真正付款时并不用这个地址。

        2. PS.我没用过真正的paypal PDT,只是开发时用过paypal sandobx的,记得当时就是随便填了个地址,重要的是有identity token,你说的是你无法申请到这个token吧。不知道实际账户和sandbox是否有区别,所以上面说的你只能试一下,我也不是太清楚。

          另外你要到woocommerce系统选项卡下看一看wp_remote_post是否能用,没这个PDT不能工作。

        3. 另外PDT只是IPN的有益补充,就算你不输入identity token,IPN也应该能更新订单状态,不可能出现用户付款了woocommerce还不知道的情况。真是这样你就要看看插件是不是有问题了。

        4. IPN 输入的时候,也是提示相同的浅黄色提示。也就是说,WC 完全不知道,付完款了还是保留的状态。那么我只能手动打开 PayPal 看了。

        5. 付款了wc还不知道那等于没集成paypal。自带的paypal付款你试了吗,那个是最简单得ipn,要是不行就是你服务器有问题,比如拦截了paypal请求。
          你用了付费插件,如果插件的server要求都满足了还不行,只能问作者了。

        6. 我用的是 WC 自带的 PayPal,按照你的方法,添加了两段函数,在人民币下启用了。没有使用第三方插件。并且 API 均有填写。差 Token、PIN。

      2. 我尝试了流程操作,的确我付完款后,WC 仍然是保留状态,不能识别为处理中。

    3. Identity token用于PDT(付款数据传输), API用于退款,两者皆为可选项目,不填不会影响paypal付款和订单状态更新,所以不要再想去paypal看状态的事,找自己服务器的问题。

      首先,去WooCommerce->系统状态下查看WordPress环境和Server环境,确保没有不符合要求的项目。
      其次,查看paypal的log记录,确保服务器有收到请求。记录位置wp-content/uploads/wc-logs/paypal-xxxxxxxx.log。
      最后,请用在线服务器测试,本地server肯定不行。

      如果问题依旧无法解决,还想问我的话,请提供更详细的信息,最好有在线站地址。

  2. 您好 想请教一下 我用的是 woocommerce 构架的商城,但是客户在进入支付页面的时候 即PAYPal 的时候出现中文页面 导致客户无法进行付款,这种一般什么情况啊,我用的是全部英文版wordpress , 不知道你有没有遇到过这种情况 谢谢

    1. 你说的付款是自己站点选择支付方式页面,还是跳转到paypal后的页面?中文页面如何导致客户无法付款的,报了什么错误吗?

评论已关闭。