@alogram/payrisk 0.1.6
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/AI.md +37 -0
- package/LICENSE +201 -0
- package/README.md +129 -0
- package/dist/_generated/apis/PayriskApi.d.ts +108 -0
- package/dist/_generated/apis/PayriskApi.js +342 -0
- package/dist/_generated/apis/index.d.ts +1 -0
- package/dist/_generated/apis/index.js +19 -0
- package/dist/_generated/index.d.ts +3 -0
- package/dist/_generated/index.js +21 -0
- package/dist/_generated/models/Account.d.ts +59 -0
- package/dist/_generated/models/Account.js +57 -0
- package/dist/_generated/models/AccountCheckRequest.d.ts +64 -0
- package/dist/_generated/models/AccountCheckRequest.js +72 -0
- package/dist/_generated/models/AvsResultEnum.d.ts +54 -0
- package/dist/_generated/models/AvsResultEnum.js +82 -0
- package/dist/_generated/models/BankTransfer.d.ts +39 -0
- package/dist/_generated/models/BankTransfer.js +59 -0
- package/dist/_generated/models/Card.d.ts +93 -0
- package/dist/_generated/models/Card.js +81 -0
- package/dist/_generated/models/CardNetworkEnum.d.ts +30 -0
- package/dist/_generated/models/CardNetworkEnum.js +58 -0
- package/dist/_generated/models/CategorySignal.d.ts +45 -0
- package/dist/_generated/models/CategorySignal.js +55 -0
- package/dist/_generated/models/ChannelEnum.d.ts +28 -0
- package/dist/_generated/models/ChannelEnum.js +56 -0
- package/dist/_generated/models/CheckRequest.d.ts +66 -0
- package/dist/_generated/models/CheckRequest.js +72 -0
- package/dist/_generated/models/ConfidenceEnum.d.ts +26 -0
- package/dist/_generated/models/ConfidenceEnum.js +54 -0
- package/dist/_generated/models/Crypto.d.ts +39 -0
- package/dist/_generated/models/Crypto.js +59 -0
- package/dist/_generated/models/CvvResultEnum.d.ts +33 -0
- package/dist/_generated/models/CvvResultEnum.js +61 -0
- package/dist/_generated/models/DecisionResponse.d.ts +128 -0
- package/dist/_generated/models/DecisionResponse.js +107 -0
- package/dist/_generated/models/DeviceInfo.d.ts +54 -0
- package/dist/_generated/models/DeviceInfo.js +56 -0
- package/dist/_generated/models/EntityIds.d.ts +113 -0
- package/dist/_generated/models/EntityIds.js +70 -0
- package/dist/_generated/models/EntryMethodEnum.d.ts +30 -0
- package/dist/_generated/models/EntryMethodEnum.js +58 -0
- package/dist/_generated/models/FraudScore.d.ts +52 -0
- package/dist/_generated/models/FraudScore.js +58 -0
- package/dist/_generated/models/Identity.d.ts +71 -0
- package/dist/_generated/models/Identity.js +57 -0
- package/dist/_generated/models/Integrity.d.ts +68 -0
- package/dist/_generated/models/Integrity.js +58 -0
- package/dist/_generated/models/Interaction.d.ts +59 -0
- package/dist/_generated/models/Interaction.js +60 -0
- package/dist/_generated/models/InteractionTypeEnum.d.ts +29 -0
- package/dist/_generated/models/InteractionTypeEnum.js +57 -0
- package/dist/_generated/models/Invoice.d.ts +39 -0
- package/dist/_generated/models/Invoice.js +59 -0
- package/dist/_generated/models/IpInfo.d.ts +101 -0
- package/dist/_generated/models/IpInfo.js +78 -0
- package/dist/_generated/models/KycCheckRequest.d.ts +64 -0
- package/dist/_generated/models/KycCheckRequest.js +74 -0
- package/dist/_generated/models/KycPayload.d.ts +84 -0
- package/dist/_generated/models/KycPayload.js +82 -0
- package/dist/_generated/models/MerchantContext.d.ts +38 -0
- package/dist/_generated/models/MerchantContext.js +50 -0
- package/dist/_generated/models/OrderContext.d.ts +60 -0
- package/dist/_generated/models/OrderContext.js +65 -0
- package/dist/_generated/models/PayerTypeEnum.d.ts +25 -0
- package/dist/_generated/models/PayerTypeEnum.js +53 -0
- package/dist/_generated/models/PaymentAuthorizationOutcome.d.ts +38 -0
- package/dist/_generated/models/PaymentAuthorizationOutcome.js +50 -0
- package/dist/_generated/models/PaymentCaptureOutcome.d.ts +42 -0
- package/dist/_generated/models/PaymentCaptureOutcome.js +60 -0
- package/dist/_generated/models/PaymentCardTypeEnum.d.ts +26 -0
- package/dist/_generated/models/PaymentCardTypeEnum.js +54 -0
- package/dist/_generated/models/PaymentChargeback.d.ts +32 -0
- package/dist/_generated/models/PaymentChargeback.js +48 -0
- package/dist/_generated/models/PaymentChargebackOutcome.d.ts +42 -0
- package/dist/_generated/models/PaymentChargebackOutcome.js +60 -0
- package/dist/_generated/models/PaymentDisputeOutcome.d.ts +43 -0
- package/dist/_generated/models/PaymentDisputeOutcome.js +61 -0
- package/dist/_generated/models/PaymentEvent.d.ts +72 -0
- package/dist/_generated/models/PaymentEvent.js +68 -0
- package/dist/_generated/models/PaymentEventType.d.ts +30 -0
- package/dist/_generated/models/PaymentEventType.js +58 -0
- package/dist/_generated/models/PaymentMethod.d.ts +39 -0
- package/dist/_generated/models/PaymentMethod.js +73 -0
- package/dist/_generated/models/PaymentMethodBase.d.ts +44 -0
- package/dist/_generated/models/PaymentMethodBase.js +64 -0
- package/dist/_generated/models/PaymentOutcome.d.ts +69 -0
- package/dist/_generated/models/PaymentOutcome.js +64 -0
- package/dist/_generated/models/PaymentRealtimeTypeEnum.d.ts +28 -0
- package/dist/_generated/models/PaymentRealtimeTypeEnum.js +56 -0
- package/dist/_generated/models/PaymentRefundOutcome.d.ts +41 -0
- package/dist/_generated/models/PaymentRefundOutcome.js +59 -0
- package/dist/_generated/models/PaymentWalletTypeEnum.d.ts +28 -0
- package/dist/_generated/models/PaymentWalletTypeEnum.js +56 -0
- package/dist/_generated/models/PostalAddress.d.ts +65 -0
- package/dist/_generated/models/PostalAddress.js +58 -0
- package/dist/_generated/models/Problem.d.ts +62 -0
- package/dist/_generated/models/Problem.js +62 -0
- package/dist/_generated/models/Purchase.d.ts +122 -0
- package/dist/_generated/models/Purchase.js +88 -0
- package/dist/_generated/models/PurchaseInitiatorEnum.d.ts +25 -0
- package/dist/_generated/models/PurchaseInitiatorEnum.js +53 -0
- package/dist/_generated/models/PurchaseSequenceEnum.d.ts +25 -0
- package/dist/_generated/models/PurchaseSequenceEnum.js +53 -0
- package/dist/_generated/models/PurchaseUsageEnum.d.ts +27 -0
- package/dist/_generated/models/PurchaseUsageEnum.js +55 -0
- package/dist/_generated/models/Realtime.d.ts +46 -0
- package/dist/_generated/models/Realtime.js +62 -0
- package/dist/_generated/models/ReasonDetail.d.ts +57 -0
- package/dist/_generated/models/ReasonDetail.js +63 -0
- package/dist/_generated/models/RiskBreakdown.d.ts +51 -0
- package/dist/_generated/models/RiskBreakdown.js +55 -0
- package/dist/_generated/models/RiskCategoryEnum.d.ts +27 -0
- package/dist/_generated/models/RiskCategoryEnum.js +55 -0
- package/dist/_generated/models/RiskLevelEnum.d.ts +26 -0
- package/dist/_generated/models/RiskLevelEnum.js +54 -0
- package/dist/_generated/models/ScaMethodEnum.d.ts +30 -0
- package/dist/_generated/models/ScaMethodEnum.js +58 -0
- package/dist/_generated/models/ScoreRecord.d.ts +107 -0
- package/dist/_generated/models/ScoreRecord.js +92 -0
- package/dist/_generated/models/ScoresSuccessResponse.d.ts +39 -0
- package/dist/_generated/models/ScoresSuccessResponse.js +51 -0
- package/dist/_generated/models/SignalsAccountVariant.d.ts +53 -0
- package/dist/_generated/models/SignalsAccountVariant.js +69 -0
- package/dist/_generated/models/SignalsInteractionVariant.d.ts +53 -0
- package/dist/_generated/models/SignalsInteractionVariant.js +69 -0
- package/dist/_generated/models/SignalsRequest.d.ts +28 -0
- package/dist/_generated/models/SignalsRequest.js +53 -0
- package/dist/_generated/models/StoredCredentialContext.d.ts +47 -0
- package/dist/_generated/models/StoredCredentialContext.js +55 -0
- package/dist/_generated/models/ThreeDSData.d.ts +68 -0
- package/dist/_generated/models/ThreeDSData.js +66 -0
- package/dist/_generated/models/Wallet.d.ts +46 -0
- package/dist/_generated/models/Wallet.js +62 -0
- package/dist/_generated/models/index.d.ts +62 -0
- package/dist/_generated/models/index.js +80 -0
- package/dist/_generated/runtime.d.ts +184 -0
- package/dist/_generated/runtime.js +338 -0
- package/dist/client.d.ts +69 -0
- package/dist/client.js +281 -0
- package/dist/exceptions.d.ts +24 -0
- package/dist/exceptions.js +59 -0
- package/dist/index.d.ts +5 -0
- package/dist/index.js +23 -0
- package/dist/testing.d.ts +24 -0
- package/dist/testing.js +100 -0
- package/dist/webhooks.d.ts +10 -0
- package/dist/webhooks.js +32 -0
- package/examples/asyncSignalIngestion.ts +52 -0
- package/examples/checkRisk.ts +26 -0
- package/examples/productionErrorHandling.ts +52 -0
- package/examples/webhookVerification.ts +29 -0
- package/package.json +64 -0
|
@@ -0,0 +1,24 @@
|
|
|
1
|
+
export declare class AlogramError extends Error {
|
|
2
|
+
status?: number | undefined;
|
|
3
|
+
body?: any | undefined;
|
|
4
|
+
constructor(message: string, status?: number | undefined, body?: any | undefined);
|
|
5
|
+
}
|
|
6
|
+
export declare class AuthenticationError extends AlogramError {
|
|
7
|
+
constructor(message: string, status?: number, body?: any);
|
|
8
|
+
}
|
|
9
|
+
export declare class RateLimitError extends AlogramError {
|
|
10
|
+
constructor(message: string, status?: number, body?: any);
|
|
11
|
+
}
|
|
12
|
+
export declare class ValidationError extends AlogramError {
|
|
13
|
+
constructor(message: string, status?: number, body?: any);
|
|
14
|
+
}
|
|
15
|
+
export declare class InternalServerError extends AlogramError {
|
|
16
|
+
constructor(message: string, status?: number, body?: any);
|
|
17
|
+
}
|
|
18
|
+
/**
|
|
19
|
+
* 🔒 Thrown when an SDK method is called using a key that does not have the required trust scope.
|
|
20
|
+
* (e.g., calling checkRisk with a pk_... key)
|
|
21
|
+
*/
|
|
22
|
+
export declare class ScopedAccessError extends AlogramError {
|
|
23
|
+
constructor(message: string);
|
|
24
|
+
}
|
|
@@ -0,0 +1,59 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
// Copyright (c) 2025 Alogram Inc.
|
|
3
|
+
// All rights reserved.
|
|
4
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
5
|
+
exports.ScopedAccessError = exports.InternalServerError = exports.ValidationError = exports.RateLimitError = exports.AuthenticationError = exports.AlogramError = void 0;
|
|
6
|
+
class AlogramError extends Error {
|
|
7
|
+
constructor(message, status, body) {
|
|
8
|
+
super(message);
|
|
9
|
+
this.status = status;
|
|
10
|
+
this.body = body;
|
|
11
|
+
this.name = 'AlogramError';
|
|
12
|
+
Object.setPrototypeOf(this, AlogramError.prototype);
|
|
13
|
+
}
|
|
14
|
+
}
|
|
15
|
+
exports.AlogramError = AlogramError;
|
|
16
|
+
class AuthenticationError extends AlogramError {
|
|
17
|
+
constructor(message, status, body) {
|
|
18
|
+
super(message, status, body);
|
|
19
|
+
this.name = 'AuthenticationError';
|
|
20
|
+
Object.setPrototypeOf(this, AuthenticationError.prototype);
|
|
21
|
+
}
|
|
22
|
+
}
|
|
23
|
+
exports.AuthenticationError = AuthenticationError;
|
|
24
|
+
class RateLimitError extends AlogramError {
|
|
25
|
+
constructor(message, status, body) {
|
|
26
|
+
super(message, status, body);
|
|
27
|
+
this.name = 'RateLimitError';
|
|
28
|
+
Object.setPrototypeOf(this, RateLimitError.prototype);
|
|
29
|
+
}
|
|
30
|
+
}
|
|
31
|
+
exports.RateLimitError = RateLimitError;
|
|
32
|
+
class ValidationError extends AlogramError {
|
|
33
|
+
constructor(message, status, body) {
|
|
34
|
+
super(message, status, body);
|
|
35
|
+
this.name = 'ValidationError';
|
|
36
|
+
Object.setPrototypeOf(this, ValidationError.prototype);
|
|
37
|
+
}
|
|
38
|
+
}
|
|
39
|
+
exports.ValidationError = ValidationError;
|
|
40
|
+
class InternalServerError extends AlogramError {
|
|
41
|
+
constructor(message, status, body) {
|
|
42
|
+
super(message, status, body);
|
|
43
|
+
this.name = 'InternalServerError';
|
|
44
|
+
Object.setPrototypeOf(this, InternalServerError.prototype);
|
|
45
|
+
}
|
|
46
|
+
}
|
|
47
|
+
exports.InternalServerError = InternalServerError;
|
|
48
|
+
/**
|
|
49
|
+
* 🔒 Thrown when an SDK method is called using a key that does not have the required trust scope.
|
|
50
|
+
* (e.g., calling checkRisk with a pk_... key)
|
|
51
|
+
*/
|
|
52
|
+
class ScopedAccessError extends AlogramError {
|
|
53
|
+
constructor(message) {
|
|
54
|
+
super(message, 403);
|
|
55
|
+
this.name = 'ScopedAccessError';
|
|
56
|
+
Object.setPrototypeOf(this, ScopedAccessError.prototype);
|
|
57
|
+
}
|
|
58
|
+
}
|
|
59
|
+
exports.ScopedAccessError = ScopedAccessError;
|
package/dist/index.d.ts
ADDED
package/dist/index.js
ADDED
|
@@ -0,0 +1,23 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
// Copyright (c) 2025 Alogram Inc.
|
|
3
|
+
// All rights reserved.
|
|
4
|
+
var __createBinding = (this && this.__createBinding) || (Object.create ? (function(o, m, k, k2) {
|
|
5
|
+
if (k2 === undefined) k2 = k;
|
|
6
|
+
var desc = Object.getOwnPropertyDescriptor(m, k);
|
|
7
|
+
if (!desc || ("get" in desc ? !m.__esModule : desc.writable || desc.configurable)) {
|
|
8
|
+
desc = { enumerable: true, get: function() { return m[k]; } };
|
|
9
|
+
}
|
|
10
|
+
Object.defineProperty(o, k2, desc);
|
|
11
|
+
}) : (function(o, m, k, k2) {
|
|
12
|
+
if (k2 === undefined) k2 = k;
|
|
13
|
+
o[k2] = m[k];
|
|
14
|
+
}));
|
|
15
|
+
var __exportStar = (this && this.__exportStar) || function(m, exports) {
|
|
16
|
+
for (var p in m) if (p !== "default" && !Object.prototype.hasOwnProperty.call(exports, p)) __createBinding(exports, m, p);
|
|
17
|
+
};
|
|
18
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
19
|
+
__exportStar(require("./client"), exports);
|
|
20
|
+
__exportStar(require("./exceptions"), exports);
|
|
21
|
+
__exportStar(require("./webhooks"), exports);
|
|
22
|
+
__exportStar(require("./testing"), exports);
|
|
23
|
+
__exportStar(require("./_generated/models/index"), exports);
|
|
@@ -0,0 +1,24 @@
|
|
|
1
|
+
import { DecisionResponse } from './_generated';
|
|
2
|
+
/**
|
|
3
|
+
* 🛠️ **MockRiskClient**
|
|
4
|
+
*
|
|
5
|
+
* A zero-dependency mock implementation of the Alogram Risk Client for local testing.
|
|
6
|
+
*/
|
|
7
|
+
export declare class MockRiskClient {
|
|
8
|
+
private _calls;
|
|
9
|
+
private _queuedResponses;
|
|
10
|
+
private _defaultDecision;
|
|
11
|
+
private _defaultScore;
|
|
12
|
+
private _delayMs;
|
|
13
|
+
setDefaultDecision(decision: string, score?: number): void;
|
|
14
|
+
private getTimestamp;
|
|
15
|
+
queueDecision(decision: string, score?: number, reason?: string): void;
|
|
16
|
+
queueError(error: Error): void;
|
|
17
|
+
setDelay(ms: number): void;
|
|
18
|
+
get callCount(): number;
|
|
19
|
+
get calls(): Array<any>;
|
|
20
|
+
private _handleCall;
|
|
21
|
+
checkRisk(request: any): Promise<DecisionResponse>;
|
|
22
|
+
ingestSignals(request: any): Promise<void>;
|
|
23
|
+
ingestEvent(event: any): Promise<void>;
|
|
24
|
+
}
|
package/dist/testing.js
ADDED
|
@@ -0,0 +1,100 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
// Copyright (c) 2025 Alogram Inc.
|
|
3
|
+
// All rights reserved.
|
|
4
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
5
|
+
exports.MockRiskClient = void 0;
|
|
6
|
+
/**
|
|
7
|
+
* 🛠️ **MockRiskClient**
|
|
8
|
+
*
|
|
9
|
+
* A zero-dependency mock implementation of the Alogram Risk Client for local testing.
|
|
10
|
+
*/
|
|
11
|
+
class MockRiskClient {
|
|
12
|
+
constructor() {
|
|
13
|
+
this._calls = [];
|
|
14
|
+
this._queuedResponses = [];
|
|
15
|
+
this._defaultDecision = 'approve';
|
|
16
|
+
this._defaultScore = 0.1;
|
|
17
|
+
this._delayMs = 0;
|
|
18
|
+
}
|
|
19
|
+
setDefaultDecision(decision, score = 0.1) {
|
|
20
|
+
this._defaultDecision = decision.toLowerCase();
|
|
21
|
+
this._defaultScore = score;
|
|
22
|
+
}
|
|
23
|
+
getTimestamp() {
|
|
24
|
+
return new Date().toISOString();
|
|
25
|
+
}
|
|
26
|
+
queueDecision(decision, score = 0.1, reason) {
|
|
27
|
+
const resp = {
|
|
28
|
+
assessmentId: `mock-${Math.random().toString(36).substring(2, 14)}`,
|
|
29
|
+
decision: decision.toLowerCase(),
|
|
30
|
+
decisionAt: this.getTimestamp(),
|
|
31
|
+
riskScore: score,
|
|
32
|
+
fraudScore: {
|
|
33
|
+
riskLevel: 'low',
|
|
34
|
+
score: score,
|
|
35
|
+
explanation: 'Mocked response',
|
|
36
|
+
},
|
|
37
|
+
reasons: reason ? [{
|
|
38
|
+
code: 'MOCK_CODE',
|
|
39
|
+
category: 'behavior',
|
|
40
|
+
displayName: 'Mock Reason',
|
|
41
|
+
description: reason,
|
|
42
|
+
}] : [],
|
|
43
|
+
};
|
|
44
|
+
this._queuedResponses.push(resp);
|
|
45
|
+
}
|
|
46
|
+
queueError(error) {
|
|
47
|
+
this._queuedResponses.push(error);
|
|
48
|
+
}
|
|
49
|
+
setDelay(ms) {
|
|
50
|
+
this._delayMs = ms;
|
|
51
|
+
}
|
|
52
|
+
get callCount() {
|
|
53
|
+
return this._calls.length;
|
|
54
|
+
}
|
|
55
|
+
get calls() {
|
|
56
|
+
return this._calls;
|
|
57
|
+
}
|
|
58
|
+
async _handleCall(method, request) {
|
|
59
|
+
this._calls.push({ method, request, timestamp: Date.now() });
|
|
60
|
+
if (this._delayMs > 0) {
|
|
61
|
+
await new Promise((resolve) => setTimeout(resolve, this._delayMs));
|
|
62
|
+
}
|
|
63
|
+
if (this._queuedResponses.length > 0) {
|
|
64
|
+
const item = this._queuedResponses.shift();
|
|
65
|
+
if (item instanceof Error) {
|
|
66
|
+
throw item;
|
|
67
|
+
}
|
|
68
|
+
return item;
|
|
69
|
+
}
|
|
70
|
+
return undefined;
|
|
71
|
+
}
|
|
72
|
+
async checkRisk(request) {
|
|
73
|
+
const res = await this._handleCall('checkRisk', request);
|
|
74
|
+
if (res)
|
|
75
|
+
return res;
|
|
76
|
+
return {
|
|
77
|
+
assessmentId: `mock-${Math.random().toString(36).substring(2, 14)}`,
|
|
78
|
+
decision: this._defaultDecision,
|
|
79
|
+
decisionAt: this.getTimestamp(),
|
|
80
|
+
riskScore: this._defaultScore,
|
|
81
|
+
fraudScore: {
|
|
82
|
+
riskLevel: 'low',
|
|
83
|
+
score: this._defaultScore,
|
|
84
|
+
},
|
|
85
|
+
reasons: [{
|
|
86
|
+
code: 'DEFAULT',
|
|
87
|
+
category: 'behavior',
|
|
88
|
+
displayName: 'Default',
|
|
89
|
+
description: 'default_mock_response',
|
|
90
|
+
}],
|
|
91
|
+
};
|
|
92
|
+
}
|
|
93
|
+
async ingestSignals(request) {
|
|
94
|
+
await this._handleCall('ingestSignals', request);
|
|
95
|
+
}
|
|
96
|
+
async ingestEvent(event) {
|
|
97
|
+
await this._handleCall('ingestEvent', event);
|
|
98
|
+
}
|
|
99
|
+
}
|
|
100
|
+
exports.MockRiskClient = MockRiskClient;
|
|
@@ -0,0 +1,10 @@
|
|
|
1
|
+
export declare class WebhookVerifier {
|
|
2
|
+
/**
|
|
3
|
+
* Utility to verify the authenticity of webhooks sent by Alogram.
|
|
4
|
+
*
|
|
5
|
+
* @param payload The raw string or Buffer of the request body.
|
|
6
|
+
* @param signature The value of the 'x-alogram-signature' header.
|
|
7
|
+
* @param secret Your Alogram Webhook Secret.
|
|
8
|
+
*/
|
|
9
|
+
static verify(payload: string | Buffer, signature: string, secret: string): boolean;
|
|
10
|
+
}
|
package/dist/webhooks.js
ADDED
|
@@ -0,0 +1,32 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
// Copyright (c) 2025 Alogram Inc.
|
|
3
|
+
// All rights reserved.
|
|
4
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
5
|
+
exports.WebhookVerifier = void 0;
|
|
6
|
+
const crypto_1 = require("crypto");
|
|
7
|
+
const exceptions_1 = require("./exceptions");
|
|
8
|
+
class WebhookVerifier {
|
|
9
|
+
/**
|
|
10
|
+
* Utility to verify the authenticity of webhooks sent by Alogram.
|
|
11
|
+
*
|
|
12
|
+
* @param payload The raw string or Buffer of the request body.
|
|
13
|
+
* @param signature The value of the 'x-alogram-signature' header.
|
|
14
|
+
* @param secret Your Alogram Webhook Secret.
|
|
15
|
+
*/
|
|
16
|
+
static verify(payload, signature, secret) {
|
|
17
|
+
if (!signature || !secret) {
|
|
18
|
+
throw new exceptions_1.ValidationError('Missing signature or secret');
|
|
19
|
+
}
|
|
20
|
+
const expectedSignature = (0, crypto_1.createHmac)('sha256', secret)
|
|
21
|
+
.update(payload)
|
|
22
|
+
.digest('hex');
|
|
23
|
+
// Use timing-safe comparison to prevent timing attacks
|
|
24
|
+
const bufferExpected = Buffer.from(expectedSignature, 'utf8');
|
|
25
|
+
const bufferActual = Buffer.from(signature, 'utf8');
|
|
26
|
+
if (bufferExpected.length !== bufferActual.length || !(0, crypto_1.timingSafeEqual)(bufferExpected, bufferActual)) {
|
|
27
|
+
throw new exceptions_1.ValidationError('Invalid webhook signature');
|
|
28
|
+
}
|
|
29
|
+
return true;
|
|
30
|
+
}
|
|
31
|
+
}
|
|
32
|
+
exports.WebhookVerifier = WebhookVerifier;
|
|
@@ -0,0 +1,52 @@
|
|
|
1
|
+
// Copyright (c) 2025 Alogram Inc.
|
|
2
|
+
// Example: Async Signal Ingestion
|
|
3
|
+
//
|
|
4
|
+
// This example shows how to ingest behavioral signals asynchronously
|
|
5
|
+
// using standard Promise patterns in TypeScript.
|
|
6
|
+
|
|
7
|
+
import { AlogramRiskClient, SignalsRequest } from '@alogram/payrisk';
|
|
8
|
+
|
|
9
|
+
const client = new AlogramRiskClient({
|
|
10
|
+
baseUrl: 'https://api.alogram.ai',
|
|
11
|
+
apiKey: 'sk_test_...'
|
|
12
|
+
});
|
|
13
|
+
|
|
14
|
+
/**
|
|
15
|
+
* Simulates a background signal sender.
|
|
16
|
+
* In a real application, you might use a dedicated queue or worker.
|
|
17
|
+
*/
|
|
18
|
+
async function sendSignalInBackground(userId: string, type: 'page_view' | 'feature_use') {
|
|
19
|
+
const request: SignalsRequest = {
|
|
20
|
+
signalType: 'interaction',
|
|
21
|
+
entities: {
|
|
22
|
+
tenantId: 'tid_123',
|
|
23
|
+
clientId: 'web_frontend',
|
|
24
|
+
endCustomerId: userId
|
|
25
|
+
},
|
|
26
|
+
interactions: [
|
|
27
|
+
{
|
|
28
|
+
interactionType: type,
|
|
29
|
+
timestamp: new Date().toISOString(),
|
|
30
|
+
locationId: 'loc_browser'
|
|
31
|
+
}
|
|
32
|
+
]
|
|
33
|
+
};
|
|
34
|
+
|
|
35
|
+
try {
|
|
36
|
+
// Note: We don't await this in the main thread to keep UI responsive
|
|
37
|
+
await client.ingestSignals(request);
|
|
38
|
+
console.log(`✅ Signal ${type} ingested for ${userId}`);
|
|
39
|
+
} catch (e) {
|
|
40
|
+
console.error(`❌ Signal ingestion failed: ${e}`);
|
|
41
|
+
}
|
|
42
|
+
}
|
|
43
|
+
|
|
44
|
+
// Simulated Express/Next.js handler
|
|
45
|
+
export function onUserClick(userId: string) {
|
|
46
|
+
console.log(`👤 User ${userId} clicked a button.`);
|
|
47
|
+
|
|
48
|
+
// Fire and forget - don't await the result
|
|
49
|
+
sendSignalInBackground(userId, 'feature_use');
|
|
50
|
+
|
|
51
|
+
return { status: 'success' };
|
|
52
|
+
}
|
|
@@ -0,0 +1,26 @@
|
|
|
1
|
+
import { AlogramRiskClient } from '@alogram/payrisk';
|
|
2
|
+
|
|
3
|
+
async function main() {
|
|
4
|
+
const client = new AlogramRiskClient({
|
|
5
|
+
baseUrl: 'https://api.alogram.ai',
|
|
6
|
+
apiKey: 'sk_test_12345'
|
|
7
|
+
});
|
|
8
|
+
|
|
9
|
+
const response = await client.checkRisk({
|
|
10
|
+
eventType: 'purchase',
|
|
11
|
+
entities: {
|
|
12
|
+
tenantId: 'tid_test',
|
|
13
|
+
clientId: 'cid_test',
|
|
14
|
+
endCustomerId: 'ecid_test'
|
|
15
|
+
},
|
|
16
|
+
purchase: {
|
|
17
|
+
amount: 10.50,
|
|
18
|
+
currency: 'USD',
|
|
19
|
+
transactionId: 'tx_test_123'
|
|
20
|
+
}
|
|
21
|
+
});
|
|
22
|
+
|
|
23
|
+
console.log('Risk Decision:', response.decision);
|
|
24
|
+
}
|
|
25
|
+
|
|
26
|
+
main().catch(console.error);
|
|
@@ -0,0 +1,52 @@
|
|
|
1
|
+
// Copyright (c) 2025 Alogram Inc.
|
|
2
|
+
// Example: Production Error Handling
|
|
3
|
+
//
|
|
4
|
+
// Demonstrates robust error handling and the "Fail-Open" strategy in TypeScript.
|
|
5
|
+
|
|
6
|
+
import {
|
|
7
|
+
AlogramRiskClient,
|
|
8
|
+
ValidationError,
|
|
9
|
+
AuthenticationError,
|
|
10
|
+
RateLimitError,
|
|
11
|
+
InternalServerError,
|
|
12
|
+
CheckRequest
|
|
13
|
+
} from '@alogram/payrisk';
|
|
14
|
+
|
|
15
|
+
const client = new AlogramRiskClient({
|
|
16
|
+
baseUrl: 'https://api.alogram.ai',
|
|
17
|
+
apiKey: 'sk_test_...'
|
|
18
|
+
});
|
|
19
|
+
|
|
20
|
+
async function processPayment(request: CheckRequest) {
|
|
21
|
+
try {
|
|
22
|
+
const decision = await client.checkRisk(request);
|
|
23
|
+
|
|
24
|
+
if (decision.decision === 'decline') {
|
|
25
|
+
return { status: 'blocked', reason: decision.reasons };
|
|
26
|
+
}
|
|
27
|
+
|
|
28
|
+
return { status: 'approved', score: decision.riskScore };
|
|
29
|
+
|
|
30
|
+
} catch (e) {
|
|
31
|
+
if (e instanceof AuthenticationError) {
|
|
32
|
+
// Logic error: Your keys are wrong. Notify Ops.
|
|
33
|
+
console.error('🚨 AUTH FAILURE: Check API Keys');
|
|
34
|
+
throw e;
|
|
35
|
+
}
|
|
36
|
+
|
|
37
|
+
if (e instanceof ValidationError) {
|
|
38
|
+
// Integration error: You sent bad data.
|
|
39
|
+
console.error('❌ INVALID DATA:', e.message);
|
|
40
|
+
return { status: 'error', message: 'Internal validation failed' };
|
|
41
|
+
}
|
|
42
|
+
|
|
43
|
+
if (e instanceof RateLimitError || e instanceof InternalServerError) {
|
|
44
|
+
// System issues: These were already retried by the SDK.
|
|
45
|
+
// STRATEGY: Fail-Open. Don't block the user if Alogram is down.
|
|
46
|
+
console.warn('⚠️ SYSTEM DEGRADED: Allowing via fail-open');
|
|
47
|
+
return { status: 'approved', note: 'manual_review_required' };
|
|
48
|
+
}
|
|
49
|
+
|
|
50
|
+
throw e;
|
|
51
|
+
}
|
|
52
|
+
}
|
|
@@ -0,0 +1,29 @@
|
|
|
1
|
+
// Copyright (c) 2025 Alogram Inc.
|
|
2
|
+
// Example: Webhook Verification
|
|
3
|
+
//
|
|
4
|
+
// Secures your Node.js endpoint by verifying Alogram's cryptographic signatures.
|
|
5
|
+
|
|
6
|
+
import { WebhookVerifier } from '@alogram/payrisk';
|
|
7
|
+
|
|
8
|
+
// In a real app, this comes from process.env
|
|
9
|
+
const WEBHOOK_SECRET = 'whsec_...';
|
|
10
|
+
|
|
11
|
+
/**
|
|
12
|
+
* Example handler for an Express.js route
|
|
13
|
+
*/
|
|
14
|
+
export async function handleWebhook(req: any, res: any) {
|
|
15
|
+
const signature = req.headers['x-alogram-signature'];
|
|
16
|
+
const rawBody = req.body; // Ensure you have access to the raw buffer
|
|
17
|
+
|
|
18
|
+
try {
|
|
19
|
+
WebhookVerifier.verify(rawBody, signature, WEBHOOK_SECRET);
|
|
20
|
+
|
|
21
|
+
console.log('✅ Webhook Verified!');
|
|
22
|
+
// Handle the event (e.g. chargeback.updated)
|
|
23
|
+
|
|
24
|
+
res.status(200).send('OK');
|
|
25
|
+
} catch (e) {
|
|
26
|
+
console.error('🛑 Invalid Signature:', e);
|
|
27
|
+
res.status(401).send('Unauthorized');
|
|
28
|
+
}
|
|
29
|
+
}
|
package/package.json
ADDED
|
@@ -0,0 +1,64 @@
|
|
|
1
|
+
{
|
|
2
|
+
"name": "@alogram/payrisk",
|
|
3
|
+
"version": "0.1.6",
|
|
4
|
+
"description": "The official 'Smart' TypeScript client for the Alogram Payrisk API.",
|
|
5
|
+
"author": "Alogram Inc. <support@alogram.ai>",
|
|
6
|
+
"license": "Apache-2.0",
|
|
7
|
+
"repository": {
|
|
8
|
+
"type": "git",
|
|
9
|
+
"url": "https://github.com/alogram/alogram-typescript.git"
|
|
10
|
+
},
|
|
11
|
+
"homepage": "https://www.alogram.ai",
|
|
12
|
+
"bugs": {
|
|
13
|
+
"url": "https://github.com/alogram/alogram-typescript/issues"
|
|
14
|
+
},
|
|
15
|
+
"engines": {
|
|
16
|
+
"node": ">=18"
|
|
17
|
+
},
|
|
18
|
+
"type": "module",
|
|
19
|
+
"main": "./dist/index.js",
|
|
20
|
+
"types": "./dist/index.d.ts",
|
|
21
|
+
"exports": {
|
|
22
|
+
".": {
|
|
23
|
+
"import": "./dist/index.js",
|
|
24
|
+
"require": "./dist/index.js",
|
|
25
|
+
"types": "./dist/index.d.ts"
|
|
26
|
+
}
|
|
27
|
+
},
|
|
28
|
+
"files": [
|
|
29
|
+
"dist",
|
|
30
|
+
"README.md",
|
|
31
|
+
"LICENSE",
|
|
32
|
+
"AI.md",
|
|
33
|
+
"examples"
|
|
34
|
+
],
|
|
35
|
+
"scripts": {
|
|
36
|
+
"build": "tsc",
|
|
37
|
+
"test": "vitest run",
|
|
38
|
+
"lint": "eslint src/**/*.ts",
|
|
39
|
+
"prepublishOnly": "npm run build"
|
|
40
|
+
},
|
|
41
|
+
"dependencies": {
|
|
42
|
+
"uuid": "^9.0.1",
|
|
43
|
+
"async-retry": "^1.3.3"
|
|
44
|
+
},
|
|
45
|
+
"peerDependencies": {
|
|
46
|
+
"@opentelemetry/api": ">=1.0.0"
|
|
47
|
+
},
|
|
48
|
+
"peerDependenciesMeta": {
|
|
49
|
+
"@opentelemetry/api": {
|
|
50
|
+
"optional": true
|
|
51
|
+
}
|
|
52
|
+
},
|
|
53
|
+
"devDependencies": {
|
|
54
|
+
"typescript": "^5.0.0",
|
|
55
|
+
"vitest": "^1.0.0",
|
|
56
|
+
"eslint": "^8.0.0",
|
|
57
|
+
"@typescript-eslint/parser": "^6.0.0",
|
|
58
|
+
"@typescript-eslint/eslint-plugin": "^6.0.0",
|
|
59
|
+
"@types/node": "^20.0.0",
|
|
60
|
+
"@types/uuid": "^9.0.0",
|
|
61
|
+
"@types/async-retry": "^1.4.0",
|
|
62
|
+
"@opentelemetry/api": "^1.7.0"
|
|
63
|
+
}
|
|
64
|
+
}
|