Skip to content

Commit

Permalink
Merge pull request #2134 from stripe/xavdid/merge-node-beta
Browse files Browse the repository at this point in the history
Fix merge conflicts
  • Loading branch information
xavdid-stripe authored Jul 9, 2024
2 parents 496a44f + f67cefb commit eba5b86
Show file tree
Hide file tree
Showing 10 changed files with 124 additions and 39 deletions.
2 changes: 1 addition & 1 deletion .eslintrc.js
Original file line number Diff line number Diff line change
Expand Up @@ -39,7 +39,7 @@ module.exports = {
'func-style': ['error', 'declaration', {allowArrowFunctions: true}],
'generator-star-spacing': 'error',
'global-require': 'off',
'guard-for-in': 'off',
'guard-for-in': 'error',
'handle-callback-err': 'off',
'id-blacklist': 'error',
'id-length': 'off',
Expand Down
5 changes: 4 additions & 1 deletion .github/workflows/main.yml
Original file line number Diff line number Diff line change
Expand Up @@ -55,7 +55,10 @@ jobs:
os:
- "ubuntu-latest"
node:
- "19"
# should include even numbers >= 12
# see: https://nodejs.org/en/about/previous-releases
- "22"
- "20"
- "18"
- "16"
- "14"
Expand Down
3 changes: 3 additions & 0 deletions .mise.toml
Original file line number Diff line number Diff line change
@@ -0,0 +1,3 @@
[tools]
# used in unit tests
deno = "1"
8 changes: 7 additions & 1 deletion CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -7,7 +7,13 @@
* Add support for `list` and `retrieve` methods on resource `Institution`
* Add support for `institution` on `Checkout.Session.payment_method_options.us_bank_account.financial_connections.filters`, `FinancialConnections.Session.filters`, `FinancialConnections.SessionCreateParams.filters`, `Invoice.payment_settings.payment_method_options.us_bank_account.financial_connections.filters`, `InvoiceCreateParams.payment_settings.payment_method_options.us_bank_account.financial_connections.filters`, `InvoiceUpdateParams.payment_settings.payment_method_options.us_bank_account.financial_connections.filters`, `PaymentIntent.payment_method_options.us_bank_account.financial_connections.filters`, `PaymentIntentConfirmParams.payment_method_options.us_bank_account.financial_connections.filters`, `PaymentIntentCreateParams.payment_method_options.us_bank_account.financial_connections.filters`, `PaymentIntentUpdateParams.payment_method_options.us_bank_account.financial_connections.filters`, `SetupIntent.payment_method_options.us_bank_account.financial_connections.filters`, `SetupIntentConfirmParams.payment_method_options.us_bank_account.financial_connections.filters`, `SetupIntentCreateParams.payment_method_options.us_bank_account.financial_connections.filters`, `SetupIntentUpdateParams.payment_method_options.us_bank_account.financial_connections.filters`, `Subscription.payment_settings.payment_method_options.us_bank_account.financial_connections.filters`, `SubscriptionCreateParams.payment_settings.payment_method_options.us_bank_account.financial_connections.filters`, and `SubscriptionUpdateParams.payment_settings.payment_method_options.us_bank_account.financial_connections.filters`
* Add support for `payment_method_allow_redisplay_filters`, `payment_method_redisplay_limit`, `payment_method_redisplay`, and `payment_method_save_usage` on `CustomerSession.components.payment_element.features` and `CustomerSessionCreateParams.components.payment_element.features`
* Add support for new value `balance` on enums `FinancialConnections.Account.subscriptions[]`, `FinancialConnections.AccountSubscribeParams.features[]`, and `FinancialConnections.AccountUnsubscribeParams.features[]`
* Add support for new value `balance` on enums `FinancialConnections.Account.subscriptions[]`, `FinancialConnections.AccountSubscribeParams.features[]`, and `FinancialConnections.AccountUnsubscribeParams.features[]`

## 16.2.0 - 2024-07-05
* [#2125](https://github.com/stripe/stripe-node/pull/2125) Update generated code
* Add support for `add_lines`, `remove_lines`, and `update_lines` methods on resource `Invoice`
* Add support for new value `payment_intent_fx_quote_invalid` on enums `Invoice.last_finalization_error.code`, `PaymentIntent.last_payment_error.code`, `SetupAttempt.setup_error.code`, `SetupIntent.last_setup_error.code`, and `StripeError.code`
* Add support for `posted_at` on `Tax.TransactionCreateFromCalculationParams` and `Tax.Transaction`

## 16.2.0-beta.1 - 2024-06-27
* [#2110](https://github.com/stripe/stripe-node/pull/2110) Update generated code for beta
Expand Down
1 change: 1 addition & 0 deletions examples/webhook-signing/.gitignore
Original file line number Diff line number Diff line change
Expand Up @@ -3,3 +3,4 @@
**/package-lock.json
.env
express-ts.js
deno.lock
3 changes: 3 additions & 0 deletions src/ResourceNamespace.ts
Original file line number Diff line number Diff line change
Expand Up @@ -16,6 +16,9 @@ function ResourceNamespace(
>
): void {
for (const name in resources) {
if (!Object.prototype.hasOwnProperty.call(resources, name)) {
continue;
}
const camelCaseName = name[0].toLowerCase() + name.substring(1);

const resource = new resources[name](stripe);
Expand Down
78 changes: 56 additions & 22 deletions src/Webhooks.ts
Original file line number Diff line number Diff line change
Expand Up @@ -65,6 +65,9 @@ export type WebhookObject = {
receivedAt: number
) => Promise<WebhookEvent>;
generateTestHeaderString: (opts: WebhookTestHeaderOptions) => string;
generateTestHeaderStringAsync: (
opts: WebhookTestHeaderOptions
) => Promise<string>;
};

export function createWebhooks(
Expand Down Expand Up @@ -142,31 +145,30 @@ export function createWebhooks(
* @property {CryptoProvider} cryptoProvider - Crypto provider to use for computing the signature if none was provided. Defaults to NodeCryptoProvider.
*/
generateTestHeaderString: function(opts: WebhookTestHeaderOptions): string {
if (!opts) {
throw new StripeError({
message: 'Options are required',
});
}

opts.timestamp =
Math.floor(opts.timestamp) || Math.floor(Date.now() / 1000);
opts.scheme = opts.scheme || signature.EXPECTED_SCHEME;

opts.cryptoProvider = opts.cryptoProvider || getCryptoProvider();
const preparedOpts = prepareOptions(opts);

opts.signature =
opts.signature ||
opts.cryptoProvider.computeHMACSignature(
opts.timestamp + '.' + opts.payload,
opts.secret
const signature =
preparedOpts.signature ||
preparedOpts.cryptoProvider.computeHMACSignature(
preparedOpts.payloadString,
preparedOpts.secret
);

const generatedHeader = [
't=' + opts.timestamp,
opts.scheme + '=' + opts.signature,
].join(',');

return generatedHeader;
return preparedOpts.generateHeaderString(signature);
},
generateTestHeaderStringAsync: async function(
opts: WebhookTestHeaderOptions
) {
const preparedOpts = prepareOptions(opts);

const signature =
preparedOpts.signature ||
(await preparedOpts.cryptoProvider.computeHMACSignatureAsync(
preparedOpts.payloadString,
preparedOpts.secret
));

return preparedOpts.generateHeaderString(signature);
},
};

Expand Down Expand Up @@ -443,6 +445,38 @@ export function createWebhooks(
return webhooksCryptoProviderInstance!;

Check warning on line 445 in src/Webhooks.ts

View workflow job for this annotation

GitHub Actions / Build

Forbidden non-null assertion
}

function prepareOptions(
opts: WebhookTestHeaderOptions
): WebhookTestHeaderOptions & {
payloadString: string;
generateHeaderString: (signature: string) => string;
} {
if (!opts) {
throw new StripeError({
message: 'Options are required',
});
}

const timestamp =
Math.floor(opts.timestamp) || Math.floor(Date.now() / 1000);
const scheme = opts.scheme || signature.EXPECTED_SCHEME;
const cryptoProvider = opts.cryptoProvider || getCryptoProvider();
const payloadString = `${timestamp}.${opts.payload}`;

const generateHeaderString = (signature: string): string => {
return `t=${timestamp},${scheme}=${signature}`;
};

return {
...opts,
timestamp,
scheme,
cryptoProvider,
payloadString,
generateHeaderString,
};
}

Webhook.signature = signature;

return Webhook;
Expand Down
6 changes: 5 additions & 1 deletion src/multipart.ts
Original file line number Diff line number Diff line change
@@ -1,8 +1,8 @@
import {
MultipartRequestData,
RequestData,
RequestHeaders,
StripeResourceObject,
RequestData,
} from './Types.js';
import {flattenAndStringify, queryStringifyRequestData} from './utils.js';

Expand Down Expand Up @@ -46,6 +46,10 @@ const multipartDataGenerator = (
const flattenedData = flattenAndStringify(data);

for (const k in flattenedData) {
if (!Object.prototype.hasOwnProperty.call(flattenedData, k)) {
continue;
}

const v = flattenedData[k];
push(`--${segno}`);
if (Object.prototype.hasOwnProperty.call(v, 'data')) {
Expand Down
33 changes: 20 additions & 13 deletions src/stripe.core.ts
Original file line number Diff line number Diff line change
@@ -1,24 +1,24 @@
import * as _Error from './Error.js';
import {RequestSender} from './RequestSender.js';
import {StripeResource} from './StripeResource.js';
import {
AppInfo,
RequestData,
RequestOptions,
StripeObject,
UserProvidedConfig,
} from './Types.js';
import {WebhookObject, createWebhooks} from './Webhooks.js';
import {ApiVersion} from './apiVersion.js';
import * as resources from './resources.js';
import {CryptoProvider} from './crypto/CryptoProvider.js';
import {HttpClient, HttpClientResponse} from './net/HttpClient.js';
import {PlatformFunctions} from './platform/PlatformFunctions.js';
import * as resources from './resources.js';
import {
determineProcessUserAgentProperties,
pascalToCamelCase,
validateInteger,
} from './utils.js';
import {CryptoProvider} from './crypto/CryptoProvider.js';
import {PlatformFunctions} from './platform/PlatformFunctions.js';
import {RequestSender} from './RequestSender.js';
import {StripeResource} from './StripeResource.js';
import {WebhookObject, createWebhooks} from './Webhooks.js';
import {
StripeObject,
AppInfo,
UserProvidedConfig,
RequestOptions,
RequestData,
} from './Types.js';

const DEFAULT_HOST = 'api.stripe.com';
const DEFAULT_PORT = '443';
Expand Down Expand Up @@ -378,6 +378,9 @@ export function createStripe(
this._platformFunctions.getUname().then((uname: string | null) => {
const userAgent: Record<string, string> = {};
for (const field in seed) {
if (!Object.prototype.hasOwnProperty.call(seed, field)) {
continue;
}
userAgent[field] = encodeURIComponent(seed[field] ?? 'null');
}

Expand Down Expand Up @@ -432,6 +435,10 @@ export function createStripe(
*/
_prepResources(): void {
for (const name in resources) {
if (!Object.prototype.hasOwnProperty.call(resources, name)) {
continue;
}

// @ts-ignore
this[pascalToCamelCase(name)] = new resources[name](this);
}
Expand Down
24 changes: 24 additions & 0 deletions test/Webhook.spec.ts
Original file line number Diff line number Diff line change
Expand Up @@ -41,6 +41,30 @@ function createWebhooksTestSuite(stripe) {
});
});

describe('.generateTestHeaderStringAsync', () => {
it('should throw when no opts are passed', async () => {
await expect(
stripe.webhooks.generateTestHeaderStringAsync()
).to.be.rejectedWith('Options are required');
});

it('should correctly construct a webhook header', async () => {
const header = await stripe.webhooks.generateTestHeaderStringAsync({
payload: EVENT_PAYLOAD_STRING,
secret: SECRET,
});

expect(header).to.not.be.undefined;
expect(header.split(',')).to.have.lengthOf(2);
expect(header).to.equal(
stripe.webhooks.generateTestHeaderString({
payload: EVENT_PAYLOAD_STRING,
secret: SECRET,
})
);
});
});

const makeConstructEventTests = (
constructEventFn: typeof stripe.webhooks.construct
) => {
Expand Down

0 comments on commit eba5b86

Please sign in to comment.