接支付宝支付, 服务端下载 java sdk, 客户端接入android sdk, 设置好沙箱。按照官网流程一步步来,最后进行测试
- 服务器生成一个支付参数字符串,传给客户端
- 客户端用服务器给的支付参数,拉起支付宝(沙箱版)
最后支付宝却传来一个失败的map:
{resultStatus=6001, result=, memo=用户取消}
问题排查
通过使用官方的支付客户端demo(在demo中生成支付参数),设置好沙箱,私钥等,结果正常拉起支付宝支付,支付成功。
这里可以确定设置的密钥是没有问题的,问题就是在支付参数这里了。
支付参数是由 server-java-sdk 来生成的,对比官网的使用示例,一切都一样,这样下来,就确认是 server-java-sdk 生成的字符串不正确了。想来这个问题也只有出现在沙箱版吧,不然正式版出现这个问题早爆炸更新了。所以最大可能是 server-java-sdk 生成的字符串沙箱支付宝不支持。
首先对 server-java-sdk 生成的字符串进行签名校验(官方工具),确定签名正确。然后与官方的支付客户端demo 生成的字符串仔细比较:
# 官方的支付客户端demo 生成的字符串
charset=utf-8&biz_content=%7B%22timeout_express%22%3A%2230m%22%2C%22product_code%22%3A%22QUICK_MSECURITY_PAY%22%2C%22total_amount%22%3A%220.01%22%2C%22subject%22%3A%221%22%2C%22body%22%3A%22%E6%88%91%E6%98%AF%E6%B5%8B%E8%AF%95%E6%95%B0%E6%8D%AE%22%2C%22out_trade_no%22%3A%220414213511-7518%22%7D&method=alipay.trade.app.pay&app_id=2016091500518622&sign_type=RSA2&version=1.0×tamp=2018-04-14+18%3A04%3A03&sign=WnfXnYtpE6%2BtUbq9Zxs3w4n%2Fe%2F%2FQxiN5B1rSsGcNjmbWSVeCHs95a3VksCIt58dRJWj4fza5KwQ0ZHOeLMVEAnZwtjYYSHO96uXYeCG0uf4fm%2FlwWYRuKse5LRW1Sh2QyaVLmn3FcZH9bEnmGaTBHcCcTt%2BPa2KK8cQMNFw6WrLLElmXk4iwXrlwCjoSScots4QIbXK2qBoDPqdHo4i%2BWoNM4V80dPQh0YieNW5AtfOtPeTNBWcvhj9fZ0obrI%2B%2Bd0TQxQzCYyOPnpDOYr9%2FaDsuG4J1SiBPRMzyysPcG9%2BC%2F8kp2iZKQQmuyTGYO9JOZnhix9O2YsGBmx5sKPwbFw%3D%3D
# server-java-sdk 生成的字符串
alipay_sdk=alipay-sdk-java-dynamicVersionNo&app_id=2016091500518622&biz_content=%7B%22body%22%3A%22%E6%88%91%E6%98%AF%E6%B5%8B%E8%AF%95%E6%95%B0%E6%8D%AE%22%2C%22out_trade_no%22%3A%221523714442123-8740%22%2C%22product_code%22%3A%22QUICK_MSECURITY_PAY%22%2C%22subject%22%3A%221%22%2C%22timeout_express%22%3A%2230m%22%2C%22total_amount%22%3A%220.01%22%7D&charset=utf-8&format=json&method=alipay.trade.app.pay&sign=JxVUnDm6I1Pwht%2BknWf6527gyM7zzeGli%2BMm3XWT19YuDcuFuc%2Fr46Qx7rB6m7ckKTPXsK2blEApWTgKvK7uA6sv0nTuCPcLD07DH6wNKygD5F%2By7tZT8M%2BWLugDZx%2BkVBmvNJ4RJDz5KtOx8g%2Fhjs6fWCUH6avWeOLsr9NVP1Jn1hrGL6%2BiCGWO7pPhGHtW7qvibfIAHM5ONBieCZ0xHqlCJDm6NWKJYj7X3avE4uAc%2Fd6TI1rL2i3T30ntAcIqQaj1XGYTJLnPRAqO%2BMDRg4gc6j39Km7lTSiwmaTV2TzHkzZhioOA3gyQa%2FdADuEuuTPEQnf%2FvaqpIzp%2BYcGomg%3D%3D&sign_type=RSA2×tamp=2018-04-14+22%3A00%3A42&version=1.0
发现官方的支付客户端demo 生成的字符串中 sign 参数总在最后,而 server-java-sdk 生成的却是在内部,然后对 server-java-sdk 生成的字符串调整:将 sign 参数移动到尾部,测试OK:
(defn trans-alipay-pay-order-string [order-string]
"将支付宝支付参数字符串中 sign 参数移动到尾部,以支持沙箱支付宝测试"
(let [start-index (clojure.string/index-of order-string "&sign=")
end-index (and start-index
(clojure.string/index-of order-string "&" (inc start-index)))]
(if (and start-index end-index)
(str (.substring order-string 0 start-index)
(.substring order-string end-index)
(.substring order-string start-index end-index))
order-string)))
总结
总的来说是沙箱支付宝的一个bug,可能是用的少,大部分开发同学用1分钱测试大法在正式上线应用中测,所以没有留意这个问题。