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

求助:基于Paytrail搭建在线支付的实现方案及代码示例

Paytrail在线支付功能实现方案

问题说明

我需要在网站上使用Paytrail搭建在线支付功能,但阅读官方文档时感到困惑,无法完成这项任务。我的实现思路是:先向自有服务器请求获取验证所需的hash及相关参数,以此向Paytrail服务器确认请求合法性;再通过前端使用这些参数向Paytrail服务器发送请求创建订单。现咨询该流程的具体实现方式,希望能提供可运行的代码示例帮助理解。


一、Node.js 服务器端实现

服务器需要处理前端的订单参数请求,生成符合Paytrail要求的随机nonce、实时timestamp,并计算对应的HMAC哈希值,返回给前端用于后续请求Paytrail。

const crypto = require('crypto');
const http = require("http");
const PORT = process.env.PORT || 3000;

// Paytrail测试凭据
const ACCOUNT = '375917';
const SECRET = 'SAIPPUAKAUPPIAS';

/**
 * 计算Paytrail要求的HMAC哈希
 * @param {string} secret - Paytrail密钥
 * @param {object} checkoutHeaders - 包含checkout-开头的请求头
 * @param {object} requestBody - 请求体数据
 * @returns {string} 计算后的哈希值
 */
const calculateHmac = (secret, checkoutHeaders, requestBody) => {
  // 只提取checkout-开头的头字段,按key排序
  const sortedHeaderKeys = Object.keys(checkoutHeaders)
    .filter(key => key.startsWith('checkout-'))
    .sort();
  
  // 拼接头字段为"key:value"格式,再拼接请求体JSON字符串
  const hmacPayload = sortedHeaderKeys
    .map(key => `${key}:${checkoutHeaders[key]}`)
    .concat(requestBody ? JSON.stringify(requestBody) : '')
    .join('\n');

  return crypto.createHmac('sha256', secret).update(hmacPayload).digest('hex');
};

const server = http.createServer(async (req, res) => {
  // 仅处理POST请求(前端提交订单参数)
  if (req.method !== 'POST') {
    res.writeHead(405, {'Content-Type': 'application/json'});
    return res.end(JSON.stringify({error: 'Method Not Allowed'}));
  }

  // 读取前端发送的订单参数
  let requestBody = '';
  req.on('data', chunk => {
    requestBody += chunk.toString();
  });

  req.on('end', () => {
    try {
      const orderData = JSON.parse(requestBody);

      // 生成随机nonce(16位随机数字字符串)
      const nonce = Math.floor(Math.random() * 10000000000000000).toString();
      // 生成符合ISO 8601格式的实时时间戳
      const timestamp = new Date().toISOString();

      // 构建Paytrail要求的请求头参数
      const checkoutHeaders = {
        'checkout-account': ACCOUNT,
        'checkout-algorithm': 'sha256',
        'checkout-method': 'POST',
        'checkout-nonce': nonce,
        'checkout-timestamp': timestamp,
      };

      // 计算HMAC哈希
      const hash = calculateHmac(SECRET, checkoutHeaders, orderData);

      // 返回给前端所需的验证参数
      res.writeHead(200, {'Content-Type': 'application/json'});
      res.end(JSON.stringify({
        ...checkoutHeaders,
        hash: hash
      }));
    } catch (error) {
      res.writeHead(400, {'Content-Type': 'application/json'});
      res.end(JSON.stringify({error: 'Invalid request body'}));
    }
  });
});

server.listen(PORT, () => {
  console.log(`服务器已启动,端口:${PORT}`);
});

二、前端(Vue)实现

前端需要先向自有服务器请求获取验证参数,再使用这些参数向Paytrail发送创建订单的请求,注意请求体字段要严格符合Paytrail的要求。

<template>
  <div>
    <button @click="createPayment">创建支付订单</button>
  </div>
</template>

<script setup>
import axios from 'axios'

const createPayment = async () => {
  try {
    // 1. 准备订单数据(根据实际业务生成)
    const orderData = {
      stamp: `order-${Date.now()}`, // 商户侧唯一订单标识
      reference: 'ORDER-20240501-001', // 订单参考号
      amount: 1525, // 金额,单位为分(15.25 EUR)
      currency: 'EUR',
      language: 'FI',
      items: [
        {
          unitPrice: 1525,
          units: 1,
          vatPercentage: 24,
          productCode: '#1234',
          deliveryDate: '2024-06-01',
        },
      ],
      customer: {
        email: 'test.customer@example.com',
      },
      redirectUrls: {
        success: 'http://localhost:8080/web/success',
        cancel: 'http://localhost:8080/web/cancel',
      },
      notificationUrl: 'http://your-server-domain/web/notification' // 支付结果通知地址
    };

    // 2. 向自有服务器请求获取Paytrail验证参数
    const serverResponse = await axios.post('http://localhost:3000/', orderData);
    const { hash, ...checkoutHeaders } = serverResponse.data;

    // 3. 向Paytrail发送创建订单请求
    const paytrailResponse = await axios.post(
      'https://services.paytrail.com/payments', // Paytrail正确的创建订单接口地址
      orderData,
      {
        headers: {
          'Content-Type': 'application/json; charset=utf-8',
          ...checkoutHeaders,
          'checkout-signature': hash // Paytrail要求的签名头字段
        }
      }
    );

    // 4. 跳转到Paytrail支付页面
    if (paytrailResponse.data.href) {
      window.location.href = paytrailResponse.data.href;
    }
  } catch (error) {
    console.error('支付创建失败:', error.response?.data || error.message);
  }
}
</script>

关键注意事项

  • 参数一致性:前端发送给自有服务器的订单数据,必须和后续发送给Paytrail的完全一致,否则哈希验证会失败。
  • Nonce与Timestamp:每次请求必须生成新的随机nonce和实时timestamp,不能硬编码,否则Paytrail会拒绝请求。
  • 接口地址:Paytrail创建订单的正确接口是https://services.paytrail.com/payments,请勿使用错误地址。
  • 签名头字段:Paytrail要求的签名头是checkout-signature,需将计算出的hash赋值给该字段。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.07.20 04:12:40