Python中的OAuth WooCommerce [英] Python OAuth WooCommerce

查看:257
本文介绍了Python中的OAuth WooCommerce的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我试图用一个WooCommerce Python客户端做一个POST请求,但
我得到提供的签名不匹配

I am trying to use a WooCommerce Python client to make a POST request but I get "Provided Signature does not match"

我使用的客户端是:

WooCommerce在Python API 的OAuth

这是我的客户:

#!/usr/bin/env python

import requests
import random
import string
import time
from hashlib import sha1
import hmac
import binascii
import re
import collections
from urllib import quote, urlencode


def uksort(dictionary):
    return collections.OrderedDict(sorted(dictionary.items(), cmp = cmp))

class WooCommerce(object):
    def __init__(self, consumer_key, consumer_secret, endpoint):

        self.consumer_key = consumer_key
        self.consumer_secret = consumer_secret
        self.endpoint = endpoint

    def _make_request(self, resource, params, method = "GET"):
        oauth_params = {
            "oauth_consumer_key": self.consumer_key,
            "oauth_nonce": self._gen_nonce(),
            "oauth_timestamp": self._gen_timestamp(),
            "oauth_signature_method": "HMAC-SHA1",
        }

        oauth_params["oauth_signature"] = self._gen_signature(resource, dict(params.items() + oauth_params.items()), method)
        params = dict(params.items() + oauth_params.items())

        if method == "GET":
            print self.endpoint + resource + "?" + urlencode(params)
        elif method == "POST":
            print self.endpoint + resource + "?" + urlencode(params)
            req = urllib.request.Request(self.endpoint + resource + "?" + urlencode(params))
            open = urllib.request.urlopen(req)
            requestContent = open.read()
            #print(open)

    def _gen_nonce(self):

        ran_string = ''.join(random.choice(string.ascii_uppercase + string.digits) for i in range(32)).encode("base64")
        alnum_hash = re.sub(r'[^a-zA-Z0-9]', "", ran_string)
        return alnum_hash

    def _gen_timestamp(self):

        return int(time.time())

    def _gen_signature(self, resource, params, method):

        base_request_uri = quote(self.endpoint + resource, safe = "")
        normalized_params = self._normalize_params(params)
        sorted_params = uksort(normalized_params)
        query_string = "%26".join([key + "%3D" + value for key, value in sorted_params.iteritems()])

        raw_string = method + "&" + base_request_uri + "&" + query_string
        hashed = hmac.new(self.consumer_secret, raw_string, sha1)

        return binascii.b2a_base64(hashed.digest()).rstrip("\n")

    def _normalize_params(self, params):

        normalized = {}

        for key, value in params.iteritems():
            key = quote(str(key), safe = "")
            value = quote(str(value), safe = "")

            normalized[key] = value

        return normalized

和我这样使用它从另一个类:

And I use it like this from another class:

woo_client = WooCommerce('ck_7bb1951bee7454b2e29bf5eef9205e0e', 'cs_155cd9420201c0a7e140bebd6a9794c7', 'http://dima.bg/wc-api/v2')

data = {
               "product": {
                "title": "testname",
               }
           }    
result = self.woo_client._make_request("/products/", data, 'POST')

你能看到的东西错了我的网址是什么?感谢您的时间。

Can you see something wrong with my URL ? Thanks for your time.

<一个href=\"http://xxxxxxxxx.xx/wc-api/v2/products/?product=%7B%27title%27%3A+%27testname%27%7D&oauth_nonce=NThWODczRFIyWkxRNFZOVkUxNFdRSVo0QjFSNllIVFk&oauth_timestamp=1423647865&oauth_consumer_key=ck_7bb1951bee7454b2e29bf5eef9205e0e&oauth_signature_method=HMAC-SHA1&oauth_signature=3PSnEEf08gFthIRAr8AUKQiDjco%3D\" rel=\"nofollow\">http://xxxxxxxxx.xx/wc-api/v2/products/?product=%7B%27title%27%3A+%27testname%27%7D&oauth_nonce=NThWODczRFIyWkxRNFZOVkUxNFdRSVo0QjFSNllIVFk&oauth_timestamp=1423647865&oauth_consumer_key=ck_7bb1951bee7454b2e29bf5eef9205e0e&oauth_signature_method=HMAC-SHA1&oauth_signature=3PSnEEf08gFthIRAr8AUKQiDjco%3D

推荐答案

我用你的code作为一个起点,我自己解决这个问题,并取得了一些成功!下面是我所做的:

I used your code as a starting point for my own solution to this problem and had some success! Here's what I did:

import requests
import random
import string
import time
from hashlib import sha1
import hmac
import binascii
import re
from urllib import quote, urlencode
import httplib2
from collections import OrderedDict

def key_compare(a, b):
    return cmp(a[0], b[0])

class Restful_Client(object):
    """docstring for Restful_Client"""
    def __init__(self, endpoint, consumer_key, consumer_secret):
        super(Restful_Client, self).__init__()
        self.consumer_key = consumer_key
        self.consumer_secret = consumer_secret
        self.endpoint = endpoint

    def make_request(self, resource, params, method='GET' ):
        oauth_params = {
            'oauth_consumer_key': self.consumer_key,
            'oauth_nonce': self.gen_nonce(),
            'oauth_timestamp': self.gen_timestamp(),
            'oauth_signature_method': 'HMAC-SHA1',
            # 'oauth_version':'1.0'
        }
        oauth_params['oauth_signature'] = self.gen_signature(
            resource,
            OrderedDict( params.items() + oauth_params.items() ),
            method
        )
        params = OrderedDict( params.items() + oauth_params.items() )
        clean_params = self.sort_params(self.normalize_params(params))

        uri = endpoint + resource
        p_string = urlencode(clean_params)

        print 'p string:'
        print '\n'.join(p_string.split('&'))

        return httplib2.Http().request(uri + '?' + p_string)

    def gen_signature(self, resource, params, method):
        base_request_uri = quote(self.endpoint + resource, safe = "")
        clean_params = self.sort_params(
            self.normalize_params(
                self.normalize_params(
                    params
                )
            )
        )
        query_string = '%26'.join([
            key + '%3D' + value\
            for key, value in clean_params.iteritems()
        ])
        raw_string = '&'.join([method, base_request_uri, query_string]) 
        print "raw string: "
        print '\n'.join(raw_string.split('%26'))
        hashed = hmac.new(self.consumer_secret, raw_string, sha1)
        return binascii.b2a_base64( hashed.digest() )[:-1]

    def normalize_string(self, string):
        return quote(str(string), safe="")

    def normalize_params(self, params):
        return OrderedDict( [
            (self.normalize_string(key), self.normalize_string(value))\
            for key, value \
            in params.iteritems()
        ])

    def sort_params(self, params):
        return OrderedDict(sorted(
            params.iteritems(),
            cmp=key_compare
        ))

    def gen_timestamp(self):
        return int(time.time())
        # return 1429451603

    def gen_nonce(self):
        return hex(self.gen_timestamp())
        #todo: make this more secure

if __name__ == "__main__":
    store_url = '<STORE URL HERE>'
    api_base = 'wc-api'
    api_ver = 'v2'
    endpoint = "%s/%s/%s/" % (store_url, api_base, api_ver)

    consumer_key = '<CK HERE>'
    consumer_secret = '<CS HERE>'

    resource = 'customers'
    parameters = {
        # 'fields':'id,first_name'
    }

    rc = Restful_Client(endpoint, consumer_key, consumer_secret)
    r, c = rc.make_request(resource, parameters, 'GET')
    print r
    print c

我的建议是,确保参数都设有codeD的正确的次数,我发现这是双恩codeD所需要的参数来工作。它看起来像在这种情况下,您的参数(key和value字符串)不是双恩codeD作为API文档的 http://woothemes.github.io/woocommerce-rest-api-docs/#authentication

您可以通过尝试不用像在我的code任何参数,一个简单的GET请求验证这一假说。如果工作那么这可能是你的问题。祝你好运!

You can test this hypothesis by trying a simple GET request without any parameters like the one in my code. if that works then that might be your problem. Good luck!

这篇关于Python中的OAuth WooCommerce的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆