C# 如何使用.net在Amzon中使用销售合作伙伴api加密和上载数据

C# 如何使用.net在Amzon中使用销售合作伙伴api加密和上载数据,c#,.net,amazon-web-services,amazon-product-api,C#,.net,Amazon Web Services,Amazon Product Api,我想使用.Net的销售合作伙伴api文档。我从下面的url中找到了一个参考,但这是使用Java示例编码: 但是我想用.Net编码可以任何一个建议的.Net编码下面的java编码部分 import java.io.ByteArrayInputStream; import java.io.IOException; import java.io.InputStream; import java.io.PipedInputStream; import java.io.PipedOutputStr

我想使用.Net的销售合作伙伴api文档。我从下面的url中找到了一个参考,但这是使用Java示例编码:

但是我想用.Net编码可以任何一个建议的.Net编码下面的java编码部分

    import java.io.ByteArrayInputStream;
import java.io.IOException;
import java.io.InputStream;
import java.io.PipedInputStream;
import java.io.PipedOutputStream;
import java.nio.charset.StandardCharsets;

import com.amazon.spapi.documents.UploadHelper;
import com.amazon.spapi.documents.UploadSpecification;
import com.amazon.spapi.documents.exception.CryptoException;
import com.amazon.spapi.documents.exception.HttpResponseException;
import com.amazon.spapi.documents.impl.AESCryptoStreamFactory;

/* We want to maintain encryption at rest, so do not write unencrypted data to disk.  This is bad:
InputStream source = new FileInputStream(new File("/path/to/myFeed.xml"));

Instead, if your data can fit in memory, you can create an InputStream from a String (see encryptAndUpload_fromString()).
Otherwise, you can pipe data into an InputStream using Piped streams (see encryptAndUpload_fromPipedInputStream()).
 */
public class UploadExample {
  private final UploadHelper uploadHelper = new UploadHelper.Builder().build();

  // key, initializationVector, and url are returned by the createFeedDocument operation.
  public void encryptAndUpload_fromString(String key, String initializationVector, String url) {
    AESCryptoStreamFactory aesCryptoStreamFactory =
      new AESCryptoStreamFactory.Builder(key, initializationVector)
      .build();

    // This contentType must be the same value that was provided to createFeedDocument.
    String contentType = String.format("text/plain; charset=%s", StandardCharsets.UTF_8);

    // The character set must be the same one that is specified in contentType.
    try
      (InputStream source = new ByteArrayInputStream("my feed data".getBytes(StandardCharsets.UTF_8))) {
        UploadSpecification uploadSpec =
          new UploadSpecification.Builder(contentType, aesCryptoStreamFactory, source, url)
          .build();

        uploadHelper.upload(uploadSpec);
      }
    catch (CryptoException | HttpResponseException | IOException e) {
      // Handle exception.
    }
  }

  // key, initializationVector, and url are returned from createFeedDocument.
  public void encryptAndUpload_fromPipedInputStream(String key, String initializationVector, String url) {
    AESCryptoStreamFactory aesCryptoStreamFactory =
      new AESCryptoStreamFactory.Builder(key, initializationVector)
      .build();

    // This contentType must be the same value that was provided to createFeedDocument.
    String contentType = String.format("text/plain; charset=%s", StandardCharsets.UTF_8);

    try
      (PipedInputStream source = new PipedInputStream()) {
        new Thread(
          new Runnable() {
          public void run() {
            try
              (PipedOutputStream feedContents = new PipedOutputStream(source)) {
                // The character set must be the same one that is specified in contentType.
                feedContents.write("my feed data\n".getBytes(StandardCharsets.UTF_8));
                feedContents.write("more feed data".getBytes(StandardCharsets.UTF_8));
              }
            catch (IOException e) {
              // Handle exception.
            }
          }
        }).start();

        UploadSpecification uploadSpec =
          new UploadSpecification.Builder(contentType, aesCryptoStreamFactory, source, url)
          .build();

        uploadHelper.upload(uploadSpec);
      }
    catch (CryptoException | HttpResponseException | IOException e) {
    
    }
  }
}
编辑-----------------------------------------------------

这就是我尝试过的,这就是我得到的

步骤1

请求URL: 请求正文:{“contentType”:“text/plain;charset=utf-8”} 请求头={主机:sellingpartnerapi-na.amazon.com x-amz-日期:20210203T120516Z 授权:AWS4-HMAC-SHA256凭证=XXXXXXXX/20210203/us-east-1/执行api/AWS4_请求,签名头=主机;x-amz-date,签名=XXXX

凭证和签名在合作伙伴门户上创建

响应步骤1

{“有效载荷”: {“encryptionDetails”:{“standard”:“AES”,“initializationVector”:“TTAVo5bUDNfuk7KPzgm+ow=”, “键”:“GrpKm3UIvxiM5xUTlzaCC9xJFORMX41chAKUk0G6Cbg=“”, “feedDocumentId”:“amzn1.tortuga.3.9968967c-048c-4e8b-a6c1-ffd764f005d4.T508PJ0OCPKJ3”, “url”:"https://tortuga-prod-na.s3-external-1.amazonaws.com/%2FNinetyDays/amzn1.tortuga.3.9968967c-048c-4e8b-a6c1-ffd764f005d4.T508PJ0OCPKJ3?X-Amz-Algorithm=AWS4-HMAC-SHA256&X-Amz-Date=20210203T114111Z&X-Amz-SignedHeaders=内容类型%3Bhost&X-Amz-Expires=300&X-Amz-Credential=Akia5U6Mo6Ranypneypl%2F202010203%2Fus-east-1%2Fs3%2Faws4\U请求和X-Amz-Signature=1fd8b69523c06d76664c22c4093be5e8adc187436f7119aa9d4b51302cc8ae84“}

第二步: 在第2步中,我使用来自第一步响应的URL,但它没有得到结果

请求URL:

看到这里的签名和凭证与我们从步骤1的响应中得到的不同

步骤2的响应


希望这有助于第二步中的c锐器

假设您已收到步骤#1的OK响应

步骤1的响应如下所示:

{
  "payload":
  {
    "feedDocumentId":"amzn1.tortuga.3.920614b0-fc4c-4393-b0d9-fff175300000.T29XK4YL08B2VM",
    "url":"https://tortuga-prod-na.s3.amazonaws.com/%2FNinetyDays/amzn1.tortuga.3.920614b0-fc4c-4393-b0d9-fff175300000.T29XK4YL08B2VM?X-Amz-Algorithm=AWS4-HMAC-SHA256&X-Amz-Date=20200919T035824Z&X-Amz-SignedHeaders=<headers>&X-Amz-Expires=300&X-Amz-Credential=<credential>&X-Amz-Signature=<signature>",
    "encryptionDetails":
    {
      "standard":"AES",
      "initializationVector":"kF3bZt0FSv6JQEimfEJD8g==",
      "key":"5EZo/P06OGF0UAy8QuOnMIaQbkAvYBru6EGsFvK8wJ2="
    }
}
使用上面的密钥和iv变量对提要进行加密

这是一个加密和解密函数,我从微软那里得到,并做了一些轻微的修改(归功于)


快乐时光…

堆栈溢出不存在,无法为您翻译代码。是的,但这是一个API,那么可能有一种方法可以使VS通过WSDL使代码成为您要查找的代码。任何人都可以告诉我,我们必须在哪个URL上推送此加密数据。在创建IAM时,将其发布到此{访问密钥}/20201013/us-east-1/execute api/aws4_请求删除此错误AuthorizationHeaderMalformed授权标头格式不正确;服务“execute api”不正确。此终结点属于“s3”"很高兴看到你质疑这一点,帮助我节省了很多时间。干杯。我几乎处于相同的情况,但在发送创建提要的第一个请求时,我有以下错误:有人得到了上面的响应吗?如果有,什么操作解决了问题?我在身份验证中遇到了问题,无法进一步。有人可以告诉我我们必须在哪个URL上推送此加密数据。Amazon返回一个预先签名的URL。检查步骤#1感谢您指点我。我向前移动了一个新错误:AuthorizationHeaderMalformedThe authorization header格式不正确;服务“execute api”不正确。此端点属于“s3”.9DD75A286E7422B6rxCxNZ3veB/3ZJ1qrtvleA0JaHTPqprLYe3I5mM/LYLLEVPL6iKGv0irGmV1O9SS4AcmPsM/8/I=已通过的标头:$headers=['内容类型:文本/普通;字符集=utf-8',X-Amz-Content-Sha256:未签名有效载荷',X-Amz-Date:20210105T095435Z','授权:AWS4-HMAC-Sha256凭证={创建IAM时的访问密钥}/20210105/us-east-1/execute api/aws4_请求,SignedHeaders=host;x-amz-access-token;x-amz-content-sha256;x-amz-date,Signature={通过身份验证过程生成}',];我正在使用相同的函数,但无法上载提要详细信息,我正在使用此响应Url作为上载文件的“Url”参数(字节[]字节,字符串Url)函数但获取此错误详细信息时出错:signaturedesnotmatch我们计算的请求签名与您提供的签名不匹配。请检查您的密钥和签名方法。
{
  "payload":
  {
    "feedDocumentId":"amzn1.tortuga.3.920614b0-fc4c-4393-b0d9-fff175300000.T29XK4YL08B2VM",
    "url":"https://tortuga-prod-na.s3.amazonaws.com/%2FNinetyDays/amzn1.tortuga.3.920614b0-fc4c-4393-b0d9-fff175300000.T29XK4YL08B2VM?X-Amz-Algorithm=AWS4-HMAC-SHA256&X-Amz-Date=20200919T035824Z&X-Amz-SignedHeaders=<headers>&X-Amz-Expires=300&X-Amz-Credential=<credential>&X-Amz-Signature=<signature>",
    "encryptionDetails":
    {
      "standard":"AES",
      "initializationVector":"kF3bZt0FSv6JQEimfEJD8g==",
      "key":"5EZo/P06OGF0UAy8QuOnMIaQbkAvYBru6EGsFvK8wJ2="
    }
}
var key = Convert.FromBase64String(createFeedDocumentResponse.Payload.EncryptionDetails.Key);
var iv = Convert.FromBase64String(createFeedDocumentResponse.Payload.EncryptionDetails.InitializationVector);
string feedData = File.ReadAllText(@"C:\temp\AmazonFlatFileTest.txt");
private byte[] EncryptStringToBytes_Aes(string plainText, byte[] key, byte[] initializationVector)
{
  // Check arguments.
  if (plainText == null || plainText.Length <= 0)
    throw new ArgumentNullException("plainText");
  if (key == null || key.Length <= 0)
    throw new ArgumentNullException("Key");
  if (initializationVector == null || initializationVector.Length <= 0)
    throw new ArgumentNullException("initializationVector");
  byte[] encrypted;

  // Create an Aes object
  // with the specified key and IV.
  using (Aes aesAlg = Aes.Create())
  {
    aesAlg.Key = key;
    aesAlg.IV = initializationVector;

    // Create an encryptor to perform the stream transform.
    ICryptoTransform encryptor = aesAlg.CreateEncryptor(aesAlg.Key, aesAlg.IV);

    // Create the streams used for encryption.
    using (MemoryStream msEncrypt = new MemoryStream())
    {
      using (CryptoStream csEncrypt = new CryptoStream(msEncrypt, encryptor, CryptoStreamMode.Write))
      {
        using (StreamWriter swEncrypt = new StreamWriter(csEncrypt, Encoding.UTF8))
        {
          //Write all data to the stream.
          swEncrypt.Write(plainText);
        }
        encrypted = msEncrypt.ToArray();
      }
    }
  }

  // Return the encrypted bytes from the memory stream.
  return encrypted;
}
private string DecryptStringFromBytes_Aes(byte[] cipherText, byte[] Key, byte[] initializationVector, string compressionAlgorithm)
{
  // Validate Compression Algorithm
  var isGzip = string.Equals(compressionAlgorithm, "GZIP", StringComparison.OrdinalIgnoreCase);
  var compressionAlgorithmValid = compressionAlgorithm == null || isGzip;

  if (!compressionAlgorithmValid)
  {
    throw new InvalidOperationException($"Unexpected CompressionAlgorithm encounted. compressionAlgorithm = {compressionAlgorithm}");
  }

  // Check arguments.
  if (cipherText == null || cipherText.Length <= 0)
    throw new ArgumentNullException("cipherText");
  if (Key == null || Key.Length <= 0)
    throw new ArgumentNullException("Key");
  if (initializationVector == null || initializationVector.Length <= 0)
    throw new ArgumentNullException("IV");

  // Declare the string used to hold
  // the decrypted text.
  string plaintext = null;

  // Create an Aes object
  // with the specified key and IV.
  using (Aes aesAlg = Aes.Create())
  {
    aesAlg.Key = Key;
    aesAlg.IV = initializationVector;

    // Create a decryptor to perform the stream transform.
    ICryptoTransform decryptor = aesAlg.CreateDecryptor(aesAlg.Key, aesAlg.IV);

    // Create the streams used for decryption.
    using (MemoryStream msDecrypt = new MemoryStream(cipherText))
    {
      using (CryptoStream csDecrypt = new CryptoStream(msDecrypt, decryptor, CryptoStreamMode.Read))
      {
        if (isGzip)
        {
          using (var decompressedFileStream = new MemoryStream())
          {

            using (GZipStream decompressionStream = new GZipStream(csDecrypt, CompressionMode.Decompress))
            {
              decompressionStream.CopyTo(decompressedFileStream);
              decompressedFileStream.Position = 0;

              using (var writer = new StreamReader(decompressedFileStream))
              {
                plaintext = writer.ReadToEnd();
              }
            }

          }
        }
        else
        {
          using (StreamReader srDecrypt = new StreamReader(csDecrypt, Encoding.UTF8))
          {
            // Read the decrypted bytes from the decrypting stream
            // and place them in a string.
            plaintext = srDecrypt.ReadToEnd();
          }
        }
      }
    }
  }

  return plaintext;
}
private async Task UploadFile(byte[] bytes, string url)
{
  var contentType = "text/plain; charset=utf-8"; // this should be the same as what was used in Step #1 (in the CreateFeedDocument API request)

  RestClient restClient = new RestClient(url);
  IRestRequest restRequest = new RestRequest(Method.PUT);
  restRequest.AddParameter(contentType, bytes, ParameterType.RequestBody);

  var response = await restClient.ExecuteAsync(restRequest);

  if (!response.IsSuccessful)
  {
    // your error logic
  }

  // success. Move to Step #3
}