Repository: fossasia/open-event-server

Issue:
Implement  Omise Payment Gateway
For the OpenTechSummit in Thailand we need local payment gateways. The most popular one is omise. Please implement it.


Discussion:
@mariobehling On it. 
@prateekj117 How you are planning to implement ?
Hi @mariobehling, @prateekj117 and @kushthedude. Feel free to ping me if you need help with anything.
@prateekj117 Progress on it ?
@kushthedude 
@iamareebjamal told me to work on it later on.
@iamareebjamal Since the issue is labelled with a `High Priority` , Should not we work on it ? 
And if you are not working on it @prateekj117 I would like to take care of it
@prateekj117 thanks for the interest in this issue, I’ll be taking care of it for now as it’s a priority for us. 

@robinclart thank you so much for offering to help, will be in touch if we need anything :) 
@prateekj117 I meant generic payments issue you mentioned in your proposal, not this
@iamareebjamal Ohh, Ok. Sorry, I misunderstood.

Resolving patch:
diff --git a/app/api/helpers/payment.py b/app/api/helpers/payment.py
--- a/app/api/helpers/payment.py
+++ b/app/api/helpers/payment.py
@@ -3,6 +3,7 @@
 import paypalrestsdk
 import requests
 import stripe
+import omise
 from forex_python.converter import CurrencyRates
 
 from app.api.helpers.cache import cache
@@ -243,3 +244,29 @@ def charge_source(order_identifier):
                  source=order.order_notes,
                  )
         return charge
+
+
+class OmisePaymentsManager(object):
+    """
+    Class to manage Omise Payments
+    """
+
+    @staticmethod
+    def charge_payment(order_identifier, token):
+        if get_settings()['app_environment'] == Environment.PRODUCTION:
+            omise.api_secret = get_settings()['omise_test_secret']
+            omise.api_public = get_settings()['omise_test_public']
+        else:
+            omise.api_secret = get_settings()['omise_test_secret']
+            omise.api_public = get_settings()['omise_test_public']
+        order = safe_query(db, Order, 'identifier', order_identifier, 'identifier')
+        charge = omise.Charge.create(
+                amount=int(round(order.amount)),
+                currency=order.event.payment_currency,
+                card=token,
+                metadata={
+                    "order_id": str(order_identifier),
+                    "status": True
+                },
+                )
+        return charge
diff --git a/app/api/orders.py b/app/api/orders.py
--- a/app/api/orders.py
+++ b/app/api/orders.py
@@ -1,6 +1,7 @@
 from datetime import datetime
-
 from flask import request, jsonify, Blueprint, url_for, redirect
+import omise
+import logging
 
 from flask_jwt import current_identity as current_user
 from flask_rest_jsonapi import ResourceDetail, ResourceList, ResourceRelationship
@@ -33,7 +34,7 @@
 from app.models.order import Order, OrderTicket, get_updatable_fields
 from app.models.ticket_holder import TicketHolder
 from app.models.user import User
-from app.api.helpers.payment import AliPayPaymentsManager
+from app.api.helpers.payment import AliPayPaymentsManager, OmisePaymentsManager
 
 
 order_misc_routes = Blueprint('order_misc', __name__, url_prefix='/v1')
@@ -499,3 +500,32 @@ def alipay_return_uri(order_identifier):
             return jsonify(status=False, error='Charge object failure')
     except TypeError:
         return jsonify(status=False, error='Source object status error')
+
+
+@order_misc_routes.route('/orders/<string:order_identifier>/omise-checkout', methods=['POST', 'GET'])
+def omise_checkout(order_identifier):
+    """
+    Charging the user and returning payment response for Omise Gateway
+    :param order_identifier:
+    :return: JSON response of the payment status.
+    """
+    token = request.form.get('omiseToken')
+    order = safe_query(db, Order, 'identifier', order_identifier, 'identifier')
+    order.status = 'completed'
+    save_to_db(order)
+    try:
+        charge = OmisePaymentsManager.charge_payment(order_identifier, token)
+        print(charge.status)
+    except omise.errors.BaseError as e:
+        logging.error(f"""OmiseError: {repr(e)}.  See https://www.omise.co/api-errors""")
+        return jsonify(status=False, error="Omise Failure Message: {}".format(str(e)))
+    except Exception as e:
+        logging.error(repr(e))
+    if charge.failure_code is not None:
+        logging.warning("Omise Failure Message: {} ({})".format(charge.failure_message, charge.failure_code))
+        return jsonify(status=False, error="Omise Failure Message: {} ({})".
+                       format(charge.failure_message, charge.failure_code))
+    else:
+        logging.info(f"Successful charge: {charge.id}.  Order ID: {order_identifier}")
+
+        return redirect(make_frontend_url('orders/{}/view'.format(order_identifier)))


Test patch: