gocardless-nodejs
Advanced tools
Comparing version 3.23.0 to 3.24.0
@@ -5,4 +5,4 @@ declare enum Environments { | ||
} | ||
declare const CLIENT_VERSION = "3.23.0"; | ||
declare const CLIENT_VERSION = "3.24.0"; | ||
declare const API_VERSION = "2015-07-06"; | ||
export { Environments, CLIENT_VERSION, API_VERSION }; |
@@ -9,3 +9,3 @@ 'use strict'; | ||
})(Environments || (exports.Environments = Environments = {})); | ||
const CLIENT_VERSION = '3.23.0'; | ||
const CLIENT_VERSION = '3.24.0'; | ||
exports.CLIENT_VERSION = CLIENT_VERSION; | ||
@@ -12,0 +12,0 @@ const API_VERSION = '2015-07-06'; |
@@ -29,35 +29,58 @@ 'use strict'; | ||
static buildFromResponse(response) { | ||
const { statusCode, body: { error: { type, errors }, }, } = response; | ||
// These statuses are for unique errors | ||
switch (statusCode) { | ||
case 401: | ||
return new AuthenticationError(response); | ||
case 403: | ||
return new PermissionsError(response); | ||
case 429: | ||
return new RateLimitError(response); | ||
default: | ||
//noop | ||
} | ||
// Whereas these errors have different meanings over the same codes | ||
switch (type) { | ||
case 'validation_failed': | ||
return new ValidationFailedError(response); | ||
case 'invalid_api_usage': | ||
return new InvalidApiUsageError(response); | ||
case 'invalid_state': | ||
for (const e of errors) { | ||
if (e.reason === 'idempotent_creation_conflict') { | ||
if (e.links && e.links.conflicting_resource_id) { | ||
return new IdempotentCreationConflictError(response, e.links.conflicting_resource_id); | ||
try { | ||
const { statusCode, body: { error: { type, errors }, }, } = response; | ||
// These statuses are for unique errors | ||
switch (statusCode) { | ||
case 401: | ||
return new AuthenticationError(response); | ||
case 403: | ||
return new PermissionsError(response); | ||
case 429: | ||
return new RateLimitError(response); | ||
default: | ||
//noop | ||
} | ||
// Whereas these errors have different meanings over the same codes | ||
switch (type) { | ||
case 'validation_failed': | ||
return new ValidationFailedError(response); | ||
case 'invalid_api_usage': | ||
return new InvalidApiUsageError(response); | ||
case 'invalid_state': | ||
for (const e of errors) { | ||
if (e.reason === 'idempotent_creation_conflict') { | ||
if (e.links && e.links.conflicting_resource_id) { | ||
return new IdempotentCreationConflictError(response, e.links.conflicting_resource_id); | ||
} | ||
return new MalformedResponseError('Idempotent Creation Conflict Error missing conflicting_resource_id', response); | ||
} | ||
return new MalformedResponseError('Idempotent Creation Conflict Error missing conflicting_resource_id', response); | ||
} | ||
} | ||
return new InvalidStateError(response); | ||
case 'gocardless': | ||
return new GoCardlessInternalError(response); | ||
default: | ||
return new ApiError(response); | ||
return new InvalidStateError(response); | ||
case 'gocardless': | ||
return new GoCardlessInternalError(response); | ||
default: | ||
return new ApiError(response); | ||
} | ||
} | ||
catch (err) { | ||
const failureResponse = { | ||
statusCode: 500, | ||
body: { | ||
error: { | ||
message: 'Internal server error', | ||
errors: [ | ||
{ | ||
reason: 'internal_server_error', | ||
message: 'Internal server error', | ||
}, | ||
], | ||
documentation_url: 'https://developer.gocardless.com/api-reference#internal_server_error', | ||
type: 'gocardless', | ||
request_id: response.headers['x-request-id'], | ||
code: 500, | ||
}, | ||
}, | ||
}; | ||
return new GoCardlessInternalError(failureResponse); | ||
} | ||
} | ||
@@ -64,0 +87,0 @@ toString() { |
{ | ||
"name": "gocardless-nodejs", | ||
"version": "3.23.0", | ||
"version": "3.24.0", | ||
"description": "Node.js client for the GoCardless API - a powerful, simple solution for the collection of recurring bank-to-bank payments", | ||
@@ -28,12 +28,14 @@ "author": "GoCardless Ltd <client-libraries@gocardless.com>", | ||
"lodash": "^4.17.15", | ||
"qs": "^6.9.1", | ||
"uuid": "^7.0.2" | ||
"uuid": "^7.0.2", | ||
"crypto-js": "3.2.1", | ||
"buffer-equal-constant-time": "1.0.1", | ||
"qs": "^6.9.1" | ||
}, | ||
"devDependencies": { | ||
"@types/node": "^13.9.0", | ||
"@types/jest": "^25.1.4", | ||
"@types/nock": "^11.1.0", | ||
"@types/node": "^13.9.0", | ||
"jest": "^25.1.0", | ||
"ts-jest": "25.2.1", | ||
"nock": "^13.0.11", | ||
"ts-jest": "25.2.1", | ||
"typescript": "^4.2.4" | ||
@@ -44,4 +46,4 @@ }, | ||
"engines": { | ||
"node": ">=18.0" | ||
"node": ">=10.0" | ||
} | ||
} |
@@ -47,3 +47,3 @@ # Node.js client for the GoCardless API | ||
// Create a new payment with an idempotency key | ||
// Create a new payment. | ||
const payment = await client.payments.create( | ||
@@ -55,3 +55,3 @@ { | ||
}, | ||
uuidv4(), | ||
{ uuidv4() }, | ||
); | ||
@@ -58,0 +58,0 @@ |
@@ -12,5 +12,2 @@ /** | ||
*/ | ||
/// <reference types="node" /> | ||
import crypto from 'crypto'; | ||
import type { Event } from './types/Types'; | ||
declare function InvalidSignatureError(): void; | ||
@@ -21,20 +18,9 @@ /** | ||
* | ||
* @body The raw webhook body. | ||
* @webhookSecret The webhook endpoint secret for your webhook endpoint, as | ||
* @body [string]: The raw webhook body. | ||
* @webhookSecret [string]: The webhook endpoint secret for your webhook endpoint, as | ||
* configured in your GoCardless Dashboard. | ||
* @signatureHeader The signature included in the webhook request, as specified | ||
* @signatureHeader [string]: The signature included in the webhook request, as specified | ||
* by the `Webhook-Signature` header. | ||
*/ | ||
declare function parse(body: crypto.BinaryLike, webhookSecret: string, signatureHeader: string): Event[]; | ||
/** | ||
* Validate the signature header. Note, we're using the `crypto.timingSafeEqual` | ||
* library for the hash comparison, to protect against timing attacks. | ||
* | ||
* @body The raw webhook body. | ||
* @webhookSecret The webhook endpoint secret for your webhook endpoint, as | ||
* configured in your GoCardless Dashboard. | ||
* @signatureHeader The signature included in the webhook request, as specified | ||
* by the `Webhook-Signature` header. | ||
*/ | ||
declare function verifySignature(body: crypto.BinaryLike, webhookSecret: string, signatureHeader: string): void; | ||
export { parse, verifySignature, InvalidSignatureError }; | ||
declare function parse(body: string, webhookSecret: string, signatureHeader: string): any; | ||
export { parse, InvalidSignatureError }; |
@@ -17,4 +17,5 @@ "use strict"; | ||
Object.defineProperty(exports, "__esModule", { value: true }); | ||
exports.InvalidSignatureError = exports.verifySignature = exports.parse = void 0; | ||
const crypto_1 = __importDefault(require("crypto")); | ||
exports.InvalidSignatureError = exports.parse = void 0; | ||
const crypto_js_1 = __importDefault(require("crypto-js")); | ||
const buffer_equal_constant_time_1 = __importDefault(require("buffer-equal-constant-time")); | ||
function InvalidSignatureError() { | ||
@@ -30,6 +31,6 @@ this.message = | ||
* | ||
* @body The raw webhook body. | ||
* @webhookSecret The webhook endpoint secret for your webhook endpoint, as | ||
* @body [string]: The raw webhook body. | ||
* @webhookSecret [string]: The webhook endpoint secret for your webhook endpoint, as | ||
* configured in your GoCardless Dashboard. | ||
* @signatureHeader The signature included in the webhook request, as specified | ||
* @signatureHeader [string]: The signature included in the webhook request, as specified | ||
* by the `Webhook-Signature` header. | ||
@@ -39,25 +40,24 @@ */ | ||
verifySignature(body, webhookSecret, signatureHeader); | ||
const bodyString = typeof body === 'string' ? body : body.toString(); | ||
const eventsData = JSON.parse(bodyString); | ||
return eventsData.events; | ||
const eventsData = JSON.parse(body)['events']; | ||
return eventsData.map(eventJson => eventJson); | ||
} | ||
exports.parse = parse; | ||
/** | ||
* Validate the signature header. Note, we're using the `crypto.timingSafeEqual` | ||
* Validate the signature header. Note, we're using the `buffer-equal-constant-time` | ||
* library for the hash comparison, to protect against timing attacks. | ||
* | ||
* @body The raw webhook body. | ||
* @webhookSecret The webhook endpoint secret for your webhook endpoint, as | ||
* @body [string]: The raw webhook body. | ||
* @webhookSecret [string]: The webhook endpoint secret for your webhook endpoint, as | ||
* configured in your GoCardless Dashboard. | ||
* @signatureHeader The signature included in the webhook request, as specified | ||
* @signatureHeader [string]: The signature included in the webhook request, as specified | ||
* by the `Webhook-Signature` header. | ||
*/ | ||
function verifySignature(body, webhookSecret, signatureHeader) { | ||
const bufferDigest = crypto_1.default.createHmac('sha256', webhookSecret).update(body).digest(); | ||
const bufferSignatureHeader = Buffer.from(signatureHeader, 'hex'); | ||
if ((bufferDigest.length !== bufferSignatureHeader.length) || !crypto_1.default.timingSafeEqual(bufferDigest, bufferSignatureHeader)) { | ||
const rawDigest = crypto_js_1.default.HmacSHA256(body, webhookSecret); | ||
const bufferDigest = Buffer.from(rawDigest.toString(crypto_js_1.default.enc.Hex)); | ||
const bufferSignatureHeader = Buffer.from(signatureHeader); | ||
if (!(0, buffer_equal_constant_time_1.default)(bufferDigest, bufferSignatureHeader)) { | ||
throw new InvalidSignatureError(); | ||
} | ||
} | ||
exports.verifySignature = verifySignature; | ||
//# sourceMappingURL=webhooks.js.map |
Sorry, the diff of this file is not supported yet
Sorry, the diff of this file is not supported yet
359323
6795
6
+ Addedcrypto-js@3.2.1
+ Addedbuffer-equal-constant-time@1.0.1(transitive)
+ Addedcrypto-js@3.2.1(transitive)