junziqian 0.1.1
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +7 -0
- data/.gitignore +10 -0
- data/.ruby-version +1 -0
- data/.travis.yml +5 -0
- data/Gemfile +5 -0
- data/README.md +64 -0
- data/Rakefile +10 -0
- data/bin/console +14 -0
- data/bin/setup +8 -0
- data/junziqian.gemspec +35 -0
- data/lib/junziqian.rb +16 -0
- data/lib/junziqian/cfg/client_info.rb +22 -0
- data/lib/junziqian/cfg/enum.rb +43 -0
- data/lib/junziqian/interface/apply_sign_file_request.rb +100 -0
- data/lib/junziqian/interface/base_request.rb +17 -0
- data/lib/junziqian/interface/detail_anony_link_request.rb +33 -0
- data/lib/junziqian/interface/file_link_request.rb +43 -0
- data/lib/junziqian/interface/ping.rb +23 -0
- data/lib/junziqian/interface/pres_file_link.rb +55 -0
- data/lib/junziqian/interface/sign_status_request.rb +54 -0
- data/lib/junziqian/model/signatory.rb +25 -0
- data/lib/junziqian/tool/attache_utils.rb +33 -0
- data/lib/junziqian/tool/http_sign_utils.rb +43 -0
- data/lib/junziqian/tool/request_tool.rb +127 -0
- data/lib/junziqian/version.rb +3 -0
- metadata +109 -0
checksums.yaml
ADDED
@@ -0,0 +1,7 @@
|
|
1
|
+
---
|
2
|
+
SHA1:
|
3
|
+
metadata.gz: b64f3ed120e160c2d5b413cbdaeeb23b187b8bbe
|
4
|
+
data.tar.gz: b9db8cfb9678ebc2fe53e9a0721635632d664a45
|
5
|
+
SHA512:
|
6
|
+
metadata.gz: 61aa917eab2244132b37f1d5099ff7784a6e66eb3e541a53531cbd820f98e5a42c7b8d72860bc47d2250360777fead9cf21adf89bd3073d26eedaf43973eb982
|
7
|
+
data.tar.gz: a86e879dfb88eea35bf243412f933fee5e08908e169c541a481af5edab15edc294cd2f4c1b4ac7ca063d31b245946d1a30f4b6d3de199a668468afd63a8a7f12
|
data/.gitignore
ADDED
data/.ruby-version
ADDED
@@ -0,0 +1 @@
|
|
1
|
+
2.3.1
|
data/.travis.yml
ADDED
data/Gemfile
ADDED
data/README.md
ADDED
@@ -0,0 +1,64 @@
|
|
1
|
+
# Junziqian
|
2
|
+
|
3
|
+
Junziqian is an electronic sign contract system. This gem is an adaptor for interactive with junziqian's service.
|
4
|
+
|
5
|
+
君子签是电子签章的一种,上传签约人,签约合同,实现电子签章或手工签约,并在三方保存,以符合一定的法律效力。
|
6
|
+
|
7
|
+
## Installation
|
8
|
+
|
9
|
+
Add this line to your application's Gemfile:
|
10
|
+
|
11
|
+
```ruby
|
12
|
+
gem 'junziqian'
|
13
|
+
```
|
14
|
+
|
15
|
+
And then execute:
|
16
|
+
|
17
|
+
$ bundle
|
18
|
+
|
19
|
+
Or install it yourself as:
|
20
|
+
|
21
|
+
$ gem install junziqian
|
22
|
+
|
23
|
+
## Usage
|
24
|
+
|
25
|
+
* 首先设置您的接口信息,包含请求地址,key,secret,gem通过 ENV 变量获取三个参数; 合同下载存放路径 ENV['contract_path'] (默认为/tmp)
|
26
|
+
````
|
27
|
+
def services_url
|
28
|
+
ENV['JZQ_SERVICES_URL'] || 'http://sandbox.api.junziqian.com/services'
|
29
|
+
end
|
30
|
+
|
31
|
+
def app_key
|
32
|
+
ENV['JZQ_APP_KEY'] || 'ecf3961459a07af4'
|
33
|
+
end
|
34
|
+
|
35
|
+
def app_secret
|
36
|
+
ENV['JZQ_APP_SECRET'] || '187a255fecf3961459a07af4d2035e47'
|
37
|
+
end
|
38
|
+
````
|
39
|
+
* 实现ping接口检测、文件上传签约、状态查询、查看链接、下载链接等等的功能,具体请看lib/junziqian/interface目录
|
40
|
+
|
41
|
+
* 回调参数校验
|
42
|
+
````
|
43
|
+
body_hash = {
|
44
|
+
'applyNo' => params[:applyNo],
|
45
|
+
'identityType' => params[:identityType],
|
46
|
+
'fullName' => params[:fullName],
|
47
|
+
'identityCard' => params[:identityCard],
|
48
|
+
'optTime' => params[:optTime],
|
49
|
+
'signStatus' => params[:signStatus]
|
50
|
+
}
|
51
|
+
if params[:sign] == Junziqian::Tool::RequestTool.create_http_sign(body_hash, params[:timestamp])
|
52
|
+
...
|
53
|
+
...
|
54
|
+
````
|
55
|
+
## Development
|
56
|
+
|
57
|
+
After checking out the repo, run `bin/setup` to install dependencies. Then, run `rake test` to run the tests. You can also run `bin/console` for an interactive prompt that will allow you to experiment.
|
58
|
+
|
59
|
+
To install this gem onto your local machine, run `bundle exec rake install`. To release a new version, update the version number in `version.rb`, and then run `bundle exec rake release`, which will create a git tag for the version, push git commits and tags, and push the `.gem` file to [rubygems.org](https://rubygems.org).
|
60
|
+
|
61
|
+
## Contributing
|
62
|
+
|
63
|
+
Bug reports and pull requests are welcome on GitHub at https://github.com/[USERNAME]/junziqian.
|
64
|
+
|
data/Rakefile
ADDED
data/bin/console
ADDED
@@ -0,0 +1,14 @@
|
|
1
|
+
#!/usr/bin/env ruby
|
2
|
+
|
3
|
+
require "bundler/setup"
|
4
|
+
require "junziqian"
|
5
|
+
|
6
|
+
# You can add fixtures and/or initialization code here to make experimenting
|
7
|
+
# with your gem easier. You can also use a different console, if you like.
|
8
|
+
|
9
|
+
# (If you use this, don't forget to add pry to your Gemfile!)
|
10
|
+
# require "pry"
|
11
|
+
# Pry.start
|
12
|
+
|
13
|
+
require "irb"
|
14
|
+
IRB.start(__FILE__)
|
data/bin/setup
ADDED
data/junziqian.gemspec
ADDED
@@ -0,0 +1,35 @@
|
|
1
|
+
# coding: utf-8
|
2
|
+
lib = File.expand_path('../lib', __FILE__)
|
3
|
+
$LOAD_PATH.unshift(lib) unless $LOAD_PATH.include?(lib)
|
4
|
+
require 'junziqian/version'
|
5
|
+
|
6
|
+
Gem::Specification.new do |spec|
|
7
|
+
spec.name = "junziqian"
|
8
|
+
spec.version = Junziqian::VERSION
|
9
|
+
spec.authors = ["方峦"]
|
10
|
+
spec.email = ["moonless@fangluandeMacBook-Pro.local"]
|
11
|
+
|
12
|
+
spec.summary = %q{支持君子签,电子签名}
|
13
|
+
spec.description = %q{ruby版本的支持君子签,电子签名的gem库}
|
14
|
+
spec.homepage = "http://github.com/orichi/junziqian"
|
15
|
+
|
16
|
+
# Prevent pushing this gem to RubyGems.org. To allow pushes either set the 'allowed_push_host'
|
17
|
+
# to allow pushing to a single host or delete this section to allow pushing to any host.
|
18
|
+
if spec.respond_to?(:metadata)
|
19
|
+
#spec.metadata['allowed_push_host'] = ""
|
20
|
+
else
|
21
|
+
raise "RubyGems 2.0 or newer is required to protect against " \
|
22
|
+
"public gem pushes."
|
23
|
+
end
|
24
|
+
|
25
|
+
spec.files = `git ls-files -z`.split("\x0").reject do |f|
|
26
|
+
f.match(%r{^(test|spec|features)/})
|
27
|
+
end
|
28
|
+
spec.bindir = "exe"
|
29
|
+
spec.executables = spec.files.grep(%r{^exe/}) { |f| File.basename(f) }
|
30
|
+
spec.require_paths = ["lib"]
|
31
|
+
|
32
|
+
spec.add_development_dependency "bundler", "~> 1.14"
|
33
|
+
spec.add_development_dependency "rake", "~> 10.0"
|
34
|
+
spec.add_development_dependency "minitest", "~> 5.0"
|
35
|
+
end
|
data/lib/junziqian.rb
ADDED
@@ -0,0 +1,16 @@
|
|
1
|
+
require "junziqian/version"
|
2
|
+
require "junziqian/cfg/client_info"
|
3
|
+
require "junziqian/cfg/enum"
|
4
|
+
require "junziqian/tool/http_sign_utils"
|
5
|
+
require "junziqian/tool/request_tool"
|
6
|
+
require "junziqian/tool/attache_utils"
|
7
|
+
require 'junziqian/model/signatory'
|
8
|
+
require 'junziqian/interface/base_request'
|
9
|
+
require 'junziqian/interface/ping'
|
10
|
+
require 'junziqian/interface/apply_sign_file_request'
|
11
|
+
require 'junziqian/interface/detail_anony_link_request'
|
12
|
+
require 'junziqian/interface/file_link_request'
|
13
|
+
|
14
|
+
module Junziqian
|
15
|
+
# Your code goes here...
|
16
|
+
end
|
@@ -0,0 +1,22 @@
|
|
1
|
+
require 'singleton'
|
2
|
+
module Junziqian
|
3
|
+
module Cfg
|
4
|
+
class ClientInfo
|
5
|
+
include Singleton
|
6
|
+
|
7
|
+
class << self
|
8
|
+
def services_url
|
9
|
+
ENV['JZQ_SERVICES_URL'] || 'http://sandbox.api.junziqian.com/services'
|
10
|
+
end
|
11
|
+
|
12
|
+
def app_key
|
13
|
+
ENV['JZQ_APP_KEY'] || 'ecf3961459a07af4'
|
14
|
+
end
|
15
|
+
|
16
|
+
def app_secret
|
17
|
+
ENV['JZQ_APP_SECRET'] || '187a255fecf3961459a07af4d2035e47'
|
18
|
+
end
|
19
|
+
end
|
20
|
+
end
|
21
|
+
end
|
22
|
+
end
|
@@ -0,0 +1,43 @@
|
|
1
|
+
module Junziqian
|
2
|
+
module Cfg
|
3
|
+
class Enum
|
4
|
+
# 用户身分证明类型枚举
|
5
|
+
IDCARD={"code" => 1, "type" => 0}
|
6
|
+
PASSPORT={"code" => 2, "type" => 0}
|
7
|
+
MTP={"code" => 3, "type" => 0}
|
8
|
+
RTMP={"code" => 4, "type" => 0}
|
9
|
+
BIZLIC={"code" => 11, "type" => 1}
|
10
|
+
USCC={"code" => 12, "type" => 1}
|
11
|
+
OTHER={"code" => 99, "type" => 3}
|
12
|
+
|
13
|
+
# * 验证等级
|
14
|
+
USEKEY=1
|
15
|
+
BANKCARD=2
|
16
|
+
ALIPAY=3
|
17
|
+
BANKTHREE=10
|
18
|
+
FACE=11
|
19
|
+
|
20
|
+
# * 企业类型
|
21
|
+
ENTERPRISE="0"
|
22
|
+
PUBLIC_INSTITUTION="1"
|
23
|
+
|
24
|
+
# 签章等级
|
25
|
+
GENERAL="0"
|
26
|
+
SEAL="1"
|
27
|
+
ESIGNSEAL="2"
|
28
|
+
|
29
|
+
#签字状态
|
30
|
+
NOTINIT=-1
|
31
|
+
INPROGRESS=0
|
32
|
+
COMPLETED=1
|
33
|
+
REFUSE=2
|
34
|
+
PRES=3
|
35
|
+
|
36
|
+
# 合同的处理类型,可以人签,也可以自动签
|
37
|
+
DEFAULT="0"
|
38
|
+
AUTH_SIGN="1"
|
39
|
+
ONLY_PRES="2"
|
40
|
+
AUTH_SIGN_PART='5'
|
41
|
+
end
|
42
|
+
end
|
43
|
+
end
|
@@ -0,0 +1,100 @@
|
|
1
|
+
module Junziqian
|
2
|
+
module Interface
|
3
|
+
class ApplySignFileRequest < BaseRequest
|
4
|
+
# attr_accessor :contractName
|
5
|
+
# attr_accessor :serverCa
|
6
|
+
# attr_accessor :dealType
|
7
|
+
# attr_accessor :file
|
8
|
+
# attr_accessor :authenticationLevel
|
9
|
+
# attr_accessor :dealType
|
10
|
+
# attr_accessor :forceAuthentication
|
11
|
+
# attr_accessor :needCa
|
12
|
+
# attr_accessor :orderFlag
|
13
|
+
# attr_accessor :signLevel
|
14
|
+
# attr_accessor :sequenceInfo
|
15
|
+
# attr_accessor :
|
16
|
+
[:contractName,:serverCa,:dealType,:file,:authenticationLevel,:dealType,:forceAuthentication,:needCa,:orderFlag,:signLevel,:sequenceInfo, :signatories].each do |at|
|
17
|
+
attr_accessor at
|
18
|
+
end
|
19
|
+
|
20
|
+
def initialize(options)
|
21
|
+
tmp = []
|
22
|
+
options.each do |k, v|
|
23
|
+
if k == :signatories
|
24
|
+
options[:signatories].each do |sign|
|
25
|
+
tmp << Model::Signatory.new(sign).hash_values
|
26
|
+
end
|
27
|
+
self.signatories = "[#{tmp.join()}]"
|
28
|
+
elsif k == :file
|
29
|
+
self.file = Junziqian::Tool::AttacheUtils.new options[:file]
|
30
|
+
else
|
31
|
+
self.send("#{k}=", v) if self.respond_to?(k)
|
32
|
+
end
|
33
|
+
end
|
34
|
+
end
|
35
|
+
|
36
|
+
def version
|
37
|
+
'1.0'
|
38
|
+
end
|
39
|
+
|
40
|
+
def content_type
|
41
|
+
'multipart/form-data'
|
42
|
+
end
|
43
|
+
|
44
|
+
def method
|
45
|
+
'sign.apply.file'
|
46
|
+
end
|
47
|
+
|
48
|
+
def ignores_params
|
49
|
+
[:file]
|
50
|
+
end
|
51
|
+
|
52
|
+
def query_params
|
53
|
+
#{contractName: contractName, serverCa: serverCa, dealType: dealType, file: file}.merge({signatories: @signatories})
|
54
|
+
[:contractName,:serverCa,:dealType,:file,:authenticationLevel,:dealType,:forceAuthentication,:needCa,:orderFlag,:signLevel,:sequenceInfo, :signatories].inject({}) do |hash,item|
|
55
|
+
(hash[item] = self.send(item)) if self.send(item).present?
|
56
|
+
hash
|
57
|
+
end
|
58
|
+
end
|
59
|
+
|
60
|
+
def request
|
61
|
+
Junziqian::Tool::RequestTool.do_post_by_requestObj(self)
|
62
|
+
end
|
63
|
+
|
64
|
+
def demo
|
65
|
+
signatories = [{
|
66
|
+
userType: Junziqian::Cfg::Enum::IDCARD['type'],
|
67
|
+
identityType: Junziqian::Cfg::Enum::IDCARD['code'],
|
68
|
+
fullName: '张三',
|
69
|
+
identityCard: '360732198908110099',
|
70
|
+
mobile: '15123649601',
|
71
|
+
signLevel: Junziqian::Cfg::Enum::GENERAL,
|
72
|
+
noNeedVerify: 0,
|
73
|
+
serverCaAuto: 1,
|
74
|
+
orderNum: 1,
|
75
|
+
chapteJson: '['+ {'page' => 0, 'chaptes' => [{"offsetX" => 0.12, "offsetY" => 0.23},{"offsetX" => 0.45, "offsetY" => 0.67}]}.to_json+']'
|
76
|
+
},{userType: Junziqian::Cfg::Enum::BIZLIC['type'],
|
77
|
+
identityType: Junziqian::Cfg::Enum::BIZLIC['code'],
|
78
|
+
fullName: '测试公司',
|
79
|
+
identityCard: '461313456461316',
|
80
|
+
email: '1244268365@qq.com',
|
81
|
+
orderNum: 2,
|
82
|
+
signLevel: Junziqian::Cfg::Enum::SEAL,
|
83
|
+
serverCaAuto: 1,
|
84
|
+
chapteJson: "["+[{'page' => 1,'chaptes' => [{"offsetX" => 0.31, "offsetY" => 0.72},{"offsetX" => 0.72, "offsetY" => 0.72}]}.to_json, {'page' => 2, 'chaptes' => [{"offsetX" => 0.8, "offsetY" => 0.82}]}.to_json].join()+']'
|
85
|
+
}]
|
86
|
+
demo1 = {
|
87
|
+
file: '/Users/moonless/Documents/demo_contract.pdf',
|
88
|
+
contractName: '合同0001',
|
89
|
+
signatories: signatories,
|
90
|
+
serverCa: 1,
|
91
|
+
dealType: Junziqian::Cfg::Enum::AUTH_SIGN,
|
92
|
+
orderFlag: 1
|
93
|
+
}
|
94
|
+
req = Junziqian::Interface::ApplySignFileRequest.new demo1
|
95
|
+
#=> {"applyNo"=>"APL882159678413475840", "success"=>true}
|
96
|
+
#=> {"applyNo"=>"APL882164292533751808", "success"=>true}
|
97
|
+
end
|
98
|
+
end
|
99
|
+
end
|
100
|
+
end
|
@@ -0,0 +1,33 @@
|
|
1
|
+
module Junziqian
|
2
|
+
module Interface
|
3
|
+
class DetailAnonyLinkRequest < BaseRequest
|
4
|
+
attr_accessor :applyNo
|
5
|
+
|
6
|
+
def initialize apply_no
|
7
|
+
self.applyNo = apply_no
|
8
|
+
end
|
9
|
+
def version
|
10
|
+
'1.0'
|
11
|
+
end
|
12
|
+
|
13
|
+
def method
|
14
|
+
'sign.link.anony.detail'
|
15
|
+
end
|
16
|
+
|
17
|
+
def ingore_signs
|
18
|
+
[]
|
19
|
+
end
|
20
|
+
|
21
|
+
def query_params
|
22
|
+
{applyNo: applyNo}
|
23
|
+
end
|
24
|
+
|
25
|
+
|
26
|
+
|
27
|
+
def request
|
28
|
+
Tool::RequestTool.do_post_by_requestObj(self)
|
29
|
+
# applyNo=APL882159678413475840=> {"link"=> "http://sandbox.junziqian.com/applaySign/toDetailAnony?timestamp=1499160325399&applyNo=APL882159678413475840&sign=a693a313a271b60a53c5c0324f14e7026f89b9f8", "success"=>true}
|
30
|
+
end
|
31
|
+
end
|
32
|
+
end
|
33
|
+
end
|
@@ -0,0 +1,43 @@
|
|
1
|
+
module Junziqian
|
2
|
+
module Interface
|
3
|
+
class FileLinkRequest < BaseRequest
|
4
|
+
attr_accessor :applyNo
|
5
|
+
|
6
|
+
def initialize apply_no
|
7
|
+
self.applyNo = apply_no
|
8
|
+
end
|
9
|
+
def version
|
10
|
+
'1.0'
|
11
|
+
end
|
12
|
+
|
13
|
+
def method
|
14
|
+
'sign.link.file'
|
15
|
+
end
|
16
|
+
|
17
|
+
def ingore_signs
|
18
|
+
[]
|
19
|
+
end
|
20
|
+
|
21
|
+
def query_params
|
22
|
+
{applyNo: applyNo}
|
23
|
+
end
|
24
|
+
|
25
|
+
def file_path
|
26
|
+
Dir.mkdir(ENV['contract_path']) if ENV['contract_path'] && Dir.exist?(ENV['contract_path'])
|
27
|
+
ENV['contract_path'] || '/tmp'
|
28
|
+
end
|
29
|
+
|
30
|
+
|
31
|
+
|
32
|
+
def request
|
33
|
+
result = Tool::RequestTool.do_post_by_requestObj(self)
|
34
|
+
if result['success'] == true
|
35
|
+
link = result['link']
|
36
|
+
system(`curl '#{link}' -o #{file_path}/applyNo#{self.applyNo}.pdf`)
|
37
|
+
else
|
38
|
+
'error'
|
39
|
+
end
|
40
|
+
end
|
41
|
+
end
|
42
|
+
end
|
43
|
+
end
|
@@ -0,0 +1,23 @@
|
|
1
|
+
module Junziqian
|
2
|
+
module Interface
|
3
|
+
class Ping < BaseRequest
|
4
|
+
def version
|
5
|
+
'1.0'
|
6
|
+
end
|
7
|
+
|
8
|
+
def method
|
9
|
+
'ping'
|
10
|
+
end
|
11
|
+
|
12
|
+
def ingore_signs
|
13
|
+
[]
|
14
|
+
end
|
15
|
+
|
16
|
+
|
17
|
+
|
18
|
+
def request
|
19
|
+
Tool::RequestTool.do_post_by_requestObj(self)
|
20
|
+
end
|
21
|
+
end
|
22
|
+
end
|
23
|
+
end
|
@@ -0,0 +1,55 @@
|
|
1
|
+
module Junziqian
|
2
|
+
module Interface
|
3
|
+
class PresFileLink < BaseRequest
|
4
|
+
attr_accessor :applyNo
|
5
|
+
attr_accessor :signatory
|
6
|
+
|
7
|
+
def initialize options
|
8
|
+
self.applyNo = options[:apply_no]
|
9
|
+
self.signatory = Junziqian::Model::Signatory.new(options[:signatory]).hash_values
|
10
|
+
end
|
11
|
+
|
12
|
+
def version
|
13
|
+
'1.0'
|
14
|
+
end
|
15
|
+
|
16
|
+
def method
|
17
|
+
'pres.link.file'
|
18
|
+
end
|
19
|
+
|
20
|
+
def ingore_signs
|
21
|
+
[]
|
22
|
+
end
|
23
|
+
|
24
|
+
def query_params
|
25
|
+
{applyNo: applyNo, signatory: signatory}
|
26
|
+
end
|
27
|
+
|
28
|
+
def file_path
|
29
|
+
Dir.mkdir(ENV['contract_path']) if ENV['contract_path'] && Dir.exist?(ENV['contract_path'])
|
30
|
+
ENV['contract_path'] || '/tmp'
|
31
|
+
end
|
32
|
+
|
33
|
+
|
34
|
+
|
35
|
+
def request
|
36
|
+
result = Tool::RequestTool.do_post_by_requestObj(self)
|
37
|
+
if result['success'] == true
|
38
|
+
link = result['link']
|
39
|
+
system(`curl '#{link}' -o #{file_path}/applyNo#{self.applyNo}.pdf`)
|
40
|
+
else
|
41
|
+
result
|
42
|
+
end
|
43
|
+
end
|
44
|
+
|
45
|
+
def demo
|
46
|
+
hash = {signatory: {userType: Junziqian::Cfg::Enum::IDCARD['type'],
|
47
|
+
identityType: Junziqian::Cfg::Enum::IDCARD['code'],
|
48
|
+
fullName: '张三',
|
49
|
+
identityCard: '360732198908110099'},
|
50
|
+
apply_no: 'APL882159678413475840'}
|
51
|
+
req = Junziqian::Interface::PresFileLink.new(hash)
|
52
|
+
end
|
53
|
+
end
|
54
|
+
end
|
55
|
+
end
|
@@ -0,0 +1,54 @@
|
|
1
|
+
module Junziqian
|
2
|
+
module Interface
|
3
|
+
class SignStatusRequest < BaseRequest
|
4
|
+
attr_accessor :applyNo
|
5
|
+
attr_accessor :signatory
|
6
|
+
|
7
|
+
def initialize options
|
8
|
+
self.applyNo = options[:apply_no]
|
9
|
+
self.signatory = Junziqian::Model::Signatory.new(options[:signatory]).hash_values
|
10
|
+
end
|
11
|
+
|
12
|
+
def version
|
13
|
+
'1.0'
|
14
|
+
end
|
15
|
+
|
16
|
+
def method
|
17
|
+
'sign.status'
|
18
|
+
end
|
19
|
+
|
20
|
+
def ingore_signs
|
21
|
+
[]
|
22
|
+
end
|
23
|
+
|
24
|
+
def query_params
|
25
|
+
{applyNo: applyNo, signatory: signatory}
|
26
|
+
end
|
27
|
+
|
28
|
+
|
29
|
+
|
30
|
+
def request
|
31
|
+
result = Tool::RequestTool.do_post_by_requestObj(self)
|
32
|
+
if result['success'] == true
|
33
|
+
[result['signStatus'], trans_signstatus(result['signStatus'])]
|
34
|
+
else
|
35
|
+
result
|
36
|
+
end
|
37
|
+
end
|
38
|
+
|
39
|
+
def trans_signstatus status_int
|
40
|
+
#1 已签、2 拒签、3 保全
|
41
|
+
{1=>'已签', 2=>'拒签', 3=>'保全'}[status_int]
|
42
|
+
end
|
43
|
+
|
44
|
+
def demo
|
45
|
+
hash = {signatory: {userType: Junziqian::Cfg::Enum::IDCARD['type'],
|
46
|
+
identityType: Junziqian::Cfg::Enum::IDCARD['code'],
|
47
|
+
fullName: '张三',
|
48
|
+
identityCard: '360732198908110099'},
|
49
|
+
apply_no: 'APL882159678413475840'}
|
50
|
+
req = Junziqian::Interface::SignStatusRequest.new(hash)
|
51
|
+
end
|
52
|
+
end
|
53
|
+
end
|
54
|
+
end
|
@@ -0,0 +1,25 @@
|
|
1
|
+
module Junziqian
|
2
|
+
module Model
|
3
|
+
class Signatory
|
4
|
+
[:userType, :fullName, :identityType, :identityCard, :mobile, :email, :address, :authLeve, :authenticationLevel, :authLevel, :authLevelRange, :forceAuthentication, :signLevel, :forceEvidence, :chapteJson, :noNeedEvidence, :orderNum, :insureYear, :noNeedVerify, :serverCaAuto, :readTime].each do |at|
|
5
|
+
attr_accessor at
|
6
|
+
end
|
7
|
+
|
8
|
+
|
9
|
+
def initialize options= {}
|
10
|
+
options.each do |k, v|
|
11
|
+
if self.respond_to?(k)
|
12
|
+
self.send("#{k}=", v)
|
13
|
+
end
|
14
|
+
end
|
15
|
+
end
|
16
|
+
|
17
|
+
def hash_values
|
18
|
+
[:userType, :fullName, :identityType, :identityCard, :mobile, :email, :address, :authLeve, :authenticationLevel, :authLevel, :authLevelRange, :forceAuthentication, :signLevel, :forceEvidence, :chapteJson, :noNeedEvidence, :orderNum, :insureYear, :noNeedVerify, :serverCaAuto, :readTime].inject({}) do |hash, item|
|
19
|
+
hash[item] = self.send(item)
|
20
|
+
hash
|
21
|
+
end.to_json
|
22
|
+
end
|
23
|
+
end
|
24
|
+
end
|
25
|
+
end
|
@@ -0,0 +1,33 @@
|
|
1
|
+
require 'base64'
|
2
|
+
module Junziqian
|
3
|
+
module Tool
|
4
|
+
class AttacheUtils
|
5
|
+
def initialize file_path
|
6
|
+
@file_path = file_path
|
7
|
+
end
|
8
|
+
|
9
|
+
def file_type
|
10
|
+
match_data = @file_path.match(/\.([a-z]+)$/)
|
11
|
+
match_data ? match_data[1] : ''
|
12
|
+
end
|
13
|
+
|
14
|
+
def value
|
15
|
+
@file_path
|
16
|
+
end
|
17
|
+
|
18
|
+
def file_name
|
19
|
+
@file_path.match(/([^\/]+\.([a-z]+))$/)[0]
|
20
|
+
end
|
21
|
+
|
22
|
+
def uploadStr
|
23
|
+
file =File.open(@file_path)
|
24
|
+
b = file.readlines().join('')
|
25
|
+
c = Base64.strict_encode64(file_name) +'@'+ Base64.strict_encode64(b)
|
26
|
+
|
27
|
+
# array('+','/','='),array('-','_','')
|
28
|
+
c.gsub('+', '-').gsub('/','_').gsub('=','')
|
29
|
+
end
|
30
|
+
end
|
31
|
+
end
|
32
|
+
|
33
|
+
end
|
@@ -0,0 +1,43 @@
|
|
1
|
+
require 'digest'
|
2
|
+
require 'uri'
|
3
|
+
module Junziqian
|
4
|
+
module Tool
|
5
|
+
class HttpSignUtils
|
6
|
+
class << self
|
7
|
+
def create_http_url body_params, timestamp = nil
|
8
|
+
timestamp ||= get_millisecond
|
9
|
+
sign=create_http_sign(body_params, timestamp)
|
10
|
+
url='timestamp='+timestamp+'&'; #timestamp必须放在最前面民
|
11
|
+
body_params.each do |k, v|
|
12
|
+
url += k.to_s + URI::escape(v.strip)
|
13
|
+
end
|
14
|
+
url += "sign=#{sign}"
|
15
|
+
end
|
16
|
+
|
17
|
+
def get_millisecond
|
18
|
+
(Time.now.to_f*1000).to_i.to_s
|
19
|
+
end
|
20
|
+
|
21
|
+
def create_http_sign body_params, timestamp = nil
|
22
|
+
timestamp ||= get_millisecond
|
23
|
+
contactStr = []
|
24
|
+
contactStr << get_params(body_params)
|
25
|
+
contactStr << ("timestamp"+timestamp)
|
26
|
+
contactStr << ("appKey"+ Cfg::ClientInfo.app_key)
|
27
|
+
contactStr << ("appSecret"+ Cfg::ClientInfo.app_secret;)
|
28
|
+
Digest::SHA1.hexdigest(contactStr.join(''));
|
29
|
+
end
|
30
|
+
|
31
|
+
def get_params(hash)
|
32
|
+
contactStr=[]
|
33
|
+
if hash.present?
|
34
|
+
hash.sort.map {|array_item|
|
35
|
+
contactStr << [array_item[0], array_item[1].strip]
|
36
|
+
}
|
37
|
+
end
|
38
|
+
contactStr.flatten.join('')
|
39
|
+
end
|
40
|
+
end
|
41
|
+
end
|
42
|
+
end
|
43
|
+
end
|
@@ -0,0 +1,127 @@
|
|
1
|
+
require 'digest'
|
2
|
+
require 'net/http'
|
3
|
+
require 'uri'
|
4
|
+
require 'json'
|
5
|
+
require 'mime/types'
|
6
|
+
|
7
|
+
module Junziqian
|
8
|
+
module Tool
|
9
|
+
class RequestTool
|
10
|
+
CV = '1.1.1'
|
11
|
+
BOUNDARY = '00content0boundary00'
|
12
|
+
class << self
|
13
|
+
def sign(query_params, ignore_params, header_map, ext_info, content_type = 'application/x-www-form-urlencoded; charset=UTF-8')
|
14
|
+
#raise '头参数不能为空' if secret.blank? || header_map.blank?
|
15
|
+
|
16
|
+
contactStr = [Cfg::ClientInfo.app_secret]
|
17
|
+
contactStr << contactValues(query_params, ignore_params, content_type)
|
18
|
+
contactStr << contactValues(header_map)
|
19
|
+
contactStr << contactValues(ext_info)
|
20
|
+
|
21
|
+
# print contactStr.join('')
|
22
|
+
Digest::SHA1.hexdigest(contactStr.join('')).upcase
|
23
|
+
end
|
24
|
+
|
25
|
+
def contactValues(query_params, ignores = [], content_type = 'application/x-www-form-urlencoded; charset=UTF-8')
|
26
|
+
contactStr = []
|
27
|
+
is_multipart = content_type.downcase.match('multipart/form-data') ? true : false
|
28
|
+
unless query_params.empty?
|
29
|
+
req_array = query_params.select {|k, v| !ignores.include?(k)}
|
30
|
+
req_array.sort.each do |array_item|
|
31
|
+
contactStr << array_item[0]
|
32
|
+
if array_item[1]
|
33
|
+
contactStr << (array_item[1].is_a?(Junziqian::Tool::AttacheUtils) ? array_item[1].value : array_item[1].strip)
|
34
|
+
end
|
35
|
+
end
|
36
|
+
end
|
37
|
+
contactStr.join('')
|
38
|
+
end
|
39
|
+
|
40
|
+
def get_heads(method = 'POST', version = '1.0')
|
41
|
+
{"ts" => HttpSignUtils.get_millisecond,
|
42
|
+
"locale" => "zh_CN",
|
43
|
+
"v" => version,
|
44
|
+
"method" => method,
|
45
|
+
"appKey" => Cfg::ClientInfo.app_key}
|
46
|
+
end
|
47
|
+
|
48
|
+
def get_ext_info
|
49
|
+
{'cv' => CV}
|
50
|
+
end
|
51
|
+
|
52
|
+
def encrypt_ext_info ext_hash
|
53
|
+
contactStr = []
|
54
|
+
if ext_hash
|
55
|
+
ext_hash.each do |k, v|
|
56
|
+
contactStr << "#{k}\001#{v}\002"
|
57
|
+
end
|
58
|
+
end
|
59
|
+
string = contactStr.join('')
|
60
|
+
string == '' ? '' : (string[0, string.length-1].to_s)
|
61
|
+
end
|
62
|
+
|
63
|
+
def create_head_hash(head_map, ext_info, sign, content_type="application/x-www-form-urlencoded; charset=UTF-8")
|
64
|
+
hash = {}
|
65
|
+
hash['ext'] = encrypt_ext_info(ext_info)
|
66
|
+
hash['sign'] = sign
|
67
|
+
hash['user-agent'] = 'php'
|
68
|
+
hash['Content-type'] = content_type
|
69
|
+
hash['accept'] = 'text/html, image/gif, image/jpeg, *; q=.2, */*; q=.2'
|
70
|
+
hash['connection'] = 'keep-alive'
|
71
|
+
hash.merge(head_map)
|
72
|
+
end
|
73
|
+
|
74
|
+
def do_post(query_params, ignores_params, head_map, content_type = 'application/x-www-form-urlencoded; charset=UTF-8')
|
75
|
+
sign_value = sign(query_params, ignores_params, head_map, get_ext_info,content_type);
|
76
|
+
uri = URI.parse(Cfg::ClientInfo.services_url)
|
77
|
+
head_hash = create_head_hash(head_map, get_ext_info, sign_value, content_type)
|
78
|
+
content = if content_type.match('multipart/form-data')
|
79
|
+
head_hash = head_hash.merge({"Content-Type"=> "multipart/form-data, boundary=#{BOUNDARY}"})
|
80
|
+
build_form_data(query_params)
|
81
|
+
else
|
82
|
+
URI.encode_www_form query_params
|
83
|
+
end
|
84
|
+
head_hash['Content-Length'] = content.length.to_s
|
85
|
+
http = Net::HTTP.new(uri.host, uri.port)
|
86
|
+
response = http.post(uri.path, content, head_hash)
|
87
|
+
return JSON.parse(response.body)
|
88
|
+
end
|
89
|
+
|
90
|
+
def do_post_by_requestObj( requestObj)
|
91
|
+
# hash = hash.serialize_keys
|
92
|
+
headerMap = get_heads(requestObj.method, requestObj.version)
|
93
|
+
query_params = requestObj.query_params
|
94
|
+
do_post(query_params, requestObj.ignores_params, headerMap, requestObj.content_type)
|
95
|
+
end
|
96
|
+
|
97
|
+
|
98
|
+
def build_form_data(query_params, boundary = BOUNDARY)
|
99
|
+
body = []
|
100
|
+
query_params.each do |k, v|
|
101
|
+
if v.present?
|
102
|
+
body << "--"+ boundary + "\r\n"
|
103
|
+
body << "Content-Disposition: form-data; name=\"#{k}\"\r\n\r\n";
|
104
|
+
if v.is_a?(Junziqian::Tool::AttacheUtils)
|
105
|
+
body << v.uploadStr+"\r\n";
|
106
|
+
else
|
107
|
+
body << "#{v}\r\n";
|
108
|
+
end
|
109
|
+
end
|
110
|
+
end
|
111
|
+
if body.size > 0
|
112
|
+
body << "--"+ boundary + "--\r\n";
|
113
|
+
end
|
114
|
+
body.join('')
|
115
|
+
end
|
116
|
+
|
117
|
+
def create_http_sign body_hash, timestamp
|
118
|
+
array = [contactValues(body_hash)]
|
119
|
+
array << "timestamp#{timestamp}"
|
120
|
+
array << "appKey#{Junziqian::Cfg::ClientInfo.app_key}"
|
121
|
+
array << "appSecret#{Junziqian::Cfg::ClientInfo.app_secret}"
|
122
|
+
Digest::SHA1.hexdigest(array.join(''))
|
123
|
+
end
|
124
|
+
end
|
125
|
+
end
|
126
|
+
end
|
127
|
+
end
|
metadata
ADDED
@@ -0,0 +1,109 @@
|
|
1
|
+
--- !ruby/object:Gem::Specification
|
2
|
+
name: junziqian
|
3
|
+
version: !ruby/object:Gem::Version
|
4
|
+
version: 0.1.1
|
5
|
+
platform: ruby
|
6
|
+
authors:
|
7
|
+
- 方峦
|
8
|
+
autorequire:
|
9
|
+
bindir: exe
|
10
|
+
cert_chain: []
|
11
|
+
date: 2017-07-11 00:00:00.000000000 Z
|
12
|
+
dependencies:
|
13
|
+
- !ruby/object:Gem::Dependency
|
14
|
+
name: bundler
|
15
|
+
requirement: !ruby/object:Gem::Requirement
|
16
|
+
requirements:
|
17
|
+
- - "~>"
|
18
|
+
- !ruby/object:Gem::Version
|
19
|
+
version: '1.14'
|
20
|
+
type: :development
|
21
|
+
prerelease: false
|
22
|
+
version_requirements: !ruby/object:Gem::Requirement
|
23
|
+
requirements:
|
24
|
+
- - "~>"
|
25
|
+
- !ruby/object:Gem::Version
|
26
|
+
version: '1.14'
|
27
|
+
- !ruby/object:Gem::Dependency
|
28
|
+
name: rake
|
29
|
+
requirement: !ruby/object:Gem::Requirement
|
30
|
+
requirements:
|
31
|
+
- - "~>"
|
32
|
+
- !ruby/object:Gem::Version
|
33
|
+
version: '10.0'
|
34
|
+
type: :development
|
35
|
+
prerelease: false
|
36
|
+
version_requirements: !ruby/object:Gem::Requirement
|
37
|
+
requirements:
|
38
|
+
- - "~>"
|
39
|
+
- !ruby/object:Gem::Version
|
40
|
+
version: '10.0'
|
41
|
+
- !ruby/object:Gem::Dependency
|
42
|
+
name: minitest
|
43
|
+
requirement: !ruby/object:Gem::Requirement
|
44
|
+
requirements:
|
45
|
+
- - "~>"
|
46
|
+
- !ruby/object:Gem::Version
|
47
|
+
version: '5.0'
|
48
|
+
type: :development
|
49
|
+
prerelease: false
|
50
|
+
version_requirements: !ruby/object:Gem::Requirement
|
51
|
+
requirements:
|
52
|
+
- - "~>"
|
53
|
+
- !ruby/object:Gem::Version
|
54
|
+
version: '5.0'
|
55
|
+
description: ruby版本的支持君子签,电子签名的gem库
|
56
|
+
email:
|
57
|
+
- moonless@fangluandeMacBook-Pro.local
|
58
|
+
executables: []
|
59
|
+
extensions: []
|
60
|
+
extra_rdoc_files: []
|
61
|
+
files:
|
62
|
+
- ".gitignore"
|
63
|
+
- ".ruby-version"
|
64
|
+
- ".travis.yml"
|
65
|
+
- Gemfile
|
66
|
+
- README.md
|
67
|
+
- Rakefile
|
68
|
+
- bin/console
|
69
|
+
- bin/setup
|
70
|
+
- junziqian.gemspec
|
71
|
+
- lib/junziqian.rb
|
72
|
+
- lib/junziqian/cfg/client_info.rb
|
73
|
+
- lib/junziqian/cfg/enum.rb
|
74
|
+
- lib/junziqian/interface/apply_sign_file_request.rb
|
75
|
+
- lib/junziqian/interface/base_request.rb
|
76
|
+
- lib/junziqian/interface/detail_anony_link_request.rb
|
77
|
+
- lib/junziqian/interface/file_link_request.rb
|
78
|
+
- lib/junziqian/interface/ping.rb
|
79
|
+
- lib/junziqian/interface/pres_file_link.rb
|
80
|
+
- lib/junziqian/interface/sign_status_request.rb
|
81
|
+
- lib/junziqian/model/signatory.rb
|
82
|
+
- lib/junziqian/tool/attache_utils.rb
|
83
|
+
- lib/junziqian/tool/http_sign_utils.rb
|
84
|
+
- lib/junziqian/tool/request_tool.rb
|
85
|
+
- lib/junziqian/version.rb
|
86
|
+
homepage: http://github.com/orichi/junziqian
|
87
|
+
licenses: []
|
88
|
+
metadata: {}
|
89
|
+
post_install_message:
|
90
|
+
rdoc_options: []
|
91
|
+
require_paths:
|
92
|
+
- lib
|
93
|
+
required_ruby_version: !ruby/object:Gem::Requirement
|
94
|
+
requirements:
|
95
|
+
- - ">="
|
96
|
+
- !ruby/object:Gem::Version
|
97
|
+
version: '0'
|
98
|
+
required_rubygems_version: !ruby/object:Gem::Requirement
|
99
|
+
requirements:
|
100
|
+
- - ">="
|
101
|
+
- !ruby/object:Gem::Version
|
102
|
+
version: '0'
|
103
|
+
requirements: []
|
104
|
+
rubyforge_project:
|
105
|
+
rubygems_version: 2.6.10
|
106
|
+
signing_key:
|
107
|
+
specification_version: 4
|
108
|
+
summary: 支持君子签,电子签名
|
109
|
+
test_files: []
|