Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

基于rack重新实现webhooks验证方法 #12

Open
wants to merge 2 commits into
base: master
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
27 changes: 19 additions & 8 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -33,13 +33,30 @@ Pingpp.api_key = "YOUR-KEY"
Pingpp.private_key_path = '/path/to/your_rsa_private_key.pem'
```

### 设置 Ping++ 公钥
公钥请登录 [Ping++ Dashboard](https://dashboard.pingxx.com) 获取
### 验证 Webhooks

#### 设置 Ping++ 公钥

公钥请登录 [Ping++ Dashboard](https://dashboard.pingxx.com) 获取。

此公钥用于webhooks回调时,验证请求对象的正确性。

设置你的 Ping++ 公钥路径

``` ruby
Pingpp.pub_key_path = "/path/to/pingpp_rsa_public_key.pem"
```

#### 验证

支持基于Rack的web框架,如Rails,Sinatra等.
```ruby
Pingpp::Webhook.verify?(request) # 验证回调的请求对象的正确性
# 解析回调内容
JSON.parse(request.raw_post) # Ruby on Rails
JSON.parse(request.body.read) # Sinatra
```

### 支付
``` ruby
Pingpp::Charge.create(
Expand All @@ -54,12 +71,6 @@ Pingpp::Charge.create(
)
```

### 验证 Webhooks
```ruby
Pingpp::Webhook.verify?(request) # 验证回调
JSON.parse(request.raw_post) # 解析回调内容(Ruby on Rails)
```

### 查询
``` ruby
Pingpp::Charge.retrieve("CHARGE_ID")
Expand Down
66 changes: 45 additions & 21 deletions lib/pingpp/webhook.rb
Original file line number Diff line number Diff line change
@@ -1,34 +1,58 @@
module Pingpp
module Webhook
def self.verify?(request, pub_key=Pingpp.pub_key)
if !pub_key
unless pub_key
puts 'Warn: ' + 'No Public key provided. ' +
'Set your Public key using "Pingpp.pub_key_path = <API-KEY-FILE> ' +
'or Pingpp.pub_key = <API-KEY>" ' +
'You can get Public key from the Pingpp website: ' +
'https://dashboard.pingxx.com/settings/development_info '
return false
end

raw_data = nil
if request.respond_to?('raw_post')
raw_data = request.raw_post
elsif request.respond_to?('body')
raw_data = request.body
else
return false
end
# raw_data = nil
# if request.respond_to?('raw_post')
# raw_data = request.raw_post
# elsif request.respond_to?('body')
# raw_data = request.body
# else
# return false
# end

headers = nil
if request.respond_to?('headers')
headers = request.headers
elsif request.respond_to?('header')
headers = request.header
else
return false
end
raw_data = extract_raw_data(request)

# headers = nil
# if request.respond_to?('headers')
# headers = request.headers
# elsif request.respond_to?('header')
# headers = request.header
# else
# return false
# end

headers = extract_headers(request)

formated_headers = Util.format_headers(headers)
return false if !formated_headers.has_key?(:x_pingplusplus_signature)
formatted_headers = Util.format_headers(headers)
return false unless formatted_headers.has_key?(:x_pingplusplus_signature)

signature = formatted_headers[:x_pingplusplus_signature]

signature = formated_headers[:x_pingplusplus_signature]
rsa_public_key = OpenSSL::PKey.read(pub_key)
return rsa_public_key.verify(OpenSSL::Digest::SHA256.new, Base64.decode64(signature), raw_data)
rsa_public_key.verify(OpenSSL::Digest::SHA256.new, Base64.decode64(signature), raw_data)
end

# A dumbed down version extracted from ActionDispatch::Request#raw_post
# see actionpack-4.2.7.1/lib/action_dispatch/http/request.rb#251
def self.extract_raw_data(request)
body = request.env['rack.input']
raw_post_body = body.read(request.content_length.to_i)
body.rewind if body.respond_to?(:rewind)
raw_post_body
end

# see actionpack-4.2.7.1/lib/action_dispatch/http/headers.rb#each
def self.extract_headers(request)
request.env
end
end
end