Jump to content

Purchased Script - Help understanding file


zimmo

Recommended Posts

Hi All, Happy New Year to you all.

I purchased a script for a cms and within this it has a feature for memberships by subscription.

The person who wrote the script has not been very helpful at all. The script manages users and subscriptions with stripe. He told us that the recurring payments are all handled by a cron file. We run the cron file each night just before midnight. It should take a recurring payment for all those people who have a monthly recurring subscription.

However, what is happening is the script is removing all the expired members from the database, and it should renew any person who has a recurring payment. BUT IT IS NOT. 

The script is removing all the members whos account have expired but it fails to take any payment.

The script uses stripe for payments.

I wonder if anyone can see from the code below what is going on. I think the way the file runs (but I am not totally sure) is it removes the expired memberships and then as it has done this it thinks there are no renewals. When you run a file for a job in php does the script follow the order of the code within it?

Also, I noticed that on the stripe code it has the currency set to USD when it should be GBP as we are in the UK.

If you look a the code that the script runs when they first sign up and then compare it to the code for the renewals you can see it is different.

Can anyone help me, as the developer is no help at all and keeps telling me he has fixed it, when he has not as no renewal has taken place at all.

The code for the first part when the user signs up is as follows:

	             //Create a client
              $client = \Stripe\Customer::create(array(
                  "description" => App::Auth()->name,
                  "source" => $token['id'],
                  ));
              //Charge client
              $row = Db::run()->first(Membership::mTable, null, array("id" => $cart->mid));
              $charge = \Stripe\Charge::create(array(
                  "amount" => round($cart->total * 100, 0), // amount in cents, again
                  "currency" => $key->extra2,
                  "customer" => $client['id'],
                  "description" => $row->{'description' . Lang::$lang},
                  ));

 

Then we was told by the developer that this file should be run on a cron job using wget, which we have set up and it runs fine but does not do anything with the stripe recurring payments.

Cron File:

	  define("_WOJO", true);
  require_once("../init.php");
  
  Cron::Run(1);
	

 

Then there is a cron.class.php file which seems to contain the information for stripe

	  class Cron
  {
	
      /**
       * Cron::Run()
       * 
       * @return
       */
      public static function Run($days)
      {
          $data = self::expireMemberships($days);
          self::runStripe($days);
          self::sendEmails($data);
      }
	      /**
       * Cron::expireMemberships()
       * 
       * @param integer $days
       * @return
       */
      public static function expireMemberships($days)
      {
	          $sql = "
          SELECT 
            u.id, CONCAT(u.fname,' ',u.lname) as fullname,
            u.email, u.mem_expire, m.id AS mid, m.title 
          FROM
            `" . Users::mTable . "` AS u 
            LEFT JOIN `" . Membership::mTable . "` AS m 
              ON m.id = u.membership_id
          WHERE u.active = ?
          AND u.membership_id <> 0
          AND u.mem_expire <= DATE_ADD(DATE(NOW()), INTERVAL $days DAY);";
	          $result = Db::run()->pdoQuery($sql, array("y"))->results();
	          if ($result) {
              $query = "UPDATE `" . Users::mTable . "` SET mem_expire = NULL, membership_id = CASE ";
              $idlist = '';
              foreach ($result as $usr) {
                  $query .= " WHEN id = " . $usr->id . " THEN membership_id = 0";
                  $idlist .= $usr->id . ',';
              }
              $idlist = substr($idlist, 0, -1);
              $query .= "
                  END
                  WHERE id IN (" . $idlist . ")";
              Db::run()->pdoQuery($query);
          }
	      }
	      /**
       * Cron::sendEmails()
       * 
       * @param array $data
       * @return
       */
      public static function sendEmails($data)
      {
	          if ($data) {
              $numSent = 0;
              $mailer = Mailer::sendMail();
              $mailer->registerPlugin(new Swift_Plugins_AntiFloodPlugin(100, 30));
              $core = App::Core();
	              $tpl = Db::run()->first(Content::eTable, array("body", "subject"), array('typeid' => 'memExpired'));
	              $replacements = array();
              foreach ($data as $cols) {
                  $replacements[$cols->email] = array(
                      '[COMPANY]' => $core->company,
                      '[LOGO]' => Utility::getLogo(),
                      '[NAME]' => $cols->fullname,
                      '[ITEMNAME]' => $cols->title,
                      '[EXPIRE]' => Date::doDate("short_date", $cols->mem_expire),
                      '[SITEURL]' => SITEURL,
                      '[DATE]' => date('Y'),
                      '[FB]' => $core->social->facebook,
                      '[TW]' => $core->social->twitter,
                      );
              }
	              $decorator = new Swift_Plugins_DecoratorPlugin($replacements);
              $mailer->registerPlugin($decorator);
	              $message = Swift_Message::newInstance()
                      ->setSubject($tpl->subject)
                      ->setFrom(array($core->site_email => $core->company))
                      ->setBody($tpl->body, 'text/html');
	              foreach ($data as $row) {
                  $message->setTo(array($row->email => $row->fullname));
                  $numSent++;
                  $mailer->send($message, $failedRecipients);
              }
              unset($row);
          }
	      }
	      /**
       * Cron::runStripe()
       * 
       * @param bool $days
       * @return
       */
      public static function runStripe($days)
      {
          $sql = "
              SELECT 
                um.*,
                m.title,
                u.id as uid,
                m.price,
                u.email,
                u.stripe_cus,
                CONCAT(u.fname,' ',u.lname) as name
              FROM
                `" . Membership::umTable . "` AS um 
                LEFT JOIN `" . Membership::mTable . "` AS m 
                  ON m.id = um.mid
                LEFT JOIN `" . Users::mTable . "` AS u 
                  ON u.id = um.uid 
              WHERE um.active = ?
              AND um.recurring = ?
              AND TRIM(IFNULL(u.stripe_cus,'')) <> ''
              AND u.mem_expire <= DATE_ADD(DATE(NOW()), INTERVAL $days DAY)
              ORDER BY expire DESC;";
	          $data = Db::run()->pdoQuery($sql, array(1, 1))->results();
	          require_once (BASEPATH . 'gateways/stripe/stripe.php');
          $key = Db::run()->first(AdminController::gTable, array("extra"), array("name" => "stripe"));
          \Stripe\Stripe::setApiKey($key->extra);
	          if ($data) {
              try {
                  foreach ($data as $row) {
                      $tax = Membership::calculateTax($row->uid);
                      $charge = \Stripe\Charge::create(array(
                          "amount" => round(($row->price + $tax) * 100, 0), // amount in cents, again
                          "currency" => "usd",
                          "customer" => $row->stripe_cus,
                          ));
	                      // insert transaction
                      $data = array(
                          'txn_id' => $charge['balance_transaction'],
                          'membership_id' => $row->mid,
                          'user_id' => $row->uid,
                          'rate_amount' => $row->price,
                          'total' => Validator::sanitize($row->price * $tax, "float"),
                          'tax' => Validator::sanitize($tax, "float"),
                          'currency' => $charge['currency'],
                          'pp' => "Stripe",
                          'status' => 1,
                          );
	                      $last_id = Db::run()->insert(Membership::pTable, $data)->getLastInsertId();
	                      //update user membership
                      $udata = array(
                          'tid' => $last_id,
                          'uid' => $row->uid,
                          'mid' => $row->mid,
                          'expire' => Membership::calculateDays($row->mid),
                          'recurring' => 1,
                          'active' => 1,
                          );
	                      //update user record
                      $xdata = array(
                          'membership_id' => $row->id,
                          'mem_expire' => $udata['expire'],
                          );
	                      Db::run()->insert(Membership::umTable, $udata);
                      Db::run()->update(Users::mTable, $xdata, array("id" => $row->uid));
                  }
	              }
              catch (\Stripe\CardError $e) {
              }
          }
      }
  }
	

I noticed on this file that the currency section is not the same as the first file, so that led me to believe that was why nothing was happening as we deal in gbp only.

So, i changed this to gbp and ran the script manually, and all it did was remove the memberships from the users who were supposed to have a recurring payment.

So, my question can you see what is wrong with that code? I have been trying to get this developer to fix this for over a week now as we have a live website running and not taking a single recurring payment.

Please help in anyway you can?

 

 

 

 

Link to comment
Share on other sites

That is what I am on here for to get help as I don't fully understand this. 

In the file that the cron runs, I see this: 

public static function expireMemberships($days)

Which I think is the part which is removing the data. As the user will have an expired account when this runs, it will remove the data and then when it tries to renew the recurring payment there is nothing there as the script has already removed the data.

This is what I am unsure of?

Link to comment
Share on other sites

I have shown the code in the first part of the post?

      public static function expireMemberships($days)
      {
	          $sql = "
          SELECT 
            u.id, CONCAT(u.fname,' ',u.lname) as fullname,
            u.email, u.mem_expire, m.id AS mid, m.title 
          FROM
            `" . Users::mTable . "` AS u 
            LEFT JOIN `" . Membership::mTable . "` AS m 
              ON m.id = u.membership_id
          WHERE u.active = ?
          AND u.membership_id <> 0
          AND u.mem_expire <= DATE_ADD(DATE(NOW()), INTERVAL $days DAY);";
	          $result = Db::run()->pdoQuery($sql, array("y"))->results();
	          if ($result) {
              $query = "UPDATE `" . Users::mTable . "` SET mem_expire = NULL, membership_id = CASE ";
              $idlist = '';
              foreach ($result as $usr) {
                  $query .= " WHEN id = " . $usr->id . " THEN membership_id = 0";
                  $idlist .= $usr->id . ',';
              }
              $idlist = substr($idlist, 0, -1);
              $query .= "
                  END
                  WHERE id IN (" . $idlist . ")";
              Db::run()->pdoQuery($query);
          }
	      }
Link to comment
Share on other sites

Your very helpful eh.. this is why forums are going down hill, people like you with remarks like that. I expected this script to work! The person who sold it via a reputable website keeps telling me it is working, when clearly it is not as the cron file is supposed to renew these stripe payments and it is not so i am trying to get help to see if it is his code so i can go back to him.

Link to comment
Share on other sites

I hope that there is more to this query than what you just posted.....

Now that you have made yourself more clear(er), it makes a big difference in your problem.  So - now that the record still exists, what IS the problem you are having?

Posting a huge block of some class code that none of us are familiar with that goes knee-deep in method calls embedded in long statements is not something that people are going to leap out at and try and resolve for you.  You have to do some of your own debugging (as any good programmer would do) before asking for some understanding. 

Of course if you don't understand PHP itself, then my previous question still stands.

Link to comment
Share on other sites

Thank you...

The problem I have is with recurring payments. The developer told us that for the recurring payments to work we need to run the cron file which contains:

define("_WOJO", true);
  require_once("../init.php");
  
  Cron::Run(1);

This file then runs the a file called cron.class.php

What I found was there was differences in the code when a user first signs up with stripe to how the recurring payments via the cron job are done.

For example the stripe initial payment which works fine,  uses the currency field in the table via this string:

"currency" => $key->extra2,

But the cron class file contains this:

currency" => "usd",

Which I find strange as its not the same?

The other question I have is with a php file when it runs, does it go in order of the code, so if you have one function at the start which is removing the expired memberships, then the next function runs, which is the stripe process, but if it goes in order then it has already removed the data so stripe would think there is nothing to process?

Link to comment
Share on other sites

You have a lot to learn about programming.  I hope you didn't pay a lot for this script.

 

A function is only executed when the main-line code makes a call to it.  Think of functions as separate parts of code that can be called into play when needed.  Usually one places them at the end of a script.  The script usually starts with some housekeeping lines that setup some necessary things (like constants, a session_start call, some defined paths perhaps, switch settings) and then it will probably grab any user inputs from either the query string ($_GET parms) or a form ($_POST vars) and then process those inputs to see what is to be done with them.  Validation is a key part of this process to make sure that the input is what is to be expected and that it is not "bad" input put there by a "bad" user.  If there's a problem, your script will usually send the data back to the user in the form again, or send back an error message only.  If the input is good then the script continues on with the main-line code and does what it is supposed to do.  During this part is when functions and class methods get referenced/called.

Link to comment
Share on other sites

I do indeed have lots to learn.. I totally understand that.

I am just annoyed that the chap is not giving the support he should and keeps telling me it is working, when not one single renewed payment has gone through. it does not help that his documentation is limited.

One question then.

The cron file is ran with wget and then it should process any renewals, but what we are finding is the script is just updating the user membership and removing their expiry date and membership access and not actual doing anything with stripe, which is the part I find hard to understand. 

We was told by the developer that we did not need to set up any subscriptions within stripe itself and that the cron file would handle all the renewals when it is not.

Link to comment
Share on other sites

wget?  stripe?  Unknowns to me. 

Do you have the documentation on what your inputs to the cron job have to look like?  Or is the cron job examining your entire db looking for certain conditions on each record to decide if it needs an update?

 

PS  -

"The cron file is RUN...."

... "and not ACTUALLY doing..."

"We WERE told".

Proper English can only lead to better communications skills when discussing programming issues...

Link to comment
Share on other sites

For all you know I could have a learning disability. I find you to be a little arrogant, we are not all at your level. We are just looking for help. Thanks anyway, I think I will refrain from using this forum as this kind of answer is not in the slightest helpful. Stripe = Payment processor, wget is the command that runs the cron file. Thanks anyway. 

Link to comment
Share on other sites

I don't think you have a learning disability.  I think you have a prevalence for not caring how you are perceived and thus do not make the effort to learn.  Arrogant?  Nah....  Just a person who cares.  And I am trying to help you.  You however must have difficulty with reading comprehension since you completely ignored my questions in order to post your unhelpful comments.

Hope you have better luck wherever you end up.

PS - I have several running cron jobs that do things for me on a regular schedule.  None of which have ever required me to become familiar with something call 'wget'.  Lucky me.

Edited by ginerjm
Link to comment
Share on other sites

I am having a bad day... look I APOLOGISE I really do.

This script has driven me nuts. The documentation is limited, so we had to use the online support page which is basically a comments page.

This is what his documentation stated:

Make sure to set up a cronjob on /cron/cron.php. Run it every day using (wGet) just before midnight.

Cron job will automatically remove expired memberships, Stripe recurring, email notifications etc…

If you don’t know how to use CronJob, please contact your hosting company.

 

That was all we were told.

The cron file contains this:

<?php
  /**
   * Cron
   *
   */
  define("_WOJO", true);
  require_once("../init.php");
  
  Cron::Run(1);

There was no closing tag for this file, so with my limited knowledge, I assumed it ran the script.

The init.php files contain the following:

<?php

  if (!defined("_WOJO"))
      die('Direct access to this location is not allowed.');

  $BASEPATH = str_replace("init.php", "", realpath(__FILE__));
  define("BASEPATH", $BASEPATH);
  
  $configFile = BASEPATH . "lib/config.ini.php";
  if (file_exists($configFile)) {
      require_once($configFile);
  } else {
      header("Location: setup/");
      exit;
  }

  require_once (BASEPATH . "bootstrap.php");
  Bootstrap::init();
  wError::run();
  Filter::run();
  Lang::Run();
  Debug::run();

  define("ADMIN", BASEPATH . "admin/");
  define("FRONT", BASEPATH . "front/");
  
  $dir = (App::Core()->site_dir) ? '/' . App::Core()->site_dir : '';
  $url = preg_replace("#/+#", "/", $_SERVER['HTTP_HOST'] . $dir);
  $site_url = Url::protocol() . "://" . $url;
  
  define("SITEURL", $site_url);
  define("UPLOADURL", SITEURL . '/uploads');
  define("UPLOADS", BASEPATH . 'uploads');
  
  define("ADMINURL", SITEURL . '/admin');
  define("ADMINVIEW", SITEURL . '/view/admin');
  define("ADMINBASE", BASEPATH . 'view/admin');
  
  define("FRONTVIEW", SITEURL . '/view/front');
  define("FRONTBASE", BASEPATH . 'view/front');

  define("THEMEURL", FRONTVIEW . '/themes/' . App::Core()->theme);
  define("THEMEBASE", FRONTBASE . '/themes/' . App::Core()->theme);
  
  define("AMODPATH", ADMINBASE . "/modules_/");
  define("AMODULEURL", ADMINVIEW . "/modules_/");
  define("APLUGPATH", ADMINBASE . "/plugins_/");
  define("APLUGINURL", ADMINVIEW . "/plugins_/");

  define("FMODPATH", FRONTBASE . "/modules_/");
  define("FMODULEURL", FRONTVIEW . "/modules_/");
  define("FPLUGPATH", FRONTBASE . "/plugins_/");
  define("FPLUGINURL", FRONTVIEW . "/plugins_/");

That is all we were told. I asked my hosting company and they stated it was using a file called cron.class.php

 

Link to comment
Share on other sites

Well this script doesn't really do much.  Apparently the cron.class script is the guts.  Have you looked at it yet? 

I suggest you put these 2 together as one test script and then run it manually without cron.  Against a test database table too unless you don't yet care about the 'real' table's contents.  Add some echo statements to see what is happening or not happening to help you debug it.

Link to comment
Share on other sites

OP, you are incorrect.

1 hour ago, zimmo said:

wget is the command that runs the cron file

That is incorrect. It is the other way around .

Quote

GNU Wget is a free software package for retrieving files using HTTP, HTTPS, FTP and FTPS

 

Quote

The software utility cron is a time-based job scheduler in Unix-like computer operating systems . Cron is most suitable for scheduling repetitive tasks.

 

Edited by benanamen
Link to comment
Share on other sites

Thanks for the replies again. 

I will do some testing. This is what the cron.class.php file looks like, can you make anything from this, with your expertise :) thanks again.

<?php

  /**
   * Cron Class
   */

  if (!defined("_WOJO"))
      die('Direct access to this location is not allowed.');

  class Cron
  {


      /**
       * Cron::Run()
       * 
       * @return
       */
      public function Run($days)
      {
          $data = self::expireMemberships($days);
          self::runStripe($days);
          self::sendEmails($data);
      }

      /**
       * Cron::expireMemberships()
       * 
       * @param integer $days
       * @return
       */
      public static function expireMemberships($days)
      {

          $sql = "
          SELECT 
            u.id, CONCAT(u.fname,' ',u.lname) as fullname,
            u.email, u.mem_expire, m.id AS mid, m.title" . Lang::$lang . " as title  
          FROM
            `" . Users::mTable . "` AS u 
            LEFT JOIN `" . Membership::mTable . "` AS m 
              ON m.id = u.membership_id
          WHERE u.active = ?
          AND u.membership_id <> 0
          AND u.mem_expire <= DATE_ADD(DATE(NOW()), INTERVAL $days DAY);";

          $result = Db::run()->pdoQuery($sql, array("y"))->results();

          if ($result) {
              $query = "UPDATE `" . Users::mTable . "` SET mem_expire = NULL, membership_id = CASE ";
              $idlist = '';
              foreach ($result as $usr) {
                  $query .= " WHEN id = " . $usr->id . " THEN membership_id = 0";
                  $idlist .= $usr->id . ',';
              }
              $idlist = substr($idlist, 0, -1);
              $query .= "
                  END
                  WHERE id IN (" . $idlist . ")";
              Db::run()->pdoQuery($query);
          }

      }

      /**
       * Cron::sendEmails()
       * 
       * @param array $data
       * @return
       */
      public static function sendEmails($data)
      {

          if ($data) {
              $numSent = 0;
              $mailer = Mailer::sendMail();
              $mailer->registerPlugin(new Swift_Plugins_AntiFloodPlugin(100, 30));
              $core = App::Core();

              $tpl = Db::run()->first(Content::eTable, array("body", "subject"), array('typeid' => 'memExpired'));

              $replacements = array();
              foreach ($data as $cols) {
                  $replacements[$cols->email] = array(
                      '[COMPANY]' => $core->company,
                      '[LOGO]' => Utility::getLogo(),
                      '[NAME]' => $cols->fullname,
                      '[ITEMNAME]' => $cols->title,
                      '[EXPIRE]' => Date::doDate("short_date", $cols->mem_expire),
                      '[SITEURL]' => SITEURL,
                      '[DATE]' => date('Y'),
                      '[FB]' => $core->social->facebook,
                      '[TW]' => $core->social->twitter,
                      );
              }

              $decorator = new Swift_Plugins_DecoratorPlugin($replacements);
              $mailer->registerPlugin($decorator);

              $message = Swift_Message::newInstance()
                      ->setSubject($tpl->subject)
                      ->setFrom(array($core->site_email => $core->company))
                      ->setBody($tpl->body, 'text/html');

              foreach ($data as $row) {
                  $message->setTo(array($row->email => $row->fullname));
                  $numSent++;
                  $mailer->send($message, $failedRecipients);
              }
              unset($row);
          }

      }

      /**
       * Cron::runStripe()
       * 
       * @param bool $days
       * @return
       */
      public static function runStripe($days)
      {
          $sql = "
              SELECT 
                um.*,
                m.title" . Lang::$lang . " as title,
                u.id as uid,
                m.price,
                u.email,
                u.stripe_cus,
                CONCAT(u.fname,' ',u.lname) as name
              FROM
                `" . Membership::umTable . "` AS um 
                LEFT JOIN `" . Membership::mTable . "` AS m 
                  ON m.id = um.mid
                LEFT JOIN `" . Users::mTable . "` AS u 
                  ON u.id = um.uid 
              WHERE um.active = ?
              AND um.recurring = ?
              AND TRIM(IFNULL(u.stripe_cus,'')) <> ''
              AND u.mem_expire <= DATE_ADD(DATE(NOW()), INTERVAL $days DAY)
              ORDER BY expire DESC;";

          $data = Db::run()->pdoQuery($sql, array(1, 1))->results();

          require_once (BASEPATH . 'gateways/stripe/stripe.php');
          $key = Db::run()->first(Core::gTable, array("extra"), array("name" => "stripe"));
          \Stripe\Stripe::setApiKey($key->extra);

          if ($data) {
              try {
                  foreach ($data as $row) {
                      $tax = Membership::calculateTax($row->uid);
                      $charge = \Stripe\Charge::create(array(
                          "amount" => round(($row->price + $tax) * 100, 0), // amount in cents, again
                          "currency" => "usd",
                          "customer" => $row->stripe_cus,
                          ));

                      // insert transaction
                      $data = array(
                          'txn_id' => $charge['balance_transaction'],
                          'membership_id' => $row->mid,
                          'user_id' => $row->uid,
                          'rate_amount' => $row->price,
                          'total' => Validator::sanitize($row->price * $tax, "float"),
                          'tax' => Validator::sanitize($tax, "float"),
                          'currency' => $charge['currency'],
                          'pp' => "Stripe",
                          'status' => 1,
                          );

                      $last_id = Db::run()->insert(Membership::pTable, $data)->getLastInsertId();

                      //update user membership
                      $udata = array(
                          'tid' => $last_id,
                          'uid' => $row->uid,
                          'mid' => $row->mid,
                          'expire' => Membership::calculateDays($row->mid),
                          'recurring' => 1,
                          'active' => 1,
                          );

                      //update user record
                      $xdata = array(
                          'membership_id' => $row->id,
                          'mem_expire' => $udata['expire'],
                          );

                      Db::run()->insert(Membership::umTable, $udata);
                      Db::run()->update(Users::mTable, $xdata, array("id" => $row->uid));
                  }

              }
              catch (\Stripe\CardError $e) {
              }
          }
      }
  }

Link to comment
Share on other sites

NO - because I do not wish to delve into your massive code - purchased or not - to find your issue.  That is the programmer's job as I mentioned earlier. Posting an entire class definition online is not the best way to get help for free.  You need to adopt this code that you have bought and get familiar with it and only THEN when you think you have found something that a) you don't understand or b) you think is the problem, should you then post that part and explain what you think it isn't doing.

Link to comment
Share on other sites

This thread is more than a year old. Please don't revive it unless you have something important to add.

Join the conversation

You can post now and register later. If you have an account, sign in now to post with your account.

Guest
Reply to this topic...

×   Pasted as rich text.   Restore formatting

  Only 75 emoji are allowed.

×   Your link has been automatically embedded.   Display as a link instead

×   Your previous content has been restored.   Clear editor

×   You cannot paste images directly. Upload or insert images from URL.

×
×
  • Create New...

Important Information

We have placed cookies on your device to help make this website better. You can adjust your cookie settings, otherwise we'll assume you're okay to continue.