0

Context: I'm tying to finish up a project that uses paypal subscriptions. The front end, with the users authenticated cookie in place, saves the subscription id to the company the user belongs to when they agree to the subscription. Then, when the webhook comes in from paypal I want to query the companies table to find which company the subscription webhook belongs to. I then intend to save the webhook data in its own table including the company ID it belongs to.

This would allow me to later run a service that goes through the webhooks table, and verify that each subscription is legit, and know what company the subscription is associated with.


This is the query, it needs to return the id of the company where the match it found:

SELECT id FROM companies WHERE json_contains(paymentData->'$[*].subscriptionID', json_array("I-5TEN0ATEN0ATF"));

My table schema looks like this:

id
name
settings
adminSettings
meta
paymentData
created
modified

My other queries not using json_contains work no problem, I assume this is something to do with the json_contains.

When I run the query in PHPMyAdmin, it finds the correct row and displays it on the screen with the json field where the match was found highlighted. Seems all good, but...

When I place this same query in my NodeJS API and execute it when a webhook comes in, I get a result without data, as if it's saying yes a match was found, but not going to give you any data. Why?

The ID of the company I expect to get, in this case, is 1. The following is the console output from my API, the query returns a variable called result which is an array with 2 entries, the first should contain the data, the second is the column schema:


Full Result:  [ [],
  [ FieldPacket {
      catalog: 'def',
      db: 'test',
      table: 'companies',
      orgTable: 'companies',
      name: 'id',
      orgName: 'id',
      charsetNr: 63,
      length: 255,
      type: 3,
      flags: 16899,
      decimals: 0,
      default: undefined,
      zeroFill: false,
      protocol41: true } ] ] 

Query from SQL Repository file:

module.exports = {
  [...],
  findCompanyBySubscriptionId: 'SELECT id FROM companies WHERE json_contains(paymentData->"$[*].subscriptionID", json_array("?"))',
   [...]
};

My API/Route Code:


var Promise = require('bluebird');
var mailer = require('../../plugins/mailer');
var paypal = require('paypal-rest-sdk'); // Include paypal sdk

// Set your configuration object
paypal.configure({
  'mode': 'sandbox', //sandbox or live
  'client_id': '---',
  'client_secret': '---'
});

module.exports = function (req, res) {
  let payload = req.body
  var SQLRep = req.app.locals.SQLRep; // Bring in my SQL queries
  
  req.app.locals.mysqlDB.getConnection((error, connection) => {
    return new Promise((resolve, reject) => {
      // Sends the webhook event data to PayPal to verify the webhook event signature is correct and
      // the event data came from PayPal.
      var headers = {
        'paypal-auth-algo': req.headers['paypal-auth-algo'],
        'paypal-cert-url': req.headers['paypal-cert-url'],
        'paypal-transmission-id': req.headers['paypal-transmission-id'],
        'paypal-transmission-sig': req.headers['paypal-transmission-sig'],
        'paypal-transmission-time': req.headers['paypal-transmission-time'] // style["text-align"]
      };

      console.log('payload: ', payload) // the post data coming in

      var webhookId = "1T966411BN030704L"; // hard code sample webhook ID, which does exist in the database

      return paypal.notification.webhookEvent.verify(headers, payload, webhookId, function (error, response) {
        if (error) {
          console.log('Verify error:', error, '');
          throw error;
        } else {
          if (response.verification_status === "SUCCESS") {
            resolve(response)
          } else {
            reject(response)
          }
        }
      })

    })

      .then(function (result) {

        if (result.verification_status === "SUCCESS" && payload.event_type == 'BILLING.SUBSCRIPTION.ACTIVATED') {
          // Save this webhook in the database webhooks table
          // Find a company with a matching subscription ID
          // If found, add the webhook ID to the company it belongs to
          return Promise.fromCallback(function (cb) {
            // findCompanyBySubscriptionId: 'SELECT id FROM companies WHERE JSON_EXTRACT(paymentData, "$.frontend") LIKE ?',
            return connection.query(SQLRep.findCompanyBySubscriptionId, [payload.resource.id], cb)
          }, { multiArgs: true })
            .then(function (result) {
              console.log("Full Result: ", result, '\n\n')
              return result
            })
        }
      })
      .then(() => {
        // res.status(504).send('Failed Validation'); // Let paypal this is a valid end point
        res.status(200).send('OK'); // Let paypal this is a valid end point
        console.log('sent status 200 OK\n\n--------------------------------------------------\n\n')
      })
      .finally(() => {
        connection.release();
      })
      .catch(e => {
        if (e.message == 'No Rows Returned') {
          return res.status(404).send({ 'error': e.message })
        } else if (e.message == 'invalid link or token') {
          return res.status(404).send({ 'error': e.message })
        } else if (e.message == 'invite expired') {
          return res.status(404).send({ 'error': e.message })
        } else if (e.message == 'missing required') {
          return res.status(404).send({ 'error': e.message })
        } else if (e.message) {
          return res.status(404).send({ 'error': e.message })
        }
        return res.sendStatus(500);
      })
  })
}
John
  • 976
  • 1
  • 15
  • 21
  • Always fun trying to debug a query pulled in from an invisible external locals and when the full `result` isn't logged – Preston PHX Jun 24 '20 at 20:38
  • lol my bad. Will update question – John Jun 24 '20 at 23:05
  • Added the SQL query and the full result set returned from the query in node. – John Jun 24 '20 at 23:25
  • Have you tried hardcoding the query to not use/ignore parameters and just be a string identical to what you ran from phpMyAdmin ? – Preston PHX Jun 25 '20 at 00:27
  • hmmm.....no, I don't think I have. I wrote the test query in phpmyadmin, copied it over and replaced the string I am searching for with a `?`. If I change the query from `SELECT id` to, say, `SELECT *` I still dont get data but that second array get's loaded with an entry for all the column names. I'll try hard coding the entire query and see if it's any different – John Jun 26 '20 at 16:53
  • Well, hardcoding the id returns data... – John Jun 26 '20 at 17:04
  • So it looks like the solution is to not place the quotes around the ? in the query...still testing – John Jun 26 '20 at 17:28

0 Answers0