Zen Cart Logo
Forums / Code Collaboration / qz print tray 2.0.7 and printing from admin

qz print tray 2.0.7 and printing from admin

Views: 17,184

Results 1 to 15 of 15
26 Jul 2018, 12:29 AM
#1
lankeeyankee avatar

lankeeyankee

Totally Zenned

Join Date:
Jan 2007
Posts:
1,514
Plugin Contributions:
1

qz print tray 2.0.7 and printing from admin

I am trying to print labels directly from the zen cart admin when the print button is clicked. I am using qz print tray 2.0.7 and can get everything working correctly on their demo and feel that I have the js written almost correctly to get this to work. I need help with the last bit.

This is on a page to print shipping labels (a commercial mod), and it has most of the logic written above the html section. The trouble I am having is getting a variable from the logic passed to the javascript to complete the URL string. When the label is created a png file is also created, stored in the admin images folder and referenced in a DB table. I cannot seem to pass the variable for the file, either directly referenced or through the DB label.

My coding chops are so rusty it's not even funny. I could really use some help or pointers to get this working. When I print the image file name to an alert box it's empty, and the qz log console keeps saying it can't connect to the endpoint. So, it appears to me that the variable is not being recognized. I have spent many hours over the past few days trying many different things and come up empty.

Here's the code that creates the image file of the label, it's in a switch statement:

if (in_array(MODULE_SHIPPING_FEDEX_WEBSERVICES_LABELS_IMAGETYPE, array(
                        'PNG',
                        'PDF'
                    ))) {
                        $tracking_number_image = $tracking_number . '.' . strtolower(MODULE_SHIPPING_FEDEX_WEBSERVICES_LABELS_IMAGETYPE);
                        $fp                    = fopen(DIR_FS_ADMIN . 'images/fedex/' . $tracking_number_image, 'wb');
                        fwrite($fp, $response->CompletedShipmentDetail->CompletedPackageDetails->Label->Parts->Image); //Create PNG or PDF file
                        fclose($fp);
                    }
                    
                    $sql_data_array = array(
                        'orders_id' => $order_id,
                        'labels' => $tracking_number_image
                    );
                    zen_db_perform(DB_PREFIX . 'fedex_labels', $sql_data_array);

my javascript, which is loaded after the <body> tag:

 <script type="text/javascript">
function connectAndPrint() {
// our promise chain
    connect().then(function() {
        return print();
    }).then(function() {
        success();              // exceptions get thrown all the way up the stack
    }).catch(fail);             // so one catch is often enough for all promises
    
    // NOTE:  If a function returns a promise, you don't need to wrap it in a fuction call.
    //        The following is perfectly valid:
    //
    //        connect().then(print).then(success).catch(fail);
    //
    // Important, in this case success is NOT a promise, so it should stay wrapped in a function() to avoid confusion
}

// connection wrapper
//  - allows active and inactive connections to resolve regardless
//  - try to connect once before firing the mimetype launcher
//  - if connection fails, catch the reject, fire the mimetype launcher
//  - after mimetype launcher is fired, try to connect 3 more times
function connect() {
    return new RSVP.Promise(function(resolve, reject) {
        if (qz.websocket.isActive()) {    // if already active, resolve immediately
            resolve();
        } else {
            // try to connect once before firing the mimetype launcher
            qz.websocket.connect().then(resolve, function reject() {
                // if a connect was not succesful, launch the mimetime, try 3 more times
                window.location.assign("qz:launch");
                qz.websocket.connect({ retries: 2, delay: 1 }).then(resolve, reject);
            });
        }
    });
}

// print logic
function print() {
    var printer = "Zebra  ZP 450-200dpi";
    var options =  { size: { width: 4, height: 6}, units: "in", density: "600", language: "ZPL" };
    var config = qz.configs.create(printer, options); 
    var data = [{ type: 'png', format: 'image', flavor: 'file', data: 'images/fedex/<?php echo $fp; ?>' }];

    // return the promise so we can chain more .then().then().catch(), etc.
    return qz.print(config, data);
}

// notify successful print
function success() { 
    alert("Success");
}

// exception catch-all
function fail(e) {
    alert("Error: " + e);
}
</script>

So, as you can see in the js, I've got this line:

data: 'images/fedex/<?php echo $fp; ?>'

Which references the $fp variable from the above PHP section. I have tried do this, too, but still nothing:

<script type="text/javascript">
function connectAndPrint() {
    <?php $oID = zen_db_prepare_input($_GET['oID']);
$fedex_labels = $db->Execute('SELECT * FROM ' . DB_PREFIX . 'fedex_labels WHERE labels IS NOT NULL AND orders_id = ' . $oID . ' ORDER BY labels ASC;');
if ($fedex_labels->RecordCount() > 0) {
  while(!$fedex_labels->EOF) {
      $printLabel = print_var($fedex_labels);
  $fedex_labels->MoveNext();
}}
?>
    // our promise chain
    connect().then(function() {
.......

I've tried so many other things that I forget them now, kind of a blur hahaha. I am hoping it is something pretty straightforward, because I really need to get this to work. In a very busy warehouse, having to click through 3 times to print a label (as this mod is currently set up by default), it's a big time waster. That's why I am trying to get qz tray to work, so when the print button is clicked it just prints the label to the thermal printer.

I have no problem paying to get this done, but thought I would throw it out here first to see if someone had a suggestion first (mostly because I really want to know what I've done wrong and learn/grow from it, not because of the cost).

26 Jul 2018, 1:06 AM
#2
mc12345678 avatar

mc12345678

Totally Zenned

Join Date:
Jul 2012
Posts:
16,908
Plugin Contributions:
2

Re: qz print tray 2.0.7 and printing from admin

$fp in the first set of php code is a resource or could be thought of as a file pointer. It looks like you are instead wanting to reference the filename. The filename portion of the fopen function (which seems to reference the desired image) contains the full path to the file. What that seems to mean is that in your javascript instead of referencing $fp, you might want to reference/use: $tracking_number_image instead. Though there appears to be the possibility that $tracking_number_image may not be set if the criteria of the first if statement is not met. What that means is that the javascript may get broken or allow undesirable operations if the specific conditions are not met to support the follow-on javascript.

26 Jul 2018, 1:46 AM
#3
lankeeyankee avatar

lankeeyankee

Totally Zenned

Join Date:
Jan 2007
Posts:
1,514
Plugin Contributions:
1

Re: qz print tray 2.0.7 and printing from admin

Thanks for the reply! $tracking_number_image was my first try and it still came up blank. I could be way off on what I am trying to do, anyway. But, the tracking email fires off when the ship (print) button is clicked so I figured the image path would be set, too. Could it be that the image path would never be set until after the button is clicked and that is why it never gets added to the URL string? In that case, would I need to do some type of ajax or js refresh or a delayed execution to then pull the image path? Currently, I have the js firing as an onclick event on the button. I didn't know how else I might get it to execute after the fact. I tried including it within the switch statement so it would fire just like the email does but that didn't work, either. Of course, I could have gotten the code wrong :-)

26 Jul 2018, 10:21 PM
#4
carlwhat avatar

carlwhat

zennedOut

Join Date:
Nov 2005
Location:
los angeles
Posts:
2,953
Plugin Contributions:
8

Re: qz print tray 2.0.7 and printing from admin

lankeeyankee:

I am trying to print labels directly from the zen cart admin when the print button is clicked. I am using qz print tray 2.0.7 and can get everything working correctly on their demo and feel that I have the js written almost correctly to get this to work. I need help with the last bit.

This is on a page to print shipping labels (a commercial mod), and it has most of the logic written above the html section. The trouble I am having is getting a variable from the logic passed to the javascript to complete the URL string. When the label is created a png file is also created, stored in the admin images folder and referenced in a DB table. I cannot seem to pass the variable for the file, either directly referenced or through the DB label.

My coding chops are so rusty it's not even funny. I could really use some help or pointers to get this working. When I print the image file name to an alert box it's empty, and the qz log console keeps saying it can't connect to the endpoint. So, it appears to me that the variable is not being recognized. I have spent many hours over the past few days trying many different things and come up empty.

Here's the code that creates the image file of the label, it's in a switch statement:

if (in_array(MODULE_SHIPPING_FEDEX_WEBSERVICES_LABELS_IMAGETYPE, array(
'PNG',
'PDF'
))) {
$tracking_number_image = $tracking_number . '.' . strtolower(MODULE_SHIPPING_FEDEX_WEBSERVICES_LABELS_IMAGETYPE);
$fp = fopen(DIR_FS_ADMIN . 'images/fedex/' . $tracking_number_image, 'wb');
fwrite($fp, $response->CompletedShipmentDetail->CompletedPackageDetails->Label->Parts->Image); //Create PNG or PDF file
fclose($fp);
}

                $sql_data_array = array(
                    'orders_id' => $order_id,
                    'labels' => $tracking_number_image
                );
                zen_db_perform(DB_PREFIX . 'fedex_labels', $sql_data_array);
> my javascript, which is loaded after the <body> tag:
> ```
 <script type="text/javascript">
function connectAndPrint() {
// our promise chain
    connect().then(function() {
        return print();
    }).then(function() {
        success();              // exceptions get thrown all the way up the stack
    }).catch(fail);             // so one catch is often enough for all promises
    
    // NOTE:  If a function returns a promise, you don't need to wrap it in a fuction call.
    //        The following is perfectly valid:
    //
    //        connect().then(print).then(success).catch(fail);
    //
    // Important, in this case success is NOT a promise, so it should stay wrapped in a function() to avoid confusion
}

// connection wrapper
//  - allows active and inactive connections to resolve regardless
//  - try to connect once before firing the mimetype launcher
//  - if connection fails, catch the reject, fire the mimetype launcher
//  - after mimetype launcher is fired, try to connect 3 more times
function connect() {
    return new RSVP.Promise(function(resolve, reject) {
        if (qz.websocket.isActive()) {    // if already active, resolve immediately
            resolve();
        } else {
            // try to connect once before firing the mimetype launcher
            qz.websocket.connect().then(resolve, function reject() {
                // if a connect was not succesful, launch the mimetime, try 3 more times
                window.location.assign("qz:launch");
                qz.websocket.connect({ retries: 2, delay: 1 }).then(resolve, reject);
            });
        }
    });
}

// print logic
function print() {
    var printer = "Zebra  ZP 450-200dpi";
    var options =  { size: { width: 4, height: 6}, units: "in", density: "600", language: "ZPL" };
    var config = qz.configs.create(printer, options); 
    var data = [{ type: 'png', format: 'image', flavor: 'file', data: 'images/fedex/<?php echo $fp; ?>' }];

    // return the promise so we can chain more .then().then().catch(), etc.
    return qz.print(config, data);
}

// notify successful print
function success() { 
    alert("Success");
}

// exception catch-all
function fail(e) {
    alert("Error: " + e);
}
</script>

So, as you can see in the js, I've got this line:

data: 'images/fedex/<?php echo $fp; ?>'

> Which references the $fp variable from the above PHP section. I have tried do this, too, but still nothing:
> ```
<script type="text/javascript">
function connectAndPrint() {
    <?php $oID = zen_db_prepare_input($_GET['oID']);
$fedex_labels = $db->Execute('SELECT * FROM ' . DB_PREFIX . 'fedex_labels WHERE labels IS NOT NULL AND orders_id = ' . $oID . ' ORDER BY labels ASC;');
if ($fedex_labels->RecordCount() > 0) {
  while(!$fedex_labels->EOF) {
      $printLabel = print_var($fedex_labels);
  $fedex_labels->MoveNext();
}}
?>
    // our promise chain
    connect().then(function() {
.......

I've tried so many other things that I forget them now, kind of a blur hahaha. I am hoping it is something pretty straightforward, because I really need to get this to work. In a very busy warehouse, having to click through 3 times to print a label (as this mod is currently set up by default), it's a big time waster. That's why I am trying to get qz tray to work, so when the print button is clicked it just prints the label to the thermal printer.

I have no problem paying to get this done, but thought I would throw it out here first to see if someone had a suggestion first (mostly because I really want to know what I've done wrong and learn/grow from it, not because of the cost).

yankee,
you are either all over the place, or i'm not following.... but i will try to help.

lets go over your first bit of php code first. as you say you are creating an image file, and then inserting into your db in a new table, the order number and the name of the image file. my first question is does this part of the code work? and really there are 2 parts to that, the easy part of the question is the table being properly populated; and then the harder part is the image file properly constructed? ie can you print the image file directly to your chosen printer correctly? this may require you to make a copy of the file on your workstation as the image file is stored on the server. as you say, you are on the last bit, so i'm guessing you have gotten this part to work properly.

if you have tested that, and you know that works, we can then move on. i want to comment on your last bit of code that you have tried. i have no idea what the function print_var is. it is not listed as anything on php.net, so have you defined a function called that? i do not see any code for it that you have posted, so perhaps you can enlighten me what that might be. or is it part of the qz app?

in addition, you are passing this undefined function a database object. i have a very distinct feeling that the print_var function will not know what to do with the db object. i think the code for this undefined function more likely would be:

print_var($fedex_labels->fields['labels']);

i see no need to assign it to anything as you don't do anything with the result. and again i have no idea what print_var does.

now with regards to your javascript and the embedded php. my first question is whether this is in a php file or if it is in a js file? it will only work in the former and not in the latter.

i think this qz app is interesting, and i want to thank you for turning me onto it. i have yet to download it and play around with it, so i know nothing about it. that said, it looks like a viable solution for what you are trying to do. so without really having any base of knowledge on it, it is hard for me to comment. i know getting javascript to run without errors can be tricky. have you used the console on the developer tools to play around with your loaded javascript objects? you should be able to call one of qz javascript functions from the console and get that label to print and then you can code accordingly.

i hope that helps a little bit. i plan on downloading and playing around with qz when i have some more time, and if i can add anything helpful, i will.

best.

27 Jul 2018, 8:25 PM
#5
lankeeyankee avatar

lankeeyankee

Totally Zenned

Join Date:
Jan 2007
Posts:
1,514
Plugin Contributions:
1

Re: qz print tray 2.0.7 and printing from admin

Thanks, Carl. Yes, I am not very good at explaining myself! I didn't post the complete files, just what I thought were the relevant sections.

Yes, everything does work as expected with the base files. The issue I was having is out of the box when you click the print button it would direct to a new page which would display a thumbnail of the generated label image, you have to click the thumbnail to open another page showing the full image which you then have to CRL+P to print. Kind of clunky when you are printing 100+ labels/day. That's where qz tray comes in.

I never figured this out, perhaps some type of AJAX call after the print button was clicked which generates the label would work. What I did was on the view label page, the new page after clicking print, I put the while loop inside the js so it automatically prints the label. It works as expected, here is my complete code, I added the refresh so it would automatically redirect back to the orders page:```php

<?php require('includes/application_top.php'); $oID = zen_db_prepare_input($_GET['oID']); ?> <!doctype html public "-//W3C//DTD HTML 4.01 Transitional//EN"> <html <?php echo HTML_PARAMS; ?>> <head> <meta http-equiv="Content-Type" content="text/html; charset=<?php echo CHARSET; ?>"> <title><?php echo TITLE; ?></title> <link rel="stylesheet" type="text/css" href="includes/stylesheet.css"> <script language="javascript" src="//ajax.googleapis.com/ajax/libs/jquery/1/jquery.min.js"></script> <script type="text/javascript" src="includes/javascript/rsvp-3.1.0.min.js"></script> <script type="text/javascript" src="includes/javascript/sha-256.min.js"></script> <script type="text/javascript" src="includes/javascript/qz-tray.js"></script> <script language="javascript" src="includes/menu.js"></script> </head> <body> <script language="javascript"> <?php $fedex_labels = $db->Execute('SELECT * FROM ' . DB_PREFIX . 'fedex_labels WHERE labels IS NOT NULL AND orders_id = ' . $oID . ' ORDER BY labels ASC;'); if ($fedex_labels->RecordCount() > 0) { while(!$fedex_labels->EOF) { $label = $fedex_labels->fields['labels']; ?> function connectAndPrint() { // our promise chain connect().then(function() { return print(); }).catch(fail); // so one catch is often enough for all promises
// NOTE:  If a function returns a promise, you don't need to wrap it in a fuction call.
//        The following is perfectly valid:
//
//        connect().then(print).then(success).catch(fail);
//
// Important, in this case success is NOT a promise, so it should stay wrapped in a function() to avoid confusion

}

// connection wrapper
// - allows active and inactive connections to resolve regardless
// - try to connect once before firing the mimetype launcher
// - if connection fails, catch the reject, fire the mimetype launcher
// - after mimetype launcher is fired, try to connect 3 more times
function connect() {
return new RSVP.Promise(function(resolve, reject) {
if (qz.websocket.isActive()) { // if already active, resolve immediately
resolve();
} else {
// try to connect once before firing the mimetype launcher
qz.websocket.connect().then(resolve, function reject() {
// if a connect was not succesful, launch the mimetime, try 3 more times
window.location.assign("qz:launch");
qz.websocket.connect({ retries: 2, delay: 1 }).then(resolve, reject);
});
}
});
}

// print logic
function print() {
var printer = "Zebra ZP 450-200dpi";
var options = {language: "ZPLII" };
var config = qz.configs.create(printer, options);
var data = [{ type: 'image', data: 'images/fedex/<?php echo $label; ?>' }];

// return the promise so we can chain more .then().then().catch(), etc.
return qz.print(config, data);

}

// exception catch-all
function fail(e) {
alert("Error: " + e);
}

connectAndPrint();

<?php  $fedex_labels->MoveNext();

}

}
?>
</script>

</body> </html> <?php header( "refresh:4; url=orders.php" ); ?> <?php require(DIR_WS_INCLUDES . 'application_bottom.php'); ?> ```Currently, I am now working on trying to get it to recognize my system as a trusted source so it will not show the 2 popups to allow the printing to occur(they call it silent printing). You can read about how to do this here: <https://qz.io/wiki/2.0-signing-messages#advanced> I am not clear on creating the intermediate certificate and if I am supposed to use the current SSL cert on my domain or create a new private key pair just for this application. If you are able to get this working please share your steps. And if you are able to get it to print without having to go to a different page please also let us know how you did it.

Once I get the silent printing sorted I am going to move on to getting it to pull values from my local USB connected shipping scale to populate the weight field for the label creation.

28 Jul 2018, 10:38 PM
#6
carlwhat avatar

carlwhat

zennedOut

Join Date:
Nov 2005
Location:
los angeles
Posts:
2,953
Plugin Contributions:
8

Re: qz print tray 2.0.7 and printing from admin

ok, so i'm clear, you now have this working, with the exception of the security prompts. that's awesome!

creating, installing, and publishing self-signed certificates always seem to be far more complicated than they need be. but when they work it is great.... i'll keep you posted with regards to what i figure out. unfortunately qz print is not too high on my list of things to do right now..... but i have downloaded it and started looking at it.

good luck with the shipping scale. i have coded a couple and it involves sending various keyboard commands, and if necessary coding the keyboard commands prior to that. they key is what is the trigger to send the weight. on the shipping scale that i coded, they were scanning a carton label, and then we coded a few post-amples into that sequence to pull the weight from the scale. not sure what your situation is like, but i agree that logistics operations should be as simple as possible, ie the silent printing, auto-populate weight, etc.

good luck with it all!

31 Jul 2018, 3:06 PM
#7
carlwhat avatar

carlwhat

zennedOut

Join Date:
Nov 2005
Location:
los angeles
Posts:
2,953
Plugin Contributions:
8

Re: qz print tray 2.0.7 and printing from admin

yankee,
have you gotten it to work w/out the prompts?

i have been working on it, and it's a bit complicated. i think i am close, although maybe not...

my opinion, is that you are NOT using your domain ssl. you need to create your own self-signed certificate.

in addition, there seems to be 2 steps, one if for the qz-tray, and the other is for signing the requests that you make on your website.

here looks to be some of the steps, but i have not gotten it to work. i had a bit of work using ant to compile, but i have succeeded in that:

https://goo.gl/ts1oGT

when installing dependencies, i would refer here:

https://github.com/qzind/tray/wiki/install-dependencies

and when compiling i would refer here:

https://github.com/qzind/tray/wiki/compiling

if i make any more headway, i will let you know. good little product... now to get rid of the security prompts!

best.

1 Aug 2018, 12:03 AM
#8
carlwhat avatar

carlwhat

zennedOut

Join Date:
Nov 2005
Location:
los angeles
Posts:
2,953
Plugin Contributions:
8

Re: qz print tray 2.0.7 and printing from admin

okay silent printing.... forget all of the other stuff... first thing, you need 2 files, a private key and public key. look up openssl... no idea how to do it in windows, but in linux, you can use:

openssl req -newkey rsa:2048 -nodes -keyout key.pem -x509 -days 365 -out certificate.pem

the key.pem should NOT be accessible via a web browser. the certificate.pem can be...

assuming you serve your site from /var/yoursite/www, put the key file above the www. in this example, i will use /var/yoursite/crt. so the two files are now here:

/var/yoursite/www/certificate.pem
/var/yoursite/crt/key.pem

now modify your php code from above as such.

        <script type="text/javascript" src="includes/javascript/rsvp-3.1.0.min.js"></script>
        <script type="text/javascript" src="includes/javascript/sha-256.min.js"></script>
        <script type="text/javascript" src="includes/javascript/qz-tray.js"></script>
        <script>
            qz.security.setSignaturePromise(function (toSign) {
                return function (resolve, reject) {
                    $.post("includes/assets/sign-message.php", {request: toSign}).then(resolve, reject);
                };
            });
            qz.security.setCertificatePromise(function (resolve, reject) {
                $.ajax({url: "/crt/certificate.pem", cache: false, dataType: "text"}).then(resolve, reject);
            });
        </script>

create the following script:

YOUR_ADMIN/includes/assets/sign-message.php

$KEY = '/var/yoursite/crt/key.pem';
//$PASS = 'S3cur3P@ssw0rd';

$req = $_POST['request'];
$privateKey = openssl_get_privatekey(file_get_contents($KEY) /*, $PASS */);

$signature = null;
openssl_sign($req, $signature, $privateKey);

if ($signature) {
	header("Content-type: text/plain");
	echo base64_encode($signature);
	exit(0);
}

echo '<h1>Error signing message</h1>';
exit(1);

finally, in your qz-tray.properties, add

authcert.override=certificate.pem

you will need to make a copy of the public key on the local machine running qz-tray.

hope that helps. best.

1 Aug 2018, 4:12 AM
#9
lankeeyankee avatar

lankeeyankee

Totally Zenned

Join Date:
Jan 2007
Posts:
1,514
Plugin Contributions:
1

Re: qz print tray 2.0.7 and printing from admin

Thanks, Carl. I followed your example to a T, apart from my site is located in /home/username/public_html/thisdomain and not /var/username/www so I changed those paths. I still cannot get it working silently. I didn't do the compiling, did you still do that? I was just using the stock qz-tray. The window still shows it's an untrusted website. Not sure what I've done differently, have gone through the steps twice. Even put the key and certificate files in the admin directory just to see if that changed anything.

1 Aug 2018, 5:53 AM
#10
carlwhat avatar

carlwhat

zennedOut

Join Date:
Nov 2005
Location:
los angeles
Posts:
2,953
Plugin Contributions:
8

Re: qz print tray 2.0.7 and printing from admin

yankee,
only twice?? c'mon now....

actually, its quite confusing and it is easy to screw it up. first thing, stay with the stock qz-tray. do NOT compile anything new.

next, let's look at the certificates. are you getting 2 pop-ups? you should be.... one is for the connection to the tray; the second one is for the print job.

now, on both of the pop-ups, are you looking at the certificate? here is an example of a screenshot of my connection certificate:

Attachment 17997

the values that i filled in are readily seen which means that the qz.security.setCertificatePromise is getting properly done. this part is crucial. is the request using your certificate? can you tell?

given that this part is done using an ajax request, you should be able to see the public certificate, using a browser. for example, if you followed my instructions to a tee, what do you get if you go here:

YOURSITE.COM/crt/certificate.pem

do you see the certificate? if not, relook at things. the ajax call is to:

$.ajax({url: "/crt/certificate.pem", cache: false, dataType: "text"}).then(resolve, reject);

which means my above link should hit your certificate. but you run into problems if in your configure, you shop is at someplace like:

YOURSITE.COM/STORE

i would NOT put the certificate on the admin side. period. don't do it. it's a public certificate. it is not protected in this setup. you are only potentially exposing your admin directory.

now when it comes time to print, look at the certificate again. does it have a fingerprint? if it does not, i would look at:

YOUR_ADMIN/includes/assets/sign-message.php

and specifically at the $KEY variable. i would change it to:

/home/username/crt/key.pem

and make sure that file is there. ftp or the like.

i think these are the 2 hard parts, and it is easy to screw up.

if your certificate is there, and they both have fingerprints, we can then look at:

qz-tray.properties, add

authcert.override=certificate.pem

this part is the tray, and if you have this configured properly, your certs can then be trusted.

i never said this was easy. it is easy to get it wrong.

post screenshots of both the certificates on the requests and we can see where we are. in addition, what is your web server running? and what is your workstation running where you are running the qz-tray?

this is an awesome little tool, but there is a reason why they charge $400/year to rid you of the security prompts. its not easy.... but we can do it.

best.

1 Aug 2018, 6:41 AM
#11
lankeeyankee avatar

lankeeyankee

Totally Zenned

Join Date:
Jan 2007
Posts:
1,514
Plugin Contributions:
1

Re: qz print tray 2.0.7 and printing from admin

Actually, I got it working with a compiled version and self-signed cert. I followed the instructions you posted a few replies up, https://goo.gl/ts1oGT. My problem was a little mistake of not completely commenting out the password part in sign-message:```php
$privateKey = openssl_get_privatekey(file_get_contents($KEY) /*, $PASS */ );


I did always get that exact "untrusted website" from your screen shot and it wouldn't save the "allow" click on the popup window. Looking at the compiled version of qz-tray.properties, I saw that the path for the override file was C:\\Program Files\\QZ Tray\\auth\\cert.pem instead of just cert.pem. I uninstalled the compiled version and tried the stock version just to check it and once I changed the path it works as expected.

Thanks again for all of your help, Carl! Hopefully others will see this and it will be easy(er) to get it running in silent mode. Now, on to the USB scale! They do have some info about it:
<https://qz.io/wiki/2.0-usb-communication>
<https://qz.io/wiki/2.0-hid-communication>
1 Aug 2018, 9:53 PM
#12
lankeeyankee avatar

lankeeyankee

Totally Zenned

Join Date:
Jan 2007
Posts:
1,514
Plugin Contributions:
1

Re: qz print tray 2.0.7 and printing from admin

In further testing, I couldn't get it to print multiple labels (if the shipment has more than 1 box). Currently, the base shipping code creates as many labels as specified and appends _1, _2, etc to the png file. I had to move the references to the external js files to within the PHP while loop. I also redid the javascript to be a little simpler, here's the complete code in case anyone has a similar need```php

<?php if ($fedex_labels->RecordCount() > 0) { while(!$fedex_labels->EOF) { $label = $fedex_labels->fields['labels']; ?> <script language="javascript" src="includes/javascript/rsvp-3.1.0.min.js"></script> <script language="javascript" src="includes/javascript/sha-256.min.js"></script> <script language="javascript" src="includes/javascript/qz-tray.js"></script> <script language="javascript" src="includes/javascript/trustedCert.js"></script> <script language="javascript"> qz.websocket.connect().then(function() { return qz.printers.find("Zebra ZP 500") // Pass the printer name into the next Promise }).then(function(printer) { var options = {language: "ZPLII" }; var config = qz.configs.create(printer, options); // Create a default config for the found printer var data = [{ type: 'image', data: 'images/fedex/<?php echo $label; ?>' }]; return qz.print(config, data); }).catch(function(e) { console.error(e); }); </script>
<?php  $fedex_labels->MoveNext();

}

} ?>

2 Aug 2018, 3:29 PM
#13
carlwhat avatar

carlwhat

zennedOut

Join Date:
Nov 2005
Location:
los angeles
Posts:
2,953
Plugin Contributions:
8

Re: qz print tray 2.0.7 and printing from admin

lankee,
while your code may work, i do not like it. in your OP, you stated you wanted to learn/grow from this experience, so allow me to throw a few things in.

the inclusion of the 4 javascripts within your while statement is bad. period. and totally unnecessary. you possibly have set cache control on, which means the processing penalty is low, but i would move those out of the while loop. you can certainly put them after the if statement, and it will still work fine.

the in-line javascript for connect and print needs to be within the while statement, and specifically for the echo of label.

i like the moving of the setSignaturePromise and setCertificatePromise to another js file; however i have not tested it. and the post link would need to be checked in order to get that properly called. i think the ajax call would be fine.

and while we are on the topic, i can tell you what i have done; i moved the sign_message.php to MY_ADMIN/sign_message.php (i changed the dash to an underline...be careful... only personal preferences...) i then added to that script:

require('includes/application_top.php');

as the first line. in the ADMIN/includes/configure.php i added a new variable called DIR_KEY which made my second line:

$KEY = DIR_KEY . 'key.pem';

you can now test your signing w/o actually doing anything. and only when logged into the admin. i suppose you could have done that before as well.... but anyone could have done it, ie without logging into the admin... but i like it MUCH better this way.

finally i love hard coding stuff as much as the next guy; however it is rarely a good idea. especially when you have test systems set up. i would set up a LABEL_PRINTER_NAME entry into your configuration database, and then use that for your printer name, ie:

$printer = LABEL_PRINTER_NAME;

and then later:

var printer = "<?php echo $printer; ?>";

doing it this way allows for setting up a test server much easier. especially if you use version control (which i recommend). the configure file is not under version control, and you will need to name the key and certificate the same, but in a small way, your code becomes much more transportable; and if you get a new label printer and need to change the name, you are not modifying code. you can change the printer name via the ADMIN -> CONFIGURATION and then whatever group into which you put the LABEL_PRINTER_NAME.

just some food for thought....

best.

2 Aug 2018, 4:23 PM
#14
lankeeyankee avatar

lankeeyankee

Totally Zenned

Join Date:
Jan 2007
Posts:
1,514
Plugin Contributions:
1

Re: qz print tray 2.0.7 and printing from admin

All very good ideas! I tried quite a few different ways to get the script to print multiple labels in one go and this was the only way I could get it to print them all. Otherwise it only ever prints the first label. I didn't like doing it this way, either, but that's all I could come up with that works. I suspect to do this properly I would probably need to rewrite the whole block containing the while loop in javascript instead of PHP. If you are able to get it printing multiple files with the current PHP/JS code I would love to see how you did it.

I will make the changes recommended and add to the admin configuration, that is much better than hard coding. I generally have tried to stay away from it, too. Like I said, I am pretty rusty hahaha.

7 Aug 2018, 2:21 PM
#15
carlwhat avatar

carlwhat

zennedOut

Join Date:
Nov 2005
Location:
los angeles
Posts:
2,953
Plugin Contributions:
8

Re: qz print tray 2.0.7 and printing from admin

lankee,
i have also moved on to printing multiple labels.

i have found that the best way to handle that is to create your print stream, and when you are done to send that stream to the printer.

if i tried to send each individual label to the printer, the system would hang during the qz.websocket.connect() part of the function. and despite the code saying it would only try twice, it would get caught into an endless loop. which suggests to me something going on in the timing with javascript and having multiple attempts to connect with multiple print jobs. i may pursue it on the qz-tray forum when i have some time.

i am reviewing your code and what you stated in #12 above (https://goo.gl/DkNyFD%29; and i can't seem to make sense of it. you state that you can not get it to print multiple labels, and then your code goes ahead and sends multiple print jobs. if that works for you great.... i moved all of the connect and print calls out of the while loop.

in any event, i think qz-tray is a great solution for any ZC user who wants/needs the ability to print directly from a browser. thanks again for turning me onto it.

best.