Zend Framework: Zend_Payment Component Proposal
| Proposed Component Name | Zend_Payment |
|---|---|
| Developer Notes | http://framework.zend.com/wiki/display/ZFDEV/Zend_Payment |
| Proposers | Vadim Vincent Gabriel |
| Zend Liaison | TBD |
| Revision | 1.0 - 1 January 2008: Initial Draft. (wiki revision: 12) |
Table of Contents
1. Overview
Zend_Payment Is a component that will offer a unified API for various payment providers. The payment component will allow you to easily process transactions without having to worry about all the backend details of connecting and setting up various options.
2. References
*
3. Component Requirements, Constraints, and Acceptance Criteria
- This component will provide a unified API.
- This component will allowbackend drivers to connect to many different payment gateways
- This component will Support both credit card gateways as well as PayPal-like gateways
4. Dependencies on Other Framework Components
- Zend_Exception
5. Theory of Operation
This component will offer a unified API for various payment providers. This payment component will allow you to easily process transactions without having to worry about all the backend details of connecting and setting up various options.
Supported Gateways
6. Milestones / Tasks
- Milestone 1: Proposal created
7. Class Index
- Zend_Payment_Exception
- Zend_Payment
- Zend_Payment_Gateway_Abstract
- Zend_Payment_Gateway_Exception
8. Use Cases
| Example using Tranzila gateway |
|---|
24 Comments
comments.show.hideApr 15, 2009
Sam Hauglustaine
+1
I'm certainly willing to contribute an implementation for Ogone (www.ogone.com, one of the mayor payment gateways in Europe).
Apr 15, 2009
Nigel James
I would also like to help out where I can too. I have some experience with some UK and Australian providers.
Apr 15, 2009
Nils Caspar
Is this component for recieving or for sending payments (or both)?
Apr 15, 2009
Vadim Vincent Gabriel
I will be posting some first mock ups on how i see it should be built and post them to the mailing list to get some feedback from the community members.
@Nils basically it's the same thing, I am not sure about all payment gateways (that's why we will be using interfaces and adapters and each gateway will extend those), But in most cases there will be a way to send and receive money using the gateways (at least using the ones listed above).
Apr 15, 2009
Cory D. Wiles
I would love to lend any assitance with the PayFlow validation, if any is needed. I had to create a custom validator for work to do just that.
http://corywiles.blogspot.com/2009/01/paypal-zend-framework-validator.html
Apr 19, 2009
Eric Haskins
+1
I would love to help. I do alot of merchant integrations. I am actually getting ready to do one for enterpayment on a project I am working on. I love this proposal
Apr 19, 2009
Vadim Vincent Gabriel
Thanks, Any help will be appreciated. Hopefully once the abstract class is done we could work on building as many gateways as possible to support various payment providers.
Unfortunately, Right now no one really gave any suggestions about the way this should be structured. And doing it based on what i think was not the way i planned on doing this. I wanted to see how others see this should be built since i won't be the only one using it. I looked at Zend_Service_Payment / Zend_Service_Paypal and it was way to complicated. What i am trying to achieve here is simplicity & efficiency, But it's hard when no one really throws ideas.
Vince.
Apr 20, 2009
Jeremy Postlethwaite
I can see having the ability to set the parameters like this:
$gateway->setParameter('credit_card','4111111111111111');
$gateway->setParameter('amount','1');
$gateway->setParameter('expiration','11/11');
This would allow the ability to use Zend_Config or pass the parameters from a database.
Every gateway will have different names and variously required parameters to set. It would seem clumsy to store them in the class, but it maybe the easiest:
protected $parameters = array(
'url' => array('value' => 'https://some-gateway.com/', 'required' => true),
'credit_card' => array('value' => '', 'required' => true),
'expiration' => array('value' => '', 'required' => true),
'address_1' => array('value' => '', 'required' => false),
...
);
It may be helpful to layout how a few gateways return error and success messages.
Apr 20, 2009
Vadim Vincent Gabriel
Thanks, I will sure look into the way the parameters are set on a gateway basis, The required element is sure a great idea to throw an exception if one of the required fields is missing.
I realized the best way of knowing the common methods needs to be in the abstract class is by actually creating some gateways and by doing that i will know what methods they all share.
Any other feedback is highly appreciated.
Vince.
Apr 22, 2009
Dolf Schimmel (Freeaqingme)
Looks good.
One thing that should be changed btw is the setFields() method. I think it would better return an instance of itself ( Zend_Payment_Gateway_Abstract ). Furthermore I think you can better stick to the new naming conventions that are coming up (see mailinglists or irc);
Then what _checkRequiredOptions() is concerned, why isn't this public nor abstract?
Apr 22, 2009
Vadim Vincent Gabriel
Thanks.
I agree the setFields method will return an instance of itself, So you could chain. The _checkRequiredOptions needs to be abstract, Still working on this.
I read about the new naming conventions, Didn't really like them, Or maybe i just misunderstood there usage, Don't have any examples yet so i will probably do that as i go, Or at the end, Will see.
Thanks for the feedback.
Apr 23, 2009
Till Klampaeckel
Hey there,
first off, this is very cool.
Awesome!
Then, to give you some feedback:
1) I'd use Zend_Http_Client because a direct cURL dependency might limit people in the end. E.g. why use cURL when socket works just as nice? Zend_Http_Client takes care of the implementation for you and what people want to use – that's up to them. By default, it [Zend_Http_Client] uses sockets and if people want cURL (or have other requirements like a proxy, etc.), i'd add a setter so they can inject their own instance of Zend_Http_Client which is customized and uses whatever they want.
2) I briefly checked your example adapter. I'm wondering, how would you handle requests from the payment provider? I've integrated a couple and for example Paypal pings you back, and that ping back might not be instant – but later on. How would see this use case fit into your proposal/code?
Till
Apr 23, 2009
Vadim Vincent Gabriel
Thanks,
1. Yea i figured the Zend component will be preferred, So i will stick with that.
2. Basically, From what i know about Paypal (not sure about the rest) while the transaction is made paypal can ping back to a URI specified (if it was specified) and then do something with the information like add it to the DB, Email etc. Regardless on this component you will need to create an action in a certain controller to handle that and provide the url to the paypal gateway when processing. If you have any suggestions feel free to post them.
Vince.
Apr 30, 2009
Colin Guthrie
This is a great idea.
We're currently toying with whether to support multiple gateways in our app, or just go with a single standard one. If this corner of Zend Framework bears fruit, then it could influence our decision quite a lot!
We currently have implementations (in our own way) for Cybersource and PayPalPro (the webservice based option rather than the "go to paypal site and come back later" option that I presume the current "paypal" class will cover.
My only major comments so far would be to try and provide a comprehensive mapping for fields and requirements for all providers.
A comment further up talked about how "different gateways will take different parameters" and while I completely see this point of view, I think it is essential to define standard names that will be used by all providers for things like amount, currency, CC number, CVV, expiry dates/issue numbers and other such common things. Obviously the end goal should be to allow for a payment to be processed with via a standard call regardless of the backend gateway used, and thus all non-standard info should be given only in the factory() method.
Another important thing here IMO, is how to handle storing an identifier after a successful payment. This is needed for e.g. issuing refunds for a previous txn. If an application allows mulitple people to define their own gateway service and account for a given "item", we need to store the gateway used and the specific account details used to access said gateway. That way when coming back later to issue a refund, we can do so via the exact same account used to make the initial payment. I'm not sure if I am explaining that well or not!
Anyway, for this reason, I wonder if it's wise to provide a mechanism or wrapper for loading an account from a database in some capacity? e.g. some kind of factory method that just takes an id and automatically looks up the gateway type and access details from a table. When payment is completely, it can give a transaction identifier that includes both the remote end id and the account id so we can store both in our transaction log. I appreciate this is perhaps something that is better handled in the application, so I only really mention it here for an example of use cases that we should consider, to make sure it will not exclude this type of use
GUTGW!
Apr 30, 2009
Vadim Vincent Gabriel
Hey,
First the current Paypal class will cover the webservice option, PDT & IPN as well. So you will be able to use this and choose which ever method suits your needs.
A common names for the credit card number, cvv etc.. is something doable, But some gateways have methods that other don't. Overall i think that each gateway will need to have a documentation and examples, Trying to make it as much as common is something that i do want to try and accomplish, But doing that will still have limitations.
Currently i think we should try and accomplish our main goal, And it's to provide a unified API for payment processing. I was thinking on adding logs, DB table and other things but that's planned for future releases.
Jul 04, 2009
Laurent Melmoux
I gave a go to the paypal gateway and I have e few suggestions :
1) return an "gateway response object" instead of an raw array so instead of checking array keys we could use method like :
2) Standardize payment status by mapping gateway paymentStatus to class constant so we could do things like :
3) I found the protected method buildRequest() confusing because it doesn't only build the request it sent it too. So I suggest to rename it too sendRequest()
4) IMHO buildButton() should be rename because it only return an url and rendering stuff should be delegated to an view helper. I would drop the autoredirect flag too and leave this to the application logic.
Aug 14, 2009
A.J. Brown
FYI, the Zend_Service_PayPal proposal's API will be updated here in a few weeks, if there's still plans to hook into it for the PayPal payments.
Aug 16, 2009
Jeremy Giberson
Heres a bunch of input on this Zend_Payment component. Theres a lot here, practically enough for an entire proposal but I'm hoping these suggestions will be incorporated into the current proposal.
Zend_Payment:
One of things I for Zend_Component is gateway indepedance, much like the Zend_Auth component is idepedant of its adaptors, Zend_Payment should only offer general api calls like "charge", "cancel", "refund", "thirdpartyPrepare", "thirdpartyReturn" etc. Leaving it to the gateway component to do the dirty work. In this manner, Zend_Payment would never offer an api call like "doExpressCheckout", "getExpressCheckoutDetails" as these are paypal specific. From my experience with different payment gateways I'm confident they all support credit cards in a way that can be abstracted generally to Zend_payment. It is possible that third party site checkouts could be implemented too, but only if we can use a series of abstracted calls that covers the general process of preparing the gateway, redirecting teh user, receiving the user, fetching checkout details and finalizing the payment. In cases where payment mechanisms can't be abstracted to Zend_Payment it will be up to the developer to incorporate that specific process utilizing the Zend_Servce_<Gateway> component.
Zend_Payment_Data
I also want to introduce a data container that standardizes the collected user input for checkout. It will be up to the gateway components to extract and format the data it needs from the container. If for some reason a gateway requires unusual information not typically collected, the container should allow the setting/getting of custom data to accomodate those needs. Data will implement named setters/getters for the standard data (that way ide's have something to code complete for us lazy developers). In addition to the standard getters/setters it will utilized a loader that reads values from Zend_Form components.
Which bings me to the next feature: Zend_Form integration for collecting data for shipping, billing, payment details. Zend_Payment_Form_Abstract will be the default fields that collects all the standard data of the Zend_Payment_Data component, including preconfigured validators. Each gateway implementation will be capable of extneding the abstract form for the opportunity to add extra fields for data collection. The user will be able to ask the Zend_Payment_Gateway component for the Zend_Form component to render. The developer can further extend that form component to add their own extra fields as desired.
Zend_Payment_Gateway
Because Zend_Payment won't introduce any gateway specific interfaces and may not be able to abstract methods to accomplish all features of a gateway, it will be necessary for the user to implement those features on their own. For code consistancy across all projects using Zend_Payment we should force Zend_Payment_Gateway components to utilize existing Zend_Service_<> components to implement payment features. This way the user can ask the zend_payment_gateway object for its Zend_Service_ implementor and get back the payment service component the gateway was using. The benefit being the Zend_Service_ component would be preconfigured (configuration it got from zend_payment setup code).
It also means the user has an obvious road to follow when they come to the "gee, Zend_Payment doesnt support fax checkouts, what now?" issue. They simply get the underlying Zend_service_ component and utilize the full api specific to fax checkouts.
Zend_Payment_Response
Still quite open on the features and requirements of Zend_Payment_Response. Still requires some brain storming, I think there may be a need to differentiate between payment responses and other api responses for things like checkout/payer details etc.
Directory structure with new form class and zend_service reliance
Zend_Payment_Data
Below I've got a use case scenario making use of the data/form/response components.
Aug 15, 2009
Jeremy Postlethwaite
I am not against Zend_Payment being able to create forms with Zend_Form, but I think the API should also support the user by allowing them to create their own forms.
It is also possible, that people will want to use Zend_Payment in a batch mode for processing several credit cards at a time, forms would not be used.
As a note, I do use Zend_Form.
Aug 16, 2009
Jeremy Giberson
The Zend_Form integration as I propose it is meant to be purely as a complimentary makes life easier for the programmer. As I said, they can extend the forms to add their own fields, they can use their own views to render the forms manually (instead of relying on decorators etc), and so long as they use the same field names they can build forms from scratch if they want.
In addition, the Zend_Form integration is optional, its a way insert data into the Zend_Payment_Data component. However, the Zend_Payment_Data component has its own setters, so you don't have to use loadValuesFromFrom method you can do the calls to set the data manually from your own data set. In this way, batching payments is just as supported as user driven payments. In addition, you can build your own data component loaders to load values from your database, or files or any mechanism. By abstracting the values that gateways use into a Zend_Payment_Data component, you get a ton a freedom in how you prepare, populate and use those values through the common interface of Zend_Payment_Data.
In short, both of your desires are freebies, already supported by the additions I proposed.
Sep 10, 2009
Adam Delyea
Is this still being developed?
I'd be highly interested in seeing this added to the framework, and would be willing to offer some assistance to complete the addition, if needed!
Nov 11, 2009
Clifford W. Hansen
I would also like to help/use this component.
Is there any progress?
Where can I download the latest?
Dec 31, 2010
Lukasz
I'd like to contribute this proposal also with my own proposal of module implementing the common payment flow from the beginning to the end. I think that it would be great to have such function in the framework. I presented general concept on my blog here: http://lifeinide.blogspot.com/2010/12/multi-payment-gateway-module-for-zend.html
Feb 06, 2011
Dolf Schimmel (Freeaqingme)
Archiving this proposal, feel free to recover it when you want to work on it again. For more details see this email.