通知
本页概述了通知服务,该服务会向您发送有关欺诈性在线交易的更新信息。
概述
欺诈防范 API 通知解决方案可让您比以往更紧密地与 欺诈防范 集成。如发生影响您业务的变更,欺诈防范 将通过标准 POST 消息直接向您的系统推送变更详情。借助我们的推送通知,您可以了解情况、简化操作并确保您的业务免受欺诈。
我们目前支持订单采购和帐户在线事件的通知。因此,如果分析专员已对交易进行了审查,您将立即收到有关决议和建议措施的通知。
消息模式和详细信息
本章节将深入探讨消息的结构组成,其中包括两个主要部分:封装和通知有效负载。封装包含通知元数据,而通知有效负载则包含通知的复杂详细信息。让我们来深入探讨一下这些组成部分。
封装对象模式
字段 | 类型 | 可能的值 | 是否可为 null | 示例 | 说明 |
---|---|---|---|---|---|
event_name | 字符串 | MERCHANTSHIELD_FRAUD | false | MERCHANTSHIELD_FRAUD | 活动名称,永远是 MERCHANTSHIELD_FRAUD 。 |
creation_time | 字符串 | 数据时间 (UTC) | false | 2024-01-18T10:29:20.484649887Z | 创建通知事件的时间。 |
notification_id | 字符串 | GUID | false | d72ac517-f0a7-4a65-8547-250cf81ce440 | 专属通知 ID。 |
payload | 有效负载 | Payload 对象 | false | 实际通知有效负载。请参阅下面的有效负载对象模式说明。 |
有效负载对象模式
字段 | 类型 | 可能的值 | 是否可为 null | 示例 | 说明 |
---|---|---|---|---|---|
risk_id | 字符串 | GUID | false | fdeaf9dc-ac79-4c2f-a148-0e722374aef1 | 风险交易唯一标识符。 |
entity_type | 字符串 | BookingFraud 、Account | false | BookingFraud | 实体类型。 |
entity_id | 字符串 | GUID | false | be8076bc-d17c-45fa-84e6-0fe6a609f3ac | 受影响的在线预订或帐户盗用交易的参考编号。 |
决策 | 字符串 | PASS、FAIL | true | PASS | 分析专员在审查交易后做出的决定。 |
decision_date_time | 字符串 | 数据时间 (UTC) | false | 2024-03-07T22:28:33.552Z | 分析专员做出决定的日期和时间(UTC 格式)。 |
recommended_actions | 字符串组 | 对于 BookingFraud 实体类型:RELEASE 、CANCEL_FULL_REFUND 、CANCEL_NO_REFUND <hr> 对于 Account 实体类型:TERMINATE_ACTIVE_SESSIONS 、HARD_PASSWORD_RESET | 可能为空 | ["CANCEL_FULL_REFUND"] | 建议采取的补救措施清单。 |
partner_account_id | 字符串 | GUID | false | ff1fddb1-29ac-41a1-8c0b-6db5932c913d | 您的合作伙伴帐户 ID。 |
每条消息均为包含 JSON 消息正文的 HTTPS POST 请求。
预订欺诈更新示例
{
"event_name": "MERCHANTSHIELD_FRAUD",
"creation_time": "2024-01-18T10:29:20.484649887Z",
"notification_id": "0597ae4c-b6d2-4d47-ba58-36534e04f1cf",
"payload": {
"risk_id": "9beabb6d-77b9-474e-852a-3cb9fedabb3a",
"entity_type": "BookingFraud",
"entity_id": "1e5092ad-4440-40cf-9a14-0bf76ced339c",
"decision_date_time": "2024-03-07T22:28:33.552Z",
"decision": "PASS",
"recommended_actions": [
"RELEASE"
],
"partner_account_id": "972edd1c-b50f-4d7e-b5bb-05212aa20d03"
}
}
帐户盗用更新示例
{
"event_name": "MERCHANTSHIELD_FRAUD",
"creation_time": "2024-01-18T10:29:20.484649887Z",
"notification_id": "c9235ccb-8716-4ac3-a3ad-ef96042aa32a",
"payload": {
"risk_id": "d2f0d5ab-cda1-484e-9507-e0fcf81960dc",
"entity_type": "Account",
"entity_id": "13538ba1-df41-446c-8266-4f325e4ef264",
"decision_date_time": "2024-03-07T22:28:33.552Z",
"decision": "PASS",
"recommended_actions": [],
"partner_account_id": "34f8df88-26f3-48f2-a81b-12fae9306192"
}
}
集成
接收消息
要开始接收通知,您将需要建立一个端点,该端点可以接受将推送到您的端点的 POST 消息。端点应该:
- 可公开访问。
- 启用 HTTPS 和 TLS 1.2 或更高版本。
- 配置受大多数现代应用程序信任的有效 TLS 证书(自签证书可能不受信任)。
与您的 欺诈防范 集成顾问合作,进行设置并向其提供下列信息:
- 用于处理消息的端点 URL。
我们正在努力向您提供各种自助服务工具,对您的集成进行测试。到那个时候,您的集成顾问可以帮助您进行测试预订,以确认您是否收到订阅的离线事件的通知。
重要的配置说明
- 欺诈防范 使用基于云的服务器 - 可确保您的侦听程序端点配置为接收来自不同的可能 IP 地址的通知推送。
- 如果您要变更端点 URL,在我们验证您的新 URL 是否可以接收通知推送之前,您必须使原始 URL 处于有效状态。在进行此类变更之前,请联系您的 欺诈防范 代表。
- 只能使用一个 URL 进行通知。
处理消息
认识到迅速采取措施的重要性。仔细查看回调请求的详细信息,确保您综合处理实体、决定和建议采取的补救措施。
无法送达的消息
如果我们在向您的端点送达信息时遇到困难,我们会建立一个协议来自动尝试重新发送。这将在延迟 5 秒后开始,以指数级回退的方式尝试五次。
确认
要确认事件,您需要将标头中的签名 SHA512 哈希值与您使用 API 密钥、共享秘钥和请求标头中的时间戳生成的进行比较。
确保验证 api-key
标头实际上是在 欺诈防范 上线流程中提供给您的 API 密钥。
保护您的共享秘钥
为您提供的共享秘钥对于您的请求数据的安全性至关重要 – 请将其视为密码。请勿在任何可公开访问的网站或 App 代码中包含原始值。当您获准可以整合 欺诈防范 之后,您将会获得共享秘钥和 API 密钥。
回调请求标头结构
标头名称 | 示例值 |
---|---|
x-eg-notification-signature | Sha256=e3b0c44298fc1c149afbf4c8996fb92427ae41e4649b934ca495991b7852b855 |
x-eg-notification-timestamp | 13536472536 |
api-key | c05b7b59-0a29-4cb1-9b09-d36954c9a605 |
根据签名步骤验证哈希值
准备
signed_payload
字符串:- signed_payload 字符串是通过连接创建的:
- 时间戳是
x-eg-notification-timestamp
标头中的字符串 .
字符。- 实际的 JSON 有效负载(即请求正文)
- 时间戳是
- signed_payload 字符串是通过连接创建的:
确定预期签名:
- 使用 SHA256 哈希函数计算 HMAC。使用端点的签名密钥作为密钥,使用
signed_payload
字符串作为消息。
- 使用 SHA256 哈希函数计算 HMAC。使用端点的签名密钥作为密钥,使用
比较签名: 将标头中的签名与预期签名进行比较。对于相等匹配,计算当前时间戳与接收到的时间戳之间的差值,然后判断该差值是否在容许范围内。
Java 示例
import javax.crypto.Mac;
import javax.crypto.spec.SecretKeySpec;
import java.security.InvalidKeyException;
import java.security.NoSuchAlgorithmException;
import java.util.Base64;
public class TestApplication {
public static final String HMAC_SHA_256 = "HmacSHA256";
public static void main(String[] args){
// extracted data from the notification request payload
// x-eg-notification-timestamp: 1634021234
String eg_timestamp_header_value = "timestamp_header_value";
// x-eg-notification-signature: SHA256=signature_header_value
String eg_signature_header_value = "signature_header_value";
// api-key: api_key_to_validate
String api_key_header_value = "api_key_to_validate";
// json payload
String json_payload = "json_payload";
// your api key
String api_key = "your_api_key";
// signing secret from the secret store
String your_endpoints_signing_secret = "your_endpoints_signing_secret";
if (!api_key.equals(api_key_header_value)) {
throw new RuntimeException("Failure! Api key does not match expected value!");
}
try {
// Prepare the `signed_payload` string
String signed_payload = eg_timestamp_header_value + "." + json_payload;
// Determine the expected signature
String expected_signature = generate_hmac(signed_payload,
your_endpoints_signing_secret);
if (!eg_signature_header_value.equals(expected_signature)) {
throw new RuntimeException("Failure! Signature does not match expected value!");
}
System.out.println("Success! The generated signature matches the expected value.");
} catch (NoSuchAlgorithmException | InvalidKeyException e) {
System.err.println("Error generating HMAC: " + e.getMessage());
}
}
/**
* Generates a hashed message authentication code using the HMAC-SHA256 algorithm.
* This method may throw an Exception when the HMAC-SHA256 algorithm is not supported
* or the secret key is invalid.
*
* @param message The message to be encoded
* @param secret The secret key
* @return The Base64 encoded HMAC
*/
public static String generate_hmac(String message, String secret)
throws NoSuchAlgorithmException, InvalidKeyException {
Mac sha256_hmac = Mac.getInstance(HMAC_SHA_256);
SecretKeySpec secret_key_spec = new SecretKeySpec(secret.getBytes(), HMAC_SHA_256);
sha256_hmac.init(secret_key_spec);
byte[] hmac = sha256_hmac.doFinal(message.getBytes());
return Base64.getEncoder().encodeToString(hmac);
}
}