From 47374f7d5dbb00c89b0389c9e6f4cf1b43e79083 Mon Sep 17 00:00:00 2001 From: Duc Le Tran Date: Thu, 15 Aug 2019 06:58:09 +0700 Subject: [PATCH] Summary: Add Paypal verification for Android client Fixes: #5961 --- app/api/helpers/payment.py | 43 +++++++++++++++++++++++++++++++++++++- app/api/orders.py | 16 ++++++++++++++ 2 files changed, 58 insertions(+), 1 deletion(-) diff --git a/app/api/helpers/payment.py b/app/api/helpers/payment.py index 3eddcfb74d..470a9dc5b5 100644 --- a/app/api/helpers/payment.py +++ b/app/api/helpers/payment.py @@ -11,7 +11,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 +from app.api.helpers.db import safe_query, save_to_db from app.models import db from app.models.order import Order @@ -200,6 +200,47 @@ 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): """ diff --git a/app/api/orders.py b/app/api/orders.py index 8cfd69bde0..980f4bddf6 100644 --- a/app/api/orders.py +++ b/app/api/orders.py @@ -503,6 +503,22 @@ def create_paypal_payment(order_identifier): 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): + """ + 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/', methods=['GET', 'POST']) def create_source(order_identifier): """