stripe does not save if transaction is successful in flask - python

I am trying to save some information in database if transaction is successful, in the stripe_webhook view. But not successful. is it that data cannot be saved directly in webhook ? so frustrating for me. I checked online for sample codes but could not find the ones that insert or update database for successful transaction.
from site.models import Post, Chapter, Order
import stripe
from sqlalchemy import desc
#posts.route("/paynow")
#login_required
def paynow():
return render_template('paynow.html',)
#posts.route('/stripe_pay')
#login_required
def stripe_pay():
amt = 10000
stripe.api_key = current_app.config['STRIPE_SECRET_KEY']
session = stripe.checkout.Session.create(
payment_method_types=['card'],
line_items=[{
'price_data': {
'currency': 'usd',
'product_data': {
'name': 'T-shirt',
},
'unit_amount': amt,
},
'quantity': 1,
}],
mode='payment',
success_url=url_for('posts.payment_success', _external=True) + '?session_id={CHECKOUT_SESSION_ID}',
cancel_url=url_for('posts.paynow', _external=True),
)
return {
'checkout_session_id': session['id'],
'checkout_public_key': current_app.config['STRIPE_PUBLIC_KEY']
}
#posts.route('/stripe_webhook', methods=['POST'])
#login_required
def stripe_webhook():
print('WEBHOOK CALLED')
if request.content_length > 1024 * 1024:
print('REQUEST TOO BIG')
abort(400)
payload = request.get_data()
sig_header = request.environ.get('HTTP_STRIPE_SIGNATURE')
endpoint_secret = 'whsec_*************************************'
event = None
try:
event = stripe.Webhook.construct_event(
payload, sig_header, endpoint_secret
)
except ValueError as e:
# Invalid payload
print('INVALID PAYLOAD')
return {}, 400
except stripe.error.SignatureVerificationError as e:
# Invalid signature
print('INVALID SIGNATURE')
return {}, 400
# Handle the checkout.session.completed event
if event['type'] == 'checkout.session.completed':
session = event['data']['object']
print(session)
line_items = stripe.checkout.Session.list_line_items(session['id'], limit=1)
print(line_items['data'][0]['description'])
# save to database if successful
save_order = Order(trans_id = "pppppppppp")
db.session.add(save_order)
db.session.commit()
return {}
#posts.route('/payment_success')
#login_required
def payment_success():
cart=Cart.query.filter_by(username = current_user.username).all()
cart.status = "paid"
db.session.commit()
return render_template('payment_success.html')

According to the Stripe customer care, I must used a live domain instead of local host

Related

Staying login problem about CallbackURL after payment

my view is like :
def get_user_pending_order(request):
user_profile = get_object_or_404(Profile, user=request.user)
order = Order.objects.filter(owner=user_profile, is_ordered=False)
if order.exists():
return order[0]
return 0
MERCHANT = 'xxx...xxx'
ZP_API_REQUEST = "https://api.zarinpal.com/pg/v4/payment/request.json"
ZP_API_VERIFY = "https://api.zarinpal.com/pg/v4/payment/verify.json"
ZP_API_STARTPAY = "https://www.zarinpal.com/pg/StartPay/{authority}"
amount = ''
description = "text" # Required
email = 'example#email.com' # Optional
mobile = '09999999999' # Optional
# Important: need to edit for realy server.
CallbackURL = 'https://example.com/payment/verify/'
def send_request(request):
print(get_user_pending_order(request).owner.phone_number)
req_data = {
"merchant_id": MERCHANT,
"amount": int(get_user_pending_order(request).get_total()),
"callback_url": CallbackURL,
"description": description,
"metadata": {"mobile": mobile,
"email": email}
}
req_header = {"accept": "application/json",
"content-type": "application/json'"}
req = requests.post(url=ZP_API_REQUEST, data=json.dumps(
req_data), headers=req_header)
authority = req.json()['data']['authority']
if len(req.json()['errors']) == 0:
return redirect(ZP_API_STARTPAY.format(authority=authority))
else:
e_code = req.json()['errors']['code']
e_message = req.json()['errors']['message']
return HttpResponse(f"Error code: {e_code}, Error Message: {e_message}")
def verify(request):
t_status = request.GET.get('Status')
t_authority = request.GET['Authority']
if request.GET.get('Status') == 'OK':
req_header = {"accept": "application/json",
"content-type": "application/json'"}
req_data = {
"merchant_id": MERCHANT,
"amount": int(get_user_pending_order(request).get_total()),
"authority": t_authority
}
req = requests.post(url=ZP_API_VERIFY, data=json.dumps(req_data), headers=req_header)
if len(req.json()['errors']) == 0:
t_status = req.json()['data']['code']
if t_status == 100:
user = request.user
order_to_purchase = get_user_pending_order(request)
order_to_purchase.is_ordered = True
order_to_purchase.date_ordered=datetime.datetime.now()
order_to_purchase.created_on_time=datetime.datetime.now()
order_to_purchase.save()
order_items = order_to_purchase.items.all()
for order_item in order_items:
order_item.product.quantity = order_item.product.quantity - 1
order_item.product.save()
order_items.update(is_ordered=True, date_ordered=datetime.datetime.now())
subject = 'successful'
c = {
"refid":str(req.json()['data']['ref_id']),
"ref_code":order_to_purchase.ref_code,
"owner":order_to_purchase.owner,
}
email_template_name = "pay/after_pay_confirm_email.html"
email_html = render_to_string(email_template_name, c)
email_from = settings.EMAIL_HOST_USER
send_mail(subject, email_html, email_from, [user.email], html_message=email_html)
ctx = {'message_good':'good'}
return render(request, 'pay/verify.html', ctx)
elif t_status == 101:
...
else:
....
else:
...
else:
...
At first about user, is logged. and about send_request function it work totally fine...so it pass user into Payment gateway and after successful payment it come back to verify function by CallbackURL. to show success page and do order_to_purchase.is_ordered = True ...
for me with my pc, phone, other android phones, ios, windows, linux. and about browsers like chrome Firefox it work correctly and everything is fine.
but some clients tell me they face to 'AnonymousUser' object is not iterable after successful payment and when they back to verify. its kinda like that they logged out by pushing request to payment gateway.
also i made purchase by that account exactly same way and i didn't face to that error. it show is that phone or browser problem that half of my clients faced to that. i have no idea what should i do!!!

Attribute error : 'str' object has no attribute 'post'

I am new to Django and trying to integrate razorpay with my website but getting error
AttributeError: 'str' object has no attribute 'post'
views.py
def order(request, id):
product = Product.objects.get(prod_ID=id)
if request.method == 'POST':
customer_id = request.user
product = Product.objects.get(prod_ID=id)
product_id = product
try:
quantity = request.POST['quantity']
quantity = int(quantity)
order_price = quantity * product.prod_Price
print(order_price)
except MultiValueDictKeyError:
pass
try:
size = request.POST['size']
value.update(size=size)
except MultiValueDictKeyError:
pass
try:
Colour = request.POST['Color']
value.update(Colour=Colour)
except MultiValueDictKeyError:
pass
attribute_value = json.dumps(value)
order_store = Order(user_id=customer_id, prod_id=product_id, quantity=quantity,
attribute_value=attribute_value,
order_price=order_price)
if order_store:
order_store.save()
o_id = Order.objects.get(order_id=order_store.order_id)
payment_store = Payment(order_id=o_id)
payment_store.save()
client = razorpay.Client('rzp_test_Cut6mUJgrjfQU', 'LSNlrKrH0NoUq8Y9rEUbg27')
print(client)
data = {
'amount': order_price * 100,
'currency': "INR",
'receipt': 'Order for ' + str(o_id.order_id),
'notes': {
'name': o_id.user_id.first_name + o_id.user_id.last_name,
'Payment_for': o_id.prod_id.prod_Name
}
}
print(data)
order_detail = client.order.create(data=data)
print(order_detail)
return render(request, 'user/payment.html', {'order_store': order_store})
context = {'products': products
}
return render(request, 'user/order.html', context)
Here I am trying to integrate payment with my website but after creating order and payment status I am trying to do payment but I don't know what I am doing wrong.
To intialize the client you have to use the auth parameter - see razorpay Initialization.
And give a tuple as value:
import razorpay
client = razorpay.Client(auth=("<YOUR_KEY>", "<YOUR_SECRET>"))

How can I make my API request working via Postman?

I am working with Postman for the first time and GET request to my simple API is working fine, but when I try POST request it gives me an error and I have no idea where is the problem. Can you please advise?
API function:
#app.route('/customer', methods=['POST'])
def create_customer():
request_data = request.get_json()
new_customer = {
"email": request_data['email'],
"username": request_data['username'],
"name": request_data['name'],
"newsletter_status": request_data['newsletter_status'],
"trips": []
}
for customer in customers:
if customer['username'] == new_customer['username']:
return jsonify({'error': 'username already exist'})
customers.append(new_customer)
return jsonify(new_customer)
Screenshots from postman
This I put in the body + error message
Headers set up - Content-Type application/json
I think your new customer variables should not be in string format, I don't know why they are and also try my option for getting the request body:
import json
def create_customer():
request_data = json.loads(request.body)
new_customer = {
email = request_data['email'],
username = request_data['username'],
name = request_data['name'],
newsletter_status = request_data['newsletter_status'],
trips: []
}
for customer in customers:
if customer['username'] == new_customer['username']:
return jsonify({'error': 'username already exist'})
customers.append(new_customer)
return jsonify(new_customer)
Yur code works fine , i just tested with postman:
from flask import jsonify
from flask import Flask
from flask import request
app = Flask(__name__)
#app.route('/')
def hello_world():
return 'Hello, World!'
#app.route('/customer', methods=['POST'])
def create_customer():
customers=[]
customers.append(request.get_json())
request_data = request.get_json()
new_customer = {
"email": request_data['email'],
"username": request_data['username']+"HHH",
"name": request_data['name'],
"newsletter_status": request_data['newsletter_status'],
"trips": []
}
print(new_customer['username'])
print(customers[0]['username'])
for customer in customers:
if customer['username'] == new_customer['username']:
return jsonify({'error': 'username already exist'})
customers.append(new_customer)
return jsonify(new_customer)
Can you check what is exactly send in postman ?
you can do it by clicking console ( can get from left botom corner or by pressing ctrl+alt+c ) >request > requestbody

How to emit to a certain socket from a thread in flask socketio?

i want to isolate each socket connection and emit to that specific connection, when i try to run without threading, it works fine and each socket gets it's own messages, but when i use threading, it just starts broadcasting and all the clients receive all the messages.
Here's how my client side looks like :
var socket = io.connect('https://my_server_link');
socket.on('connect', function() {
console.log('Connection Success')
});
// Recieves the session id
socket.on('connection_status', (data)=>{
console.log('Connection Status')
console.log(data);
session_id = data['session_id']
socket.emit('verifyClient', {'session_id': session_id, 'api_id': api_id})
})
socket.on('verification_status', (data)=>{
console.log('Verification Status')
console.log(data)
if (data['status']){
console.log('Verified')
socket.emit('setupUser', {'session_id': session_id, 'user_id': user_id})
}
})
socket.on('user_setup_status', (data)=>{
console.log('User Setup Status');
console.log(data);
if (data['status']){
console.log('User Setup Successful, Starting monitoring...')
running_ops = setInterval(()=>{
op_interval(session_id)
}, 5000)
}
})
function op_interval(session_id){
ctx2.drawImage(video, 0, 0, video.width, video.height);
frame = canva.toDataURL('image/jpeg');
frame = to_blob(frame);
socket.emit('monitor', {
'frame':frame,
'session_id':session_id
});
}
// when error messages are encountered, generate alert on client side
socket.on('alert', (alert)=>{
console.log(alert);
// TODO : Handle Alerts Here
})
And here's my server side.
app = Flask(__name__)
CORS(app, resources={"*": {"origins": "*"}})
# eventlet.monkey_patch()
socketio = SocketIO(app, async_mode='threading', cors_allowed_origins="*")
# Set up socket connection to the client and register session id
#socketio.on('connect')
def handle_connection():
print('Connection Successfull')
# connection_id = request.sid
session_id = ''.join(random.choice(string.ascii_lowercase) for i in range(10))
active_socket_sessions[session_id] = {'session_id': session_id}#, 'connection_id': connection_id}
join_room(session_id)
emit('connection_status', {'status':'success', 'session_id':session_id}, room=session_id)
#socketio.on('verifyClient')
def verification(data):
session_id = data['session_id']
client_id = data['api_id']
verified = False
message = "Session not found."
if session_id in active_socket_sessions.keys():
client, message = verify_client(database, client_id, active_sessions)
if len(client.keys()) > 0:
verified = True
active_socket_sessions[session_id]['client_id'] = client['client_id']
emit('verification_status', {'status':verified, 'message': message, 'session_id':session_id}, room=session_id)
else:
emit('verification_status', {'status':verified, 'message': message, 'session_id':session_id})
#socketio.on('setupUser')
def user_setup(data):
session_id = data['session_id']
user_id = data['user_id']
found = False
message = 'Session not found.'
if session_id in active_socket_sessions.keys():
client_id = active_socket_sessions[session_id]['client_id']
user, message = get_user(database, {'client_id': client_id}, user_id)
if len(user.keys()) > 0:
found = True
user['person_encoding'] = str(user['person_encoding'])
active_socket_sessions[session_id]['user'] = user
rediss.set_dict(session_id, active_socket_sessions[session_id])
active_socket_sessions[session_id] = {}
emit('user_setup_status', {'status': found, 'message': message, 'session_id': session_id}, room=session_id)
else:
emit('user_setup_status', {'status': found, 'message': message, 'session_id': session_id})
#socketio.on('disconnect')
def handle_disconnect():
# Handle Clearing Of Socket From Redis And Also Closing The Socket Connection
emit('connection_ended', {'data': 'Successfully Disconnected, Socket Is Closed.'})
#socketio.on('monitor')
def monitor(data):
frame = data['frame']
session_id = data['session_id']
socketio.start_background_task(monitoring_process, frame, session_id)
def monitoring_process(frame, session_id):
if session_id in active_socket_sessions.keys():
session = rediss.get_dict(session_id)
client_id = session['client_id']
user = session['user']
user_encoding = np.array(eval(user['person_encoding']))
person_id = user['person_id']
browser_info = {}
frame = cv2.imdecode(np.frombuffer(frame, np.uint8), -1)
preds = model.model.predict(frame, user_encoding)
if not preds['recognized']:
alert = vars.BRISO_ALERTS[preds['message']]
alert['timestamp'] = str(time.time())
alert['log_id'] = ''.join(random.choice(string.ascii_lowercase) for i in range(10))
alert['person_id'] = person_id
headers = browser_info
message, flag = log_alert(database, client_id, alert, headers)
preds['session_id'] = session_id
socketio.emit('alert', preds, room=session_id)
if __name__ == "__main__":
socketio.run(app, host=vars.HOST_NAME, port=vars.SERVER_PORT, debug=False, use_reloader=False)
Ok, so as suggested by Miguel Grinberg himself, when i asked him on github, the only replacement i had to make was to switch from setting my own session_id to request.sid and not calling the join_room method.
The updated (working) code looks like this :
For client side socket.io:
socket.on('connect', function() {
console.log('Connection Success')
});
// Recieves the session id
socket.on('connection_status', (data)=>{
console.log('Connection Status')
console.log(data);
session_id = data['session_id']
socket.emit('verify_client', {'session_id': session_id, 'api_id': api_id}, (status)=>{
socket.emit('setup_user', {'session_id': session_id, 'user_id': user_id}, (status)=>{
running_ops = setInterval(()=>{
op_interval(session_id)
}, 5000)
})
})
})
function op_interval(session_id){
ctx2.drawImage(video, 0, 0, video.width, video.height);
frame = canva.toDataURL('image/jpeg');
frame = to_blob(frame);
socket.emit('monitor', {
'frame':frame,
'session_id':session_id
});
}
// when error messages are encountered, generate alert on client side
socket.on('alert', (alert)=>{
console.log(alert);
})
for python flask socketio
# Set up socket connection to the client and register session id
#socketio.on('connect')
def handle_connection():
print('Connection Successfull')
session_id = request.sid
active_socket_sessions[session_id] = {'session_id': session_id}#, 'connection_id': connection_id}
emit('connection_status', {'status':'success', 'session_id':session_id}, room=session_id)
#socketio.on('verify_client')
def verification(data):
session_id = request.sid
client_id = data['api_id']
verified = False
message = "Session not found."
if session_id in active_socket_sessions.keys():
client, message = verify_client(database, client_id, active_sessions)
if len(client.keys()) > 0:
verified = True
active_socket_sessions[session_id]['client_id'] = client['client_id']
return json.dumps({'status': verified, 'message': message, 'session_id': session_id})
else:
return json.dumps({'status': verified, 'message': message, 'session_id': session_id})
#socketio.on('setup_user')
def user_setup(data):
session_id = request.sid
user_id = data['user_id']
found = False
message = 'Session not found.'
if session_id in active_socket_sessions.keys():
client_id = active_socket_sessions[session_id]['client_id']
user, message = get_user(database, {'client_id': client_id}, user_id)
if len(user.keys()) > 0:
found = True
user['person_encoding'] = str(user['person_encoding'])
active_socket_sessions[session_id]['user'] = user
rediss.set_dict(session_id, active_socket_sessions[session_id])
active_socket_sessions[session_id] = {}
return json.dumps({'status': found, 'message': message, 'session_id': session_id})
else:
return json.dumps({'status': found, 'message': message, 'session_id': session_id})
#socketio.on('disconnect')
def handle_disconnect():
# Handle Clearing Of Socket From Redis And Also Closing The Socket Connection
emit('connection_ended', {'data': 'Successfully Disconnected, Socket Is Closed.'})
#socketio.on('monitor')
def monitor(data):
frame = data['frame']
session_id = request.sid
process = Thread(target=monitoring_process, args=(frame, session_id,))
process.start()
process.join()
socketio.start_background_task(monitoring_process, frame, session_id)
def monitoring_process(frame, session_id):
if session_id in active_socket_sessions.keys():
session = rediss.get_dict(session_id)
client_id = session['client_id']
user = session['user']
user_encoding = np.array(eval(user['person_encoding']))
person_id = user['person_id']
browser_info = {}
frame = cv2.imdecode(np.frombuffer(frame, np.uint8), -1)
preds = model.model.predict(frame, user_encoding)
if not preds['recognized']:
alert = vars.ALERTS[preds['message']]
alert['timestamp'] = str(time.time())
alert['log_id'] = ''.join(random.choice(string.ascii_lowercase) for i in range(10))
alert['person_id'] = person_id
headers = browser_info
message, flag = log_alert(database, client_id, alert, headers)
preds['session_id'] = session_id
# return preds
socketio.emit('alert', preds, room=session_id)

Using Flask API, how to upload & download file from server using jwt_required decorator from browser/ client?

I suspect it has something got to do with refresh token. Could not understand how to use it by the docs. Can I know the exact code how to use it?
The access token is created during login:
#app.route('/login', methods=['POST','GET'])
def login():
username = request.form["email"]
password = request.form["password"]
my_token_expiry_time = datetime.timedelta(seconds=60)
segments = 0
access_token = None
if request.method == 'POST':
result_set = authenticate_user(username, password)
if result_set:
ss1 = select([nsettings]).\
where(nsettings.c.mattribute == 'my_jwt_expiry_time_min')
rss1 = g.conn.execute(ss1)
if rss1.rowcount > 0:
for r in rss1:
my_token_expiry_time = datetime.timedelta(seconds=
(int(r[nsettings.c.mvalue])* 60))
else:
my_token_expiry_time = datetime.timedelta(
seconds=(2 * 60 *60)) # 2 hours
#print result_set, 'result_set result_set'
session['email'] = result_set['email']
access_token = create_access_token(
identity=username, expires_delta=my_token_expiry_time)
user_dict = result_set
if user_dict:
session['email'] = user_dict['email']
session['id'] = result_set['id']
# users and related views
session['access_token'] = access_token
print access_token, 'aaaaaaaaaaa'
return jsonify({
'email': session['email'],
'user_id': result_set['id'],
'access_token': access_token,
'id': session['id'],
}), 200
else:
return jsonify({'message': "Invalid credentials, retry"}), 401
return "True"
The flask api call to upload:
#app.route('/rt/api/v1.0/issues/<int:issue_id>/documents', methods=['POST'])
#jwt_required
def rt_doc_upload(issue_id):
'''
Upload documents for a rt ticket.
'''
# Iterate through the list of files, we don't care about the
# attribute name. We consider only the first file and ignore the
# rest.
if 'id' in session:
uploader = "3"
minternal_only = True
bool_internal_update = False
msg_str = None
for attr, document in request.files.iteritems():
trans = g.conn.begin()
try:
orig_filename = document.filename
filename, upload_folder = check_or_insert_document(
orig_filename, uploader)
new_doc = add_doc(orig_filename, filename)
print orig_filename, 'origooooo'
ins = archival_docs.insert().values(new_doc)
rs = g.conn.execute(ins)
doc_id = rs.inserted_primary_key[0]
filename = (str(doc_id) + '_' + orig_filename)
stmt = archival_docs.update().values(stored_name=filename).\
where(archival_docs.c.id == doc_id)
g.conn.execute(stmt)
document.save(os.path.join(upload_folder, filename))
mattach_doc_id = genUrl(doc_id)
trans.commit()
return jsonify(
{'issue_doc_id': rs.inserted_primary_key[0]}), 201
except Exception, e:
print e
trans.rollback()
return jsonify({'message': "Did not find any file"}), 400
return jsonify({'message': "UNAUTHORIZED"}), 401
When used with runserver and on commenting the jwt_required decorator I am able to upload and download files
Using sqlalchemy core, python and flask. The api call to upload worked for more than a month, but suddenly stopped working now

Categories

Resources