We've reached the end of GSOC. From the mid-term to this point, the API has been through some major changes, most of which have to do with validation and error handling. Particularly, the changes include:
- Providing a systematically for catching validation and gateway errors. Validation errors are thrown as exceptions when no data has been sent to the external gateway yet. Gateway errors are saved directly to the database after they're returned back from the external gateway and can be processed by looking up the database records.
- Updating DummyPayment and PaymentTest to reflect and demonstrate the API changes.
- Minor changes including changing naming convention, improving inheritance structure...
So to summarize the whole project, here are the most notable features of the new Payment API:
This is the biggest part of the project. Over the last 3 months, we have been experimenting with different approaches and finally came up with a stable system to handle various types of payment gateways. The architecture is summarized in this diagram:
What's good about this architecture is that it is loosely coupled and gives developers the flexibility to customize it based on their own needs. Detailed documentation of the architecture can be found in the SilverStripe docs.
2. Yaml configuration:
To achieve the desired flexibility, we've developed a yaml config system that is capable of registering and configuring payment gateways. For example, when developing a new payment gateway integration, the developer can specify which classes he wants to use for model, processor, and gateway:
title: 'A new payment gateway'
That way he does not have to adhere to the default classes provided by the API if they are not suitable for the gateway being developed. By default, every implementation of a new gateway can just use the model class "Payment" and the processor classes "PaymentProcessor_MerchantHosted" and "PaymentProcessor_GatewayHosted", but it's not compulsary.
3. Unit testing with mock gateway:
This is another good feature that we've included in the API. Basically unit testing is quite difficult when it comes to dealing with external API. To tackle this problem, we've implemented a mock gateway system to be used for testing purpose only. An example can be found in the PayPal Direct Payment's mock gateway. which mocks up the responses based on a template response from the PayPal server. The mock gateway then uses the PayPalDirect API methods to process the dummy responses and return the respective results. That way we can use the mock gateway for effective unit testing.
4. PaymentTest module and DummyPayment:
API is not complete when there's no demonstration to show what it can do. In order to demonstrate the Payment API, we use the PaymentTest module and DummyPayment. DummyPayment is basically a mock gateway that generates dummy requests and responses and process them using the base API. PaymentTest is a means for UI testing and used for testing the payment flow. It provides a form for choosing payment methods and processes a test payment. The PaymentTest module is good for Sandbox testing, i.e. testing with the remote API in a test environment.
There are still a few things to be done in order for the module to be ready for a release. All the works that needs to be done are specified in the GitHub Issues List. Moreover, more payment gateways need to be supported, and that will be done after GSOC. Right now my mentors and I have accomplished the minimum-viable results for GSOC. All the work after GSOC will be our own open-source contributions to SilverStripe.
I would like to thank my mentors, Frank Mullenger and Jeremy Shipman for helping me with all the technical aspects of the project. I wouldn't have done it till this point without their help!
So I'm here, half way through GSOC 2012. At this point the Payment module architecture is quite solid and tested well. PayPal payment is already finished and works well with PayPal Sandbox (I haven't tested it on a live site though). I have some unit testing set up to help testing PayPal payment with Sandbox https://github.com/ryandao/silverstripe-payment/blob/1.0/code/PayPal/tes...
I'm currently looking at how to implement mock gateways for unit testing, which is the last major element of the project. The mock gateways serve the purpose of mocking HTTP responses from the gateways. Developers can use them to quickly test out their gateway response handlers.
Overall, I'm quite happy with where things are at the moment. There are still a lot of improvements to the architecture as well as PayPal submodule, but generally, other developers can start using the current architecture to implement other gateways of their choices. There's a simple guide on how to do that here https://github.com/silverstripe-labs/silverstripe-payment/wiki/Writing-y....
As schedule, I've finished coding out DummyPayment and using it as a proof of concept for the new architecture my mentors and I designed for the Payment module. All what DummyPayment does is recording the payment data and updating the payment status. I've created a mock order form for easy testing at /test/order/placeOrder. Upon submission, DummyPayment will process a payment of $10 using the designed API.
I'll modify DummyPayment a little bit with the feedback from my mentors and the community. After that, the next step is incorporating PayPalExpressCheckout and then PayPal Merchant Hosted payment. Hopefully I'll be able to finish it within one week after my vacation from 5-12 June.
So I've been one week into GSOC 2012. Let's take a look at what I've done so far and review the current progress.
The code is currently hosted on my GitHub repo branch 1.0. The repo is forked from the official Payment module repo and I'm working on a separate branch so that it'll not mess up the existing code. Here are the things I've accomplished during this very first week:
- Test DPS gateway-hosted payment and PayPalExpressCheckout to understand the API and find the common structure.
- Separate Payment into model (Payment class) and controller (PaymentController class).
- Provide skeleton code and core API for the base classes.
- Set up DummyPayment, a test gateway to verify the architecture and test the API. I will modify the Payment-Test module to test the DummyPayment gateway.
According to my initial timeline, at the moment I should've finished the core API and separated all gateways into sub-modules. However, during the community bonding period, my mentors and I agreed that we should discuss the architecture carefully before getting into the code. Therefore, I only started coding from May 22nd, which is 2 weeks later than the initial plan. We also agreed that the architecture should be done first and fully tested using the DummyPayment gateway. Then we can implement/refactor the individual gateways easily following the architecture. So now my timeline has been adjusted as follow:
May 7th – 20th: Familiarize myself with the code and the community; discuss architecture and implementation plan with the mentors.
May 21th – June 3rd: Implement the architecture and test it using DummyPayment. Study payment gateways’ API and test environments.
June 4th – 10th: One-week vacation.
June 11th – June 17th: Implement PayPal payment gatway following the architecture with unit testing supported.
June 18th – June 24th: Implement other gateways that are currently supported by the module. Implementing the mock servers used for unit-testing the gateways is not neccessarily to be done at this time since it requires tedius gathering of HTTP request/response dialogues.
June 25th – July 8th: Gather HTTP request/response dialogues and set up mock servers for each payment gatway.
July 9th – July 15th: Implement Google Checkout and other gateways if time allows.
July 16th – July 22nd: Implement recurring payment API and PayPalRecurringPayment.
July 23rd – July 29th: Do more testing and refactoring. Make sure all payment gateways work perfectly.
July 30st – August 13th: Further refine tests and documentation for the whole project.
This updated timeline is not fixed and subjected to change as I go along. My aim is to try things out fast and react quickly if changes are needed. The minimum deliverable for the mid-term evaluation is the newly structured Payment core module with PayPal support. I'll make sure that will be achieved regardless of the changes I may encounter. I also set a 3-week buffer from July 23rd to August 13th for testing and documentation which can also be used for development if more time is needed. I'll continue working until the official GSOC end date, August 22nd if any aspect of the project still needs to be done.
I'm currently doing Google Summer of Code with SilverStripe with the project Improve Payment Module. Basically the project aims to refactor the Payment module, which is a very important part of SilverStripe ecommerce solutions, to make it more robust and flexible. Over the last few weeks during the community bonding period, my mentors and I have discussed the new architecture of the module and here's what we've come up with:
- Make it as easy as possible for developers to process payment on an ecommerce site.
- Decouple the module's components and separate payment gateways into sub-modules. The core module after GSOC should not be changed much, and changes to payment gateways can be made separately from the core module.
- Provide unit testing capability.
The old Payment class now is separated into model and controller. The new Payment class only acts as a model to record the payment information. Anything related to payment processing is now andled PaymentController. Each payment gateway module should sub-class the 2 base classes to satisfy the specific requirements pertinent to that gateway. One thing to take note is that each gateway module can have up to 3 different controllers for the 3 purposes: production, development, and testing. The architecture is set up in the way such that developers can easily set up which controller they want to use through the config.php file and that controller will be used by PaymentProcessor accordingly. PaymentProcessor takes order information from the order form and forward the request to the PaymentController currently in use.
To make it even easier for developers, we provide a PaymentFactory class which is in charge of creating the model and controller objects of the gateway that they want to use. For example, processing a payment with PayPal now can be easily done as following:
Basically that's the direction we're heading so far. I forsee we'll need to modify the architecture a little bit here and there as we go along, but I hope the changes will not be significant and we'll not have to get off the current track.