Skip to content

Commit

Permalink
Initial commit
Browse files Browse the repository at this point in the history
  • Loading branch information
Joeri Djojosoeparto committed Sep 26, 2011
0 parents commit b125ca9
Show file tree
Hide file tree
Showing 17 changed files with 457 additions and 0 deletions.
3 changes: 3 additions & 0 deletions MANIFEST.in
Original file line number Diff line number Diff line change
@@ -0,0 +1,3 @@
recursive-include multisafepay *
recursive-include etc *
global-exclude *pyc
17 changes: 17 additions & 0 deletions PKG-INFO
Original file line number Diff line number Diff line change
@@ -0,0 +1,17 @@
Metadata-Version: 1.0
Name: multisafepay
Version: 0.1.5
Summary: Multisafepay integration
Home-page: http://www.pareto.nl
Author: Jan Murre
Author-email: [email protected]
License: Apache
Description: This package enables you to talk to a multisafepay
payment provider. There is not much documentation at the moment. In the
package are tests that give you a good starting point.

Platform: UNKNOWN
Classifier: Operating System :: OS Independent
Classifier: Programming Language :: Python
Classifier: Topic :: Internet :: WWW/HTTP
Classifier: Topic :: Software Development :: Libraries :: Python Modules
7 changes: 7 additions & 0 deletions etc/serve.ini
Original file line number Diff line number Diff line change
@@ -0,0 +1,7 @@
[app:main]
use = egg:multisafepay

[server:main]
use = egg:PasteScript#wsgiutils
host = 127.0.0.1
port = 9000
17 changes: 17 additions & 0 deletions multisafepay.egg-info/PKG-INFO
Original file line number Diff line number Diff line change
@@ -0,0 +1,17 @@
Metadata-Version: 1.0
Name: multisafepay
Version: 0.1.5
Summary: Multisafepay integration
Home-page: http://www.pareto.nl
Author: Jan Murre
Author-email: [email protected]
License: Apache
Description: This package enables you to talk to a multisafepay
payment provider. There is not much documentation at the moment. In the
package are tests that give you a good starting point.

Platform: UNKNOWN
Classifier: Operating System :: OS Independent
Classifier: Programming Language :: Python
Classifier: Topic :: Internet :: WWW/HTTP
Classifier: Topic :: Software Development :: Libraries :: Python Modules
15 changes: 15 additions & 0 deletions multisafepay.egg-info/SOURCES.txt
Original file line number Diff line number Diff line change
@@ -0,0 +1,15 @@
MANIFEST.in
setup.py
etc/serve.ini
multisafepay/__init__.py
multisafepay/status.py
multisafepay/test_msp.py
multisafepay/testhttpserver.py
multisafepay/transaction.py
multisafepay.egg-info/PKG-INFO
multisafepay.egg-info/SOURCES.txt
multisafepay.egg-info/dependency_links.txt
multisafepay.egg-info/entry_points.txt
multisafepay.egg-info/not-zip-safe
multisafepay.egg-info/requires.txt
multisafepay.egg-info/top_level.txt
1 change: 1 addition & 0 deletions multisafepay.egg-info/dependency_links.txt
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@

6 changes: 6 additions & 0 deletions multisafepay.egg-info/entry_points.txt
Original file line number Diff line number Diff line change
@@ -0,0 +1,6 @@
[paste.app_factory]
main = multisafepay.testhttpserver:app_factory

[console_scripts]
msp_serve = multisafepay.testhttpserver:main

1 change: 1 addition & 0 deletions multisafepay.egg-info/not-zip-safe
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@

1 change: 1 addition & 0 deletions multisafepay.egg-info/requires.txt
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
otto
1 change: 1 addition & 0 deletions multisafepay.egg-info/top_level.txt
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
multisafepay
1 change: 1 addition & 0 deletions multisafepay/__init__.py
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
#
Empty file added multisafepay/status.py
Empty file.
57 changes: 57 additions & 0 deletions multisafepay/test_msp.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,57 @@
from time import sleep
import pytest
from multisafepay.transaction import Transaction, MSPError, get_status
from testhttpserver import TestServer


def pytest_funcarg__wsgiserver(request):
# Module level startup of wsgi server
# so it is started only once for all test runs

def setup_wsgisrvr():
srv = TestServer()
srv.run()
# give some time to start server
sleep(1)
print 'wsgi started'
return srv

def teardown_wsgisrv(srv):
srv.stop()

request.cached_setup(
setup=setup_wsgisrvr,
teardown=teardown_wsgisrv,
scope='module')


def test_msp_ok(wsgiserver):
transaction = Transaction(account='a', site_id='b', site_secure_code='c',
notification_url='http://localhost/notify', cancel_url='',
locale='nl_NL', ipaddress='1.2.3.4', email='[email protected]',
transaction_id='1234', amount='2300', description='party',
api_url='http://localhost:9000/ok')
res = transaction.start()
assert res == 'http://localhost:9000/paylink'


def test_msp_error(wsgiserver):
transaction = Transaction(account='a', site_id='b', site_secure_code='c',
notification_url='http://localhost/notify', cancel_url='',
locale='nl_NL', ipaddress='1.2.3.4', email='[email protected]',
transaction_id='1234', amount='2300', description='party',
api_url='http://localhost:9000/error')
pytest.raises(MSPError, transaction.start)


def test_status(wsgiserver):
status = get_status(account='a', site_id='b', site_secure_code='c',
transaction_id='1234', api_url='http://localhost:9000/status_ok')
assert status == 'completed'


def test_status_error(wsgiserver):
pytest.raises(MSPError, get_status, account='a', site_id='b',
site_secure_code='c',
transaction_id='1234',
api_url='http://localhost:9000/status_error')
178 changes: 178 additions & 0 deletions multisafepay/testhttpserver.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,178 @@
# from wsgiref.util import setup_testing_defaults
import sys
from string import Template
import urllib
from wsgiref.simple_server import make_server
from xml.etree import ElementTree as ET
from multiprocessing import Process
from otto import Application as BaseApplication
from webob import Response


ok_response = \
"""<?xml version="1.0" encoding="UTF-8" ?>
<redirecttransaction result="ok">
<transaction>
<id>4084044</id>
<payment_url>http://$host:$port/paylink</payment_url>
</transaction>
</redirecttransaction>
"""

error_response =\
"""<?xml version="1.0" encoding="UTF-8"?>
<redirecttransaction result="error">
<error>
<code>1013</code>
<description>MD5 mismatch</description>
</error>
<transaction>
<id>4084044</id>
</transaction>
</redirecttransaction>
"""

status_ok_response = \
"""<?xml version="1.0" encoding="UTF-8"?>
<status result="ok">
<ewallet>
<id>80675</id>
<status>completed</status>
<created>20100415132654</created>
<modified/>
</ewallet>
<customer>
<currency>EUR</currency>
<amount>1000</amount>
<exchange_rate>1</exchange_rate>
<firstname>Jan</firstname>
<lastname>Modaal</lastname>
<city>Amsterdam</city>
<state/>
<country>NL</country>
<countryname>Netherlands</countryname>
</customer>
<transaction>
<id>4084044</id>
<currency>EUR</currency>
<amount>1000</amount>
<description>Test transaction</description>
<var1/>
<var2/>
<var3/>
<items/>
</transaction>
</status>"""

pay_response = \
"""<html>
<body>
$shop_return_link
<a href="$cancel_url">cancel</a>
</body>
</html>"""


class Application(BaseApplication):

def __init__(self):
super(Application, self).__init__()
self.notify_url = ''
self.transaction_id = 0
self.cancel_url = ''
self.host = 'localhost'
self.port = 9000

app = Application()


class TestServer(object):

def __init__(self, host='localhost', port=9000):
self.host = host
self.port = port

def run(self):

def run_server():
app.host = self.host
app.port = self.port
httpd = make_server(self.host, self.port, app)
print "Serving for '{0}' on port {1}...".format(
self.host, self.port)
httpd.serve_forever()

self.process = Process(target=run_server)
self.process.start()

def stop(self):
self.process.terminate()


@app.connect('/ok')
def ok_handler(request):
tree = ET.fromstring(request.body)
body = Template(ok_response).substitute(host=app.host,
port=app.port)
app.notify_url = tree.find('merchant/notification_url').text
app.cancel_url = tree.find('merchant/cancel_url').text
app.transaction_id = tree.find('transaction/id').text
return Response(content_type='application/xml',
body=body)


@app.connect('/paylink')
def paylink_handler(request):
return Response(content_type='text/html',
body='<a href="./pay">pay</a>')


@app.connect('/pay')
def pay_handler(request):
# do a request to the notify_url
# show the result in the template
f = urllib.urlopen('{0}&transactionid={1}'.format(
app.notify_url, app.transaction_id))
#f = urllib.urlopen('http://nu.nl')
shop_return_link = f.read()
f.close()
#shop_return_link =\
# '<a href="http://localhost:8000/shop/delivery/">return</a>'
return Response(content_type='text/html',
body=Template(pay_response).substitute(
shop_return_link=shop_return_link,
cancel_url=app.cancel_url))


@app.connect('/error')
def error_handler(request):
return Response(content_type='application/xml',
body=error_response)


@app.connect('/status_ok')
def status_ok_handler(request):
return Response(content_type='application/xml',
body=status_ok_response)


@app.connect('/status_error')
def status_error_handler(request):
return Response(content_type='application/xml',
body=error_response)


def main():
args = sys.argv[1:]
host = len(args) > 0 and args[0] or 'localhost'
port = len(args) > 1 and int(args[1]) or 9000
server = TestServer(host, port)
server.run()


def app_factory(global_config, **local_config):
""" creates an otto WSGI-compliant HTTP publisher. """
# config = ConfigParser()
# config.read(global_config['__file__'])
# app.set_config(config)
return app
Loading

0 comments on commit b125ca9

Please sign in to comment.