How can I access item description from my Stripe webhook? - python-3.x

I am using Stripe Checkout (Client & Server Integration) and I want to be able to access the item description from my web hook.
session = stripe.checkout.Session.create(
payment_method_types=['card'],
line_items=[{
'name': 'Name of Product',
'description': description,
'amount': 30,
'currency': 'gbp',
'quantity': 1,
}],
success_url='https://www.website.uk/success',
cancel_url='https://www.website.uk/cancel',
)
Description is a variable that holds my item description.
My web hook looks like this (straight from docs):
#require_POST
#csrf_exempt
def my_webhook_view(request):
payload = request.body
sig_header = request.META['HTTP_STRIPE_SIGNATURE']
event = None
try:
event = stripe.Webhook.construct_event(
payload, sig_header, endpoint_secret
)
except ValueError as e:
# Invalid payload
return HttpResponse(status=400)
except stripe.error.SignatureVerificationError as e:
# Invalid signature
return HttpResponse(status=400)
# Handle the checkout.session.completed event
if event['type'] == 'payment_intent.succeeded':
session = event['data']['object']
# Fulfill the purchase...
return HttpResponse(status=200)
My question is, how can I access my "description" variable from within the web hook? (Will be accessing it after # Fulfill the purchase)
I can see it is part of the session object (https://stripe.com/docs/api/checkout/sessions/object) but I'm not sure how to access it?
Have tried:
description = session['display_items']['custom']['description']
But I'm getting a key_error on display_items even though it is listed in the docs as part of the session object.

I had a similar issue which may help others who end up here; the length of the line_items array is 1 and the object which holds the properties is at index [0], therefore:
session.line_items[0].description
should give one access to the properties and values

Related

How to specify dependencies for the entire router?

class User(BaseModel):
name: str
token: str
fake_db = [
User(name='foo', token='a1'),
User(name='bar', token='a2')
]
async def get_user_by_token(token: str = Header()):
for user in fake_db:
if user.token == token:
return user
else:
raise HTTPException(status_code=401, detail='Invalid token')
#router.get(path='/test_a', summary='Test route A')
async def test_route_a(user: User = Depends(get_user_by_token)):
return {'name': user.name}
#router.get(path='/test_b', summary='Test route B')
async def test_route_a(user: User = Depends(get_user_by_token)):
return {'name': user.name}
I would like to avoid code duplication. Is it possible to somehow set the line user: User = Depends(get_user_by_token) for the entire router? At the same time, I need the user object to be available in each method.
It is very important that the openapi says that you need to specify a header with a token for the method.
You can use the dependencies parameter to add global dependencies when creating the router instance:
router = APIRouter(dependencies=[Depends(get_user_by_token)])
or, when adding the router to the app instance:
app.include_router(router, dependencies=[Depends(get_user_by_token)])
Please have a look at FastAPI's documentation on Dependencies for more details.
As for getting the return value of a global dependency, you can't really do that. The way around this issue is to store the returned value to request.state (as described here), which is used to store arbitrary state (see the implementation of State as well). Hence, you could have something like this:
def get_user_by_token(request: Request, token: str = Header()):
for user in fake_db:
if user.token == token:
request.state.user = user
# ...
Then, inside your endpoint, you could retrieve the user object using request.state.user, as described in this answer.

Search for git issue that contains a specific string in title using requests library python

I am using requests library to search for git issues. I want to search a git issue that contains a specific string ("has issues") in the title of the issue. I have tried various approaches, but my search results do not get filtered by the string.
def search_issue():
url = "https://api.github.com/repos/%s/%s/issues" % (REPO_OWNER, REPO_NAME)
print(url)
session = create_session()
session.params = {'q':'has issues+in:title', 'state': 'open', 'type': 'issue', 'sort': 'created', 'direction': 'desc'}
r = session.get(url)
pprint(r.json())
def create_session():
# Create an authenticated session
session = requests.Session()
session.auth = (USERNAME, TOKEN)
return session
How do I pass the params to session such that the results get filtered by the string "has issues" in title? Other params, like state: open or closed and direction: asc or desc are working fine. But I'm not able to filter based on title.

Creating several DB instances from a single POST request

I have a table like this:
class Mapping(db.Model):
map_id = db.Column(db.Integer, primary_key=True)
user_id = db.Column(db.Integer)
bike_id = db.Column(db.String(255))
is_active_data = db.Column(db.Boolean, default=True)
created_by = db.Column(db.String(150))
updated_by = db.Column(db.String(150))
My POST method:
def save_MapperM(adddata):
create_data = Mapping(**adddata)
db.session.add(create_data)
db.session.commit()
return dict(Successful="Successfully Created")
Route:
#test.route("/addmapper"))
class MapperV(Resource):
#staticmethod
def post():
if request.method == 'POST':
save_data = request.get_json()
try:
return jsonify(save_MapperM(save_data))
except Exception:
return jsonify({'Unsuccessful': 'Looks like you missed something !!'})
Current Code :
The current code will take only one bike_id for every request.
Requirements:
I want to take multiple bike_id's as for one user id and store it as multiple records in the table level.
Example data format coming from UI:
{ user_id: 1, bike_id: 1,2,3,4 }
The easiest solution is to modify your save_MapperM function with a cycle:
def save_MapperM(adddata):
for bike_id in adddata["bike_id"]:
item_data = adddata.copy()
item_data["bike_id"] = bike_id
create_data = Mapping(**item_data)
db.session.add(create_data)
db.session.commit()
return dict(Successful="Successfully Created")
But be careful with this function as it allows to create Mapping instances with any parameters received from the POST request. It looks like it is intended but it can lead to security issues if your Mapping class has some private attributes which should be filled only on the server side. For example the user "Mike" can send a request:
{ "user_id": 1, "bike_id": [1, 2], "created_by": "Alex", "updated_by": "Alex" }
It will cause the save_MapperM function to create instances with created_by and updated_by values set to "Alex" which may not be true. It is better to get such attributes from the session data.
So your post method may look like this (post and save_MapperM functionality combined):
def post():
request_data = request.get_json()
for bike_id in request_data.get("bike_id", []):
item = Mapping(
user_id=request_data.get("user_id"),
bike_id=bike_id,
created_by=session.get("username"),
updated_by=session.get("username"),
)
db.session.add(item)
try:
db.session.commit()
except Exception:
return jsonify({"success": False})
return jsonify({"success": True})
The next step may be implementing request JSON data validation. It is OK when you have a couple of JSON keys with a simple structure but when you need to pass lots of data you need to be sure it is correct. You can use some of the serialization/ODM libraries for this Marshmallow for example.

How to submit custom fields data by python wordpress xmlrpc

I use wp job manager on my website. when I tried to add listing by xmlrpc, everything is fine, but Categories and Location are empty.
Screenshot
Screenshot
My code is as below. Could you tell me what's wrong with my code?
Thanks
from wordpress_xmlrpc import Client, WordPressPost
from wordpress_xmlrpc.methods.posts import GetPosts
from wordpress_xmlrpc.methods import posts
from wordpress_xmlrpc import WordPressTerm
from wordpress_xmlrpc.methods import taxonomies
wp = Client('http://127.0.0.1/15wp/xmlrpc.php', 'admin', '123456')
# now let's create a new product
widget = WordPressPost()
widget.post_type = 'job_listing'
widget.title = 'Widgetlast02'
widget.content = 'This is the widgets description.'
widget.post_status = 'publish'
widget.custom_fields = []
widget.custom_fields.append({
'job_location': 'Newyork',
'job_listing_category': 'hotel'
})
widget.id = wp.call(posts.NewPost(widget))
The custom_fields attribute expects a list of dicts.
Within each dict, it expects values for key and value fields.
Here, key is the name of the custom field, and value is the value you want to assign to it.
Below is the snippet for your specific example.
widget.custom_fields = [
{
'key': 'job_location',
'value': 'Newyork'
},
{
'key': 'job_listing_category',
'value': 'hotel'
}
]
This is just a guess from looking at the documentation for WordPressPost in wordpress_xmlrpc:
(Emphasis mine)
class WordPressPost
Represents a post, page, or other registered custom post type in
WordPress.
id
user
date (datetime)
date_modified (datetime)
slug
post_status
title
content
excerpt
link
comment_status
ping_status
terms (list of WordPressTerms)
terms_names (dict)
custom_fields (dict)
enclosure (dict)
password
post_format
thumbnail
sticky
post_type
It expects custom_fields to be a dict - you're creating a list and then inserting a dict into that list:
widget.custom_fields = []
widget.custom_fields.append({
'job_location': 'Newyork',
'job_listing_category': 'hotel'
})
This will probably work better:
widget.custom_fields = {
'job_location': 'Newyork',
'job_listing_category': 'hotel'
}

Messenger Send API

I am creating a self built Python chatbot that does not use a chatbot platform such as Dialogflow. The issue is that there is no easy integration with messaging apps such as Messenger to connect it too. I am trying to create a webhook to Messenger using the Messenger Send API. I am looking at the documentation and it shows me how to request a POST api call. However when I look at examples online they all seem to deal with json values called "entry" and "messaging" which I can't find anywhere and can't seem to see why it is necessary. I was wondering how exactly the input body of a Messenger Send API looks like so I can call it appropriately and what json objects are in its body. This is what I have so far from following online examples. I am using Flask. And am using Postman to test this
#app.route("/webhook", methods=['GET','POST'])
def listen():
if request.method == 'GET':
return verify_webhook(request)
if request.method == 'POST':
payload = request.json
event = payload['entry'][0]['messaging']
for x in event:
if is_user_message(x):
text = x['message']['text']
sender_id = x['sender']['id']
respond(sender_id, text)
return "ok"
Below is what I think the body of the request looks like:
{
"object":"page",
"entry":[
{
"id":"1234",
"time":1458692752478,
"messaging":[
{
"message":{
"text":"book me a cab"
},
"sender":{
"id":"1234"
}
}
]
}
]
}
But it is unable to read this and gives me an error of:
File"/Users/raphael******/Documents/*****_Project_Raphael/FacebookWebHookEdition.py", line 42, in listen
event = payload['entry'][0]['messaging']
TypeError: 'NoneType' object is not subscriptable
Where am I going wrong that the webhook is not registering the body correctly as json objects?
Here is how we do it:
# GET: validate facebook token
if request.method == 'GET':
valid = messenger.verify_request(request)
if not valid:
abort(400, 'Invalid Facebook Verify Token')
return valid
# POST: process message
output = request.get_json()
if 'entry' not in output:
return 'OK'
for entry in output['entry']:
if 'messaging' not in entry:
continue
for item in entry['messaging']:
# delivery notification (skip)
if 'delivery' in item:
continue
# get user
user = item['sender'] if 'sender' in item else None
if not user:
continue
else:
user_id = user['id']
# handle event
messenger.handle(user_id, item)
# message processed
return 'OK'
EDIT:
If you are using postman, please make sure to also set Content-Type header to application/json, otherwise Flask can't decode it with request.json. I guess that's where None comes from in your case.

Resources