使用 Google Apps 脚本更新 NetSuite

问题描述 投票:0回答:1

尝试将适用于 Google Apps 脚本的 Python 脚本转换为更易于分发的脚本。似乎按其应有的方式运行并生成签名,但是通过使用来自 Python 脚本的相同随机数和时间戳,我可以看到 Google Apps 脚本创建了不同的签名,但我无法理解为什么。 我知道它会失败,我只是想在继续之前匹配签名!

有关 Google Apps 脚本使用 TBA 连接到 NetSuite 的任何方法的任何想法 - 我重复一遍,这需要使用 TBA 而不是 OAuth2 等。感谢任何帮助或指导。

 function main() {
  var REALM = 'XXXXX';
  var CONSUMER_KEY = 'XXXXXXx';
  var CONSUMER_SECRET = 'XXXXXXXX';
  var RESOURCE_OWNER_KEY = 'XXXXXXXXX';
  var RESOURCE_OWNER_SECRET = 'XXXXXXXX';
  
  var method = "PATCH";
  var url = 'https://' + REALM + '.suitetalk.api.netsuite.com/services/rest/record/v1/vendor/1846';
  
  var params = {
    'oauth_consumer_key': CONSUMER_KEY,
    'oauth_nonce': '38751934124598253091697458273',
    'oauth_signature_method': 'HMAC-SHA256',
    'oauth_timestamp': '1697458273',
    'oauth_token': RESOURCE_OWNER_KEY,
    'oauth_version': '1.0',
    'realm': REALM
  };
  
  // Sorting and encoding the parameters
  // Sorting and encoding the parameters
  var paramKeys = Object.keys(params);
  paramKeys.sort();
  var paramStr = paramKeys.map(function(key) {
  return encodeURIComponent(key) + "=" + encodeURIComponent(params[key]);
  }).join('&');
  
  // Create base string
  var baseString = method + '&' + encodeURIComponent(url) + '&' + encodeURIComponent(paramStr);
  
  // Create signature key
  var signatureKey = encodeURIComponent(CONSUMER_SECRET) + '&' + encodeURIComponent(RESOURCE_OWNER_SECRET);
  
  // Generate HMAC-SHA256 signature
  var signature = Utilities.computeHmacSha256Signature(baseString, signatureKey);
  signature = Utilities.base64Encode(signature);
  
  Logger.log('Base String: ' + baseString);
  Logger.log('Signature Key: ' + signatureKey);
  Logger.log('Signature: ' + signature);
  
  // Prepare OAuth1.0 headers
  params['oauth_signature'] = signature;
  var authHeader = 'OAuth ' + Object.keys(params).map(function(key) {
    return encodeURIComponent(key) + '="' + encodeURIComponent(params[key]) + '"';
  }).join(', ');
  Logger.log("Params are:   "+JSON.stringify(params))
  
  // Prepare HTTP options
  var options = {
    'method': method,
    'headers': {
      'Authorization': authHeader,
      'Content-Type': 'application/json'
    },
    'payload': JSON.stringify({"custentity_id": "2"})
  };
  
  // Send HTTP request and log the response
  try {
    var response = UrlFetchApp.fetch(url, options);
    Logger.log('Response: ' + response.getContentText());
  } catch (e) {
    Logger.log('Error: ' + e);
  }
}

Python 脚本

import requests
import oauthlib.oauth1
import json
import hmac
import hashlib
import base64
from urllib.parse import quote_plus
from pprint import pprint

# Constants and configurations
REALM = 'XXXXXXX'
CONSUMER_KEY = 'XXXXXXXXXXX'
CONSUMER_SECRET = 'XXXXXXXX'
RESOURCE_OWNER_KEY = 'XXXXXXXX'
RESOURCE_OWNER_SECRET = 'XXXXXXXX'

# Create a session object
session = requests.Session()


def generate_signature(base_string, signature_key):
    hmac_obj = hmac.new(signature_key.encode('utf-8'), base_string.encode('utf-8'), hashlib.sha256)
    return base64.b64encode(hmac_obj.digest()).decode('utf-8')


def create_netsuite_client():
    client = oauthlib.oauth1.Client(
        CONSUMER_KEY,
        client_secret=CONSUMER_SECRET,
        resource_owner_key=RESOURCE_OWNER_KEY,
        resource_owner_secret=RESOURCE_OWNER_SECRET,
        realm=REALM,
        signature_method="HMAC-SHA256",
        timestamp='1697458273',
        nonce='38751934124598253091697458273'
    )
    return client


def process_vendor(netsuite, id, netsuite_id):
    data = {"custentity_id": id}
    hdr = {"Content-Type": "application/json"}
    url = f'https://{REALM}.suitetalk.api.netsuite.com/services/rest/record/v1/vendor/{netsuite_id}'
    url, headers, body = netsuite.sign(url, headers=hdr, body=json.dumps(data), http_method="PATCH")
    pprint(headers)
    try:
        response = session.request("PATCH", url, headers=headers, data=body)
        response.raise_for_status()
        print(f"{id},{netsuite_id},Successful")
    except requests.RequestException as err:
        print(f"{id},{netsuite_id},{str(err)},{json.dumps(response.json()).replace(',', ' ')}")


def main():
    netsuite = create_netsuite_client()
    process_vendor(netsuite, '2', '1846')


if __name__ == '__main__':
    main()

python authentication google-apps-script netsuite hmacsha256
1个回答
0
投票

以防万一它对其他人有帮助 - 回到基础并设法纠正 - 事物的组合,但主要是 OAuth 参数和标头的顺序。所有值都是虚拟值! 可能不是最优雅的,但最终的结果已经实现了!!

function upsertOperation(externalId, body) {
  // Constants and configurations
  var REALM = '123456';
  var CONSUMER_KEY = 'xxxxxxxxxxxxxxxxxxxxxxxxxx';
  var CONSUMER_SECRET = 'xxxxxxxxxxxxxxxxxxxxxxxxxx';
  var RESOURCE_OWNER_KEY = 'xxxxxxxxxxxxxxxxxxxxxxxxxx';
  var RESOURCE_OWNER_SECRET = 'xxxxxxxxxxxxxxxxxxxxxxxxxxxx';
  var NETSUITE_ID = '1234';
  var ID = '2';
  var METHOD = "PATCH";
  var baseUrl = 'https://123456.suitetalk.api.netsuite.com/services/rest/record/v1/vendor/' + NETSUITE_ID;

  // Generate OAuth nonce and timestamp
  var oauthNonce = Utilities.getUuid();
  var oauthTimestamp = Math.floor(new Date().getTime() / 1000);

  // OAuth Parameters
  var oauthSignatureMethod = 'HMAC-SHA256';
  var oauthVersion = '1.0';
  var realm = REALM;

  // Collect and sort OAuth parameters
  var oauthParameters = {
    oauth_consumer_key: CONSUMER_KEY,
    oauth_token: RESOURCE_OWNER_KEY,
    oauth_nonce: oauthNonce,
    oauth_timestamp: oauthTimestamp,
    oauth_signature_method: oauthSignatureMethod,
    oauth_version: oauthVersion
  };

  var sortedParameters = Object.keys(oauthParameters)
    .sort()
    .map(function(key) {
      return key + '=' + oauthParameters[key];
    })
    .join('&');
  
  Logger.log("Sorted Params: "+sortedParameters);




  // Compute OAuth signature
  var signatureBaseString = METHOD + '&' + encodeURIComponent(baseUrl) + '&' + encodeURIComponent(sortedParameters);  //WORKING CORRECTLY
  Logger.log("Signature BaseString: "+signatureBaseString);

  var signingKey = encodeURIComponent(CONSUMER_SECRET) + '&' + encodeURIComponent(RESOURCE_OWNER_SECRET);    //WORKING CORRECTLY
  Logger.log("Signing Key: "+signingKey);

  var hmac = Utilities.computeHmacSha256Signature(signatureBaseString, signingKey);
  var oauthSignature = Utilities.base64Encode(hmac);
  Logger.log("SIGNATURE: "+ oauthSignature);

  // Prepare headers
var headers = {
  'Content-Type': 'application/json',
  'Authorization': 'OAuth ' +
    'realm="' + encodeURIComponent(realm) + '", ' +
    'oauth_token="' + encodeURIComponent(RESOURCE_OWNER_KEY) + '", ' +
    'oauth_consumer_key="' + encodeURIComponent(CONSUMER_KEY) + '", ' +
    'oauth_nonce="' + encodeURIComponent(oauthNonce) + '", ' +
    'oauth_timestamp="' + encodeURIComponent(oauthTimestamp) + '", ' +
    'oauth_signature_method="' + encodeURIComponent(oauthSignatureMethod) + '", ' +
    'oauth_version="' + encodeURIComponent(oauthVersion) + '", ' +
    'oauth_signature="' + encodeURIComponent(oauthSignature) + '"'
};
  Logger.log("Headers: " + JSON.stringify(headers, null, 2));

  var PAYLOAD = {
    'id': id
  };

  // HTTP request options
  var options = {
    method: METHOD,
    headers: headers,
    payload: JSON.stringify(PAYLOAD),
    followRedirects: true
  };

  // Perform HTTP request and log response
  var response = UrlFetchApp.fetch(baseUrl, options);
  
  if (response.getResponseCode() === 200) {
    // Successfully connected
    var json = response.getContentText();
    var data = JSON.parse(json);
    // Do something with the data
  } else {
    // Log the error information for debugging
    Logger.log("Error: " + response.getContentText());
  }
}
© www.soinside.com 2019 - 2024. All rights reserved.