diff --git a/README.md b/README.md index 91a1c40..2c237ae 100644 --- a/README.md +++ b/README.md @@ -4,9 +4,9 @@ A simple alipay ruby gem, without unnecessary magic or wraper, it's directly fac It contain this API: -* Generate payment url +* Generate payment url (web, wap) * Send goods -* Verify notify +* Verify notify (web, wap, app) Please read alipay official document first: https://b.alipay.com/order/techService.htm . @@ -40,7 +40,7 @@ Alipay.key = 'YOUR_KEY' Alipay.seller_email = 'YOUR_SELLER_EMAIL' ``` -### Generate payment url +### Generate payment url for web ```ruby options = { @@ -125,7 +125,7 @@ Notify Url Demo: http://git.io/pst4Tw ```ruby # Example in rails, -# both notify url MUST be set when generate payment url +# notify url MUST be set when generate payment url def alipay_web_notify # except :controller_name, :action_name, :host, etc. @@ -152,6 +152,18 @@ def alipay_wap_notify render :text => 'error' end end + +def alipay_app_notify + # except :controller_name, :action_name, :host, etc. + notify_params = params.except(*request.path_parameters.keys) + + if Alipay::Notify::App.verify?(notify_params) + # valid notify, code your business logic. + render :text => 'success' + else + render :text => 'error' + end +end ``` ## Contributing diff --git a/lib/alipay/notify.rb b/lib/alipay/notify.rb index 6dcf230..f87d9b2 100644 --- a/lib/alipay/notify.rb +++ b/lib/alipay/notify.rb @@ -9,6 +9,13 @@ def self.verify?(params) end end + module App + def self.verify?(params) + params = Utils.stringify_keys(params) + Sign::App.verify?(params) && Notify.verify_notify_id?(params['notify_id']) + end + end + def self.verify?(params) params = Utils.stringify_keys(params) Sign.verify?(params) && verify_notify_id?(params['notify_id']) diff --git a/lib/alipay/sign.rb b/lib/alipay/sign.rb index e669298..f489eab 100644 --- a/lib/alipay/sign.rb +++ b/lib/alipay/sign.rb @@ -1,4 +1,6 @@ require 'digest/md5' +require 'openssl' +require 'base64' module Alipay module Sign @@ -31,5 +33,28 @@ def self.verify?(params) params['sign'] == Digest::MD5.hexdigest("#{query}#{Alipay.key}") end end + + module App + # Alipay public key + PEM = "-----BEGIN PUBLIC KEY-----\n" \ + "MIGfMA0GCSqGSIb3DQEBAQUAA4GNADCBiQKBgQCnxj/9qwVfgoUh/y2W89L6BkRA\n" \ + "FljhNhgPdyPuBV64bfQNN1PjbCzkIM6qRdKBoLPXmKKMiFYnkd6rAoprih3/PrQE\n" \ + "B/VsW8OoM8fxn67UDYuyBTqA23MML9q1+ilIZwBC2AQ2UBVOrFXfFl75p6/B5Ksi\n" \ + "NG9zpgmLCUYuLkxpLQIDAQAB\n" \ + "-----END PUBLIC KEY-----" + + def self.verify?(params) + params = Utils.stringify_keys(params) + + pkey = OpenSSL::PKey::RSA.new(PEM) + digest = OpenSSL::Digest::SHA1.new + + params.delete('sign_type') + sign = params.delete('sign') + to_sign = params.sort.map { |item| item.join('=') }.join('&') + + pkey.verify(digest, Base64.decode64(sign), to_sign) + end + end end end diff --git a/lib/alipay/utils.rb b/lib/alipay/utils.rb index 7220ceb..0c86e58 100644 --- a/lib/alipay/utils.rb +++ b/lib/alipay/utils.rb @@ -11,8 +11,9 @@ def self.stringify_keys(hash) # 退款批次号,支付宝通过此批次号来防止重复退款操作,所以此号生成后最好直接保存至数据库,不要在显示页面的时候生成 # 共 24 位(8 位当前日期 + 9 位纳秒 + 1 位随机数) def self.generate_batch_no - time = Time.now - time.strftime('%Y%m%d%H%M%S') + time.nsec.to_s + Random.new.rand(1..9).to_s + t = Time.now + batch_no = t.strftime('%Y%m%d%H%M%S') + t.nsec.to_s + batch_no.ljust(24, Random.new.rand(1..9).to_s) end end end