分享 支付宝 API 向导 (Ruby 版),以及开源一个支付宝 gem

Rei · 2013年08月02日 · 最后由 uestc_bird 回复于 2017年06月13日 · 28271 次阅读
本帖已被管理员设置为精华贴

最近花了一周时间搞定了 https://writings.io/ 的自助支付功能,做的过程中感觉 Ruby 社区关于支付宝的资源不多,所以写了一篇文章抛砖引玉。

支付宝 API 向导(Ruby 版) http://chloerei.com/2013/08/01/alipay-payment-in-ruby/

同时开源一个支付宝接口的 gem https://github.com/chloerei/alipay

做这个 gem 的原因是发现已有的 gem 不够好:

activemerchant_patch_for_china 依赖 activemerchant,实现得很复杂

ralipay 功能较全,但是代码中有一些不好的地方,比如全局变量太多。

另外还参考了 alipay_dualfun 和 china_pay,觉得包装有些多。

所以我还是自己写了一个 gem,代码更少,没有依赖,可以用于所有 Ruby Web 项目;直接面对支付宝接口,不加过多的包装。

比如,生成担保交易地址只是一个方法

Alipay::Service.create_partner_trade_by_buyer_url(
  :out_trade_no      => 'YOUR_ORDER_ID',
  :subject           => 'YOUR_ORDER_SUBJECCT',
  ...
)

我向之前提到的几个 gem 的作者致敬,因为不参考他们的代码我遇到很多问题都解决不了。

欢迎贡献代码,像即时到帐接口我没有权限访问,测试不了,所以还没写进去。

或者捐助我,让我更积极维护这个 gem https://me.alipay.com/chloerei

再搭一个广告,writings.io 现在可以自助付费了:https://writings.io/billing ,也欢迎继续联系我个人购买:[email protected]

欢迎拿出来共享 即时到帐接口更简单 非常简单的生成一个 url 页面跳转过去即可 商业项目所以没法拿出来代码 仅说流程~

#1 楼 @zj0713001 就是把 service 改成 create_direct_pay_by_user 就行了吧?那我明天加上去。

#2 楼 @Rei 从流程上 没有确认发货的过程~ 然后你说的对 'service' => 'create_direct_pay_by_user'

之前我也准备做一个支付宝付款的事情,然后我看这里:https://b.alipay.com/order/productSet.htm ,发现即时到帐需要执照。 不知道你的 gem,是不是支持担保交易和即时到帐两种情况的?

#4 楼 @JeskTop 现在只有担保交易和双功能接口。

申请不到即时到帐的话,用担保交易就好了,双功能不能控制用户用什么方式支付,还是要处理担保交易一样的流程。

还有,其实 gem 要做的事情不多:生成 url、发货、校验通知,其余都是取决于自己的业务代码。

好东东,支持。

现在登录是有问题吗? 我登录提示服务端错误,但是刷新一下发现登录进去了

china_pay 做了很多封装,本来是想支持多种支付渠道的,比如财付通,快钱什么的。

其实生成跳转的 url 还是相对容易的,比较麻烦的是处理支付宝的异步通知,要校验什么的。

我觉得理想的情况是,支付 gem 应该是个 engine,把这些细节都搞定,大家只要写业务代码就行了,跟 devise 那样。

@Rei 我也仔细看过支付宝的流程,其实前面那个支付提交还是很简单的,当时想用 ruby 搞定也不会太费事;不过那个支付成功之后支付宝回调通知的时候还有一个到支付宝的验证过程,貌似复杂些,而且现有的 gem 中貌似也没有这部分,不知道你做了没有

#10 楼 @donnior 是指这个吗? https://github.com/chloerei/alipay/blob/master/lib/alipay/notify.rb 我看回调和异步消息的参数应该一样的。校验回调先用签名检查,再访问 notify_query 接口检查。

#11 楼 @Rei 是这个,不过我看支付宝自己提供的 Java 版代码中除了验证这个接口检查还根据返回验证了签名

#12 楼 @donnior

它校验的签名是回调参数,不是接口返回值。

我给拆成两个方法了 https://github.com/chloerei/alipay/blob/master/lib/alipay/sign.rb#L13

也许我应该在 Notify.verify? 里面也调用 Sign.verify?

回头有时间了也研究一下,我之前都是用的 gem 也是依赖activemerchant_patch_for_china

已经加上即时到帐,不过我没有测试。

为什么 https://writings.io/ 我没有找到忘记密码功能?

#16 楼 @simlegate 还没空做,要手工帮你重置吗?把帐号告诉我,然后我发新密码到邮箱。

#8 楼 @daqing 你那个多重封装我也看出来了,就是为了未来能多兼容几个业务进去。我也是不太赞同这个做法,理由就是咱们一般不可能有足够的精力打理太多的接口。

所以我那个 Gem,alipay_dualfun 一看名字就知道了,就是个功能单一的 Gem,而且封装上我也比你那个少一层,@Rei 说的简单透明,我很支持。

@Rei 需要请教一个问题:如何确认通知(同步和异步)确实来自于支付宝,而非第三方伪造? 我看支付包文档上说是通过校验 notify_id,不过具体代码如何来写比较合适呢?

#19 楼 @happypeter

先校验签名,然后 GET 一个地址,看返回内容是不是 true

module Alipay
  class Notify
    def self.verify?(params)
      if Sign.verify?(params)
        params = Utils.symbolize_keys(params)
        open("https://mapi.alipay.com/gateway.do?service=notify_verify&partner=#{Alipay.pid}&notify_id=#{CGI.escape params[:notify_id].to_s}").read == 'true'
      else
        false
      end
    end
  end
end

更新,更正了校验地址

#20 楼 @Rei 受教,要的就是这个

#21 楼 @happypeter 奥,我发现这个地址跟文档看的不一样,忘了是哪里抄的。

正确的应该是

"https://mapi.alipay.com/gateway.do?service=notify_verify&partner=#{Alipay.pid}&notify_id=#{CGI.escape params[:notify_id].to_s}"

好文,公司有个同事给我们分享过。。但是我在想为什么没有抽成 gem 分享出来。。。哈哈

#23 楼 @small_fish__ 没有利益吧。我做的时候也想,为什么要帮别的公司写工具包啊,应该是这些公司的责任。后来想到写出来对 Ruby 社区有好处,还是坚持下来了。

果断 mark 下

正要做支付呢!

赞,测试了一下发现 ruby2.0 还没法用。

#30 楼 @rasefon 恩?我用 2.0 啊,发现什么错误了?

#31 楼 @Rei 好象是 require 的问题,我回去给你发错误信息。

#31 楼 @Rei

➜  ~  ruby -v
ruby 2.0.0p247 (2013-06-27 revision 41674) [i686-linux]
➜  ~  rvm list   

rvm rubies

   ruby-1.9.3-p448 [ i686 ]
=* ruby-2.0.0-p247 [ i686 ]

# => - current
# =* - current && default
#  * - default

➜  ~  rvm gemset list

gemsets for ruby-2.0.0-p247 (found in /home/rasefon/.rvm/gems/ruby-2.0.0-p247)
   (default)
   global
=> r2

➜  ~  gem install alipay
Successfully installed alipay-0.0.1
1 gem installed
➜  ~  irb
2.0.0p247 :001 > require 'alipay'
LoadError: cannot load such file -- alipay
    from /home/rasefon/.rvm/rubies/ruby-2.0.0-p247/lib/ruby/site_ruby/2.0.0/rubygems/core_ext/kernel_require.rb:51:in `require'
    from /home/rasefon/.rvm/rubies/ruby-2.0.0-p247/lib/ruby/site_ruby/2.0.0/rubygems/core_ext/kernel_require.rb:51:in `require'
    from (irb):1
    from /home/rasefon/.rvm/rubies/ruby-2.0.0-p247/bin/irb:13:in `<main>'
2.0.0p247 :002 > 

#33 楼 @rasefon 我也看不出什么问题,在我这正常的。

  1. gem list | grep alipay 能看到 alipay 吗?
  2. irb 里面 require 其他 gem 正常吗?
  3. irb 里面执行 puts $LOAD_PATH 看看。

#34 楼 @Rei 有些 gem 也有不能加载的现象比如 win32-process,大部分可以用。 这是我的结果: ➜ ~ gem list | grep alipay alipay (0.0.1) ➜ ~ irb 2.0.0p247 :001 > require 'nokogiri' => true 2.0.0p247 :002 > puts $LOAD_PATH /home/rasefon/.rvm/gems/ruby-2.0.0-p247@r2/gems/mini_portile-0.5.1/lib /home/rasefon/.rvm/gems/ruby-2.0.0-p247@r2/gems/nokogiri-1.6.0/lib /home/rasefon/.rvm/rubies/ruby-2.0.0-p247/lib/ruby/site_ruby/2.0.0 /home/rasefon/.rvm/rubies/ruby-2.0.0-p247/lib/ruby/site_ruby/2.0.0/i686-linux /home/rasefon/.rvm/rubies/ruby-2.0.0-p247/lib/ruby/site_ruby /home/rasefon/.rvm/rubies/ruby-2.0.0-p247/lib/ruby/vendor_ruby/2.0.0 /home/rasefon/.rvm/rubies/ruby-2.0.0-p247/lib/ruby/vendor_ruby/2.0.0/i686-linux /home/rasefon/.rvm/rubies/ruby-2.0.0-p247/lib/ruby/vendor_ruby /home/rasefon/.rvm/rubies/ruby-2.0.0-p247/lib/ruby/2.0.0 /home/rasefon/.rvm/rubies/ruby-2.0.0-p247/lib/ruby/2.0.0/i686-linux => nil 2.0.0p247 :003 > ^C

#35 楼 @rasefon 我也搞不懂了

#35 楼 @rasefon 或者去看看 gem 安装路径下 alipay 的 lib 目录有没有内容

#35 楼 @rasefon

  • which gem
  • which ruby
  • which irb

担保交易的手续费是多少?你给支付宝的

Any way.支持 Rei 同学的分享精神!

你好,我自己在网上下载了支付宝接口,我想先测试一下能不能通过支付宝接口进行简单的付款交易,是不是要注册企业账号,或者说个人账号。可是我看条件说注册个人账号要有自己的已发布网站。我没有个人网站。是不是就不能测试了,就只有注册企业账号来测试这个支付宝交易功能了是吗。

#43 楼 @huangling02 企业号或个人号都行,个人号限制多。需要有线上的网站提交审核。

#44 楼 @Rei 嗯。那如果注册了企业账号,直接用下载的 Demo 就可以测试成功吗。需要把 Demo 发布到外网去吗。也就是上线。你可以发一份 Demo 给我吗。~~(>_<)~~ 我邮箱 [email protected].先谢谢了

#44 楼 @Rei 楼主。能发一份 Demo 给我吗,我下载的官方 Demo,测试不成功。~~(>_<)~~ 提示操作已经取消,系统繁忙。求你了

@Rei ,后台打款到用户支付宝账户,支付宝,有这样的 API 吗?

#47 楼 @robertyu 我没看到有这个 API,如果发现了请告诉我。

@Rei 请问这个 gem 支持手机支付嘛

看了下源码,感觉主要用来生成请求 url 的,另外 GATEWAY_URL 似乎不可配置,比如想改成测试环境 url https://openapi.alipaydev.com/gateway.do请指点 @rei ,谢谢!

#50 楼 @wikimo 这个测试地址不是给 web/wap API 用的,openapi 是另一套 API,不过我没试过能不能用,文档没写。

#51 楼 @rei 下载了海外支付文档,里面有 Alipay testing environment WAP.docx 的文档,提供了测试环境地址账号,生成 service url 的原理是一样的,通过你的 gem 生成的 url,直接贴浏览器可以完成支付,给 a 标签跳转也可以,不过 form action method=get 方式提示“调试错误,请回到请求来源地,重新发起请求” ,错误代码 ILLEGAL_EXTERFACE,但是提供的 php demo 也是创建 form 方式 submit 有些奇怪

#52 楼 @wikimo 不知道 form action metho=get 方式是指什么。应该要把 form 提交到你的服务器,然后服务器返回重定向到支付宝的 url。

#53 楼 @rei 是不是说 form 是在 server 端拼接后然后提交过去的,官方的 php demo 是这样的,在 server 端动态创建 form 然后 submit

#54 楼 @wikimo 你可以看这个项目 https://github.com/chloerei/alipay-demo,用的是担保交易接口,但是流程差不多。

支付宝 API 向导(Ruby 版)这个怎么打不开的?

@rei 问一下,像你最新做的 selfstore,允许用户卖东西,是用的什么接口?是不是用担保交易接口也可以搞定?还是得用支付宝的平台商接口?谢谢

#58 楼 @grantbb 我先收款,然后每周再人工转给卖家。平台商接口一直没明白什么回事。

#59 楼 @rei 谢谢了,有空研究研究平台商接口。

happypeter 个人可以申请支付宝即时收款接口啦 提及了此话题。 06月17日 17:36

gem 支持 ruby1.8.7 么?

移动支付接口 (mobile.securitypay.pay) 的 ist of arguments zip 压缩包实效了,能给一个吗

github 上没写对 ruby 版本的支持?还是都支持?

uestc_bird 回复

2.1 2.2 2.3

Rei 回复

OK 我这边的 ruby 版本是 1.9.3😭

uestc_bird 回复

你可以试试,印象中没使用 1.9 不支持的语法。不过 1.9 官方都不支持了,字符串处理有问题,建议升级。

Rei 回复

OK,我试试 1.9.3 行不,可以的话,我告知你 thanks

69 楼 已删除
Rei 回复

不好意思 这么久才来回复 ruby 1.9.3 版本的可以正常使用,到目前为止,没有出现任何问题

需要 登录 后方可回复, 如果你还没有账号请 注册新账号