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. thinkphp cookie支持

    系统内置了一个cookie函数用于支持和简化Cookie的相关操作,该函数可以完成Cookie的设置.获取.删除操作. Cookie设置 cookie('name','value'); //设置coo ...

  2. thinkphp 数据库缓存

    默认的数据库驱动位于Think\Db\Driver命名空间下面,驱动类必须继承Think\Db类,每个数据库驱动必须要实现的接口方法包括(具体参数可以参考现有的数据库驱动类库): 驱动方法 方法说明 ...

  3. 小程序生成海报:通过 json 配置方式轻松制作一张海报图

    背景 由于我们无法将小程序直接分享到朋友圈,但分享到朋友圈的需求又很多,业界目前的做法是利用小程序的 Canvas 功能生成一张带有二维码的图片,然后引导用户下载图片到本地后再分享到朋友圈.而小程序 ...

  4. delphi Sqlite

    Delphi中SQLite如何读写二进制字段(Blob类型) 在Delphi中,有大量的组件可以操作SQLite数据库,如UniDAC就是其中一个比较优秀的,当然还有ASQLite3Component ...

  5. 如何把本地文件上传github

    1.$ git config --global user.name "xxx" 2.$ git config --global user.email xxx@qq.com 3.进入 ...

  6. Adobe Fireworks CS6 win64的安装

    网页三大剑客之一    FW的安装 本人也是找了半天才找到的. (没有视频)这里先感谢原帖给我的链接https://blog.csdn.net/qq_38053395/article/details/ ...

  7. element-ui表格点击一行展开

    转载:https://www.cnblogs.com/xiaochongchong/p/8127282.html <template> <el-table :data="t ...

  8. file对象的获取 radio值的获取

    jq $("#hiddenFile").get(0).filesjs this.files; 获取radio的值 $('input:radio:checked').val(): $ ...

  9. Linux sed -i 字符串替换

    sed -i 直接替换文件中的内容不输出, 如 将 laravel .env中的 QUEUE_DRIVER=sync 替换为 QUEUE_DRIVER=redis, 在Laravel的项目根目录中运行 ...

  10. 《parsing techniques》中文翻译和正则引擎解析技术入门

    http://parsing-techniques.duguying.net/ (中文版) https://swtch.com/~rsc/regexp/ https://blog.csdn.net/m ...