在Python中访问Gravity Forms API的正确方法是什么?

时间:2019-07-22 19:55:53

标签: python authentication python-requests gravityforms

我正在尝试使用Python通过其REST API v2访问Gravity Forms条目数据,但无法弄清楚如何正确进行身份验证。我应该使用基本身份验证还是OAuth1?我也从未成功使用过,因此示例代码将非常有用。

我尝试了基本身份验证,这似乎是requests模块的默认身份验证。

import requests

url = 'https://<INSERT DOMAIN HERE>/wp-json/gf/v2/entries'
auth = (<CONSUMER KEY>, <CONSUMER SECRET>)
r = requests.get(url, auth=auth)
print(r.status_code)

当基本身份验证不起作用时,我还使用requests_oathlibthis post作为准则尝试了OAuth1,但我也无法使它起作用。我不确定什么是不同的密钥/令牌/秘密或如何获得它们。我有WordPress信息中心的Gravity Forms REST API部分中的“用户密钥”和“用户机密”,仅此而已。

import requests
from requests_oauthlib import OAuth1

url = 'https://<INSERT DOMAIN HERE>/wp-json/gf/v2/entries'
auth = OAuth1('YOUR_APP_KEY', 'YOUR_APP_SECRET', 'USER_OAUTH_TOKEN', 'USER_OAUTH_TOKEN_SECRET')
r = requests.get(url, auth=auth)
print(r.status_code)

我也尝试按照requests_oauthlib here的文档进行操作,但是我不确定要在哪个URL中使用哪个URL或采用哪个路径(会话与帮助程序)。

Gravity Forms REST API documentation说,只要使用HTTPS发送请求,基本身份验证就可以接受,而HTTP请求必须使用OAuth1.0a。我都不能上班。但是,我知道我已经接近了,因为我可以使用带有OAuth1和HMAC-SHA1“签名方法”的“消费者密钥”和“消费者秘密”来使Postman应用程序正常工作。

我期望200个响应状态代码,但是无论我使用哪种身份验证,我都会不断收到401个响应状态代码。

1 个答案:

答案 0 :(得分:0)

我不确定对此有何细微差别,但经过大量研究和反复试验后,我才开始对此进行研究。请随时添加建议。

import requests
import time
import random
import string
import oauthlib.oauth1.rfc5849.signature as oauth
from urllib.parse import quote_plus
import os
import json
import datetime


def create_nonce(N = 32): # randomly generated 32 character (recommended) string
    result = ''.join(random.choices(string.ascii_letters + string.digits, k = N))
    return result


def create_signature(httpMethod, url, urlSuffix, nonce, timestamp, consumerKey, signatureMethod, version):
    consumerSecret = <INSERT_YOUR_CONSUMER_SECRET_HERE>
    # https://stackoverflow.com/a/39494701/5548564
    # In case of http://example.org/api?a=1&b=2 - the uri_query value would be "a=1&b=2".
    uri_query = urlSuffix
    # The oauthlib function 'collect_parameters' automatically ignores irrelevant header items like 'Content-Type' or
    # 'oauth_signature' in the 'Authorization' section.
    headers = {
        "Authorization": (
            f'OAuth realm="", '
            f'oauth_nonce={nonce}, '
            f'oauth_timestamp={timestamp}, '
            f'oauth_consumer_key={consumerKey}, '
            f'oauth_signature_method={signatureMethod}, '
            f'oauth_version={version}')}
    # There's no POST data here - in case it was: x=1 and y=2, then the value would be '[("x","1"),("y","2")]'.
    data = []
    params = oauth.collect_parameters(uri_query=uri_query,
                                      body=data,
                                      headers=headers,
                                      exclude_oauth_signature=True,
                                      with_realm=False)
    norm_params = oauth.normalize_parameters(params)
    base_string = oauth.construct_base_string(httpMethod, url, norm_params)
    signature = oauth.sign_hmac_sha1(base_string, consumerSecret, '')
    return quote_plus(signature)


def send_request():
    url = <INSERT_URL_HERE>
    urlSuffix = "_labels=1"  # Addes array at end of json results including a map to the field labels
    httpMethod = "GET"
    consumerKey = <INSERT_CONSUMER_KEY_HERE>
    signatureMethod = "HMAC-SHA1"
    timestamp = str(int(time.time()))
    nonce = create_nonce()
    version = "1.0"
    signature = create_signature(httpMethod, url, urlSuffix, nonce, timestamp, consumerKey, signatureMethod, version)
    queryString = {"oauth_consumer_key": consumerKey,
                   "oauth_signature_method": signatureMethod,
                   "oauth_timestamp": timestamp,
                   "oauth_nonce": nonce,
                   "oauth_version": version,
                   "oauth_signature": signature}
    headers = {'User-Agent': "Testing/0.1",
               'Accept': "*/*",
               'Host': "<INSERT_YOUR_DOMAIN_HERE>",
               'Accept-Encoding': "gzip, deflate",
               'Connection': "keep-alive"}
    if urlSuffix:
        url = url + "?" + urlSuffix
    r = requests.request(httpMethod, url, headers=headers, params=queryString)
    if r.status_code == 200:
        dict = json.loads(r.text)
        return dict
    else:
        print(r.status_code)
        return None


response = send_request()