July 2020

Amazon Fresh API: PHP/cURL Woes and a Final Solution! – July 29, 2020

I just spent four hours trying to get the Amazon API to work properly.  The documentation is pretty poor, and just has the one example, which as I finally figured out in the end, works completely differently than the "landing" URL, which is the one you actually need to use.

How I thought it would work is that I would send my ingredients off to Amazon and they would return a customized link (in the form of the green button like on the verify page) and then I could display that to the visitors.  So, I worked on cURL using various methodologies of encoding, etc. and when it finally started to work, I realized that Amazon doesn't actually return the HTML for a form or button, but the whole HTML of the page, so what they really want you to do is to setup an HTML form on your page with a hidden input and then have the user press on the submit button and hope for the best (rather than me see if the items are available and in stock, etc, and provide a better user experience for the visitor).

So, without further ado, here is the code you want to take a PHP array of ingredients and display an HTML form that your visitor can click on to link to Amazon's Fresh API.

 

$list = array();
foreach($ingredients as $ingredient) {
   $list[] = array("name" => $ingredient['name'],
                        "quantityList" => array(array("unit" => $measurement = $ingredient['measurement'],"amount" => $ingredient['amount'])));
}
$result = '<form method="POST" action="https://www.amazon.com/afx/ingredients/landing">'.
     '<input type="hidden" name="ingredients" value=\''.json_encode(array("ingredients" => $list)).'\'>'.
     '<input type="submit" value="Buy on Amazon">'.
   '</form>';

 

As always, if you are looking for a professional developer to help you get your projects done, I'm available for consulting.

Script to Generate Self-Signed Certificates Automatically – July 26, 2020

I always have trouble remembering how to make self-signed certificates, and there are a million different webpages devoted to doing so, but they all do it a little differently, and don't always, work, so here is the millionth-and-one web page, but at least it will work for me.

The features I care about are using private IP addresses, private DNS names, public DNS names, a root authority that needs to be imported into the browser's trusted certificates, and remembering/auto-filling passwords automatically.

Here is my config:

#!/bin/bash
set -e
set -u

ROOT=MyRootCA
SERVER=MyClient1

if [ -f $ROOT.pem ] ; then
  echo "Regenerate root certificate too? (Y/n)"
  read confirm
fi

if [ "${confirm:-Y}" == "Y" ]; then
  echo "Generating root certificate..."
  openssl genrsa -out $ROOT.key 2048
  openssl req -x509 -new -nodes -key $ROOT.key -sha256 -days 1024 -out $ROOT.pem -config $ROOT.req
fi

echo "Generating server certificate..."
openssl genrsa -out $SERVER.key 2048
openssl req -new -key $SERVER.key -out $SERVER.csr -config $SERVER.req
openssl x509 -req -days 730 -CA $ROOT.pem -CAkey $ROOT.key -CAcreateserial -out $SERVER.pem -in $SERVER.csr -extfile $SERVER.req -extensions v3_req

if [ "${confirm:-Y}" == "Y" ]; then
  echo ""
  echo "Remember to import the certificate into your browser: chrome://settings/certificates."
fi

And then the two .req files:

MyRootCA.req:
[req]
distinguished_name = req_distinguished_name
prompt = no
[req_distinguished_name]
C = US
ST = NH
L = Hillsboro
O = Lime Daley Root
CN = limedaley.com

MyClient1.req:
[req]
distinguished_name = req_distinguished_name
x509_extensions = v3_req
prompt = no
[req_distinguished_name]
C = US
ST = NH
L = Hillsboro
O = Lime Daley
CN = lemon.limedaley.com
[v3_req]
subjectAltName = @alt_names

[alt_names]
IP = 10.243.0.10 
DNS.1   = lemon.local
DNS.3   = localhost
DNS.4   = lemon.limedaley.com
DNS.5   = lemon

To use, edit the two .req files as appropriate, and then run the generate script (you shouldn't need to edit it) and then import the *root* certificate, not the server certificate into the "Authorities" section in the certificate management section of your browser.

You also need to put the appropriate lines into your webserver.  Here is an example for Apache:

SSLCertificateFile      /etc/ssl/limedaley/MyClient1.pem
SSLCertificateKeyFile /etc/ssl/limedaley/MyClient1.key

When you want to make changes to the $SERVER.req file, you don't need to regenerate the root certificate, but just use the old one, and then you won't need to import it into your browser.