WooCommerce

Woocommerce 支付宝插件初探

Woocommerce虽然没有中文语言包,把前台做成中文后台保留英文确是一件很简单的事,如果你略懂中文,想用Woocommerce做个小网店,是个不错的选择。最麻烦的是支付方式,国外的产品基本不支持支付宝、财付通等国内流行的支付方式,所以研究了下如何让Woocommerce支持支付宝。

支付宝文档

在网上搜了下,只能搜到一个Woocommerce支付宝产品,虽然我没有购买,但大体猜测这个支付宝功能不是以插件形式写的,支付宝网关添加到Woocommerce的核心文件中,要更新的话只能从作者这里更新,有点麻烦。

给Woocommerce添加网关不难,文档很丰富,在文章Woocommerce如何扩展支付方式中介绍过。难的是支付宝,示例代码看着很痛苦,我对电商本来就了解的不多,许多术语都不懂,支付宝的文档对我来说就是一本看一分钟就会睡着的天书。

支付宝工作流程

支付宝常用有三种网关接口:即时到帐接口、双功能接口和担保买卖接口。

虽然示例代码中这三种接口分别带有自己的库文件,其实库文件是相同的,只需要一份。使用wp-alipay插件时,发现他用了三个库,分别放在目录lib-direct、lib-dualfun和lib-escow中,其实这是没必要的。支付宝区分这三种接口只是靠一个参数service,如下

"service" => "create_partner_trade_by_buyer" //担保买卖接口
"service" => "trade_create_by_buyer"  //双功能接口
"service" => "create_direct_pay_by_user" //即时到帐接口

支付宝三种方式的区别是提交的数据不同,我选择用get方式向支付宝发送数据,在Woocommerce中写了一个函数用来获取支付宝需要传递的数据。

构造支付宝所需要的参数数组

function get_alipay_args( $order ) {
    global $woocommerce;

    $paymethod = 'directPay';
    $order_id = $order->id;
    
    if ($this->debug=='yes') $this->log->add( 'alipay', 'Generating payment form for order #' . 
$order_id . '. Notify URL: ' . $this->notify_url);
    
    $buyer_name = $order->billing_last_name.$order->billing_first_name;
    if( $this->payment_method == 'direct')
        $service = 'create_direct_pay_by_user';
    else if ( $this->payment_method == 'dualfun' )
        $service = 'trade_create_by_buyer';
    else if ( $this->payment_method == 'escrow' )
        $service = 'create_partner_trade_by_buyer';
    $total_fee = $order->order_total;
    
    $alipay_args = array(
        "service"            => $service,
        "payment_type"       => "1",
        
        "partner"            => trim($this->partnerID),
        "_input_charset"     => 'utf-8',
        "seller_email"       => trim($this->alipay_account),
        "return_url"         => $this->get_return_url( $order ),
        "notify_url"         => $this->notify_url,
        
        "out_trade_no"       => $order->order_key.'|'.$order->id,
        "subject"            => $buyer_name,
        "body"               => $order->customer_note,
        "price"              => $total_fee,
        "quantity"           => 1
    );
    
    if( $this->payment_method != 'direct' ) {
        $add_args = array(
            "logistics_fee"        => '0',
            "logistics_type"       => 'EXPRESS', //optional EXPRESS(快递)、POST(平邮)、EMS(EMS)
            "logistics_payment"    => 'SELLER_PAY', //optional SELLER_PAY(卖家承担运费)、BUYER_PAY(买家承担运费)
            
            "receive_name"         => $buyer_name,
            "receive_address"      => $order->billing_address_1,
            "receive_zip"          => $order->shipping_postcode,
            //"receive_phone"      => $order->billing_phone,
            "receive_mobile"       => $order->billing_phone
        );
        $alipay_args = array_merge($alipay_args, $add_args);
    }

    $alipay_args = apply_filters( 'woocommerce_alipay_args', $alipay_args );
    return $alipay_args;
}

获取支付宝config参数

/**
 * Get Alipay config info for processing payment
 **/
function get_alipay_config( $order ){
	$alipay_config = array();
	$alipay_config['partner']      = trim($this->partnerID);
	$alipay_config['key']          = trim($this->secure_key);
	$alipay_config['seller_email'] = trim($this->alipay_account);
	$alipay_config['return_url']   = $this->get_return_url( $order );
	$alipay_config['notify_url']   = $this->notify_url;
	
	$alipay_config['sign_type']    = 'MD5';
	$alipay_config['input_charset']= 'utf-8';
	$alipay_config['transport']    = 'http';
	$alipay_config = apply_filters( 'woocommerce_alipay_config_args', $alipay_config );
	return $alipay_config;
}

建立支付宝query string

/**
 * Build Alipay http string to pass to Alipay gateway
 **/
function build_alipay_string( $order ) {
	require_once( "lib/alipay_service.class.php");
	//Get alipay args
	$alipay_args = $this->get_alipay_args( $order ); 
	$alipay_config = $this->get_alipay_config( $order );
	
	$alipayService = new AlipayService( $alipay_config );
	$alipay_submit = new AlipaySubmit();
	$para = $alipay_submit->buildRequestPara($alipay_args,$alipay_config);
	$query_string = http_build_query( $para, '', '&' );
	$alipay_string = $alipayService->alipay_gateway_new.$query_string;
	
	return $alipay_string;			
}	

有了这些,process_payment()函数只需要几行代码,就可以把数据发送给支付宝了。我们传递的参数中定义了return_url和notify_url,出于安全性考虑,return_url只用来获取创建的支付宝交易号,不做其他处理。写数据库更新订单的操作在notify_url中完成。

实际测试

后台界面如下

woocommerce alipay back end

在Alipay Payment Gateway Type处可以选择使用哪种支付方式,支持即时到帐、双功能和担保买卖。

前台界面如下

用户在checkout页面选择Alipay支付,点击Place order就会直接到达支付宝页面,支付完成后会跳回网站,显示订单已接受,并显示接收到的支付宝交易号,订单状态会被自动更新为Processing。

支付宝异步通知

支付宝会用异步方式向服务器(notify_url)发送支付结果,每次发送都会包含状态,状态根据你选择支付方式不同而有所差异,可以根据状态更新订单状态,或者为订单添加备注,比如担保买卖中有四种状态

WAIT_BUYER_PAY——等待买家付款

WAIT_SELLER_SEND_GOODS——买家已付款,等待卖家发货

WAIT_BUYER_CONFIRM_GOODS——等待买家确认收货

TRADE_FINISHED——交易完成

必须echo ‘success’给支付宝,否则支付宝会每隔一段时间就向服务器发送一次信息,直到24小时候以后超时才停止。

用1分钱测试了几次,没有啥大问题,只是即时到帐接口没法测试,需要企业账户才能注册。

69条评论

  1. 请问怎么实现虚拟物品在买家确认收货后才发货?
    之前能实现,现在换了空间重建网站后不可以了

    1、商品已经勾选虚拟和下载
    2、在woocommerce里的可下载商品里去勾选最下的已付款后可下载而非已完成
    3、woocommerce里支付宝PID、校验码、支付宝号、担保交易也填写好,没有勾选别的东西

    现在的情况是买家下单付款后会收到一封订单的邮件,但是确认收货后却没有收到虚拟物品的邮件
    在后台是显示买家已发货,等待买家确认收货,要人工点击已完成才能发虚拟物品的邮件

    之前是买家下单付款后会收到一封订单的邮件,确认收货后才会收到虚拟物品的邮件,后台也会自动显示已完成

    1. 现在的流程就是虚拟可下载物品自动发货,如果你不想自动发货,可以只设置下载属性,不设置虚拟。

      正常情况下,买家购买虚拟可下载商品,只要支付宝付款后就会自动将支付宝状态改为“卖家已发货”。注意这一步同步和异步通知都能完成。

      买家在支付宝确认收货后,支付宝通知woocommerce,woocommerce将订单状态变为已完成,并发送order complete邮件,我不知道这是不是你说的虚拟物品邮件,而这一步只能由异步通知完成。

      如果你的订单无法自动变成完成状态,那可能是异步通知不管用,被服务器屏蔽了,支付宝的异步通知很容易被当成垃圾请求。

    1. 信用卡支付服务有很多提供商,根据你的提供商找对应woocommerce插件即可。

  2. 樓主,謝謝你的介紹。

    我在 WooCommerce 官方网站上看, 有 Alipay for WooCommerce (http://www.woothemes.com/products/alipay-cross-border-payment-gateway/) 的插件。但细看之后,它需要申请一个 Global Alipay (global.alipay.com) 这与在 alipay.com 上申请的户口有何不同?我有一个个人的支付宝户口,还要申请吗?个人、商用和 Global Alipay 三者如何分别及使用?可有这方面的资料可分享吗?

    Kelvin

    1. 这个插件是给国外客户用的,需要在global.alipay.com注册一个账户,具体用法因为我是国内客户所以没用过。
      如果是国内客户,去alipay.com申请账户,通过实名认证,到https://b.alipay.com/order/productSet.htm选一个服务跟支付宝签约,就可以使用了。但不是用上面那个收费插件,要用这个https://wordpress.org/plugins/alipay-for-woocommerce/

      说白了就是支付宝对国外和国内客户分开管理,提供的服务也不一样。

  3. 亲爱的楼主,我也在做online shop,没有任何编程知识,我直接装上这个插件,发现有partner ID和Key这两个是必须要填吗?
    如果不改这些程序,这个插件可以直接用吗?
    我去淘宝网上发现它们有出售各种支付对接现有网站的服务,我需要购买吗?
    谢谢楼主了,我真的对这个很晕。期待你的解答!

      1. 非常感谢博主!自己做的主题兼容WooCommerce的教程能多写一点就好了.

    1. 不好意思,没接触过财付通插件。如果你对财付通的工作流程比较了解,我想问题就不大。woocommerce的支付接口比较模式化,需要付款后更新数据库的参考paypal就可以。

  4. SOLAGIRL,你好,遇到一个难题,翻译后的账单用户的姓名比较复杂,名在姓前面,不符合中文用户习惯,如何修改,我找了一个晚上没照出来,不会php,求指导,谢谢

    1. 编辑文件夹i18n里的.po和.mo 文件即可。

      你这么问sola妹妹没法回答你。

    2. 大灰狼说的对,改改翻译,看下官方文档http://docs.woothemes.com/document/woocommerce-localization/
      翻译好的文件可以放到wp-content/languages/woocommerce/目录下,这样下次更新就不会丢失了。

    3. solagirl,又来麻烦你了
      我的网站是自适应的,但是因为之前申请的双功能接口,用户无法在移动端支付,现在申请了支付宝手机网站支付,所以现在我想这样:用户如果在PC端上的时候就跳到双功能接口,如果判断到用户是用移动端登录支付时就跳到支付宝手机网站支付
      可不可以将手机网站支付做成一个插件alipay_mobile,在你的插件“感谢您在本网站下单。现在帮您转到支付宝完成付款。”这里加个判断,如果为移动端则跳到alipay_mobile 插件内的函数来处理,这个判断如何加呢?

  5. 请问这些代码我应该加在那里?我在订单中无法区分那些订单已经通过支付宝付了款的,万分感谢!

      1. 额,意思是,这些function的代码我应该加在支付宝插件的那个文件呀?附上结构图
        [root@web alipay-for-woocommerce]# tree
        .
        ├── alipay.php
        ├── class-wc-alipay.php
        ├── images
        │   └── alipay.png
        ├── lang
        │   ├── alipay-xx_XX.pot
        │   ├── alipay-zh_CN.mo
        │   └── alipay-zh_CN.po
        ├── lib
        │   ├── alipay_core.function.php
        │   ├── alipay_notify.class.php
        │   ├── alipay_service.class.php
        │   └── alipay_submit.class.php
        ├── readme.txt
        ├── screenshot-1.png
        ├── screenshot-2.png
        └── screenshot-3.png

        1. 抱歉,实在不明白你的意思。如果你要修改插件,请说明要做什么功能。如果你要往插件里添加代码,麻烦贴一下要加的代码。

        2. 额,目前已经装官方的支付宝和WC,但是通过支付宝付款之后,订单状态仍然为等待中,想实现的目标是,在通过支付宝之后,订单状态能变为处理中,以区别未付款的订单,找到你的这篇文章,想通过你上你给的代码,修改现有的插件,所以想知道我改在哪里改哪些文件,万分感谢!

    1. 这个插件的设定的就是付款后订单状态变为处理中,支付宝会在24小时内每隔一段时间给服务器通知,如果服务器受理成功(即订单状态变为处理中),支付宝就停止推送。
      如果过一段时间还不行,那只能打开debug模式看看到底卡在哪里了,但订单状态变更功能插件中确实写了。

    2. 你可以看看订单的订单备注一项有没有“买家已付款,等待卖家发货 订单状态从等待中改为 处理中”这条记录,如果没有就说明服务器没成功接收支付宝异步推送,比如超时之类的。

  6. SOLA 美女,我发现一个问题哦,在跳到支付宝的后,显示的货物名称变成了用户名,如下,如何修改为货物名呢?谢谢
    “subject” => $buyer_name,

    1. 你可以从$order中获取订单信息,应该有产品名称,不过产品可以是多个,用产品名称就得考虑下了。

      1. 对了,又遇到个新问题,现在wc更新了,启用你的插件后会有Alipay is enabled, but the store currency is not set to RMB. Please set the CNY against the RMB exchange rate.,这个可能要修改下了,你插件里面的RMB就是WC里面的CNY啦,虽然也可以设置为比例为1。

        还有一个非常恐怖的问题!!!

        更新了wp版本后,启用wc再启用你的插件的话,写新文章时插入媒体无法见到媒体库里面的图片,上传图片也会出现 :“上传时发生了错误。请稍后再试。”的错误,每次更新都要关掉插可以解决下这个冲突吗?万分感谢

        1. RMB和CNY一直是WooCommerce官方搞不清的东西,现在的新版,他们干脆把两个都加上了,这个应该不影响使用,设置汇率转换是1就行。不过我选了货币是人民币,没出这提示,真奇怪。

          至于你说的媒体上传的问题,我更新过很多次wp和wc,每次都开着alipay插件,没发现出现过问题。我现在也没法去花大量时间重现这个错误,如果这个对你很麻烦,建议你选择付费版的alipay插件吧,支持会好很多。我只能在心有余力的时候去支持下,现在我已经忙的上火了,真是对不住。

  7. 随便搜了一下,就有以下这些已经集成了支付宝的汉化WooCommerce插件,似乎应该不是从你这里抄袭的。可惜的是他们最少卖40,多的卖到80软妹币:

    wordpress购物车插件Woocommerce汉化版集成支付宝、财付通、网银在线支付【更新至2.0.9】

    完美汉化wordpress购物车插件WooCommerce集成支付宝担保交易+及时到账+财付通+银联[更新至v2.0.9]

    WooCommerce购物车插件完美汉化中文版+集成支付宝担保交易+及时到账&财付通+银联[更新至v1.6.5.1]

    1. 他们没有抄袭我的,我也没抄他们的!他们出的更早,我要用,但必须要支持英文,所以没从他们那买,自己写了。我感觉他们那个可能更稳定一点,我对支付宝并不精通。40块钱嘛,说心里话,我觉得很便宜!

    1. WooCommerce哪个版本?WooCommerce最近版本号跳的太快了,我用2.0.3测试的时候状态可以变成processing。

        1. 我升级到2.0.5试了一下,付款成功后状态会变为processing。不知你的是什么问题

  8. 博主,请问下:

    右下角弹出 More in
    以及左边侧边栏弹出 “文章目录”

    这是什么插件实现的?

    另外,这个修改的主题,你打算放出吗?

    1. upprev
      我的主题是试验品,我学wp时有啥想法就会用这主题试试,所以改的比较乱,说实话我正打算有空换个白纸一样的主题呢。你要喜欢我可以整理一份给你

  9. 我是台灣的使用者
    我想寫Woocommerce的超商取貨功能
    不知道站長可不可以指點幾招

    感謝

    1. 我对超商取货不太了解,根据我的经验,写WooCommerce的插件难点都在于要集成的那个第三方功能,WooCommerce的文档很详细,代码也整洁,看起来不费力。如果您要写的超商取货功能流程比较清晰,只要按照WooCommerce的文档把功能加到对应位置就可以了。

      1. 站長您好

        抱歉再請教您一次
        您說的WooCommerce的文檔說明 我網上一直找不到
        可否跟您要個連結

        謝謝~!

  10. 如果能全面支持,这个就太赞了。

    在应用支付宝支持时,以及网站优化方面,可否请你们提供咨询服务?

      1. 请问下,这个插件完成了吗?到哪里下载?

        博主能否在主页设置一个 Contact 功能,这样访问者可给你写信。

        1. 博主,你的“收到回复后邮件通知”似乎有问题。

          我没有收到你回复的邮件。确认了电子邮件地址正确的。

        2. 有可能是进了垃圾邮件,有可能是服务器不稳定,我的gmail邮箱可以收到,别的邮箱有时候就收不到

评论已关闭。