[getpaid commit] r2685 - First work-in-progress commit with checkout wizard rework

0 views
Skip to first unread message

codesite...@google.com

unread,
Jun 9, 2009, 12:14:52 PM6/9/09
to getpaid...@groups.google.com
Author: mi...@redinnovation.com
Date: Tue Jun 9 09:11:28 2009
New Revision: 2685

Added:

Products.PloneGetPaid/branches/multiplepaymentprocessors/Products/PloneGetPaid/browser/templates/button.pt

Products.PloneGetPaid/branches/multiplepaymentprocessors/Products/PloneGetPaid/browser/templates/checkout-payment-method.pt

Products.PloneGetPaid/branches/multiplepaymentprocessors/Products/PloneGetPaid/browser/templates/settings-payment-processors.pt

Products.PloneGetPaid/branches/multiplepaymentprocessors/Products/PloneGetPaid/browser/templates/thank_you.pt

Products.PloneGetPaid/branches/multiplepaymentprocessors/Products/PloneGetPaid/profiles/default/propertiestool.xml
(contents, props changed)

Products.PloneGetPaid/branches/multiplepaymentprocessors/Products/PloneGetPaid/tests/dummy_processors.py

Products.PloneGetPaid/branches/multiplepaymentprocessors/Products/PloneGetPaid/tests/templates/

Products.PloneGetPaid/branches/multiplepaymentprocessors/Products/PloneGetPaid/tests/templates/button.pt

Products.PloneGetPaid/branches/multiplepaymentprocessors/Products/PloneGetPaid/tests/templates/thank_you.pt

Products.PloneGetPaid/branches/multiplepaymentprocessors/Products/PloneGetPaid/tests/test_payment_processors.py
Modified:

Products.PloneGetPaid/branches/multiplepaymentprocessors/Products/PloneGetPaid/browser/admin.py

Products.PloneGetPaid/branches/multiplepaymentprocessors/Products/PloneGetPaid/browser/checkout.py

Products.PloneGetPaid/branches/multiplepaymentprocessors/Products/PloneGetPaid/browser/configure.zcml

Products.PloneGetPaid/branches/multiplepaymentprocessors/Products/PloneGetPaid/browser/settings.zcml

Products.PloneGetPaid/branches/multiplepaymentprocessors/Products/PloneGetPaid/configure.zcml

Products.PloneGetPaid/branches/multiplepaymentprocessors/Products/PloneGetPaid/payment.py

Log:
First work-in-progress commit with checkout wizard rework

Modified:
Products.PloneGetPaid/branches/multiplepaymentprocessors/Products/PloneGetPaid/browser/admin.py
==============================================================================
---
Products.PloneGetPaid/branches/multiplepaymentprocessors/Products/PloneGetPaid/browser/admin.py
(original)
+++
Products.PloneGetPaid/branches/multiplepaymentprocessors/Products/PloneGetPaid/browser/admin.py
Tue Jun 9 09:11:28 2009
@@ -17,6 +17,7 @@
from zope.viewlet.interfaces import IViewlet

import getpaid.core.interfaces as igetpaid
+from getpaid.paymentprocessors.registry import paymentProcessorRegistry

from Products.PloneGetPaid.interfaces import ISettingsShipmentManager
from Products.PloneGetPaid.i18n import _
@@ -216,6 +217,60 @@
"
self.
"""
+
+class PaymentProcessors(BrowserView):
+ """ The user goes to payment processor settings in GetPaid setup.
+
+ Print available payment processors and see if they are enabled. Allow
users
+ to choose which processors to enable. Print links to individual
processor setting
+ pages.
+
+ Payment processors are stored in
portal_properties.payment_processor_properties.
+
+ TODO: This form is not protected against XSS attacks.
+ """
+
+ template =
ZopeTwoPageTemplateFile('templates/settings-payment-processors.pt')
+
+ def getCheckedForProcessor(self, processor):
+ """
+
+ @param processsor: Processor class instance
+ """
+
+ # See profiles/default/propertiestool.xml
+ if processor.name in
self.context.portal_properties.payment_processor_properties.enabled_processors:
+ return "CHECKED"
+ else:
+ return None
+
+ def getProcessors(self):
+ """ Called from the template.
+
+ @return: Iterable of Processor objects
+ """
+ return paymentProcessorRegistry.getProcessors()
+
+ def processForm(self):
+ """ Manage HTTP post """
+ actived = self.request["active-payment-processors"]
+
+ # Add some level of safety
+ for a in actived:
+ if not a in paymentProcessorRegistry.getNames():
+ raise RuntimeError("Tried to enable unsupported
processor %s" % a)
+
+
self.context.portal_properties.payment_processor_properties.enabled_processors
= actived
+
+ def __call__(self):
+
+ if self.request["REQUEST_METHOD"] == "GET":
+ return self.template() # render page
+ else:
+ # Assume POST, user is changing active payment methods
+ self.processForm()
+ return self.template() # render page
+

class PaymentProcessor( BaseSettingsForm ):
"""

Modified:
Products.PloneGetPaid/branches/multiplepaymentprocessors/Products/PloneGetPaid/browser/checkout.py
==============================================================================
---
Products.PloneGetPaid/branches/multiplepaymentprocessors/Products/PloneGetPaid/browser/checkout.py
(original)
+++
Products.PloneGetPaid/branches/multiplepaymentprocessors/Products/PloneGetPaid/browser/checkout.py
Tue Jun 9 09:11:28 2009
@@ -28,6 +28,9 @@
from getpaid.core import interfaces, options, cart
from getpaid.core.order import Order

+from getpaid.paymentprocessors.registry import paymentProcessorRegistry
+from Products.PloneGetPaid.payment import getActivePaymentProcessors
+
import Acquisition
from AccessControl import getSecurityManager
from ZTUtils import make_query as mq
@@ -87,6 +90,35 @@

return '\n'.join(qlist)

+
+class BasePaymentMethodButton(BrowserView):
+ """ Render payment method button on payment method checkout screen.
+
+ Subclass this to add your on payment method selection HTML on payment
selection
+ checkout screen.
+ """
+
+ def update(self, processor, paymentMethodsView):
+ """ Called by CheckoutPaymentMethodSelection to tell
+
+ @param processor: getpaid.paymentprocessor.registry.Entry instance
+ @param paymentMethodView: CheckoutPaymentMethodSelection instance
+ """
+ self.processor = processor
+ self.paymentMethodsView = paymentMethodsView
+
+ def getProcessor(self):
+ """
+ """
+ return self.processor # Set externally by
CheckoutPaymentMethodSelection
+
+ def isChecked(self):
+ if self.processor.name in
self.paymentMethodsView.getActiveProcessorName():
+ return "CHECKED"
+ else:
+ return None
+
+
class BaseCheckoutForm( BaseFormView ):

template = None # must be overridden
@@ -356,7 +388,7 @@
class CheckoutController( ListViewController ):

conditions = {'checkout-select-shipping' : 'checkShippableCart'}
- steps =
['checkout-address-info', 'checkout-select-shipping', 'checkout-review-pay']
+ steps =
['checkout-address-info', 'checkout-select-shipping', 'checkout-payment-method', 'checkout-review-pay']

def getStep( self, step_name ):
step = component.getMultiAdapter(
@@ -507,6 +539,43 @@
fields.__FormFields_byname__[ field.__name__] = field

return fields
+
+class CheckoutPaymentMethodSelection( BaseCheckoutForm ):
+ """
+ browser view for collecting credit card information and submitting it
to
+ a processor.
+ """
+
+ template =
ZopeTwoPageTemplateFile("templates/checkout-payment-method.pt")
+
+ def getProcessors(self):
+ """ Get active payment processors. """
+ processors = getActivePaymentProcessors(self.context)
+ return processors
+
+ def update( self ):
+ formbase.processInputs( self.request )
+ self.adapters = self.wizard.data_manager.adapters
+ super( CheckoutPaymentMethodSelection, self).update()
+
+ def renderProcessor(self, processor):
+ """ Create selection button renderer view and call it.
+
+ @param processor: registry.Entry instance
+ """
+ view = processor.getButtonView(self.context, self.request)
+ return view()
+
+ @form.action(_(u"Cancel"), name="cancel", validator=null_condition)
+ def handle_cancel( self, action, data):
+ url = self.context.portal_url.getPortalObject().absolute_url()
+ url = url.replace("https://", "http://")
+ return self.request.response.redirect(url)
+
+ @form.action(_(u"Continue"), name="continue")
+ def handle_continue( self, action, data ):
+ self.next_step_name = wizard_interfaces.WIZARD_NEXT_STEP
+

class CheckoutReviewAndPay( BaseCheckoutForm ):


Modified:
Products.PloneGetPaid/branches/multiplepaymentprocessors/Products/PloneGetPaid/browser/configure.zcml
==============================================================================
---
Products.PloneGetPaid/branches/multiplepaymentprocessors/Products/PloneGetPaid/browser/configure.zcml
(original)
+++
Products.PloneGetPaid/branches/multiplepaymentprocessors/Products/PloneGetPaid/browser/configure.zcml
Tue Jun 9 09:11:28 2009
@@ -102,6 +102,14 @@

<browser:page
for="*"
+ name="checkout-payment-method"
+ class=".checkout.CheckoutPaymentMethodSelection"
+ permission="zope2.View"
+ />
+
+
+ <browser:page
+ for="*"
name="checkout-review-pay"
class=".checkout.CheckoutReviewAndPay"
permission="zope2.View"

Modified:
Products.PloneGetPaid/branches/multiplepaymentprocessors/Products/PloneGetPaid/browser/settings.zcml
==============================================================================
---
Products.PloneGetPaid/branches/multiplepaymentprocessors/Products/PloneGetPaid/browser/settings.zcml
(original)
+++
Products.PloneGetPaid/branches/multiplepaymentprocessors/Products/PloneGetPaid/browser/settings.zcml
Tue Jun 9 09:11:28 2009
@@ -80,13 +80,14 @@
permission="cmf.ManagePortal"
menu="getpaid_settings"
title="Payment Options"
+ template="templates/settings-payment-processors.pt"
/>

<!-- Management Payment Processor Editing -->
<browser:page
for="getpaid.core.interfaces.IStore"
name="manage-getpaid-payment-processor"
- class=".admin.PaymentProcessor"
+ class=".admin.PaymentProcessors"
permission="cmf.ManagePortal"
menu="getpaid_settings"
title="Payment Processor Settings"

Added:
Products.PloneGetPaid/branches/multiplepaymentprocessors/Products/PloneGetPaid/browser/templates/button.pt
==============================================================================
--- (empty file)
+++
Products.PloneGetPaid/branches/multiplepaymentprocessors/Products/PloneGetPaid/browser/templates/button.pt
Tue Jun 9 09:11:28 2009
@@ -0,0 +1 @@
+<span>Magical string checked by unit tests</span>
\ No newline at end of file

Added:
Products.PloneGetPaid/branches/multiplepaymentprocessors/Products/PloneGetPaid/browser/templates/checkout-payment-method.pt
==============================================================================
--- (empty file)
+++
Products.PloneGetPaid/branches/multiplepaymentprocessors/Products/PloneGetPaid/browser/templates/checkout-payment-method.pt
Tue Jun 9 09:11:28 2009
@@ -0,0 +1,45 @@
+<html metal:use-macro="here/main_template/macros/master"
i18n:domain="plonegetpaid" >
+ <body>
+ <div metal:fill-slot="main" class="payment-selection" >
+
+ <h1 i18n:translate="choose_payment_method" />
+
+ <tal:payment-methods define="processors view/getProcessors">
+
+ <p tal:condition="python:len(processors) == 0">
+ No payment processors enabled. Please use
&lt;paymentprocessors:registerProcessor&gt; ZCML
+ directive to register your payment processors to payment method
multiplexer. Also, make sure
+ that those payment processors are enabled in GetPaid portal setup.
+ </p>
+
+ <form action="." method="POST" class="payment-method">
+ <table>
+ <tbody>
+ <tal:processor repeat="processor processors">
+ <tr replace="structure python:view.renderProcessor(processor)" />
+ </tal:processor>
+ </tbody>
+ </table>
+
+ <div id="actionsView">
+ <span class="actionButtons"
+ tal:define="actions view/availableActions"
+ tal:condition="actions">
+ <tal:loop repeat="action actions">
+ <input type="submit" class="button context"
+ tal:define="name action/__name__"
+ tal:attributes="id name;
+ name name;
+ value python:str(action.label);"
+ i18n:attributes="value" />
+ </tal:loop>
+ </span>
+ </div>
+
+ </form>
+
+ </tal:payment-methods>
+
+ </div>
+ </body>
+</html>
\ No newline at end of file

Added:
Products.PloneGetPaid/branches/multiplepaymentprocessors/Products/PloneGetPaid/browser/templates/settings-payment-processors.pt
==============================================================================
--- (empty file)
+++
Products.PloneGetPaid/branches/multiplepaymentprocessors/Products/PloneGetPaid/browser/templates/settings-payment-processors.pt
Tue Jun 9 09:11:28 2009
@@ -0,0 +1,36 @@
+<html metal:use-macro="here/main_template/macros/master"
i18n:domain="getpaid.paymentprocessors" >
+ <body>
+ <div metal:fill-slot="main" class="payment-selection" >
+
+ <h1 i18n:translate="choose_payment_method">choose_payment_method</h1>
+
+ <tal:core tal:define="portal_state context/@@plone_portal_state"
i18n:domain="getpaid.paymentprocessors">
+
+ <form method="POST" tal:attributes="action
string:${portal_state/portal_url}/@@manage-getpaid-payment-options">
+ <table>
+ <thead>
+ <tr>
+ <th i18n:translate="enabled">enabled</th>
+ <th i18n:translate="payment_processor">payment_processor</th>
+ </tr>
+ </thead>
+ <tbody>
+ <tal:payment-methods define="processors view/getProcessors">
+ <tr tal:repeat="processor processors">
+ <td>
+ <input type="checkbox" name="active-payment-processors"
value="processor/name" tal:attributes="CHECKED
python:view.getCheckedForProcessor(processor) or None"/>
+ <td class="payment-processor-link">
+ <span tal:content="processor/name" />
+ [ <a tal:attributes="href
string:${portal_state/portal_url}/@@${processor/settings_view}"
i18n:translate="edit_settings">edit_settings</a> ]
+ </td>
+ </tr>
+ </tal:payment-methods>
+ </tbody>
+ </table>
+
+ <input type="submit" i18n:attributes="value" name="submit"
value="set_enabled_processors" />
+ </form>
+ </tal:core>
+ </div>
+ </body>
+</html>
\ No newline at end of file

Added:
Products.PloneGetPaid/branches/multiplepaymentprocessors/Products/PloneGetPaid/browser/templates/thank_you.pt
==============================================================================
--- (empty file)
+++
Products.PloneGetPaid/branches/multiplepaymentprocessors/Products/PloneGetPaid/browser/templates/thank_you.pt
Tue Jun 9 09:11:28 2009
@@ -0,0 +1,35 @@
+<metal:page
use-macro="context/@@getpaid-content-template/macros/content_space"
+ i18n:domain="plonegetpaid">
+ <metal:block fill-slot="getpaid_content">
+
+
+ <h3 i18n:translate="heading_checkout_thank_you"> Thank you for your
order </h3>
+
+ <div tal:condition="view/getInvoice">
+ <div>
+ <span i18n:translate="your_order_id">
+ Your order id is
+ </span>
+ <tal:replace tal:replace="view/getInvoice"></tal:replace>
+ </div>
+
+ <div tal:condition="not:isAnon">
+ <span i18n:translate="box_order_status_url_description">You can
check the status of your order
+ <span i18n:name="status_url">
+ <a href=""
+ tal:attributes="href view/getURL"
+ i18n:translate="">here</a>
+ </span>
+ </span>
+ </div>
+
+ <div class="documentActions">
+ <a href="javascript:this.print()" i18n:domain="plone"
i18n:translate="">
+ Print this page
+ </a>
+ </div>
+ </div>
+
+
+ </metal:block>
+</metal:page>

Modified:
Products.PloneGetPaid/branches/multiplepaymentprocessors/Products/PloneGetPaid/configure.zcml
==============================================================================
---
Products.PloneGetPaid/branches/multiplepaymentprocessors/Products/PloneGetPaid/configure.zcml
(original)
+++
Products.PloneGetPaid/branches/multiplepaymentprocessors/Products/PloneGetPaid/configure.zcml
Tue Jun 9 09:11:28 2009
@@ -8,6 +8,7 @@
<!-- Dependencies -->
<include package="getpaid.core" />
<!--<include package="getpaid.io" />-->
+<include package="getpaid.paymentprocessors" />

<!-- zope.annotation is used in Zope 2.10 -->
<include

Modified:
Products.PloneGetPaid/branches/multiplepaymentprocessors/Products/PloneGetPaid/payment.py
==============================================================================
---
Products.PloneGetPaid/branches/multiplepaymentprocessors/Products/PloneGetPaid/payment.py
(original)
+++
Products.PloneGetPaid/branches/multiplepaymentprocessors/Products/PloneGetPaid/payment.py
Tue Jun 9 09:11:28 2009
@@ -4,6 +4,8 @@
from interfaces import IGetPaidManagementOptions
from Products.CMFCore.utils import getToolByName

+from getpaid.paymentprocessors.registry import paymentProcessorRegistry
+
class CreditCardTypeEnumerator(CreditCardTypeEnumerator):
implements(ICreditCardTypeEnumerator)

@@ -15,3 +17,20 @@
portal =
getToolByName(self.context.context, 'portal_url').getPortalObject()
options = IGetPaidManagementOptions(portal)
return options.accepted_credit_cards
+
+
+def getActivePaymentProcessors(context):
+ """ Return list of activated payment processors.
+
+ @return: List of getpaid.paymentprocessor.registry.Entry objects
+ """
+
+ portal_properties = getToolByName(context, 'portal_properties')
+ enabled =
portal_properties.payment_processor_properties.enabled_processors
+
+ processors = paymentProcessorRegistry.getProcessors()
+
+ # Filter out processors which are activated in the settings
+
+ return [ p for p in processors if p.name in enabled ]
+
\ No newline at end of file

Added:
Products.PloneGetPaid/branches/multiplepaymentprocessors/Products/PloneGetPaid/profiles/default/propertiestool.xml
==============================================================================
--- (empty file)
+++
Products.PloneGetPaid/branches/multiplepaymentprocessors/Products/PloneGetPaid/profiles/default/propertiestool.xml
Tue Jun 9 09:11:28 2009
@@ -0,0 +1,15 @@
+<?xml version="1.0"?>
+<object name="portal_properties" meta_type="Plone Properties Tool">
+
+ <object name="payment_processor_properties" meta_type="Plone Property
Sheet">
+
+ <property name="title">GetPaid enabled payment processors</property>
+
+ <!-- Contain list of enabled payment processor ids.
+ Ids correspond the declaration in ZCML <paymentProcessor:name>
+ -->
+ <property name="enabled_processors" type="lines" purge="False">
+ <element value="nullpayment"/>
+ </property>
+ </object>
+</object>

Added:
Products.PloneGetPaid/branches/multiplepaymentprocessors/Products/PloneGetPaid/tests/dummy_processors.py
==============================================================================
--- (empty file)
+++
Products.PloneGetPaid/branches/multiplepaymentprocessors/Products/PloneGetPaid/tests/dummy_processors.py
Tue Jun 9 09:11:28 2009
@@ -0,0 +1,85 @@
+"""
+
+ Dummy payment processor definitions.
+
+"""
+
+import zope.interface
+
+from Products.Five.browser import BrowserView
+from Products.Five.browser.pagetemplatefile import ViewPageTemplateFile
+
+import getpaid.core.interfaces
+
+from Products.PloneGetPaid.browser.checkout import BasePaymentMethodButton
+
+class DummyButton(BasePaymentMethodButton):
+ """ This piece of HTML is rendered on the payment method selection
page """
+
+
+class DummyThankYou(BrowserView):
+ """ This piece of HTML is rendered when the payment has been
completed """
+
+
+class DummyProcessor:
+ zope.interface.implements(getpaid.core.interfaces.IPaymentProcessor)
+
+
+# Enable one dummy payment processor
+configure_zcml = '''
+<configure
+ xmlns="http://namespaces.zope.org/zope"
+ xmlns:five="http://namespaces.zope.org/five"
+
xmlns:paymentprocessors="http://namespaces.plonegetpaid.com/paymentprocessors"
+ xmlns:browser="http://namespaces.zope.org/browser"
+ i18n_domain="foo">
+
+ <paymentprocessors:registerProcessor
+ name="dummy"
+
processor="Products.PloneGetPaid.tests.dummy_processors.DummyProcessor"
+ selection_view="dummy_payment_processor_button"
+ thank_you_view="dummy_payment_processor_thank_you_page"
+ settings_view="dummy_payment_processor_settings"
+ />
+
+ <browser:page
+ for="getpaid.core.interfaces.IStore"
+ name="dummy_payment_processor_button"
+ class="Products.PloneGetPaid.tests.dummy_processors.DummyButton"
+ permission="zope2.View"
+ template="templates/button.pt"
+ />
+
+ <browser:page
+ for="getpaid.core.interfaces.IStore"
+ name="dummy_payment_processor_thank_you_page"
+ class="Products.PloneGetPaid.tests.dummy_processors.DummyThankYou"
+ permission="zope2.View"
+ template="templates/thank_you.pt"
+ />
+
+ <browser:page
+ for="getpaid.core.interfaces.IStore"
+ name="dummy_payment_processor_settings"
+ class="Products.PloneGetPaid.browser.admin.PaymentProcessor"
+ permission="cmf.ManagePortal"
+ />
+
+</configure>'''
+
+# Enable two dummy payment processors
+configure_zcml_2 = '''
+<configure
+ xmlns="http://namespaces.zope.org/zope"
+ xmlns:five="http://namespaces.zope.org/five"
+
xmlns:paymentprocessors="http://namespaces.plonegetpaid.com/paymentprocessors"
+ i18n_domain="foo">
+
+ <paymentprocessors:registerProcessor
+ name="dummy2"
+
processor="Products.PloneGetPaid.tests.dummy_processors.DummyProcessor"
+ selection_view="dummy_payment_processor_button"
+ thank_you_view="dummy_payment_processor_thank_you_page"
+ />
+
+</configure>'''
\ No newline at end of file

Added:
Products.PloneGetPaid/branches/multiplepaymentprocessors/Products/PloneGetPaid/tests/templates/button.pt
==============================================================================
--- (empty file)
+++
Products.PloneGetPaid/branches/multiplepaymentprocessors/Products/PloneGetPaid/tests/templates/button.pt
Tue Jun 9 09:11:28 2009
@@ -0,0 +1,11 @@
+<tr i18n:domain="getpaid.dummypaymentprocessor" tal:define="processor
view/getProcessor">
+
+ <td >
+ <input name="payment-method" type="radio" tal:attributes="value
processor/name">
+ <img src="foobar.jpg" alt="Magical processor"/>
+ </td>
+ <td i18n:translate="dummy_payment_method_description">
+ Magical string checked by unit tests
+ </td>
+</tr>
+

Added:
Products.PloneGetPaid/branches/multiplepaymentprocessors/Products/PloneGetPaid/tests/templates/thank_you.pt
==============================================================================
--- (empty file)
+++
Products.PloneGetPaid/branches/multiplepaymentprocessors/Products/PloneGetPaid/tests/templates/thank_you.pt
Tue Jun 9 09:11:28 2009
@@ -0,0 +1,35 @@
+<metal:page
use-macro="context/@@getpaid-content-template/macros/content_space"
+ i18n:domain="plonegetpaid">
+ <metal:block fill-slot="getpaid_content">
+
+
+ <h3 i18n:translate="heading_checkout_thank_you"> Thank you for your
order </h3>
+
+ <div tal:condition="view/getInvoice">
+ <div>
+ <span i18n:translate="your_order_id">
+ Your order id is
+ </span>
+ <tal:replace tal:replace="view/getInvoice"></tal:replace>
+ </div>
+
+ <div tal:condition="not:isAnon">
+ <span i18n:translate="box_order_status_url_description">You can
check the status of your order
+ <span i18n:name="status_url">
+ <a href=""
+ tal:attributes="href view/getURL"
+ i18n:translate="">here</a>
+ </span>
+ </span>
+ </div>
+
+ <div class="documentActions">
+ <a href="javascript:this.print()" i18n:domain="plone"
i18n:translate="">
+ Print this page
+ </a>
+ </div>
+ </div>
+
+
+ </metal:block>
+</metal:page>

Added:
Products.PloneGetPaid/branches/multiplepaymentprocessors/Products/PloneGetPaid/tests/test_payment_processors.py
==============================================================================
--- (empty file)
+++
Products.PloneGetPaid/branches/multiplepaymentprocessors/Products/PloneGetPaid/tests/test_payment_processors.py
Tue Jun 9 09:11:28 2009
@@ -0,0 +1,179 @@
+"""
+
+ Multiple payment processors test cases.
+
+"""
+import os, sys
+import unittest
+
+from Products.Five import zcml
+from zope.configuration.exceptions import ConfigurationError
+
+from base import PloneGetPaidTestCase
+from getpaid.paymentprocessors.registry import
BadViewConfigurationException, paymentProcessorRegistry
+import dummy_processors
+
+class TestPaymentMethods(PloneGetPaidTestCase):
+ """ Test ZCML directives """
+
+ def afterSetUp(self):
+ PloneGetPaidTestCase.afterSetUp(self)
+ paymentProcessorRegistry.clear()
+
+ def loadDummyZCML(self, string):
+ """ Load ZCML as a string and set the folder so that template
references are related correctly. """
+ module = sys.modules[__name__]
+ dir = os.path.dirname(module.__file__)
+ os.chdir(dir)
+ zcml.load_string(string)
+
+ def render_admin(self):
+ """ Test rendering admin interface views with the current
paymentprocessor configuration. """
+
+ # Render the page where you can choose which payment processor
settings are managed
+
+ self.loginAsPortalOwner()
+ view =
self.portal.restrictedTraverse("@@manage-getpaid-payment-processor")
+ view()
+ self.logout()
+
+
+ def get_payment_method_selection_screen(self):
+ """ Get the checkout payment method selection view via checkout
wizard """
+
+ # Force in checkout wizard step
+ step = "checkout-payment-method"
+ self.portal.REQUEST["cur_step"] = step # See _wizard.pt
+ wizard =
self.portal.restrictedTraverse("@@getpaid-checkout-wizard")
+
+ view = wizard.controller.getCurrentStep()
+ return view
+
+ def render_payment_method_selection_screen(self,
assertedProcessorCount):
+ """ Test rendering payment method selection page in checkout
wizard """
+
+ view = self.get_payment_method_selection_screen()
+
+ processors = view.getProcessors()
+ self.assertEqual(len(processors), assertedProcessorCount)
+
+ # Render payment method selection HTML - see that template doesn't
raise an error
+ # TODO: Check HTML output validy using functional tests
+ view()
+
+
+ def test_selection_screen_no_processor(self):
+ """ Test different count of site payment processors """
+
+ # Go to checkout process point where the payment method is selected
+ self.render_payment_method_selection_screen(0)
+
+
self.portal.portal_properties.payment_processor_properties.enabled_processors
= []
+
+ # Test rendering related admin interface pages and hope to catch
all raised exceptions
+ self.render_admin()
+
+ def test_selection_screen_one_processor(self):
+ """ Test different count of site payment processors """
+ self.loadDummyZCML(dummy_processors.configure_zcml)
+
+
self.portal.portal_properties.payment_processor_properties.enabled_processors
= [ "dummy"]
+
+ # Go to checkout process point where the payment method is selected
+ self.render_payment_method_selection_screen(1)
+
+ # Test rendering related admin interface pages and hope to catch
all raised exceptions
+ self.render_admin()
+
+
+ def test_selection_screen_n_processors(self):
+ """ Test different count of site payment processors """
+ self.loadDummyZCML(dummy_processors.configure_zcml)
+ self.loadDummyZCML(dummy_processors.configure_zcml_2)
+
+
self.portal.portal_properties.payment_processor_properties.enabled_processors
= [ "dummy", "dummy2"]
+
+ # Go to checkout process point where the payment method is selected
+ self.render_payment_method_selection_screen(2)
+
+ # Test rendering related admin interface pages and hope to catch
all raised exceptions
+ self.render_admin()
+
+ def test_bad_view_definition(self):
+ """ Try refering non-existing browser:page in payment processor """
+ bad_button_configure_zcml = '''
+ <configure
+ xmlns="http://namespaces.zope.org/zope"
+ xmlns:five="http://namespaces.zope.org/five"
+
xmlns:paymentprocessors="http://namespaces.plonegetpaid.com/paymentprocessors"
+ xmlns:browser="http://namespaces.zope.org/browser"
+ i18n_domain="foo">
+
+ <paymentprocessors:registerProcessor
+ name="dummy"
+
processor="Products.PloneGetPaid.tests.dummy_processors.DummyProcessor"
+ selection_view="BAD_ENTRY_HERE"
+ thank_you_view="dummy_payment_processor_thank_you_page"
+ />
+
+ </configure>'''
+ zcml.load_string(bad_button_configure_zcml)
+
self.portal.portal_properties.payment_processor_properties.enabled_processors
= [ "dummy" ]
+ try:
+ self.render_payment_method_selection_screen(1)
+ raise AssertionError("Should not be never reached")
+ except BadViewConfigurationException:
+ pass
+
+ def test_choose_available_payment_processors(self):
+ """ Test admin page where you can enabled different payment
processors on the site """
+ self.loadDummyZCML(dummy_processors.configure_zcml)
+ self.loginAsPortalOwner()
+
+ # Do fake POST
+ request = self.portal.REQUEST
+ request["REQUEST_METHOD"] = "POST"
+ request["active-payment-processors"] =["dummy"]
+
+ view =
self.portal.restrictedTraverse("@@manage-getpaid-payment-processor")
+ view()
+
self.assertEqual(self.portal.portal_properties.payment_processor_properties.enabled_processors,
["dummy"])
+
+ def test_settings_view(self):
+ """ Render settings view for an payment processor. """
+ self.loadDummyZCML(dummy_processors.configure_zcml)
+ self.loginAsPortalOwner()
+
self.portal.restrictedTraverse("@@dummy_payment_processor_settings")
+
+
+ def test_payment(self):
+
+ self.loadDummyZCML(dummy_processors.configure_zcml)
+
+
self.portal.portal_properties.payment_processor_properties.enabled_processors
= [ "dummy"]
+
+ view = self.get_payment_method_selection_screen()
+ html = view()
+
+ self.assertTrue('name="dummy"' in html) # Check that payment
processor button is rendered there
+
+ # Now simulate POST
+ request = self.portal.REQUEST
+ request["REQUEST_METHOD"] = "POST"
+ request["dummy"] = 'dummy' # <button> submit
+
+ view = get_payment_method_selection_screen()
+
+ # Now we should contain the payment data in the wizard
+ step = "checkout-review-pay"
+ self.portal.REQUEST["cur_step"] = step # See _wizard.pt
+ wizard =
self.portal.restrictedTraverse("@@getpaid-checkout-wizard")
+
+ entry = self.wizard.data_manager.get("payment_method")
+ self.assertEqual(entry, "dummy")
+
+def test_suite():
+ from unittest import TestSuite, makeSuite
+ suite = TestSuite()
+ suite.addTest(makeSuite(TestPaymentMethods))
+ return suite

Reply all
Reply to author
Forward
0 new messages