2

So I'm implementing a payment system with NMI gateway api. I've got everything working except for my update subscription function. To give a break down of how the NMI api works, you put in the required variables for the process you want done, in my case it's updating a subscription on a plan. So I've put the variables and used the POST directly to NMI to update the subscription with the variables that were passed in. I'm getting a response of ok and says it went through and updated subscription, however when I go to my merchant portal to make sure it worked, nothing has changed. To have recurring payments you first set up a plans and then users subscribe to the plans. I've got three different plans that the users should be able to Upgrade or Downgrade to.

Here is my utility function that will update the subscription on a plan

export const updateSubNmi = async ({
  subscription_id,
  plan_amount,
  plan_payments,
  day_frequency,
}) => {
  const data = {
    recurring: 'update_subscription',
    subscription_id: subscription_id,
    plan_amount: plan_amount,
    plan_payments: plan_payments,
    day_frequency: day_frequency,

    //These are the required variables to read and react with NMI gateway
    merchant_id: process.env.NMI_MERCHANT_ID,
    merchant_password: process.env.NMI_MERCHANT_PASSWORD,
    tokenization_key: process.env.NMI_TOKENIZATION_KEY,
    security_key: process.env.NMI_API_KEY,
  }
  console.log('data to pass in: ', data)

  const options = {
    method: 'POST',
    url: 'https://secure.nmi.com/api/transact.php',
    headers: {
      'Content-Type': 'application/x-www-form-urlencoded',
    },
    form: data,
  }
  return new Promise((resolve, reject) => {
    request(options, (err, response, body) => {
      if (err) {
        reject(err)
      } else {
        resolve(body, response)

        console.log(body)

        // console.log(response.body)
      }
    })
  })
}

export default updateSubNmi

Then I've set up a controller that awaits the above function then runs.

import expressAsyncHandler from 'express-async-handler'
import updateSubNmi from '../../Utils/nmiGatewayFunctions/nmiSubUpdate.js'
import Subscription from '../../models/Subscription.js'

export const updateNmiSub = expressAsyncHandler(async (req, res) => {
  try {
    const { subscription } = req.body
    const sub = await Subscription.findById(subscription._id)
    if (!sub) {
      return res.status(400).json({
        message: 'Subscription not found',
      })
    }
    try {
      if (sub.plan_id === '') {
        console.log(`Free Subscription: ${sub.plan_id}`)
      }
    } catch (error) {
      console.log(error)

      return res.status(500).json({
        success: false,
        message: err.message,
      })
    }
    await updateSubNmi(req.body)
    res.status(200).json({ message: `process finished` })
  } catch (error) {
    console.error(error)
    res.status(500).json({ message: `Server Error: ${error.message}` })
  }
})

export default updateNmiSub

This is my Postman request to send the body to the gateway. It responds with 200 OK and gives my my custom message I've set up as "process finished"

{
    "subscription": {
        "_id": "6256f0ab7417d91f8e080aec"
    },
    "subscription_id": "7146266977",
    "plan_amount": "49.99",
    "plan_payments": "0",
    "day_frequency": "30"
    
}

Once my route hits it gives me a response from gateway of Subscription Updated as you see below, however when I go the my merchant portal to ensure the subscription was updated to a different plan it's not showing changes.

response=1&responsetext=Subscription Updated&authcode=&transactionid=7146266977&avsresponse=&cvvresponse=&orderid=&type=&response_code=100&subscription_id=7146266977

There is obviously something I'm missing and have been stuck on this for a few days. Any help would be greatly appreciated.

HPierce
  • 7,249
  • 7
  • 33
  • 49
HacAtac
  • 31
  • 6

1 Answers1

1

Once a subscription is on a defined plan, the subscription’s plan cannot be updated. You’ll notice that documentation describes the plan_amount, plan_payments, day_frequency variables under the header titled:

Update a Custom Subscription's Plan Details

If the subscription you're attempting to edit uses a plan that's been saved in your account then these values are being ignored. Custom subscriptions are subscriptions that have their own plan that isn’t shared with other subscriptions.

To accommodate your use case, I’d suggest one of two approaches:

  1. When a customer wants to switch plans, you cancel the existing subscription and create a new subscription on the new plan.

Or:

  1. Use custom subscriptions instead of subscriptions on a named plan. To do this in the merchant portal, leave the “Save plan for future use” unchecked when creating subscriptions. If you’re using the Payments API to create subscriptions, use variables described under the “Adding a Custom Subscription” header in the documentation to create subscriptions.

enter image description here

HPierce
  • 7,249
  • 7
  • 33
  • 49
  • Fantastic, thanks so much! One question though, If I was to go the Custom Subscription route, would there even be a need for setting up plans? I'm trying to decide which day will be best. Canceling and recreating a subscription sounds good but at the same time it could cause some extra code like pro-rating for upgrades etc.. – HacAtac Apr 15 '22 at 01:59
  • I can't think of a reason why you would need to set up any plans if you used custom subscriptions exclusively. I would try to skip plans entirely. – HPierce Apr 15 '22 at 12:13