typescript NetSuite OAuth 1.0签名REST API

2uluyalo  于 2023-04-07  发布在  TypeScript
关注(0)|答案(1)|浏览(173)

我已经阅读了Stack Overflow上的文档和每篇文章,我可以找到关于使用TBA为NetSuite OAuth1.0创建签名的内容。从我所看到的,我正在输入所有要求并正确创建密钥,但是当我调用服务器时,我仍然得到
“拒绝设置不安全头“Cookie”
我做了以下工作:

  • 通过 Postman 成功地接通了
  • 在chrome中禁用cors策略,我正在那里打电话
  • 我已经尝试了每一个可能的组合,我可以尽可能的参数添加到基本字符串。

我可以确认我无法复制 Postman 的签名(使用相同的参数值),但我确实读到了一篇文章,这并不一定表明我错了,因为 Postman 使用了一些其他PM特定的参数/变量(不确定这有多有效)。
我在这里遵循文档:https://docs.oracle.com/en/cloud/saas/netsuite/ns-online-help/section_157652390285.html以及所有相关文档。
下面的帖子是最接近回答问题的,但是NetSuite不再支持HMAC-SHA1,但除了我改为HMAC-SHA 256之外,我提供了所有相同的参数。
类似问题和答案,我相信我是匹配减去一些NS文档的补充:Netsuite Rest Web Services Signature
我遇到的一个问题是,所有的文档都使用PHP,所以我试图将其与JavaScript等价物相匹配。但我从未在PHP中工作过,所以我不确定我是否使用了错误的编码方法。

import axios from 'axios';
        import { nanoid } from 'nanoid';
        import hmacSHA256 from 'crypto-js/hmac-sha256'
        import base64 from 'crypto-js/enc-base64'

        function encodeRFC3986URIComponent(str: string) {
            return encodeURIComponent(str)
                .replace(
                    /[!'()*]/g,
                    (c) => `%${c.charCodeAt(0).toString(16).toUpperCase()}`
                );
        }

        const parameters = {
            grant_type: "client_credentials",
            oauth_consumer_key: consumerKey,              
            oauth_signature_method: "HMAC-SHA256",
            oauth_timestamp: timeStamp,
            oauth_token: accessToken,
            oauth_nonce: nonce,
            oauth_version: "1.0",
        };

        const signatureKey = encodeURIComponent(consumerSecret) + '&' + encodeURIComponent(tokenSecret)
        console.log('signatureKey: ', signatureKey)

        var baseString = httpMethod + '&' + requestURL;

        for (const key in parameters) {
            baseString += "&" + key + "=" + parameters[key as keyof object];
        }

        const encodedBaseString = encodeRFC3986URIComponent(baseString)

        const signature = base64.stringify(hmacSHA256(encodedBaseString, signatureKey));

        let data = JSON.stringify({
            "q": "SELECT id, entityid FROM employee WHERE custentity_time_badge = '12345'"
        });

        let authorizationHeader = 'OAuth realm=' + OauthRealm

        for (const key in parameters) {
            authorizationHeader += ',' + key + "=" + parameters[key as keyof object];
        }
        authorizationHeader += ',oauth_signature=' + signature
        authorizationHeader = JSON.stringify(authorizationHeader)

        let config = {
            method: 'post',
            maxBodyLength: Infinity,
            url: 'https://5283244-sb2.suitetalk.api.netsuite.com/services/rest/query/v1/suiteql',
            headers: {
                'prefer': 'transient',
                'Content-Type': 'application/json',
                'Authorization': authorizationHeader,
                'Cookie': 'NS_ROUTING_VERSION=LAGGING'
            },
            data: data
        };

        axios.request(config)
            .then((response) => {
                console.log(JSON.stringify(response.data));
            })
            .catch((error) => {
                console.log(error);
            });
bgibtngc

bgibtngc1#

感谢Krypton为我指明了正确的方向。在他帮助我将问题隔离为真正的错误凭据之后,我去了下面的文档,从头开始创建一个与文档中的签名匹配的签名。
文档:https://docs.oracle.com/en/cloud/saas/netsuite/ns-online-help/section_1534941088.html
在我解决了导致签名不正确的问题之后,我有了一个工作示例。
现在我的代码如下

const parameters = {
            oauth_consumer_key: consumerKey,
            oauth_nonce: nonce,
            oauth_signature_method: "HMAC-SHA256",
            oauth_timestamp: timeStamp,
            oauth_token: tokenKey,
            oauth_version: "1.0",
        };

        let e_baseString = httpMethod + '&' + encodeURIComponent(requestURL) + '&'
        let firstiteration = 0
        for (const key in parameters) {
            if (firstiteration === 0) {
                e_baseString += key + "%3D" + parameters[key as keyof object];
                firstiteration = 1
            } else {
                e_baseString += "%26" + key + "%3D" + parameters[key as keyof object];
            }
        }
        
        const e_key = encodeURIComponent(consumerSecret) + '&' + encodeURIComponent(tokenSecret)
        let signature = base64.stringify(hmacSHA256(e_baseString, e_key))
        signature = encodeURIComponent(signature)

        let authorizationHeader = 'OAuth realm="' + OauthRealm + '"'
        for (const key in parameters) {
            authorizationHeader += ',' + key + '="' + parameters[key as keyof object] + '"';
        }
        authorizationHeader += ',oauth_signature="' + signature + '"' 

        console.log('authorizationHeader: ', authorizationHeader)

        let data = JSON.stringify({
            "q": "SELECT id, entityid FROM employee WHERE custentity_time_badge = '123456'"
        });

        let config = {
            method: 'post',
            maxBodyLength: Infinity,
            url: 'https://5283244-sb2.suitetalk.api.netsuite.com/services/rest/query/v1/suiteql',
            headers: {
                'prefer': 'transient',
                'Content-Type': 'application/json',
                'Authorization': authorizationHeader,
            },
            data: data
        };

        axios.request(config)
            .then((response) => {
                console.log(JSON.stringify(response.data));
            })
            .catch((error) => {
                console.log(error);
            });

再次感谢Krypton,我正在使用多个新的框架/库等。你帮助我隔离问题是一个巨大的帮助。

相关问题