1

We are trying to implement ApplePay on the web in my project. As per apple documentation i am getting the validation url from applejs api onvalidatemerchant function and i am passing this validation url to a node js route to get the apple payment session. This is the documentation i am following to get the apple payment session(https://developer.apple.com/documentation/apple_pay_on_the_web/apple_pay_js_api/requesting_an_apple_pay_payment_session).

The below is the custom node js code i have written to get the apple payment session. The validation url ie)req.query.url passed to this node js route code is https://apple-pay-gateway-cert.apple.com/paymentservices/startSession.

app.get('/getAppleSession2', function (req, res) {


  var endpointURL = req.query.url;
  var cert_path = './apple_pay.pem';
  var cert = fs.readFileSync(cert_path);
  console.log('endpointURL is ' + endpointURL);
  console.log('cert_path is ' + cert_path);
  console.log('cert is'+cert);
  const options = {
    url: endpointURL,
    method: 'post',
    cert: cert,
    key: cert,
    body: {
      merchantIdentifier: "xxxxx.xxxxx.xxxxx.xxxxx.xxxxx",
      displayName: "xxxxx.xxxxx.xxxxx.xxxxx.xxxxx",
      initiative: "web",
      initiativeContext: "xxxxx.xxxx.xxxx.xxxx.com"
    },
    json: true,
  };
  //console.log("body" + body);
  request(options, function (error, response, body) {
    console.log('body of  getAppleSession' + body);
    console.log('Response from getAppleSession' + response);
    console.error('Error object ' + error);

    res.send(body);
  });

});

But this is the response i am getting for this route

body of  getAppleSession undefined
Response from getAppleSession undefined
Error object Error: error:0906D06C:PEM routines:PEM_read_bio:no start line

Not sure what is wrong here as i am doing this as per apple's documentation. I suspect if it has anything to do with how i am passing the certs(Merchant Identity certificate)to this nodejs route. I generated the certificate by downloading the Merchant Identity certificate in .cer format from Apple Development portal and converted the certificate i downloaded from Apple portal to .pem format by importing the .cer file in KeyChain access in my mac and exporting it to .pem in keychain access. I then placed the .pem file('./apple_pay.pem') in same directory of my node js route. Is there anything wrong in how i am generating the certificates or passing them in my node js route?

Not sure what is wrong here. Any code sample or pointers will be really helpful.

vignesh d
  • 235
  • 3
  • 6
  • 15

3 Answers3

2

Seems like this is due to certificate validity related issue. Would you please ensure whether a self-signed certificate is valid.

Hope this may helps.

1

I might be late, but leaving a working solution here for anyone else who stumbles upon this same issue:

Before beginning with the creation of api for requesting the Apple Pay Session, you need to the create the payment processing and merchant identifier certificates. A detailed explanation can be found at this link:

At the end of the merchant identifier certificate process, you will be left with a .cer file. Double click on this file to add it to your keychain app.

After this, Go to your keychain, right click on certificate, and export it as PKCS #12 (.p12). You can then use openssl to convert this to a .pem file or you can use the .p12 directly (in nodejs with request. You need to set agentOptions as {pfx: p12File, and passphrase: '***'}.

My working solution for NodeJS is as below:

async validateMerchant(ctx) {
  let response = {};
  try {
    const options = {
      url: ctx.query.validationURL,
      agentOptions: {
        pfx: fs.readFileSync(
          path.resolve(__dirname, 'MerchantIDCertificate.p12')
        ),
        passphrase: '********',
      },
      method: 'post',
      body: {
        merchantIdentifier: 'merchant.***.***.*****',
        displayName: 'Your Store Name',
        initiative: 'web',
        initiativeContext: 'Verified.domain.com',
      },
      json: true,
    };
    response = await this.promisifyRequest(options);
  } catch (error) {
    logger.error(error);
  }
  return response;
}

promisifyRequest(options) {
  return new Promise((resolve, reject) => {
    request(options, (error, response, body) => {
      if (body) {
        console.log(response);
        return resolve(body);
      }
      if (error) {
        return reject(error);
      }
    });
  });
}

Salvino D'sa
  • 4,018
  • 1
  • 7
  • 19
0

Look here, how they use apple pay certificate:

enter image description here

Plus their docs are great, look here

Looks like we can also generate .pem file without .p12 file (according to their docs), which was an issue for me (because macOS disabled this format export in KeyChain Access, don't know why).

Another good tutorial: https://ionutghisoi.medium.com/apple-pay-example-payments-2-86ff893fdc9c and their example of code how to get payment session:

app.post('/validateSession', async (req, res) => {
    const { appleUrl } = req.body;

    // use set the certificates for the POST request
    httpsAgent = new https.Agent({
        rejectUnauthorized: false,
        cert: fs.readFileSync(path.join(__dirname, './certificate.pem')),
        key: fs.readFileSync(path.join(__dirname, './sandbox.key')),
    });

    response = await axios.post(
        appleUrl,
        {
            merchantIdentifier: 'your.apple.merchant.id',
            domainName: 'yourdomain.com',
            displayName: 'Your Shop Name',
        },
        {
            httpsAgent,
        }
    );
    res.send(response.data);
});
Alex Golovin
  • 232
  • 3
  • 6