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-31 17:27:17 +00:00
|
|
|
import opentracing as ot
|
|
|
|
import opentracing.ext.tags as tags
|
2018-01-25 17:42:38 +00:00
|
|
|
from flask import Flask
|
|
|
|
from flask import request
|
2018-01-26 16:01:39 +00:00
|
|
|
from flask import jsonify
|
|
|
|
from rabbitmq import Publisher
|
2018-01-25 17:42:38 +00:00
|
|
|
|
|
|
|
app = Flask(__name__)
|
|
|
|
|
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
|
|
|
|
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'
|
|
|
|
|
|
|
|
@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
|
|
|
|
|
2019-02-11 16:17:38 +00:00
|
|
|
# add some log info to the active trace
|
|
|
|
span = ot.tracer.active_span
|
|
|
|
span.log_kv({'id': id})
|
|
|
|
span.log_kv({'cart': cart})
|
|
|
|
|
2019-01-23 18:02:32 +00:00
|
|
|
# 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
|
|
|
|
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')
|
2019-02-11 16:17:38 +00:00
|
|
|
# RabbitMQ pika is not currently traced automatically
|
2018-01-31 17:27:17 +00:00
|
|
|
# opentracing tracer is automatically set to Instana tracer
|
|
|
|
# start a span
|
2018-07-23 12:20:20 +01:00
|
|
|
|
2018-10-11 11:09:50 +02:00
|
|
|
parent_span = ot.tracer.active_span
|
2019-02-08 13:17:52 +00:00
|
|
|
with ot.tracer.start_active_span('queueOrder', child_of=parent_span,
|
2018-01-31 17:27:17 +00:00
|
|
|
tags={
|
2019-02-08 13:17:52 +00:00
|
|
|
'exchange': Publisher.EXCHANGE,
|
|
|
|
'key': Publisher.ROUTING_KEY
|
|
|
|
}) as tscope:
|
2019-02-15 12:56:25 +00:00
|
|
|
tscope.span.set_tag('span.kind', 'intermediate')
|
2019-02-11 16:17:38 +00:00
|
|
|
tscope.span.log_kv({'orderid': order.get('orderid')})
|
2019-02-08 13:17:52 +00:00
|
|
|
with ot.tracer.start_active_span('rabbitmq', child_of=tscope.span,
|
|
|
|
tags={
|
|
|
|
'exchange': Publisher.EXCHANGE,
|
|
|
|
'sort': 'publish',
|
|
|
|
'address': Publisher.HOST,
|
|
|
|
'key': Publisher.ROUTING_KEY
|
|
|
|
}
|
|
|
|
) as scope:
|
|
|
|
|
|
|
|
# For screenshot demo requirements optionally add in a bit of delay
|
|
|
|
delay = int(os.getenv('PAYMENT_DELAY_MS', 0))
|
|
|
|
time.sleep(delay / 1000)
|
|
|
|
|
|
|
|
headers = {}
|
|
|
|
ot.tracer.inject(scope.span.context, ot.Format.HTTP_HEADERS, headers)
|
|
|
|
app.logger.info('msg headers {}'.format(headers))
|
|
|
|
|
|
|
|
publisher.publish(order, headers)
|
2018-01-26 16:01:39 +00:00
|
|
|
|
2019-01-23 18:02:32 +00:00
|
|
|
|
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')
|
|
|
|
#sh.setFormatter(fmt)
|
|
|
|
#app.logger.addHandler(sh)
|
2018-01-25 17:42:38 +00:00
|
|
|
app.logger.setLevel(logging.INFO)
|
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)
|