分享 Rails 开发微信支付的一些总结

greatbody · 2015年10月09日 · 最后由 1c7 回复于 2019年11月30日 · 8446 次阅读

1、使用 gem 包 我使用的是 wx_pay 这个 gem,github:https://github.com/jasl/wx_pay 【建议自己 fork 一下,然后在 gem 里面引用自己的 github 地址】 例如: gem 'wx_pay', :github => 'greatbody/wx_pay' 2、配置信息 参见https://github.com/jasl/wx_pay 其中需要注意的是: WxPay.appid = '微信给的公众号的 id' WxPay.key = '自己设置的 api Key',32 个字符,推荐自己去随机生成 32 个 16 进制数。【这个 key 不可以长了,长了会导致认证失败】 WxPay.mch_id = '微信支付商户号' 3、提交预订单

# required fields
params = {
  body: '商品名',
  out_trade_no: '交易序列号,',
  total_fee: 1,
  spbill_create_ip: '127.0.0.1',
  notify_url: 'http://xxx.xxxx.xxx/static/receive_pay_notify/',
  trade_type: 'JSAPI', # could be "JSAPI", "NATIVE" or "APP",
  openid: session[:openid] # required when trade_type is `JSAPI`
}
@result = WxPay::Service.invoke_unifiedorder(params)
@sign_package = $weixin_client.get_jssign_package(request.url)
if @result.nil?
  render html: "no"
else
  render html: "#{@result.to_s},#{params.to_s}" if @result['return_code']=='FAIL'
  @pay_ticket_param = {
    timeStamp: @sign_package["timestamp"],
    nonceStr: @sign_package["nonceStr"],
    package: "prepay_id=#{@result['prepay_id']}",  #这里一定注意,不仅仅是prepay_id,还需要拼接上“prepay_id=”
    signType: "MD5",
    appId: WxPay.appid,
    key: WxPay.key
  }
  @pay_ticket_param = {
    paySign: WxPay::Sign.generate(@pay_ticket_param)  #然后我们手动进行paySign计算
  }.merge(@pay_ticket_param)
end

4、页面上 js-sdk 的授权部分,参见 weixin_authorize 这个 gem 的说明,其实上面已经获取了授权信息,并且存在了@sign_package中。

wx.config({
  debug: false,
  appId: '<%= @sign_package["appId"] %>',
  url: '<%= @sign_package["url"] %>',
  timestamp: '<%= @sign_package["timestamp"] %>' ,
  nonceStr: '<%= @sign_package["nonceStr"] %>',
  signature: '<%= @sign_package["signature"] %>',
  jsApiList: ['chooseWXPay']
});

wx.ready(function() {
  window.weixin_ready = true;
});

wx.error(function() {
  window.weixin_ready = false;
});

然后,加一个支付函数

function pay() {
  if (window.weixin_ready) {
    wx.chooseWXPay({
      timestamp: <%= @pay_ticket_param[:timeStamp] %>, // 支付签名时间戳,注意微信jssdk中的所有使用timestamp字段均为小写。但最新版的支付后台生成签名使用的timeStamp字段名需大写其中的S字符
      nonceStr: "<%= @pay_ticket_param[:nonceStr] %>", // 支付签名随机串,不长于 32 位
      package: "<%= @pay_ticket_param[:package] %>", //统一支付接口返回的prepay_id参数值,提交格式如:prepay_id=***
      signType: "<%= @pay_ticket_param[:signType] %>", // 签名方式,默认为"SHA1",使用新版支付需传入"MD5"
      paySign: "<%= @pay_ticket_param[:paySign] %>", // 支付签名
      success: function(res) {
        // 支付成功后的回调函数
        alert("支付成功");
      }
    });
  } else {
    alert('wait for authentication!');
  }
}

页面上调用这个支付函数就可以了。

坑点: 1、第三步提交预订单中,out_trade_no 记得每次成功后要改变,最好的就是按照一个规则生成不重复的单号 2、关于授权目录的事情 首先,登陆进入:https://mp.weixin.qq.com 然后,登陆后,点击左侧导航栏的,“微信支付”,然后再点开“开发配置”,在里面寻找“公众号支付->支付授权目录”,设置支付授权目录时一定注意,这个路径就是 routes 里面处理支付页面的那个 get 的 path,例如:http://xx.xxxx.xx/weixin/pay/ 对应我的 routes 是:

namespace :weixin do
  get 'pay' => :pay
end

其实微信支付有很多坑,换设备、换账号登录、接口升级、流水号唯一性; wx_pay 一开始设计还是以单个公众号为主,对于支持多个公众号,就显得有点勉强。

#2 楼 @ruby_sky 惭愧,说好的重构下支持多账号的,拖延症一直进度不快,我努力下...

#3 楼 @jasl 但是我启用它的时候,按照单账号来设计的。所以我自己 fork 了一份代码,就是为了避免主版本升级导致程序挂掉。

#2 楼 @ruby_sky 其实,微信本身就是一个坑。文档不完善,文档到处都是坑。

#5 楼 @greatbody 因为。。。大会结束后 花了半个月补落下公司的工作 然后 英雄无敌 7 接 COD12 接 虚空之遗 现在 Fallout 4 拖延症犯了。。。

请问 openid 是怎么获取的

#7 楼 @liwen_zhang 用户关注的时候就会得到 openid

#7 楼 @liwen_zhang 然后你就将 openid 一直保存到 session 甚至 cookie 中。

#9 楼 @greatbody 谢谢,已经搞明白了

开发步骤几乎跟楼主的一模一样,楼主提到的坑也都没犯,死活没法支付,就提示个{"errMs":"chooseWXPay:fail"}……唉

#12 楼 @greatbody 是啊,已经搞定了,微信的坑……

evedreamer 回复

我最近在做对接微信支付的开发,也是一直遇到{"errMs":"chooseWXPay:fail"},死活不知道是哪里出现问题,请问你是怎么解决的?或者能给我提供一些线索吗?

看了大伙儿的回复,我决定还是自己动手写个 Gem。

成功!赞一个

2019 年 11 月,我给微信支付的"二维码扫码支付"(微信叫这个 NATIVE 支付) 写了篇博客:https://1c7.me/rails-wechat-pay-tutorial/ 需要参考的开发者可以看看

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