新手问题 【已解决】付宝移动支付异步 POST 请求处理问题

pengedy · 2015年06月30日 · 最后由 nowherekai 回复于 2015年07月01日 · 2873 次阅读

支付宝移动支付中,服务器需要根据支付宝发来的异步 POST 请求来处理具体的业务逻辑。

我开发的应用中,Android 客户端已经成功收到支付宝的同步消息,服务器也受到了支付宝的异步 POST,但无法执行该 POST 路径对应的方法,也就无法处理请求中的参数,无法处理任何业务逻辑。

根据我测试的写法,当收到 POST 时候,我会把这个 POST 中的参数在数据库里存成一个账单,然而服务器的响应如下:

Started POST "/api/users/34341/bills" for 110.75.152.2 at 2015-06-30 11:57:52 +0800
Processing by Api::BillsController#create as HTML
  Parameters: {"discount"=>"0.00", "payment_type"=>"1", "subject"=>"xxx", "trade_no"=>"2015063000001001", "buyer_email"=>"[email protected]", "gmt_create"=>"2015-06-30 11:57:51", "notify_type"=>"trade_status_sync", "quantity"=>"1", "out_trade_no"=>"063011574", "seller_id"=>"208851211", "notify_time"=>"2015-06-30 11:57:52", "body"=>"测试", "trade_status"=>"TRADE_FINISHED", "is_total_fee_adjust"=>"N", "total_fee"=>"0.01", "gmt_payment"=>"2015-06-30 11:57:52", "seller_email"=>"[email protected]", "gmt_close"=>"2015-06-30 11:57:51", "price"=>"0.01", "buyer_id"=>"208800251", "notify_id"=>"001eb177a9475a8d", "use_coupon"=>"N", "sign_type"=>"RSA", "sign"=>"ahpwrghaiuhgaiouerghiauer", "user_id"=>"34341"}
Completed 200 OK in 1ms (Views: 0.2ms | ActiveRecord: 0.0ms)

以上,收到 POST 之后直接相应 200,并没有任何数据操作,经检查数据库里也确实没有账单。

但如果我自己按照参数格式强行 POST 这个接口,就可以正常完成业务逻辑。

Started POST "/api/users/27/bills" for 127.0.0.1 at 2015-06-30 10:19:22 +0800
Processing by Api::BillsController#create as */*
  Parameters: {"discount"=>"0.00", "payment_type"=>"1", "subject"=>"xxx", "trade_no"=>"2015063000001001", "buyer_email"=>"[email protected]", "gmt_create"=>"2015-06-30 11:57:51", "notify_type"=>"trade_status_sync", "quantity"=>"1", "out_trade_no"=>"063011574", "seller_id"=>"208851211", "notify_time"=>"2015-06-30 11:57:52", "body"=>"测试", "trade_status"=>"TRADE_FINISHED", "is_total_fee_adjust"=>"N", "total_fee"=>"0.01", "gmt_payment"=>"2015-06-30 11:57:52", "seller_email"=>"[email protected]", "gmt_close"=>"2015-06-30 11:57:51", "price"=>"0.01", "buyer_id"=>"208800251", "notify_id"=>"001eb177a9475a8d", "use_coupon"=>"N", "sign_type"=>"RSA", "sign"=>"ahpwrghaiuhgaiouerghiauer", "user_id"=>"34341"}
Unpermitted parameters: notify_type, seller_email, gmt_close
   (0.1ms)  begin transaction
  SQL (1.0ms)  INSERT INTO "bills" ......
   (0.8ms)  commit transaction
Completed 200 OK in 31ms (Views: 0.3ms | ActiveRecord: 3.1ms)

在自己测试中,发现了一个服务器响应中一个值得注意的地方:

# 处理支付宝异步POST
Processing by Api::BillsController#create as HTML
# 对应的Nginx Log
"POST /api/users/34341/bills HTTP/1.1" 200 115 "-" "Mozilla/4.0" "-"

# 处理自己的POST测试
Processing by Api::BillsController#create as */*
# 对应的Nginx Log
"POST /api/users/7/bills HTTP/1.1" 200 93 "-" "Mozilla/5.0 (Macintosh; Intel Mac OS X 10_10_3) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/43.0.2357.130 Safari/537.36" "-"

根据回帖中的方法进行调试,Bill.create! bill_params即可正常运行。

#1 楼 @cysh 多谢 我去读一下

#1 楼 @cysh 然而并没有明白你让我看的是什么。我在方法里最后写的是 render 出来一段 JSON 返回过去,所以本身也很奇怪这个 as HTML 是什么情况。

所有非GET的HTTP request都必須帶有一個Token參數才能存取,Rails會自動在所有表單中幫你插入Token參數,預設的Layout中也有一行<%= csrf_meta_tag %>標籤可以讓JavaScript讀取到這個Token。會需要關閉這個功能的時機是,你需要開放API給非瀏覽器客戶端,這時候你會需要取消它

我觉得可能是你没跳过 CSRF,所以提示你一下

#4 楼 @cysh 嗯嗯,明白,其实是跳过了的。

controller 代码贴出来

注意地方就是 post request format as html or another,好像也没什么,是不是 controller 里面代码设置校验之类的,校验没通过,所以没执行订单创建之类

这种情况很容易 debug 出来吧,执行在哪一步有问题,什么问题。

@nowherekai @mouse_lin @hanluner 按理说是很容易 debug 出来,但其实根本没有 debug 的余地,因为这个用来测试的 Controller Action 里只写了一行语句:

def create
  Bill.create bill_params
end

至于bill_params方法,是标准的强参数写法,已经通过了本地测试。

#9 楼 @pengedy 你用的是 create, 而不是 create! 。自然不会强写入。那你把线上数据阻断掉,然后手工在 rails c 里面运行一下。而且还要注意看线上 log。

#9 楼 @pengedy 显然还有 debug 的余地,例如在 action 里面打一条 log 看看有没有执行。

这个问题其实是因为你不会debug 比如用楼上的方法

def create
  b = Bill.create bill_params
  Rails.loger.debug "debug0: #{b.error.full_messages}"
end
需要 登录 后方可回复, 如果你还没有账号请 注册新账号