Paypal subscription and recurring payments - the rules
Following my posts regarding to Paypal recurring payments, I was asked to fill the gap that was left there - how to setup the needed Rules in order to manage the payments.
It took me a while, but here it is.
In order to manage the payment using Rules I created this module, and used it in my site as follows:Rule #1 - make the paypal order a subscriptionThe event used: "Before user redirect to paypal for checkout".The action: "Add subscription information".In my case every checkout should become a subscription, so except for adding some fields in the conditions (just so I will be able to use them in the action), I didn't need to filter more. You can filter based on the order and its line items, so it means you can pinpoint exactly what you are looking for if needed.Below is a snippet of this rule:
<br>{ "rules_set_subscription_while_checkout_via_paypal" : {<br> "LABEL" : "Set subscription while checkout via paypal",<br> "PLUGIN" : "reaction rule",<br> "REQUIRES" : [ "rules", "commerce_paypal_ipn_rules_integration" ],<br> "ON" : [ "commerce_paypal_ipn_rules_integration_paypal_wps_redirect" ],<br> "IF" : [<br> { "entity_has_field" : {<br> "entity" : [ "order:commerce-line-items:0" ],<br> "field" : "commerce_product"<br> }<br> },<br> { "entity_has_field" : {<br> "entity" : [ "order:commerce-line-items:0:commerce-product" ],<br> "field" : "field_interval"<br> }<br> }<br> ],<br> "DO" : [<br> { "commerce_paypal_ipn_rules_integration_add_subscription_info" : {<br> "form" : [ "form" ],<br> "item_name" : [ "order:commerce-line-items:0:line-item-label" ],<br> "a3" : [ "order:commerce-order-total:amount-decimal" ],<br> "p3" : [ "order:commerce-line-items:0:commerce-product:field-interval:interval" ],<br> "t3" : [ "order:commerce-line-items:0:commerce-product:field-interval:period" ]<br> }<br> }<br> ]<br> }<br>}<br>
In the "add subscription information" you can set several values related to the subscription. In order to fully understand it, you can read Paypal documentation. This action adds the "_xclick-subscriptions" command into the post, and in the arguments you should define as follows:
- Item name
- Amount (a3) - Regular rate. This is the price of the subscription.
- Interval period (t3) - should be one of "day", "week", "month" or "year". The default in this action is "day".
- Interval amount (p3) - Regular billing cycle. This is the length of the billing cycle. The number is modified by the regular billing cycle units.
Rule #2 - handle cancellationsOnce the user created the subscription, he will need to manually cancel it via his paypal account. This case is critical for you in your site, but you should think what should be the right behavior in such situation.In our use case we try to avoid loosing a subscription, hence instead of automatically disable the subscription, we move to manual handling of the situation - just trying to reach the user by phone or mail, and see how we can help him to help us, and bring him back to be a happy subscriber.Bottom line - when getting an IPN with cancellation, all the rule do is to send an email to the "sales" with detailed information, so they can handle it from there.Of course, it all depends what you try to achieve. The event "Process Paypal IPN" is triggered from the hook_commerce_paypal_ipn_process, and provides lots of information on the IPN, which you can use as you want.Note: one of the Paypal pitfalls (except for sandbox environment hell) is documentation. Currently (April 2013) they announce the x.com site is deprecated, and they move to https://developer.paypal.com/. Unfortunately, not only this new site is not well indexed by Google yet, but it also has no internal search option I could use. I guess it means linking into any existing Paypal docs won't be useful in few weeks, so I rather not do it at all.You will get:
- Order - the Drupal Commerce order object related to this IPN.
- Payment method - The payment method instance used to create the payment and perform initial processing on the IPN.
- Transaction type - the different transaction type, as detailed here.
- User - the Drupal user entity of this order.
- IPN ID
- Transaction ID
- Receiver email - the email address of the one who get paid. Should be your site email address.
- Payer email - the Paypal user email address. This might not be the same as the email used in the user account.
- Payment status
- Sandbox test IPN - boolean, whether this is a test or not.
Back to my rule, here it is:
<br>{ "rules_notify_amdin_on_ipn_cancellation_message" : {<br> "LABEL" : "Notify amdin on IPN cancellation message",<br> "PLUGIN" : "reaction rule",<br> "REQUIRES" : [ "rules", "commerce_paypal_ipn_rules_integration" ],<br> "ON" : [ "commerce_paypal_ipn_rules_integration_ipn_process" ],<br> "IF" : [<br> { "data_is" : {<br> "data" : [ "txn-type" ],<br> "op" : "IN",<br> "value" : { "value" : [<br> "subscr_cancel",<br> "subscr_eot",<br> "recurring_payment_expired",<br> "subscr_failed"<br> ]<br> }<br> }<br> },<br> { "entity_has_field" : { "entity" : [ "order:commerce-line-items:0" ], "field" : "field_node" } }<br> ],<br> "DO" : [<br> { "entity_fetch" : {<br> "USING" : {<br> "type" : "node",<br> "id" : [ "order:commerce-line-items:0:field-node:nid" ]<br> },<br> "PROVIDE" : { "entity_fetched" : { "entity_fetched" : "Fetched entity" } }<br> }<br> },<br> { "mail" : {<br> "to" : "[site:mail]",<br> "subject" : "Note: [order:owner:name] subscription was changed ",<br> "message" : "Owner: [order:owner:name]\r\nOrder: [order:view-url]\r\nProduct: [order:commerce-line-items:0:field_node:url]\r\n[entity-fetched:nid]\r\n[entity-fetched:title]\r\n[entity-fetched:url]",<br> "from" : [ "" ],<br> "language" : [ "" ]<br> }<br> }<br> ]<br> }<br>}<br>
Rule #3 - clone Drupal Commerce orderDrupal Commerce-wise, each subscription payment should become an order of itself, which should be created automatically when the proper IPN is accepted. As a business owner, you should decide whether you handle the legal-related documentation based on your Drupal Commerce information or based on your Paypal account (I think you must do it based on Paypal, but I am not sure), but as for your user - he will defenetly expect to see a nice payments history in his profile, hence you should handle this IPN properly.The event "Process Paypal IPN" gives you all the information you need, and accordingly you should trigger a "clone order" action, and then complete the checkout process for this new order.The rule:
<br>{ "rules_clone_subscription_order" : {<br> "LABEL" : "Clone subscription order",<br> "PLUGIN" : "reaction rule",<br> "REQUIRES" : [ "rules", "commerce_paypal_ipn_rules_integration", "commerce_checkout" ],<br> "ON" : [ "commerce_paypal_ipn_rules_integration_ipn_process" ],<br> "IF" : [<br> { "data_is" : { "data" : [ "order:status" ], "value" : "completed" } },<br> { "data_is" : {<br> "data" : [ "txn-type" ],<br> "op" : "IN",<br> "value" : { "value" : [ "subscr_payment", "recurring_payment" ] }<br> }<br> }<br> ],<br> "DO" : [<br> { "commerce_paypal_ipn_rules_integration_clone_order" : {<br> "USING" : { "order" : [ "order" ] },<br> "PROVIDE" : { "new_order" : { "new_order" : "New cloned order" } }<br> }<br> },<br> { "commerce_checkout_complete" : { "commerce_order" : [ "new-order" ] } }<br> ]<br> }<br>}<br>
Those are the 3 main rules I am using in order to manage this Drupal Commerce Paypal subscription based site. I believe this covers the main use cases, and that whoever wants to build similar solutions will find this post useful.Feel free to ask anything, and (when I will have some spare time) I will be happy to help.Regards,Shushu
Ralates to: Drupal Planet