概述

参考

使用Chargify.js

Chargify.js是一个功能强大的工具,可用于简化Chargify中基于API的现有工作流程。 Chargify.js可用于轻松构造现有网站上的注册和付款资料更新。

这个怎么运作

Chargify provides transparent iframes that allow you to customize a customer’s payment form. This approach ensures the you meet the latest PCI合规性要求。

当客户提交您的付款表格时,Chargify.js发送客户付款信息以安全地存储在您的付款网关中。作为回报,将生成一次性令牌,供您使用我们的API来完成订阅过程。一次性付款令牌引用安全存储在网关中的付款信息。

使用此令牌,您可以创建分配给客户的订阅或付款资料。由于您没有传递任何敏感的付款信息,因此PCI大大减少了。对订阅端点的API调用示例将采用以下形式:

  • 在Chargify.js中使用以下类型创建的令牌:“ credit_card”
{
  "subscription": {
    "product_handle": "pro-plan",
    "customer_attributes": {
      "first_name": "Joe",
      "last_name": "Smith",
      "email": "j.smith@example.com"
    },
    "credit_card_attributes": {
      "chargify_token": "tok_cwhvpfcnbtgkd8nfkzf9dnjn"
    }
  }
}
  • 在Chargify.js中使用以下类型创建的令牌:“ gocardless”
{
  "subscription": {
    "product_handle": "pro-plan",
    "customer_attributes": {
      "first_name": "Joe",
      "last_name": "Smith",
      "email": "j.smith@example.com"
    },
    "bank_account_attributes": {
      "chargify_token": "tok_cwhvpfcnbtgkd8nfkzf9dnjn"
    }
  }
}
  • 在Chargify.js中使用以下类型创建的令牌:“ apple_pay”
{
  "subscription": {
    "product_handle": "pro-plan",
    "customer_attributes": {
      "first_name": "Joe",
      "last_name": "Smith",
      "email": "j.smith@example.com"
    },
    "apple_pay_attributes": {
      "chargify_token": "tok_cwhvpfcnbtgkd8nfkzf9dnjn"
    }
  }
}
  • 在Chargify.js中使用以下类型创建的令牌:“ pay_pal”
{
  "subscription": {
    "product_handle": "pro-plan",
    "customer_attributes": {
      "first_name": "Joe",
      "last_name": "Smith",
      "email": "j.smith@example.com"
    },
    "paypal_account_attributes": {
      "chargify_token": "tok_cwhvpfcnbtgkd8nfkzf9dnjn"
    }
  }
}

创建新的订阅

Use Chargify.js to allow new subscribers to securely enter their payment information from your site. Instead of sending a credit_card_attribute with your POST to the /subscriptions endpoint, your workflow will closely follow this outline:

  • 潜在的订户将在您的网站上填写基于付款的表格
  • Chargify returns a one-time token for you to use to complete the subscription request to the /subscriptions endpoint

更新现有付款方式

In addition to creating new subscribers, use Chargify.js to create new payment methods. This workflow allows your existing subscribers to enter new card information on your site. From here, you’ll use the token to send a POST to the /payment_profiles to create a new payment method.

  • 现有订户在您的网站上填写基于付款的表格,目的是向其帐户添加新的信用卡
  • Chargify返回一次性令牌,用于将新的付款方式添加到现有订阅中
Chargify.js与更新Chargify中的现有信用卡不兼容。您只能将新卡添加到现有订阅中,或使用最近标记化的卡创建新订阅。

入门

1) To begin using Chargify.js, include the Chargify.js script on your page. This exposes a single global object, Chargify.

<script src="//js.ikvrej.icu/latest/chargify.js"></script>

强烈建议使用Chargify.js的最新Chargify托管版本。该版本会定期更新以与系统的其余部分兼容。使用本地托管的Chargify.js版本可能会带来与我们的服务器不兼容的风险。我们强烈建议您反对这种做法。

2)实例化页面上的Chargify变量,或将其包含在附加到前端表单的单独文件中:

var chargify = new Chargify();

3) 生成公钥。这将与您的API密钥分开,API密钥必须保密。

4)用所需的身份验证和自定义加载Chargify。我们有一个 专门针对此主题的全文.

5) Based on the selectors you have configured within Chargify.load, add those to your main form. Here’s an example with some basic configuration included inline with a single selector to pull in all iframes:

<!DOCTYPE html>
<html>
    <head>
        <script src="//js.ikvrej.icu/latest/chargify.js"></script>
    </head>

    <body>
        <form id='chargify-form'>
            <div id="chargify1"></div>

            <!-- While testing, you can remove the "hidden" type to expose the token for easy viewing. -->
            <input id="chargify-token" type="hidden" />

            <button type="submit">Submit Form</button>
        </form>
    </body>

    <script>
        var chargify = new Chargify();

        chargify.load({
            // selector, where the iframe will be included on your page
            // optional, if you have a `selector` for every field ('fields' option)
            selector: '#chargify1',

            // (i.e. '1a2cdsdn3lkn54lnlkn')
            publicKey: 'your-public-api-key',

            // payment profile type you will accept
            type: 'card',

            // points to your Chargify site
            serverHost: '//acme.ikvrej.icu'
        });
    </script>
</html>

6)此时您应该具有基本形式。接下来,中断表单的提交以将账单信息发送给Chargify并获得一次性令牌作为交换。

document.querySelector('#chargify-form').addEventListener('submit', function(event) {
    var form = this;

    event.preventDefault();

    chargify.token(
        form,
        function success(token) {
            // optionally, you can assign a chargify token to a hidden field
            // or pass it to your backend in other way
            document.querySelector('#chargify-token').value = token;

            // and then submit the form
            form.submit();
        },
        function error(err) {
            // be aware that an error can occur for different reasons
            // while saving billing info in the gateway or directly
            // on the Chargify backend. It is rare but still possible.
            // Remember to make the user aware the presence of an error
            console.log('token ERROR - err: ', err);
        }
    );
});

7)获得令牌后,将其提交到服务器并使用它来 创建订阅 或者 付款资料 using our API.

令牌会在20分钟后过期。

8)现在,Chargify.js的基本工作流程正在运行,请在表单中添加一些样式! 这是一个看起来像的例子。该页面底部可以找到最小和完整的其他示例。

处理错误

When an error occurs on the back-end side, the error callback is invoked with the object having 2 properties:

{
    status: 400, // HTTP status
    errors: "Your card was declined." // it can be an array of errors as well
}

单页应用

截至2019年2月5日,Chargify.js可与诸如 反应 或者 角度的.

我们已经发布了两个带有示例应用程序的存储库,这些存储库演示了如何在这些框架中使用Chargify.js:

托管和技术注意事项

The static files on //js.ikvrej.icu are hosted via AWS Cloudfront. They use a different set of HTTP & TLS specifications than //app.ikvrej.icu. As such, their compatibility with various browsers and clients may be different. It also may be 受与我们的主应用程序不同的故障的影响。

需要注意的特定技术注意事项:

  • TLS is terminated by Cloudfront using the TLSv1.2_2018 config. TLS 1.0 and TLS 1.1 are not supported. The full cipher suite list is 可从AWS获得
  • 将SNI用于TLS,这会导致与浏览器的兼容性比Chargify应用程序低。 Akamai有 发表研究 描述了浏览器对SNI的支持的演变,这是非常高的,但并不完美。
  • 支持HTTP / 2,HTTP / 1.1,HTTP / 1.0
  • Through the use of AWS Cloudfront, //js.ikvrej.icu is designed for maximum reliability and speed, but is not covered by our SLA, uptime, or performance guarantees.
使用Chargify.js时,您的工作流程将归类为SAQ-A。有关更多信息,请参见我们的文档。 PCI合规性。

传递预先填写的客户信息

可以在Chargify.js外部收集以下内容,然后将其与令牌提交一起传递以将其存储在付款资料中:

  • 名字和姓氏
  • 帐单地址(街道地址,城市,州,国家/地区,邮政编码)

预先填写客户名称可以带来更加个性化的体验,例如,如果客户名称已经存在于您的应用程序中,或者注册流程涉及多个步骤。此外,如果您需要先使用外部库来首先验证地址,或者已经从客户处收集了地址,则预填写地址可能会很有用。

To make use of this functionality, do not include any of the address iframe fields within the Chargify.js chargify.load() script. Instead, include the hidden fields below within the HTML form and dynamically fill in the value of each field with the desired information:

<div class="host-field">
  <input type="hidden" class="host-input" data-chargify="firstName" value="Jane"/>
</div>
<div class="host-field">
  <input type="hidden" class="host-input" data-chargify="lastName" value="Mehmed"/>
</div>
<div class="host-field">
  <input type="hidden" class="host-input" data-chargify="address" value="123 Main St"/>
</div>
<div class="host-field">
  <input type="hidden" class="host-input" data-chargify="address2" value="#321"/>
</div>
<div class="host-field">
  <input type="hidden" class="host-input" data-chargify="city" value="San Antonio"/>
</div>
<div class="host-field">
  <input type="hidden" class="host-input" data-chargify="state" value="TX"/>
</div>
<div class="host-field">
  <input type="hidden" class="host-input" data-chargify="country" value="US"/>
</div>
<div class="host-field">
  <input type="hidden" class="host-input" data-chargify="zip" value="12345"/>
</div>

安全

使用Chargify.js,您可以使用Chargify和网关标记卡。由于我们大多数网关还在令牌化过程中执行“卡验证”,因此,您应采取措施以大规模验证偷来的卡凭据,以保护Chargify.js表单不受不良行为的影响。

默认情况下,Chargify在令牌化终结点上提供一层防欺诈功能,该功能可以无提示地保护您的令牌化端点。此外,您的网关可能会提供欺诈检测工具,以防止不必要的卡令牌化/验证。

除这些工具外,Chargify还为您提供配置以提高Chargify.js表单提交的安全性。我们的“安全令牌”使您可以使用自己与Chargify之间共享的私钥对正式表单提交进行签名,而我们的配置允许您选择重复表单提交的容忍度。

就其本质而言,Chargify.js允许最终用户直接从其客户端环境向Chargify服务器提交持卡人数据。您有目的地脱离了令牌化过程的循环。稍后,您必须发出服务器到服务器的API请求才能使用令牌,该令牌受您的API密钥保护。因此,请记住,这些安全措施的目的是减少黑客以批量方式对卡进行令牌化的能力,并且不影响订阅创建或令牌使用的行为-后者已经受到使用您的密码的保护受保护的API密钥。

安全令牌

安全令牌的生成需要您的Chargify.js私钥。您可以从Integrations生成或查看您的Chargify.js密钥对>Chargify.js。私钥最初是隐藏的,但是您可以单击以显示,然后复制该值。

需要私钥来签名您的安全令牌。 不要公开共享您的私钥!。您将需要在服务器上生成安全令牌,然后与客户端Chargify.js配置共享结果令牌(而不是私钥)。

安全令牌是签名的 JSON Web令牌(JWT) 有几项主张。只要您的私钥保持私密,其他任何人都不能代表您提出新的有效声明。

必须使用HMAC SHA 256(HS256)算法使用私钥对令牌进行签名。

索偿

声明包含在您的JWT的有效负载中:

  • iss 颁发者(必需):颁发者必须设置为Chargify.js公钥的值。这是唯一需要的要求。通过使用此声明,攻击者无法仅使用您的公共密钥来提出自己的请求。但是,您仍然可以避免重播攻击-攻击者加载了官方认可的Chargify.js表单后,它们还将具有有效的安全令牌。因此,该权利要求应与以下权利要求之一结合使用。
  • jti JWT ID (Optional): “JWT ID” should be set to a unique value each time you generate a Chargify.js form for submission. Using the security configuration, you can limit your exposure to replay attacks by limiting the number of times each unique jti may be used to attempt a card tokenization. With the protection of this claim, attackers would need to continually load your officially sanctioned forms to obtain new, valid security tokens. This gives you an ability to detect and prevent abuse from your app, where the forms are generated.
  • sub (可选):“主题”应设置为一个标识系统内用户或帐户的值,尤其是当Chargify.js令牌化表单在登录后受到保护时。受此主张的保护,您可以将系统中每个用户的令牌化请求数限制为与用户体验一致的值。要利用您的令牌化表单,攻击者将需要在您的系统中不断生成新帐户,如果您阻止创建一次性帐户,这将给您另一个防止应用滥用的机会。

代币示例

Your JWT must include at least the iss claim, and should be signed using the HMAC SHA 256 (HS256) algorithm using your private key.

Ruby中的示例使用 JWT Rubygem 如下。您可以使用此示例来确保您的JWT库产生与我们预期相同的结果。

@security_token = JWT.encode(
  {
    iss: "chjs_mypublickey",
    jti: SecureRandom.hex, # "b8a9044cbada8b24a230ff8934663843"
    sub: current_user.account_id.to_s, # "4035"
  },
  "chjs_pvt_myprivatekey",
  "HS256"
)
# => "eyJ0eXAiOiJKV1QiLCJhbGciOiJIUzI1NiJ9.eyJpc3MiOiJjaGpzX215cHVibGlja2V5IiwianRpIjoiYjhhOTA0NGNiYWRhOGIyNGEyMzBmZjg5MzQ2NjM4NDMiLCJzdWIiOiI0MDM1In0.l9k-aZ8bES0AlTnCMUyDo3XwLMtmYmFhTUOZho2QVos"

The token should then be provided to your Chargify.js client-side configuration under the key securityToken.

例如,如果进行内联配置,则可以将安全令牌发送到HTML中:

<!-- form.html.erb -->
<script>
  var chargify = new Chargify();

  chargify.load({
      selector: '#chargify-form',
      publicKey: 'chjs_mypublic_key',
      securityToken: '<%= @security_token %>',
      type: 'card',
      serverHost: '//acme.ikvrej.icu'
  });
</script>

或者,您可以将安全令牌发送给页面上的元素,然后从DOM中获取它。

// client.js
// DOM has element <div id="jwt" data-security-token="<%= @security_token %>"></div>
const securityToken = document.querySelector("#jwt).dataset.securityToken;
var chargify = new Chargify();

chargify.load({
    selector: '#chargify-form',
    publicKey: 'chjs_mypublic_key',
    securityToken: securityToken,
    type: 'card',
    serverHost: '//acme.ikvrej.icu'
});

安全配置

将有效的安全令牌发送到服务器后,可以启用设置以要求令牌并强制执行限制。

共有三种配置选择:

  1. 需要securityToken。 必须启用此选项才能启用其他两个选项。请注意,启用此选项后,您仅确保每次提交表单都需要签名的JWT。攻击者仍然可以导航到您的页面,加载您批准的表格,然后能够复制您的表格。
  2. 将每个JWT ID限制为一定数量的总请求。 这有助于防止重放攻击。每次攻击者访问您批准的表格时,他们将仅能针对此配置中列出的提交总数重复使用安全令牌。请记住,合法用户在提供所有必填字段之前可能会提交您的表单几次。因此,除非您在每次提交表单后都重新初始化安全性令牌,否则请考虑在阻止之前至少允许尝试5次。
  3. 每个帐户范围(即您应用中的用户或帐户ID)的速率限制为每小时一定数量的请求。 对于仅在应用程序的登录页面(例如“我的帐户”页面)上提供Chargify.js表单的那些设置,这是最佳选择。普通用户在一小时内不需要多次更新卡,因此请考虑将其设置为较低的值(例如5)。

失误

这些是启用安全设置时可以从令牌化过程返回的错误和状态代码。

状态码 信息 描述
401 安全令牌无效。 The security token has been marked as required, and it was either not provided, is invalid, is incorrectly signed, or has the wrong value for iss (which should be set to the public key).
401 安全令牌缺少必需的数据。 The security token requires either jti 或者 sub, but the required value was not supplied.
429 安全令牌已超出配置的速率限制。 Either the same jti value has been used more than the allowed number of times, or the same sub value has been used more than the allowed number of times in one hour.