好友
阅读权限10
听众
最后登录1970-1-1
|
勤勤学长
发表于 2020-1-28 21:23
本帖最后由 勤勤学长 于 2020-1-28 23:52 编辑
起因:
今晚想做个支付页面,参考了一下腾讯云的充值页面。因为现在的支付功能有网站在用着,直接改动也可以用于新网站的话,难度很大。突然想起之前做过集合型的支付系统。找到了17年做的商城系统,那时候用的是这套支付,由于想过把代码开源,把里边的商品信息给清空了,进不了支付页面参考代码,怎么都进不去后台添加。
直接看支付系统的代码,一时间也看不懂了,换过一次服务器,清理过一些数据库,数据也丢失了。可能要重写支付系统。
把支付功能独立出来也是有好处的吧?规范代码之后,即便以后再有新的网站需要支付功能,直接提供本地订单号、付款金额、回调URL就可以生成对应数据的支付订单支付页面,支付产生的数据单独数据库储存,查询也是直接开接口出来。后期也可以把接口开放给一些客户使用。
为什么要计算sign?
可能有些开发新手会好奇,尤其一些网站发起支付的时候,会有一个参数sign。如果是用作区别是谁发起的,直接用key不就行了?为什么还要算出sign?
一般情况下,生成一个支付,需要提交本地订单号、支付金额、商品名称。这样就谁都可以发起支付生成订单,数据库会产生一堆无用数据。
/pay?title=勤勤学长支付商品名称&money=10.08&out_trade_no=202001281234
如果是加key的话,可以区分是提交商户,再谁都可以发起支付生成大量无用订单数据的前提下,每次生成订单之前还查询一次key存在不存在。
/pay?title=勤勤学长支付订单名称&money=10.08&out_trade_no=202001281234&key=byGY8B4
如果是用sign,就是一种简单的技术基础过滤,你提交的之前到支付接口的时候,接口直接就可以判断你提交的数据跟sign是否一致了。
一般情况下,sign值是通过提交参数的拼接加密而成,比如本地订单号、支付金额、商品名称,生成了一个sign。
$sign=md5('title=勤勤学长订单名称&money=10.08&out_trade_no=202001281234&key=byGY8B4');
//计算得438574b9d68b642f2493c4cd16b5a1cd
/pay?title=勤勤学长支付订单名称&money=10.08&out_trade_no=202001281234&key=byGY8B4&sign=438574b9d68b642f2493c4cd16b5a1cd
服务端接收的是两部分信息:接收参数+sign值。
参数:title=勤勤学长支付订单名称&money=10.08&out_trade_no=202001281234&key=byGY8B4
sign:438574b9d68b642f2493c4cd16b5a1cd
如果把其中一个值改变(如支付金额、订单号),通过服务端计算出来的sign就与之前的不一样了。
比如说我把金额改为11.08,其他值均不改
/pay?title=勤勤学长支付订单名称&money=11.08&out_trade_no=202001281234&key=byGY8B4&sign=438574b9d68b642f2493c4cd16b5a1cd
服务端接收
参数:title=勤勤学长支付订单名称&money=11.08&out_trade_no=202001281234&key=byGY8B4
sign:438574b9d68b642f2493c4cd16b5a1cd
服务端计算参数
$sign=md5('title=勤勤学长支付订单名称&money=11.08&out_trade_no=202001281234&key=byGY8B4');
//计算得48c8573c1ebfc56a06f3e08072400be5
与接收到的sign不一致,服务端就可以直接返回错误提示,不会再进行数据库操作。
reture ‘sign错误’;
如果接收到的sign和接收到参数计算出来的sign一致,再通过key查询发起支付的商户是谁。信息不存在返回 reture ‘key错误或不存在’;
商户存在再真正的发起支付。
我也是小白,边做边学,哪里不对或者做得不好的地方还请指出。
2020年1月28日23点45分更新
关于有前辈提到key存在泄露风险,前文提到生成订单的方式是通过get方式,只是方便大家理解。
目前我想到的方式有两种:
1、把get提交改成post提交,服务端校对通过后,直接跳转到带着订单号的支付页面。
比如:/pay?out_trade_no=20200128123456
但是其他用户可以修改订单号访问链接会触发数据库查询操作。
2、弄一个对称加解密方式,提供开发者加密方式
例如把字符串
title=勤勤学长支付订单名称&money=11.08&out_trade_no=202001281234&key=byGY8B4&sign=438574b9d68b642f2493c4cd16b5a1cd
加密成类似/pay?order=byGY8B4XbXL7X4GM8K99Xq9gLM8KFY88
我在服务端通过接收order值解密之后再校对,解密失败或sign错误就能直接拦截了。 |
|
发帖前要善用【论坛搜索】功能,那里可能会有你要找的答案或者已经有人发布过相同内容了,请勿重复发帖。 |
|
|
|
|