如何在JavaScript中validationEAN / GTIN条形码

如何检查string是否是JavaScript中的有效EAN / GTIN条形码?

我需要检查EAN8,EAN12,EAN13,EAN14,EAN18以及GTIN12,GTIN13,GTIN14。

编辑我还创build了一个npm模块,可以在github上find。

我创build了一个小型库,支持EAN8,EAN12,EAN13,EAN14,EAN18,GTIN12,GTIN13和GTIN14。

它适用于node.js和所有现代浏览器。

barcoder.js:

/*! * Barcoder * Copyright (c) 2013 mifitto GmbH <dominik@mifitto.com> * MIT Licensed */ (function() { 'use strict'; /** * Library version. */ var version = '1.1.0'; /** * Supported formats */ var minValidLength = 6; var maxValidLength = 18; var usualValidChars = /^\d+$/; var formats = { 'ean8' : { validChars : /^\d+$/, validLength : 8 }, 'ean12' : { validChars : /^\d+$/, validLength : 12 }, 'ean13' : { validChars : /^\d+$/, validLength : 13 }, 'ean14' : { validChars : /^\d+$/, validLength : 14 }, 'ean18' : { validChars : /^\d+$/, validLength : 18 }, 'gtin12' : { validChars : /^\d+$/, validLength : 12 }, 'gtin13' : { validChars : /^\d+$/, validLength : 13 }, 'gtin14' : { validChars : /^\d+$/, validLength : 14 } }; /** * Validates the checksum (Modulo 10) * GTIN implementation factor 3 * * @param {String} value The barcode to validate * @return {Boolean} * @api private */ var validateGtin = function( value ) { var barcode = value.substring( 0, value.length - 1 ); var checksum = parseInt( value.substring( value.length - 1 ), 10 ); var calcSum = 0; var calcChecksum = 0; barcode.split('').map(function( number, index ) { number = parseInt( number, 10 ); if ( value.length % 2 === 0 ) { index += 1; } if ( index % 2 === 0 ) { calcSum += number; } else { calcSum += number * 3; } }); calcSum %= 10; calcChecksum = (calcSum === 0) ? 0 : (10 - calcSum); if ( calcChecksum !== checksum ) { return false; } return true; }; /** * Barcoder class * * @param {string} format See formats * @param {Object} options Valid option `enableZeroPadding`, defaults to `true` * @api public */ var Barcoder = function ( format, options ) { if ( format && !formats[format] ) throw new Error( '"format" invalid' ); this.format = (format) ? formats[format] : 'autoSelect'; this.options = (options) ? options : { enableZeroPadding : true }; if ( !this.options.enableZeroPadding ) { this.options.enableZeroPadding = true; } }; /** * Validates a barcode * * @param {string} barcode EAN/GTIN barcode * @return {Boolean} * @api public */ Barcoder.prototype.validate = function( barcode ) { var self = this; if ( self.format === 'autoSelect' ) { if ( barcode.length < minValidLength || barcode.length > maxValidLength ) { return false; } var isValidGtin = validateGtin( barcode ); var paddedBarcode = barcode; var successfullyPadded = false; if ( !isValidGtin ) { var possiblyMissingZeros = maxValidLength - barcode.length; while( possiblyMissingZeros-- ) { paddedBarcode = '0' + paddedBarcode; if ( validateGtin( paddedBarcode ) ) { isValidGtin = true; successfullyPadded = true; break; } } } return { possibleType: (barcode.length > 8) ? 'GTIN' + barcode.length : 'EAN8 / padded GTIN', isValid: isValidGtin }; } var validChars = self.format.validChars; var validLength = self.format.validLength; var enableZeroPadding = self.options.enableZeroPadding; if ( validChars.exec( barcode ) === null ) { return false; } if ( enableZeroPadding && barcode.length < validLength ) { var missingZeros = validLength - barcode.length; while( missingZeros-- ) { barcode = '0' + barcode; } } else if ( !enableZeroPadding && barcode.length != validLength ) { return false; } else if ( barcode.length > validLength ) { return false; } return validateGtin( barcode ); }; /** * Export */ if ( 'undefined' !== typeof module && module.exports ) { module.exports = Barcoder; exports.version = version; } if ( 'undefined' === typeof ender ) { this['Barcoder'] = Barcoder; } if ( 'function' === typeof define && define.amd ) { define('Barcoder', [], function () { return Barcoder; }); } }).call( this ); 

安装:

 $ npm install barcoder 

用法:

 var Barcoder = require('barcoder'); var ean1 = '0016T20054453'; var ean2 = '9330071314999'; var validator = new Barcoder('ean13'); console.log( '%s ean1 is valid: %s', ean1, validator.validate( ean1 ) ); console.log( '%s ean2 is valid: %s', ean1, validator.validate( ean2 ) ); // or /w automatic type selection validator = new Barcoder(); var validation1 = validator.validate( ean1 ); var validation2 = validator.validate( ean2 ); console.log( '%s is valid: %s and has guessed type: %s', ean1, validation1.isValid, validation1.possibleType ); console.log( '%s is valid: %s and has guessed type: %s', ean2, validation2.isValid, validation2.possibleType ); 

我不知道为什么,但@ moosgummi的解决scheme不适合我。 我也想计算新的代码,以及validation旧的。 最后,我已经证实我的浏览器至less在工作:

 function eanCheckDigit(s){ var result = 0; for (counter = s.length-1; counter >=0; counter--){ result = result + parseInt(s.charAt(counter)) * (1+(2*(counter % 2))); } return (10 - (result % 10)) % 10; } 

这是一个简短的版本,可以检查EAN13校验位是否有效:

  var checkSum = ean.split('').reduce(function(p,v,i) { return i % 2 == 0 ? p + 1 * v : p + 3 * v; }, 0); if (checkSum % 10 != 0) { alert('error'); } 

对不起,如果这个代码有点太长,但这是我有validation一个EAN13条码:

 function isBarcode(barcode) { if (typeof barcode === 'number') { throw 'RuntimeError: Barcode MUST NOT be in number format' } else if (barcode.length!==12) { throw 'RuntimeError: String length is not 12' }; var _= barcode.toString().split("") var _1 = 0 var _2 = 0 var __ for ($=0;$<=10;++$) { _1+=+_[$] };for ($=10;$>=0;$-=2) { _2+=+_[$] };_2*=2 var _3 = _1+_2 __=+_3.toString().substring(1,2) if (__>9) { __=+_3.toString().substring(1,2) } else if (__===0) { __=10 }; __=10-__ if (__===+_[11]) { return true } return false }; 

这是我的解决scheme,使用规范来检查不同长度的条码,最后计算校验位(见注):

 // ean/gtin validation for 8, 12, 13 & 14 digit barcodes function codeOnBlur(barcode) { var barcodeLengthArr = [8, 12, 13, 14]; var allowedChars = new RegExp(/\d{8,14}/); // >7 & <15 // put numbers in array and convert to type Int. var barcodeArray = barcode.split(''); for( var i = 0; i < barcodeArray.length; i++) { barcodeArray[i] = parseInt(barcodeArray[i], 10); } // get the last digit for checking later var checkDigit = barcodeArray.slice(-1)[0]; // we'll need a to compare it to this: var remainder = 0; // check if input (barcode) is in the array and check against the regex. if (($.inArray(barcode.length, barcodeLengthArr) > -1) && (allowedChars.test(barcode))) { console.log("barcodeArray ", barcodeArray, " :: checkDigit ", checkDigit); // Pop the last item from the barcode array, test if the length is // odd or even (see note on calculating the check digit) and // multiply each item in array based in position: var total = 0; barcodeArray.pop(); // odd length after pop if (barcodeArray.length % 2 === 1) { for (var i = barcodeArray.length - 1; i >= 0; i--) { barcodeArray[i] = i % 2 === 0 ? barcodeArray[i] * 3 : barcodeArray[i] * 1; total += barcodeArray[i]; } // even length after pop } else if (barcodeArray.length % 2 === 0) { for (var i = barcodeArray.length - 1; i >= 0; i--) { barcodeArray[i] = i % 2 === 0 ? barcodeArray[i] * 1 : barcodeArray[i] * 3; total += barcodeArray[i]; } } else { // validation passed = false } // calculate the remainder of totalrounded up to nearest multiple of 10: remainder = (Math.ceil((total + 1) / 10) * 10) - total; console.log("loop total = ", total, ", remainder: ", remainder); if ( remainder === checkDigit ) { //validation passed = true; return; } else { //validation passed = false; } } else { //validation Passed = false; } } 

我敢肯定,这个代码可以整理一些:)

手动检查“完整性位”或校验位:

  barcode: 13: 4 0 1 1 2 0 0 2 9 6 9 0 8 8: 5 0 8 1 8 9 0 7 multiplier: 3 1 3 1 3 1 3 1 3 1 3 1 check digit 

采取8位数字代码倒退:

 0*1 + 9*3 + 8*1 + 1*3 + 8*1 + 0*3 + 5*1 = 73 Difference from 73 to 80 is 7 (the specification will have you round up to the nearest power of 10). 

7是检查数字和80-73的剩余部分。