1 支付宝签名与验签

  • 签名与验签的作用
    首先了解下使用RSA签名与验签的作用是什么?
    对数据进行签名后,可以保证数据完整性,机密性和发送方角色的不可抵赖性,可以有效防止请求信息信息被篡改。

以商户服务端(A)、支付宝服务端(B)、发送的消息内容(C)、加密后的签名(D)举例如下:
• 签名:商户A将需要发给支付宝B的消息内容C利用app私钥进行加密得到签名D。然后A将C和D一起发给B。
• 验签:支付宝B接收到内容C和签名D后,使用app公钥进行验证,验证签名D解密后的内容是否与内容C相同,相同返回true验签成功。反之,返回false验签失败。

以上是商户端的加密流程,支付宝端签名和验签流程是刚好与之相反,支付宝端签名,商户端验签。所以在整个接口请求过程中一共用到了两对密钥,商户端的应用密钥和支付宝端的支付宝密钥。深入了解可参考上期提到的《密钥交互原理》。

1.1 商户服务器签名

商户服务器生成支付页面API url请求参数,这些参数需要使用app应用私钥加密,而支付宝收到数据后,使用app应用公钥解密后与原始请求参数对比,以确定确实是商户服务器发送的请求。

1.2 商户服务器端自行实现签名过程

过程: 筛选请求参数并排序==>拼接==>使用app应用私钥加密==>拼接成url
(然后使用该url向支付宝发起请求,支付宝返回支付页面)

准备的参数如下:

REQUEST URL: https://openapi.alipay.com/gateway.do
REQUEST METHOD: GET
CONTENT:
app_id=2016101800718925
method=alipay.trade.page.pay
charset=utf-8
sign_type=RSA2
timestamp=2020-10-13 09:58:50
version=1.0
biz_content={"out_trade_no":"20150519815610100992007","product_code":"FAST_INSTANT_TRADE_PAY","total_amount":88.88,"subject":"Iphone6 16G","body":"Iphone6 16G"}
return_url="https://example.com"
notify_url="https://example.com/notify"

请求参数筛选之后形式如下:

app_id=2016101800718925
method=alipay.trade.page.pay
charset=utf-8
sign_type=RSA2
timestamp=2020-10-13 09:58:50
version=1.0
biz_content={"out_trade_no":"20150519815610100992007","product_code":"FAST_INSTANT_TRADE_PAY","total_amount":88.88,"subject":"Iphone6 16G","body":"Iphone6 16G"}
return_url="https://example.com"
notify_url="https://example.com/notify"

排序之后形式如下:

app_id=2016101800718925
biz_content={"out_trade_no":"20150519815610100992007","product_code":"FAST_INSTANT_TRADE_PAY","total_amount":88.88,"subject":"Iphone6 16G","body":"Iphone6 16G"}
charset=utf-8
format=json
method=alipay.trade.page.pay
notify_url="https://example.com/notify"
return_url="https://example.com"
sign_type=RSA2
timestamp=2020-10-13 09:58:50
version=1.0

生成的待签名内容形式如下:

app_id=2016101800718925&biz_content={"out_trade_no":"20150519815610100992007","product_code":"FAST_INSTANT_TRADE_PAY","total_amount":88.88,"subject":"Iphone6 16G","body":"Iphone6 16G"}&charset=utf-8&format=json&method=alipay.trade.page.pay&notify_url="https://example.com/notify"&
return_url="https://example.com"sign_type=RSA2&timestamp=2020-10-13 09:58:50&version=1.0

使用app应用私钥加密(必须与应用 ID 中上传的应用公钥是匹配的,支付宝会使用应用公钥解密:即验签),
app应用私钥形式如下:

MIIEpQIBAAKCAQEAv/JKebY7hSXhg1q3V2Z1KCTtfCDLBIhfaLM3RqkHUsxoqdiXYzzJKX7f/hIVdkL/6Gza0PTDbG3dohCx5G2yIo6Gariq4IyFk4cDc3jIooi4kShz4nVzEgS333ZdmZ3LHRcGf2353INUp55Sv0dOMDkLeZA09lJujisJ5UGfgeFM79v+a1tvlcwPnMQmbF9t9ddBhH6/WDZgEL+x2EaytX9+tyhRLffA12OewgI8e0DACk2XSO1vyOtYl5e3LI/DVjByiwzUr+bWpqNKAm4PmzTL5OFvZBE5LwQSJ/qYu6pA2BKuxmn65lsBk/sGBwMJa/WezZIb+BALsyyOKWxVCwIDAQABAoIBAG9FnjcAlXCSjTEAndhk5PXosmOK/yYZiHXBrwGfa0dsiCAuF1TIIDWV/3PiN97e6EttD0yjF8b7ycfxta6eiO3PgczMUQLrc2QamL2P/395ksVTlhppy9NeONmqXIh5GQ48EuA8eOSEncat2XpZc9Iwv54xIwLItp5kBNCKQlWfrNKJUp1ZjpVBfh1fENjktkdyN9uzZp6PInuEH5WM//4tTGi78oGzDtg1r8DwHS5KqXYo9ulEOyd0KH1OAYXZLqjYJ2xIzotlvu7WlWxYFwK5+D+iiYYdF+vrNnXaQQRcwHJztc386usdMnk5FRRZNdoHrcJ2QOpSXvni14vfksECgYEA7KgbZx8oyudulQqzzus/m2hUudbPJbTa6w0P10QX1Efn2mEmWeg6p7bj3L+cN/OoOWZ4Ke0xKxkOQ0WYLLOvNVxRzF0Xjj+C57YHtShvbwe54IZFNrDe/FKHhpBYS6vFzKX6ck3HHEjC2WlqolAEHAbYFGTHobKBa0qgIvPl/UUCgYEAz6KmhQhNTOBIG/kY7MVHLfMQyvefhT+Xm/h73hJK3Nfp1M+QQZIj1uiDld6bEu7vUP91K6+JyE0BJZcP4eHCmzkp2KjcyGDWJQfbpaaH9RT0uiR7D7obBHf8BGOAgnA809SX8CD3cS+gCx8cqiIsMZB494A2iVyNiiufVIX1Zg8CgYEA0jHpzOjnEXkHRgewduuJnl3HSxyY9lOxUa5TUI6hX6HSM6uwJZDXcBlIP8xMU4Ht+7WgqxSKZE4n1eZdZ+7cgteRq6NPhb+xZF7Qb74PY52IIf0AQrhMBe7Dguh4FBXoZIFTdezRGbUio3o3BR1u2PnXOB3fFiZ3PrWUkBbzQsUCgYEApbd5E+AmYd73bmwHOqHRR5kho/yycpTomfFeW0VaPpyM4e6vgcXzmMiGjQzX0+qjUpAwoic93oGnEqtYX73hpiWfgm5zl/HBuFhnM/SPukl5cT9AgLLWcWCZ4Z7QqEqQIbkhcuO82bdbEsVICXmwr/ZQtai83jDiPo7GYZ1w2H0CgYEAjFxeHoUKnMO0GqOHy/v3gqS4357kTz7/PfXqbIO2OvyW5KX9MXeVJ6OD6KiqVGBGStF8Vy8VT/j2KXCjiJQ91gFqEJvkadsB1HXfXxPRwUYi3i7BaadpfnW3cM6uAE6iPVqhGu4Z0uyUp/koGgkBr/qbnwRgF9/hXb8Pygu0s5c=

生成的签名(sign)形式如下:

p0du54PYDnCdHjYFgc0mri5KqA09ziGVJZi/xaDiPzvePlMGGGHcBzH8qNV3pYvBxv60ezxC2a9ZM97bTkmJZt21mb5tBDPWBpYZsJqU3XCMgDnlisiq3Us2glwB9eHzVaZPTW14lSykkPEwLk8mwzQdwM5/SmCnHpAT+I3BOkBUPs6pl5i0eE/dA4ePAkXgWIqmsQbgh9As7Fgh65wScxbzsC8FJfbMhQDNV94WYCQd9cbkyOPidpnT9o7u2GoqkVjm2N73Ja2ObSdp5PQNbQ8UdtJ+PYBUTXDa7cLIkoc00JGSCqhGPA6rFCnNuAay/C4wtSKJzKZ5XpRWwYrkWQ==
https://openapi.alipaydev.com/gateway.do?app_id=2016101800718925&biz_content={"out_trade_no":"20150519815610100992007","product_code":"FAST_INSTANT_TRADE_PAY","total_amount":88.88,"subject":"Iphone6 16G","body":"Iphone6 16G"}&charset=utf-8&format=json&method=alipay.trade.page.pay&notify_url="https://example.com/notify"&
return_url="https://example.com"sign_type=RSA2&timestamp=2020-10-1309:58:50&version=1.0&sign=p0du54PYDnCdHjYFgc0mri5KqA09ziGVJZi/xaDiPzvePlMGGGHcBzH8qNV3pYvBxv60ezxC2a9ZM97bTkmJZt21mb5tBDPWBpYZsJqU3XCMgDnlisiq3Us2glwB9eHzVaZPTW14lSykkPEwLk8mwzQdwM5/SmCnHpAT+I3BOkBUPs6pl5i0eE/dA4ePAkXgWIqmsQbgh9As7Fgh65wScxbzsC8FJfbMhQDNV94WYCQd9cbkyOPidpnT9o7u2GoqkVjm2N73Ja2ObSdp5PQNbQ8UdtJ+PYBUTXDa7cLIkoc00JGSCqhGPA6rFCnNuAay/C4wtSKJzKZ5XpRWwYrkWQ==

经过urlencode加密后实际形式如下:

app_id=2016102400749214&biz_content=%7B%22subject%22%3A%22%5Cu5929%5Cu5929%5Cu751f%5Cu9c9c2021041010554419%22%2C%22out_trade_no%22%3A%222021041010554419%22%2C%22total_amount%22%3A%2233.99%22%2C%22product_code%22%3A%22FAST_INSTANT_TRADE_PAY%22%7D&charset=utf-8&method=alipay.trade.page.pay&notify_url=http%3A%2F%2F120.77.253.68%3A8000%2Fuser%2F&return_url=http%3A%2F%2F120.77.253.68%3A8000%2Fuser%2Forder%2F1&sign_type=RSA2&timestamp=2021-04-10+10%3A55%3A50&version=1.0&sign=cGeKkdf4tsZ18BvcfwbuclshF6XR9vAZYhGsJk%2BznaxGzl%2FsDPoG28e2ihw%2BS47rEJ64xGfTaT57ids7RckpsvOHseLUi5ziPu6VO38ogFvsrhXRceo2Jtp0TGJqaCAP4Chrpz2SD2j08GjH0RXUiK3I%2FX1IYxfN2lMbZfFi0SHqPv9eSoDVaYzXznYW%2BMcPX5zWfjPNsVXChRKIi8aeMKPjdGztDK9cxdbC7gol07EGRAcpAbNT73WTn7PPKqEnpV8o9vkIZ65L3mmupQmXkqsYoXE%2FlW4Y2P1IsZMg0diZxtQKOoQM5ObkRxFwbq%2BmrPE7uHvG2PEGRHN3S2mzOg%3D%3D

1.3 使用SDK自动签名

自动签名可以很方便的帮助我们实现签名操作。

class OrderPayView(View):'''支付'''def post(self, request):'''支付'''# 用户登录判断user = request.userif not user.is_authenticated():return JsonResponse({'res': 0, 'errmsg': '用户未登录'})# 获取订单idorder_id = request.POST.get('order_id')# 校验参数if not order_id:return JsonResponse({'res': 1, 'errmsg': '无效订单'})try:order = OrderInfo.objects.get(order_id=order_id,user = user,pay_method = 3,order_status = 1,)except OrderInfo.DoesNotExist:return JsonResponse({'res': 2, 'errmsg': '订单错误'})# 调用支付宝API# 初始化支付对象app_private_key_string = open(os.path.join(settings.BASE_DIR, 'apps/order/app_private_key.pem')).read()alipay_public_key_string = open(os.path.join(settings.BASE_DIR, 'apps/order/alipay_public_key.pem')).read()alipay = AliPay(appid="2016102400749214", # 应用idapp_notify_url=None,  # 默认回调urlapp_private_key_string=app_private_key_string,# 支付宝的公钥,验证支付宝回传消息使用,不是你自己的公钥,alipay_public_key_string=alipay_public_key_string,sign_type="RSA2",  # RSA 或者 RSA2debug=True  # 默认False,使用沙箱环境时置为True)# 调用支付APItotal_pay = order.total_price+order.transit_price # Decimal 是不能序列化的,应转换字符串# 电脑网站支付try:# SDK封装的API会自动签名,省去了我们很多的功夫order_string = alipay.api_alipay_trade_page_pay(out_trade_no=order_id, # 订单idtotal_amount=str(total_pay), # 支付总金额subject='天天生鲜%s' % order_id,#return_url="https://example.com",return_url="http://120.77.253.68:8000/user/order/1", # 可选, 不填则使用默认notify url#notify_url="https://example.com/notify" # 可选, 不填则使用默认notify urlnotify_url="http://120.77.253.68:8000/user/" # 可选, 不填则使用默认notify url)except Exception as e:print(e)# 返回:提交支付页面urlpay_url = 'https://openapi.alipaydev.com/gateway.do?' + order_stringprint(order_string)return JsonResponse({'res':3, 'pay_url':pay_url}) # 将支付地址回传给浏览器,从而引导用户跳转到支付页面

2 商户服务器验签

验证是否是支付宝服务器发来的请求。
商户服务器接收到支付宝的请求后,使用支付公钥解密

2.1 自行实现验签

普通公钥模式:
如当面付扫码支付获取二维码的返回内容为:

{"alipay_trade_precreate_response":{"code":"10000","msg":"Success","out_trade_no":"6141161365682511","qr_code":"https:\/\/qr.alipay.com\/bax03206ug0kulveltqc80a8"},"sign":"VrgnnGgRMNApB1QlNJimiOt5ocGn4a4pbXjdoqjHtnYMWPYGX9AS0ELt8YikVAl6LPfsD7hjSyGWGjwaAYJjzH1MH7B2/T3He0kLezuWHsikao2ktCjTrX0tmUfoMUBCxKGGuDHtmasQi4yAoDk+ux7og1J5tL49yWiiwgaJoBE="}

则待验签字段为:

{"code":"10000","msg":"Success","out_trade_no":"6141161365682511","qr_code":"https:\/\/qr.alipay.com\/bax03206ug0kulveltqc80a8"}

同时取出签名值 sign:

VrgnnGgRMNApB1QlNJimiOt5ocGn4a4pbXjdoqjHtnYMWPYGX9AS0ELt8YikVAl6LPfsD7hjSyGWGjwaAYJjzH1MH7B2/T3He0kLezuWHsikao2ktCjTrX0tmUfoMUBCxKGGuDHtmasQi4yAoDk+ux7og1J5tL49yWiiwgaJoBE=

调用验签函数:使用各自语言对应的 SHA256WithRSA (对应 sign_type 为 RSA2) 或 SHA1WithRSA (对应 sign_type 为 RSA) 签名验证函数,传入待验签字段、支付宝公钥、签名内容(sign),验签方法(signType)进行验签,根据返回结果判定是否验签通过(其原理:使用支付宝公钥加密待验签字段,并将结果与签名内容比较,如果相等则验签通过,说明请求是支付宝发送过来的)

2.2 使用SDK自动验签

支付宝SDK封装了验签功能,实现了自动验签
示法代码如下(支付宝返回页return_url和通知页notify_url的视图,使用自动验签):

class AlipayView(APIView):def get(self, request):"""处理支付宝的return_url返回"""processed_dict = {}# 1. 获取GET中参数for key, value in request.GET.items():processed_dict[key] = value# 2. 取出signsign = processed_dict.pop("sign", None)# 3. 生成ALipay对象alipay = AliPay(appid="2016091200490210",app_notify_url="http://115.159.122.64:8000/alipay/return/",app_private_key_path=private_key_path,alipay_public_key_path=ali_pub_key_path,  # 支付宝的公钥,验证支付宝回传消息使用,不是你自己的公钥,debug=True,  # 默认False,return_url="http://115.159.122.64:8000/alipay/return/")# 进行验签,确保这是支付宝给我们的verify_re = alipay.verify(processed_dict, sign)# 这里可以不做操作。因为不管发不发return url。notify url都会修改订单状态。if verify_re is True:order_sn = processed_dict.get('out_trade_no', None)trade_no = processed_dict.get('trade_no', None)existed_orders = OrderInfo.objects.filter(order_sn=order_sn)for existed_order in existed_orders:existed_order.trade_no = trade_noexisted_order.pay_time = datetime.now()existed_order.save()response = redirect("/index/#/app/home/member/order")# response.set_cookie("nextPath","pay", max_age=3)return responseelse:response = redirect("index")return responsedef post(self, request):"""处理支付宝的notify_url"""# 1. 先将sign剔除掉processed_dict = {}for key, value in request.POST.items():processed_dict[key] = valuesign = processed_dict.pop("sign", None)# 2. 生成一个Alipay对象alipay = AliPay(appid="2016091200490210",app_notify_url="http://115.159.122.64:8000/alipay/return/",app_private_key_path=private_key_path,alipay_public_key_path=ali_pub_key_path,  # 支付宝的公钥,验证支付宝回传消息使用,不是你自己的公钥,debug=True,  # 默认False,return_url="http://115.159.122.64:8000/alipay/return/")# 3. 进行验签,确保这是支付宝给我们的verify_re = alipay.verify(processed_dict, sign)# 如果验签成功if verify_re is True:order_sn = processed_dict.get('out_trade_no', None)trade_no = processed_dict.get('trade_no', None)trade_status = processed_dict.get('trade_status', None)# 查询数据库中存在的订单existed_orders = OrderInfo.objects.filter(order_sn=order_sn)for existed_order in existed_orders:# 订单商品项order_goods = existed_order.goods.all()# 商品销量增加订单中数值for order_good in order_goods:goods = order_good.goodsgoods.sold_num += order_good.goods_numgoods.save()# 更新订单状态,填充支付宝给的交易凭证号。existed_order.pay_status = trade_statusexisted_order.trade_no = trade_noexisted_order.pay_time = datetime.now()existed_order.save()# 将success返回给支付宝,支付宝就不会一直不停的继续发消息了。return Response("success")

支付宝签名与验签,return_url和通知页notify_url相关推荐

  1. 支付宝 java 签名算法_(支付宝)签名与验签

    # 签名与验签 更新时间:2017-06-13 # [](https://docs.open.alipay.com/#%E8%AF%B7%E6%B1%82%E5%8F%82%E6%95%B0%E7%A ...

  2. 支付宝支付API之签名与验签

    支付宝开发平台支付API文档: https://docs.open.alipay.com/291/106130 对接支付API出现问题的主要原因:数据被转义,所以在调试时先把数据可以写死 注意:在调试 ...

  3. 支付宝APP支付-php后台签名以及验签

    签名和验签在APP端也是可以完成的,考虑到安全问题,签名和验签最好在服务端完成,支付宝官方建议也是这样的,所以php端需要把签名好的参数传给APP端.详细步骤见正文: 一. 下载php支付宝sdk h ...

  4. PHP 支付宝SDK加密与解密、签名与验签(含php原生写法)

    1.使用支付宝SDK,本次使用的SDK是老版 支付宝文档:https://opendocs.alipay.com/open/54/103419 首先下载或使用新上线的Web在线加密,生成应用私钥与应用 ...

  5. 支付宝请求签名php,支付宝APP之php后台签名以及验签实现方法

    签名和验签在APP端也是可以完成的,考虑到安全问题,签名和验签最好在服务端完成,支付宝官方建议也是这样的,所以php端需要把签名好的参数传给APP端.详细步骤见正文: 一. 下载php支付宝sdk h ...

  6. 支付宝扫码验签实例php,PHP 支付宝支付,支付宝回调

    下载官方SDK:https://openhome.alipay.com/doc/sdkDownload.resource?sdkType=PHP 在支付宝所创建的应用中添加" 电脑网站支付. ...

  7. php支付宝异步回调验签失败,thinkphp网站支付宝异步回调验签失败问题_PHP开发框架教程...

    了解Redis这个核心数据类型_PHP开发框架教程 string字符串tring类型是二进制安全的,即string中可以包含任何数据,Redis 中的普通string采用rawencoding 即原始 ...

  8. Java应用服务系统安全性,签名和验签浅析

    1 前言 随着互联网的普及,分布式服务部署越来越流行,服务之间通信的安全性也是越来越值得关注.这里,笔者把应用与服务之间通信时,进行的的安全性相关,加签与验签,进行了一个简单的记录. 2 安全性痛点 ...

  9. 数字证书应用综合揭秘(包括证书生成、加密、解密、签名、验签)

    引言 数字证书是一个经证书授权中心数字签名的包含公开密钥拥有者信息以及公开密钥的文件.为现实网络安全化标准如今大部分的 B2B.B2C.P2P.O2O 等商业网站含有重要企业资料个人资料的信息资信网站 ...

最新文章

  1. 乔安监控云存储_让数据更安全可用,阿里云存储多项新功能发布
  2. linux 磁盘延时,Linux:如何模拟硬盘延迟?我想在不使用CPU电源的情况下增加iowait值...
  3. [视频教程] 如何在Linux深度系统deepin下安装docker
  4. android studio 工程demo例子,Android Studio 实现跑马灯微项目实例
  5. 学习pytorch: API 学习
  6. 2021-07-13 CNN池化理解学习
  7. BootDo:源代码打包与自启动
  8. biopython教程与手册_使用biopython处理序列数据
  9. R语言中,如何设置当前工作文件路径?
  10. 程序开发中常用的第三方API接口汇总,包含各种类别的介绍
  11. Mysql序号 查询
  12. 集束搜索beam search和贪心搜索greedy search
  13. iOS开发之支付宝集成
  14. 回文数(Java解法)
  15. macOS Command - xattr
  16. whistle安装,成功率高
  17. 3dmax基础教程:聚光灯的创建及调整方式
  18. 提升工作效率的五款实用工具软件及其应用心得
  19. osgQTWidget
  20. Maven 私服 Nexus Win 10 安装与快速使用入门

热门文章

  1. rog枪神7超竞版评测 rog枪神7超竞版 参数配置
  2. php5应用程序无法启动,因为应用程序的并行配置不正确
  3. C++_关于char*字符指针赋值问题
  4. Yii2 render 和 renderPartial 问题
  5. 终于知道如何 把MATLAB中的 程序字体变大了!
  6. keil编写的程序一直在startup_XXXX.s中等待,进不到main函数。有效的解决办法
  7. 【windows脚本】开启启动注册表位置
  8. 手机备份/恢复分区(boot/system/userdata)、数据的几种方法
  9. initialcontext java_再发一帖,初始化上下文求解(initialContext)
  10. 廖雪峰历时 3 个月打磨出价值 1980 的数据分析教程,终终终于免费啦!!!