Django Virtual Pos
==================
Django module that abstracts the flow of several virtual points of sale
including PayPal
What’s this?
-------------------------
This module abstracts the use of the most used virtual points of sale in
Spain.
License
-------------------------
`MIT LICENSE`_.
Implemented payment methods
----------------------------
Paypal
-------------------------
`Paypal`_ paypal payment available.
Bitpay
-------------------------
`Bitpay`_ bitcoin payments, from wallet to checkout
Spanish Virtual Points of Sale
------------------------------
- Ceca
`CECA`_ is the Spanish confederation of savings banks.
- RedSyS
`RedSyS`_ gives payment services to several Spanish banks like CaixaBank
or Caja Rural.
Santander Elavon
----------------
`Santander Elavon`_ is one of the payment methods of the Spanish bank
Santander.
Requirements and Installation
==============================
Requirements
----------------
- Python 2.7 (Python 3 not tested, contributors wanted!)
- ``Django``
- ``BeautifulSoup4``
- ``lxml``
- ``pycrypto``
- ``Pytz``
- ``Requests``
Type:
.. code:: sh
$ pip install django beautifulsoup4 lxml pycrypto pytz
Installation
----------------
From PyPi
----------------
.. code:: sh
$ pip install django-virtual-pos
From master branch
-------------------
Master branch will allways contain a working version of this module.
.. code:: sh
$ pip install git+git://github.com/intelligenia/django-virtual-pos.git
settings.py
-------------
Add the application djangovirtualpos to your settings.py:
.. code:: python
INSTALLED_APPS = (
# ...
"djangovirtualpos",
)
Use
----
See this ``manual`` (currently only in Spanish).
Needed models
-------------
You will need to implement this skeleton view using your own **Payment**
model.
This model has must have at least the following attributes: - **code**:
sale code given by our system. - **operation_number**: bank operation
number. - **status**: status of the payment: “paid”, “pending”
(**pending** is mandatory) or “canceled”. - **amount**: amount to be
charged.
And the following methods: - **online_confirm**: mark the payment as
paid.
Integration examples
-----------------------
- ``djshop``
Needed views
--------------
Sale summary view
------------------
.. code:: python
def payment_summary(request, payment_id):
"""
Load a Payment object and show a summary of its contents to the user.
"""
payment = get_object_or_404(Payment, id=payment_id, status="pending")
replacements = {
"payment": payment,
# ...
}
return render(request, '<sale summary template path>', replacements)
Note that this payment summary view should load a JS file called
**set_payment_attributes.js**.
This file is needed to set initial payment attributes according to which
bank have the user selected.
Payment_confirm view
-------------------------
.. code:: python
@csrf_exempt
def payment_confirmation(request, virtualpos_type):
"""
This view will be called by the bank.
"""
# Directly call to confirm_payment view
# Or implement the following actions
# Checking if the Point of Sale exists
virtual_pos = VirtualPointOfSale.receiveConfirmation(request, virtualpos_type=virtualpos_type)
if not virtual_pos:
# The VPOS does not exist, inform the bank with a cancel
# response if needed
return VirtualPointOfSale.staticResponseNok(virtualpos_type)
# Verify if bank confirmation is indeed from the bank
verified = virtual_pos.verifyConfirmation()
operation_number = virtual_pos.operation.operation_number
with transaction.atomic():
try:
# Getting your payment object from operation number
payment = Payment.objects.get(operation_number=operation_number, status="pending")
except Payment.DoesNotExist:
return virtual_pos.responseNok("not_exists")
if verified:
# Charge the money and answer the bank confirmation
try:
response = virtual_pos.charge()
# Implement the online_confirm method in your payment
# this method will mark this payment as paid and will
# store the payment date and time.
payment.online_confirm()
except VPOSCantCharge as e:
return virtual_pos.responseNok(extended_status=e)
except Exception as e:
return virtual_pos.responseNok("cant_charge")
else:
# Payment could not be verified
# signature is not right
response = virtual_pos.responseNok("verification_error")
return response
Payment ok view
-------------------------
.. code:: python
def payment_ok(request, sale_code):
"""
Informs the user that the payment has been made successfully
:param payment_code: Payment code.
:param request: request.
"""
# Load your Payment model given its code
payment = get_object_or_404(Payment, code=sale_code, status="paid")
context = {'pay_status': "Done", "request": request}
return render(request, '<payment_ok template>', {'context': context, 'payment': payment})
Payment cancel view
--------------------
.. code:: python
def payment_cancel(request, sale_code):
"""
Informs the user that the payment has been canceled
:param payment_code: Payment code.
:param request: request.
"""
# Load your Payment model given its code
payment = get_object_or_404(Payment, code=sale_code, status="pending")
# Mark this payment as canceled
payment.cancel()
context = {'pay_status': "Done", "request": request}
return render(request, '<payment_canceled template>', {'context': context, 'payment': payment})
Refund view
-----------
.. code:: python
def refund(request, tpv, payment_code, amount, description):
"""
:param request:
:param tpv: TPV Id
:param payment_code: Payment code
:param amount: Refund Amount (Example 10.89).
:param description: Description of refund cause.
:return:
"""
amount = Decimal(amount)
try:
# Checking if the Point of Sale exists
tpv = VirtualPointOfSale.get(id=tpv)
# Checking if the Payment exists
payment = Payment.objects.get(code=payment_code, state="paid")
except Payment.DoesNotExist as e:
return http_bad_request_response_json_error(message=u"Does not exist payment with code {0}".format(payment_code))
refund_status = tpv.refund(payment_code, amount, description)
if refund_status:
message = u"Refund successful"
else:
message = u"Refund with erros"
return http_response_json_ok(message)
Authors
===============
- Mario Barchéin marioREMOVETHIS@REMOVETHISintelligenia.com
- Diego J. Romero diegoREMOVETHIS@REMOVETHISintelligenia.com
Remove REMOVETHIS to contact the authors.
.. _MIT LICENSE: LICENSE
.. _Paypal: https://www.paypal.com/
.. _Bitpay: http://bitpay.com
.. _CECA: http://www.cajasdeahorros.es/
.. _RedSyS: http://www.redsys.es/
.. _Santander Elavon: https://www.santanderelavon.com/
.. _Django: https://pypi.python.org/pypi/django
.. _BeautifulSoup4: https://pypi.python.org/pypi/beautifulsoup4
.. _lxml: https://pypi.python.org/pypi/lxml
.. _pycrypto: https://pypi.python.org/pypi/pycrypto
.. _Pytz: https://pypi.python.org/pypi/pytz
.. _Requests: https://pypi.python.org/pypi/requests
.. _manual: manual/COMMON.md
.. _djshop: https://github.com/diegojromerolopez/djshop
Raw data
{
"_id": null,
"home_page": "https://github.com/intelligenia/django-virtual-pos",
"name": "django-virtual-pos",
"maintainer": null,
"docs_url": null,
"requires_python": ">=2.7.0",
"maintainer_email": null,
"keywords": "virtual, point-of-sale, puchases, online, payments",
"author": "intelligenia",
"author_email": "mario@intelligenia.com",
"download_url": "https://files.pythonhosted.org/packages/13/cc/300fa8f61bfee3d73e14650dadfee55d5575c7c17c2e6330d1f5b6452b91/django-virtual-pos-1.7.1.tar.gz",
"platform": null,
"description": "Django Virtual Pos\n==================\n\nDjango module that abstracts the flow of several virtual points of sale\nincluding PayPal\n\nWhat\u2019s this?\n-------------------------\n\nThis module abstracts the use of the most used virtual points of sale in\nSpain.\n\nLicense\n-------------------------\n\n`MIT LICENSE`_.\n\nImplemented payment methods\n----------------------------\n\nPaypal\n-------------------------\n\n`Paypal`_ paypal payment available.\n\nBitpay\n-------------------------\n\n`Bitpay`_ bitcoin payments, from wallet to checkout\n\nSpanish Virtual Points of Sale\n------------------------------\n\n- Ceca\n\n\n`CECA`_ is the Spanish confederation of savings banks.\n\n- RedSyS\n\n`RedSyS`_ gives payment services to several Spanish banks like CaixaBank\nor Caja Rural.\n\nSantander Elavon\n----------------\n\n`Santander Elavon`_ is one of the payment methods of the Spanish bank\nSantander.\n\nRequirements and Installation\n==============================\n\nRequirements\n----------------\n\n- Python 2.7 (Python 3 not tested, contributors wanted!)\n- ``Django``\n- ``BeautifulSoup4``\n- ``lxml``\n- ``pycrypto``\n- ``Pytz``\n- ``Requests``\n\nType:\n\n.. code:: sh\n\n $ pip install django beautifulsoup4 lxml pycrypto pytz\n\nInstallation\n----------------\n\n\nFrom PyPi\n----------------\n\n.. code:: sh\n\n $ pip install django-virtual-pos\n\nFrom master branch\n-------------------\n\nMaster branch will allways contain a working version of this module.\n\n.. code:: sh\n\n $ pip install git+git://github.com/intelligenia/django-virtual-pos.git\n\nsettings.py\n-------------\n\nAdd the application djangovirtualpos to your settings.py:\n\n.. code:: python\n\n INSTALLED_APPS = (\n # ...\n \"djangovirtualpos\",\n )\n\nUse\n----\n\nSee this ``manual`` (currently only in Spanish).\n\nNeeded models\n-------------\n\nYou will need to implement this skeleton view using your own **Payment**\nmodel.\n\nThis model has must have at least the following attributes: - **code**:\nsale code given by our system. - **operation_number**: bank operation\nnumber. - **status**: status of the payment: \u201cpaid\u201d, \u201cpending\u201d\n(**pending** is mandatory) or \u201ccanceled\u201d. - **amount**: amount to be\ncharged.\n\nAnd the following methods: - **online_confirm**: mark the payment as\npaid.\n\nIntegration examples\n-----------------------\n\n- ``djshop``\n\nNeeded views\n--------------\n\nSale summary view\n------------------\n\n.. code:: python\n\n def payment_summary(request, payment_id):\n \"\"\"\n Load a Payment object and show a summary of its contents to the user.\n \"\"\"\n\n payment = get_object_or_404(Payment, id=payment_id, status=\"pending\")\n replacements = {\n \"payment\": payment,\n # ...\n }\n return render(request, '<sale summary template path>', replacements)\n\nNote that this payment summary view should load a JS file called\n**set_payment_attributes.js**.\n\nThis file is needed to set initial payment attributes according to which\nbank have the user selected.\n\nPayment_confirm view\n-------------------------\n\n.. code:: python\n\n @csrf_exempt\n def payment_confirmation(request, virtualpos_type):\n \t\"\"\"\n \tThis view will be called by the bank.\n \t\"\"\"\n \t# Directly call to confirm_payment view\n\n \t# Or implement the following actions\n\n \t# Checking if the Point of Sale exists\n \tvirtual_pos = VirtualPointOfSale.receiveConfirmation(request, virtualpos_type=virtualpos_type)\n\n \tif not virtual_pos:\n \t\t# The VPOS does not exist, inform the bank with a cancel\n \t\t# response if needed\n \t\treturn VirtualPointOfSale.staticResponseNok(virtualpos_type)\n\n \t# Verify if bank confirmation is indeed from the bank\n \tverified = virtual_pos.verifyConfirmation()\n \toperation_number = virtual_pos.operation.operation_number\n\n \twith transaction.atomic():\n \t\ttry:\n \t\t\t# Getting your payment object from operation number\n \t\t\tpayment = Payment.objects.get(operation_number=operation_number, status=\"pending\")\n \t\texcept Payment.DoesNotExist:\n \t\t\treturn virtual_pos.responseNok(\"not_exists\")\n\n \t\tif verified:\n \t\t\t# Charge the money and answer the bank confirmation\n \t\t\ttry:\n \t\t\t\tresponse = virtual_pos.charge()\n \t\t\t\t# Implement the online_confirm method in your payment\n \t\t\t\t# this method will mark this payment as paid and will\n \t\t\t\t# store the payment date and time.\n \t\t\t\tpayment.online_confirm()\n \t\t\texcept VPOSCantCharge as e:\n \t\t\t\treturn virtual_pos.responseNok(extended_status=e)\n \t\t\texcept Exception as e:\n \t\t\t\treturn virtual_pos.responseNok(\"cant_charge\")\n\n \t\telse:\n \t\t\t# Payment could not be verified\n \t\t\t# signature is not right\n \t\t\tresponse = virtual_pos.responseNok(\"verification_error\")\n\n \t\treturn response\n\nPayment ok view\n-------------------------\n\n.. code:: python\n\n def payment_ok(request, sale_code):\n \"\"\"\n Informs the user that the payment has been made successfully\n :param payment_code: Payment code.\n :param request: request.\n \"\"\"\n\n # Load your Payment model given its code\n payment = get_object_or_404(Payment, code=sale_code, status=\"paid\")\n\n context = {'pay_status': \"Done\", \"request\": request}\n return render(request, '<payment_ok template>', {'context': context, 'payment': payment})\n\nPayment cancel view\n--------------------\n\n.. code:: python\n\n def payment_cancel(request, sale_code):\n \"\"\"\n Informs the user that the payment has been canceled\n :param payment_code: Payment code.\n :param request: request.\n \"\"\"\n\n # Load your Payment model given its code\n payment = get_object_or_404(Payment, code=sale_code, status=\"pending\")\n # Mark this payment as canceled\n payment.cancel()\n\n context = {'pay_status': \"Done\", \"request\": request}\n return render(request, '<payment_canceled template>', {'context': context, 'payment': payment})\n\n\nRefund view\n-----------\n\n.. code:: python\n\n def refund(request, tpv, payment_code, amount, description):\n \t\"\"\"\n \t:param request:\n \t:param tpv: TPV Id\n \t:param payment_code: Payment code\n \t:param amount: Refund Amount (Example 10.89).\n \t:param description: Description of refund cause.\n \t:return:\n \t\"\"\"\n\n \tamount = Decimal(amount)\n\n \ttry:\n \t\t# Checking if the Point of Sale exists\n \t\ttpv = VirtualPointOfSale.get(id=tpv)\n \t\t# Checking if the Payment exists\n \t\tpayment = Payment.objects.get(code=payment_code, state=\"paid\")\n\n \texcept Payment.DoesNotExist as e:\n \t\treturn http_bad_request_response_json_error(message=u\"Does not exist payment with code {0}\".format(payment_code))\n\n \trefund_status = tpv.refund(payment_code, amount, description)\n\n \tif refund_status:\n \t\tmessage = u\"Refund successful\"\n \telse:\n \t\tmessage = u\"Refund with erros\"\n\n \treturn http_response_json_ok(message)\n\nAuthors\n===============\n\n- Mario Barch\u00e9in marioREMOVETHIS@REMOVETHISintelligenia.com\n- Diego J. Romero diegoREMOVETHIS@REMOVETHISintelligenia.com\n\nRemove REMOVETHIS to contact the authors.\n\n\n.. _MIT LICENSE: LICENSE\n.. _Paypal: https://www.paypal.com/\n.. _Bitpay: http://bitpay.com\n.. _CECA: http://www.cajasdeahorros.es/\n.. _RedSyS: http://www.redsys.es/\n.. _Santander Elavon: https://www.santanderelavon.com/\n.. _Django: https://pypi.python.org/pypi/django\n.. _BeautifulSoup4: https://pypi.python.org/pypi/beautifulsoup4\n.. _lxml: https://pypi.python.org/pypi/lxml\n.. _pycrypto: https://pypi.python.org/pypi/pycrypto\n.. _Pytz: https://pypi.python.org/pypi/pytz\n.. _Requests: https://pypi.python.org/pypi/requests\n.. _manual: manual/COMMON.md\n.. _djshop: https://github.com/diegojromerolopez/djshop\n\n",
"bugtrack_url": null,
"license": "MIT",
"summary": "django-virtual-pos is a module that abstracts the flow of paying in several online payment platforms.",
"version": "1.7.1",
"project_urls": {
"Homepage": "https://github.com/intelligenia/django-virtual-pos"
},
"split_keywords": [
"virtual",
" point-of-sale",
" puchases",
" online",
" payments"
],
"urls": [
{
"comment_text": "",
"digests": {
"blake2b_256": "42b5ab82443ed8b807642cebbf34030b127e1278657994d25a00aceb2bf134f4",
"md5": "239bc2f7a576840b71c769f5e6fe4dc3",
"sha256": "85c80d7a1ddbd527a2bd016bf2ed250e77e2ac1f1936cdf3e2010f8cec7e94d0"
},
"downloads": -1,
"filename": "django_virtual_pos-1.7.1-py2.py3-none-any.whl",
"has_sig": false,
"md5_digest": "239bc2f7a576840b71c769f5e6fe4dc3",
"packagetype": "bdist_wheel",
"python_version": "py2.py3",
"requires_python": ">=2.7.0",
"size": 62497,
"upload_time": "2024-07-23T13:26:11",
"upload_time_iso_8601": "2024-07-23T13:26:11.635421Z",
"url": "https://files.pythonhosted.org/packages/42/b5/ab82443ed8b807642cebbf34030b127e1278657994d25a00aceb2bf134f4/django_virtual_pos-1.7.1-py2.py3-none-any.whl",
"yanked": false,
"yanked_reason": null
},
{
"comment_text": "",
"digests": {
"blake2b_256": "13cc300fa8f61bfee3d73e14650dadfee55d5575c7c17c2e6330d1f5b6452b91",
"md5": "d62bc0f69e4007e8daf513d412d14570",
"sha256": "6664bc98f1af6b831157287b356b742a8291e7b153fc7228f7e2c37464f8e25d"
},
"downloads": -1,
"filename": "django-virtual-pos-1.7.1.tar.gz",
"has_sig": false,
"md5_digest": "d62bc0f69e4007e8daf513d412d14570",
"packagetype": "sdist",
"python_version": "source",
"requires_python": ">=2.7.0",
"size": 55319,
"upload_time": "2024-07-23T13:26:14",
"upload_time_iso_8601": "2024-07-23T13:26:14.148317Z",
"url": "https://files.pythonhosted.org/packages/13/cc/300fa8f61bfee3d73e14650dadfee55d5575c7c17c2e6330d1f5b6452b91/django-virtual-pos-1.7.1.tar.gz",
"yanked": false,
"yanked_reason": null
}
],
"upload_time": "2024-07-23 13:26:14",
"github": true,
"gitlab": false,
"bitbucket": false,
"codeberg": false,
"github_user": "intelligenia",
"github_project": "django-virtual-pos",
"travis_ci": false,
"coveralls": false,
"github_actions": false,
"lcname": "django-virtual-pos"
}