向 Intuit/Quickbooks Payments API 提交标记化卡数据时出错

Error submitting tokenized card data to Intuit/Quickbooks Payments API

我正在将 Intuit/Quickbooks 支付 API 整合到现有的电子商务网站中。由于 PCI 要求,我需要在卡数据到达服务器之前通过 JavaScript 对其进行标记,然后使用该标记而不是实际的卡数据提交费用。

为什么我从付款 API 收到“令牌无效”错误?

第一次尝试

我遵循了 this page 上的说明,其中描述了如何使用因纽特人提供的 JavaScript 文件来标记卡数据。

<script src="https://js.appcenter.intuit.com/Content/IA/intuit.ipp.payments.sandbox-0.0.3.js"></script>

intuit.ipp.payments.tokenize(
  qbAppToken, {
    card: {
      number: $("#tokenize_cc-number").val(),
      expMonth: $("#tokenize_cc-expmonth").val(),
      expYear: $("#tokenize_cc-expyear").val(),
      cvc: $("#tokenize_cc-cvc").val(),
      address: {
        streetAddress: $("#tokenize_cc-address-street").val(),
        city: $("#tokenize_cc-address-city").val(),
        region: $("#tokenize_cc-address-region").val(),
        country: $("#tokenize_cc-address-country").val(),
        postalCode: $("#tokenize_cc-address-postalcode").val()
      }
    }
  },
  function(token, response) {
    console.log(response);
    if (token != null) {
      console.log(token);
      $cardToken.val(token);
      $paymentForm[0].submit();
    } else {
      console.log("Error during tokenization " + response.code + "; " + response.message + "; " + response.detail + "; " + response.moreinfo);
    }
  });

我找回了似乎是卡片标记的东西:

f9e7a378-c3f2-4343-b0a8-ee376d4ed472

我将该令牌插入我的表单并将表单提交到我的服务器,然后服务器使用卡令牌通过 CURL 向付款 API 提交费用。

我正在提交到端点:

https://sandbox.api.intuit.com/quickbooks/v4/payments/charges

Array
(
    [amount] => 6992.83
    [currency] => USD
    [capture] => true
    [token] => f9e7a378-c3f2-4343-b0a8-ee376d4ed472
    [context] => Array
        (
            [mobile] => false
            [isEcommerce] => true
        )

)

但是,我从付款 API 收到的回复说“令牌无效”:

{
  "errors": [{
    "code": "PMT-4000",
    "type": "invalid_request",
    "message": "token is invalid.",
    "detail": "token",
    "infoLink": "https://developer.intuit.com/v2/docs?redirectID=PayErrors"
  }]
}

完整回复如下:

HTTP/1.1 400 Bad Request
Server: nginx
Date: Wed, 05 Jun 2019 18:13:20 GMT
Content-Type: application/json;charset=utf-8
Content-Length: 175
Connection: keep-alive
Keep-Alive: timeout=5
Strict-Transport-Security: max-age=15552000
intuit_tid: [redacted]
Set-Cookie: ADRUM_BT=R:0|clientRequestGUID:9ae895d4-44ee-4175-bb47-4e37e95162a819|btId:755|backendSnapshotType:f; Expires=Wed,  5-Jun-2019 18:13:49 GMT; Path=/

{"errors":[{"code":"PMT-4000","type":"invalid_request","message":"token is invalid.","detail":"token","infoLink":"https://developer.intuit.com/v2/docs?redirectID=PayErrors"}]}

我注意到 instructions 对于 JavaScript 卡片标记化说“此部分仅适用于 OAuth 1.0 应用程序。”这可能是个问题。但我没有看到如何为 OAuth 2.0 应用程序标记卡数据。

解释错误

我假设“令牌无效”错误指的是我的卡令牌,而不是我的应用程序身份验证令牌。我的假设基于两件事:

  1. 当我更改我的应用程序身份验证令牌时,出现不同的错误:

    {
      "code": "AuthenticationFailed",
      "type": "INPUT",
      "message": null,
      "detail": null,
      "moreInfo": null
    }
    
  2. Intuit 开发人员关系说 Intuit JavaScript 文件中的令牌端点“不正确”,这表明我收到的卡令牌有问题。

联系开发者关系

Intuit 开发者关系说:

The reason you get that error is because that javascript file didn't create the token correctly in the correct environment.

QuickBooks Payments API has two different environments. One is called sandbox environment, the other is called production environment. For creating a token for sandbox environment, you will need to use this URL: https://sandbox.api.intuit.com/quickbooks/v4/payments/tokens

However, in that javascript, the URL for token is: https://transaction-api-e2e.payments.intuit.net/v2/tokens, which is incorrect. It is an internal testing environment we used. The token created in the e2e would not work for sandbox. That is why you get the token is invalid error.

再次尝试

在查看 API 浏览器和 tokens endpoint 之后,我尝试在没有 Intuit 的 JavaScript 库的情况下生成卡片令牌。

这使用与开发人员关系引用的 API Explorer 中相同的端点,尽管 sandbox.api.intuit.com/v4/payments/tokens 不存在所以我认为这是一个错字。

POST v4/payments/tokens
FOR IE8/IE9 - POST /quickbooks/v4/payments/tokens/ie
Content type: application/json
Production Base URL: https://api.intuit.com
Sandbox Base URL: https://sandbox.api.intuit.com

jQuery.ajax({
  url: "https://sandbox.api.intuit.com/quickbooks/v4/payments/tokens",
  type: "POST",
  contentType: 'application/json',
  dataType: "json",
  data: JSON.stringify(cardData)
}).done(function(msg) {

  ...

});

结果是一样的。
我得到的似乎是卡片令牌,但当我通过 CURL 提交费用时,我仍然得到:

{
  "errors": [{
    "code": "PMT-4000",
    "type": "invalid_request",
    "message": "token is invalid.",
    "detail": "token",
    "infoLink": "https://developer.intuit.com/v2/docs?redirectID=PayErrors"
  }]
}

怎么了?

除了 post in the developer community forums 之外,我还有 Intuit 的公开票证。如果我从他们那里收到任何进一步的信息,我会更新这个 post。

如果您正在关注 instructions here 使用位于 https://js.appcenter.intuit.com/Content/IA/intuit.ipp.payments-0.0.3.js 的 javascript 文件对信用卡信息进行标记化,请注意开发人员关系部的回复:

...in that javascript, the URL for token is: https://transaction-api-e2e.payments.intuit.net/v2/tokens, which is incorrect. It is an internal testing environment we used. The token created in the e2e would not work for sandbox. That is why you get the token is invalid error.

For creating a token for sandbox environment, you will need to use this URL: https://sandbox.api.intuit.com/quickbooks/v4/payments/tokens

我通过 AJAX 从令牌端点成功请求了一个卡令牌。

此外,当使用卡令牌提交费用时,请务必在 headers 中发送唯一的 RequestID

If the service receives another request with the same RequestID, instead of performing the operation again or returning an error, the service sends the same response as it did for the original request. (What is RequestId and its usage)

这就是为什么我在切换到正确的端点后仍然收到 "invalid token" 错误的原因。

我一直在用 Postman 测试(我知道 JS 不是问题),但是 API。也许这有帮助。

卡片标记化:

  • 端点: https://sandbox.api.intuit.com/quickbooks/v4/payments/tokens
  • Header: Content-Type: application/json
  • Body(原始)JSON(application/json):

    { "card":{ "name": "emulate=0", "number": "4111111111111111", "expMonth": "02", "address":{ "postalCode": "94086", "country": "US", "region": "CA", "streetAddress": "Road Street", "city": "Sunnyvale" }, "expYear": "2020", "cvc": "123" } }

回复:

{
 "value": "7e92f015-820b-4e70-81b9-8ce840c76389"
}

充电:

  • 端点: https://sandbox.api.intuit.com/quickbooks/v4/payments/charges
  • Header: Content-Type: application/json
  • request-id:随机数
  • 授权:OAuth 2.0 访问令牌(59 分钟)
  • Body(原始)JSON(application/json):

    { "currency": "USD", "amount": "10.55", "context":{ "mobile": "false", "isEcommerce": "true" }, "token":“7e92f015-820b-4e70-81b9-8ce840c76389” }

回复:

{
"created": "2019-06-17T16:18:43Z",
"status": "CAPTURED",
"amount": "10.55",
"currency": "USD",
"token": "7e92f015-820b-4e70-81b9-8ce840c76389",
"card": {
    "number": "xxxxxxxxxxxx1111",
    "name": "emulate=0",
    "address": {
        "city": "Sunnyvale",
        "region": "CA",
        "country": "US",
        "streetAddress": "Road Street",
        "postalCode": "94086"
    },
    "cardType": "Visa",
    "expMonth": "02",
    "expYear": "2020",
    "cvc": "xxx"
},
"avsStreet": "Pass",
"avsZip": "Pass",
"cardSecurityCodeMatch": "NotAvailable",
"id": "E4JTLAV2QAFF",
"context": {
    "mobile": false,
    "deviceInfo": {},
    "recurring": false,
    "isEcommerce": true
},
"authCode": "546816"
}