easycard 1.0.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- checksums.yaml +7 -0
- data/bin/easycard +57 -0
- data/lib/easycard.rb +45 -0
- data/lib/easycard/color_string.rb +10 -0
- data/lib/easycard/response.rb +66 -0
- data/lib/easycard/version.rb +3 -0
- metadata +65 -0
checksums.yaml
ADDED
@@ -0,0 +1,7 @@
|
|
1
|
+
---
|
2
|
+
SHA1:
|
3
|
+
metadata.gz: de65d5a1fa9046e9b85a468ce23da1c259b968cf
|
4
|
+
data.tar.gz: c0c60ef9ea374f6957fa657dd4092dc7ee70565b
|
5
|
+
SHA512:
|
6
|
+
metadata.gz: 602fdb29058772249ab6eb56b19bf43a21025f8b1ee6d8608ddb72f8ab89e0d1ec168fb6e0cbd742e8d9fec4e544f9089b45f393e71a2b079060bbc258cc7e54
|
7
|
+
data.tar.gz: 5257b248199a25b517710f2421c5fd86f2e0bf1352457aa2c26556da2529fd3f218097d8ab5a6095b5d40cda859c10a75ea296642b1039a1ef80a6566f8f25fb
|
data/bin/easycard
ADDED
@@ -0,0 +1,57 @@
|
|
1
|
+
#!/usr/bin/env ruby
|
2
|
+
require 'optparse'
|
3
|
+
require 'optparse/time'
|
4
|
+
require 'easycard'
|
5
|
+
|
6
|
+
options = {format: :table, from: Date.today << 1, to: Date.today}
|
7
|
+
parser = OptionParser.new do |opts|
|
8
|
+
opts.banner = 'Usage: easycard CARD_ID [options]'
|
9
|
+
|
10
|
+
opts.on('-mNUMBER', '--months=NUMBER', Float, '最近 n 月') do |n|
|
11
|
+
today = Date.today
|
12
|
+
options[:from] = today << n
|
13
|
+
options[:to] = today
|
14
|
+
end
|
15
|
+
|
16
|
+
opts.on('-dNUMBER', '--days=NUMBER', Float, '最近 n 天') do |n|
|
17
|
+
today = Date.today
|
18
|
+
options[:from] = today - n
|
19
|
+
options[:to] = today
|
20
|
+
end
|
21
|
+
|
22
|
+
opts.on('-j', '--json', '以 JSON 格式顯示') do
|
23
|
+
options[:format] = :json
|
24
|
+
end
|
25
|
+
|
26
|
+
opts.on('-y', '--yaml', '以 YAML 格式顯示') do
|
27
|
+
options[:format] = :yaml
|
28
|
+
end
|
29
|
+
|
30
|
+
opts.on('-f', '--from=YYYY/MM/DD', Time, '起始時間') do |time|
|
31
|
+
options[:from] = time
|
32
|
+
end
|
33
|
+
|
34
|
+
opts.on('-t', '--to=YYYY/MM/DD', Time, '結束時間') do |time|
|
35
|
+
options[:to] = time
|
36
|
+
end
|
37
|
+
|
38
|
+
opts.on('-h', '--help', '顯示此訊息') do |v|
|
39
|
+
puts opts
|
40
|
+
exit 0
|
41
|
+
end
|
42
|
+
end
|
43
|
+
|
44
|
+
parser.parse!
|
45
|
+
|
46
|
+
if ARGV.empty?
|
47
|
+
puts parser.help
|
48
|
+
exit 0
|
49
|
+
end
|
50
|
+
|
51
|
+
|
52
|
+
begin
|
53
|
+
response = EasyCard.query(ARGV.first, from: options[:from], to: options[:to])
|
54
|
+
puts response.as(options[:format])
|
55
|
+
rescue EasyCard::Error => e
|
56
|
+
$stderr.puts e.message
|
57
|
+
end
|
data/lib/easycard.rb
ADDED
@@ -0,0 +1,45 @@
|
|
1
|
+
require 'easycard/response'
|
2
|
+
require 'openssl'
|
3
|
+
require 'cgi'
|
4
|
+
require 'base64'
|
5
|
+
require 'net/http'
|
6
|
+
|
7
|
+
module EasyCard
|
8
|
+
KEY = 'EasyCardToKingay23456789'
|
9
|
+
IV = '01234567'
|
10
|
+
SALT = 'L0CalKing'
|
11
|
+
CONST = 8544
|
12
|
+
|
13
|
+
class Error < RuntimeError; end
|
14
|
+
class NotFound < Error; end
|
15
|
+
|
16
|
+
module_function
|
17
|
+
|
18
|
+
def query cart_number, from: Date.today-30, to: Date.today, format: nil
|
19
|
+
query_hash = {
|
20
|
+
cardID: card_id(cart_number),
|
21
|
+
begin: from.strftime('%Y-%m-%d'),
|
22
|
+
end: to.strftime('%Y-%m-%d'),
|
23
|
+
verify: verify,
|
24
|
+
ev: 1
|
25
|
+
}
|
26
|
+
uri = URI('https://wallet.easycard.com.tw/EasyWallet/QueryManager/V3/GetTXNThinDataInfo')
|
27
|
+
uri.query = URI.encode_www_form(query_hash)
|
28
|
+
Response.new(Net::HTTP.get(uri))
|
29
|
+
end
|
30
|
+
|
31
|
+
def card_id card_number
|
32
|
+
remainder = card_number.size % 16
|
33
|
+
data = card_number + "\x06"*(16 - remainder) if remainder != 0
|
34
|
+
cipher = OpenSSL::Cipher.new('DES3')
|
35
|
+
cipher.encrypt
|
36
|
+
cipher.key = KEY
|
37
|
+
cipher.iv = IV
|
38
|
+
Base64.encode64(cipher.update(data)).chop!
|
39
|
+
end
|
40
|
+
|
41
|
+
def verify time = Time.now
|
42
|
+
seed = time.month + time.day + time.hour
|
43
|
+
Digest::MD5.hexdigest("#{seed * CONST}#{SALT}").upcase!
|
44
|
+
end
|
45
|
+
end
|
@@ -0,0 +1,66 @@
|
|
1
|
+
require 'easycard/color_string'
|
2
|
+
require 'json'
|
3
|
+
require 'yaml'
|
4
|
+
require 'forwardable'
|
5
|
+
|
6
|
+
module EasyCard
|
7
|
+
class Response
|
8
|
+
extend Forwardable
|
9
|
+
|
10
|
+
attr_reader :data, :raw_data, :parsed_data, :balance
|
11
|
+
def_delegators :@data, :to_json, :to_yaml, :to_a
|
12
|
+
|
13
|
+
using ColorString
|
14
|
+
|
15
|
+
def self.normalize_record record
|
16
|
+
type = case record[?T]
|
17
|
+
when ?D then :withdrawal
|
18
|
+
when ?U then :deposit
|
19
|
+
when '罰款' then :fine
|
20
|
+
when '查無交易資料' then raise EasyCard::NotFound, record[?T]
|
21
|
+
else raise EasyCard::Error, "未知類型: #{record[?T]}"
|
22
|
+
end
|
23
|
+
record[?L].gsub!('<BR>', ?-)
|
24
|
+
{type: type, datetime: record[?D], location: record[?L], balance: record[?A], amount: record[?Q]}
|
25
|
+
end
|
26
|
+
|
27
|
+
def self.type_text type
|
28
|
+
case type
|
29
|
+
when :withdrawal then '扣款'.red.bold
|
30
|
+
when :deposit then '儲值'.green.bold
|
31
|
+
when :fine then '罰款'.yellow.bold
|
32
|
+
end
|
33
|
+
end
|
34
|
+
|
35
|
+
def initialize raw_data
|
36
|
+
@raw_data = raw_data
|
37
|
+
@parsed_data = JSON.parse(@raw_data)
|
38
|
+
@balance = @parsed_data.pop[?B].to_i if @parsed_data.last[?B]
|
39
|
+
@data = @parsed_data.map do |record|
|
40
|
+
self.class.normalize_record(record)
|
41
|
+
end
|
42
|
+
end
|
43
|
+
|
44
|
+
def as format = nil
|
45
|
+
case format
|
46
|
+
when :json then to_json
|
47
|
+
when :yaml then to_yaml
|
48
|
+
when :table then to_s
|
49
|
+
else data
|
50
|
+
end
|
51
|
+
end
|
52
|
+
|
53
|
+
def to_s
|
54
|
+
ret = "%3s | %-17s | %s | %-3s | %-3s | %s\n" % %w[# 時間 種類 金額 餘額 地點]
|
55
|
+
ret << "#{?-*3} | #{?-*19} | #{?-*4} | #{?-*5} | #{?-*5} | #{?-*20}\n"
|
56
|
+
@data.each_with_index.map{|record, i| ret << line(i+1, record) << $/}
|
57
|
+
ret
|
58
|
+
end
|
59
|
+
|
60
|
+
def line id, record
|
61
|
+
type = self.class.type_text(record[:type])
|
62
|
+
'%3d | %19s | %s | %5s | %5s | %s' % [id, record[:datetime], type, record[:amount], record[:balance], record[:location]]
|
63
|
+
end
|
64
|
+
|
65
|
+
end
|
66
|
+
end
|
metadata
ADDED
@@ -0,0 +1,65 @@
|
|
1
|
+
--- !ruby/object:Gem::Specification
|
2
|
+
name: easycard
|
3
|
+
version: !ruby/object:Gem::Version
|
4
|
+
version: 1.0.0
|
5
|
+
platform: ruby
|
6
|
+
authors:
|
7
|
+
- Jian Weihang
|
8
|
+
autorequire:
|
9
|
+
bindir: bin
|
10
|
+
cert_chain: []
|
11
|
+
date: 2015-05-06 00:00:00.000000000 Z
|
12
|
+
dependencies:
|
13
|
+
- !ruby/object:Gem::Dependency
|
14
|
+
name: rake
|
15
|
+
requirement: !ruby/object:Gem::Requirement
|
16
|
+
requirements:
|
17
|
+
- - "~>"
|
18
|
+
- !ruby/object:Gem::Version
|
19
|
+
version: '0'
|
20
|
+
type: :development
|
21
|
+
prerelease: false
|
22
|
+
version_requirements: !ruby/object:Gem::Requirement
|
23
|
+
requirements:
|
24
|
+
- - "~>"
|
25
|
+
- !ruby/object:Gem::Version
|
26
|
+
version: '0'
|
27
|
+
description: |
|
28
|
+
台灣悠遊卡交易紀錄查詢工具,支援指令模式。
|
29
|
+
A search tool for Taiwan EasyCard, supporting CLI mode.
|
30
|
+
email: tonytonyjan@gmail.com
|
31
|
+
executables:
|
32
|
+
- easycard
|
33
|
+
extensions: []
|
34
|
+
extra_rdoc_files: []
|
35
|
+
files:
|
36
|
+
- bin/easycard
|
37
|
+
- lib/easycard.rb
|
38
|
+
- lib/easycard/color_string.rb
|
39
|
+
- lib/easycard/response.rb
|
40
|
+
- lib/easycard/version.rb
|
41
|
+
homepage: https://github.com/tonytonyjan/easycard
|
42
|
+
licenses:
|
43
|
+
- MIT
|
44
|
+
metadata: {}
|
45
|
+
post_install_message:
|
46
|
+
rdoc_options: []
|
47
|
+
require_paths:
|
48
|
+
- lib
|
49
|
+
required_ruby_version: !ruby/object:Gem::Requirement
|
50
|
+
requirements:
|
51
|
+
- - ">="
|
52
|
+
- !ruby/object:Gem::Version
|
53
|
+
version: '0'
|
54
|
+
required_rubygems_version: !ruby/object:Gem::Requirement
|
55
|
+
requirements:
|
56
|
+
- - ">="
|
57
|
+
- !ruby/object:Gem::Version
|
58
|
+
version: '0'
|
59
|
+
requirements: []
|
60
|
+
rubyforge_project:
|
61
|
+
rubygems_version: 2.4.6
|
62
|
+
signing_key:
|
63
|
+
specification_version: 4
|
64
|
+
summary: "台灣悠遊卡交易紀錄查詢工具/A search tool for Taiwan EasyCard"
|
65
|
+
test_files: []
|