Python对接支付宝支付自实现

# -*- coding: utf-8 -*-

import base64
import json
import urllib.parse
from datetime import datetime import requests
from cryptography.hazmat.backends import default_backend
from cryptography.hazmat.primitives import hashes
from cryptography.hazmat.primitives import serialization
from cryptography.hazmat.primitives.asymmetric import padding class AliPayException(Exception):
def __init__(self, data):
super(AliPayException, self).__init__()
self.data = data def __str__(self):
return "alipay - {}".format(self.data) def __unicode__(self):
return u"alipay - {}".format(self.data) class AliPayVerifyException(AliPayException):
def __init__(self, msg, data):
super(AliPayVerifyException, self).__init__('alipay verify except - {}:{}'.format(msg, data)) class AliPay:
def __init__(self, **kwargs):
"""
:param kwargs:
url: 请求地址
notify_url: 支付宝服务器主动通知商户服务器里指定的页面http/https路径
app_id: 支付宝分配给开发者的应用ID
sign_type: 商户生成签名字符串所使用的签名算法类型,目前支持RSA2和RSA,推荐使用RSA2
app_private_key: 签名私钥
"""
self._app_id = kwargs['app_id']
self._seller_id = kwargs['seller_id']
self._gateway_url = kwargs['gateway_url']
self._notify_url = kwargs.get('notify_url')
self._sign_type = kwargs.get('sign_type', 'RSA2')
if self._sign_type not in ('RSA', 'RSA2'):
raise Exception('alipay sign_type must `RSA` or `RSA2`')
self._charset = 'utf-8'
self._format = 'json' with open(kwargs['app_private_key']) as f:
self._app_private_key = serialization.load_pem_private_key(
f.read().encode('utf8'),
None,
default_backend()
)
with open(kwargs['public_key']) as f:
self._public_key = serialization.load_pem_public_key(
f.read().encode('utf8'),
default_backend()
) @property
def app_id(self):
return self._app_id @property
def seller_id(self):
return self._seller_id def app_private_sign(self, data):
if self._sign_type == 'RSA':
signature = self._app_private_key.sign(
data.encode('utf8'),
padding.PKCS1v15(),
hashes.SHA1())
else:
signature = self._app_private_key.sign(
data.encode('utf8'),
padding.PKCS1v15(),
hashes.SHA256())
return base64.b64encode(signature).decode('utf8') def sync_verify(self, method, raw_data):
"""
同步验签
:return:
"""
method = method.replace('.', '_') + '_response'
raw_data = raw_data.decode('utf8')
sign_index = raw_data.rfind('sign')
signature = base64.b64decode(raw_data[sign_index + 7: -2])
method_data = raw_data[raw_data.find(method) + len(method) + 2: sign_index - 2]
self._public_key.verify(
signature,
method_data.encode('utf8'),
padding.PKCS1v15(),
hashes.SHA256()) def async_verify(self, data):
"""
异步验签
:return:
"""
sign_data = {}
for k, v in data.items():
if k in ('sign', 'sign_type'):
continue
sign_data[k] = v self._public_key.verify(
base64.b64decode(data['sign']),
'&'.join(['{}={}'.format(item) for item in self.sort_data(sign_data)]).encode('utf8'),
padding.PKCS1v15(),
hashes.SHA256()) @staticmethod
def sort_data(data):
return [(k, data[k]) for k in sorted(data.keys())] def params(self, method, biz_content):
data = {
'app_id': self._app_id,
'method': method,
'format': self._format,
'charset': self._charset,
'sign_type': self._sign_type,
'timestamp': datetime.now().strftime('%Y-%m-%d %H:%M:%S'), # yyyy-MM-dd HH:mm:ss
'version': '1.0',
'biz_content': json.dumps(biz_content, separators=(',', ':'))
}
if self._notify_url:
data['notify_url'] = self._notify_url sign = self.app_private_sign('&'.join(['{}={}'.format(item) for item in self.sort_data(data)])) p = '&'.join(['{}={}'.format(item[0], urllib.parse.quote(item[1])) for item in self.sort_data(data)])
p += '&{}={}}'.format('sign', urllib.parse.quote(sign)) return p def command(self, method, biz_content):
params = self.params(method, biz_content) response = requests.get('%s?%s' % (self._gateway_url, params))
response_raw_data = response.content
response_data = response.json()
alipay_response_data = response_data[method.replace('.', '_') + '_response']
if alipay_response_data.get('code', '10000') != '10000':
raise AliPayException(alipay_response_data)
self.sync_verify(method, response_raw_data)
return alipay_response_data if __name__ == '__main__':
alipay = AliPay(**{
'app_id': '...',
'seller_id': '...',
'gateway_url': 'https://openapi.alipaydev.com/gateway.do',
'notify_url': '...',
'app_private_key': 'path to private_key.pem',
'public_key': 'path to public_key.pem'
})
biz_content = {
'out_trade_no': "111",
'total_amount': 0.01,
'subject': "test",
}
alipay.command('alipay.trade.precreate', biz_content)

Python对接支付宝支付自实现的更多相关文章

  1. python调用支付宝支付接口

    python调用支付宝支付接口详细示例—附带Django demo代码   项目演示: 一.输入金额 二.跳转到支付宝付款 三.支付成功 四.跳转回自己网站 在使用支付宝接口的前期准备: 1.支付宝公 ...

  2. Django 对接 支付宝支付, 回调

    平台 点击这里进入 蚂蚁金服开放平台 沙箱 点击这里进入 沙箱环境 初始界面 设置公钥 下载创建秘钥工具 1.  进入文档中心 这里 2. 选中 电脑网站支付 3. 进入后选中 API 列表 中的 统 ...

  3. tp5对接支付宝支付简单集成

    对于每个刚开始工作的新手来说,无论支付宝支付还是微信支付都是跑不掉的一个小门槛. 在加上本人比较技术比较渣(比较懒导致的),不太喜欢引用那么大的SDK,于是就简单集成了一下支付宝的支付. 但也只是只有 ...

  4. python调用支付宝支付接口详细示例—附带Django demo代码

    项目演示: 一.输入金额 二.跳转到支付宝付款 三.支付成功 四.跳转回自己网站 在使用支付宝接口的前期准备: 1.支付宝公钥 2.应用公钥 3.应用私钥 4.APPID 5.Django 1.11. ...

  5. springboot项目对接支付宝支付

    支付宝对接文档 一.准备工作 1. 首先要到 蚂蚁金服开发者中心 https://openhome.alipay.com/platform/home.htm 注册商家账户,并认证. 2.下载java版 ...

  6. python - 对接微信支付(PC)和 注意点

    注:本文仅提供 pc 端微信扫码支付(模式一)的示例代码. 关于对接过程中遇到的问题总结在本文最下方. 参考: 官方文档,    https://blog.csdn.net/lm_is_dc/arti ...

  7. Thinkcmf对接支付宝支付和获取用户信息

    一.         登录支付宝开放平台 平台地址:https://open.alipay.com/ 二.         创建应用并申请上线 登录后,[进入我的开放平台],依次点击[开发者中心]-& ...

  8. Django中对接第三方支付(支付宝)实现支付的流程

    1. 业务逻辑准备 1. 使用沙箱提供的商家环境 沙箱环境:是支付宝提供给开发者的模拟支付的环境 沙箱应用:https://docs.open.alipay.com/200/105311 沙箱账号:h ...

  9. django中使用事务以及接入支付宝支付功能

    之前一直想记录一下在项目中使用到的事务以及支付宝支付功能,自己一直犯懒没有完,趁今天有点兴致,在这记录一下. 商城项目必备的就是支付订单的功能,所以就会涉及到订单的保存以及支付接口的引入.先来看看订单 ...

随机推荐

  1. leetcood学习笔记-110-平衡二叉树

    ---恢复内容开始--- 题目描述: 方法一: class Solution(object): def isBalanced(self, root): """ :type ...

  2. sed 一 文本处理工具

    简介 sed 采用的是流编辑模式: 最明显的特点是,在 sed 处理数据之前,需要预先提供一组规则,sed 会按照此规则来编辑数据. sed 会根据脚本命令来处理文本文件中的数据,这些命令要么从命令行 ...

  3. PHP PDO 大对象 (LOBs)

    应用程序在某一时刻,可能需要在数据库中存储"大"数据. "大"通常意味着"大约 4kb 或以上",尽管某些数据库在数据达到"大&q ...

  4. 基于bootstrap的时间选择插件daterangepicker以及汉化方法

    双日历时间段选择插件 — daterangepicker是bootstrap框架后期的一个时间控件: 可以设定多个时间段选项:也可以自定义时间段:由用户自己选择起始时间和终止时间:时间段的最大跨度可以 ...

  5. luoguP5162 WD与积木

    我怎么这么zz啊.... 法一: 枚举最后一层的方案:没了... 法二: 生成函数:没了. k*F^k(x),就是错位相减. 法三: 我的辣鸡做法:生成函数 求方案数,用的等比数列求和....多项式快 ...

  6. 牛客多校第九场 B Quadratic equation 模平方根

    题意: 已知 $x+y$ $mod$ $q = b$ $x*y$ $mod$ $q = c$ 已知b和c,求x和y 题解: 容易想到$b^2-4c=x^2-2xy+y^2=(x-y)^2$ 那么开个根 ...

  7. Spring Boot 遇到空指针

    @Autowired private IRoadRescueService roadRescueService; 千万不要把注入的service类设为static

  8. VScode中写vue代码 Ctrl+/添加注释失效

    1.点击列表的文件——>首选项——>键盘快捷方式,在里面查看 Ctrl+/ 是否有冲突 2.查看右下角的选择语言模式是否是Vue,如下图

  9. LeetCode 197. Rising Temperature (上升的温度)

    题目标签: 题目给了我们一个 温度表格,让我们找到 所有温度比之前一天高的,返回id. 建立 Weather w1, Weather w2,找到当w1 的温度 大于 w2 的时候,而且 w1 的日期是 ...

  10. scrollReveal.js导致页面加载完之后页面中点击事件添加的css参数失效了(我的Hexo next博客引发的问题)

    文章目录 时间 背景 问题解决 个人博客:https://mmmmmm.me 源码:https://github.com/dataiyangu/dataiyangu.github.io 时间 2019 ...