How to tie actions to payments
Purpose
A common practice or at least a common request is if it is possible tie the
occurrence of something or the condition for something to happen to a payment.
As easy as it sounds.. it is :). I can think of a couple of ways of doing this
but instead of just using one idea lets explain some general easy concepts.
Prerequisities
A plone instance with PloneGetPaid installed.
Step by step
They key of all the ideas I got about this are event subscribers, you can learn about them in this link, these allow us to perform actions in certain situations without having to just override code from getpaid to insert a call
to our methods.
So lets use the best of developer learning tools, an example.
Let's suppose you want to charge users of your site to pay to directly publish their documents instead of waiting for the revision period (yes, sounds
dangerous but it is a very useful example).
You will have your workflow to allow users to create draft and submit them forpublication.
So the first step you will need to do is to make sure every Document created is buyable (you do not want to go over every new document and set them as buyable or have the owner to do so). So we will subscribe to the creationevent of Document objects.
<subscriber
for="Products.ATContentTypes.interface.IATDocument
zope.app.container.interfaces.IObjectAddedEvent"
factory="Products.PerritoExample.makePayableOnCreation"
/>
Now we need to define a subscriber (makePayableOnCreation) that applies the buyable marker to them and set the annotated attributes of every GetPaid Object.
It is that simple as this (in a real life situation you may need to define some smarter logic to make sure the objects will get the correct price and perhaps some other attributes that you will want but it is not under the scope of thishow-to)
So our subscriber will do the following.
>>> from Products.PloneGetPaid import interfaces
>>> from getpaid.core import interfaces as coreInterfaces
>>> from Products.Five.utilities.marker import mark
>>>
>>> def makePayableOnCreation(obj, event):
... mark(obj, interfaces.IShippableMarker)
... coreInterfaces.IBuyableContent(obj).setProperty('price', 3.14)
... coreInterfaces.IBuyableContent(obj).setProperty('product_code', obj.ID)
Our first part is ready, after object creation is being mark as buyable, assigned a price and finally gets his product_code from objects ID, now we need to make the second part, this is making this object published after the owner pays.
We then subscribe to getpaid Orders workflow transitions to know when a transition has been fired that marks it as payed, this way we will know when any of the objects we are interested in are sold.
<subscriber for="getpaid.core.interfaces.IOrder hurry.workflow.interfaces.IWorkflowTransitionEvent" handler="Products.PerritoExample.publishIfPaid" />
And respectively the handler.
>>> from Products.ATContentTypes.interface import IATDocument >>> from Products.CMFCore.utils import getToolByName >>> >>> def publishIfPaid(order, event): >>> # We are only interested on the event where the payment happent >>> if event.destination != workflow_states.order.finance.CHARGEABLE: >>> return >>> for cart_item in order.shopping_cart.values(): >>> buyable_object = cart_item.resolve() >>> if IATDocument.implementedBy(buyable_object): >>> workflowTool = getToolByName(buyable_object,'portal_workflow') >>> workflowTool.doActionFor(buyable_object,'publish')
So now every time someone buys a Document it will became public, off course you can then do some checking if the one who purchased the item was actually the person suposed, also you could subscribe to the Documents transition to submit for publication and make the object payable then. The idea was to show you the basic tools to start doing the modifications that suit the most your site.
If you have more doubts do not heistate in join our mailing list or go to #getpaid@irc.freenode.net at any moment.
