alipay 0.0.1

Sign up to get free protection for your applications and to get access to all the features.
checksums.yaml ADDED
@@ -0,0 +1,7 @@
1
+ ---
2
+ SHA1:
3
+ metadata.gz: 76821d020f3247b02202d5253dae2df6a8ce1288
4
+ data.tar.gz: db6abc47a810d5390ddce5e2506c09bc2b11e0b4
5
+ SHA512:
6
+ metadata.gz: c6774216b77ea292b1169dfd3ca0ac9475e76881a66fb7ac824eb7cffcf2528215637114b527989b2d0a56187b8152c182e3fdaeeb4594f3920bccba2874b0a6
7
+ data.tar.gz: 42f41ead9ce83eaca5c30bd4cc477b3119ec4323190077b1387a729c2ad5e5c218ca542000c5bbeb9c1c816bcac969ec9b8d3610053b58a0f9b8cfd2ce4c1f8d
data/.gitignore ADDED
@@ -0,0 +1,17 @@
1
+ *.gem
2
+ *.rbc
3
+ .bundle
4
+ .config
5
+ .yardoc
6
+ Gemfile.lock
7
+ InstalledFiles
8
+ _yardoc
9
+ coverage
10
+ doc/
11
+ lib/bundler/man
12
+ pkg
13
+ rdoc
14
+ spec/reports
15
+ test/tmp
16
+ test/version_tmp
17
+ tmp
data/Gemfile ADDED
@@ -0,0 +1,4 @@
1
+ source 'https://rubygems.org'
2
+
3
+ # Specify your gem's dependencies in alipay.gemspec
4
+ gemspec
data/LICENSE.txt ADDED
@@ -0,0 +1,22 @@
1
+ Copyright (c) 2013 Rei
2
+
3
+ MIT License
4
+
5
+ Permission is hereby granted, free of charge, to any person obtaining
6
+ a copy of this software and associated documentation files (the
7
+ "Software"), to deal in the Software without restriction, including
8
+ without limitation the rights to use, copy, modify, merge, publish,
9
+ distribute, sublicense, and/or sell copies of the Software, and to
10
+ permit persons to whom the Software is furnished to do so, subject to
11
+ the following conditions:
12
+
13
+ The above copyright notice and this permission notice shall be
14
+ included in all copies or substantial portions of the Software.
15
+
16
+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
17
+ EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
18
+ MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
19
+ NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
20
+ LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
21
+ OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
22
+ WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
data/README.md ADDED
@@ -0,0 +1,112 @@
1
+ # Alipay
2
+
3
+ A simple alipay ruby gem, without unnecessary magic or wraper, it's directly facing how alipay api works.
4
+
5
+ It contain this API:
6
+
7
+ * Generate payment url
8
+ * Send goods
9
+ * Verify when receive alipay notify
10
+
11
+ Please read alipay official document first: https://b.alipay.com/order/techService.htm
12
+
13
+ ## Installation
14
+
15
+ Add this line to your application's Gemfile:
16
+
17
+ ```ruby
18
+ gem 'alipay', :github => 'chloerei/alipay'
19
+ ```
20
+
21
+ And then execute:
22
+
23
+ ```sh
24
+ $ bundle
25
+ ```
26
+
27
+ ## Usage
28
+
29
+ ### Init
30
+
31
+ ```ruby
32
+ Alipay.pid = 'YOUR_PID'
33
+ Alipay.key = 'YOUR_KEY'
34
+ Alipay.seller_email = 'YOUR_SELLER_EMAIL'
35
+ ```
36
+
37
+ ### Generate payment url
38
+
39
+ ```ruby
40
+ options = {
41
+ :out_trade_no => 'YOUR_ORDER_ID', # 20130801000001
42
+ :subject => 'YOUR_ORDER_SUBJECCT', # Writings.io Base Account x 12
43
+ :logistics_type => 'DIRECT',
44
+ :logistics_fee => '0',
45
+ :logistics_payment => 'SELLER_PAY',
46
+ :price => '10.00',
47
+ :quantity => 12,
48
+ :discount => '20.00'
49
+ :return_url => 'YOUR_ORDER_RETURN_URL', # https://writings.io/orders/20130801000001
50
+ :notify_url => 'YOUR_ORDER_NOTIFY_URL' # https://writings.io/orders/20130801000001/alipay_notify
51
+ }
52
+
53
+ Alipay::Service.create_partner_trade_by_buyer_url(options)
54
+ # => 'https://mapi.alipay.com/gateway.do?out_trade_no=...'
55
+ ```
56
+
57
+ You can redirect user to this payment url, and user will see a payment page for his/her order.
58
+
59
+ Current support three payment type:
60
+
61
+ Alipay::Service#create_partner_trade_by_buyer_url # 担保交易
62
+ Alipay::Service#trade_create_by_buyer_url # 标准双接口
63
+ Alipay::Service#create_direct_pay_by_user_url # 即时到帐
64
+
65
+ ### Send goods
66
+
67
+ ```ruby
68
+ options = {
69
+ :trade_no => 'trade_no_id',
70
+ :logistics_name => 'writings.io',
71
+ :transport_type => 'DIRECT'
72
+ }
73
+
74
+ Alipay::Service.send_goods_confirm_by_platform(options)
75
+ # => '<!xml version="1.0" encoding="utf-8"?><alipay><is_success>T</is_success></alipay>'
76
+ ```
77
+
78
+ ### Verify when receive alipay notify
79
+
80
+ ```ruby
81
+ # exxample in rails
82
+ # The notify url MUST be set when generate payment url
83
+ def alipay_notify
84
+ notify_params = params.except(*request.path_parameters.keys) # except :controller_name, :action_name, :host
85
+ if Alipay::Notify.verify?(notify_params)
86
+ # valid notify, code your business logic.
87
+ render :text => 'success'
88
+ else
89
+ render :text => 'error'
90
+ end
91
+ end
92
+ ```
93
+
94
+ ## Contributing
95
+
96
+ Bug report or pull request is welcome.
97
+
98
+ ### Make a pull request
99
+
100
+ 1. Fork it
101
+ 2. Create your feature branch (`git checkout -b my-new-feature`)
102
+ 3. Commit your changes (`git commit -am 'Add some feature'`)
103
+ 4. Push to the branch (`git push origin my-new-feature`)
104
+ 5. Create new Pull Request
105
+
106
+ Please write unit test with your code if necessary.
107
+
108
+ ## Donate
109
+
110
+ Donate to maintainer let him make this gem better.
111
+
112
+ Alipay donate link: https://me.alipay.com/chloerei .
data/Rakefile ADDED
@@ -0,0 +1,9 @@
1
+ require "bundler/gem_tasks"
2
+ require "rake/testtask"
3
+
4
+ Rake::TestTask.new do |t|
5
+ t.libs << "test"
6
+ t.test_files = FileList['test/**/*_test.rb']
7
+ end
8
+
9
+ task :default => :test
data/alipay.gemspec ADDED
@@ -0,0 +1,24 @@
1
+ # coding: utf-8
2
+ lib = File.expand_path('../lib', __FILE__)
3
+ $LOAD_PATH.unshift(lib) unless $LOAD_PATH.include?(lib)
4
+ require 'alipay/version'
5
+
6
+ Gem::Specification.new do |spec|
7
+ spec.name = "alipay"
8
+ spec.version = Alipay::VERSION
9
+ spec.authors = ["Rei"]
10
+ spec.email = ["chloerei@gmail.com"]
11
+ spec.description = %q{An unofficial simple alipay gem}
12
+ spec.summary = %q{An unofficial simple alipay gem}
13
+ spec.homepage = ""
14
+ spec.license = "MIT"
15
+
16
+ spec.files = `git ls-files`.split($/)
17
+ spec.executables = spec.files.grep(%r{^bin/}) { |f| File.basename(f) }
18
+ spec.test_files = spec.files.grep(%r{^(test|spec|features)/})
19
+ spec.require_paths = ["lib"]
20
+
21
+ spec.add_development_dependency "bundler", "~> 1.3"
22
+ spec.add_development_dependency "rake"
23
+ spec.add_development_dependency "fakeweb"
24
+ end
data/lib/alipay.rb ADDED
@@ -0,0 +1,13 @@
1
+ require "alipay/version"
2
+ require 'alipay/utils'
3
+ require 'alipay/sign'
4
+ require 'alipay/service'
5
+ require 'alipay/notify'
6
+
7
+ module Alipay
8
+ class << self
9
+ attr_accessor :pid
10
+ attr_accessor :key
11
+ attr_accessor :seller_email
12
+ end
13
+ end
@@ -0,0 +1,12 @@
1
+ module Alipay
2
+ class Notify
3
+ def self.verify?(params)
4
+ if Sign.verify?(params)
5
+ params = Utils.symbolize_keys(params)
6
+ open("https://mapi.alipay.com/gateway.do?service=notify_verify&partner=#{Alipay.pid}&notify_id=#{CGI.escape params[:notify_id].to_s}").read == 'true'
7
+ else
8
+ false
9
+ end
10
+ end
11
+ end
12
+ end
@@ -0,0 +1,89 @@
1
+ require 'cgi'
2
+ require 'open-uri'
3
+
4
+ module Alipay
5
+ module Service
6
+ GATEWAY_URL = 'https://mapi.alipay.com/gateway.do'
7
+
8
+ CREATE_PARTNER_TRADE_BY_BUYER_REQUIRED_OPTIONS = %w( service partner _input_charset out_trade_no subject payment_type logistics_type logistics_fee logistics_payment seller_email price quantity )
9
+ # alipayescow
10
+ def self.create_partner_trade_by_buyer_url(options)
11
+ options = {
12
+ :service => 'create_partner_trade_by_buyer',
13
+ :_input_charset => 'utf-8',
14
+ :partner => Alipay.pid,
15
+ :seller_email => Alipay.seller_email,
16
+ :payment_type => '1'
17
+ }.merge(Utils.symbolize_keys(options))
18
+
19
+ check_required_options(options, TRADE_CREATE_BY_BUYER_REQUIRED_OPTIONS)
20
+
21
+ "#{GATEWAY_URL}?#{query_string(options)}"
22
+ end
23
+
24
+ TRADE_CREATE_BY_BUYER_REQUIRED_OPTIONS = %w( service partner _input_charset out_trade_no subject payment_type logistics_type logistics_fee logistics_payment seller_email price quantity )
25
+ # alipaydualfun
26
+ def self.trade_create_by_buyer_url(options = {})
27
+ options = {
28
+ :service => 'trade_create_by_buyer',
29
+ :_input_charset => 'utf-8',
30
+ :partner => Alipay.pid,
31
+ :seller_email => Alipay.seller_email,
32
+ :payment_type => '1'
33
+ }.merge(Utils.symbolize_keys(options))
34
+
35
+ check_required_options(options, TRADE_CREATE_BY_BUYER_REQUIRED_OPTIONS)
36
+
37
+ "#{GATEWAY_URL}?#{query_string(options)}"
38
+ end
39
+
40
+ CREATE_DIRECT_PAY_BY_USER_REQUIRED_OPTIONS = %w( service partner _input_charset out_trade_no subject payment_type seller_email )
41
+ # direct
42
+ def self.create_direct_pay_by_user_url(options)
43
+ options = {
44
+ :service => 'create_direct_pay_by_user',
45
+ :_input_charset => 'utf-8',
46
+ :partner => Alipay.pid,
47
+ :seller_email => Alipay.seller_email,
48
+ :payment_type => '1'
49
+ }.merge(Utils.symbolize_keys(options))
50
+
51
+ check_required_options(options, CREATE_DIRECT_PAY_BY_USER_REQUIRED_OPTIONS)
52
+
53
+ if options[:total_fee].nil? and (options[:price].nil? || options[:quantity].nil?)
54
+ warn("Ailpay Warn: total_fee or (price && quantiry) must have one")
55
+ end
56
+
57
+ "#{GATEWAY_URL}?#{query_string(options)}"
58
+ end
59
+
60
+ SEND_GOODS_CONFIRM_BY_PLATFORM_REQUIRED_OPTIONS = %w( service partner _input_charset trade_no logistics_name )
61
+ def self.send_goods_confirm_by_platform(options)
62
+ options = {
63
+ :service => 'send_goods_confirm_by_platform',
64
+ :partner => Alipay.pid,
65
+ :_input_charset => 'utf-8'
66
+ }.merge(Utils.symbolize_keys(options))
67
+
68
+ check_required_options(options, SEND_GOODS_CONFIRM_BY_PLATFORM_REQUIRED_OPTIONS)
69
+
70
+ if options[:transport_type].nil? and options[:create_transport_type].nil?
71
+ warn("Ailpay Warn: transport_type or create_transport_type must have one")
72
+ end
73
+
74
+ open("#{GATEWAY_URL}?#{query_string(options)}").read
75
+ end
76
+
77
+ def self.query_string(options)
78
+ options.merge(:sign_type => 'MD5', :sign => Alipay::Sign.generate(options)).map do |key, value|
79
+ "#{CGI.escape(key.to_s)}=#{CGI.escape(value.to_s)}"
80
+ end.join('&')
81
+ end
82
+
83
+ def self.check_required_options(options, names)
84
+ names.each do |name|
85
+ warn("Ailpay Warn: missing required option: #{name}") unless options.has_key?(name.to_sym)
86
+ end
87
+ end
88
+ end
89
+ end
@@ -0,0 +1,21 @@
1
+ require 'digest/md5'
2
+
3
+ module Alipay
4
+ module Sign
5
+ def self.generate(params)
6
+ query = params.sort.map do |key, value|
7
+ "#{key}=#{value}"
8
+ end.join('&')
9
+
10
+ Digest::MD5.hexdigest("#{query}#{Alipay.key}")
11
+ end
12
+
13
+ def self.verify?(params)
14
+ params = Utils.symbolize_keys(params)
15
+ params.delete(:sign_type)
16
+ sign = params.delete(:sign)
17
+
18
+ generate(params) == sign
19
+ end
20
+ end
21
+ end
@@ -0,0 +1,11 @@
1
+ module Alipay
2
+ module Utils
3
+ def self.symbolize_keys(hash)
4
+ new_hash = {}
5
+ hash.each do |key, value|
6
+ new_hash[(key.to_sym rescue key) || key] = value
7
+ end
8
+ new_hash
9
+ end
10
+ end
11
+ end
@@ -0,0 +1,3 @@
1
+ module Alipay
2
+ VERSION = "0.0.1"
3
+ end
@@ -0,0 +1,25 @@
1
+ require 'test_helper'
2
+
3
+ class Alipay::NotifyTest < Test::Unit::TestCase
4
+ def setup
5
+ @options = {
6
+ :notify_id => '1234'
7
+ }
8
+ @sign_options = @options.merge(:sign_type => 'MD5', :sign => Alipay::Sign.generate(@options))
9
+ end
10
+
11
+ def test_unsign_notify
12
+ FakeWeb.register_uri(:get, "https://mapi.alipay.com/gateway.do?service=notify_verify&partner=#{Alipay.pid}&notify_id=1234", :body => "true")
13
+ assert !Alipay::Notify.verify?(@options)
14
+ end
15
+
16
+ def test_verify_notify_when_true
17
+ FakeWeb.register_uri(:get, "https://mapi.alipay.com/gateway.do?service=notify_verify&partner=#{Alipay.pid}&notify_id=1234", :body => "true")
18
+ assert Alipay::Notify.verify?(@sign_options)
19
+ end
20
+
21
+ def test_verify_notify_when_false
22
+ FakeWeb.register_uri(:get, "https://mapi.alipay.com/gateway.do?service=notify_verify&partner=#{Alipay.pid}&notify_id=1234", :body => "false")
23
+ assert !Alipay::Notify.verify?(@sign_options)
24
+ end
25
+ end
@@ -0,0 +1,60 @@
1
+ require 'test_helper'
2
+
3
+ class Alipay::ServiceTest < Test::Unit::TestCase
4
+ def test_generate_create_partner_trade_by_buyer_url
5
+ options = {
6
+ :out_trade_no => '1',
7
+ :subject => 'test',
8
+ :logistics_type => 'POST',
9
+ :logistics_fee => '0',
10
+ :logistics_payment => 'SELLER_PAY',
11
+ :price => '0.01',
12
+ :quantity => 1
13
+ }
14
+ assert_not_nil Alipay::Service.create_partner_trade_by_buyer_url(options)
15
+ end
16
+
17
+ def test_generate_trade_create_by_buyer_url
18
+ options = {
19
+ :out_trade_no => '1',
20
+ :subject => 'test',
21
+ :logistics_type => 'POST',
22
+ :logistics_fee => '0',
23
+ :logistics_payment => 'SELLER_PAY',
24
+ :price => '0.01',
25
+ :quantity => 1
26
+ }
27
+ assert_not_nil Alipay::Service.trade_create_by_buyer_url(options)
28
+ end
29
+
30
+ def test_generate_create_direct_pay_by_user_url
31
+ options = {
32
+ :out_trade_no => '1',
33
+ :subject => 'test',
34
+ :price => '0.01',
35
+ :quantity => 1
36
+ }
37
+ assert_not_nil Alipay::Service.create_direct_pay_by_user_url(options)
38
+ end
39
+
40
+
41
+ def test_should_send_goods_confirm_by_platform
42
+ body = <<-EOF
43
+ <?xml version="1.0" encoding="utf-8"?>
44
+ <alipay>
45
+ <is_success>T</is_success>
46
+ </alipay>
47
+ EOF
48
+ FakeWeb.register_uri(
49
+ :get,
50
+ %r|https://mapi\.alipay\.com/gateway\.do.*|,
51
+ :body => body
52
+ )
53
+
54
+ assert_equal body, Alipay::Service.send_goods_confirm_by_platform(
55
+ :trade_no => 'trade_no_id',
56
+ :logistics_name => 'writings.io',
57
+ :transport_type => 'POST'
58
+ )
59
+ end
60
+ end
@@ -0,0 +1,23 @@
1
+ require 'test_helper'
2
+
3
+ class Alipay::SignTest < Test::Unit::TestCase
4
+ def setup
5
+ @params = {
6
+ :service => 'test',
7
+ :partner => '123'
8
+ }
9
+ @sign = Digest::MD5.hexdigest("partner=123&service=test#{Alipay.key}")
10
+ end
11
+
12
+ def test_generate_sign
13
+ assert_equal @sign, Alipay::Sign.generate(@params)
14
+ end
15
+
16
+ def test_verify_sign
17
+ assert Alipay::Sign.verify?(@params.merge(:sign => @sign))
18
+ end
19
+
20
+ def test_verify_sign_when_fails
21
+ assert !Alipay::Sign.verify?(@params.merge(:danger => 'danger', :sign => @sign))
22
+ end
23
+ end
@@ -0,0 +1,8 @@
1
+ require 'test_helper'
2
+
3
+ class Alipay::UtilsTest < Test::Unit::TestCase
4
+ def test_symbolize_keys
5
+ hash = { 'a' => 1, :b => 2 }
6
+ assert_equal({ :a => 1, :b => 2 }.sort, Alipay::Utils.symbolize_keys(hash).sort)
7
+ end
8
+ end
@@ -0,0 +1,7 @@
1
+ require 'test/unit'
2
+ require 'alipay'
3
+ require 'fakeweb'
4
+
5
+ Alipay.pid = 'pid'
6
+ Alipay.key = 'key'
7
+ Alipay.seller_email = 'chloerei@gmail.com'
metadata ADDED
@@ -0,0 +1,108 @@
1
+ --- !ruby/object:Gem::Specification
2
+ name: alipay
3
+ version: !ruby/object:Gem::Version
4
+ version: 0.0.1
5
+ platform: ruby
6
+ authors:
7
+ - Rei
8
+ autorequire:
9
+ bindir: bin
10
+ cert_chain: []
11
+ date: 2013-08-02 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.3'
20
+ type: :development
21
+ prerelease: false
22
+ version_requirements: !ruby/object:Gem::Requirement
23
+ requirements:
24
+ - - ~>
25
+ - !ruby/object:Gem::Version
26
+ version: '1.3'
27
+ - !ruby/object:Gem::Dependency
28
+ name: rake
29
+ requirement: !ruby/object:Gem::Requirement
30
+ requirements:
31
+ - - '>='
32
+ - !ruby/object:Gem::Version
33
+ version: '0'
34
+ type: :development
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: fakeweb
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: An unofficial simple alipay gem
56
+ email:
57
+ - chloerei@gmail.com
58
+ executables: []
59
+ extensions: []
60
+ extra_rdoc_files: []
61
+ files:
62
+ - .gitignore
63
+ - Gemfile
64
+ - LICENSE.txt
65
+ - README.md
66
+ - Rakefile
67
+ - alipay.gemspec
68
+ - lib/alipay.rb
69
+ - lib/alipay/notify.rb
70
+ - lib/alipay/service.rb
71
+ - lib/alipay/sign.rb
72
+ - lib/alipay/utils.rb
73
+ - lib/alipay/version.rb
74
+ - test/alipay/notify_test.rb
75
+ - test/alipay/service_test.rb
76
+ - test/alipay/sign_test.rb
77
+ - test/alipay/utils_test.rb
78
+ - test/test_helper.rb
79
+ homepage: ''
80
+ licenses:
81
+ - MIT
82
+ metadata: {}
83
+ post_install_message:
84
+ rdoc_options: []
85
+ require_paths:
86
+ - lib
87
+ required_ruby_version: !ruby/object:Gem::Requirement
88
+ requirements:
89
+ - - '>='
90
+ - !ruby/object:Gem::Version
91
+ version: '0'
92
+ required_rubygems_version: !ruby/object:Gem::Requirement
93
+ requirements:
94
+ - - '>='
95
+ - !ruby/object:Gem::Version
96
+ version: '0'
97
+ requirements: []
98
+ rubyforge_project:
99
+ rubygems_version: 2.0.3
100
+ signing_key:
101
+ specification_version: 4
102
+ summary: An unofficial simple alipay gem
103
+ test_files:
104
+ - test/alipay/notify_test.rb
105
+ - test/alipay/service_test.rb
106
+ - test/alipay/sign_test.rb
107
+ - test/alipay/utils_test.rb
108
+ - test/test_helper.rb