├── .built ├── .gitignore ├── Dockerfile ├── LICENSE ├── Makefile ├── README.md ├── __init__.py ├── docker-compose.yml ├── oneclick ├── __init__.py └── routes.py ├── oneclick_deferred ├── __init__.py └── routes.py ├── patpass_by_webpay ├── __init__.py └── routes.py ├── patpass_comercio ├── __init__.py └── routes.py ├── requirements.txt ├── tbk_examples.py ├── templates ├── include │ ├── footer.html │ └── header.html ├── index.html ├── oneclick │ ├── authorize.html │ ├── deferred │ │ ├── authorize.html │ │ ├── authorized.html │ │ ├── capture.html │ │ ├── delete.html │ │ ├── deleted.html │ │ ├── start.html │ │ ├── started.html │ │ ├── status.html │ │ └── status_form.html │ ├── delete.html │ ├── deleted.html │ ├── refund.html │ ├── start.html │ ├── started.html │ ├── status.html │ └── status_form.html ├── patpass_comercio │ ├── finish_inscription.html │ ├── start_inscription.html │ ├── status.html │ └── voucher_displayed.html ├── transaccion_completa │ ├── create.html │ ├── created.html │ ├── deferred │ │ ├── capture.html │ │ ├── commit.html │ │ ├── create.html │ │ ├── created.html │ │ └── status.html │ ├── installments.html │ ├── refund-form.html │ ├── status-form.html │ ├── transaction_committed.html │ ├── transaction_refunded.html │ └── transaction_status.html ├── transaccion_completa_mall │ ├── create.html │ ├── created.html │ ├── deferred │ │ ├── capture.html │ │ ├── commit.html │ │ ├── create.html │ │ ├── created.html │ │ ├── installments.html │ │ ├── status.html │ │ ├── transaction_committed.html │ │ └── transaction_refunded.html │ ├── installments.html │ ├── refund-form.html │ ├── status-form.html │ ├── transaction_committed.html │ ├── transaction_refunded.html │ └── transaction_status.html └── webpay │ ├── patpass │ ├── commit.html │ ├── create.html │ ├── status-form.html │ └── status.html │ ├── plus │ ├── commit.html │ ├── create.html │ ├── refund-form.html │ ├── refund.html │ ├── status-form.html │ └── status.html │ ├── plus_deferred │ ├── capture.html │ ├── commit.html │ ├── create.html │ ├── refund-form.html │ ├── refund.html │ ├── status-form.html │ └── status.html │ ├── plus_mall │ ├── commit.html │ ├── create.html │ ├── created.html │ ├── refund-form.html │ ├── refund.html │ ├── status-form.html │ └── status.html │ └── plus_mall_deferred │ ├── capture.html │ ├── commit.html │ ├── create.html │ ├── created.html │ ├── refund-form.html │ ├── refund.html │ ├── status-form.html │ └── status.html ├── transaccion_completa ├── __init__.py └── routes.py ├── transaccion_completa_deferred ├── __init__.py └── routes.py ├── transaccion_completa_mall ├── __init__.py └── routes.py ├── transaccion_completa_mall_deferred ├── __init__.py └── routes.py ├── webpay_plus ├── __init__.py └── routes.py ├── webpay_plus_deferred ├── __init__.py └── routes.py ├── webpay_plus_mall ├── __init__.py └── routes.py └── webpay_plus_mall_deferred ├── __init__.py └── routes.py /.built: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/TransbankDevelopers/transbank-sdk-python-webpay-rest-example/0caa3ee714b8ff4e9f481e19f2cda2a7756b916b/.built -------------------------------------------------------------------------------- /.gitignore: -------------------------------------------------------------------------------- 1 | __pycache__/ 2 | *.py[cod] 3 | *$py.class 4 | 5 | # C extensions 6 | *.so 7 | 8 | # Distribution / packaging 9 | .Python 10 | build/ 11 | develop-eggs/ 12 | dist/ 13 | downloads/ 14 | eggs/ 15 | .eggs/ 16 | lib/ 17 | lib64/ 18 | parts/ 19 | sdist/ 20 | var/ 21 | wheels/ 22 | *.egg-info/ 23 | .installed.cfg 24 | *.egg 25 | MANIFEST 26 | 27 | # PyInstaller 28 | # Usually these files are written by a python script from a template 29 | # before PyInstaller builds the exe, so as to inject date/other infos into it. 30 | *.manifest 31 | *.spec 32 | 33 | # Installer logs 34 | pip-log.txt 35 | pip-delete-this-directory.txt 36 | 37 | # Unit test / coverage reports 38 | htmlcov/ 39 | .tox/ 40 | .coverage 41 | .coverage.* 42 | .cache 43 | nosetests.xml 44 | coverage.xml 45 | *.cover 46 | .hypothesis/ 47 | .pytest_cache/ 48 | cover/ 49 | 50 | # Translations 51 | *.mo 52 | *.pot 53 | 54 | # Django stuff: 55 | *.log 56 | local_settings.py 57 | db.sqlite3 58 | 59 | # Flask stuff: 60 | instance/ 61 | .webassets-cache 62 | 63 | # Scrapy stuff: 64 | .scrapy 65 | 66 | # Sphinx documentation 67 | docs/_build/ 68 | 69 | # PyBuilder 70 | target/ 71 | 72 | # Jupyter Notebook 73 | .ipynb_checkpoints 74 | 75 | # pyenv 76 | .python-version 77 | 78 | # celery beat schedule file 79 | celerybeat-schedule 80 | 81 | # SageMath parsed files 82 | *.sage.py 83 | 84 | # Environments 85 | .env 86 | .venv 87 | env/ 88 | venv/ 89 | ENV/ 90 | env.bak/ 91 | venv.bak/ 92 | 93 | # Spyder project settings 94 | .spyderproject 95 | .spyproject 96 | 97 | # Rope project settings 98 | .ropeproject 99 | 100 | # mkdocs documentation 101 | /site 102 | 103 | # mypy 104 | .mypy_cache/ 105 | 106 | .vscode 107 | 108 | .DS_Store 109 | 110 | .idea 111 | 112 | .pipped -------------------------------------------------------------------------------- /Dockerfile: -------------------------------------------------------------------------------- 1 | FROM tiangolo/uwsgi-nginx-flask:python3.7-alpine3.7 2 | RUN apk --update add bash nano 3 | RUN pip install --upgrade pip 4 | -------------------------------------------------------------------------------- /LICENSE: -------------------------------------------------------------------------------- 1 | BSD 3-Clause License 2 | 3 | Copyright (c) 2019, Transbank Developers 4 | All rights reserved. 5 | 6 | Redistribution and use in source and binary forms, with or without 7 | modification, are permitted provided that the following conditions are met: 8 | 9 | 1. Redistributions of source code must retain the above copyright notice, this 10 | list of conditions and the following disclaimer. 11 | 12 | 2. Redistributions in binary form must reproduce the above copyright notice, 13 | this list of conditions and the following disclaimer in the documentation 14 | and/or other materials provided with the distribution. 15 | 16 | 3. Neither the name of the copyright holder nor the names of its 17 | contributors may be used to endorse or promote products derived from 18 | this software without specific prior written permission. 19 | 20 | THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" 21 | AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 22 | IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE 23 | DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE 24 | FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 25 | DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR 26 | SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER 27 | CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, 28 | OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE 29 | OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 30 | -------------------------------------------------------------------------------- /Makefile: -------------------------------------------------------------------------------- 1 | SHELL := /bin/bash 2 | 3 | all: build run 4 | 5 | run: build 6 | docker-compose run --rm --service-ports web 7 | 8 | build: .built .pipped 9 | 10 | .built: Dockerfile 11 | docker-compose build 12 | touch .built 13 | 14 | .pipped: requirements.txt 15 | docker-compose run web pip install -r requirements.txt 16 | touch .pipped 17 | 18 | logs: 19 | docker-compose logs 20 | 21 | clean: 22 | docker-compose rm 23 | rm .built 24 | rm .pipped 25 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | ## Transbank SDK Webpay REST example project for Python 2 | 3 | ### Requirements 4 | 5 | You need to have `docker` and `docker-compose`installed 6 | 7 | #### How to run this example project 8 | 9 | You can run this project by typing `make` on your Terminal 10 | 11 | ### Troubleshooting 12 | 13 | Currently this example project uses local repos as dependencies, exposing them from your computer to 14 | the docker container. If the SDK is not found, you can check `docker-compose.yml` on the repo's root and check the 15 | `volumes` entry, to verify that the origin path (the one with `{$HOME}`) matches the location of the SDK on your local 16 | machine 17 | 18 | ### Alternative Way to run the example project 19 | 20 | If you don't want to use docker, you can run the example project by following these steps: 21 | 22 | - Execute the command `python3 -m venv venv` 23 | - Activate the virtual environment with `source venv/bin/activate` 24 | - Install the dependencies with `pip install -r requirements.txt` 25 | - Run the example with python `__init__.py` 26 | -------------------------------------------------------------------------------- /__init__.py: -------------------------------------------------------------------------------- 1 | from flask import Flask, Config, app, render_template 2 | import os 3 | 4 | APP_PATH = os.path.dirname(os.path.dirname(os.path.abspath(__file__))) 5 | TEMPLATE_PATH = os.path.join(APP_PATH, 'templates/') 6 | 7 | 8 | def create_app(config_class=Config): 9 | app = Flask(__name__) 10 | app.config.from_object(config_class) 11 | 12 | from transaccion_completa import bp as transaccion_completa_bp 13 | from transaccion_completa_deferred import bp as transaccion_completa_deferred_bp 14 | from patpass_by_webpay import bp as patpass_by_webpay_bp 15 | from webpay_plus import bp as webpay_plus_bp 16 | from webpay_plus_mall import bp as webpay_plus_mall_bp 17 | from webpay_plus_deferred import bp as webpay_plus_deferred_bp 18 | from webpay_plus_mall_deferred import bp as webpay_plus_mall_deferred_bp 19 | from transaccion_completa_mall import bp as transaccion_completa_mall_bp 20 | from transaccion_completa_mall_deferred import bp as transaccion_completa_mall_deferred_bp 21 | from patpass_comercio import bp as patpass_comercio_bp 22 | from oneclick import bp as oneclick_bp 23 | from oneclick_deferred import bp as oneclick_deferred_bp 24 | 25 | app.register_blueprint(transaccion_completa_bp, url_prefix='/fulltransaction') 26 | app.register_blueprint(transaccion_completa_deferred_bp, url_prefix='/fulltransaction-deferred') 27 | app.register_blueprint(transaccion_completa_mall_deferred_bp, url_prefix='/mallfulltransaction-deferred') 28 | app.register_blueprint(patpass_by_webpay_bp, url_prefix='/patpass-webpay') 29 | app.register_blueprint(webpay_plus_bp, url_prefix="/webpay-plus") 30 | app.register_blueprint(webpay_plus_mall_bp, url_prefix="/webpay-plus-mall") 31 | app.register_blueprint(webpay_plus_deferred_bp, url_prefix="/webpay-plus-deferred") 32 | app.register_blueprint(webpay_plus_mall_deferred_bp, url_prefix="/webpay-plus-mall-deferred") 33 | app.register_blueprint(transaccion_completa_mall_bp, url_prefix='/mallfulltransaction/') 34 | app.register_blueprint(patpass_comercio_bp, url_prefix='/patpass-comercio') 35 | app.register_blueprint(oneclick_bp, url_prefix='/oneclick-mall') 36 | app.register_blueprint(oneclick_deferred_bp, url_prefix='/oneclick-mall-deferred') 37 | 38 | @app.route('/') 39 | def index(): 40 | return render_template('index.html') 41 | 42 | return app 43 | 44 | 45 | create_app().run() 46 | #create_app() -------------------------------------------------------------------------------- /docker-compose.yml: -------------------------------------------------------------------------------- 1 | version: '2' 2 | services: 3 | web: &web 4 | tty: true 5 | stdin_open: true 6 | build: 7 | context: . 8 | dockerfile: Dockerfile 9 | command: flask run --host=0.0.0.0 10 | volumes: 11 | - .:/app 12 | volumes_from: 13 | - python_cache 14 | ports: 15 | - "5000:5000" 16 | environment: 17 | - FLASK_APP=/app/__init__.py 18 | - FLASK_ENV=development 19 | 20 | python_cache: 21 | image: tiangolo/uwsgi-nginx-flask:python3.7-alpine3.7 22 | volumes: 23 | - /usr/local/lib/python3.7/site-packages -------------------------------------------------------------------------------- /oneclick/__init__.py: -------------------------------------------------------------------------------- 1 | from flask import Blueprint 2 | 3 | bp = Blueprint('oneclick', __name__) 4 | 5 | from oneclick import routes 6 | -------------------------------------------------------------------------------- /oneclick/routes.py: -------------------------------------------------------------------------------- 1 | from transbank.error.transbank_error import TransbankError 2 | from transbank.webpay.oneclick.request import MallTransactionAuthorizeDetails 3 | 4 | from oneclick import bp 5 | from flask import render_template, request 6 | from transbank.webpay.oneclick.mall_inscription import MallInscription 7 | from transbank.webpay.oneclick.mall_transaction import MallTransaction 8 | 9 | import random 10 | 11 | 12 | @bp.route('start', methods=['GET']) 13 | def show_start(): 14 | hostname = request.headers.get('Host') 15 | protocol = request.scheme 16 | endpoint = protocol + "://" + hostname + "/oneclick-mall/finish" 17 | return render_template('/oneclick/start.html', endpoint=endpoint) 18 | 19 | 20 | @bp.route('status', methods=['GET']) 21 | def show_status(): 22 | return render_template('/oneclick/status_form.html') 23 | 24 | 25 | @bp.route('start', methods=['POST']) 26 | def start(): 27 | user_name = request.form.get('user_name') 28 | email = request.form.get('email') 29 | response_url = request.form.get('response_url') 30 | 31 | ins = MallInscription() 32 | resp = ins.start( 33 | username=user_name, 34 | email=email, 35 | response_url=response_url) 36 | 37 | return render_template('oneclick/started.html', resp=resp, req=request.form) 38 | 39 | 40 | @bp.route('finish', methods=['GET']) 41 | def finish(): 42 | req = request.form 43 | token = request.args.get('TBK_TOKEN') 44 | 45 | ins = MallInscription() 46 | resp = ins.finish(token) 47 | buy_order_1 = str(random.randrange(1000000, 99999999)) 48 | buy_order_2 = str(random.randrange(1000000, 99999999)) 49 | buy_order = str(random.randrange(1000000, 99999999)) 50 | commerce_code_1 = '597055555542' 51 | commerce_code_2 = '597055555543' 52 | return render_template('oneclick/authorize.html', req=req, resp=resp, buy_order_1=buy_order_1, 53 | buy_order_2=buy_order_2, buy_order=buy_order, token=token, commerce_code_1=commerce_code_1, 54 | commerce_code_2=commerce_code_2) 55 | 56 | @bp.route('finish', methods=['POST']) 57 | def finish_error(): 58 | req = request.form 59 | token = request.form.get('TBK_TOKEN') 60 | 61 | ins = MallInscription() 62 | resp = ins.finish(token=token) 63 | buy_order_1 = str(random.randrange(1000000, 99999999)) 64 | buy_order_2 = str(random.randrange(1000000, 99999999)) 65 | buy_order = str(random.randrange(1000000, 99999999)) 66 | commerce_code_1 = '597055555542' 67 | commerce_code_2 = '597055555543' 68 | return render_template('oneclick/authorize.html', req=req, resp=resp, buy_order_1=buy_order_1, 69 | buy_order_2=buy_order_2, buy_order=buy_order, token=token, commerce_code_1=commerce_code_1, 70 | commerce_code_2=commerce_code_2) 71 | 72 | @bp.route('delete', methods=['POST']) 73 | def delete(): 74 | req = request.form 75 | 76 | tbk_user = request.form.get('tbk_user') 77 | user_name = request.form.get('user_name') 78 | 79 | try: 80 | ins = MallInscription() 81 | resp = ins.delete(tbk_user, user_name) 82 | return render_template('oneclick/deleted.html', req=req, resp=resp) 83 | except TransbankError as e: 84 | print("ERROR_MESSAGE: {}".format(e.message)) 85 | 86 | @bp.route('authorize', methods=['POST']) 87 | def authorize(): 88 | req = request.form 89 | tbk_user = request.form.get('tbk_user') 90 | user_name = request.form.get('user_name') 91 | buy_order = request.form.get('buy_order') 92 | token_inscription = request.form.get('token_inscription') 93 | 94 | commerce_code = request.form.get('details[0][commerce_code]') 95 | buy_order_child = request.form.get('details[0][buy_order]') 96 | installments_number = request.form.get('details[0][installments_number]') 97 | amount = request.form.get('details[0][amount]') 98 | 99 | commerce_code2 = request.form.get('details[1][commerce_code]') 100 | buy_order_child2 = request.form.get('details[1][buy_order]') 101 | installments_number2 = request.form.get('details[1][installments_number]') 102 | amount2 = request.form.get('details[1][amount]') 103 | 104 | details = MallTransactionAuthorizeDetails(commerce_code, buy_order_child, installments_number, amount) \ 105 | .add(commerce_code2, buy_order_child2, installments_number2, amount2) 106 | 107 | tx = MallTransaction() 108 | resp = tx.authorize(username=user_name, tbk_user=tbk_user, parent_buy_order=buy_order, details=details) 109 | return render_template('oneclick/refund.html', req=req, resp=resp, details=details.details, buy_order=buy_order, 110 | tbk_user=tbk_user) 111 | 112 | 113 | @bp.route('refund', methods=['POST']) 114 | def refund(): 115 | req = request.form 116 | buy_order = request.form.get('buy_order') 117 | child_commerce_code = request.form.get('child_commerce_code') 118 | child_buy_order = request.form.get('child_buy_order') 119 | amount = request.form.get('amount') 120 | tbk_user = request.form.get('tbk_user') 121 | tx = MallTransaction() 122 | resp = tx.refund(buy_order, child_commerce_code, child_buy_order, amount) 123 | return render_template('oneclick/delete.html', req=req, resp=resp, tbk_user=tbk_user) 124 | 125 | 126 | 127 | 128 | 129 | @bp.route('status', methods=['POST']) 130 | def status(): 131 | buy_order = request.form.get('buy_order') 132 | tx = MallTransaction() 133 | resp = tx.status(buy_order) 134 | 135 | return render_template('oneclick/status.html', resp=resp, req=request.form) 136 | -------------------------------------------------------------------------------- /oneclick_deferred/__init__.py: -------------------------------------------------------------------------------- 1 | from flask import Blueprint 2 | 3 | bp = Blueprint('oneclick_deferred', __name__) 4 | 5 | from oneclick_deferred import routes 6 | -------------------------------------------------------------------------------- /oneclick_deferred/routes.py: -------------------------------------------------------------------------------- 1 | from transbank.error.transbank_error import TransbankError 2 | from transbank.webpay.oneclick.request import MallTransactionAuthorizeDetails 3 | 4 | from oneclick_deferred import bp 5 | from flask import render_template, request 6 | from transbank.webpay.oneclick.mall_inscription import MallInscription 7 | from transbank.webpay.oneclick.mall_transaction import MallTransaction 8 | from transbank.common.integration_commerce_codes import IntegrationCommerceCodes 9 | from transbank.common.integration_type import IntegrationType 10 | from transbank.common.integration_api_keys import IntegrationApiKeys 11 | from transbank.common.options import WebpayOptions 12 | 13 | import random 14 | 15 | 16 | @bp.route('start', methods=['GET']) 17 | def show_start(): 18 | hostname = request.headers.get('Host') 19 | protocol = request.scheme 20 | endpoint = protocol + "://" + hostname + "/oneclick-mall-deferred/finish" 21 | return render_template('/oneclick/deferred/start.html', endpoint=endpoint) 22 | 23 | 24 | @bp.route('status', methods=['GET']) 25 | def show_status(): 26 | return render_template('/oneclick/deferred/status_form.html') 27 | 28 | 29 | @bp.route('start', methods=['POST']) 30 | def start(): 31 | user_name = request.form.get('user_name') 32 | email = request.form.get('email') 33 | response_url = request.form.get('response_url') 34 | 35 | ins = MallInscription(WebpayOptions(IntegrationCommerceCodes.ONECLICK_MALL_DEFERRED, IntegrationApiKeys.WEBPAY, IntegrationType.TEST)) 36 | resp = ins.start( 37 | username=user_name, 38 | email=email, 39 | response_url=response_url) 40 | 41 | return render_template('oneclick/deferred/started.html', resp=resp, req=request.form) 42 | 43 | 44 | @bp.route('finish', methods=['GET']) 45 | def finish(): 46 | req = request.form 47 | token = request.args.get('TBK_TOKEN') 48 | 49 | ins = MallInscription(WebpayOptions(IntegrationCommerceCodes.ONECLICK_MALL_DEFERRED, IntegrationApiKeys.WEBPAY, IntegrationType.TEST)) 50 | resp = ins.finish(token) 51 | buy_order_1 = str(random.randrange(1000000, 99999999)) 52 | buy_order_2 = str(random.randrange(1000000, 99999999)) 53 | buy_order = str(random.randrange(1000000, 99999999)) 54 | commerce_code_1 = IntegrationCommerceCodes.ONECLICK_MALL_DEFERRED_CHILD1 55 | commerce_code_2 = IntegrationCommerceCodes.ONECLICK_MALL_DEFERRED_CHILD2 56 | return render_template('oneclick/deferred/authorize.html', req=req, resp=resp, buy_order_1=buy_order_1, 57 | buy_order_2=buy_order_2, buy_order=buy_order, token=token, commerce_code_1=commerce_code_1, 58 | commerce_code_2=commerce_code_2) 59 | 60 | 61 | @bp.route('finish', methods=['POST']) 62 | def finish_error(): 63 | req = request.form 64 | token = request.form.get('TBK_TOKEN') 65 | 66 | ins = MallInscription(WebpayOptions(IntegrationCommerceCodes.ONECLICK_MALL_DEFERRED, IntegrationApiKeys.WEBPAY, IntegrationType.TEST)) 67 | resp = ins.finish(token=token) 68 | buy_order_1 = str(random.randrange(1000000, 99999999)) 69 | buy_order_2 = str(random.randrange(1000000, 99999999)) 70 | buy_order = str(random.randrange(1000000, 99999999)) 71 | commerce_code_1 = IntegrationCommerceCodes.ONECLICK_MALL_DEFERRED_CHILD1 72 | commerce_code_2 = IntegrationCommerceCodes.ONECLICK_MALL_DEFERRED_CHILD2 73 | return render_template('oneclick/deferred/authorize.html', req=req, resp=resp, buy_order_1=buy_order_1, 74 | buy_order_2=buy_order_2, buy_order=buy_order, token=token, commerce_code_1=commerce_code_1, 75 | commerce_code_2=commerce_code_2) 76 | 77 | 78 | @bp.route('delete', methods=['POST']) 79 | def delete(): 80 | req = request.form 81 | 82 | tbk_user = request.form.get('tbk_user') 83 | user_name = request.form.get('user_name') 84 | 85 | try: 86 | ins = MallInscription(WebpayOptions(IntegrationCommerceCodes.ONECLICK_MALL_DEFERRED, IntegrationApiKeys.WEBPAY, IntegrationType.TEST)) 87 | resp = ins.delete(tbk_user, user_name) 88 | return render_template('oneclick/deferred/deleted.html', req=req, resp=resp) 89 | except TransbankError as e: 90 | print("ERROR_MESSAGE: {}".format(e.message)) 91 | 92 | 93 | @bp.route('authorize', methods=['POST']) 94 | def authorize(): 95 | req = request.form 96 | tbk_user = request.form.get('tbk_user') 97 | user_name = request.form.get('user_name') 98 | buy_order = request.form.get('buy_order') 99 | token_inscription = request.form.get('token_inscription') 100 | 101 | commerce_code = request.form.get('details[0][commerce_code]') 102 | buy_order_child = request.form.get('details[0][buy_order]') 103 | installments_number = request.form.get('details[0][installments_number]') 104 | amount = request.form.get('details[0][amount]') 105 | 106 | commerce_code2 = request.form.get('details[1][commerce_code]') 107 | buy_order_child2 = request.form.get('details[1][buy_order]') 108 | installments_number2 = request.form.get('details[1][installments_number]') 109 | amount2 = request.form.get('details[1][amount]') 110 | 111 | details = MallTransactionAuthorizeDetails(commerce_code, buy_order_child, installments_number, amount) \ 112 | .add(commerce_code2, buy_order_child2, installments_number2, amount2) 113 | 114 | tx = MallTransaction(WebpayOptions(IntegrationCommerceCodes.ONECLICK_MALL_DEFERRED, IntegrationApiKeys.WEBPAY, IntegrationType.TEST)) 115 | response = tx.authorize(username=user_name, tbk_user=tbk_user, parent_buy_order=buy_order, details=details) 116 | return render_template('oneclick/deferred/authorized.html', request=req, response=response, details=details.details, buy_order=buy_order, 117 | tbk_user=tbk_user) 118 | 119 | 120 | @bp.route('refund', methods=['POST']) 121 | def refund(): 122 | req = request.form 123 | buy_order = request.form.get('buy_order') 124 | child_commerce_code = request.form.get('child_commerce_code') 125 | child_buy_order = request.form.get('child_buy_order') 126 | amount = request.form.get('amount') 127 | tbk_user = request.form.get('tbk_user') 128 | tx = MallTransaction(WebpayOptions(IntegrationCommerceCodes.ONECLICK_MALL_DEFERRED, IntegrationApiKeys.WEBPAY, IntegrationType.TEST)) 129 | resp = tx.refund(buy_order, child_commerce_code, child_buy_order, amount) 130 | return render_template('oneclick/deferred/delete.html', req=req, resp=resp, tbk_user=tbk_user) 131 | 132 | 133 | @bp.route('status', methods=['POST']) 134 | def status(): 135 | buy_order = request.form.get('buy_order') 136 | tx = MallTransaction(WebpayOptions(IntegrationCommerceCodes.ONECLICK_MALL_DEFERRED, IntegrationApiKeys.WEBPAY, IntegrationType.TEST)) 137 | resp = tx.status(buy_order) 138 | 139 | return render_template('oneclick/deferred/status.html', resp=resp, req=request.form) 140 | 141 | 142 | @bp.route('capture', methods=['POST']) 143 | def capture(): 144 | buy_order = request.form.get('buy_order') 145 | authorization_code = request.form.get('authorization_code') 146 | commerce_code = request.form.get('commerce_code') 147 | capture_amount = request.form.get('capture_amount') 148 | tx = MallTransaction(WebpayOptions(IntegrationCommerceCodes.ONECLICK_MALL_DEFERRED, IntegrationApiKeys.WEBPAY, IntegrationType.TEST)) 149 | response = tx.capture(commerce_code, buy_order, authorization_code, capture_amount) 150 | request_data = { 151 | "buy_order": buy_order, 152 | "authorization_code": authorization_code, 153 | "commerce_code": commerce_code, 154 | "capture_amount": capture_amount 155 | } 156 | return render_template('oneclick/deferred/capture.html', request= request_data, response=response) 157 | 158 | -------------------------------------------------------------------------------- /patpass_by_webpay/__init__.py: -------------------------------------------------------------------------------- 1 | from flask import Blueprint 2 | 3 | # from transaccion_completa.transaccion_completa import TransaccionCompleta 4 | 5 | bp = Blueprint('patpass_by_webpay', __name__) 6 | 7 | from patpass_by_webpay import routes 8 | -------------------------------------------------------------------------------- /patpass_by_webpay/routes.py: -------------------------------------------------------------------------------- 1 | import string 2 | import random 3 | from transbank.error.transbank_error import TransbankError 4 | from patpass_by_webpay import bp 5 | from flask import render_template, request 6 | from transbank.patpass_by_webpay.transaction import Transaction 7 | 8 | 9 | @bp.route('create') 10 | def patpass_webpay_create(): 11 | print("Patpass Webpay Transaction.create") 12 | buy_order = str(random.randrange(1000000, 99999999)) 13 | session_id = str(random.randrange(1000000, 99999999)) 14 | return_url = request.url_root + 'patpass-webpay/commit' 15 | service_id = random_string(20) 16 | card_holder_id = random_string(20) 17 | card_holder_name = random_string(20) 18 | card_holder_last_name1 = random_string(20) 19 | card_holder_last_name2 = random_string(20) 20 | card_holder_mail = '{}@{}.com'.format(random_string(10), random_string(7)) 21 | commerce_mail = '{}@{}.com'.format(random_string(10), random_string(7)) 22 | cellphone_number = random.randrange(1000000, 99999999) 23 | expiration_date = '2222-11-11' 24 | 25 | create_request = { 26 | 'buy_order': buy_order, 27 | 'session_id': session_id, 28 | 'return_url': return_url, 29 | 'service_id': service_id, 30 | 'card_holder_id': card_holder_id, 31 | 'card_holder_name': card_holder_name, 32 | 'card_holder_last_name1': card_holder_last_name1, 33 | 'card_holder_last_name2': card_holder_last_name2, 34 | 'card_holder_mail': card_holder_mail, 35 | 'commerce_mail': commerce_mail, 36 | 'cellphone_number': cellphone_number, 37 | 'expiration_date': expiration_date, 38 | } 39 | 40 | tx = Transaction() 41 | response = tx.create(buy_order, session_id, 1000, return_url, service_id, card_holder_id, card_holder_name, 42 | card_holder_last_name1, card_holder_last_name2, card_holder_mail, cellphone_number, 43 | expiration_date, commerce_mail, False) 44 | 45 | print(response) 46 | 47 | return render_template('webpay/patpass/create.html', request=create_request, response=response) 48 | 49 | 50 | @bp.route('commit', methods=["GET"]) 51 | def patpass_webpay_commit(): 52 | token = request.args.get("token_ws") 53 | print("commit for token_ws: {}".format(token)) 54 | 55 | tx = Transaction() 56 | response = tx.commit(token=token) 57 | print("response: {}".format(response)) 58 | 59 | return render_template('webpay/patpass/commit.html', token=token, response=response) 60 | 61 | 62 | @bp.route("status-form", methods=["GET"]) 63 | def patpass_webpay_status_form(): 64 | return render_template("webpay/patpass/status-form.html") 65 | 66 | 67 | @bp.route("status", methods=["POST"]) 68 | def patpass_webpay_status(): 69 | token = request.form.get("token_ws") 70 | try: 71 | tx = Transaction() 72 | response = tx.status(token) 73 | print(response) 74 | return render_template("webpay/patpass/status.html", token=token, response=response) 75 | except TransbankError as e: 76 | print(e.message) 77 | 78 | 79 | def random_string(string_length=10): 80 | """Generate a random string of fixed length """ 81 | letters = string.ascii_lowercase 82 | return ''.join(random.choice(letters) for i in range(string_length)) 83 | -------------------------------------------------------------------------------- /patpass_comercio/__init__.py: -------------------------------------------------------------------------------- 1 | from flask import Blueprint 2 | 3 | bp = Blueprint('patpass_comercio', __name__) 4 | 5 | from patpass_comercio import routes 6 | -------------------------------------------------------------------------------- /patpass_comercio/routes.py: -------------------------------------------------------------------------------- 1 | import string 2 | import random 3 | from transbank.error.transbank_error import TransbankError 4 | from transbank.patpass_comercio.inscription import Inscription 5 | 6 | from patpass_comercio import bp 7 | from flask import render_template, request 8 | 9 | 10 | @bp.route('start') 11 | def patpass_comercio_inscription(): 12 | print("Patpass Comercio Transaction.inscription") 13 | name = 'nombre' 14 | first_last_name = 'apellido' 15 | second_last_name = 'apellido' 16 | rut = '14140066-5' 17 | return_url = 'http://return_url' #request.url_root + 'patpass-comercio/end-inscription' 18 | service_id = random.randrange(1000000, 99999999) 19 | final_url = 'http://final_url' #request.url_root + 'patpass-comercio/voucher-generated' 20 | max_amount = 0 21 | phone_number = random.randrange(1000000, 99999999) 22 | mobile_number = random.randrange(1000000, 99999999) 23 | patpass_name = random_string(20) 24 | person_email = '{}@{}.com'.format(random_string(10), random_string(7)) 25 | commerce_mail = '{}@{}.com'.format(random_string(10), random_string(7)) 26 | address = random_string(20) 27 | city = random_string(20) 28 | 29 | 30 | inscription_request = { 31 | 'return_url': return_url, 32 | 'name': name, 33 | 'first_last_name': first_last_name, 34 | 'second_last_name': second_last_name, 35 | 'rut': rut, 36 | 'service_id': service_id, 37 | 'final_url': final_url, 38 | 'max_amount': max_amount, 39 | 'phone_number': phone_number, 40 | 'mobile_number': mobile_number, 41 | 'patpass_name': patpass_name, 42 | 'person_email': person_email, 43 | 'commerce_mail': commerce_mail, 44 | 'address': address, 45 | 'city': city, 46 | } 47 | 48 | ins = Inscription().configure_for_testing() 49 | response = ins.start(return_url, name, first_last_name, second_last_name, rut, service_id, None, 50 | max_amount, phone_number, mobile_number, patpass_name, 51 | person_email, commerce_mail, address, city) 52 | 53 | print(response) 54 | 55 | return render_template('patpass_comercio/start_inscription.html', request=inscription_request, response=response) 56 | 57 | 58 | @bp.route('end-inscription', methods=["POST"]) 59 | def patpass_comercio_end_inscription(): 60 | token = request.form.get("j_token") 61 | print("commit for token_ws: {}".format(token)) 62 | 63 | return render_template('patpass_comercio/finish_inscription.html', token=token) 64 | 65 | 66 | @bp.route("status", methods=["POST"]) 67 | def patpass_comercio_status(): 68 | token = request.form.get("tokenComercio") 69 | try: 70 | ins = Inscription() 71 | response = ins.status(token) 72 | print(response) 73 | return render_template("patpass_comercio/status.html", token=token, response=response) 74 | except TransbankError as e: 75 | print(e.message) 76 | 77 | 78 | @bp.route('voucher-generated', methods=["POST"]) 79 | def patpass_comercio_voucher_generated(): 80 | return render_template('patpass_comercio/voucher_displayed.html') 81 | 82 | 83 | def random_string(string_length=10): 84 | """Generate a random string of fixed length """ 85 | letters = string.ascii_lowercase 86 | return ''.join(random.choice(letters) for i in range(string_length)) 87 | -------------------------------------------------------------------------------- /requirements.txt: -------------------------------------------------------------------------------- 1 | transbank-sdk==5.0.0 -------------------------------------------------------------------------------- /tbk_examples.py: -------------------------------------------------------------------------------- 1 | from main import create_app 2 | app = create_app() 3 | -------------------------------------------------------------------------------- /templates/include/footer.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | -------------------------------------------------------------------------------- /templates/include/header.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | -------------------------------------------------------------------------------- /templates/index.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | Ejemplo integración Webpay Rest 4 | {% include 'include/header.html' %} 5 | 6 | 7 | 8 |

Ejemplos Webpay

9 | 10 | 11 | 12 | 13 | 14 | 15 | 16 | 17 | 18 | 19 | 20 | 21 | 22 | 23 | 24 | 25 | 26 | 27 | 28 | 29 | 30 | 31 | 32 | 33 | 34 | 35 | 36 | 37 | 38 | 39 | 40 | 41 | 42 | 43 | 44 | 45 | 46 | 47 | 48 | 49 | 50 | 51 | 52 | 53 | 54 | 55 | 56 | 57 | 58 | 59 | 60 | 61 | 62 | 63 | 64 | 65 | 66 | 67 | 68 | 69 | 70 | 71 | 72 | 73 | 74 | 75 | 76 | 77 | 78 | 79 | 80 | 81 | 82 | 83 | 84 | 85 | 86 | 87 | 88 | 89 | 90 | 91 | 92 | 93 | 94 | 95 | 96 | 97 | 98 | 99 |
ServiceCreateRefundStatus
Webpay PlusCrear TransacciónReembolsar TransacciónConsultar Estado Transacción
Webpay Plus MallCrear TransacciónReembolsar TransacciónConsultar Estado Transacción
Webpay Plus Captura DiferidaCrear TransacciónReembolsar TransacciónConsultar Estado Transacción
Webpay Plus Mall DeferredCrear TransacciónReembolsar TransacciónConsultar Estado Transacción
Oneclick MallComenzar InscripciónConsultar Estado Transacción
Oneclick Mall DeferredComenzar Inscripción
Transacción CompletaCrear TransacciónReembolsar TransacciónConsultar Estado Transacción
Transacción Completa DeferredCrear Transacción--
Patpass-webpayCrear Transacción-Consultar Estado Transacción
Transacción Completa MallCrear TransacciónReembolsar TransacciónConsultar Estado Transacción
Transacción Completa Mall DeferredCrear Transacción--
Patpass ComercioCrear Transacción
100 | {% include 'include/footer.html' %} 101 | 102 | 103 | -------------------------------------------------------------------------------- /templates/oneclick/authorize.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | Ejemplo Oneclick Mall - Autorizar Transacción 5 | {% include 'include/header.html' %} 6 | 7 | 8 | 9 | 19 | 20 | 24 | 28 | 29 |
30 |
31 | 32 | 33 | 39 | 40 |

Comercio 1

41 |
42 |
43 | 46 | 52 |
53 |
54 | 55 | 61 |
62 |
63 | 64 | 70 |
71 |
72 | 73 | 79 |
80 |

Comercio 2

81 |
82 |
83 | 86 | 92 |
93 |
94 | 95 | 101 |
102 |
103 | 104 | 110 |
111 |
112 | 113 | 119 |
120 | 121 |
122 | « volver a index 123 | 124 | 125 | -------------------------------------------------------------------------------- /templates/oneclick/deferred/authorize.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | Ejemplo Oneclick Mall - Autorizar Transacción 5 | {% include 'include/header.html' %} 6 | 7 | 8 | 9 | 19 | 20 | 24 | 28 | 29 |
30 |
31 | 32 | 33 | 39 | 40 |

Comercio 1

41 |
42 |
43 | 46 | 52 |
53 |
54 | 55 | 61 |
62 |
63 | 64 | 70 |
71 |
72 | 73 | 79 |
80 |

Comercio 2

81 |
82 |
83 | 86 | 92 |
93 |
94 | 95 | 101 |
102 |
103 | 104 | 110 |
111 |
112 | 113 | 119 |
120 | 121 |
122 | « volver a index 123 | 124 | 125 | -------------------------------------------------------------------------------- /templates/oneclick/deferred/authorized.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | Ejemplo Oneclick Mall Diferido - Transacción autorizada 6 | 7 | {% include 'include/header.html' %} 8 | 9 | 10 | 11 | 23 | 24 | 28 | 32 |
33 |
34 | 40 | 46 | 47 |

Comercio 1

48 | 49 |
50 | 53 | 59 |
60 |
61 | 62 | 68 |
69 |
70 | 71 | 77 |
78 | 79 | 80 |
81 | 82 |
83 | 88 | 93 | 98 | 103 | 104 |
105 | 106 |
107 | 113 | 119 | 120 |

Comercio 2

121 | 122 |
123 | 126 | 132 |
133 |
134 | 135 | 141 |
142 |
143 | 144 | 150 |
151 | 152 | 153 |
154 | 155 |
156 | 161 | 166 | 171 | 176 | 177 |
178 | 179 | « volver a index 180 | 181 | 182 | -------------------------------------------------------------------------------- /templates/oneclick/deferred/capture.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | Ejemplo Oneclick Mall Diferido - Captura 5 | {% include 'include/header.html' %} 6 | 7 | 8 | 9 | 15 | 16 | 20 | 24 | « volver a index 25 | 26 | -------------------------------------------------------------------------------- /templates/oneclick/deferred/delete.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | Ejemplo Oneclick Mall Diferido - Borrar Inscripción 5 | {% include 'include/header.html' %} 6 | 7 | 8 | 9 | 21 | 22 | 26 | 30 |
31 |
32 | 33 | 34 | 35 | 36 |
37 | « volver a index 38 | 39 | 40 | -------------------------------------------------------------------------------- /templates/oneclick/deferred/deleted.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | Ejemplo Oneclick Mall Diferido - Borrar Inscripción 5 | {% include 'include/header.html' %} 6 | 7 | 8 | 9 | 21 | 22 | 26 | 30 | « volver a index 31 | 32 | 33 | -------------------------------------------------------------------------------- /templates/oneclick/deferred/start.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | Ejemplo Oneclick Mall Diferido - Iniciar Inscripción 5 | {% include 'include/header.html' %} 6 | 7 | 8 | 9 | 15 | 16 |
17 | 18 |
19 | 20 | 21 |
22 |
23 | 24 | 25 |
26 |
27 | 28 | 29 |
30 | 31 |
32 | 33 | « volver a index 34 | 35 | -------------------------------------------------------------------------------- /templates/oneclick/deferred/started.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | Ejemplo Oneclick Mall Diferido - Inscripción iniciada 5 | {% include 'include/header.html' %} 6 | 7 | 8 | 9 | 21 | 22 | 26 | 30 |
31 | 32 |
38 | 39 | 40 | 41 |
42 | « volver a index 43 | 44 | 45 | -------------------------------------------------------------------------------- /templates/oneclick/deferred/status.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | Ejemplo Oneclick Mall Diferido - Estado Inscripción 5 | {% include 'include/header.html' %} 6 | 7 | 8 | 9 | 21 | 22 | 26 | 30 |
31 | 32 | « volver a index 33 | 34 | 35 | -------------------------------------------------------------------------------- /templates/oneclick/deferred/status_form.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | Ejemplo Oneclick Mall Diferido - Iniciar Inscripción 5 | {% include 'include/header.html' %} 6 | 7 | 8 | 9 | 15 | 16 |
17 |
18 | 19 | 20 |
21 | 22 |
23 | 24 | « volver a index 25 | 26 | -------------------------------------------------------------------------------- /templates/oneclick/delete.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | Ejemplo Oneclick Mall - Borrar Inscripción 5 | {% include 'include/header.html' %} 6 | 7 | 8 | 9 | 19 | 20 | 24 | 28 |
29 |
30 | 31 | 32 | 33 | 34 |
35 | « volver a index 36 | 37 | 38 | -------------------------------------------------------------------------------- /templates/oneclick/deleted.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | Ejemplo Oneclick Mall - Borrar Inscripción 5 | {% include 'include/header.html' %} 6 | 7 | 8 | 9 | 19 | 20 | 24 | {% if resp == True %} 25 |