Python Stripe SDK Authentication error (key contains at least one space) - python

I'm trying to duplicate some subscription Plans in my Stripe account using the Python SDK, so that I can update the plan prices (plans are immutable). I can successfully list all plans, so authentication is not an issue.:
import stripe
stripe.api_key = 'sk_test_...'
start_id = None
while True:
if start_id:
resp = stripe.Plan.list(starting_after=start_id)
else:
resp = stripe.Plan.list()
plans = resp['data']
if len(plans) == 0: break
start_id = plans[-1]['id']
for plan in plans:
new_amount = get_new_plan_amount(plan['id'], plan['name'])
new_plan = {
"id": "%s-v2" % plan["id"],
"name": "%s V2" % plan["name"],
"amount": new_amount,
"interval": plan["interval"],
"currency": plan["currency"],
}
if plan['interval_count']:
new_plan["interval_count"] = plan['interval_count']
if plan['metadata']:
new_plan["metadata"] = plan['metadata']
if plan['statement_descriptor']:
new_plan["statement_descriptor"] = plan['statement_descriptor']
stripe.Plan.create(new_plan) ### error
When I try to update a plan I get the following error:
Stripe.error.AuthenticationError: Invalid API Key provided: "{'****': *'*********** ', '********': *'*****', '********_*****': *, '********': '', '******': *****, '**': *'*******-v2'}". This key contains at least one space. Please delete the spaces and try again.
I don't get it. Which field is it that contains a space? I've checked the id field (which it seems to be suggesting) but there are no spaces in that field.
I'm using Python 2.7 and version 2013-08-13 of the Stripe API.

You need to unpack the dictionary containing your parameters when creating the plan:
stripe.Plan.create(**new_plan)
Additionally, you don't need to manage pagination parameters yourself. The Python library can do it for you using auto-pagination:
plans = stripe.Plan.list()
for plan in plans.auto_paging_iter():
# do something with plan

Related

For loop not iterating in Mailchimp

So, I'm trying to get every sent to list from the Mailchimp API. I've made this code to elaborate a list of it to later generate a join and get both the list and the campaign name and not the campaign id only:
try:
client = MailchimpMarketing.Client()
client.set_config({
"api_key": "xxxx",
"server": "xxx"
})
response_id = client.campaigns.list(count=1000)
df_full = pd.json_normalize(response_id['campaigns'])
df_id = df_full['id']
df_id = df_id.values.tolist()
df_id_camp_name = df_full[['id','settings.subject_line']]
#display(df_id)
except ApiClientError as error:
print("Error: {}".format(error.text))
This part of the script gets the ID for each campaign and each campaign name.
for id in df_id:
try:
client = MailchimpMarketing.Client()
client.set_config({
"api_key": "xxxxx",
"server": "xxxx"
})
response_open = client.reports.get_campaign_recipients(id, count=1000)
df_open = pd.json_normalize(response_open['sent_to'])
df_open_full = df_open.append(df_open)
except ApiClientError as error:
print("Error: {}".format(error.text))
df_open_full.to_excel("campaign_reports_mailchimp.xlsx")
And this last piece, takes the ID from the generated list and allegedly runs the code for each ID. Problem is that the generated excel only brings one campaign and doesn't iterates for the rest of the IDs.
I know that the API has a limit count but it should move to the next ID once the cap reaches since it restarts the for loop itself.
What could be wrong in this case?
Thanks!
Adding some details about the print itself of each piece of code:
First block:
['076ff218d1', '08f16d1014', '0abfd11f5d', '0bb98a7839', '0bca92ee08', '0be206c6ac', '0e048c0d08', '0e28d0feee', '138271cade', '14bf2cd33b', '15c9ce24ed', '17b5302f30', '19721c1e8a', '1d8cc5c1da', '1f5362e2f4', '205480a063', '225bc2469b', '22f286dfbe', '26dec9723b', '2846539c87', '296e9c24f5', '2aa089aa37', '2f819130ff', '352d7913ae', '3a563ffb24', '3a73d3e5b6', '3c83f64170', '3d87a76763', '3e6a903948', '404ab63b91', '4198b629c6', '424b941199', '42e948e744', '46a29946a3', '48e56d7481', '4a0a55eb73', '4caf7e8cc1', '4e3c90946f', '53c8e8a8de', '54600382dd', '55a8915fb8', '5a28843185', '5d575f0de8', '60488c9e4b', '612b068a5b', '6161c05556', '61f5edcefa', '623c98757a', '689ae72a35', '68a8b5dadd', '6b3797ea1a', '6b606e78fb', '6dd276171d', '6ead2584c8', '6f99e38311', '70632fe9e7', '709b6fd5f8', '72a1b314b4', '74b92a828e', '75bdf2a3fe', '75cce79a85', '7687c62b55', '79e63229a8', '79f67ec7b8', '7f9dddc6c0', '807a75418e', '8548a5f525', '8602aa9cdd', '87c4bd5a07', '8bb822eeb3', '8ec05b63fa', '8f0c7d0cce', '900018816a', '924976c731', '933a2af282', '95a170d72c', '977beb5616', '98f8ee7fed', '99dbbc746c', '9a01a1b518', 'a1ad97ae8e', 'a4aa98b22b', 'a7c535a5b9', 'a978bab42b', 'ab13c82454', 'ab7c015390', 'acdc57b754', 'ad66024938', 'ae8464e351', 'ae95f63873', 'aeba2b962a', 'af0d9fe032', 'af6a4efe07', 'b19c553cd1', 'b5f4196035', 'b7a9ced6c8', 'b7eab10f0f', 'b80b52c97b', 'bd56fd7a6d', 'bdbb60aec7', 'c142343cfd', 'c2eb923ada', 'c407b9856d', 'c4636be5a1', 'c6145916ae', 'c84e39f8ef', 'c937f5876e', 'c97497c3e4', 'ca468b0942', 'cf2a040b92', 'cf81c2ac84', 'd006696585', 'd1b57067d2', 'd67915da02', 'd687b97dec', 'd698158ac5', 'd78cb47ccd', 'da0e85a878', 'dfc6a9bffc', 'dfe8e851e8', 'e08ce9ad82', 'e33f24fdcb', 'e4c478afb4', 'e8e3faaf5a', 'ebee2d5079', 'ecafe77954', 'ef1dae3863', 'f045de38f4', 'fa07a15c0e', 'fa3936c575', 'fa4def8ca1', 'fc1f708dc7', 'fe4f89c745']
Second block of code:
Extract of code display(df)
Also adding an error displayed in the loop because I'm using pd.append instead of pd.concatenate (since I don't have any other df to concatenate with)
FutureWarning: The frame.append method is deprecated and will be
removed from pandas in a future version. Use pandas.concat instead.

1064 SQL You have an error in your SQL syntax; Python List to String Convert?

I'm still new to coding and sql, and I am working on a library management database system as a project.
And I keep getting a 1064 when trying to store my information in my database.
I'm pretty sure it's trying to tell me that the authors are Lists, and need to be a string, but I'm not sure how to do that, and if I can without query entries!
below is the def in question!
def googleAPI(self):
lineTitle = str(titleInfo.text())
# create getting started variables
api = "https://www.googleapis.com/books/v1/volumes?q=isbn:"
isbn = lineTitle.strip()#input("Enter 10 digit ISBN: ").strip()
# send a request and get a JSON response
resp = urlopen(api + isbn)
# parse JSON into Python as a dictionary
book_data = json.load(resp)
# create additional variables for easy querying
volume_info = book_data["items"][0]["volumeInfo"]
author = volume_info["authors"]
# practice with conditional expressions!
prettify_author = author if len(author) > 1 else author[0]
# display title, author, page count, publication date
# fstrings require Python 3.6 or higher
# \n adds a new line for easier reading
gTitle = str(volume_info['title'])
pCount = str(volume_info['pageCount'])
pubDate = str(volume_info['publishedDate'])
author = str(volume_info["authors"])
prettify_author = author if len(author) > 1 else author[0]
stringAuthor = str(prettify_author)
insertBooksF = "insert into "+bookTable+" values('"+isbn+"','"+gTitle+"','"+stringAuthor+"','"+pubDate+"','"+pCount+"')"
try:
cur.execute(insertBooksF)
con.commit()
print("You failed at failing")
except:
print("You actually failed")
print(f"\nTitle: {volume_info['title']}")
print(f"Author: {prettify_author}")
print(f"Page Count: {volume_info['pageCount']}")
print(f"Publication Date: {volume_info['publishedDate']}")
print("\n***\n")
I believe this line is the one needed adjusting
insertBooksF = "insert into "+bookTable+" values('"+isbn+"','"+gTitle+"','"+stringAuthor+"','"+pubDate+"','"+pCount+"')"
You should ALWAYS let the database connector substitute your field values. Otherwise, you open yourself up to SQL injection, where a malicious user provides a field value like "; delete * from table;
stringAuthor = author if isinstance(author,str) else author[0]
insertBooksF = "insert into "+bookTable+" values(?,?,?,?,?)"
cur.execute(insertBooksF, (isbn, gTitle, stringAuthor, pubDate, pCount))

I have a problem in Trading with Kucoin API (Python)

I tried to do API trading in Kucoin. I developed a bot that is finding the trading opportunities well, while I encountered problems in making new orders. Pls check the code and help me to make it functional.
The code was edited in accordance with the comment of Lev Levitsky
is as follows:
import json
import urllib
import requests
import base64
import hmac
import hashlib
api_key = 'api_key'
api_secret = 'api_secret'
api_passphrase = 'api_passphrase'
base_uri = 'https://api-futures.kucoin.com'
endpoint = '/api/v1/orders?symbol=MATICUSDTM'
method = 'POST'
x= {}
x["symbol"] = "MATICUSDTM"
x["signal_type"] = "SHORT"
x["leverage"] = 5
x["exchange"] = "Kucoin"
x["entrance_price"] = 2.1000
x["trading_size"] = 150
x["tp1"] = 2.08
x["sl1"] = 2.12
all_futures_signals = list()
all_futures_signals.append(x)
def get_headers(method, endpoint, api_key, api_passphrase,body):
api_secret = ''
now = int(time.time() * 1000)
str_to_sign = str(now) + method + endpoint + str(body)
signature = base64.b64encode(hmac.new(api_secret.encode('utf-8'), str_to_sign.encode('utf-8'), hashlib.sha256).digest())
passphrase = base64.b64encode(hmac.new(api_secret.encode('utf-8'), api_passphrase.encode('utf-8'), hashlib.sha256).digest())
return {'KC-API-KEY': api_key,
'KC-API-KEY-VERSION': '2',
'KC-API-PASSPHRASE': passphrase,
'KC-API-SIGN': signature,
'KC-API-TIMESTAMP': str(now)}
body = {
"clientOid" : "",
"reduceOnly" : False, # A mark to reduce the position size only
"closeOrder" : False, # If closeOrder is set to TRUE, the system will close the position and the position size will become 0. Side, Size and Leverage fields can be left empty and the system will determine the side and size automatically.
"forceHold" : False, # The system will forcely freeze certain amount of funds for this order, including orders whose direction is opposite to the current positions. This feature is to ensure that the order won’t be canceled by the matching engine in such a circumstance that not enough funds are frozen for the order.
"hidden" : False, # A hidden order will enter but not display on the orderbook.
"iceberg" : False, # When placing an iceberg order, you need to set the visible size. The minimum visible size is 1/20 of the order size. The minimum visible size shall be greater than the minimum order size, or an error will occur.
"visibleSize" : 0, # When placing an iceberg order, you need to set the visible size. The minimum visible size is 1/20 of the order size. The minimum visible size shall be greater than the minimum order size, or an error will occur.
"leverage" : x["leverage"],
"postOnly" : False, # The post-only flag ensures that the trader always pays the maker fee and provides liquidity to the order book.
"price" : 2.1000, # The price specified must be a multiple number of the contract tickSize,
"remark" : "remark",
"side" : "buy",# sell/buy
"size" : x["trading_size"], # The size must be no less than the lotSize for the contract and no larger than the maxOrderQty.
"stop" : "", # down/up
"stopPrice" : "",
"stopPriceType": "", # TP/MP/IP: TP for trade price, MP for mark price, and IP for index price
"symbol" : x["symbol"],
"timeInForce" : "", # GTC/IOC: Good Till Canceled GTC and Immediate Or Cancel IOC.
"type" : "limit", # limit/market
}
headers = get_headers(method, endpoint, api_key, api_passphrase, body)
x["opening_response"] = requests.post( base_uri + endpoint, body, headers=headers).json()
print(x["opening_response"])
I receive this error: {'code': '400005', 'msg': 'Invalid KC-API-SIGN'}
All inputs are correct. I think there is a problem with the code.
Best Regards
Javad
I think the problem is your endpoint variable. I believe you should not add the symbol to endpoint, when you are trying to add a new order. Remove it from endpoint and pass the symbol in body object. The other thing is that I think you do not need to pass empty strings to optional fields in body object. I am not sure about this but I think you should remove them from body object. It is a signing problem, therefore you have to check 4 variables: timestamp, method, endpoint and body. I hope this works.
have you considered using ccxt? It makes dealing with lower level API stuff like this somewhat easier.
Given that it's singling out the signature as being invalid, but not saying any headers are missing, it could mean that the signature for str_to_sign variable is wrong?
Let's look at it:
api_secret = ''
now = int(time.time() * 1000)
str_to_sign = str(now) + method + endpoint + str(body)
From the looks of it, your api_secret is just an empty string, so the resulting signature won't be correct.
so, a couple of lines down when you make the signature:
signature = base64.b64encode(hmac.new(api_secret.encode('utf-8'), str_to_sign.encode('utf-8'), hashlib.sha256).digest())
Even though api_secret is given a value in the higher scope, it's overridden by this local variable which is an empty string.
If your api_secret were actually an empty string, then your code would produce the correct signature, but it's not so it isn't
So, If you give it as a param to your get_headers function ie.
def get_headers(method, endpoint, api_key, api_passphrase, api_secret, body):
And delete the first line api_secret = ''
Then maybe it will work?
If it doesn't work, then it's a different problem. (eg. if you had actually put your API key in there and just redacted it before posting). I don't know since I haven't tried running your code.
PS: To Edelweiss: Grüzi aus Berner Oberland!
According to a comment of edelweiss, an easier way is using the client of Kucoin API. It is here.
First, I installed the client using this code.
!pip install kucoin-futures-python
Then, I opened a position by this code:
from kucoin_futures.client import Trade
client = Trade(key='api_key', secret='api_secret', passphrase='api_passphrase', is_sandbox=False, url='')
order_id = client.create_limit_order(symbol, side, lever, size, price, clientOid='', **kwargs)

How can I add item cost to a product variant using ShopifyAPI?

I'm trying to programmatically add a couple dozens products to my Shopify shop using the official ShopifyAPI Python SDK, but I can't figure out how to specify the cost of each variant.
This is what I've tried so far:
variant = shopify.Variant()
variant.price = price
variant.option1 = size
variant.inventory_quantity = qty
variant.inventory_management = "shopify"
variant.fullfilment_service = "manual"
variant.requires_shipping = True
variant.sku = sku
variant.taxable = False
variant.inventory_policy = 'deny'
variant.cost = cost
new_product.variants.append(variant)
Naturally, variant.cost doesn't work. How should I do this? Or is it not yet supported?
I'm using ShopifyAPI version 5.1.0, and the API version is 2019-07.
You cann't update unit cost with variant update api call, you need to call inventoryItem api to update unit cost.
**Update a unit cost**
PUT /admin/api/#{api_version}/inventory_items/#{inventory_item_id}.json
{
"inventory_item": {
"id": 808950810,
"cost": "25.00"
}
}
please refer this link https://help.shopify.com/en/api/reference/inventory/inventoryitem#update-2019-07

Cosmos DB - Delete Document with Python

In this SO question I had learnt that I cannot delete a Cosmos DB document using SQL.
Using Python, I believe I need the DeleteDocument() method. This is how I'm getting the document ID's that are required (I believe) to then call the DeleteDocument() method.
# set up the client
client = document_client.DocumentClient()
# use a SQL based query to get a bunch of documents
query = { 'query': 'SELECT * FROM server s' }
result_iterable = client.QueryDocuments('dbs/DB/colls/coll', query, options)
results = list(result_iterable);
for x in range(0, len (results)):
docID = results[x]['id']
Now, at this stage I want to call DeleteDocument().
The inputs into which are document_link and options.
I can define document_link as something like
document_link = 'dbs/DB/colls/coll/docs/'+docID
And successfully call ReadAttachments() for example, which has the same inputs as DeleteDocument().
When I do however, I get an error...
The partition key supplied in x-ms-partitionkey header has fewer
components than defined in the the collection
...and now I'm totally lost
UPDATE
Following on from Jay's help, I believe I'm missing the partitonKey element in the options.
In this example, I've created a testing database, it looks like this
So I think my partition key is /testPART
When I include the partitionKey in the options however, no results are returned, (and so print len(results) outputs 0).
Removing partitionKey means that results are returned, but the delete attempt fails as before.
# Query them in SQL
query = { 'query': 'SELECT * FROM c' }
options = {}
options['enableCrossPartitionQuery'] = True
options['maxItemCount'] = 2
options['partitionKey'] = '/testPART'
result_iterable = client.QueryDocuments('dbs/testDB/colls/testCOLL', query, options)
results = list(result_iterable)
# should be > 0
print len(results)
for x in range(0, len (results)):
docID = results[x]['id']
print docID
client.DeleteDocument('dbs/testDB/colls/testCOLL/docs/'+docID, options=options)
print 'deleted', docID
According to your description, I tried to use pydocument module to delete document in my azure document db and it works for me.
Here is my code:
import pydocumentdb;
import pydocumentdb.document_client as document_client
config = {
'ENDPOINT': 'Your url',
'MASTERKEY': 'Your master key',
'DOCUMENTDB_DATABASE': 'familydb',
'DOCUMENTDB_COLLECTION': 'familycoll'
};
# Initialize the Python DocumentDB client
client = document_client.DocumentClient(config['ENDPOINT'], {'masterKey': config['MASTERKEY']})
# use a SQL based query to get a bunch of documents
query = { 'query': 'SELECT * FROM server s' }
options = {}
options['enableCrossPartitionQuery'] = True
options['maxItemCount'] = 2
result_iterable = client.QueryDocuments('dbs/familydb/colls/familycoll', query, options)
results = list(result_iterable);
print(results)
client.DeleteDocument('dbs/familydb/colls/familycoll/docs/id1',options)
print 'delete success'
Console Result:
[{u'_self': u'dbs/hitPAA==/colls/hitPAL3OLgA=/docs/hitPAL3OLgABAAAAAAAAAA==/', u'myJsonArray': [{u'subId': u'sub1', u'val': u'value1'}, {u'subId': u'sub2', u'val': u'value2'}], u'_ts': 1507687788, u'_rid': u'hitPAL3OLgABAAAAAAAAAA==', u'_attachments': u'attachments/', u'_etag': u'"00002100-0000-0000-0000-59dd7d6c0000"', u'id': u'id1'}, {u'_self': u'dbs/hitPAA==/colls/hitPAL3OLgA=/docs/hitPAL3OLgACAAAAAAAAAA==/', u'myJsonArray': [{u'subId': u'sub3', u'val': u'value3'}, {u'subId': u'sub4', u'val': u'value4'}], u'_ts': 1507687809, u'_rid': u'hitPAL3OLgACAAAAAAAAAA==', u'_attachments': u'attachments/', u'_etag': u'"00002200-0000-0000-0000-59dd7d810000"', u'id': u'id2'}]
delete success
Please notice that you need to set the enableCrossPartitionQuery property to True in options if your documents are cross-partitioned.
Must be set to true for any query that requires to be executed across
more than one partition. This is an explicit flag to enable you to
make conscious performance tradeoffs during development time.
You could find above description from here.
Update Answer:
I think you misunderstand the meaning of partitionkey property in the options[].
For example , my container is created like this:
My documents as below :
{
"id": "1",
"name": "jay"
}
{
"id": "2",
"name": "jay2"
}
My partitionkey is 'name', so here I have two paritions : 'jay' and 'jay1'.
So, here you should set the partitionkey property to 'jay' or 'jay2',not 'name'.
Please modify your code as below:
options = {}
options['enableCrossPartitionQuery'] = True
options['maxItemCount'] = 2
options['partitionKey'] = 'jay' (please change here in your code)
result_iterable = client.QueryDocuments('dbs/db/colls/testcoll', query, options)
results = list(result_iterable);
print(results)
Hope it helps you.
Using the azure.cosmos library:
install and import azure cosmos package:
from azure.cosmos import exceptions, CosmosClient, PartitionKey
define delete items function - in this case using the partition key in query:
def deleteItems(deviceid):
client = CosmosClient(config.cosmos.endpoint, config.cosmos.primarykey)
# Create a database if not exists
database = client.create_database_if_not_exists(id=azure-cosmos-db-name)
# Create a container
# Using a good partition key improves the performance of database operations.
container = database.create_container_if_not_exists(id=container-name, partition_key=PartitionKey(path='/your-pattition-path'), offer_throughput=400)
#fetch items
query = f"SELECT * FROM c WHERE c.device.deviceid IN ('{deviceid}')"
items = list(container.query_items(query=query, enable_cross_partition_query=False))
for item in items:
container.delete_item(item, 'partition-key')
usage:
deviceid=10
deleteItems(items)
github full example here: https://github.com/eladtpro/python-iothub-cosmos

Categories

Resources