mollie / mollie-api-node

Official Mollie API client for Node
http://www.mollie.com
BSD 3-Clause "New" or "Revised" License
237 stars 63 forks source link

Client fails to import pem file on AWS lambda #105

Closed danlutz closed 4 years ago

danlutz commented 5 years ago

Because of a known problem with the __dirname variable in serverless lambda functions, it is not possible to use the mollie-api-node module in a serverless environment.

See: https://github.com/serverless/serverless/issues/4778

A possible fix would be to inline the pem file as part of the build process of the module, or somehow work around using __dirname in /dist/mollie.js on line 35:

options.httpsAgent = new https.Agent({
    cert: fs.readFileSync(path.resolve(__dirname, cert))
});

If you have any other solutions for this issue, I would be glad to hear about it

smonist commented 5 years ago

i ran into the same problem yesterday - i fixed it by using raw-loader and replacing the fs.readFileSync(path.resolve(__dirname, cert)) call with a require at the top of the file. its a quick workaround, if there are better solutions please let me know!

danlutz commented 5 years ago

Nice solution! Did you fork the module for this? Our solution was to just manually implement the apis we needed, but it would be much nicer to use the official client 👍

smonist commented 5 years ago

nope, not yet. but i will propably create a fork tomorrow :)

TheDancingCode commented 5 years ago

Having the same issue.

smonist commented 5 years ago

i changed a few small things in their config files and finally got their module bundler to inline the .pem file enjoy: https://github.com/smonist/mollie-api-node-inline-pem

github-actions[bot] commented 5 years ago

This issue is stale because it has been open 30 days with no activity. Remove stale label or comment or this will be closed in 5 days.

kokeksibir commented 5 years ago

If you use webpack (probably because you are developing typescript) then here is my workaround:

  1. Mollie calculates the path of certificate using __dirname. I used string-replace-loader to replace __dirname in mollie code with process.env.LAMBDA_TASK_ROOT

    rules: [
      ...
      {
        test: /mollie(.cjs|.esm)?\.js$/,
        loader: "string-replace-loader",
        options: {
          search: "__dirname",
          replace: "process.env.LAMBDA_TASK_ROOT",
          flags: "i"
        }
      }
    ]
    }
  2. I used copy-webpack-plugin plugin to copy the certificate to distribution folder

    plugins: [
    new CopyPlugin([
      {
        from: "node_modules/@mollie/api-client/dist/cacert.pem",
        to: "./",
        flatten: true
      }
    ])
    ]
niklas-may commented 4 years ago

i changed a few small things in their config files and finally got their module bundler to inline the .pem file enjoy: https://github.com/smonist/mollie-api-node-inline-pem

I ran into the same problem trying to integrate mollie with gatsby and netlify functions

@smonist can you help me on how to use your version, i guess i can not npm install it?

smonist commented 4 years ago

i changed a few small things in their config files and finally got their module bundler to inline the .pem file enjoy: https://github.com/smonist/mollie-api-node-inline-pem

I ran into the same problem trying to integrate mollie with gatsby and netlify functions

@smonist can you help me on how to use your version, i guess i can not npm install it?

Hi,

I basically changed the rollup.config.js file to include the .pem file in the source code. Take a look at my commits here: https://github.com/smonist/mollie-api-node-inline-pem/commits/master

But after looking at the source code of the mollie library i decided it was not worth it. I am using this function instead, which is basically doing exactly the same thing as the library:

//CREATE A PAYMENT AND RETURN ITS ID
async function molliePaymentRequest(data: object = {}) {
    let result: any = await fetch('https://api.mollie.com/v2/payments', {
        method: 'post',
        body:    JSON.stringify(data),
        headers: {
            'Content-Type': 'application/json',
            'Authorization': `Bearer ${process.env.mollieAPIKey}`
        }
    });

    result = await result.json();

    if (isDefined(result.id) && isDefined(result.status) && isDefined(result._links.checkout.href)) {
        return result;
    } else {
        throw 'no id/checkout url in mollie response';
    }
}
niklas-may commented 4 years ago

thank you for your help @smonist. This looks great!

But i get an error that seams to be related to the data that I pass into the body of the post request:

result Promise {
  <rejected> TypeError: o is not a function
      at n.amount.currency ... 

amount.currency is the first property of of the object i pass into body. I do not know where the "n" and the "o" are coming from.

Here is the function, how I call it and the data I call it with. Am i missing something?

async function molliePaymentRequest(data) {
    let result = await fetch('https://api.mollie.com/v2/payments', {
          method: 'post',
          body:    JSON.stringify(data),
          headers: {
            'Content-Type': 'application/json',
            'Authorization': `Bearer ${process.env.mollieAPIKey}`
          }
      });

    result = await result.json();

    if (isDefined(result.id) && isDefined(result.status) && isDefined(result._links.checkout.href)) {
      return result;
    } else {
      throw 'no id/checkout url in mollie response';
    }
  }

  const request = {
    amount: {
      currency: 'EUR',
      value: '10.00',
    },
    description: 'My first payment',
  }

  const result = molliePaymentRequest(request)

  console.log("result", result)
smonist commented 4 years ago

Hi,

take a look at the api docs: https://docs.mollie.com/reference/v2/payments-api/create-payment you are missing the parameter 'redirectUrl'.

I think the Promise error you are getting is because you are using an async function (molliePaymentRequest) without await. This is the code I used:

//CREATE PAYMENT
    const paymentData = {
        amount: {
            value: totalPrice.toFixed(2),
            currency: 'EUR'
        },
        description: 'Your compensation with xxx',
        redirectUrl: 'https://www.xxx.com/en/thank-you',
        webhookUrl:  process.env.webhookUrl,
        metadata: {
            'orderID': thisOrderID,
            order
        }
    }

let payment;
    try {
        payment = await molliePaymentRequest(paymentData);
    } catch (e) {
        console.error(e);
        return badRequestReturn;
    }
edblocker commented 4 years ago

@smonist is it possible to create a pull request for your solution? Your fork has been a little outdated compared to the latest version of the plugin. And there a more people experiencing this problem.

regreenat commented 4 years ago

@edblocker I originally wanted to create a pull request but then I ended up using just this one simple function instead of the whole library. This is way easier than modifying the whole library. Take a look at the code snippet i posted here, I am sure it will help you: https://github.com/mollie/mollie-api-node/issues/105#issuecomment-605466479

edblocker commented 4 years ago

@regreenat I will probably do the same, thanks! But I also think it would be nice if the solution was included in the repository. For people who're using more functionality and want to use the libary :)

JoschuaSchneider commented 4 years ago

I'm running into this issue on vercel.

Using the client in a vercel serverless function breaks with Error: ENOENT: no such file or directory, open '/var/task/node_modules/@mollie/api-client/dist/cacert.pem'

Pretty frustrating, we can't go live with our payments. And the proposed webpack changes (for me in next.config.js) won't fix it.

Does anyone have experience with mollie and vercel? I really don't want to re-implement this whole library myself.

Pimm commented 4 years ago

@JoschuaSchneider We have been dabbling with the idea of bundling the certificates into the JavaScript file. This should fix this issue. (See https://github.com/mollie/mollie-api-node/commit/966044314aca0810b918756e503e03b199d85f6f if you are interested.)

I will bring this up internally once again and keep you posted.

Pimm commented 4 years ago

This should be fixed in version 3.2.4.