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

Rei · 发布于 2013年8月02日 · 最后由 gaolei14 回复于 2016年8月03日 · 19561 次阅读
1
本帖已被设为精华帖!

最近花了一周时间搞定了 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 ,也欢迎继续联系我个人购买:chloerei@gmail.com 。

共收到 61 条回复
3753
zj0713001 · #1 · 2013年8月02日

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

1
Rei · #2 · 2013年8月02日

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

3753
zj0713001 · #3 · 2013年8月02日

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

1164
jesktop · #4 · 2013年8月02日

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

1
Rei · #5 · 2013年8月02日

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

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

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

681
sevk · #6 · 2013年8月02日

好东东,支持。

395
fresh_fish · #7 · 2013年8月02日

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

101
daqing · #8 · 2013年8月02日

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

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

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

96
sailingyang · #9 · 2013年8月02日

非常感谢

96
donnior · #10 · 2013年8月02日

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

1
Rei · #11 · 2013年8月02日

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

96
donnior · #12 · 2013年8月02日

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

1
Rei · #13 · 2013年8月02日

#12楼 @donnior

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

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

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

4755
martin91 · #14 · 2013年8月02日

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

1
Rei · #15 · 2013年8月02日

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

3672
simlegate · #16 · 2013年8月02日

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

1
Rei · #17 · 2013年8月02日

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

96
happypeter · #18 · 2013年8月02日

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

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

96
happypeter · #19 · 2013年8月02日

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

1
Rei · #20 · 2013年8月02日 1 个赞

#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

更新,更正了校验地址

96
happypeter · #21 · 2013年8月02日

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

1
Rei · #22 · 2013年8月02日

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

正确的应该是

"https://mapi.alipay.com/gateway.do?service=notify_verify&partner=#{Alipay.pid}&notify_id=#{CGI.escape params[:notify_id].to_s}"
2973
small_fish__ · #23 · 2013年8月02日

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

1
Rei · #24 · 2013年8月02日 3 个赞

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

4584
imlcl · #25 · 2013年8月02日

果断mark下

1107
jasl · #26 · 2013年8月02日

正要做支付呢!

3672
simlegate · #27 · 2013年8月03日

#17楼 @Rei simlegate@163.com

1
Rei · #28 · 2013年8月03日

#27楼 @simlegate 已发送

96
happypeter · #29 · 2013年8月03日

#22楼 @Rei 多谢

2466
rasefon · #30 · 2013年8月05日

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

1
Rei · #31 · 2013年8月05日

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

2466
rasefon · #32 · 2013年8月05日

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

2466
rasefon · #33 · 2013年8月05日

#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 > 
1
Rei · #34 · 2013年8月05日

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

  1. gem list | grep alipay 能看到 alipay 吗?
  2. irb 里面 require 其他 gem 正常吗?
  3. irb 里面执行 puts $LOAD_PATH 看看。
2466
rasefon · #35 · 2013年8月05日

#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

1
Rei · #36 · 2013年8月05日

#35楼 @rasefon 我也搞不懂了

1
Rei · #37 · 2013年8月05日

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

8
hooopo · #38 · 2013年8月05日

#35楼 @rasefon

  • which gem
  • which ruby
  • which irb
600
huihen · #39 · 2013年8月07日

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

1
Rei · #40 · 2013年8月08日
6727
haohan · #41 · 2013年9月18日

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

449
victor · #42 · 2014年1月23日

👍

12240
huangling02 · #43 · 2014年3月25日

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

1
Rei · #44 · 2014年3月28日

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

12240
huangling02 · #45 · 2014年3月31日

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

12240
huangling02 · #46 · 2014年4月17日

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

910
robertyu · #47 · 2014年12月08日

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

1
Rei · #48 · 2014年12月08日

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

1516
luffycn · #49 · 2014年12月25日

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

341
wikimo · #50 · 2015年5月16日

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

1
Rei · #51 · 2015年5月16日

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

341
wikimo · #52 · 2015年5月16日

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

1
Rei · #53 · 2015年5月16日

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

341
wikimo · #54 · 2015年5月16日

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

1
Rei · #55 · 2015年5月16日

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

96
osbron · #56 · 2015年8月25日

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

1
Rei · #57 · 2015年8月25日
4594
grantbb · #58 · 2015年9月23日

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

1
Rei · #59 · 2015年9月23日

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

4594
grantbb · #60 · 2015年9月28日

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

32 happypeter 个人可以申请支付宝即时收款接口啦 中提及了此贴 6月17日 17:36
96
gaolei14 · #62 · 2016年8月03日

gem 支持ruby1.8.7 么?

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