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

如何在CyberSource中使用Flexible Token通过Payments API发起扣款?

我完全理解你的困惑——CyberSource的文档确实把令牌化和支付流程拆得比较开,没有直接给出整合后的示例。不过你并没有遗漏内容,只需要把Flexible Token替换掉Payments API里的卡信息字段就行,下面是具体的实现方案,包括Node.js的代码示例:

核心思路

当你通过Secure Acceptance Flexible Token API获取到令牌后,这个令牌(通常返回在paymentInstrument.token字段)可以直接替代Payments API请求中的卡号、CVV等敏感卡信息。只需要在请求体的paymentInformation节点下,用tokenizedCard对象包裹令牌,而不是使用card对象。

Node.js 实现方案(官方SDK)

使用CyberSource官方提供的cybersource-rest-client SDK是最简便的方式,它已经封装了认证和请求逻辑:

  1. 首先安装依赖:
npm install cybersource-rest-client
  1. 编写支付请求代码:
const cybersourceRestApi = require('cybersource-rest-client');

// 从CyberSource后台获取你的商户配置信息
const config = {
  authenticationType: 'http_signature',
  merchantID: 'YOUR_MERCHANT_ID',
  merchantKeyId: 'YOUR_API_KEY_ID',
  merchantSecretKey: 'YOUR_SECRET_KEY',
  runEnvironment: 'sandbox' // 生产环境改为 'production'
};

const apiClient = new cybersourceRestApi.ApiClient();
apiClient.setConfiguration(config);

const paymentsApi = new cybersourceRestApi.PaymentsApi(apiClient);

// 构造支付请求,使用Flexible Token
const paymentRequest = {
  clientReferenceInformation: {
    code: 'ORDER_12345' // 自定义订单编号
  },
  processingInformation: {
    capture: true, // true = 直接扣款;false = 预授权(后续需调用Capture API完成扣款)
    commerceIndicator: 'internet'
  },
  paymentInformation: {
    tokenizedCard: {
      number: 'YOUR_FLEXIBLE_TOKEN', // 这里填入你获取到的Flex令牌
      expirationMonth: '12', // 若令牌未包含过期信息,需传入原卡的过期月份
      expirationYear: '2028' // 若令牌未包含过期信息,需传入原卡的过期年份
    }
  },
  orderInformation: {
    amountDetails: {
      totalAmount: '99.99',
      currency: 'USD'
    },
    billTo: {
      firstName: 'Jane',
      lastName: 'Smith',
      address1: '456 Oak Ave',
      locality: 'San Francisco',
      administrativeArea: 'CA',
      postalCode: '94105',
      country: 'US',
      email: 'jane.smith@example.com'
    }
  }
};

// 发起扣款请求
paymentsApi.createPayment(paymentRequest)
  .then(response => {
    console.log('支付成功:', JSON.stringify(response.data, null, 2));
  })
  .catch(error => {
    console.error('支付失败:', error.response.data);
  });
Node.js 实现方案(原生HTTP请求)

如果你不想依赖官方SDK,可以直接构造HTTP请求并处理签名:

const axios = require('axios');
const crypto = require('crypto');
const moment = require('moment');

// 配置信息
const merchantId = 'YOUR_MERCHANT_ID';
const apiKeyId = 'YOUR_API_KEY_ID';
const secretKey = 'YOUR_SECRET_KEY';
const baseUrl = 'https://apitest.cybersource.com'; // 生产环境改为 'https://api.cybersource.com'

// 生成HTTP签名
function generateHmacSignature(method, path, payload) {
  const timestamp = moment().utc().format('YYYY-MM-DDTHH:mm:ss[Z]');
  const digest = crypto.createHash('sha256').update(JSON.stringify(payload)).digest('base64');
  
  const signingString = `${method}\n${path}\n${timestamp}\n${digest}\n`;
  const signature = crypto.createHmac('sha256', secretKey).update(signingString).digest('base64');
  
  return `keyid="${apiKeyId}",algorithm="HmacSHA256",headers="host date request-target digest",signature="${signature}"`;
}

// 构造支付请求体
const paymentPayload = {
  clientReferenceInformation: { code: 'ORDER_67890' },
  processingInformation: { capture: true, commerceIndicator: 'internet' },
  paymentInformation: {
    tokenizedCard: {
      number: 'YOUR_FLEXIBLE_TOKEN',
      expirationMonth: '12',
      expirationYear: '2028'
    }
  },
  orderInformation: {
    amountDetails: { totalAmount: '49.99', currency: 'EUR' },
    billTo: {
      firstName: 'Pierre',
      lastName: 'Dubois',
      address1: '789 Rue de Paris',
      locality: 'Paris',
      postalCode: '75001',
      country: 'FR',
      email: 'pierre.dubois@example.com'
    }
  }
};

const method = 'POST';
const path = '/pts/v2/payments/';
const timestamp = moment().utc().format('YYYY-MM-DDTHH:mm:ss[Z]');
const digest = crypto.createHash('sha256').update(JSON.stringify(paymentPayload)).digest('base64');
const signature = generateHmacSignature(method, path, paymentPayload);

axios({
  method,
  url: `${baseUrl}${path}`,
  headers: {
    'Content-Type': 'application/json',
    'Authorization': `Signature ${signature}`,
    'Date': timestamp,
    'Digest': `SHA-256=${digest}`,
    'Host': 'apitest.cybersource.com', // 生产环境改为 'api.cybersource.com'
    'Merchant-ID': merchantId
  },
  data: paymentPayload
})
.then(response => {
  console.log('支付成功:', response.data);
})
.catch(error => {
  console.error('支付失败:', error.response.data);
});
关键注意事项
  • 令牌有效性:确保你的Flexible Token是由你的商户ID生成的,且未过期(测试环境令牌通常有效期较短)。
  • 预授权流程:如果需要预授权,将processingInformation.capture设为false,之后需要调用CaptureApi(或对应的HTTP端点)来完成实际扣款。
  • 过期信息:部分Flex令牌会包含卡的过期信息,若返回结果中没有,必须传入原卡的过期月/年,否则请求会失败。
  • 环境切换:测试环境(sandbox)和生产环境的API地址、密钥都是独立的,切换时要注意更新配置。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.05.13 08:00:31