JANコードをアプリに読み込ませ、API経由でサーバー側に保存されたJANコードのリストと照らし合わせて各処理を行う仕組みを作っているのですが、JANコードを扱うには実は単純に見えて少々手間のかかる処理が必要になります。
それがチェックディジットの計算です。
実は、JANコードの最終桁はチェックディジットとよばれ、ほかの桁が正常に読み込まれたかどうかの判定に使われる、エラーチェック用の桁となっています。
JANコードは13桁のものと8桁のものがあるのですが、実際の内容となる部分は左から12桁目まで、もしくは7桁目までとなります。
さて、チェックディジット部分は無視して扱うこともできますが、折角エラーチェック用の仕組みがあるので、ちゃんと生かして実装しておきたいところ。
そこで、サーバー側へ投げられたJANコードをサーバー側でデータ部分とチェックディジットに分けた上で、データ部分からチェックディジットを計算し、入力されたチェックディジットと一致するかの確認を行う処理を入れ込みます。
チェックディジットの算出方法は次の通りです。
①JANコードの偶数桁を足し合わせる
②①で出てきた値を3倍する
③奇数桁を足し合わせる
④ ②+③をした値を10から引く
④で出てきた値がチェックディジットとなる。
(※④の結果が10の場合、つまり②+③の結果が0の場合はチェックディジットは0となります。)
後は算出されたチェックディジットがJANコードの一番右側の桁と一致すれば、JANコードは正しく読み取れていることになります。
この処理をPHPにすると次のようになります。
$RawJanCode = チェックしたいJANコード;
if (mb_strlen($RawJanCode) <= 8) { //8桁JANコードの場合
$num = substr($RawJanCode, 0, 7); //8桁JANコードのチェックデジットを削除
$num = str_pad($num, 12, 0, STR_PAD_LEFT); //JANコードが12桁になるように0詰め
$digit = substr($RawJanCode, 7, 1); //8桁JANコードのチェックデジットのみを取り出し
} else { //13桁JANコードの場合
$num = substr($RawJanCode, 0, 12); //13桁JANコードのチェックデジットを削除
$digit = substr($RawJanCode, 12, 1); //8桁JANコードのチェックデジットのみを取り出し
}
$arr = str_split($num); //1桁づつ配列に格納
$odd = 0;
$mod = 0;
for ($i = 0, $iMax = count($arr); $i < $iMax; ++$i) {
if (($i + 1) % 2 == 0) {
//偶数の総和
$mod += intval($arr[$i]);
} else {
//奇数の総和
$odd += intval($arr[$i]);
}
}
//偶数の和を3倍+奇数の総和を加算して、下1桁の数字を10から引く
$cd = 10 - intval(substr((string) ($mod * 3) + $odd, -1));
//10なら1の位は0なので、0を返す。
$result = $cd === 10 ? 0 : $cd;
if ((int) $result === (int) $digit) {
echo 'チェック成功';
} else {
echo 'チェック失敗';
}
ここで気を付けなければいけない点は、8桁のJANコードは計算時に13桁のJANコードを処理したときと同じ桁数になるように左側から0で詰めないといけない点です。
これをやらないと偶数桁と奇数桁がずれてしまい、正常にチェックディジットが算出できずに常にJANコードから取得したチェックディジットと一致しなくなってしまいます。
上記のルールに従って計算することで、JANコードをエラーチェック込みで利用することができるようになり、より正確に扱うことができるようになります。
JANコードを扱うプログラムをPHPで記述する際は是非参考にしてみてください。
参考:
gothedistance/calc_jancode_digit.php – GitHub Gist