接入教程
1. 在Adyen后台配置webhook接收地址
2. 监听POST请求获取报表生成通知
3. 解析通知中的reportId参数
4. 使用reportId发起HTTP GET请求下载报表
5. 或登录客户区域手动下载报表文件
Python Webhook验证与处理
import hashlib
import hmac
import json
from flask import Flask, request
app = Flask(__name__)
WEBHOOK_SECRET = 'YOUR_WEBHOOK_SECRET'
@app.route('/webhook', methods=['POST'])
def handle_webhook():
# 验证签名
signature = request.headers.get('Adyen-Signature')
payload = request.get_data(as_text=True)
# 使用HMAC验证签名(示例逻辑)
expected_signature = hmac.new(
WEBHOOK_SECRET.encode(),
payload.encode(),
hashlib.sha256
).hexdigest()
if not hmac.compare_digest(signature, expected_signature):
return 'Invalid signature', 401
# 处理通知
data = json.loads(payload)
report_id = data.get('reportId')
# 下载报表(示例)
import requests
download_url = f'https://api.example.com/reports/{report_id}/download'
headers = {'Authorization': 'Bearer YOUR_API_KEY'}
response = requests.get(download_url, headers=headers)
if response.status_code == 200:
# 保存报表文件
with open(f'report_{report_id}.csv', 'wb') as f:
f.write(response.content)
return 'Report processed', 200
return 'Download failed', 500
if __name__ == '__main__':
app.run(port=3000)
PHP Webhook接收实现
<?php
$webhookSecret = 'YOUR_WEBHOOK_SECRET';
$apiKey = 'YOUR_API_KEY';
// 获取请求头和内容
$signature = $_SERVER['HTTP_ADYEN_SIGNATURE'] ?? '';
$payload = file_get_contents('php://input');
// 验证签名
$expectedSignature = hash_hmac('sha256', $payload, $webhookSecret);
if (!hash_equals($signature, $expectedSignature)) {
http_response_code(401);
exit('Invalid signature');
}
// 解析通知
$data = json_decode($payload, true);
$reportId = $data['reportId'] ?? '';
if ($reportId) {
// 下载报表
$downloadUrl = "https://api.example.com/reports/{$reportId}/download";
$ch = curl_init();
curl_setopt($ch, CURLOPT_URL, $downloadUrl);
curl_setopt($ch, CURLOPT_RETURNTRANSFER, true);
curl_setopt($ch, CURLOPT_HTTPHEADER, [
'Authorization: Bearer ' . $apiKey
]);
$reportContent = curl_exec($ch);
$httpCode = curl_getinfo($ch, CURLINFO_HTTP_CODE);
curl_close($ch);
if ($httpCode === 200 && $reportContent) {
// 保存文件
file_put_contents("report_{$reportId}.csv", $reportContent);
http_response_code(200);
echo 'Report downloaded';
} else {
http_response_code(500);
echo 'Download failed';
}
} else {
http_response_code(400);
echo 'Invalid payload';
}
?>
Node.js Webhook服务器
const express = require('express');
const crypto = require('crypto');
const axios = require('axios');
const app = express();
const WEBHOOK_SECRET = 'YOUR_WEBHOOK_SECRET';
const API_KEY = 'YOUR_API_KEY';
app.use(express.text({ type: '*/*' }));
app.post('/webhook', async (req, res) => {
try {
const signature = req.headers['adyen-signature'];
const payload = req.body;
// 验证签名
const expectedSignature = crypto
.createHmac('sha256', WEBHOOK_SECRET)
.update(payload)
.digest('hex');
if (!crypto.timingSafeEqual(
Buffer.from(signature),
Buffer.from(expectedSignature)
)) {
return res.status(401).send('Invalid signature');
}
// 解析通知
const data = JSON.parse(payload);
const reportId = data.reportId;
// 下载报表
const downloadUrl = `https://api.example.com/reports/${reportId}/download`;
const response = await axios.get(downloadUrl, {
headers: {
'Authorization': `Bearer ${API_KEY}`
},
responseType: 'stream'
});
// 保存文件(示例)
const fs = require('fs');
const writer = fs.createWriteStream(`report_${reportId}.csv`);
response.data.pipe(writer);
writer.on('finish', () => {
res.status(200).send('Report processed');
});
writer.on('error', () => {
res.status(500).send('Save failed');
});
} catch (error) {
console.error('Webhook error:', error);
res.status(500).send('Processing failed');
}
});
app.listen(3000, () => {
console.log('Webhook server listening on port 3000');
});
常见问题
Webhook通知的签名如何验证?
Adyen使用HMAC SHA256算法生成签名,签名位于'Adyen-Signature'请求头中。您需要使用相同的密钥和算法计算载荷的签名,并进行比对验证。
报表下载失败应如何处理?
建议检查API密钥权限、报表ID有效性及网络连接。可设置重试机制,若持续失败请联系Adyen技术支持。下载链接通常有时效性,请及时处理通知。
Webhook服务器需要满足哪些要求?
服务器需支持HTTPS、正确处理POST请求、及时返回2xx状态码(避免重试)。建议设置超时处理、日志记录和监控告警机制以保证可靠性。
Aitishiku.com