a2800276 / 8583

ruby implementation of iso 8583 financial messages
http://www.kuriositaet.de
MIT License
42 stars 45 forks source link

unicode in to_b #11

Closed uptownhr closed 9 years ago

uptownhr commented 9 years ago

Just got to my first test message class. After sending in some initial values, and using the to_b method to see the result, i'm seeing a bunch of "\u" texts in the beginning. Do you know why this is happening or help explain what is going on and what I can do to remove this?

    class Message < ISO8583::Message
      mti_format ISO8583::N, :length => 4
      mti 0100, "Authorisation Request"

      bmp 2, "Primary Account Number (PAN)", ISO8583::LLVAR_N, :max => 19
      bmp 3, "Processing Code", ISO8583::N, :length => 4
      bmp_alias 2, :pan
    end

      message = Iso::Omnipay::Message.new 0100
      message[2] = '4242424242424242'
      message[3] = '0001'
      message.to_b #0064`\u0000\u0000\u0000\u0000\u0000\u0000\u00001642424242424242420001
a2800276 commented 9 years ago

i'm seeing a bunch of "\u" texts in the beginning

unfortunately ruby is not very good at handling byte data. This is how ruby escapes strings to represent the binary 0x00 values in the initial bitmap.

uptownhr commented 9 years ago
message._body
["`\x00\x00\x00\x00\x00\x00\x00", "1642424242424242420001"]

Sorry, I'm having hard time following, is _body[0], the hex bitmap for the message? Where would be the best place to modify this? I'm assuming defining bm1?
a2800276 commented 9 years ago

I'm having a hard time following as well :) How does this relate to the last question? What are you trying to do? In general, you shouldn't need to touch any _underscore methods, consider them private.

uptownhr commented 9 years ago

:). I'm trying to get the bitmap representing the message. the \x00 doesn't seem to be right according to the the bms 2 an 3. I'm trying to get the hex of 011 representing the bits that are being sent

a2800276 commented 9 years ago

What do you mean by "the hex of '011' "?

Can't really say what's wrong off the bat, without actual working code (also, what ruby version?).

One things I noticed: 0 prefixing is octal (just as 0x prefixing is hex), so 0100 is probably not what you intend...

uptownhr commented 9 years ago

sorry, i'm trying to get my head wrapped around this right now. Basically here's the code that I'm working on and what I'm expecting to achieve.

For omnipay, BM1 contains the message_type, primary_bitmap, and secondary_bitmap

The primary_bitmap is a 16 byte hex that represents 64BMs that are going to be a part of the message. *first byte is a conditional indicator for the prescense of the secondary_bitmap

For example, BM1 :message_type => N, :length => 4 :primary_bitmap => N, :length => 16 :secondary_bitmap => N, :length => 16 #conditional if first it in primary_bitmap is on

primary_bitmap = 011 .......... 64 Represents that bits 2 and 3 are being sent. #in hex, 6000000000000000 pan = 4242424242424242 processing_code = 0001

The full byte message with the message length would look as follows, 00400100600000000000000042424242424242420001

Basically, my primary goal is to manually get the primary_bitmap. As to the current .to_b is not resulting in the correct length.

a2800276 commented 9 years ago

Basically here's the code that I'm working on and what I'm expecting to achieve.

I think you forgot to provide a link to the code?

For omnipay, BM1 contains the message_type, primary_bitmap, and secondary_bitmap

Generally, the mti (message type) is not part of bmp 1. Can you provide the docs of the format you're implementing?

Basically, my primary goal is to manually get the primary_bitmap. As to the current .to_b is not resulting in the correct length.

You're calling to_b on the entire message, so you're getting back the entire message. Have a look at the bitmap test cases, if you're only interested in generating/decoding bitmaps.

uptownhr commented 9 years ago

Here's the method I wrote to mimic what I want.

def get_message
        message_data = _body[1]
        #get used bits
        used_bits = @values.map do |v|
          v[0]
        end

        primary_bitmap = ''

        #create 1st bit on bitmap depending on if BMS > 64 are set
        if used_bits.any?{ |bit| bit > 64 }
          primary_bitmap << '1'
          secondary_map = true
        else
          primary_bitmap << '0'
          secondary_map = false
        end

        #get primarybitmap
        (2..64).each do |i|
          if used_bits.any? { |bit| bit == i }
            primary_bitmap << '1'
          else
            primary_bitmap << '0'
          end
        end

        #convert to hex
        primary_bitmap_hex = primary_bitmap.to_i(2).to_s(16)

        #run secondary bitmap if 1st bit is set
        secondary_bitmap = ''
        secondary_bitmap_hex = ''
        if secondary_map
          (65..128).each do |i|
            if used_bits.any? { |bit| bit == i }
              secondary_bitmap << '1'
            else
              secondary_bitmap << '0'
            end
          end
          secondary_bitmap_hex = secondary_bitmap.to_i(2).to_s(16)
        end

        bm_message = self.mti + primary_bitmap_hex + secondary_bitmap_hex + message_data
        res = bm_message.length.to_s.rjust(4,'0') + bm_message

        return res
      end
a2800276 commented 9 years ago

Ok, still not sure what you are trying to do. If you just want to create a bitmap with the proper bits set, use the bitmap class directly instead of generating an entire message and then stripping the message off the bitmap. Like so:

 require 'iso8583/bitmap'
 bitmap = ISO8583::Bitmap.new
 [4,6,8].each {|b| bitmap.set(b)} # or bitmap[b] = true
 [4,5,6,7,8].each {|b| puts "#{b} ? #{bitmap[b]}"}
 puts bitmap.to_s

This outputs:

4 ? true
5 ? false
6 ? true
7 ? false
8 ? true
0001010100000000000000000000000000000000000000000000000000000000

You can access the raw bytes using Bitmap's to_bytes method