Files
robot-shop/payment/payment.py

158 lines
4.6 KiB
Python
Raw Permalink Normal View History

import random
2019-12-19 11:00:26 +00:00
import instana
2018-01-25 17:42:38 +00:00
import os
import sys
2018-01-26 16:01:39 +00:00
import time
2018-01-25 17:42:38 +00:00
import logging
2018-01-26 16:01:39 +00:00
import uuid
2018-02-12 13:06:35 +00:00
import json
2018-01-25 17:42:38 +00:00
import requests
2019-01-25 17:32:35 +00:00
import traceback
2018-01-25 17:42:38 +00:00
from flask import Flask
from flask import Response
2018-01-25 17:42:38 +00:00
from flask import request
2018-01-26 16:01:39 +00:00
from flask import jsonify
from rabbitmq import Publisher
# Prometheus
import prometheus_client
from prometheus_client import Counter, Histogram
2018-01-25 17:42:38 +00:00
app = Flask(__name__)
app.logger.setLevel(logging.INFO)
2018-01-25 17:42:38 +00:00
2018-04-16 15:19:38 +01:00
CART = os.getenv('CART_HOST', 'cart')
USER = os.getenv('USER_HOST', 'user')
2018-12-18 12:51:11 +00:00
PAYMENT_GATEWAY = os.getenv('PAYMENT_GATEWAY', 'https://paypal.com/')
2018-04-16 15:19:38 +01:00
# Prometheus
PromMetrics = {}
PromMetrics['SOLD_COUNTER'] = Counter('sold_count', 'Running count of items sold')
PromMetrics['AUS'] = Histogram('units_sold', 'Avergae Unit Sale', buckets=(1, 2, 5, 10, 100))
PromMetrics['AVS'] = Histogram('cart_value', 'Avergae Value Sale', buckets=(100, 200, 500, 1000, 2000, 5000, 10000))
2019-01-25 17:32:35 +00:00
@app.errorhandler(Exception)
def exception_handler(err):
app.logger.error(str(err))
return str(err), 500
2018-01-25 17:42:38 +00:00
@app.route('/health', methods=['GET'])
def health():
return 'OK'
# Prometheus
@app.route('/metrics', methods=['GET'])
def metrics():
res = []
for m in PromMetrics.values():
res.append(prometheus_client.generate_latest(m))
return Response(res, mimetype='text/plain')
2018-01-25 17:42:38 +00:00
@app.route('/pay/<id>', methods=['POST'])
def pay(id):
app.logger.info('payment for {}'.format(id))
cart = request.get_json()
app.logger.info(cart)
2019-01-23 18:02:32 +00:00
anonymous_user = True
# check user exists
try:
req = requests.get('http://{user}:8080/check/{id}'.format(user=USER, id=id))
except requests.exceptions.RequestException as err:
app.logger.error(err)
return str(err), 500
if req.status_code == 200:
anonymous_user = False
# check that the cart is valid
2019-01-25 17:32:35 +00:00
# this will blow up if the cart is not valid
2019-01-23 18:02:32 +00:00
has_shipping = False
for item in cart.get('items'):
if item.get('sku') == 'SHIP':
has_shipping = True
2019-02-11 16:17:38 +00:00
if cart.get('total', 0) == 0 or has_shipping == False:
2019-01-25 17:32:35 +00:00
app.logger.warn('cart not valid')
2019-01-23 18:02:32 +00:00
return 'cart not valid', 400
# dummy call to payment gateway, hope they dont object
try:
req = requests.get(PAYMENT_GATEWAY)
app.logger.info('{} returned {}'.format(PAYMENT_GATEWAY, req.status_code))
except requests.exceptions.RequestException as err:
app.logger.error(err)
return str(err), 500
if req.status_code != 200:
return 'payment error', req.status_code
2018-01-25 17:42:38 +00:00
# Prometheus
# items purchased
item_count = countItems(cart.get('items', []))
PromMetrics['SOLD_COUNTER'].inc(item_count)
PromMetrics['AUS'].observe(item_count)
PromMetrics['AVS'].observe(cart.get('total', 0))
2018-01-26 16:01:39 +00:00
# Generate order id
orderid = str(uuid.uuid4())
2018-01-30 09:16:51 +00:00
queueOrder({ 'orderid': orderid, 'user': id, 'cart': cart })
2018-01-26 16:01:39 +00:00
2019-01-23 18:02:32 +00:00
# add to order history
if not anonymous_user:
try:
req = requests.post('http://{user}:8080/order/{id}'.format(user=USER, id=id),
data=json.dumps({'orderid': orderid, 'cart': cart}),
headers={'Content-Type': 'application/json'})
app.logger.info('order history returned {}'.format(req.status_code))
except requests.exceptions.RequestException as err:
app.logger.error(err)
return str(err), 500
2018-02-12 13:06:35 +00:00
2018-02-14 09:29:47 +00:00
# delete cart
2019-01-23 18:02:32 +00:00
try:
req = requests.delete('http://{cart}:8080/cart/{id}'.format(cart=CART, id=id));
app.logger.info('cart delete returned {}'.format(req.status_code))
except requests.exceptions.RequestException as err:
app.logger.error(err)
return str(err), 500
if req.status_code != 200:
return 'order history update error', req.status_code
2018-01-25 17:42:38 +00:00
2018-01-30 09:16:51 +00:00
return jsonify({ 'orderid': orderid })
2018-01-26 16:01:39 +00:00
def queueOrder(order):
app.logger.info('queue order')
2021-03-02 16:02:45 +00:00
# For screenshot demo requirements optionally add in a bit of delay
delay = int(os.getenv('PAYMENT_DELAY_MS', 0))
time.sleep(delay / 1000)
headers = {}
publisher.publish(order, headers)
2018-01-26 16:01:39 +00:00
2019-01-23 18:02:32 +00:00
def countItems(items):
count = 0
for item in items:
if item.get('sku') != 'SHIP':
count += item.get('qty')
return count
2018-01-26 16:01:39 +00:00
# RabbitMQ
publisher = Publisher(app.logger)
2018-01-25 17:42:38 +00:00
if __name__ == "__main__":
sh = logging.StreamHandler(sys.stdout)
sh.setLevel(logging.INFO)
2019-02-06 10:04:52 +00:00
fmt = logging.Formatter('%(asctime)s - %(name)s - %(levelname)s - %(message)s')
2018-12-18 12:51:11 +00:00
app.logger.info('Payment gateway {}'.format(PAYMENT_GATEWAY))
2018-01-31 10:11:58 +00:00
port = int(os.getenv("SHOP_PAYMENT_PORT", "8080"))
2019-01-23 18:02:32 +00:00
app.logger.info('Starting on port {}'.format(port))
2018-01-25 17:42:38 +00:00
app.run(host='0.0.0.0', port=port)