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

TypeError: Cannot read properties of undefined (reading 'event') #28

Open
balramxyadav opened this issue Oct 13, 2024 · 22 comments
Open

Comments

@balramxyadav
Copy link

When i try to integrate razorpay webhook with the plugin i get that error:
TypeError: Cannot read properties of undefined (reading 'event')

I also get this with alot of numbers:
info: Received Razorpay webhook body as object : {"type":"Buffer","data":

How can i make it work?

@balramxyadav
Copy link
Author

@SGFGOV - Can you help me here?

@SGFGOV
Copy link
Owner

SGFGOV commented Oct 13, 2024 via email

@balramxyadav
Copy link
Author

balramxyadav commented Oct 13, 2024

Now i am getting the webhook logged but my payment status is still awaiting in the medusa dashboard but the payment is actually captured.

info: Received Razorpay webhook body as object : {"entity":"event","account_id":"acc_P8De6sNJ1BGm7N","event":"payment.captured","contains":["payment"],"payload":{"payment":{"entity":{"id":"pay_P8Z9Xt31NCgYIA","entity":"payment","amount":155000,"currency":"INR","status":"captured","order_id":"order_P8Z8xDZqyZEIqJ","invoice_id":null,"international":false,"method":"wallet","amount_refunded":0,"refund_status":null,"captured":true,"description":"Order number order_P8Z8xDZqyZEIqJ","card_id":null,"bank":null,"wallet":"airtelmoney","vpa":null,"email”:”[email protected]","contact":"+912822193549","notes":{"resource_id":"cart_01J9N0WY3BQMBVDRADSYAGZ8TP"},"fee":3658,"tax":558,"error_code":null,"error_description":null,"error_source":null,"error_step":null,"error_reason":null,"acquirer_data":{"transaction_id":null},"created_at":1728832083,"reward":null,"base_amount":155000}}},"created_at":1728832087}

@balramxyadav
Copy link
Author

I am also have some problems implementing it in the frontend.

Sometimes i get:

Error: Functions cannot be passed directly to Client Components unless you explicitly expose it by marking it with "use server". Or maybe you meant to call this function rather than return it.

{transitional: ..., adapter: function, transformRequest: ..., transformResponse: ..., timeout: ..., xsrfCookieName: ..., xsrfHeaderName: ..., maxContentLength: ..., maxBodyLength: ..., validateStatus: ..., headers: ..., baseURL: ..., raxConfig: ..., method: ..., withCredentials: ..., url: ..., json: ..., data: ...}

When the order is being placed.

And sometimes i also get: TypeError: Cannot read properties of null (reading 'removeChild')

Can you help me with that too?

@balramxyadav
Copy link
Author

@SGFGOV

@RohitBansal272
Copy link

I am also getting buffer data as log

{"type":"Buffer","data":[]}
TypeError: Cannot read properties of undefined (reading 'event')
    at /Users/rohit/Desktop/******/node_modules/medusa-payment-razorpay/dist/api/hooks/razorpay.js:92:30
    at step (/Users/rohit/Desktop/******/node_modules/medusa-payment-razorpay/dist/api/hooks/razorpay.js:33:23)
    at Object.next (/Users/rohit/Desktop/******/node_modules/medusa-payment-razorpay/dist/api/hooks/razorpay.js:14:53)
    at /Users/rohit/Desktop/******/node_modules/medusa-payment-razorpay/dist/api/hooks/razorpay.js:8:71
    at new Promise (<anonymous>)
    at __awaiter (/Users/rohit/Desktop/******/node_modules/medusa-payment-razorpay/dist/api/hooks/razorpay.js:4:12)
    at /Users/rohit/Desktop/******/node_modules/medusa-payment-razorpay/dist/api/hooks/razorpay.js:44:49
    at /Users/rohit/Desktop/******/node_modules/@medusajs/medusa/dist/api/middlewares/await-middleware.js:58:42
    at step (/Users/rohit/Desktop/******/node_modules/@medusajs/medusa/dist/api/middlewares/await-middleware.js:33:23)
    at Object.next (/Users/rohit/Desktop/******/node_modules/@medusajs/medusa/dist/api/middlewares/await-middleware.js:14:53)

@balramxyadav
Copy link
Author

@RohitBansal272 Are you also getting Error: Functions cannot be passed directly to Client Components unless you explicitly expose it by marking it with "use server". Or maybe you meant to call this function rather than return it.

When it places the order, in the frontend?

My manual payment method works fine, but when i use the razorpay it doesnt work.

@RohitBansal272
Copy link

@balramxyadav I am using React Native but i faced the same error using the next.js storefront
Use this code in razorpay-payment-button.tsx

"use client"
import { Button } from "@medusajs/ui"
import { Cart,PaymentSession } from "@medusajs/medusa"
import Spinner from "@modules/common/icons/spinner"
import React, { useCallback, useState } from "react"
import { useRazorpay, RazorpayOrderOptions } from "react-razorpay";
import { placeOrder } from "@modules/checkout/actions"

const RazorpayPaymentButton = ({
  session,
  notReady,
  cart
}: {
  session: PaymentSession
  notReady: boolean
  cart: Omit<Cart, "refundable_amount" | "refunded_total">
}) => {
  const [disabled, setDisabled] = useState(false)
  const [submitting, setSubmitting] = useState(false)
  const [errorMessage, setErrorMessage] = useState<string | undefined>(undefined)
  const Razorpay = useRazorpay();

  const orderData = session.data as Record<string, string>
  const onPaymentCompleted = async () => {
    await placeOrder().catch(() => {
      setErrorMessage("An error occurred, please try again.")
      setSubmitting(false)
    })
  }


  const handlePayment = useCallback(() => {
    const options: RazorpayOrderOptions = {
      callback_url: `${process.env.NEXT_PUBLIC_MEDUSA_BACKEND_URL}/razorpay/hooks`,
      key: process.env.NEXT_PUBLIC_RAZORPAY_KEY ?? '',
      amount: session.amount,
      order_id: orderData.id,
      currency: cart.region.currency_code.toLocaleUpperCase(),
      name: process.env.COMPANY_NAME ?? "your company name ",
      description: `Order number ${orderData.id}`,

      image: "https://example.com/your_logo",
      modal: {
        backdropclose: true,
        escape: true,
        handleback: true,
        confirm_close: true,
        ondismiss: () => {
          setSubmitting(false)
        },
        animation: true,
      },
      handler: async (args) => {
        onPaymentCompleted()
      },
      "prefill": {
        "name": cart?.billing_address.first_name + " " + cart?.billing_address.last_name,
        "email": cart?.email,
        "contact": (cart?.shipping_address?.phone) ?? undefined
      }
    };

    const razorpay = new Razorpay.Razorpay(options);
    razorpay.open();
    razorpay.on("payment.failed", function (response: any) {
      console.log(response.error)
    })
    razorpay.on("payment.authorized", function (response: any) {

    })
    razorpay.on("payment.captured", function (response: any) {

    }
    )
  }, [Razorpay]);
  return (
    <>
      <Button
        disabled={submitting || notReady}
        onClick={handlePayment}
      >
        {submitting ? <Spinner /> : "Checkout"}
      </Button>
      {errorMessage && (
        <div className="text-red-500 text-small-regular mt-2">
          {errorMessage}
        </div>
      )}
    </>
  )
}

export default RazorpayPaymentButton

@Rohit3523
Copy link

@SGFGOV I have tried to resolve the issue and solved 50% of it, will try to open a tomorrow

The thing I did

  1. Convert the body response to json from buffer
  2. Optional chaining for getting cart id because for some events it trigger error

I am stuck with something related to event issue where is falls to default switch condition but the above one fixed the issue for few orders.

Also I guess the repo is out of sync because in ide I can see I am using 7.3.0-next version but GitHub has 7.3.0 as latest

@SGFGOV
Copy link
Owner

SGFGOV commented Oct 14, 2024

Are you using an iPhone?

@Rohit3523
Copy link

Rohit3523 commented Oct 14, 2024

I am using Android and haven't tested on iphone but does it matter because I have added webhook url in razorpay dashboard webhook section (not passing in razorpay options during checkout)

@balramxyadav
Copy link
Author

Does auto capture work with it? I can see the payment captured in razorpay but the status is not paid in medusa.

@Rohit3523
Copy link

@balramxyadav webhook is currently broken so it is not showing paid in medusa

@balramxyadav
Copy link
Author

Another problem: When I click on ‘Pay’ on mobile, it redirects me to a Razorpay page from the checkout, and then it sends me to the callback URL.

It works fine on desktop as the page only opens in a popup, and the state is retained to place the order. However, on mobile, it redirects directly to the callback URL.

One approach could be to create a new endpoint for the callback. Verify if the payment was successful. If yes, create an order and redirect directly to the confirmation page, and in case of failure, redirect to the checkout page. Is this the right approach, or how should this be handled?

@balramxyadav
Copy link
Author

@SGFGOV - Hey, i somehow made it work but it doesn't work it mobile becuase the razorpay redirects to the otp page and the handler func doesnt run on mobile. Can you help me?

@SGFGOV
Copy link
Owner

SGFGOV commented Oct 14, 2024

I have not tried using dart. Otherwise if it's the mobile web browser you remove the client side call back url in the ui

@SGFGOV
Copy link
Owner

SGFGOV commented Oct 14, 2024

I have not tried using dart. Otherwise if it's the mobile web browser you remove the client side call back url in the ui

Please use the latest version

@balramxyadav
Copy link
Author

I am trying something like

import { NextResponse } from "next/server"
import { cookies } from "next/headers" // Necessary for cookie handling
// Assuming this is where your completeCart function is
import { revalidateTag } from "next/cache" // Adjust as needed
import { completeCart } from "@lib/data"
import { redirect } from "next/navigation"
import { placeOrder } from "@modules/checkout/actions"

export async function POST() {
  try {
    // Place order and get the cart
    const cart = await placeOrder()

    console.log("From API:", cart)

    if (cart?.type === "order") {
      const countryCode =
        cart.data.shipping_address?.country_code?.toLowerCase()
      const orderId = cart.data.id
      const redirectUrl = `/${countryCode}/order/confirmed/${orderId}`

      redirect(redirectUrl)

      // return NextResponse.json({ success: true })
    }

    // If no order was created, return an error
    return NextResponse.json(
      { success: false, message: "Order could not be placed" },
      { status: 400 }
    )
  } catch (error: any) {
    // Handle errors and return an appropriate error message
    return NextResponse.json({ error: error.message }, { status: 500 })
  }
}

And putting the api route in the callback. Would a approach like this work? How would you approach it?

@Rohit3523
Copy link

@SGFGOV Any update regarding this issue?

@balramxyadav
Copy link
Author

@SGFGOV - After placing the order, the response I get from the ‘place order’ function is payment_status: 'requires_more', type: 'cart', even though the payment shows as completed in Razorpay.

I found this in the documentation:

‘Complete a cart and place an order or create a swap, based on the cart’s type. This includes attempting to authorize the cart’s payment. If authorizing the payment requires more action, the cart will not be completed, and the order will not be placed, or the swap will not be created.’

I believe the issue might be with the authorization process when the order is placed. How can I resolve this?

Also, for some reason, I’m getting the error:

⨯ Error: Functions cannot be passed directly to Client Components unless you explicitly expose it by marking it with “use server.” Or maybe you meant to call this function rather than return it.

How can I fix this?

More info:

There were some of these logs

error: An error occurred in updatePayment
Error: An error occurred in updatePayment
at PaymentProviderService.throwFromPaymentProcessorError (/Users/balram/Documents/Website/luxigro-production/medusajs-backend/node_modules/@medusajs/medusa/dist/services/payment-provider.js:1053:15)
at PaymentProviderService. (/Users/balram/Documents/Website/luxigro-production/medusajs-backend/node_modules/@medusajs/medusa/dist/services/payment-provider.js:401:50)
at step (/Users/balram/Documents/Website/luxigro-production/medusajs-backend/node_modules/@medusajs/medusa/dist/services/payment-provider.js:48:23)
at Object.next (/Users/balram/Documents/Website/luxigro-production/medusajs-backend/node_modules/@medusajs/medusa/dist/services/payment-provider.js:29:53)
at fulfilled (/Users/balram/Documents/Website/luxigro-production/medusajs-backend/node_modules/@medusajs/medusa/dist/services/payment-provider.js:20:58)
at process.processTicksAndRejections (node:internal/process/task_queues:95:5) {
type: 'invalid_data',
code: '',
date: 2024-10-16T09:13:17.875Z
}

Client side:

From action: {
data: {
object: 'cart',
id: 'cart_01JAA94S2Q6K5AHA5HT71TWJ8E',
created_at: '2024-10-16T09:04:33.988Z',
updated_at: '2024-10-16T09:05:34.973Z',
deleted_at: null,
email: '[email protected]',
billing_address_id: 'addr_01JAA96SS73B9PNQZ3WZ3DTARC',
shipping_address_id: 'addr_01JAA94S2R7FTNN06WA6Y5DJ51',
region_id: 'reg_01J8R7K5PMJRH82AD7EZSDKBSJ',
customer_id: 'cus_01JA8BCXKXPVPZTJCYB09VAK3W',
payment_id: null,
type: 'default',
completed_at: null,
payment_authorized_at: null,
idempotency_key: null,
context: { ip: '::1', user_agent: 'axios/0.24.0' },
metadata: null,
sales_channel_id: 'sc_01J8NYB0RRDVTP33YP40MH3ZGC',
payment_sessions: [ [Object] ],
payment_session: {
id: 'ps_01JAA95RR81FB278JB1KDWG46K',
created_at: '2024-10-16T09:05:06.716Z',
updated_at: '2024-10-16T09:32:51.052Z',
cart_id: 'cart_01JAA94S2Q6K5AHA5HT71TWJ8E',
provider_id: 'razorpay',
is_selected: true,
is_initiated: true,
status: 'requires_more',
data: [Object],
idempotency_key: null,
amount: 310000,
payment_authorized_at: null
}
},
payment_status: 'requires_more',
type: 'cart',
response: {
status: 200,
statusText: 'OK',
headers: {
'x-powered-by': 'Express',
vary: 'Origin',
'access-control-allow-credentials': 'true',
'access-control-expose-headers': 'Idempotency-Key',
'idempotency-key': '36260dcc-6c92-430f-9b74-453f3c3ae63a',
'content-type': 'application/json; charset=utf-8',
'content-length': '1881',
etag: 'W/"759-9Jw5dwDk7Szajmarjd0n0Xfen3s"',
'set-cookie': [Array],
date: 'Wed, 16 Oct 2024 09:33:02 GMT',
connection: 'keep-alive',
'keep-alive': 'timeout=5'
},
config: {
transitional: [Object],
adapter: [Function: httpAdapter],
transformRequest: [Array],
transformResponse: [Array],
timeout: 0,
xsrfCookieName: 'XSRF-TOKEN',
xsrfHeaderName: 'X-XSRF-TOKEN',
maxContentLength: -1,
maxBodyLength: -1,
validateStatus: [Function: validateStatus],
headers: [Object],
baseURL: 'http://localhost:9000',
raxConfig: [Object],
method: 'post',
withCredentials: true,
url: '/store/carts/cart_01JAA94S2Q6K5AHA5HT71TWJ8E/complete',
json: true,
data: '{}'
},
request: ClientRequest {
_events: [Object: null prototype],
_eventsCount: 7,
_maxListeners: undefined,
outputData: [],
outputSize: 0,
writable: true,
destroyed: true,
_last: false,
chunkedEncoding: false,
shouldKeepAlive: true,
maxRequestsOnConnectionReached: false,
_defaultKeepAlive: true,
useChunkedEncodingByDefault: true,
sendDate: false,
_removedConnection: false,
_removedContLen: false,
_removedTE: false,
strictContentLength: false,
_contentLength: 2,
_hasBody: true,
_trailer: '',
finished: true,
_headerSent: true,
_closed: true,
socket: [Socket],
_header: 'POST /store/carts/cart_01JAA94S2Q6K5AHA5HT71TWJ8E/complete HTTP/1.1\r\n' +
'Accept: application/json\r\n' +
'Content-Type: application/json\r\n' +
'Idempotency-Key: 73caff2e-df43-41a8-87b6-1febcb264bf5\r\n' +
'next: [object Object]\r\n' +
'authorization: \r\n' +
'User-Agent: axios/0.24.0\r\n' +
'Content-Length: 2\r\n' +
'Host: localhost:9000\r\n' +
'Connection: keep-alive\r\n' +
'\r\n',
_keepAliveTimeout: 0,
_onPendingData: [Function: nop],
agent: [Agent],
socketPath: undefined,
method: 'POST',
maxHeaderSize: undefined,
insecureHTTPParser: undefined,
joinDuplicateHeaders: undefined,
path: '/store/carts/cart_01JAA94S2Q6K5AHA5HT71TWJ8E/complete',
_ended: true,
res: [IncomingMessage],
aborted: false,
timeoutCb: null,
upgradeOrConnect: false,
parser: null,
maxHeadersCount: null,
reusedSocket: false,
host: 'localhost',
protocol: 'http:',
_redirectable: [Writable],
[Symbol(shapeMode)]: false,
[Symbol(kCapture)]: false,
[Symbol(kBytesWritten)]: 0,
[Symbol(kNeedDrain)]: false,
[Symbol(corked)]: 0,
[Symbol(kOutHeaders)]: [Object: null prototype],
[Symbol(errored)]: null,
[Symbol(kHighWaterMark)]: 16384,
[Symbol(kRejectNonStandardBodyWrites)]: false,
[Symbol(kUniqueHeaders)]: null
}
}
}

@mittalyashu
Copy link

I am getting this same error in the logs.

@SGFGOV
Copy link
Owner

SGFGOV commented Nov 4, 2024

Building a new plugin for v2. I think this will be addressed there

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 a pull request may close this issue.

5 participants