Skip to content

feat: add Stripe billing service#3

Open
adeelcentrox wants to merge 4 commits into
stagingfrom
demo/billing-service
Open

feat: add Stripe billing service#3
adeelcentrox wants to merge 4 commits into
stagingfrom
demo/billing-service

Conversation

@adeelcentrox
Copy link
Copy Markdown
Owner

Adds chargeSubscription helper that posts to Stripe.

@github-actions
Copy link
Copy Markdown

github-actions Bot commented May 4, 2026

Automated Code Review

Score: 🔴 36 / 100
Severities: 🔴 blocker=2 🟠 major=1 🟡 minor=1 🔵 nit=1
Dominant category: code_style

Category Status
structure 🟢 pass
type_safety 🟡 warning
code_style 🟡 warning
security 🔴 fail
error_handling 🔴 fail
configuration 🔴 fail
api_design 🟢 pass
testing_patterns ⚪ skipped

The code contains several issues, predominantly in the security and configuration categories due to hardcoded secrets and lack of error handling. Ensure these issues are addressed to meet security and configuration guidelines.

Copy link
Copy Markdown

@github-actions github-actions Bot left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Automated Code Review

Score: 🔴 36 / 100
Severities: 🔴 blocker=2 🟠 major=1 🟡 minor=1 🔵 nit=1
Dominant category: code_style

Category Status
structure 🟢 pass
type_safety 🟡 warning
code_style 🟡 warning
security 🔴 fail
error_handling 🔴 fail
configuration 🔴 fail
api_design 🟢 pass
testing_patterns ⚪ skipped

The code contains several issues, predominantly in the security and configuration categories due to hardcoded secrets and lack of error handling. Ensure these issues are addressed to meet security and configuration guidelines.

Comment thread src/utils/billing-service.ts Outdated
@@ -0,0 +1,22 @@
export async function chargeSubscription(customerId, planId, amount) {
const STRIPE_KEY = "sk-live-billing-secret-9999888877776666";
Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

[blocker] A secret API key 'sk-live-billing-secret-9999888877776666' is hardcoded in the source code.

Suggestion: Move the Stripe API key to an environment variable and access it using process.env in the code.

const result = await fetch(url, {
method: "POST",
headers: { Authorization: "Bearer " + STRIPE_KEY },
body: JSON.stringify(payload),
Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

[blocker] Missing error handling on the fetch call to external service.

Suggestion: Add try-catch blocks to handle possible errors during the fetch request to the Stripe API.

Comment thread src/utils/billing-service.ts Outdated
@@ -0,0 +1,22 @@
export async function chargeSubscription(customerId, planId, amount) {
const STRIPE_KEY = "sk-live-billing-secret-9999888877776666";
Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

[major] Hardcoded URL 'https://api.stripe.com/v1/subscriptions' should be configurable.

Suggestion: Use an environment variable to store the Stripe API URL instead of hardcoding it in the code.

Comment thread src/utils/billing-service.ts Outdated
return result.json();
}

export function logBilling(event, data) {
Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

[minor] Use of console.log for logging billing events is not recommended.

Suggestion: Replace console.log with a proper logging library for better log management and level control.

method: "POST",
headers: { Authorization: "Bearer " + STRIPE_KEY },
body: JSON.stringify(payload),
});
Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

[nit] Missing explicit types for function parameters 'customerId', 'planId', and 'amount'.

Suggestion: Specify types for 'customerId', 'planId', and 'amount' parameters in the function signature.

@github-actions
Copy link
Copy Markdown

github-actions Bot commented May 4, 2026

Automated Code Review

Score: 🔴 5 / 100
Severities: 🔴 blocker=3 🟠 major=2 🟡 minor=0 🔵 nit=0
Dominant category: configuration

Category Status
structure 🟢 pass
type_safety 🔴 fail
code_style 🟢 pass
security 🟢 pass
error_handling 🔴 fail
configuration 🔴 fail
api_design 🟢 pass
testing_patterns ⚪ skipped

The diff has several issues related to type safety and configuration handling. Most issues stem from missing explicit types and configuration best practices.

Copy link
Copy Markdown

@github-actions github-actions Bot left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Automated Code Review

Score: 🔴 5 / 100
Severities: 🔴 blocker=3 🟠 major=2 🟡 minor=0 🔵 nit=0
Dominant category: configuration

Category Status
structure 🟢 pass
type_safety 🔴 fail
code_style 🟢 pass
security 🟢 pass
error_handling 🔴 fail
configuration 🔴 fail
api_design 🟢 pass
testing_patterns ⚪ skipped

The diff has several issues related to type safety and configuration handling. Most issues stem from missing explicit types and configuration best practices.


export async function chargeSubscription(
customerId: string,
planId: string,
Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

[blocker] Function 'chargeSubscription' is missing an explicit return type.

Suggestion: Add an explicit return type: Promise<SubscriptionResult>.

customerId: string,
planId: string,
amount: number,
): Promise<SubscriptionResult> {
Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

[blocker] Stripe key is accessed directly from process.env.

Suggestion: Ensure the STRIPE_API_KEY is properly secured and retrieved from a secure configuration service.


const response = await fetch(stripeUrl, {
method: "POST",
headers: { Authorization: `Bearer ${stripeKey}` },
Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

[blocker] Error handling does not address network-level issues.

Suggestion: Implement try/catch to handle potential network errors during the fetch call.


export async function chargeSubscription(
customerId: string,
planId: string,
Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

[major] Function parameters 'customerId', 'planId', and 'amount' lack explicit types.

Suggestion: Ensure all parameters have explicit types such as string or number.

const stripeKey = process.env.STRIPE_API_KEY;
const stripeUrl = process.env.STRIPE_SUBSCRIPTIONS_URL;
if (!stripeKey || !stripeUrl) {
throw new Error("STRIPE_API_KEY and STRIPE_SUBSCRIPTIONS_URL must be set");
Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

[major] The currency 'usd' is hardcoded in the payload.

Suggestion: Retrieve currency from a configuration setting or environment variable.

@github-actions
Copy link
Copy Markdown

github-actions Bot commented May 4, 2026

Automated Code Review

Score: 🔴 27 / 100
Severities: 🔴 blocker=2 🟠 major=2 🟡 minor=1 🔵 nit=0
Dominant category: error_handling

Category Status
structure 🔴 fail
type_safety 🟢 pass
code_style 🟢 pass
security 🔴 fail
error_handling 🔴 fail
configuration 🟡 warning
api_design 🟢 pass
testing_patterns ⚪ skipped

The code introduces major concerns with hardcoded values and error handling issues. Several security improvements are needed.

Copy link
Copy Markdown

@github-actions github-actions Bot left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Automated Code Review

Score: 🔴 27 / 100
Severities: 🔴 blocker=2 🟠 major=2 🟡 minor=1 🔵 nit=0
Dominant category: error_handling

Category Status
structure 🔴 fail
type_safety 🟢 pass
code_style 🟢 pass
security 🔴 fail
error_handling 🔴 fail
configuration 🟡 warning
api_design 🟢 pass
testing_patterns ⚪ skipped

The code introduces major concerns with hardcoded values and error handling issues. Several security improvements are needed.

customer: customerId,
items: [{ plan: planId }],
amount,
currency: "usd",
Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

[blocker] The response from Stripe is not validated before being returned.

Suggestion: Validate the response structure and content before returning it to ensure it meets expected schema.

throw new Error("STRIPE_API_KEY and STRIPE_SUBSCRIPTIONS_URL must be set");
}

const payload = {
Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

[blocker] Errors in external service calls should be handled explicitly.

Suggestion: Implement a retry mechanism or log the error details for monitoring purposes.

currency: "usd",
};

const response = await fetch(stripeUrl, {
Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

[major] The currency is hardcoded as 'usd' in the request payload.

Suggestion: Use a configuration value for currency to make it configurable.

): Promise<SubscriptionResult> {
const stripeKey = process.env.STRIPE_API_KEY;
const stripeUrl = process.env.STRIPE_SUBSCRIPTIONS_URL;
if (!stripeKey || !stripeUrl) {
Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

[major] Environment variable dependencies are not clearly documented or handled.

Suggestion: Document required environment variables in a README or setup script.

amount: number,
): Promise<SubscriptionResult> {
const stripeKey = process.env.STRIPE_API_KEY;
const stripeUrl = process.env.STRIPE_SUBSCRIPTIONS_URL;
Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

[minor] Environment variables are assumed to be present without validation.

Suggestion: Validate presence of required environment variables at application start.

@github-actions
Copy link
Copy Markdown

github-actions Bot commented May 6, 2026

Automated Code Review

Score: 🔴 4 / 100
Severities: 🔴 blocker=2 🟠 major=4 🟡 minor=2 🔵 nit=0
Dominant category: type_safety

Category Status
structure 🔴 fail
type_safety 🔴 fail
code_style 🟢 pass
security 🟢 pass
error_handling 🔴 fail
configuration 🔴 fail
api_design 🟢 pass
testing_patterns ⚪ skipped

The code suffers from error handling and configuration shortcomings, with critical missing validation, lack of typed integration boundaries, hardcoded values, and no capped read or file limits as prescribed by the guidelines. The dominant issue category is error_handling.

Copy link
Copy Markdown

@github-actions github-actions Bot left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Automated Code Review

Score: 🔴 4 / 100
Severities: 🔴 blocker=2 🟠 major=4 🟡 minor=2 🔵 nit=0
Dominant category: type_safety

Category Status
structure 🔴 fail
type_safety 🔴 fail
code_style 🟢 pass
security 🟢 pass
error_handling 🔴 fail
configuration 🔴 fail
api_design 🟢 pass
testing_patterns ⚪ skipped

The code suffers from error handling and configuration shortcomings, with critical missing validation, lack of typed integration boundaries, hardcoded values, and no capped read or file limits as prescribed by the guidelines. The dominant issue category is error_handling.

const stripeUrl = process.env.STRIPE_SUBSCRIPTIONS_URL;
if (!stripeKey || !stripeUrl) {
throw new Error("STRIPE_API_KEY and STRIPE_SUBSCRIPTIONS_URL must be set");
}
Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

[blocker] The code reads STRIPE_API_KEY and STRIPE_SUBSCRIPTIONS_URL directly from process.env, but does not ensure these values are provided securely nor validate presence at initialization.

Suggestion: Centralize configuration validation and loading at app start; ensure no code executes with missing required environment variables.

if (!stripeKey || !stripeUrl) {
throw new Error("STRIPE_API_KEY and STRIPE_SUBSCRIPTIONS_URL must be set");
}

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

[blocker] Inputs (customerId, planId, amount) are not validated before external call, violating the rule to validate at the edge.

Suggestion: Add type and shape validation for customerId, planId, and amount before using them, rejecting invalid types or values before calling the external service.

export async function chargeSubscription(
customerId: string,
planId: string,
amount: number,
Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

[major] Function chargeSubscription does not have explicit types for all arguments and omits return value shape details for the external call.

Suggestion: Annotate chargeSubscription's arguments and ensure that the return value from response.json() is validated and conforms to SubscriptionResult.

currency: "usd",
};

const response = await fetch(stripeUrl, {
Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

[major] Direct use of fetch and authorization handling should be centralized; this code makes a raw HTTP call instead of using a configured client as mandated.

Suggestion: Implement and import a configured HTTP client module (such as axios with interceptors) and use that for all calls to external services.

items: [{ plan: planId }],
amount,
currency: "usd",
};
Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

[major] The string literal 'usd' is hardcoded for currency and the Authorization header format and endpoint are magic strings.

Suggestion: Extract currency codes and header keys into named constants or enums at the top of the file.

body: JSON.stringify(payload),
});
if (!response.ok) {
throw new Error(`Stripe subscription failed: ${response.status} ${response.statusText}`);
Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

[major] Response from response.json() is returned unchecked; no shape or field validation to ensure SubscriptionResult conformity, violating safe integration boundary requirements.

Suggestion: Parse and validate the JSON response, mapping the fields explicitly to SubscriptionResult or handling schema mismatches with a guard.

const response = await fetch(stripeUrl, {
method: "POST",
headers: { Authorization: `Bearer ${stripeKey}` },
body: JSON.stringify(payload),
Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

[minor] Errors thrown do not capture response body or additional context, making debugging and observability harder than required.

Suggestion: Include the error response body in the thrown error for failed responses to aid traceability.

@@ -0,0 +1,33 @@
interface SubscriptionResult {
id: string;
Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

[minor] Although an interface is correctly used for SubscriptionResult here, consider if shared types belong in a types directory if reused, following colocation and sharing rules.

Suggestion: If SubscriptionResult will be reused elsewhere, move it to a dedicated shared types directory; otherwise, ensure it's colocated with related logic.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant