Skip to content

Commit

Permalink
feat: Transaction Processing logic & Wallet linking implementation
Browse files Browse the repository at this point in the history
  • Loading branch information
mrsaicharan1 committed Aug 21, 2019
1 parent 622ae4f commit d6bc2a3
Show file tree
Hide file tree
Showing 2 changed files with 123 additions and 68 deletions.
62 changes: 19 additions & 43 deletions app/api/helpers/payment.py
Original file line number Diff line number Diff line change
Expand Up @@ -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

Expand Down Expand Up @@ -206,47 +206,6 @@ def create_payment(order, return_url, cancel_url):
else:
return False, payment.error

@staticmethod
def verify_payment(payment_id, order):
"""
Verify Paypal payment one more time for paying with Paypal in mobile client
"""
try:
payment_server = paypalrestsdk.Payment.find(payment_id)
if payment_server.state != 'approved':
return False, 'Payment has not been approved yet. Status is ' + payment_server.state + '.'

# Get the most recent transaction
transaction = payment_server.transactions[0]
amount_server = transaction.amount.total
currency_server = transaction.amount.currency
sale_state = transaction.related_resources[0].sale.state

if amount_server != order.amount:
return False, 'Payment amount does not match order'
elif currency_server != order.event.payment_currency:
return False, 'Payment currency does not match order'
if sale_state != 'completed':
return False, 'Sale not completed'
elif PayPalPaymentsManager.used_payment(payment_id, order):
return False, 'Payment already been verified'
else:
return True, None
except paypalrestsdk.ResourceNotFound:
return False, 'Payment Not Found'

@staticmethod
def used_payment(payment_id, order):
"""
Function to check for recycling of payment IDs
"""
if Order.query.filter(Order.paypal_token == payment_id).first() is None:
order.paypal_token = payment_id
save_to_db(order)
return False
else:
return True

@staticmethod
def execute_payment(paypal_payer_id, paypal_payment_id):
"""
Expand Down Expand Up @@ -324,10 +283,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
129 changes: 104 additions & 25 deletions app/api/orders.py
Original file line number Diff line number Diff line change
@@ -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
Expand Down Expand Up @@ -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')

Expand Down Expand Up @@ -544,22 +545,6 @@ def create_paypal_payment(order_identifier):
return jsonify(status=False, error=response)


@order_misc_routes.route('/orders/<string:order_identifier>/verify-mobile-paypal-payment', methods=['POST'])
@jwt_required
def verify_mobile_paypal_payment(order_identifier):
"""
Verify paypal payment made on mobile client
:return: The status of order verification
"""
try:
payment_id = request.json['data']['attributes']['payment-id']
except TypeError:
return BadRequestError({'source': ''}, 'Bad Request Error').respond()
order = safe_query(db, Order, 'identifier', order_identifier, 'identifier')
status, error = PayPalPaymentsManager.verify_payment(payment_id, order)
return jsonify(status=status, error=error)


@alipay_blueprint.route('/create_source/<string:order_identifier>', methods=['GET', 'POST'])
def create_source(order_identifier):
"""
Expand Down Expand Up @@ -641,14 +626,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,
Expand All @@ -660,11 +645,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/<string:order_identifier>/paytm/fetch-payment-options/<string:txn_token>')
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/<string:order_identifier>/paytm/send_otp/<string:txn_token>', methods=['POST', 'GET'])
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": ""}
response = PaytmPaymentsManager.hit_paytm_endpoint(url=url, head=head, body=body)
return response


@order_misc_routes.route('/orders/<string:order_identifier>/paytm/validate_otp/<string:txn_token>')
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": ""}
response = PaytmPaymentsManager.hit_paytm_endpoint(url=url, head=head, body=body)
return response


@order_misc_routes.route('/orders/<string:order_identifier>/paytm/process_transaction/<string:txn_token>')
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

0 comments on commit d6bc2a3

Please sign in to comment.