You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

NetSuite SOAP API签名生成与文档不符问题排查

NetSuite令牌认证签名不一致问题排查

我正在基于令牌认证流程构建Node.js版NetSuite集成。按照文档示例编写单元测试时,基础字符串(base string)和密钥(key)的生成结果均与文档一致,但使用HMAC SHA256算法生成的签名却与文档给出的示例不符。改用文档示例使用的Java语言实现后,得到的签名结果仍与Node.js版本一致,而与文档示例不同。目前集成还遇到“无效凭证”错误,需要确认是代码问题、文档存在错误,或是遗漏了某些步骤。

通过的单元测试

it("Generates a base string", () => {
    const baseString = shared.exportsForTest.genBaseString(__testConfig, __docNonce, __docTimestamp);
    expect(baseString).toEqual(__docBaseString);
  });

  it("Generates a key", () => {
    const key = shared.exportsForTest.genKey(__testConfig);
    expect(key).toEqual(__docKey);
  });

失败的单元测试

it("Generates a signature", () => {
    const baseString = shared.exportsForTest.genBaseString(__testConfig, __docNonce, __docTimestamp);
    const key = shared.exportsForTest.genKey(__testConfig);
    const signature = shared.exportsForTest.genSignature({
      baseString,
      key
    });
    expect(signature).toEqual(__docSignature);
  });

核心生成函数定义

__genBaseString(基础字符串生成)

function __genBaseString(config: INetSuiteConfig, nonce: string, timestamp: DateTime) {
  return _.join([
    config.accountId,
    config.consumerKey,
    config.tokenId,
    nonce,
    timestamp.toUnixInteger() // Timestamp as epoch time.
  ], '&');
}

__genKey(密钥生成)

function __genKey(config: INetSuiteConfig) {
  return _.join([
    config.consumerSecret,
    config.tokenSecret
  ], '&');
}

__genSignature(签名生成)

function __genSignature({
  baseString, key
}: {
  baseString: string;
  key: string;
}) {
  const keyAsBytes = Buffer.from(key, 'utf-8');
  const baseStringAsBytes = Buffer.from(baseString, 'utf-8');

  const hash = crypto.createHmac('sha256', keyAsBytes)
    .update(baseStringAsBytes)
    .digest();

  return hash.toString('base64');
}

程序生成的签名为 FCghIZqXNetuZY8ILWOFH0ucdfzQOmAuL+q+kF21zPs=,文档给出的签名为 fzGxUBu6SZvGqv5hk8P4ou2DPthSxXtJ4zJIeCBQK5A=

文档提供的测试值

const __testConfig: shared.INetSuiteConfig = {
  accountId: '1234567',
  applicationId: '',
  consumerKey: '71cc02b731f05895561ef0862d71553a3ac99498a947c3b7beaf4a1e4a29f7c4',
  consumerSecret: '7278da58caf07f5c336301a601203d10a58e948efa280f0618e25fcee1ef2abd',
  tokenId: '89e08d9767c5ac85b374415725567d05b54ecf0960ad2470894a52f741020d82',
  tokenSecret: '060cd9ab3ffbbe1e3d3918e90165ffd37ab12acc76b4691046e2d29c7d7674c2'
};

const __docBaseString =
'1234567&71cc02b731f05895561ef0862d71553a3ac99498a947c3b7beaf4a1e4a29f7c4&89e08d9767c5ac85b374415725567d05b54ecf0960ad2470894a52f741020d82&6obMKq0tmY8ylVOdEkA1&1439829974';
const __docKey = '7278da58caf07f5c336301a601203d10a58e948efa280f0618e25fcee1ef2abd&060cd9ab3ffbbe1e3d3918e90165ffd37ab12acc76b4691046e2d29c7d7674c2';
const __docNonce = '6obMKq0tmY8ylVOdEkA1';
const __docSignature = 'fzGxUBu6SZvGqv5hk8P4ou2DPthSxXtJ4zJIeCBQK5A=';
const __docTimestamp = DateTime.fromSeconds(1439829974);

Java对比实现代码

import java.security.InvalidKeyException;
import java.security.NoSuchAlgorithmException;

import javax.crypto.Mac;
import javax.crypto.spec.SecretKeySpec;

class SignatureTestProgram {

  public static void main(String[] args) throws NoSuchAlgorithmException, InvalidKeyException {
    SignatureTestProgram hello = new SignatureTestProgram();
    String signature = hello.computeShaHash(
      hello.getBaseString(),
      hello.getKey(),
      "HmacSHA256"
    );
    System.out.println(signature);
  }

  public String getBaseString() {
    return "1234567" + // account
      "&" +
      "71cc02b731f05895561ef0862d71553a3ac99498a947c3b7beaf4a1e4a29f7c4" + // consumer key
      "&" +
      "89e08d9767c5ac85b374415725567d05b54ecf0960ad2470894a52f741020d82" + // token
      "&" +
      "6obMKq0tmY8ylVOdEkA1" + // nonce
      "&" +
      "1439829974"; // timestamp
  }

  public String getKey() {
    return "7278da58caf07f5c336301a601203d10a58e948efa280f0618e25fcee1ef2abd" + // consumer secret
      "&" +
      "060cd9ab3ffbbe1e3d3918e90165ffd37ab12acc76b4691046e2d29c7d7674c2"; // token secret
  }

  public String computeShaHash(String baseString, String key, String algorithm) throws NoSuchAlgorithmException, InvalidKeyException {
    byte[] bytes = key.getBytes();
    SecretKeySpec mySigningKey = new SecretKeySpec(bytes, algorithm);
    Mac messageAuthenticationCode = Mac.getInstance(algorithm);
    messageAuthenticationCode.init(mySigningKey);
    byte[] hash = messageAuthenticationCode.doFinal(baseString.getBytes());
    return new String(java.util.Base64.getEncoder().encode(hash));
  }
}

内容的提问来源于stack exchange,提问作者Andrew D

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.07.27 03:52:34