From 386db974551df3c5fab40c002b53304e2f9c2a29 Mon Sep 17 00:00:00 2001 From: mrsaicharan1 Date: Tue, 20 Aug 2019 12:16:05 +0530 Subject: [PATCH 1/2] feat: Transaction Processing logic & Wallet linking implementation --- app/api/helpers/payment.py | 21 ++++++- app/api/orders.py | 114 +++++++++++++++++++++++++++++++++---- 2 files changed, 123 insertions(+), 12 deletions(-) diff --git a/app/api/helpers/payment.py b/app/api/helpers/payment.py index 276bc4b4e0..b4c4ed13d6 100644 --- a/app/api/helpers/payment.py +++ b/app/api/helpers/payment.py @@ -13,7 +13,7 @@ from app.api.helpers.utilities import represents_int from app.models.stripe_authorization import StripeAuthorization from app.settings import get_settings, Environment -from app.api.helpers.db import safe_query, save_to_db +from app.api.helpers.db import safe_query from app.models import db from app.models.order import Order @@ -324,10 +324,27 @@ class PaytmPaymentsManager(object): Class to manage PayTM payments """ + @property + def paytm_endpoint(self): + if get_settings()['paytm_mode'] == 'test': + url = "https://securegw-stage.paytm.in/theia/api/v1/" + else: + url = "https://securegw.paytm.in/theia/api/v1/" + return url + @staticmethod def generate_checksum(paytm_params): - if get_settings()['paytm_mode'] == 'sandbox': + if get_settings()['paytm_mode'] == 'test': merchant_key = get_settings()['paytm_sandbox_secret'] else: merchant_key = get_settings()['paytm_live_secret'] return checksum.generate_checksum_by_str(json.dumps(paytm_params["body"]), merchant_key) + + @staticmethod + def hit_paytm_endpoint(url, head, body=None): + paytm_params = {} + paytm_params["body"] = body + paytm_params["head"] = head + post_data = json.dumps(paytm_params) + response = requests.post(url, data=post_data, headers={"Content-type": "application/json"}).json() + return response diff --git a/app/api/orders.py b/app/api/orders.py index 8d8e69776e..0fee23dd20 100644 --- a/app/api/orders.py +++ b/app/api/orders.py @@ -1,11 +1,11 @@ import logging import json import pytz -from datetime import datetime +import time +import omise import requests - -import omise +from datetime import datetime from flask import request, jsonify, Blueprint, url_for, redirect from flask_jwt_extended import current_user from flask_rest_jsonapi import ResourceDetail, ResourceList, ResourceRelationship @@ -41,6 +41,7 @@ from app.models.ticket_holder import TicketHolder from app.models.user import User + order_misc_routes = Blueprint('order_misc', __name__, url_prefix='/v1') alipay_blueprint = Blueprint('alipay_blueprint', __name__, url_prefix='/v1/alipay') @@ -543,7 +544,6 @@ def create_paypal_payment(order_identifier): else: return jsonify(status=False, error=response) - @order_misc_routes.route('/orders//verify-mobile-paypal-payment', methods=['POST']) @jwt_required def verify_mobile_paypal_payment(order_identifier): @@ -641,14 +641,14 @@ def initiate_transaction(order_identifier): # body parameters paytm_params["body"] = { "requestType": "Payment", - "mid": (get_settings()['paytm_sandbox_merchant'] if paytm_mode == 'sandbox' + "mid": (get_settings()['paytm_sandbox_merchant'] if paytm_mode == 'test' else get_settings()['paytm_live_merchant']), "websiteName": "eventyay", - "orderId": order.id, + "orderId": order_identifier, "callbackUrl": "", "txnAmount": { "value": order.amount, - "currency": order.event.payment_currency, + "currency": "INR", }, "userInfo": { "custId": order.user.id, @@ -660,11 +660,105 @@ def initiate_transaction(order_identifier): "signature" : checksum } post_data = json.dumps(paytm_params) - if paytm_mode == 'sandbox': + if paytm_mode == 'test': url = "https://securegw-stage.paytm.in/theia/api/v1/initiateTransaction?mid={}&orderId={}".\ - format(get_settings()['paytm_sandbox_merchant'], order.id) + format(get_settings()['paytm_sandbox_merchant'], order_identifier) else: url = "https://securegw.paytm.in/theia/api/v1/initiateTransaction?mid={}&orderId={}".\ - format(get_settings()['paytm_sandbox_merchant'], order.id) + format(get_settings()['paytm_live_merchant'], order_identifier) response = requests.post(url, data=post_data, headers={"Content-type": "application/json"}) return response.json() + + +@order_misc_routes.route('/orders//paytm/fetch-payment-options/') +def fetch_payment_options(order_identifier, txn_token): + paytm_mode = get_settings()['paytm_mode'] + if paytm_mode == 'test': + url = "https://securegw-stage.paytm.in/theia/api/v1/fetchPaymentOptions?mid={}&orderId={}".\ + format(get_settings()['paytm_sandbox_merchant'], order_identifier) + else: + url = "https://securegw.paytm.in/theia/api/v1/fetchPaymentOptions?mid={}&orderId={}".\ + format(get_settings()['paytm_live_merchant'], order_identifier) + head = { + "clientId": "C11", + "version": "v1", + "requestTimestamp": str(int(time.time())), + "channelId": "WEB", + "txnToken": txn_token + } + response = PaytmPaymentsManager.hit_paytm_endpoint(url=url, head=head) + return response + + +@order_misc_routes.route('/orders//paytm/send_otp/', methods=['POST']) +def send_otp(order_identifier, txn_token): + paytm_mode = get_settings()['paytm_mode'] + if paytm_mode == 'test': + url = "https://securegw-stage.paytm.in/theia/api/v1/login/sendOtp?mid={}&orderId={}".\ + format(get_settings()['paytm_sandbox_merchant'], order_identifier) + else: + url = "https://securegw.paytm.in/theia/api/v1/login/sendOtp?mid={}&orderId={}".\ + format(get_settings()['paytm_live_merchant'], order_identifier) + + head = { + "clientId": "C11", + "version": "v1", + "requestTimestamp": str(int(time.time())), + "channelId": "WEB", + "txnToken": txn_token + } + body = {"mobileNumber": request.json['data']['phone']} + response = PaytmPaymentsManager.hit_paytm_endpoint(url=url, head=head, body=body) + return response + + +@order_misc_routes.route('/orders//paytm/validate_otp/', methods=['POST']) +def validate_otp(order_identifier, txn_token): + paytm_mode = get_settings()['paytm_mode'] + if paytm_mode == 'test': + url = "https://securegw-stage.paytm.in/theia/api/v1/login/validateOtp?mid={}&orderId={}".\ + format(get_settings()['paytm_sandbox_merchant'], order_identifier) + else: + url = "https://securegw.paytm.in/theia/api/v1/login/validateOtp?mid={}&orderId={}".\ + format(get_settings()['paytm_live_merchant'], order_identifier) + head = { + "clientId": "C11", + "version": "v1", + "requestTimestamp": str(int(time.time())), + "channelId": "WEB", + "txnToken": txn_token + } + body = {"otp": request.json['data']['otp']} + response = PaytmPaymentsManager.hit_paytm_endpoint(url=url, head=head, body=body) + return response + + +@order_misc_routes.route('/orders//paytm/process_transaction/') +def process_transaction(order_identifier, txn_token): + paytm_mode = get_settings()['paytm_mode'] + merchant_id = (get_settings()['paytm_sandbox_merchant'] if paytm_mode == 'test' + else get_settings()['paytm_live_merchant']) + + if paytm_mode == 'test': + url = "https://securegw-stage.paytm.in/theia/api/v1/processTransaction?mid={}&orderId={}".\ + format(get_settings()['paytm_sandbox_merchant'], order_identifier) + else: + url = "https://securegw.paytm.in/theia/api/v1/processTransaction?mid={}&orderId={}".\ + format(get_settings()['paytm_live_merchant'], order_identifier) + + head = { + "version": "v1", + "requestTimestamp": str(int(time.time())), + "channelId": "WEB", + "txnToken": txn_token + } + + body = { + "requestType": "NATIVE", + "mid": merchant_id, + "orderId": order_identifier, + "paymentMode": "BALANCE" + } + + response = PaytmPaymentsManager.hit_paytm_endpoint(url=url, head=head, body=body) + return response From b9bf3a2d456f4efc24b63cf08dddfc75f99ebc69 Mon Sep 17 00:00:00 2001 From: mrsaicharan1 Date: Fri, 23 Aug 2019 10:43:24 +0530 Subject: [PATCH 2/2] Added jwt headers --- app/api/orders.py | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/app/api/orders.py b/app/api/orders.py index 0fee23dd20..587f42e339 100644 --- a/app/api/orders.py +++ b/app/api/orders.py @@ -629,6 +629,7 @@ def omise_checkout(order_identifier): @order_misc_routes.route('/orders//paytm/initiate-transaction', methods=['POST', 'GET']) +@jwt_required def initiate_transaction(order_identifier): """ Initiating a PayTM transaction to obtain the txn token @@ -671,6 +672,7 @@ def initiate_transaction(order_identifier): @order_misc_routes.route('/orders//paytm/fetch-payment-options/') +@jwt_required def fetch_payment_options(order_identifier, txn_token): paytm_mode = get_settings()['paytm_mode'] if paytm_mode == 'test': @@ -691,6 +693,7 @@ def fetch_payment_options(order_identifier, txn_token): @order_misc_routes.route('/orders//paytm/send_otp/', methods=['POST']) +@jwt_required def send_otp(order_identifier, txn_token): paytm_mode = get_settings()['paytm_mode'] if paytm_mode == 'test': @@ -734,6 +737,7 @@ def validate_otp(order_identifier, txn_token): @order_misc_routes.route('/orders//paytm/process_transaction/') +@jwt_required def process_transaction(order_identifier, txn_token): paytm_mode = get_settings()['paytm_mode'] merchant_id = (get_settings()['paytm_sandbox_merchant'] if paytm_mode == 'test'