junziqian 0.1.1
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/.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: []
|