Drupal commerce orders not process with Paypal payment

We have a site based on Drupal Commerce and Paypal WPS payment method. After launch, we found some orders by Paypal is stuck in the status of “Checkout: Confirm order” and not go to the next status.

After checking we find when a Paypal payment finished,  the user will be gave two options. One is go back to our site, another is go to Paypal site. And if a user chose the second option, we will lost the order confirmation from Paypal.

Luckily I find Paypal has a “auto return” option for us. So we can force user to redirect to our site after he/she finished the payment, without giving a option to Paypal site.

It works but has some exceptions. We still found some orders are not confirmed after set our Paypal to “auto return”.

The issue be found when a user chose Paypal but select the credit card to pay. This is called “Paypal account optional”, and if this one is turning on, the user using credit card will not be redirected. As in the Paypal docs said:

Note: If you have turned on Auto Return and have chosen to turn on PayPal Account Optional for new users, a new user will not be automatically directed back to your website, but will be given the option to return.

So turn off this option will fix the issue.

For more solutions, we can look at this discussion on drupal.org: “When completing the checkout process” never fires if a rule sets order complete on IPN

The solution works around “auto redirect”: https://www.drupal.org/node/2485507

如何用Drupal Commerce实现定金功能

需求

客户需求是这样的:
网站的订单支付不要求全额支付(因为是B2B的业务),只需要支付一个定金就可以。
根据不同的user类型(A,B)以及他们是否在试用期,来要求支付不同的比例。如果A,定金为订单总额的50%。如果B,并且在试用期,30%。B不在试用期,则免定金,即跳过支付这个环节。

现状

Drupal Commerce并没有原生的定金功能。展开地毯式搜索,得到几个相关模块如下,但没有一个是成熟模块。

  • commerce_deposit 业务逻辑和我的需求有些差异,放弃。但有兴趣的朋友可以看一下代码,还是比较简单的。
  • Commerce Partial Payment  这个思路不错,也是最后我采用的办法。

与几位熟悉Drupal Commerce的朋友交流,现有的思路一般是通过添加price component或者custom line item来实现。我也尝试了第二种方法,具体的代码可以参考Commerce discount的模块。问题不大,如果作为折扣,这个line item作为负值没有什么问题,但作为定金,一个负值就看起来比较奇怪。容易让用户很困惑,并且这个方法最后改变了订单的总额。而从需求出发,订单总额是不应该改变的。所以这种方式最后也放弃了。

解决方案

参考Commerce Partial Payment ,基本实现了我需要的功能。我假设新建一个模块叫my_deposit。

定金计算

基本思路是这样的,首先写一个函数判断该用户是否需要定金,代码如下:

另外再写一个函数用来计算该用户该订单的定金数额,代码如下:

修改checkout页面

然后在checkout的付款页面,我们用 hook_form_BASE_FORM_ID_alter() 来修改commerce_checkout_form。基本思路如下:

首先调用上面的函数,看该用户是否需要付定金,如果不需要,则把payment methods 都删掉,这样就直接可以跳过payment步骤了。同时,在checkout form里加一个message给用户,说明定金数量或者你不需要支付定金。具体细节可看代码注释。

修改payment method表单的submit callback

下面是我们自己的callback,大部分是从commerce payment模块里的commerce_payment_pane_checkout_form_submit()里copy来的,47-56行是我们自己的修改。因为没有hook,所以目前只能这么改了。

其实很简单,就是把提交给payment method的金额修改为我们自己的定金金额。

这样就算基本完工了,测试一下你可以看到信用卡付款的金额已经变成了定金金额。订单完成后,查看order,可以看到付款记录,order balance是扣除定金余下的部分。

我们的需求并不涉及余款的支付,客户将会通过其它方式支付余款。所以这里就不讨论了。

注意事项

Paypal等offsite payment method的问题

以上方法在paypal上不起作用,我没有太深究原因,基本上的原因就是Paypal没有上面的callback提交,所以我们的蓝色代码不会被运行。暂时的解决办法就是直接用强大的hook_form_alter。直接修改commerce_paypal_wps_redirect_form。

这样就搞定啦。

Paypal的Sandbox测试,IPN在localhost会有问题:

because in the paypal sandbox(for example) you must specify an IPN handler URL. Paypal is using this URL to call the php file on your website that handles the IPN call. So you cannot pass into that url localhost/yourwebsite/ipn_handler.php. You will need something like your_computer_public_ip/yourwebsite/ipn_handler.php

一些相关的有用的参考资料

 

Payment模块:一个简单的Drupal Commerce替代方案

最近在OSTraining我们做了针对Drupal Commerce的全面的攻略。你可以观看30节课程的视频教程和下载“Building E-commerce Sites with Drupal Commerce”电子书。

然而,Drupal Commerce是一个企业级的解决方案,但是大多数OSTraining的学员们可能需要的只是一个简单的电子商务方案。

所以对这些需求,我们经常推荐Payment模块,它可以很轻松的把电子商务的功能添加到你的网站内容里。

Payment模块支持差不多六个支付网关(PayPal, Stripe, iDEAL, Authorize.net, Ogone, Rabo OmniKassa)。

在这个教程里,我们将展示如何使用Payment模块,并且启用Paypal支付。 Continue reading Payment模块:一个简单的Drupal Commerce替代方案