Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Block to implement Razorpay payment gateway #1169

Closed
wants to merge 23 commits into from

Conversation

dkashikar
Copy link
Contributor

@dkashikar dkashikar commented Jan 19, 2024

This block implements the Razorpay payment gateway

  1. Credentials need to be generated from https://dashboard.razorpay.com/app/api-keys

  2. Base options define common values like Company name etc. These are in baseOptions.ts

  3. There are four actions

  4. createQrCode: This generates a qrcode for payment using UPI (which is quite popular in india) This is compatible with Whatsapp.

  5. createOrder, createPaymentButton and verifyPayment: these three actions together generate a payment button and verify payment. This generates an embedBubble so it's not compatible with whatsapp. however it is compatible with all payment methods offered by razorpay - cards, net banking, wallets etc.

Summary by CodeRabbit

  • New Features

    • Introduced Razorpay payment order creation capability.
    • Implemented QR code generation for Razorpay payment transactions.
    • Provided payment verification feature using Razorpay.
  • Enhancements

    • Integrated Razorpay payment gateway with Typebot Forge.
    • Included Razorpay logo for better brand recognition.
  • Documentation

    • Updated schema to reflect the addition of Razorpay integration.

Copy link

vercel bot commented Jan 19, 2024

@dkashikar is attempting to deploy a commit to the Typebot Team on Vercel.

A member of the Team first needs to authorize it.

Copy link

coderabbitai bot commented Jan 19, 2024

Important

Auto Review Skipped

Draft detected.

Please check the settings in the CodeRabbit UI or the .coderabbit.yaml file in this repository.

To trigger a single review, invoke the @coderabbitai review command.

Walkthrough

The update introduces Razorpay payment integration into the Typebot Forge application, enabling functionalities like creating payment orders, displaying payment buttons, generating QR codes for transactions, and verifying payments. It includes the setup of authentication credentials, configuration options, and constants specific to Razorpay. Additionally, the Razorpay block is now enabled and incorporated into the existing schema of forged blocks.

Changes

File Path Change Summary
.../razorpay/actions/createOrder.ts Introduces functionality to create a payment order with specified details and store the order ID.
.../razorpay/actions/createQrCode.ts Adds functionality to generate a QR code for a payment transaction using the Razorpay API.
.../razorpay/actions/verifyPayment.ts Provides functionality to verify a payment using Razorpay.
.../razorpay/auth.ts Introduces functionality for defining encrypted credentials for a Razorpay account.
.../razorpay/baseOptions.ts Introduces functionality for defining base options for a payment integration using Razorpay.
.../razorpay/constants.ts Introduces constants related to the Razorpay integration.
.../razorpay/index.ts Introduces the functionality for integrating Razorpay payment gateway into the application.
.../razorpay/logo.tsx Contains a React component RazorpayLogo that renders the Razorpay logo as an SVG image.
.../forge/repository/index.ts Added 'razorpay' to the enabledBlocks array.
.../forge/schemas/index.ts Updated to include the razorpay block in the list of forged blocks.

Thank you for using CodeRabbit. We offer it for free to the OSS community and would appreciate your support in helping us grow. If you find it useful, would you consider giving us a shout-out on your favorite social media?

Share

Tips

Chat

There are 3 ways to chat with CodeRabbit:

  • Review comments: Directly reply to a review comment made by CodeRabbit. Example:
    • I pushed a fix in commit <commit_id>.
    • Generate unit-tests for this file.
  • Files and specific lines of code (under the "Files changed" tab): Tag @coderabbitai in a new review comment at the desired location with your query. Examples:
    • @coderabbitai generate unit tests for this file.
    • @coderabbitai modularize this function.
  • PR comments: Tag @coderabbitai in a new PR comment to ask questions about the PR branch. For the best results, please provide a very specific query, as very limited context is provided in this mode. Examples:
    • @coderabbitai generate interesting stats about this repository from git and render them as a table.
    • @coderabbitai show all the console.log statements in this repository.
    • @coderabbitai read src/utils.ts and generate unit tests.
    • @coderabbitai read the files in the src/scheduler package and generate a class diagram using mermaid and a README in the markdown format.

Note: Be mindful of the bot's finite context window. It's strongly recommended to break down tasks such as reading entire modules into smaller chunks. For a focused discussion, use review comments to chat about specific files and their changes, instead of using the PR comments.

CodeRabbit Commands (invoked as PR comments)

  • @coderabbitai pause to pause the reviews on a PR.
  • @coderabbitai resume to resume the paused reviews.
  • @coderabbitai review to trigger a review. This is useful when automatic reviews are disabled for the repository.
  • @coderabbitai resolve resolve all the CodeRabbit review comments.
  • @coderabbitai help to get help.

Additionally, you can add @coderabbitai ignore anywhere in the PR description to prevent this PR from being reviewed.

CodeRabbit Configration File (.coderabbit.yaml)

  • You can programmatically configure CodeRabbit by adding a .coderabbit.yaml file to the root of your repository.
  • The JSON schema for the configuration file is available here.
  • If your editor has YAML language server enabled, you can add the path at the top of this file to enable auto-completion and validation: # yaml-language-server: $schema=https://coderabbit.ai/integrations/coderabbit-overrides.v2.json

CodeRabbit Discord Community

Join our Discord Community to get help, request features, and share feedback.

Copy link

@coderabbitai coderabbitai bot left a comment

Choose a reason for hiding this comment

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

Review Status

Actionable comments generated: 4

Configuration used: CodeRabbit UI

Commits Files that changed from the base of the PR and between 29bd5f1 and 3c3598b.
Files ignored due to path filters (4)
  • packages/forge/blocks/razorpay/package.json is excluded by: !**/*.json
  • packages/forge/blocks/razorpay/tsconfig.json is excluded by: !**/*.json
  • packages/forge/schemas/package.json is excluded by: !**/*.json
  • pnpm-lock.yaml is excluded by: !**/*.yaml
Files selected for processing (11)
  • packages/forge/blocks/razorpay/actions/createOrder.ts (1 hunks)
  • packages/forge/blocks/razorpay/actions/createPaymentButton.ts (1 hunks)
  • packages/forge/blocks/razorpay/actions/createQrCode.ts (1 hunks)
  • packages/forge/blocks/razorpay/actions/verifyPayment.ts (1 hunks)
  • packages/forge/blocks/razorpay/auth.ts (1 hunks)
  • packages/forge/blocks/razorpay/baseOptions.ts (1 hunks)
  • packages/forge/blocks/razorpay/constants.ts (1 hunks)
  • packages/forge/blocks/razorpay/index.ts (1 hunks)
  • packages/forge/blocks/razorpay/logo.tsx (1 hunks)
  • packages/forge/repository/index.ts (1 hunks)
  • packages/forge/schemas/index.ts (2 hunks)
Files skipped from review due to trivial changes (2)
  • packages/forge/blocks/razorpay/constants.ts
  • packages/forge/repository/index.ts
Additional comments: 5
packages/forge/blocks/razorpay/auth.ts (1)
  • 3-13: The auth object is well-defined and follows the expected structure for an AuthDefinition. The use of option.object and option.string.layout is appropriate for defining the schema of the authentication object. The helper text provides a direct link to generate the API key and secret, which is a good user experience practice.
packages/forge/blocks/razorpay/logo.tsx (1)
  • 3-17: The RazorpayLogo component is a straightforward React functional component returning an SVG. The SVG paths and attributes are hardcoded, which is acceptable for a logo component. There are no props validations or default props, but since the component is simple and only receives SVG props, this is not a concern.
packages/forge/blocks/razorpay/index.ts (1)
  • 10-18: The razorpay block is correctly created using the createBlock function. It includes the necessary components such as auth, baseOptions, and actions. The LightLogo is properly assigned to the RazorpayLogo component. The block's structure is consistent with the expected pattern for defining blocks in the Typebot Forge package.
packages/forge/schemas/index.ts (1)
  • 1-5: > 📝 NOTE

This review was outside the diff hunks and was mapped to the diff hunk with the greatest overlap. Original lines [2-22]

The import and inclusion of the razorpay block in the forgedBlocks array are correct. The file follows the established pattern for including new blocks in the Typebot Forge package. The razorpay block is added to the array without disrupting the existing order or structure of the file.

packages/forge/blocks/razorpay/baseOptions.ts (1)
  • 4-42: The baseOptions object is well-structured, using option.object to define a set of configuration options. Each option is clearly labeled and includes helper text or tooltips where appropriate. Default values are provided for some options, which is a good practice to ensure that there are sensible defaults in place if the user does not specify a value.

Comment on lines 6 to 50
export const verifyPayment = createAction({
name: 'Verify Payment',
auth,
baseOptions,
options: option.object({
paymentResponse: option.string.layout({
label: 'Payment Response',
moreInfoTooltip: 'Payment response from Payment Button action',
}),
saveStatusInVariableId: option.string.layout({
label: 'Payment Status',
inputType: 'variableDropdown',
}),
}),
getSetVariableIds: (options) =>
options.saveStatusInVariableId ? [options.saveStatusInVariableId] : [],
run: {
server: async ({ credentials, options, variables, logs }) => {
if (!credentials.keySecret)
return logs.add(
'Invalid razorpay secret. Please check your configuration.'
)
if (!options.paymentResponse)
return logs.add(
'Payment response is empty. Please check the logs for any error.'
)
if (!options.saveStatusInVariableId)
return logs.add(
'Payment Status variable is not specified. Please select a variable to save the payment status.'
)

try {
const paymentResponse = JSON.parse(options.paymentResponse)

const payload = paymentResponse.razorpay_order_id + '|' + paymentResponse.razorpay_payment_id;
const expectedSignature = createHmac('sha256', credentials.keySecret).update(payload).digest('hex');
variables.set(options.saveStatusInVariableId, expectedSignature == paymentResponse.razorpay_signature)
} catch (error) {
return logs.add(error as string)
}


},
},
})
Copy link

Choose a reason for hiding this comment

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

The verifyPayment action is well-structured and includes proper error handling and logging. The use of createHmac for signature verification is appropriate. However, there is a potential security concern with the direct comparison of the expected signature and the payment response signature (line 42). A timing attack could be possible here, so it's recommended to use a constant-time comparison function to mitigate this risk.

- variables.set(options.saveStatusInVariableId, expectedSignature == paymentResponse.razorpay_signature)
+ variables.set(options.saveStatusInVariableId, crypto.timingSafeEqual(Buffer.from(expectedSignature), Buffer.from(paymentResponse.razorpay_signature)))

Committable suggestion

‼️ IMPORTANT
Carefully review the code before committing. Ensure that it accurately replaces the highlighted code, contains no missing lines, and has no issues with indentation.

Suggested change
export const verifyPayment = createAction({
name: 'Verify Payment',
auth,
baseOptions,
options: option.object({
paymentResponse: option.string.layout({
label: 'Payment Response',
moreInfoTooltip: 'Payment response from Payment Button action',
}),
saveStatusInVariableId: option.string.layout({
label: 'Payment Status',
inputType: 'variableDropdown',
}),
}),
getSetVariableIds: (options) =>
options.saveStatusInVariableId ? [options.saveStatusInVariableId] : [],
run: {
server: async ({ credentials, options, variables, logs }) => {
if (!credentials.keySecret)
return logs.add(
'Invalid razorpay secret. Please check your configuration.'
)
if (!options.paymentResponse)
return logs.add(
'Payment response is empty. Please check the logs for any error.'
)
if (!options.saveStatusInVariableId)
return logs.add(
'Payment Status variable is not specified. Please select a variable to save the payment status.'
)
try {
const paymentResponse = JSON.parse(options.paymentResponse)
const payload = paymentResponse.razorpay_order_id + '|' + paymentResponse.razorpay_payment_id;
const expectedSignature = createHmac('sha256', credentials.keySecret).update(payload).digest('hex');
variables.set(options.saveStatusInVariableId, expectedSignature == paymentResponse.razorpay_signature)
} catch (error) {
return logs.add(error as string)
}
},
},
})
export const verifyPayment = createAction({
name: 'Verify Payment',
auth,
baseOptions,
options: option.object({
paymentResponse: option.string.layout({
label: 'Payment Response',
moreInfoTooltip: 'Payment response from Payment Button action',
}),
saveStatusInVariableId: option.string.layout({
label: 'Payment Status',
inputType: 'variableDropdown',
}),
}),
getSetVariableIds: (options) =>
options.saveStatusInVariableId ? [options.saveStatusInVariableId] : [],
run: {
server: async ({ credentials, options, variables, logs }) => {
if (!credentials.keySecret)
return logs.add(
'Invalid razorpay secret. Please check your configuration.'
)
if (!options.paymentResponse)
return logs.add(
'Payment response is empty. Please check the logs for any error.'
)
if (!options.saveStatusInVariableId)
return logs.add(
'Payment Status variable is not specified. Please select a variable to save the payment status.'
)
try {
const paymentResponse = JSON.parse(options.paymentResponse)
const payload = paymentResponse.razorpay_order_id + '|' + paymentResponse.razorpay_payment_id;
const expectedSignature = createHmac('sha256', credentials.keySecret).update(payload).digest('hex');
variables.set(options.saveStatusInVariableId, crypto.timingSafeEqual(Buffer.from(expectedSignature), Buffer.from(paymentResponse.razorpay_signature)))
} catch (error) {
return logs.add(error as string)
}
},
},
})

Comment on lines 7 to 66
export const createOrder = createAction({
name: 'Payment Order',
auth,
baseOptions,
options: option.object({
amount: option.string.layout({
label: 'Amount',
moreInfoTooltip: 'Amount to be paid',
isRequired: true
}),
uid: option.string.layout({
label: 'Transaction ID',
moreInfoTooltip: 'Any unique id for the transaction'
}),
saveOrderInVariableId: option.string.layout({
label: 'Save Order ID',
inputType: 'variableDropdown',
}),
}),
getSetVariableIds: (options) =>
options.saveOrderInVariableId ? [options.saveOrderInVariableId] : [],
run: {
server: async ({ credentials, options, variables, logs }) => {
if (!options.amount || !parseInt(options.amount))
return logs.add(
'Amount is empty. Please provide the amount to generate the QR code.'
)
if (!options.saveOrderInVariableId)
return logs.add(
'Order ID variable is not specified. Please select a variable to save the generated order id.'
)

try {
const notes: Record<string, string> = {}
notes[options.uidLabel ?? defaultUidLabel] = options.uid ?? ''
const order = {
currency: options.currency ?? defaultCurrency,
amount: options.amount,
receipt: options.uid ?? '',
notes: notes
}

const response: Record<string, string> = await got.post(`${apiBaseUrl}/orders`, {
headers: {
"Content-Type": "application/json"
},
username: options.keyId,
password: credentials.keySecret,
json: order,
})
.json()

variables.set(options.saveOrderInVariableId, response.id)
} catch (error) {
return logs.add(error as string)
}

},
},
})
Copy link

Choose a reason for hiding this comment

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

The createOrder action is well-structured, with appropriate error handling and logging. The use of got for HTTP requests is consistent with modern JavaScript practices. However, there is a potential issue with the error handling in the catch block (line 61). The error is cast to a string, which may not provide useful information if the error object contains more details. It would be better to log the error message or the entire error object.

- return logs.add(error as string)
+ return logs.add(`Error creating order: ${error.message}`)

Committable suggestion

‼️ IMPORTANT
Carefully review the code before committing. Ensure that it accurately replaces the highlighted code, contains no missing lines, and has no issues with indentation.

Suggested change
export const createOrder = createAction({
name: 'Payment Order',
auth,
baseOptions,
options: option.object({
amount: option.string.layout({
label: 'Amount',
moreInfoTooltip: 'Amount to be paid',
isRequired: true
}),
uid: option.string.layout({
label: 'Transaction ID',
moreInfoTooltip: 'Any unique id for the transaction'
}),
saveOrderInVariableId: option.string.layout({
label: 'Save Order ID',
inputType: 'variableDropdown',
}),
}),
getSetVariableIds: (options) =>
options.saveOrderInVariableId ? [options.saveOrderInVariableId] : [],
run: {
server: async ({ credentials, options, variables, logs }) => {
if (!options.amount || !parseInt(options.amount))
return logs.add(
'Amount is empty. Please provide the amount to generate the QR code.'
)
if (!options.saveOrderInVariableId)
return logs.add(
'Order ID variable is not specified. Please select a variable to save the generated order id.'
)
try {
const notes: Record<string, string> = {}
notes[options.uidLabel ?? defaultUidLabel] = options.uid ?? ''
const order = {
currency: options.currency ?? defaultCurrency,
amount: options.amount,
receipt: options.uid ?? '',
notes: notes
}
const response: Record<string, string> = await got.post(`${apiBaseUrl}/orders`, {
headers: {
"Content-Type": "application/json"
},
username: options.keyId,
password: credentials.keySecret,
json: order,
})
.json()
variables.set(options.saveOrderInVariableId, response.id)
} catch (error) {
return logs.add(error as string)
}
},
},
})
} catch (error) {
return logs.add(`Error creating order: ${error.message}`)
}

Comment on lines 10 to 105
export const createQrCode = createAction({
name: 'Generate a QR Code',
auth,
baseOptions,
options: option.object({
amount: option.string.layout({
label: 'Amount',
moreInfoTooltip: 'Amount to be paid',
isRequired: true
}),
uid: option.string.layout({
label: 'Transaction ID',
moreInfoTooltip: 'Any unique id for the transaction'
}),
name: option.string.layout({
accordion: 'Advanced Configuration',
label: 'QR Code Name',
moreInfoTooltip: 'Name of the QR Code',
defaultValue: 'QR Code'
}),
usage: option.enum(['single_use', 'multiple_use']).layout({
accordion: 'Advanced Configuration',
label: 'Usage',
moreInfoTooltip: 'Will the qr code be used once or multiple times',
defaultValue: 'single_use'
}),
fixed_amount: option.boolean.layout({
accordion: 'Advanced Configuration',
label: 'Fixed Amount',
moreInfoTooltip: 'Is the amount fixed',
defaultValue: true
}),
valid_till: option.string.layout({
accordion: 'Advanced Configuration',
label: 'Valid Till',
moreInfoTooltip: 'How long is the QR code valid till',
defaultValue: '900'
}),
saveUrlInVariableId: option.string.layout({
label: 'Save QR code image URL',
inputType: 'variableDropdown',
}),
}),
getSetVariableIds: (options) =>
options.saveUrlInVariableId ? [options.saveUrlInVariableId] : [],
run: {
server: async ({ credentials, options, variables, logs }) => {
if (!options.amount || !parseInt(options.amount))
return logs.add(
'Amount is empty. Please provide the amount to generate the QR code.'
)
if (!options.saveUrlInVariableId)
return logs.add(
'QR code image URL is not specified. Please select a variable to save the generated QR code image.'
)

const delta = parseInt(options.valid_till ?? '900')
const close_by = delta > 900 ? Math.floor(Date.now() / 1000) + delta : Math.floor(Date.now() / 1000) + 900
const notes: Record<string, string> = {}
notes[options.uidLabel ?? 'vdsid'] = options.uid ?? `${close_by}`
try {
const qrcode = {
"type": "upi_qr",
"name": options.name,
"usage": options.usage ?? 'single_use',
"fixed_amount": options.fixed_amount ?? true,
"payment_amount": options.amount,
"description": `For ${options.name ?? 'Razorpay'}`,
"close_by": close_by,
"notes": notes
}

const response: Record<string, string> = await got.post(`${apiBaseUrl}/payments/qr_codes`, {
headers: {
"Content-Type": "application/json"
},
username: options.keyId,
password: credentials.keySecret,
json: qrcode,
})
.json()

const url = await uploadFileToBucket({
file: await generateQrCodeBuffer(response.image_content),
key: `tmp/qrcodes/${createId() + createId()}.png`,
mimeType: 'image/png',
})

variables.set(options.saveUrlInVariableId, url)
} catch (error) {
return logs.add(error as string)
}

},
},
})
Copy link

Choose a reason for hiding this comment

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

The createQrCode action is well-structured and includes proper error handling and logging. The use of uploadFileToBucket for storing the QR code image is appropriate. However, there is a potential issue with the default value for valid_till (line 46). The default value is a string, but it is used in a calculation as a number (line 66). It would be safer to ensure that the default value is a number or to parse it as a number before using it in calculations.

- const delta = parseInt(options.valid_till ?? '900')
+ const delta = parseInt(options.valid_till) || 900

Committable suggestion

‼️ IMPORTANT
Carefully review the code before committing. Ensure that it accurately replaces the highlighted code, contains no missing lines, and has no issues with indentation.

Suggested change
export const createQrCode = createAction({
name: 'Generate a QR Code',
auth,
baseOptions,
options: option.object({
amount: option.string.layout({
label: 'Amount',
moreInfoTooltip: 'Amount to be paid',
isRequired: true
}),
uid: option.string.layout({
label: 'Transaction ID',
moreInfoTooltip: 'Any unique id for the transaction'
}),
name: option.string.layout({
accordion: 'Advanced Configuration',
label: 'QR Code Name',
moreInfoTooltip: 'Name of the QR Code',
defaultValue: 'QR Code'
}),
usage: option.enum(['single_use', 'multiple_use']).layout({
accordion: 'Advanced Configuration',
label: 'Usage',
moreInfoTooltip: 'Will the qr code be used once or multiple times',
defaultValue: 'single_use'
}),
fixed_amount: option.boolean.layout({
accordion: 'Advanced Configuration',
label: 'Fixed Amount',
moreInfoTooltip: 'Is the amount fixed',
defaultValue: true
}),
valid_till: option.string.layout({
accordion: 'Advanced Configuration',
label: 'Valid Till',
moreInfoTooltip: 'How long is the QR code valid till',
defaultValue: '900'
}),
saveUrlInVariableId: option.string.layout({
label: 'Save QR code image URL',
inputType: 'variableDropdown',
}),
}),
getSetVariableIds: (options) =>
options.saveUrlInVariableId ? [options.saveUrlInVariableId] : [],
run: {
server: async ({ credentials, options, variables, logs }) => {
if (!options.amount || !parseInt(options.amount))
return logs.add(
'Amount is empty. Please provide the amount to generate the QR code.'
)
if (!options.saveUrlInVariableId)
return logs.add(
'QR code image URL is not specified. Please select a variable to save the generated QR code image.'
)
const delta = parseInt(options.valid_till ?? '900')
const close_by = delta > 900 ? Math.floor(Date.now() / 1000) + delta : Math.floor(Date.now() / 1000) + 900
const notes: Record<string, string> = {}
notes[options.uidLabel ?? 'vdsid'] = options.uid ?? `${close_by}`
try {
const qrcode = {
"type": "upi_qr",
"name": options.name,
"usage": options.usage ?? 'single_use',
"fixed_amount": options.fixed_amount ?? true,
"payment_amount": options.amount,
"description": `For ${options.name ?? 'Razorpay'}`,
"close_by": close_by,
"notes": notes
}
const response: Record<string, string> = await got.post(`${apiBaseUrl}/payments/qr_codes`, {
headers: {
"Content-Type": "application/json"
},
username: options.keyId,
password: credentials.keySecret,
json: qrcode,
})
.json()
const url = await uploadFileToBucket({
file: await generateQrCodeBuffer(response.image_content),
key: `tmp/qrcodes/${createId() + createId()}.png`,
mimeType: 'image/png',
})
variables.set(options.saveUrlInVariableId, url)
} catch (error) {
return logs.add(error as string)
}
},
},
})
const delta = parseInt(options.valid_till) || 900

Comment on lines 6 to 173
amount: options.amount,
keyId: options.keyId,
orderId: options.orderId ?? '',
uid: options.uid ?? null,
name: options.name ?? null,
email: options.email ?? null,
contact: options.contact ?? null,
currency: options.currency ?? defaultCurrency,
companyLogo: options.companyLogo ?? null,
companyName: options.companyName ?? null,
themeColor: options.themeColor ?? defaultThemeColor,
uidLabel: options.uidLabel ?? defaultUidLabel,
rzpScriptUrl: rzpScriptUrl
},
content: `
function TR() {
// Store callbacks for different actions
this.callbacks = {};

// Method to handle "init" action
this.init = function(callback) {
console.log('Initializing...');
window.rzp = this
const rzpScript = document.createElement('script');
rzpScript.src = rzpScriptUrl;
rzpScript.onload = function() {

const rzpButton = document.createElement('button');
rzpButton.classList.add("py-2", "px-4", "font-semibold", "focus:outline-none", "filter", "hover:brightness-90", "active:brightness-75", "disabled:opacity-50", "disabled:cursor-not-allowed", "disabled:brightness-100", "flex", "justify-center", "typebot-button", "w-full");
rzpButton.textContent = "Pay";

var rzpoptions = {
"key": keyId,
"amount": amount,
"currency": currency,
"name": companyName,
"description": companyName,
"image": companyLogo,
"order_id": orderId,
"prefill": {
"name": name,
"email": email,
"contact": contact
},
"handler": function (response) {

rzpButton.disabled = true;
rzpButton.classList.replace("typebot-button", "typebot-guest-bubble")

if (rzp.callbacks['success']) {
rzp.callbacks['success'](response);
}
},
"notes": {
uidLabel: uid
},
"theme": {
"color": themeColor
}
};
var rzp1 = new Razorpay(rzpoptions);

rzpButton.onclick = function(e){
rzp1.open();
e.preventDefault();
}

typebotElement.appendChild(rzpButton);
callback();

}
typebotElement.appendChild(rzpScript);
};

// Method to handle "on" action
this.on = function(options) {
if (options && options.action && options.callback) {

// Store the callback for the specified action
this.callbacks[options.action] = options.callback;
} else {
console.error('Invalid "on" action configuration');
}
};

}

const rzp1 = new TR();

rzp1.init(function() {
console.log('Initialization complete');
});

`,
}
},
},
},
},
})
Copy link

Choose a reason for hiding this comment

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

The createPaymentButton action is complex and includes inline JavaScript code for the web client. The action structure is correct, and the error handling is appropriate. However, the inline JavaScript code (lines 55-167) is difficult to maintain and could be prone to errors. It would be beneficial to extract this code into a separate file or module to improve maintainability and testability.

Consider refactoring the inline JavaScript code into a separate file or module to improve maintainability and testability.

Copy link

@coderabbitai coderabbitai bot left a comment

Choose a reason for hiding this comment

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

Review Status

Actionable comments generated: 0

Configuration used: CodeRabbit UI

Commits Files that changed from the base of the PR and between 3c3598b and a123fc1.
Files selected for processing (3)
  • packages/forge/blocks/razorpay/actions/createOrder.ts (1 hunks)
  • packages/forge/blocks/razorpay/actions/createQrCode.ts (1 hunks)
  • packages/forge/blocks/razorpay/actions/verifyPayment.ts (1 hunks)
Files skipped from review as they are similar to previous changes (3)
  • packages/forge/blocks/razorpay/actions/createOrder.ts
  • packages/forge/blocks/razorpay/actions/createQrCode.ts
  • packages/forge/blocks/razorpay/actions/verifyPayment.ts

Copy link

@coderabbitai coderabbitai bot left a comment

Choose a reason for hiding this comment

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

Review Status

Actionable comments generated: 0

Configuration used: CodeRabbit UI

Commits Files that changed from the base of the PR and between a123fc1 and d1f6d95.
Files ignored due to path filters (1)
  • pnpm-lock.yaml is excluded by: !**/*.yaml
Files selected for processing (1)
  • packages/forge/blocks/razorpay/actions/verifyPayment.ts (1 hunks)
Files skipped from review as they are similar to previous changes (1)
  • packages/forge/blocks/razorpay/actions/verifyPayment.ts

@dkashikar dkashikar marked this pull request as draft January 21, 2024 15:11
@baptisteArno
Copy link
Owner

Stalled. Feel free to re-open :)

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.

None yet

2 participants