0

我正在开发一个 react native 项目,我需要在 woocommerce rest api 的帮助下创建一个应用程序来显示产品和订单。

我正在发出自己的 oauth 请求来获取 json 数据,因为 react native 不支持加密 npm 模块,因此我不能使用 oauth 管理器和 woocommerce-api npm 模块。

我根据 woocommerce 的官方文档对请求所需的所有参数进行了编码。

http://woocommerce.github.io/woocommerce-rest-api-docs/#authentication-over-http

以下代码发出身份验证请求。

import React, { Component } from 'react';
import {
  StyleSheet,
  Text,
  Image,
  TextInput,
  Alert,
  Navigator,
  TouchableHighlight,
  View
} from 'react-native';

var n = require('nonce')();
var percentEncode = require('oauth-percent-encode');
var timestamp = require('timestamp');
var hmacsha1 = require('hmacsha1');
var Hashes = require('jshashes');
var appendQuery =require('append-query');
var consumerSecret = "cs_xxxxxxxxxxxxxxxxxxxxxxx";
var consumerKey ="ck_xxxxxxxxxxxxxxxxxxxxxxx";
var time = timestamp();

var nonce = n().toString();
console.log(nonce);
var httpMethod ="GET";
var storeURL = "http://stephin.xyz.net/wordpress/";
var endPoint = storeURL+"wc-api/v1/orders";
var params = percentEncode('oauth_callback')+"="+percentEncode('homebrew://')+"&"+percentEncode('oauth_consumer_key')+"="+percentEncode(consumerKey)+"&"+percentEncode('oauth_nonce')+"="+percentEncode(nonce)+"&"+percentEncode('oauth_signature_method')+"="+percentEncode('HMAC-SHA1')+"&"+percentEncode('oauth_timestamp')+"="+percentEncode(time);
var baseURL = httpMethod+"&"+percentEncode(endPoint)+"&"+percentEncode(params);

var signature= hmacsha1(baseURL,consumerSecret);

var finalURL = endPoint+'?oauth_consumer_key='+consumerKey+'&oauth_signature='+signature+'&oauth_signature_method=HMAC-SHA1&oauth_callback=honestbrew://&oauth_nonce='+nonce+'&oauth_timestamp='+time;
console.log(signature);
export default class HonestBrewLogin extends Component{
  constructor(){
    super();
    this.state={
      title: "Log In",
      sitelogo:'../../assets/images/hb-logo.png',
      email:"",
      password:""
    }
  }

  _handleAppLogin(){
    if (this.state.email == "") {
      if (this.state.password == "") {
        // this.props.navigator.push({
        //   name: 'HonestBrewMyOrders', // Matches route.name
        // });
        console.log(finalURL);
        fetch(finalURL).then((response) => console.log(response)).catch((error) => {
          console.error(error);
        });
      }
      else {
        console.log("password incorect")
      }
    }
    else {
      console.log("email incorrect");
    }
  }

  _handleRegisterLink(){
    console.log("Link to register screen clicked");
  }

  _handleForgetPassword(){
    console.log("Link to forgot password screen tapped");
  }


  render() {
    return (
      <View style={styles.loginContainer}>
        <View style={styles.headingContainer}>
          <Text style={styles.loginText}>
            {this.state.title}
          </Text>
        </View>
        <View style={styles.loginFormContainer}>
          <View style={styles.loginImageSection}>
            <Image style={styles.loginLogo} source={require("../../assets/images/hb-logo.png")} />
          </View>
          <View style={styles.loginSection}>
            <TextInput
              style={styles.loginEmailTextInput}
              placeholder="Enter Email"
              value={this.state.email}
              onChangeText={(email) => this.setState({email})}
            />
            <TextInput
              style={styles.loginPasswordTextInput}
              placeholder="Enter Password"
              value={this.state.password}
              secureTextEntry={true}
              onChangeText={(password) => this.setState({password})}
            />
          <TouchableHighlight style={styles.loginSubmitButton} underlayColor="#deb887" onPress={this._handleAppLogin.bind(this)}>
              <Text style={styles.loginSubmitButtonText}>Sign in</Text>
            </TouchableHighlight>
            <TouchableHighlight style={styles.loginForgotPasswordLink} underlayColor="#deb887" onPress={this._handleForgetPassword}>
              <Text>Forgot Password?</Text>
            </TouchableHighlight>
          </View>
        </View>
        <TouchableHighlight style={styles.registerLinkContainer} underlayColor="#deb887" onPress={this._handleRegisterLink}>
          <Text>Dont have an account? Register now.</Text>
        </TouchableHighlight>
      </View>
    );
  }
}

const styles = StyleSheet.create({
  headingContainer: {
    flex:0.2,
    height:10,
    marginTop:20,
    alignItems:'center'
  },
  loginText:{
    color: "#000",
    textAlign:"center"
  },
  loginContainer:{
    flex:1
  },
  loginFormContainer:{
    backgroundColor: "#f0efeb",
    alignItems:"center",
    justifyContent:"center",
    flex:8,
  },
  loginSection:{
    flex:2,
    flexDirection:"column",
    alignItems:'center',
    justifyContent:"flex-start"
  },
  registerLinkContainer:{
    flex:0.2,
  },
  loginLogo:{
    height:65,
    width:100,
  },
  loginImageSection:{
    flex:1,
    alignItems:"center",
    justifyContent:"flex-end"
  },
  loginEmailTextInput:{
    height:40,
    width:250,
    marginTop:40,
    padding: 10,
    fontSize:14,
    alignItems:"center",
    backgroundColor:"#fff",
    borderWidth:0.5,
    borderColor: "#D6D3D3"
  },
  loginPasswordTextInput:{
    height:40,
    width:250,
    marginTop:10,
    padding: 10,
    fontSize:14,
    alignItems:"center",
    backgroundColor:"#fff",
    borderWidth:0.5,
    borderColor: "#D6D3D3"
  },
  loginSubmitButton:{
    height:40,
    width:250,
    backgroundColor:"#ff9002",
    marginTop:20,
    justifyContent:"center",
    alignItems:"center"
  },
  loginSubmitButtonText:{
    color:"#fff"
  },
  registerLinkContainer:{
    alignItems:"center",
    height:40,
    justifyContent:"center"
  },
  loginForgotPasswordLink:{
    marginTop:20
  }
});

每次我提出请求时,都会收到以下错误。

{
"errors": [
{
"code": "woocommerce_api_authentication_error",
"message": "Invalid Signature - provided signature does not match"
}
]
}

无论我做什么,最终结果总是这个错误。

4

3 回答 3

0

我已经制作了身份验证文件和 woocommerce api 文件及其工作。

Woocommerce API 文件

'use strict';

import OAuth from "oauth-1.0a";

module.exports = WooCommerceAPI;

/**
 * WooCommerce REST API wrapper
 *
 * @param {Object} opt
 */
function WooCommerceAPI(opt) {
	if (!(this instanceof WooCommerceAPI)) {
		return new WooCommerceAPI(opt);
	}

	opt = opt || {};

	if (!(opt.url)) {
		throw new Error('url is required');
	}

	if (!(opt.consumerKey)) {
		throw new Error('consumerKey is required');
	}

	if (!(opt.consumerSecret)) {
		throw new Error('consumerSecret is required');
	}

	this.classVersion = '1.0.0';
	this._setDefaultsOptions(opt);
}

/**
 * Set default options
 *
 * @param {Object} opt
 */
WooCommerceAPI.prototype._setDefaultsOptions = function (opt) {
	this.url = opt.url;
	this.wpAPI = opt.wpAPI || false;
	this.wpAPIPrefix = opt.wpAPIPrefix || 'wp-json';
	this.version = opt.version || 'v3';
	this.isSsl = /^https/i.test(this.url);
	this.consumerKey = opt.consumerKey;
	this.consumerSecret = opt.consumerSecret;
	this.verifySsl = false === opt.verifySsl ? false : true;
	this.encoding = opt.encoding || 'utf8';
	this.queryStringAuth = opt.queryStringAuth || false;
	this.port = opt.port || '';
	this.timeout = opt.timeout;
};

/**
 * Normalize query string for oAuth
 *
 * @param  {string} url
 * @return {string}
 */
WooCommerceAPI.prototype._normalizeQueryString = function (url) {
	// Exit if don't find query string
	if (-1 === url.indexOf('?')) {
		return url;
	}

	// var query       = _url.parse(url, true).query;
	var query = url;
	var params = [];
	var queryString = '';

	for (var p in query) {
		params.push(p);
	}
	params.sort();

	for (var i in params) {
		if (queryString.length) {
			queryString += '&';
		}

		queryString += encodeURIComponent(params[i]).replace('%5B', '[').replace('%5D', ']');
		queryString += '=';
		queryString += encodeURIComponent(query[params[i]]);
	}

	return url.split('?')[0] + '?' + queryString;
};

/**
 * Get URL
 *
 * @param  {String} endpoint
 *
 * @return {String}
 */
WooCommerceAPI.prototype._getUrl = function (endpoint) {
	var url = '/' === this.url.slice(-1) ? this.url : this.url + '/';
	var api = this.wpAPI ? this.wpAPIPrefix + '/' : 'wp-json/';

	url = url + api + this.version + '/' + endpoint;

	// Include port.
	if ('' !== this.port) {
		var hostname = url; //_url.parse(url, true).hostname;
		url = url.replace(hostname, hostname + ':' + this.port);
	}

	if (!this.isSsl) {
		return this._normalizeQueryString(url);
	}

	return url;
	console.log("Normalize URl:- "+url);
};

/**
 * Get OAuth
 *
 * @return {Object}
 */
WooCommerceAPI.prototype._getOAuth = function () {
	var data = {
		consumer: {
			public: this.consumerKey,
			secret: this.consumerSecret
		},
		signature_method: 'HMAC-SHA256'
	};
	if (-1 < ['v1', 'v2'].indexOf(this.version)) {
		data.last_ampersand = false;
	}
	return new OAuth(data);
	console.log("My _Data:- "+data);
};

/**
 * Join key object value to string by separator
 */
WooCommerceAPI.prototype.join = function (obj, separator) {
	var arr = [];
	for (var key in obj) {
		if (obj.hasOwnProperty(key)) {
			arr.push(key + '=' + obj[key]);
		}
	}
	;
	return arr.join(separator);
}

/**
 * Do requests
 *
 * @param  {String}   method
 * @param  {String}   endpoint
 * @param  {Object}   data
 * @param  {Function} callback
 *
 * @return {Object}
 */
WooCommerceAPI.prototype._request = function (method, endpoint, data, callback) {
	var url = this._getUrl(endpoint);

	var params = {
		url: url,
		method: method,
		encoding: this.encoding,
		timeout: this.timeout,
		headers: {
			'User-Agent': 'WooCommerce API React Native/' + this.classVersion,
			'Content-Type': 'application/json',
			'Accept': 'application/json'
		}
	};

	if (this.isSsl) {
		if (this.queryStringAuth) {
			params.qs = {
				consumer_key: this.consumerKey,
				consumer_secret: this.consumerSecret
			};
		} else {
			params.auth = {
				user: this.consumerKey,
				pass: this.consumerSecret
			};
		}

		if (!this.verifySsl) {
			params.strictSSL = false;
		}
	}
	else {

		params.qs = this._getOAuth().authorize({
			url: url,
			method: method,
			data: data
		});
	}

	// encode the oauth_signature to make sure it not remove + charactor
	params.qs.oauth_signature = encodeURIComponent(params.qs.oauth_signature);
	var requestUrl = params.url + '?' + this.join(params.qs, '&');

	// extra data info for paging
	if (data) {
		requestUrl += '&' + this.join(data, '&');
	}

	// console.log('encode', params.qs.oauth_signature);
	console.log("Request URl:- "+requestUrl);

	return fetch(requestUrl,
		{
			headers: {
				'Cache-Control': 'no-cache'
			}
		})
		.then((response) => {
			console.log(response);
			return response.json()
		})
		.then((responseData) => {
			if (typeof callback == 'function') {
				callback();
			}
			return responseData
		})
		.catch((error, data) => {
				console.log('error network -', error, data);
			}
		);
};

/**
 * GET requests
 *
 * @param  {String}   endpoint
 * @param  {Function} callback
 *
 * @return {Object}
 */
WooCommerceAPI.prototype.get = function (endpoint, data, callback) {
	return this._request('GET', endpoint, data, callback);
};

/**
 * POST requests
 *
 * @param  {String}   endpoint
 * @param  {Object}   data
 * @param  {Function} callback
 *
 * @return {Object}
 */
WooCommerceAPI.prototype.post = function (endpoint, data, callback) {
	return this._request('POST', endpoint, data, callback);
};

/**
 * PUT requests
 *
 * @param  {String}   endpoint
 * @param  {Object}   data
 * @param  {Function} callback
 *
 * @return {Object}
 */
WooCommerceAPI.prototype.put = function (endpoint, data, callback) {
	return this._request('PUT', endpoint, data, callback);
};

/**
 * DELETE requests
 *
 * @param  {String}   endpoint
 * @param  {Function} callback
 *
 * @return {Object}
 */
WooCommerceAPI.prototype.delete = function (endpoint, callback) {
	return this._request('DELETE', endpoint, null, callback);
};

/**
 * OPTIONS requests
 *
 * @param  {String}   endpoint
 * @param  {Function} callback
 *
 * @return {Object}
 */
WooCommerceAPI.prototype.options = function (endpoint, callback) {
	return this._request('OPTIONS', endpoint, null, callback);
};

API 文件

import WooCommerceAPI from "./WooCommerceAPI";
import Constants from './Config';
var Api = new WooCommerceAPI({
    url: Constants.URL.root,
    consumerKey: Constants.Keys.ConsumeKey,
    consumerSecret: Constants.Keys.ConsumerSecret,
    wp_api: true,
    version: 'wc/v2',
    queryStringAuth: true
});

export default Api;

配置文件

'use strict';

const Constants = {
    URL: {
        root: 'https://www.yoururl.com/wordpress'
    },
    Keys: {
	    ConsumeKey: '',
	    ConsumerSecret: ''
    },

}

module.exports = Constants;

使用此代码创建 oauth url,然后您的代码将起作用。

于 2018-03-27T14:05:06.787 回答
0

您的网站 URL 可能有问题。打开您的 WordPress > 以管理员身份登录 > 设置 > 常规 > 寻找 WordPress 地址 (URL)。

您的请求 URL 应如下所示:WordPress 地址 (URL) + "/wp-json/wc/v1/" + funtion_name + "/" 添加条件 + "?" + 授权码

例子:

http://www.foo.boo/wordpress/wp-json/wc/v1/orders/45?oauth_consumer_key=ck_00000&oauth_signature_method=HMAC-SHA1&oauth_timestamp=0000000&oauth_nonce=000000&oauth_version=1.0&oauth_signature=000000=&oauth_token
于 2016-10-05T04:48:27.557 回答
0

'use strict';

const Constants = {
    URL: {
        root: 'https://www.yoururl.com/wordpress'
    },
    Keys: {
	    ConsumeKey: '',
	    ConsumerSecret: ''
    },

}

module.exports = Constants;

于 2019-01-15T08:15:36.937 回答