/** ****************************************************************************** * @file billmode.c * @author TMC Scan Team * @version V1.0.0 * @date 09/06/2019 * @brief This file provides the different modes of scanning. ****************************************************************************** * * THE PRESENT FIRMWARE WHICH IS FOR GUIDANCE ONLY AIMS AT PROVIDING CUSTOMERS * WITH CODING INFORMATION REGARDING THEIR PRODUCTS IN ORDER FOR THEM TO SAVE * TIME. AS A RESULT, TMC SHALL NOT BE HELD LIABLE FOR ANY * DIRECT, INDIRECT OR CONSEQUENTIAL DAMAGES WITH RESPECT TO ANY CLAIMS ARISING * FROM THE CONTENT OF SUCH FIRMWARE AND/OR THE USE MADE BY CUSTOMERS OF THE * CODING INFORMATION CONTAINED HEREIN IN CONNECTION WITH THEIR PRODUCTS. * *

© COPYRIGHT 2016 TMC

****************************************************************************** **/ #include "global.h" static const unsigned char base64_suffix_map[256] = { 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 253, 255, 255, 253, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 253, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 62, 255, 255, 255, 63, 52, 53, 54, 55, 56, 57, 58, 59, 60, 61, 255, 255, 255, 254, 255, 255, 255, 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 20, 21, 22, 23, 24, 25, 255, 255, 255, 255, 255, 255, 26, 27, 28, 29, 30, 31, 32, 33, 34, 35, 36, 37, 38, 39, 40, 41, 42, 43, 44, 45, 46, 47, 48, 49, 50, 51, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255 }; const uint8_t TAXHead[3][2] = {{0x30, 0x31}, {0x31, 0x30}, {0x30, 0x34}}; const uint8_t BaiWangHead[7] = {0x5C, 0x30, 0x30, 0x30, 0x30, 0x32, 0x36}; const uint8_t HangXinHead[5] = {0x6C, 0x78, 0x6B, 0x70, 0x3A}; const uint8_t QuanMinETail[9] = "CHINAUMS_"; /** * @function base64_decode * @brief base64解码 * @param[in] *indata input data * @param[in] inlen input data length * @param[out] *outdata output data buf * @param[out] *outlen output data length * @return */ int base64_decode(const uint8_t *indata, uint16_t inlen, uint8_t *outdata, uint16_t *outlen) { int ret = 0; if(indata == NULL || inlen <= 0 || outdata == NULL || outlen == NULL) { return ret = -1; } ret = inlen % 4; if(ret != 0) { // 需要解码的数据不是4字节倍数 return ret = -2; } int t = 0, x = 0, y = 0, i = 0; unsigned char c = 0; int g = 3; while((indata[x] != 0) && (x < inlen)) { // 需要解码的数据对应的ASCII值对应base64_suffix_map的值 c = base64_suffix_map[indata[x++]]; if(c == 255) { return -1; } // 对应的值不在转码表中 if(c == 253) { continue; } // 对应的值是换行或者回车 if(c == 254) { c = 0; g--; } // 对应的值是'=' t = (t << 6) | c; // 将其依次放入一个int型中占3字节 if(++y == 4) { outdata[i++] = (unsigned char)((t >> 16) & 0xff); if(g > 1) { outdata[i++] = (unsigned char)((t >> 8) & 0xff); } if(g > 2) { outdata[i++] = (unsigned char)(t & 0xff); } y = t = 0; } } *outlen = (i - 4); //四位校验位 return ret; } /** * @function TaxBillMode * @brief 解析税务发票助手的数据 * @param[in] pCode 输入数据 * @return */ int TaxBillMode(BarData *pCode) { int ret, i = 0, j = 0; uint8_t *pData = NULL; pData = (uint8_t *) PREOUTBUF; uint16_t dataLen = 0; uint8_t *pOut = NULL; pOut = (uint8_t *) POSOUTBUF; // 需要解码的数据需要是4字节倍数 ret = (pCode->datalen - 4) % 4; i = 0; if(ret > 0) { while((4 - ret) != 0) { pCode->bardata[pCode->datalen - 1 + i] = '='; ret++; i++; } } ret = base64_decode(pCode->bardata + 3, pCode->datalen - 4 + i, pData, &dataLen); if(ret == 0) { i = 0; while(i < dataLen) { if(pData[i] == 0x3C) { if((pData[i + 1] == 0x2F) && ((pData[i + 2] == 0x3E))) { pOut[j] = 0x20; j++; pOut[j] = 0x09; j++; i += 3; } else { pOut[j] = pData[i]; j++; i++; } } else { pOut[j] = pData[i]; j++; i++; } } Memcpy(pCode->bardata, pOut, j); pCode->datalen = j; return j; } else { return 0; } } /** * @function HangXinBillMode * @brief 航信发票助手,从生成的码制上看,存在两种情况,一种数字开头,需要去掉多余位 * 另外一种直接打印即可 * @param[in] pCode 输入数据 * @return */ int HangXinBillMode(BarData *pCode) { int ret, i = 0, j = 0; int base64codelen = pCode->datalen - 6; uint8_t *pData = NULL; pData = (uint8_t *) PREOUTBUF; uint16_t dataLen = 0; uint8_t *pOut = NULL; pOut = (uint8_t *) POSOUTBUF; // 需要解码的数据需要是4字节倍数 ret = base64codelen % 4; i = 0; if(ret > 0) { while((4 - ret) != 0) { pCode->bardata[pCode->datalen - 1 + i] = '='; ret++; i++; } } ret = base64_decode(pCode->bardata + 5, pCode->datalen - 6 + i, pData, &dataLen); if(ret == 0) { i = 0; if((pData[0] >= 0x30) && (pData[0] <= 0x39)) { i = 1; dataLen = dataLen - 2; } while(i < dataLen) { if(pData[i] == 0x3C) { if((pData[i + 1] == 0x2F) && ((pData[i + 2] == 0x3E))) { pOut[j] = 0x20; j++; pOut[j] = 0x09; j++; i += 3; } else { pOut[j] = pData[i]; j++; i++; } } else { pOut[j] = pData[i]; j++; i++; } } Memcpy(pCode->bardata, pOut, j); pCode->datalen = j; return j; } else { return 0; } } /** * @function AliBillMode * @brief 支付宝发票助手 * @param[in] pCode 输入数据 * @return */ int AliBillMode(BarData *pCode) { int i = 0, j = 0; uint8_t *pOut = NULL; pOut = (uint8_t *) POSOUTBUF; i = 2; j = 0; while(i < pCode->datalen) { if(pCode->bardata[i] == 0xE2) { if((pCode->bardata[i + 1] == 0x86) && (pCode->bardata[i + 2] == 0x92)) { pOut[j] = 0x20; j++; pOut[j] = 0x09; j++; i += 4; } else { pOut[j] = pCode->bardata[i]; i++; j++; } } else if((pCode->bardata[i] == 0x41) && (pCode->bardata[i + 1] == 0x4C)) { if((pCode->bardata[i + 2] == 0x49) && (pCode->bardata[i + 3] == 0x50)) { break; } else { pOut[j] = pCode->bardata[i]; i++; j++; } } else { pOut[j] = pCode->bardata[i]; i++; j++; } } if(j > 0) { Memcpy(pCode->bardata, pOut, j); pCode->datalen = j; } else { return 0; } return j; } /** * @function BaiWangBillMode * @brief 百旺发票助手 * @param[in] pCode 输入数据 * @return */ int BaiWangBillMode(BarData *pCode) { int i = 0, j = 0; uint8_t *pOut = NULL; pOut = (uint8_t *) POSOUTBUF; i = 9; j = 0; while(i < pCode->datalen) { if(pCode->bardata[i] == 0xE2) { if((pCode->bardata[i + 1] == 0x86) && (pCode->bardata[i + 2] == 0x92)) { pOut[j] = 0x20; j++; pOut[j] = 0x09; j++; i += 4; } else { pOut[j] = pCode->bardata[i]; i++; j++; } } else { pOut[j] = pCode->bardata[i]; i++; j++; } } if(j > 0) { Memcpy(pCode->bardata, pOut, j); pCode->datalen = j; } else { return 0; } return j; } /** * @function QuanMinEBillMode * @brief 全民E发票助手 * @param[in] pCode 输入数据 * @return */ int QuanMinEBillMode(BarData *pCode) { int i = 0, j = 0; uint8_t *pOut = NULL; pOut = (uint8_t *) POSOUTBUF; i = 1; j = 0; while(i < (pCode->datalen - 9)) { if(pCode->bardata[i] == 0xE2) { if((pCode->bardata[i + 1] == 0x86) && (pCode->bardata[i + 2] == 0x92)) { pOut[j] = 0x20; j++; pOut[j] = 0x09; j++; i += 4; } else { pOut[j] = pCode->bardata[i]; i++; j++; } } else { pOut[j] = pCode->bardata[i]; i++; j++; } } if(j > 0) { Memcpy(pCode->bardata, pOut, j); pCode->datalen = j; } else { return 0; } return j; } //增值税发票 int VATBillMode(BarData *pCode) { int i = 5, j = 0; uint8_t *pOut = NULL; pOut = (uint8_t *) POSOUTBUF; for(i = 0; i < 3; i++) { if(Memcmp(&pCode->bardata[3], (uint8_t *)&TAXHead[i][0], 2) == TRUE) { break; } } if(i >= 3) { return 0; } if(pCode->bardata[5] == ',') { for(i = 6; i < (pCode->datalen - 6); i++) { if(pCode->bardata[i] == ',') { pOut[j] = 0x09; } else { pOut[j] = pCode->bardata[i]; } j++; } } if(j > 0) { memcpy(pCode->bardata, pOut, j); pCode->datalen = j; } else { return 0; } return j; } /** * @function BillMode * @brief 解析不同发票模式数据 * @param[in] pCode 输入数据 * @return 如果是发票数据,返回值大于0;否则返回0 */ int BillMode(BarData *pCode) { int tmp; /*如果符合发票模式,进行发票模式输出*/ /*税务发票助手*/ if((pCode->bardata[0] == '$') && (pCode->bardata[pCode->datalen - 1] == '$')) { if((pCode->bardata[1] == '0') && (pCode->bardata[2] == '1')) { tmp = TaxBillMode(pCode); return tmp; } } /*支付宝发票助手*/ if((pCode->bardata[0] == '1') && (pCode->bardata[pCode->datalen - 1] == 0x92)) { if((pCode->bardata[pCode->datalen - 2] == 0x86) && (pCode->bardata[pCode->datalen - 3] == 0xE2)) { tmp = AliBillMode(pCode); return tmp; } } //百旺发票助手 if((Memcmp(pCode->bardata, (uint8_t *) BaiWangHead, sizeof(BaiWangHead))) && (pCode->bardata[pCode->datalen - 1] == 0x92)) { if((pCode->bardata[pCode->datalen - 2] == 0x86) && (pCode->bardata[pCode->datalen - 3] == 0xE2)) { tmp = BaiWangBillMode(pCode); return tmp; } } //航信发票助手 if((Memcmp(pCode->bardata, (uint8_t *) HangXinHead, sizeof(HangXinHead))) && (pCode->bardata[pCode->datalen - 1] == '$')) { tmp = HangXinBillMode(pCode); return tmp; } //全民E发票助手 if(pCode->bardata[0] == '1') { if(Memcmp(&pCode->bardata[pCode->datalen - 9], (uint8_t *) QuanMinETail, sizeof(QuanMinETail))) { tmp = QuanMinEBillMode(pCode); return tmp; } } //增值税发票 if((pCode->bartype == QR_Id) && (pCode->bardata[0] == '0')) { if((pCode->bardata[1] == '1') && (pCode->bardata[2] == ',')) { tmp = VATBillMode(pCode); return tmp; } } return 0; }