嵌入式linux之go语言开发(四)go语言8583协议报文解析

本文涉及的产品
全局流量管理 GTM,标准版 1个月
云解析 DNS,旗舰版 1个月
公共DNS(含HTTPDNS解析),每月1000万次HTTP解析
简介: 嵌入式linux之go语言开发(四)go语言8583协议报文解析

原来的pos用c语言开发的,与银联后台通信走的是8583协议。那么用go来做,得实现个go语言8583协议报文解析


且若想在电脑上跑交易,做个工具。用c语音处理起来不方便。用go还可以在电脑上跑交易。


于是用go语言做一个8583解析,方便使用


https://github.com/yangyongzhen/go8583/


package up8583
import (
  "errors"
  "fmt"
  "go8583/byteutil"
  "go8583/desutil"
  "go8583/easy8583"
  "strconv"
)
var (
  ManNum  string = "000000000000000"
  PosNum  string = "00000000"
  MainKey string = "00000000000000000000000000000000"
  TPDU    string = "6000000000"
  CommSn     int    = 1
  RecSn      int    = 1
  PiciNum    []byte = make([]byte, 3)
  LicenceNum        = []byte{0x33, 0x30, 0x36, 0x30}
  MacKey string = "0000000000000000"
)
type Up8583 struct {
  Ea *easy8583.Easy8583
}
func memcpy(dst, src []byte, size int) {
  for i := 0; i < size; i++ {
    dst[i] = src[i]
  }
  return
}
func equals(src1 []byte, src2 []byte) bool {
  if src1 == nil || src2 == nil {
    return false
  }
  le1 := len(src1)
  le2 := len(src2)
  if le1 != le2 {
    return false
  }
  for i := 0; i < le1; i++ {
    if src1[i] != src2[i] {
      return false
    }
  }
  return true
}
/*
银联8583签到组包
*/
func (up *Up8583) Frame8583QD() {
  s := up.Ea
  field := up.Ea.Field_S
  s.Init8583Fields(field)
  //消息类型
  s.Msgtype[0] = 0x08
  s.Msgtype[1] = 0x00
  //11域,受卡方系统跟踪号BCD 通讯流水
  field[10].Ihave = true
  field[10].Len = 3
  sn := fmt.Sprintf("%06d", CommSn)
  field[10].Data = byteutil.HexStringToBytes(sn)
  //41域,终端号
  field[40].Ihave = true
  field[40].Len = 8
  field[40].Data = []byte(PosNum)
  //42域,商户号
  field[41].Ihave = true
  field[41].Len = 15
  field[41].Data = []byte(ManNum)
  //60域
  field[59].Ihave = true
  field[59].Len = 0x11
  field[59].Data = make([]byte, 6)
  field[59].Data[0] = 0x00
  memcpy(field[59].Data[1:], PiciNum, 3)
  field[59].Data[4] = 0x00
  field[59].Data[5] = 0x30
  //62域
  field[61].Ihave = true
  field[61].Len = 0x25
  field[61].Data = make([]byte, 25)
  str := "Sequence No12"
  memcpy(field[61].Data, []byte(str), 13)
  memcpy(field[61].Data[13:], LicenceNum, 4)
  memcpy(field[61].Data[17:], []byte(PosNum), 8)
  //63域
  field[62].Ihave = true
  field[62].Len = 0x03
  field[62].Data = make([]byte, 3)
  field[62].Data[0] = 0x30
  field[62].Data[1] = 0x30
  field[62].Data[2] = 0x31
  /*报文组帧,自动组织这些域到Pack的TxBuffer中*/
  s.Pack8583Fields()
  CommSn++ //通讯流水每次加一
  //s.PrintFields(up.Ea.Field_S)
}
func (up *Up8583) Ans8583QD(rxbuf []byte, rxlen int) error {
  r := up.Ea
  fields := up.Ea.Field_S
  fieldr := up.Ea.Field_R
  ret := r.Ans8583Fields(rxbuf, rxlen)
  if ret == 0 {
    fmt.Println("解析成功")
    r.PrintFields(fieldr)
  } else {
    fmt.Println("解析失败")
    return errors.New("error,failed to ans..")
  }
  //消息类型判断
  if (r.Msgtype[0] != 0x08) || (r.Msgtype[1] != 0x10) {
    //Log.d(TAG,"消息类型错!");
    return errors.New("error,wrong Msgtype ")
  }
  //应答码判断
  if (fieldr[38].Data[0] != 0x30) || (fieldr[38].Data[1] != 0x30) {
    //Log.d(TAG,"应答码不正确!");
    return errors.New("error,wrong resp code:" + fmt.Sprintf("%02x%02x", fieldr[38].Data[0], fieldr[38].Data[1]))
  }
  //跟踪号比较
  //memcmp
  if !equals(fields[10].Data, fieldr[10].Data) {
    return errors.New("error,wrong comm no ")
  }
  //终端号比较
  if !equals(fields[40].Data, fieldr[40].Data) {
    return errors.New("error,posnum not equal ")
  }
  //商户号比较
  if !equals(fields[41].Data, fieldr[41].Data) {
    return errors.New("error,mannum not equal ")
  }
  //3DES解密PIN KEY
  data := make([]byte, 16)
  memcpy(data, fieldr[61].Data, 16)
  pinkey, err := desutil.Des3Decrypt(data, byteutil.HexStringToBytes(MainKey))
  if err != nil {
    return errors.New("1" + err.Error())
  }
  //解密后的结果对8Byte全0做3DES加密运算
  tmp := make([]byte, 8)
  out, err := desutil.Des3Encrypt(tmp, pinkey)
  if err != nil {
    return errors.New("2" + err.Error())
  }
  check := make([]byte, 4)
  pincheck := make([]byte, 4)
  memcpy(check, out, 4)
  memcpy(pincheck, fieldr[61].Data[16:], 4)
  if !equals(check, pincheck) {
    return errors.New("error,Er PIK")
  }
  //3DES解密MAC KEY
  memcpy(data, fieldr[61].Data[20:], 16)
  mackey, err := desutil.Des3Decrypt(data, byteutil.HexStringToBytes(MainKey))
  if err != nil {
    return errors.New("3" + err.Error())
  }
  out, err = desutil.DesEncrypt(tmp, mackey[0:8])
  if err != nil {
    return errors.New("4" + err.Error())
  }
  maccheck := make([]byte, 4)
  memcpy(check, out, 4)
  memcpy(maccheck, fieldr[61].Data[36:], 4)
  if !equals(check, maccheck) {
    return errors.New("error,Er MAC")
  }
  memcpy(PiciNum, fieldr[59].Data[1:], 3)
  MacKey = byteutil.BytesToHexString(mackey[0:8])
  fmt.Printf("mackey:%s\n", MacKey)
  up.Ea.SetMacKey(MacKey)
  return nil
}
/*
银联8583 二维码交易组包
*/
func (up *Up8583) Frame8583Qrcode(qrcode string, money int) {
  s := up.Ea
  field := up.Ea.Field_S
  s.Init8583Fields(field)
  //消息类型
  s.Msgtype[0] = 0x02
  s.Msgtype[1] = 0x00
  //3域 交易处理码
  field[2].Ihave = true
  field[2].Len = 3
  field[2].Data = make([]byte, 3)
  //4域 交易金额
  field[3].Ihave = true
  field[3].Len = 6
  field[3].Data = byteutil.HexStringToBytes(fmt.Sprintf("%012d", money))
  //11域,受卡方系统跟踪号BCD 通讯流水
  field[10].Ihave = true
  field[10].Len = 3
  sn := fmt.Sprintf("%06d", RecSn)
  field[10].Data = byteutil.HexStringToBytes(sn)
  //22域
  field[21].Ihave = true
  field[21].Len = 2
  field[21].Data = []byte{0x03, 0x20}
  //25域
  field[24].Ihave = true
  field[24].Len = 1
  field[24].Data = make([]byte, 1)
  //41域,终端号
  field[40].Ihave = true
  field[40].Len = 8
  field[40].Data = []byte(PosNum)
  //42域,商户号
  field[41].Ihave = true
  field[41].Len = 15
  field[41].Data = []byte(ManNum)
  //49域 交易货币代码
  field[48].Ihave = true
  field[48].Len = 3
  field[48].Data = []byte{0x31, 0x35, 0x36}
  //59域,扫码的数据
  field[58].Ihave = true
  field[58].Len = 0x24
  field[58].Data = make([]byte, 24)
  field[58].Data[0] = 'A' //TAG+Len(019)
  field[58].Data[1] = '3'
  field[58].Data[2] = '0'
  field[58].Data[3] = '1'
  field[58].Data[4] = '9'
  memcpy(field[58].Data[5:], []byte(qrcode), 19)
  //60域
  field[59].Ihave = true
  field[59].Len = 0x13
  field[59].Data = make([]byte, 7)
  field[59].Data[0] = 0x22
  memcpy(field[59].Data[1:], PiciNum, 3)
  field[59].Data[4] = 0x00
  field[59].Data[5] = 0x06
  field[59].Data[6] = 0x00
  //MAC,64域
  field[63].Ihave = true
  field[63].Len = 0x08
  field[63].Data = make([]byte, 8)
  //这个域要求填MAC,只需按这样填,MAC的计算在pack8583Fields自动完成了
  /*报文组帧,自动组织这些域到Pack的TxBuffer中*/
  s.Pack8583Fields()
  //CommSn++ //通讯流水每次加一
  //s.PrintFields(up.Ea.Field_S)
}
func NewUp8583() *Up8583 {
  var up = new(Up8583)
  up.Ea = easy8583.New8583()
  up.Ea.Tpdu = byteutil.HexStringToBytes(TPDU)
  return up
}
/*
银联8583 电子现金交易组包
*/
//获取55域 IC卡数据域
/*
9F26 08
9F27 01
9F10
9F37 04
9F36 02
95 05
9A 03
9C 01
9F02 06
5F2A 02
82 02
9F1A 02
9F03 06
9F33 03
9F1E 08
84
9F09 02
9F41 04
9F34 03
9F35 01
9F63 10
9F74 06
8A 02
*/
func getfield55() {
}
func (up *Up8583) Frame8583UpCash(cardbin string, money int, cardvailddata string, cardholdsn string, field55 []byte) {
  s := up.Ea
  field := up.Ea.Field_S
  s.Init8583Fields(field)
  //消息类型
  s.Msgtype[0] = 0x02
  s.Msgtype[1] = 0x00
  //2域 卡号
  field[1].Ihave = true
  tmp := fmt.Sprintf("%02d", len(cardbin))
  t, _ := strconv.ParseInt(tmp, 16, 16)
  if len(cardbin)%2 != 0 {
    cardbin += "0"
  }
  field[1].Len = int(t)
  field[1].Data = byteutil.HexStringToBytes(cardbin)
  //3域 交易处理码
  field[2].Ihave = true
  field[2].Len = 3
  field[2].Data = make([]byte, 3)
  //4域 交易金额
  field[3].Ihave = true
  field[3].Len = 6
  field[3].Data = byteutil.HexStringToBytes(fmt.Sprintf("%012d", money))
  //11域,受卡方系统跟踪号BCD 通讯流水
  field[10].Ihave = true
  field[10].Len = 3
  sn := fmt.Sprintf("%06d", RecSn)
  field[10].Data = byteutil.HexStringToBytes(sn)
  //14域 卡有效期,能获取到时存在
  if len(cardvailddata) > 0 {
    field[13].Ihave = true
    field[13].Len = 2
    field[13].Data = byteutil.HexStringToBytes(cardvailddata)
  }
  //22域
  field[21].Ihave = true
  field[21].Len = 2
  field[21].Data = []byte{0x07, 0x20}
  //23域,卡序列号 能获取时存在
  if len(cardholdsn) > 0 {
    field[22].Ihave = true
    field[22].Len = 2
    field[22].Data = byteutil.HexStringToBytes(cardholdsn)
  }
  //25域
  field[24].Ihave = true
  field[24].Len = 1
  field[24].Data = make([]byte, 1)
  //41域,终端号
  field[40].Ihave = true
  field[40].Len = 8
  field[40].Data = []byte(PosNum)
  //42域,商户号
  field[41].Ihave = true
  field[41].Len = 15
  field[41].Data = []byte(ManNum)
  //49域 交易货币代码
  field[48].Ihave = true
  field[48].Len = 3
  field[48].Data = []byte{0x31, 0x35, 0x36}
  //55域 IC卡数据域
  field[54].Ihave = true
  tmp = fmt.Sprintf("%04d", len(field55))
  b := byteutil.HexStringToBytes(tmp)
  field[54].Len = int(b[0])<<8 | int(b[1])
  field[54].Data = field55
  //60域
  field[59].Ihave = true
  field[59].Len = 0x13
  field[59].Data = make([]byte, 7)
  field[59].Data[0] = 0x36
  memcpy(field[59].Data[1:], PiciNum, 3)
  field[59].Data[4] = 0x00
  field[59].Data[5] = 0x06
  field[59].Data[6] = 0x00
  //63域
  field[62].Ihave = true
  field[62].Len = 0x03
  field[62].Data = make([]byte, 3)
  memcpy(field[62].Data, []byte("CUP"), 3)
  //MAC,64域
  field[63].Ihave = true
  field[63].Len = 0x08
  field[63].Data = make([]byte, 8)
  //这个域要求填MAC,只需按这样填,MAC的计算在pack8583Fields自动完成了
  /*报文组帧,自动组织这些域到Pack的TxBuffer中*/
  s.Pack8583Fields()
}
func (up *Up8583) Ans8583UpCash(rxbuf []byte, rxlen int) error {
  r := up.Ea
  fields := up.Ea.Field_S
  fieldr := up.Ea.Field_R
  ret := r.Ans8583Fields(rxbuf, rxlen)
  if ret == 0 {
    fmt.Println("解析成功")
    r.PrintFields(fieldr)
  } else {
    fmt.Println("解析失败")
    r.PrintFields(fieldr)
    return errors.New("error,failed to ans..")
  }
  //消息类型判断
  if (r.Msgtype[0] != 0x02) || (r.Msgtype[1] != 0x10) {
    //Log.d(TAG,"消息类型错!");
    return errors.New("error,wrong Msgtype ")
  }
  //应答码判断
  if (fieldr[38].Data[0] != 0x30) || (fieldr[38].Data[1] != 0x30) {
    //Log.d(TAG,"应答码不正确!");
    return errors.New("error,wrong resp code:" + fmt.Sprintf("%02x%02x", fieldr[38].Data[0], fieldr[38].Data[1]))
  }
  //跟踪号比较
  //memcmp
  if !equals(fields[10].Data, fieldr[10].Data) {
    return errors.New("error,wrong comm no ")
  }
  //终端号比较
  if !equals(fields[40].Data, fieldr[40].Data) {
    return errors.New("error,posnum not equal ")
  }
  //商户号比较
  if !equals(fields[41].Data, fieldr[41].Data) {
    return errors.New("error,mannum not equal ")
  }
  //MAC验证
  mac, err := easy8583.UpGetMac(rxbuf[13:], rxlen-13-8, easy8583.MacKey)
  if err != nil {
    fmt.Println(err)
    panic("calc mac error!")
  }
  if !equals(fieldr[63].Data, mac) {
    return errors.New("error,mac check err")
  }
  return nil
}
func main() {
  fmt.Println("test...")
  up := NewUp8583()
  //up.Frame8583QD()
  //recvstr := "007960000001386131003111080810003800010AC0001450021122130107200800085500323231333031343931333239303039393939393930363030313433303137303131393939390011000005190030004046F161A743497B32EAC760DF5EA57DF5900ECCE3977731A7EA402DDF0000000000000000CFF1592A"
  //recv := byteutil.HexStringToBytes(recvstr)
  //ret := up.Ea.Ans8583Fields(recv, len(recv))
  //if ret == 0 {
  //  fmt.Println("解析成功")
  //  up.Ea.PrintFields(up.Ea.Field_R)
  // } else {
  //  fmt.Println("解析失败")
  // }
  up.Frame8583QD()
  up.Ea.PrintFields(up.Ea.Field_S)
  //fmt.Println(byteutil.BytesToHexString(up.Ea.Txbuf))
  up.Frame8583Qrcode("6220485073630469936", 1)
  up.Ea.PrintFields(up.Ea.Field_S)
}


/**
 * Created by yangyongzhen on 2019/01/11
 * simple 8583 Protocol Analysis
 */
package easy8583
import (
  "bytes"
  "fmt"
  "strconv"
)
type Field struct {
  Ihave bool   //是否存在该域
  Ltype int    //长度类型 (NOVAR,LLVAR,LLLVAR)
  Dtype int    //数据类型 (BCD,ASCII)
  Len   int    //域的数据内容的长度
  Data  []byte //域的有效数据
}
type Easy8583 struct {
  Len     []byte
  Tpdu    []byte
  Head    []byte
  Msgtype []byte
  Bitmap  []byte
  Txbuf   []byte
  Field_S []Field //发送的域
  Field_R []Field //接收的域
}
//定义枚举类型 长度类型定义
const (
  NOVAR  = iota //value = 0,定长,
  LLVAR         //value = 1,长度为1字节
  LLLVAR        //value = 2,长度为2字节
)
//定义枚举类型 数据类型定义
const (
  UN  = iota //value = 0, 未定义,定长的域无需关注类型
  BIN        //value = 1,BIN
  BCD        //value = 2,BCD
)
//各个域的初始配置
func (ea *Easy8583) Init8583Fields(fds []Field) {
   for i := 0; i < 64;i++ {
    fds[i].Ihave = false
   }
  fds[0].Ltype = 0
  fds[1].Ltype = LLVAR //LLVAR
  fds[1].Dtype = BCD
  fds[2].Ltype = 0
  fds[2].Len = 3
  fds[3].Ltype = 0
  fds[3].Len = 6
  fds[10].Ltype = 0
  fds[10].Len = 3
  fds[11].Ltype = 0
  fds[11].Len = 3
  fds[12].Ltype = 0
  fds[12].Len = 2
  fds[13].Ltype = 0
  fds[13].Len = 2
  fds[14].Ltype = 0
  fds[14].Len = 2
  fds[21].Ltype = 0
  fds[21].Len = 2
  fds[22].Ltype = 0
  fds[22].Len = 2
  fds[24].Ltype = 0
  fds[24].Len = 1
  fds[25].Ltype = 0
  fds[25].Len = 1
  fds[31].Ltype = LLVAR //LLVAR
  fds[31].Dtype = BCD
  fds[34].Ltype = LLVAR //LLVAR
  fds[34].Dtype = BCD
  fds[36].Ltype = 0
  fds[36].Len = 12
  fds[37].Ltype = 0
  fds[37].Len = 6
  fds[38].Ltype = 0
  fds[38].Len = 2
  fds[39].Ltype = LLVAR
  fds[40].Ltype = 0
  fds[40].Len = 8
  fds[41].Ltype = 0
  fds[41].Len = 15
  fds[43].Ltype = LLVAR
  fds[47].Ltype = LLLVAR
  fds[47].Dtype = BCD
  fds[48].Ltype = 0
  fds[48].Len = 3
  fds[51].Ltype = 0
  fds[51].Len = 8
  fds[52].Ltype = 0
  fds[52].Len = 8
  fds[54].Ltype = LLLVAR //LLLVAR
  fds[58].Ltype = LLLVAR
  fds[59].Ltype = LLLVAR
  fds[59].Dtype = BCD
  fds[60].Ltype = LLLVAR
  fds[60].Dtype = BCD
  fds[61].Ltype = LLLVAR
  fds[62].Ltype = LLLVAR
  fds[63].Ltype = 0
  fds[63].Len = 8
}
/*
构造函数,初始化
*/
func New8583() *Easy8583 {
  var ea = new(Easy8583)
  ea.Txbuf = make([]byte, 0, 1024)
  ea.Txbuf = ea.Txbuf[0:23]
  ea.Len  = []byte{0x00, 0x00}
  ea.Tpdu = []byte{0x60, 0x05, 0x01, 0x00, 0x00}
  ea.Head = []byte{0x61, 0x31, 0x00, 0x31, 0x11, 0x08}
  ea.Msgtype = []byte{0x08, 0x00}
  ea.Bitmap = make([]byte, 8)
  ea.Field_S = make([]Field,64)
  ea.Field_R = make([]Field,64)
  ea.Init8583Fields(ea.Field_S)
  ea.Init8583Fields(ea.Field_R)
  return ea
}
func memcpy(dst, src []byte, size int) {
  for i := 0; i < size; i++ {
    dst[i] = src[i]
  }
  return
}
func bytesToHexStr(data []byte, lenth int) string {
  buf := data[0:lenth]
  hexStr := fmt.Sprintf("%x", buf)
  //fmt.Println(hexStr)
  return hexStr
}
// bytes to hex string
func bytesToHexString(b []byte) string {
  var buf bytes.Buffer
  for _, v := range b {
    t := strconv.FormatInt(int64(v), 16)
    if len(t) > 1 {
      buf.WriteString(t)
    } else {
      buf.WriteString("0" + t)
    }
  }
  return buf.String()
}
// hex string to bytes
func hexStringToBytes(s string) []byte {
  bs := make([]byte, 0)
  for i := 0; i < len(s); i = i + 2 {
    b, _ := strconv.ParseInt(s[i:i+2], 16, 16)
    bs = append(bs, byte(b))
  }
  return bs
}
//例:0x19 --> 19, 0x0119 -> 119
func bcdToInt(data []byte, lenth int) int {
  buf := data[0:lenth]
  hexStr := fmt.Sprintf("%x", buf)
  out, _ := strconv.ParseInt(hexStr, 10, 32)
  return int(out)
}
func toZero(p []byte) {
  for i := range p {
    p[i] = 0
  }
}
/*
8583报文打包
*/
func (ea *Easy8583) Pack8583Fields() int {
  fmt.Printf("pack 8583 fields\n")
  //ea.Txbuf[]
  ea.Txbuf = ea.Txbuf[0:23]
  toZero(ea.Txbuf)
  memcpy(ea.Txbuf[2:], ea.Tpdu, 5)
  memcpy(ea.Txbuf[7:], ea.Head, 6)
  memcpy(ea.Txbuf[13:], ea.Msgtype, 2)
  memcpy(ea.Txbuf[15:], ea.Bitmap, 8)
  j := 0
  len := 23
  tmplen := 0
  seat := 0x80
  for i := 0; i < 64; i++ {
    seat = (seat >> 1)
    if (i % 8) == 0 {
      j++
      seat = 0x80
    }
    if ea.Field_S[i].Ihave {
      ea.Bitmap[j-1] |= byte(seat)
      if ea.Field_S[i].Ltype == NOVAR {
        ea.Txbuf = ea.Txbuf[0 : len+ea.Field_S[i].Len]
        memcpy(ea.Txbuf[len:], ea.Field_S[i].Data, ea.Field_S[i].Len)
        len += ea.Field_S[i].Len
      } else if ea.Field_S[i].Ltype == LLVAR {
        ea.Txbuf = ea.Txbuf[0 : len+1]
        ea.Txbuf[len] = byte(ea.Field_S[i].Len)
        tmplen = bcdToInt(ea.Txbuf[len:],1)
        if ea.Field_S[i].Dtype == BCD {
          tmplen = ((tmplen/2) + (tmplen%2))
        }
        len += 1
        ea.Txbuf = ea.Txbuf[0 : len+tmplen]
        memcpy(ea.Txbuf[len:], ea.Field_S[i].Data, tmplen)
        len += tmplen
      } else if ea.Field_S[i].Ltype == LLLVAR {
        ea.Txbuf = ea.Txbuf[0 : len+2]
        ea.Txbuf[len] =   byte(ea.Field_S[i].Len>>8)
        ea.Txbuf[len+1] = byte(ea.Field_S[i].Len)
        tmplen = bcdToInt(ea.Txbuf[len:],2)
        if ea.Field_S[i].Dtype == BCD {
          tmplen = ((tmplen/2) + (tmplen%2))
        }
        len += 2
        ea.Txbuf = ea.Txbuf[0 : len+tmplen]
        memcpy(ea.Txbuf[len:], ea.Field_S[i].Data, tmplen)
        len += tmplen
      }
    }
    //报文总长度
    ea.Txbuf[0] = byte((len-2)>>8)
    ea.Txbuf[1] = byte((len-2))
    memcpy(ea.Len,ea.Txbuf,2)
  }
  return 0
}
/*
8583报文解包
*/
func (ea *Easy8583) Ans8583Fields( rxbuf []byte,rxlen int) int {
  fmt.Printf("ans 8583 fields\n")
  ea.Init8583Fields(ea.Field_R)
  len := 0
  tmplen := 0
  bitMap := make([]byte,8)
  var seat,buf uint64 = 1,0
  memcpy(bitMap,rxbuf[15:],8)
  memcpy(ea.Len,rxbuf[0:],2)
  //memcpy(ea.Tpdu,rxbuf[2:],5)
  memcpy(ea.Head,rxbuf[7:],6)
  memcpy(ea.Msgtype,rxbuf[13:],2)
  memcpy(ea.Bitmap,rxbuf[15:],8)
  len += 23
  for i := 0;i < 8;i++ {
        buf = ((buf<<8) | uint64(bitMap[i]))
  }
  for i := 0; i < 64; i++ {
    if  (buf & (seat << uint(63 - i))) > 0 {
      ea.Field_R[i].Ihave = true
      if ea.Field_R[i].Ltype == NOVAR {
        ea.Field_R[i].Data = make([]byte,ea.Field_R[i].Len)
        memcpy(ea.Field_R[i].Data, rxbuf[len:], ea.Field_R[i].Len)
        len += ea.Field_R[i].Len
      } else if ea.Field_R[i].Ltype == LLVAR {
        ea.Field_R[i].Len = int(rxbuf[len])
        tmplen = bcdToInt(rxbuf[len:],1)
        if ea.Field_R[i].Dtype == BCD {
          tmplen = ((tmplen/2) + (tmplen%2))
        }
        len += 1
        ea.Field_R[i].Data = make([]byte,tmplen)
        memcpy(ea.Field_R[i].Data, rxbuf[len:], tmplen)
        len += tmplen
      } else if ea.Field_R[i].Ltype == LLLVAR {
        ea.Field_R[i].Len = ( ( int(rxbuf[len])<<8 ) | int(rxbuf[len+1] ) )
        tmplen = bcdToInt(rxbuf[len:],2)
        if ea.Field_R[i].Dtype == BCD {
          tmplen = ((tmplen/2) + (tmplen%2))
        }
        len += 2
        ea.Field_R[i].Data = make([]byte,tmplen)
        memcpy(ea.Field_R[i].Data, rxbuf[len:], tmplen)
        len += tmplen
      }
    }
  }
  if(len > rxlen){
        return 1;
  }
  return 0
}
/*
打印信息,调试用
*/
func (ea *Easy8583) PrintFields(fds []Field){
  fmt.Println("Print fields...")
  fmt.Printf("\n==========================================\n")
  fmt.Printf("Len:\t%s\n", bytesToHexString(ea.Len))
  fmt.Printf("Tpdu:\t%s\n", bytesToHexString(ea.Tpdu))
  fmt.Printf("Head:\t%s\n", bytesToHexString(ea.Head))
  fmt.Printf("Msge:\t%s\n", bytesToHexString(ea.Msgtype))
  fmt.Printf("Bitmap:\t%s\n", bytesToHexString(ea.Bitmap))
  fmt.Printf("\n==========================================\n")
  for i:=0; i < 64; i++{
    if fds[i].Ihave {
      fmt.Printf("[field:%d] ",i+1)
      if fds[i].Ltype == LLVAR{
        fmt.Printf("[len:%02x] ",fds[i].Len)
      }else if fds[i].Ltype == LLLVAR{
        fmt.Printf("[len:%04x] ",fds[i].Len)
      }
      fmt.Printf("[%s]\n",bytesToHexString(fds[i].Data))
      fmt.Printf("\n------------------------------\n")
    }
  }
}
func main() {
  fmt.Println("test...")
}
相关文章
|
21天前
|
安全 前端开发 Android开发
探索移动应用与系统:从开发到操作系统的深度解析
在数字化时代的浪潮中,移动应用和操作系统成为了我们日常生活的重要组成部分。本文将深入探讨移动应用的开发流程、关键技术和最佳实践,同时分析移动操作系统的核心功能、架构和安全性。通过实际案例和代码示例,我们将揭示如何构建高效、安全且用户友好的移动应用,并理解不同操作系统之间的差异及其对应用开发的影响。无论你是开发者还是对移动技术感兴趣的读者,这篇文章都将为你提供宝贵的见解和知识。
|
27天前
|
存储 缓存 监控
后端开发中的缓存机制:深度解析与最佳实践####
本文深入探讨了后端开发中不可或缺的一环——缓存机制,旨在为读者提供一份详尽的指南,涵盖缓存的基本原理、常见类型(如内存缓存、磁盘缓存、分布式缓存等)、主流技术选型(Redis、Memcached、Ehcache等),以及在实际项目中如何根据业务需求设计并实施高效的缓存策略。不同于常规摘要的概述性质,本摘要直接点明文章将围绕“深度解析”与“最佳实践”两大核心展开,既适合初学者构建基础认知框架,也为有经验的开发者提供优化建议与实战技巧。 ####
|
25天前
|
开发框架 Go 计算机视觉
纯Go语言开发人脸检测、瞳孔/眼睛定位与面部特征检测插件-助力GoFly快速开发框架
开发纯go插件的原因是因为目前 Go 生态系统中几乎所有现有的人脸检测解决方案都是纯粹绑定到一些 C/C++ 库,如 OpenCV 或 dlib,但通过 cgo 调用 C 程序会引入巨大的延迟,并在性能方面产生显著的权衡。此外,在许多情况下,在各种平台上安装 OpenCV 是很麻烦的。使用纯Go开发的插件不仅在开发时方便,在项目部署和项目维护也能省很多时间精力。
|
25天前
|
Java 调度 Android开发
安卓与iOS开发中的线程管理差异解析
在移动应用开发的广阔天地中,安卓和iOS两大平台各自拥有独特的魅力。如同东西方文化的差异,它们在处理多线程任务时也展现出不同的哲学。本文将带你穿梭于这两个平台之间,比较它们在线程管理上的核心理念、实现方式及性能考量,助你成为跨平台的编程高手。
|
1月前
|
监控 前端开发 安全
如何开发一个网站:全面解析与实战指南
在数字化时代,网站是企业和个人展示形象、传播信息的关键平台。本文提供从规划、设计、开发、上线到后期维护的全方位网站开发指南,涵盖明确目标、分析用户、设定功能需求、设计风格、技术选型、测试部署及优化升级等内容,帮助你打造既美观又实用的网站。
60 4
|
27天前
|
前端开发 Android开发 UED
移动应用与系统:从开发到优化的全面解析####
本文深入探讨了移动应用开发的全过程,从最初的构思到最终的发布,并详细阐述了移动操作系统对应用性能和用户体验的影响。通过分析当前主流移动操作系统的特性及差异,本文旨在为开发者提供一套全面的开发与优化指南,确保应用在不同平台上均能实现最佳表现。 ####
28 0
|
1月前
|
Linux 网络安全 数据安全/隐私保护
Linux 超级强大的十六进制 dump 工具:XXD 命令,我教你应该如何使用!
在 Linux 系统中,xxd 命令是一个强大的十六进制 dump 工具,可以将文件或数据以十六进制和 ASCII 字符形式显示,帮助用户深入了解和分析数据。本文详细介绍了 xxd 命令的基本用法、高级功能及实际应用案例,包括查看文件内容、指定输出格式、写入文件、数据比较、数据提取、数据转换和数据加密解密等。通过掌握这些技巧,用户可以更高效地处理各种数据问题。
108 8
|
1月前
|
监控 Linux
如何检查 Linux 内存使用量是否耗尽?这 5 个命令堪称绝了!
本文介绍了在Linux系统中检查内存使用情况的5个常用命令:`free`、`top`、`vmstat`、`pidstat` 和 `/proc/meminfo` 文件,帮助用户准确监控内存状态,确保系统稳定运行。
381 6
|
1月前
|
Linux
在 Linux 系统中,“cd”命令用于切换当前工作目录
在 Linux 系统中,“cd”命令用于切换当前工作目录。本文详细介绍了“cd”命令的基本用法和常见技巧,包括使用“.”、“..”、“~”、绝对路径和相对路径,以及快速切换到上一次工作目录等。此外,还探讨了高级技巧,如使用通配符、结合其他命令、在脚本中使用,以及实际应用案例,帮助读者提高工作效率。
88 3

热门文章

最新文章