1

I am trying to detect status of invoice from a json file, then if the status is a confirmed payment, update the status and write the json to a new location, then unlink the existing json location.

<?php
  // get posted variables or die;
  if (isset($_POST['num'])) {
    $invoice = strip_tags($_POST['num']);
    $filename = $invoice.'.json';
  } else {
    die;
  }
  if (isset($_POST['status'])) {
    $status = strip_tags($_POST['status']);
  } else {
    die;
  }

  // get existing invoice 
  $content = file_get_contents('data/'.$invoice.'.json');
  $data = json_decode($content, true);

  // read json into variables
  $email =  $data['email'];
  $id = $data['id'];
  $addr = $data['tac_address'];
  $os = $data['os'];
  $exp = $data['experience'];
  $hosting = $data['type'];
  if (isset($data['telegram']) && $data['telegram'] != '') { $telegram = $data['telegram']; } else { $telegram = ''; }
  if (isset($data['linkedin']) && $data['linkedin'] != '') { $linkedin = $data['linkedin']; } else { $linkedin = ''; }
  if (isset($data['pay_status']) && $data['pay_status'] != '' && $data['pay_status'] == $status) { $status = $data['pay_status']; }
  $payment_addr = $data['bitcoin'];
  $payment_value = $data['value'];
  $payment =  substr($payment_value, 0, -4);

  // turn variables into json array
  $arr = array(
    'id' => $invoice,
    'email' => $email,
    'tac_address' => $addr,
    'os' => $os,
    'experience' => $exp,
    'type' => $hosting,
    'telegram' => $telegram,
    'linkedin' => $linkedin,
    'bitcoin' => $payment_addr,
    'value' => $payment_value,
    'pay_status' => $status
  );
  $json = json_encode($arr);

  // check status if paid save output to new location and delete old file
  if ($status == 'Confirmed Payment') {
    file_put_contents('paid_data/'.$filename, $json);
    unlink('data/'.$filename);
  }

The problem I am facing is that file_put_contents('paid_data/'.$filename, $json); ends up a file with a bunch of NULL variables. If I remove the unlink the variables save just fine, when I add it back the variables are all NULL.

So how can I verify file_put_contents takes place before the unlinking happens?

Also.... WHY does this happen? Isn't php supposed to be linear and shouldn't file_put_contents finish before the next line is carried out? Everything I have read about file_put_contents suggests as much. So why does the unlink take place before writing the content to a new location?

Bruce
  • 1,039
  • 1
  • 9
  • 31
  • " // read json into variables ... // turn variables into json array" they already were in a variable called `$data`. All these extra variables have no effect but to make sure you drop any json data you didn't explicitly account for. – erik258 Sep 15 '21 at 19:19
  • Reading the `// read json into variables` allows me to update the `pay_status` variable before re-writing them to the new location. So `$data` would contain the json before updating the `pay_status` – Bruce Sep 15 '21 at 19:21
  • and yes I could just update `$data['pay_status']` within the array without rebuilding. I just find it easier to see whats going on this way. – Bruce Sep 15 '21 at 19:38
  • Is there any chance this script is being executed twice for each request? I could speculate about why that might happen, but adding a little "print debugging" should rule it out (or in) quickly. – A.K. Farrell Sep 15 '21 at 20:22

3 Answers3

0

I still hope for a better answer, but so far this is my working solution to the problem. I changed the final if statement to the following. This seems to solve the issue - but there really has to be a better way than this. This feels very "hacky".

if ($status == 'Confirmed Payment') {
  file_put_contents('paid_data/'.$filename, $json);
  $i = 0;
  while ($i < 1000) {
    $i++;
    if (file_exists('paid_data/'.$filename)) {
      unlink('data/'.$filename);
      break;
    }
  }
}
Bruce
  • 1,039
  • 1
  • 9
  • 31
0

After mimicking your file structure and seeding a few examples, I was able to execute your code as is with the expected results. However, file_put_contents willreturn false on failure, so you might try something like this:

 if ($status == 'Confirmed Payment') {
  if(!file_put_contents('paid_data/'.$filename, $json);){
    print_r(error_get_last());
    die;
  }
  unlink('data/'.$filename);
}
outlaw
  • 197
  • 8
0

Your code as originally written should be fine, as far as I can see. Usually when I see the kind of behavior you're describing, the problem is that the script itself is being called twice (or more) and overlapping calls are manipulating the same file.

I would definitely put in some debugging statements to verify this; I don't know your environment, but a simple line written to a log will probably be enlightening.

A.K. Farrell
  • 270
  • 3
  • 9