[教程第1篇] Ruby on Rails 微信支付
大概花30分钟
这篇文章写什么?
这是一篇教程,教 Ruby on Rails 开发者在 20~40 分钟内搞定微信支付
写于2019年11月29号
目标读者
Ruby on Rails 开发者
说明
本文教电脑端扫二维码支付,微信叫这个 "NATIVE 支付"
其他方式的教程 (App, 小程序, 微信内网页端等)
以后如果有条件就写,现在没有。
二维码支付适合电脑端网站,如下图:
我们用模式二
举几个扫码支付的例子
先演示一下最终结果
本次的 demo 部署后,首页如下图:
这个网址你就不要访问了,继续往下看演示就行。
这篇文章写完了我会把这个例子下线的
点击"新建订单"。会看到如下画面,可以直接扫码支付1分钱
如果没支付就直接关掉了页面。
想重新支付,可以在首页找到订单,点击"去支付"
付款后会变成"已支付"
本文技术栈+用到的工具
- Ruby on Rails 6
- Heroku (用于部署)
- 一个已备案的域名
在微信商户后台设置"回调地址"时,域名必须备案过.
在开始写代码之前 需要准备什么
- 一个公司(这样才能申请微信支付)
- 申请微信支付
- 一个已备案的域名(用于支付后的回调)
如果微信支付申请好了,你应该有如下4样信息,开发需要这4样信息:
- appid
- appsecret
- mch_id
- key
具体含义请看下方微信的文档:
https://pay.weixin.qq.com/wiki/doc/api/app/app.php?chapter=3_1
你也应该收到如下这封邮件:
接下来我详细讲解如何获取
- appid
- appsecret
- mch_id
- key
appid 和 appsecret 是成对的,
可以把 appid 想成是账号, appsecret 想成是密码.
既可以是公众号的appid+appsecret,可以是小程序的appid+appsecret,
实测没有区别,两个都可以用。因为在"商户平台"绑定了这两个 appid。
https://pay.weixin.qq.com/static/pay_setting/appid_protocol.shtml
1. 公众号的 appid 和 appsecret 如何获取:
登录公众平台 -> 基本配置 -> "公众号开发信息"
AppID 示例: wxdxxx9xxxd402bxxx
AppSecret 示例: eeexxx0e3dc3a0xxx3ede1xxxe4eaxxx
大概长这样, 为了保密把一些信息用 xxx 替换掉了.
但是长度是这样没错
可以确认一下这个公众号和商户号绑定了没有,如下图:
顺便一说这是"服务号"
2. 小程序的 appid 和 appsecret 如何获取:
登录小程序平台后 -> 开发 -> 开发设置
3. mch_id 如何获取:
上面那封绿色邮件里,有写"微信支付商户号",直接复制即可。
示例: 14942618xx
商户平台里也可以找到这个商户号。
4. key 如何获取:
商户平台 -> 账户中心 -> API 安全 -> 设置 API 密钥。
自己设置一个32位的 key,前面的 mch_id, appid 都是直接复制粘贴,这个是要自己设置。
如果4样信息都收集好了,看起来如下:
AppID: wxdxxx9xxxd402bxxx
AppSecret: eeexxx0e3dc3a0xxx3ede1xxxe4eaxxx
mch_id: 149xx71xxx
key: fff444GS444kiHrNqxxxBcF6bZkkkxxx
我们使用"统一下单"接口
https://pay.weixin.qq.com/wiki/doc/api/native.php?chapter=9_1
来实现二维码扫码支付
文档内容就不过一遍了,简单来说就是:
- 用 XML 格式,带上必要信息,签个名,发到指定 url。
- 微信会返回各种数据,其中包括 code_url。我们用二维码显示这个 code_url 让用户扫码支付就可以了。
以下开始弄代码
分2个部分
第一部分。先不讲原理,直接告诉你 appid, key, mch_id 填哪里,然后部署。先把代码跑起来看到效果
第二部分。讲原理。
第一部分
这里是代码
https://github.com/1c7/demo_ruby_on_rails_wechat_pay
我们要做的操作比直接 git clone 稍微复杂一点,如下:
- 在 Github 上新建一个私有库 (注意是私有) (2019年现在在 Github 弄私有库是免费的了)
- 把代码复制一份 (git clone)
- 把代码推到刚新建的私有库
命令如下
[新建私有库]
# 复制代码到本地
git clone [email protected]:1c7/demo_ruby_on_rails_wechat_pay.git
# 改名 git remote 的地址
git remote rename origin upstream
# 设置新地址
git remote add origin [你的私有库链接, 如 [email protected]:[用户名]/[仓库名].git]
# 把代码推到这个新地址
git push origin master
这么做的理由是,我们希望 Github 上有一份私有代码(只有你能访问)。
需要代码在 Github 上,是因为待会要用 Heroku 部署。
需要代码私有,是因为待会会填写 appid, key, mch_id 等秘密信息,需要保密。
直接 fork 是没法转成私有代码的。所以做这样一个操作。
接下来我们填入配置信息,也就是前面说的 key, appid, mch_id
往 config/initializers/wx_pay.rb 里面填入必须信息
同样,也往 app/controllers/home_controller.rb 里面填入必要信息
代码只需要改这两处就可以了,很简单。
你可能发现了,这里只用上了 key, appid, mch_id,没有用上 appsecret。
这次二维码付款其实不需要 appsecret。
之所以前面还是拿了,是因为 appid 和 appsecret 是一对的。
以后如果你需要获取 access_token 就方便一点,不需要又打开公众号/小程序把这个 appsecret 拿一份。省点事。
当然,实际项目中可以抽到一个配置文件里。不把同样的东西写在2个地方。
demo 为了方便,就不搞太多抽象。
接下来讲如何部署:
我用的是 Heroku。
理由:
- 免费(仅针对小规模应用)
- Github 自动触发部署,方便
虽然 Heroku 需要翻墙访问,但因为是 demo,不用面向客户,不用担心这个问题
如果你不想用 Heroku 也可以,下面的部分可以跳过。
你可以自行部署到任意地方,阿里云,UCloud,腾讯云,Digital Ocean, Linode 等等。
目的是线上可访问,同时有一个已备案域名指向它。具体用什么工具不重要。
Heroku 操作步骤:登录后,在面板中选择右上角 new app
App name 名字你可以随便写一个,demo-for-wechat-pay 之类的,一眼认出来是什么就行了
Deployment method 部署方法选择 Github
然后选择你刚新建那个私有库
输入名字搜索到之后,选择 connect
然后点击两个黑色按钮。
一个是自动部署。
一个是选择部署分支。
这就可以了
你还需要一个 Heroku cli 把 db:migrate 跑一下。
heroku run rake db:migrate -a [App name]
现在来配置"已备案域名指向 Heroku"
在 app 面板里选择 Settings
向下滚动找到 Domain.
点击右边的 "Add domain"
我这里配置的是 heroku.[已备案域名]
配了个子域名。
接下来去域名的 DNS 服务商(我这里用的是阿里云)
(找到域名,点击"解析")
配置 CNAME。
记录值前面 heroku 有给,复制粘贴一下就行。
部署就此完成。
现在可以通过一个已备案的域名。访问到 Heroku 上的应用。
heroku.[你的域名].cn
(请把 [你的域名] 换成你的域名)
最后一步:配置支付回调地址
这一步的意义:用户支付后,微信会通过"支付回调地址"告知我们(发一个 POST 请求,带上必要的信息)
这样我们就可以把用户的订单从"未支付"变成"已支付"状态
(当然,变更订单状态之前,要做签名校验,确保的确是微信发来的请求)
商户平台 -> 产品中心 -> 开发配置
这里填写刚刚配置的域名。比如我需要填 heroku.[域名].cn
(请替换掉[域名]为你的域名)
可以测试了!
现在访问 heroku.[域名].cn
你看的画面应该和以下类似,只不过没有那么多订单就是了。
你可以点击"新建订单",然后"返回首页"。
应该会看到刚刚新建的订单,点击"去支付"
会显示二维码。
二维码扫码是要支付1分钱。支付完之后,那一分钱可以到你自己的商户平台里查看。
第一部分就讲完了。你有了一个实际可支付的例子。
第二部分:讲代码
这次用了2个 gem(可以打开 Gemfile 查看)
wx_pay 和 rest-client
wx_pay 是用来验证回调签名。
rest-client 用来调用"统一下单"接口。
来看一下路由,其实就4条。
- 单个订单页
- 首页
- 下单页
- 接受微信回调通知
二维码支付的核心代码在 home controller
app/controllers/home_controller.rb
def unifieorder 代码很短,解释一下
- 把必要的商品信息如商品名,价格(x分钱),回调地址,支付类型 NATIVE 写清楚(info = {})
- 写上 key, appid, mch_id (whole_params = {})
- RestClient 发一个 POST 请求,payload 是 xml 格式的
注意,最后结果存入了 @result 里。我们会在 view 里使用它。
home controller 里剩余代码如下:
def get_sign:生成 md5 的签名
def make_payload:把参数转成 XML 格式
接下来我们看看 home#unifieorder 的 view
其实就是把 code_url 用一个前端 js 库显示二维码。没有别的了。
接下来看看微信回调代码
- 验证签名
- 签名没问题了,找到订单,改为已支付状态。
总结
填入必要配置信息后(appid, key, mch_id)
unifieorder 接口下单,把二维码 (code_url)显示给用户,
让用户扫码付款即可。
用户付款后,notify 会收到通知,改成已支付状态。
文末再强调一遍
微信提供了多种支付方式,这次只是做了一种。"二维码扫码支付"。
没做的:(以后有机会再写)
- App支付
- 小程序支付
- 公众号内网页支付
- 退款
- 发红包
- 查询订单状态(异步付款通知出问题,需要主动去查)
最后
希望这篇文章对你有帮助
有问题可联系 guokrfans#gmail.com
我觉得这篇文章讲得比较清晰了,代码实际上也不多。加起来大概50行左右。
gem "wx_pay" 只用来在回调接口里验证签名,没有用 gem "wx_pay" 的 unifieorder,
因为我用这个东西碰到了一些问题。干脆就自己写 unifieorder 下单的那几行代码。
承接开发
如果你觉得以上太麻烦。太费时间。
希望花钱让别人来帮你开发,可以联系 guokrfans#gmail.com(#换成@)