jw_alipay 1.0.4

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 ADDED
@@ -0,0 +1,15 @@
1
+ ---
2
+ !binary "U0hBMQ==":
3
+ metadata.gz: !binary |-
4
+ NjA0NzY3OGJhOThkY2VhZThiZTEyMGQ4MTA1MWIxY2YyNWNlMzYzOA==
5
+ data.tar.gz: !binary |-
6
+ MmE3ZTI2ZTk0ZTEyOTllMDU0ODE5ODYwZTM3ZTc2MDFhNWQzZmFmZg==
7
+ !binary "U0hBNTEy":
8
+ metadata.gz: !binary |-
9
+ YTk4ZDA3YTg4NDMwNmJhMzk4YWNiM2FkZDk0MDBjNzQ2YzdjNWZlYmQ2NzBk
10
+ OGY3MDY4MGY2NGU4OWQ0N2U1YjBlNWUwNTU0YTUxNzQ0MjM3ZTljOWE5OGJh
11
+ MDA4MzA0N2E3Y2I4OTFjOGM1ZDUwMmNmZmRiOWNlN2Y0YjRhOWE=
12
+ data.tar.gz: !binary |-
13
+ YTI3ZjhlYzUyODgzYTNiMWIzYmU2OTM3OGQyZmE3MTYzZjNiYWM4NzJkYTBl
14
+ OTNkYzUzN2QwZWJkYTNiOTYzMjg2ZGU3ZDNkMmE3NGM2NzJhNDRjOTViYzMz
15
+ Yzc2YjA0NGVkODhkNDdmOTYyMTM3NmMzMzc0MzZhZTRlYTQ3Zjk=
data/MIT-LICENSE ADDED
@@ -0,0 +1,20 @@
1
+ Copyright 2013 YOURNAME
2
+
3
+ Permission is hereby granted, free of charge, to any person obtaining
4
+ a copy of this software and associated documentation files (the
5
+ "Software"), to deal in the Software without restriction, including
6
+ without limitation the rights to use, copy, modify, merge, publish,
7
+ distribute, sublicense, and/or sell copies of the Software, and to
8
+ permit persons to whom the Software is furnished to do so, subject to
9
+ the following conditions:
10
+
11
+ The above copyright notice and this permission notice shall be
12
+ included in all copies or substantial portions of the Software.
13
+
14
+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
15
+ EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
16
+ MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
17
+ NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
18
+ LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
19
+ OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
20
+ WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
data/README.rdoc ADDED
@@ -0,0 +1,70 @@
1
+ = JwAlipay
2
+
3
+ install
4
+
5
+ gem 'jw_alipay'
6
+ bundle install
7
+
8
+ or
9
+
10
+ gem install 'jw_alipay'
11
+
12
+ doc
13
+ https://b.alipay.com/order/productDetail.htm?productId=2012120700377308
14
+
15
+ config(config/alipay.yml)
16
+ development:
17
+ # alipay pid http://help.alipay.com/support/help_detail.htm?help_id=243726&sh=Y&tab=null&info_type=9
18
+ partner: '***'
19
+ # alipay key http://help.alipay.com/support/help_detail.htm?help_id=243726&sh=Y&tab=null&info_type=9
20
+ key: ***
21
+ # alipay account
22
+ email: ***
23
+
24
+ test:
25
+ partner: '***'
26
+ key: ***
27
+ email: ***
28
+
29
+ production:
30
+ partner: '***'
31
+ key: ***
32
+ email: ***
33
+
34
+ routes
35
+ get "pay/index"
36
+ get "pay/pay_call_back"
37
+ post "pay/pay_notify"
38
+
39
+ controller
40
+ # encoding: utf-8
41
+ class PayController < ApplicationController
42
+ include JwAlipay::WapHelper
43
+
44
+ def index
45
+ redirect_to_wap_alipay_gateway(
46
+ :subject => "pay",
47
+ :out_trade_no => '1234567890', :total => 0.01,
48
+ :call_back_url => 'http://domain/pay/pay_call_back',
49
+ :notify_url => 'http://domain/pay/pay_notify',
50
+ :merchant_url => 'http://domain'
51
+ ) do |token|
52
+ puts token
53
+ end
54
+ end
55
+
56
+ # call_back_url http://help.alipay.com/support/help_detail.htm?help_id=243126&sh=Y&tab=null&info_type=9
57
+ def pay_call_back
58
+ call_back do |data|
59
+ puts data.inspect
60
+ end
61
+ end
62
+
63
+ # notify_url http://help.alipay.com/support/help_detail.htm?help_id=243126&sh=Y&tab=null&info_type=9
64
+ def pay_notify
65
+ notify do |data|
66
+ puts data.inspect
67
+ end
68
+ render :text => 'success'
69
+ end
70
+ end
data/Rakefile ADDED
@@ -0,0 +1,40 @@
1
+ #!/usr/bin/env rake
2
+ begin
3
+ require 'bundler/setup'
4
+ rescue LoadError
5
+ puts 'You must `gem install bundler` and `bundle install` to run rake tasks'
6
+ end
7
+ begin
8
+ require 'rdoc/task'
9
+ rescue LoadError
10
+ require 'rdoc/rdoc'
11
+ require 'rake/rdoctask'
12
+ RDoc::Task = Rake::RDocTask
13
+ end
14
+
15
+ RDoc::Task.new(:rdoc) do |rdoc|
16
+ rdoc.rdoc_dir = 'rdoc'
17
+ rdoc.title = 'JwAlipay'
18
+ rdoc.options << '--line-numbers'
19
+ rdoc.rdoc_files.include('README.rdoc')
20
+ rdoc.rdoc_files.include('lib/**/*.rb')
21
+ end
22
+
23
+ APP_RAKEFILE = File.expand_path("../test/dummy/Rakefile", __FILE__)
24
+ load 'rails/tasks/engine.rake'
25
+
26
+
27
+
28
+ Bundler::GemHelper.install_tasks
29
+
30
+ require 'rake/testtask'
31
+
32
+ Rake::TestTask.new(:test) do |t|
33
+ t.libs << 'lib'
34
+ t.libs << 'test'
35
+ t.pattern = 'test/**/*_test.rb'
36
+ t.verbose = false
37
+ end
38
+
39
+
40
+ task :default => :test
@@ -0,0 +1,15 @@
1
+ // This is a manifest file that'll be compiled into application.js, which will include all the files
2
+ // listed below.
3
+ //
4
+ // Any JavaScript/Coffee file within this directory, lib/assets/javascripts, vendor/assets/javascripts,
5
+ // or vendor/assets/javascripts of plugins, if any, can be referenced here using a relative path.
6
+ //
7
+ // It's not advisable to add code directly here, but if you do, it'll appear at the bottom of the
8
+ // the compiled file.
9
+ //
10
+ // WARNING: THE FIRST BLANK LINE MARKS THE END OF WHAT'S TO BE PROCESSED, ANY BLANK LINE SHOULD
11
+ // GO AFTER THE REQUIRES BELOW.
12
+ //
13
+ //= require jquery
14
+ //= require jquery_ujs
15
+ //= require_tree .
@@ -0,0 +1,13 @@
1
+ /*
2
+ * This is a manifest file that'll be compiled into application.css, which will include all the files
3
+ * listed below.
4
+ *
5
+ * Any CSS and SCSS file within this directory, lib/assets/stylesheets, vendor/assets/stylesheets,
6
+ * or vendor/assets/stylesheets of plugins, if any, can be referenced here using a relative path.
7
+ *
8
+ * You're free to add application-wide styles to this file and they'll appear at the top of the
9
+ * compiled file, but it's generally better to create a new file per style scope.
10
+ *
11
+ *= require_self
12
+ *= require_tree .
13
+ */
@@ -0,0 +1,4 @@
1
+ module JwAlipay
2
+ class ApplicationController < ActionController::Base
3
+ end
4
+ end
@@ -0,0 +1,78 @@
1
+ # encoding: utf-8
2
+
3
+ require 'rest-client'
4
+ module JwAlipay
5
+ module WapHelper
6
+ def redirect_to_wap_alipay_gateway(options = {})
7
+ helper = JwAlipay::Helper.new(:xml_root => :auth_and_execute_req)
8
+ token = get_token(options).tap do |token|
9
+ yield token if block_given?
10
+ end
11
+ helper.add_xml_fields(:request_token => token)
12
+ helper.add_fields(
13
+ :service => "alipay.wap.auth.authAndExecute", :sec_id => "MD5", :v => "2.0",
14
+ :req_data => CGI.escape(helper.xml_string), :format => "xml"
15
+ )
16
+
17
+ redirect_to "http://wappaygw.alipay.com/service/rest.htm?#{helper.query_string}"
18
+ end
19
+
20
+ def get_token(options = {})
21
+ helper = JwAlipay::Helper.new(:xml_root => :direct_trade_create_req)
22
+ helper.add_xml_fields(
23
+ :subject => options[:subject],
24
+ :out_trade_no => options[:out_trade_no],
25
+ :total_fee => options[:total],
26
+ :seller_account_name => JwAlipay::EMAIL,
27
+ :call_back_url => options[:call_back_url],
28
+ :notify_url => options[:notify_url],
29
+ :out_user => options[:out_user],
30
+ :merchant_url => options[:merchant_url],
31
+ :pay_expire => options[:pay_expire]
32
+ )
33
+ helper.add_fields(
34
+ :service => "alipay.wap.trade.create.direct", :sec_id => "MD5", :v => "2.0",
35
+ :req_data => helper.xml_string, :req_id => JwAlipay.seq, :format => "xml"
36
+ )
37
+
38
+ res_string = RestClient.post("http://wappaygw.alipay.com/service/rest.htm", helper.query_string)
39
+ res = JwAlipay::Response.new(
40
+ res_string,
41
+ :data_name => :res_data,
42
+ :data_root => :direct_trade_create_res,
43
+ :error_name => :res_error,
44
+ :error_root => :err
45
+ )
46
+
47
+ raise res.error[:detail] if res.error
48
+ res.data[:request_token]
49
+ end
50
+
51
+ def call_back
52
+ logger.info "支付宝call_back,request string:#{request.query_string}"
53
+ res = JwAlipay::Response.new(request.query_string)
54
+ if res.fields.try{ |x| x[:result] } == 'success'
55
+ logger.info "订单[#{res.fields.try{ |x| x[:out_trade_no] }}]支付成功,调用call_back"
56
+ yield res.fields
57
+ else
58
+ logger.error "订单[#{res.data.try{ |x| x[:out_trade_no] }}]支付出现问题,#{res.error.try{ |x| x[:detail] }}"
59
+ end
60
+ end
61
+
62
+ def notify
63
+ logger.info "支付宝notify,request string:#{env['rack.request.form_vars']}"
64
+ res = JwAlipay::Response.new(
65
+ env['rack.request.form_vars'],
66
+ :sort => [:service, :v, :sec_id, :notify_data],
67
+ :data_name => :notify_data,
68
+ :data_root => :notify
69
+ )
70
+ if ['TRADE_SUCCESS', 'TRADE_PENDING', 'TRADE_FINISHED'].include? res.data.try{ |x| x[:trade_status] }
71
+ logger.info "订单[#{res.data.try{ |x| x[:out_trade_no] }}]支付成功,调用notify"
72
+ yield res.data
73
+ else
74
+ logger.error "订单[#{res.data.try{ |x| x[:out_trade_no] }}]支付出现问题,status:#{res.data.try{ |x| x[:trade_status] }},detail:#{res.error.try{ |x| x[:detail] }}"
75
+ end
76
+ end
77
+ end
78
+ end
@@ -0,0 +1,4 @@
1
+ module JwAlipay
2
+ module ApplicationHelper
3
+ end
4
+ end
@@ -0,0 +1,14 @@
1
+ <!DOCTYPE html>
2
+ <html>
3
+ <head>
4
+ <title>JwAlipay</title>
5
+ <%= stylesheet_link_tag "jw_alipay/application", :media => "all" %>
6
+ <%= javascript_include_tag "jw_alipay/application" %>
7
+ <%= csrf_meta_tags %>
8
+ </head>
9
+ <body>
10
+
11
+ <%= yield %>
12
+
13
+ </body>
14
+ </html>
data/config/routes.rb ADDED
@@ -0,0 +1,2 @@
1
+ JwAlipay::Engine.routes.draw do
2
+ end
@@ -0,0 +1,16 @@
1
+ module JwAlipay
2
+ class Engine < ::Rails::Engine
3
+ isolate_namespace JwAlipay
4
+
5
+ initializer "load_configs" do |app|
6
+ config_file = Rails.root.join("config/alipay.yml")
7
+ if config_file.file?
8
+ configs = YAML.load_file(config_file)[Rails.env]
9
+
10
+ JwAlipay::PARTNER = configs["partner"]
11
+ JwAlipay::KEY = configs["key"]
12
+ JwAlipay::EMAIL = configs["email"]
13
+ end
14
+ end
15
+ end
16
+ end
@@ -0,0 +1,45 @@
1
+ module JwAlipay
2
+ class Helper
3
+ include Sign
4
+
5
+ attr_reader :fields, :datum, :xml_root
6
+
7
+ def initialize(options = {})
8
+ @fields = {}
9
+ @datum = {}
10
+ @xml_root = options[:xml_root]
11
+ add_field('partner', PARTNER)
12
+ add_field('_input_charset', 'utf-8')
13
+ end
14
+
15
+ def add_field(name, value)
16
+ return if name.blank? || value.blank?
17
+ self.fields[name.to_s] = value.to_s
18
+ end
19
+
20
+ def add_fields(params)
21
+ (params || {}).each do |k, v|
22
+ add_field(k, v)
23
+ end
24
+ end
25
+
26
+ def add_xml_field(name, value)
27
+ self.datum[name.to_s] = value.to_s
28
+ end
29
+
30
+ def add_xml_fields(params)
31
+ (params || {}).each do |k, v|
32
+ add_xml_field(k, v)
33
+ end
34
+ end
35
+
36
+ def xml_string
37
+ xml = self.datum.to_xml(:skip_instruct => true, :root => self.xml_root, :skip_types => true)
38
+ xml.gsub("-", "_").gsub("\n", "").gsub(" ", "")
39
+ end
40
+
41
+ def query_string
42
+ sign(self.fields)
43
+ end
44
+ end
45
+ end
@@ -0,0 +1,27 @@
1
+ module JwAlipay
2
+ class Response
3
+ include Sign
4
+
5
+ attr_reader :fields, :data, :error
6
+
7
+ def initialize(res, options = {})
8
+ fields = Hash[res.split('&').map{ |f| f.split('=') }].symbolize_keys
9
+ sign, sort = fields[:sign], options[:sort].nil? ? true : options[:sort]
10
+ if sign and verify_sign(fields, sort)
11
+ data = fields[options[:data_name]]
12
+ @fields = fields
13
+ @data = data ? parse_xml_data(data, options[:data_root]) : nil
14
+ elsif sign
15
+ @error = {:msg => :sign_error, :detail => 'sign error'}
16
+ else
17
+ err = fields[options[:error_name]]
18
+ @error = err ? parse_xml_data(err, options[:error_root]) : nil
19
+ end
20
+ end
21
+
22
+ def parse_xml_data(xml, root = nil)
23
+ res = Hash.from_xml(CGI.unescape(xml)).symbolize_keys
24
+ (root ? res[root] : res).symbolize_keys
25
+ end
26
+ end
27
+ end
@@ -0,0 +1,51 @@
1
+ require 'digest/md5'
2
+ require 'cgi'
3
+
4
+ module JwAlipay
5
+ # TODO 暂时只支持MD5方式,RSA后续添加
6
+ module Sign
7
+ def verify_sign(params, sort = true, sign_type = nil)
8
+ sign, sign_type = params.delete(:sign), params.delete(:sign_type) || sign_type || 'MD5'
9
+ _md5_sign(params, sort) == sign.downcase
10
+ end
11
+
12
+ def sign(params, sort = true)
13
+ sign_type, sign = "MD5", _md5_sign(params, sort)
14
+ _query_string(params.merge(:sign => sign))
15
+ end
16
+
17
+ def _md5_sign(params, sort = true)
18
+ Digest::MD5.hexdigest(_sign_string(params, sort) + KEY)
19
+ end
20
+
21
+ def _sign_string(params, sort)
22
+ params = _sort_params(params, sort)
23
+ params.stringify_keys.collect do |s|
24
+ unless s[0] == :notify_id
25
+ "#{s[0]}=#{CGI.unescape(s[1])}"
26
+ else
27
+ "#{s[0]}=#{s[1]}"
28
+ end
29
+ end.join("&")
30
+ end
31
+
32
+ def _query_string(params)
33
+ params.collect{ |k, v| "#{k}=#{v}" }.join("&")
34
+ end
35
+
36
+ # 排序
37
+ # sort true 排序
38
+ # sort false 不排序
39
+ # sort Array 按数组顺序排序
40
+ def _sort_params(params, sort)
41
+ case
42
+ when sort.is_a?(Array)
43
+ then Hash[sort.map{ |key| [key, params[key]] }]
44
+ when true
45
+ then Hash[params.sort]
46
+ else
47
+ params
48
+ end
49
+ end
50
+ end
51
+ end
@@ -0,0 +1,3 @@
1
+ module JwAlipay
2
+ VERSION = "1.0.4"
3
+ end
data/lib/jw_alipay.rb ADDED
@@ -0,0 +1,13 @@
1
+ require "jw_alipay/engine"
2
+
3
+ module JwAlipay
4
+ autoload :Helper, 'jw_alipay/helper'
5
+ autoload :Response, 'jw_alipay/response'
6
+ autoload :Sign, 'jw_alipay/sign'
7
+
8
+ class << self
9
+ def seq
10
+ ("%10.6f" % Time.now.to_f).to_s.gsub('.', '')
11
+ end
12
+ end
13
+ end
@@ -0,0 +1,4 @@
1
+ # desc "Explaining what the task does"
2
+ # task :jw_alipay do
3
+ # # Task goes here
4
+ # end
metadata ADDED
@@ -0,0 +1,102 @@
1
+ --- !ruby/object:Gem::Specification
2
+ name: jw_alipay
3
+ version: !ruby/object:Gem::Version
4
+ version: 1.0.4
5
+ platform: ruby
6
+ authors:
7
+ - fz
8
+ autorequire:
9
+ bindir: bin
10
+ cert_chain: []
11
+ date: 2013-09-12 00:00:00.000000000 Z
12
+ dependencies:
13
+ - !ruby/object:Gem::Dependency
14
+ name: rails
15
+ requirement: !ruby/object:Gem::Requirement
16
+ requirements:
17
+ - - ~>
18
+ - !ruby/object:Gem::Version
19
+ version: 3.2.8
20
+ type: :runtime
21
+ prerelease: false
22
+ version_requirements: !ruby/object:Gem::Requirement
23
+ requirements:
24
+ - - ~>
25
+ - !ruby/object:Gem::Version
26
+ version: 3.2.8
27
+ - !ruby/object:Gem::Dependency
28
+ name: rest-client
29
+ requirement: !ruby/object:Gem::Requirement
30
+ requirements:
31
+ - - ! '>='
32
+ - !ruby/object:Gem::Version
33
+ version: '0'
34
+ type: :runtime
35
+ prerelease: false
36
+ version_requirements: !ruby/object:Gem::Requirement
37
+ requirements:
38
+ - - ! '>='
39
+ - !ruby/object:Gem::Version
40
+ version: '0'
41
+ - !ruby/object:Gem::Dependency
42
+ name: sqlite3
43
+ requirement: !ruby/object:Gem::Requirement
44
+ requirements:
45
+ - - ! '>='
46
+ - !ruby/object:Gem::Version
47
+ version: '0'
48
+ type: :development
49
+ prerelease: false
50
+ version_requirements: !ruby/object:Gem::Requirement
51
+ requirements:
52
+ - - ! '>='
53
+ - !ruby/object:Gem::Version
54
+ version: '0'
55
+ description: A gem for alipay, contains mobile payment
56
+ email:
57
+ - zhu.fang@joowing.com
58
+ executables: []
59
+ extensions: []
60
+ extra_rdoc_files: []
61
+ files:
62
+ - app/helpers/jw_alipay/application_helper.rb
63
+ - app/controllers/jw_alipay/wap_helper.rb
64
+ - app/controllers/jw_alipay/application_controller.rb
65
+ - app/assets/stylesheets/jw_alipay/application.css
66
+ - app/assets/javascripts/jw_alipay/application.js
67
+ - app/views/layouts/jw_alipay/application.html.erb
68
+ - config/routes.rb
69
+ - lib/jw_alipay.rb
70
+ - lib/tasks/jw_alipay_tasks.rake
71
+ - lib/jw_alipay/engine.rb
72
+ - lib/jw_alipay/version.rb
73
+ - lib/jw_alipay/helper.rb
74
+ - lib/jw_alipay/response.rb
75
+ - lib/jw_alipay/sign.rb
76
+ - MIT-LICENSE
77
+ - Rakefile
78
+ - README.rdoc
79
+ homepage: https://github.com/fangzhu19880123/jw_alipay
80
+ licenses: []
81
+ metadata: {}
82
+ post_install_message:
83
+ rdoc_options: []
84
+ require_paths:
85
+ - lib
86
+ required_ruby_version: !ruby/object:Gem::Requirement
87
+ requirements:
88
+ - - ! '>='
89
+ - !ruby/object:Gem::Version
90
+ version: '0'
91
+ required_rubygems_version: !ruby/object:Gem::Requirement
92
+ requirements:
93
+ - - ! '>='
94
+ - !ruby/object:Gem::Version
95
+ version: '0'
96
+ requirements: []
97
+ rubyforge_project:
98
+ rubygems_version: 2.0.7
99
+ signing_key:
100
+ specification_version: 4
101
+ summary: A gem for alipay
102
+ test_files: []