Python支付宝在线支付API
一.蚂蚁金服开发平台申请测试账号
a. 登陆蚂蚁金服开放平台https://open.alipay.com/platform/manageHome.htm,在“开发中心”—“研发服务”下拉处选择沙箱作为测试环境。

b. 填写相关信息,成功申请沙箱账号后进入沙箱环境页面

c.下载沙箱钱包(目前仅支持安卓手机)

d. 使用沙箱账号处的买家账号登陆下载好的沙箱钱包

二.制作公钥和密钥
a.制作应用私钥和公钥
在沙箱应用处点击查看应用公钥

在显示的应用公钥处点击修改

在点击查看密钥生成方法

根据教程生成密钥和公钥

得到一个RSA密钥文件夹,里面有两个文件

b. 制作支付宝公钥
将应用公钥复制上传,点击保存会自动生成支付宝公钥

查看支付宝公钥

三.Django程序开发
a.创建一个django项目

b.配置支付宝公钥和应用私钥
在私钥和公钥头围加上标记便于python识别

c.代码编写
首先安装依赖 pip3 install pycryptodome
SDK官方加密代码,可以在github上找到
# _*_ coding=utf-8 _*_
from datetime import datetime
from Crypto.PublicKey import RSA
from Crypto.Signature import PKCS1_v1_5
from Crypto.Hash import SHA256
from urllib.parse import quote_plus
from base64 import decodebytes, encodebytes
import json class AliPay(object):
"""
支付宝支付接口(PC端支付接口)
""" def __init__(self, appid, app_notify_url, app_private_key_path,
alipay_public_key_path, return_url, debug=False):
self.appid = appid
self.app_notify_url = app_notify_url
self.app_private_key_path = app_private_key_path
self.app_private_key = None
self.return_url = return_url
with open(self.app_private_key_path) as fp:
self.app_private_key = RSA.importKey(fp.read())
self.alipay_public_key_path = alipay_public_key_path
with open(self.alipay_public_key_path) as fp:
self.alipay_public_key = RSA.importKey(fp.read()) if debug is True:
self.__gateway = "https://openapi.alipaydev.com/gateway.do"
else:
self.__gateway = "https://openapi.alipay.com/gateway.do" def direct_pay(self, subject, out_trade_no, total_amount, return_url=None, **kwargs):
biz_content = {
"subject": subject,
"out_trade_no": out_trade_no,
"total_amount": total_amount,
"product_code": "FAST_INSTANT_TRADE_PAY",
# "qr_pay_mode":4
} biz_content.update(kwargs)
data = self.build_body("alipay.trade.page.pay", biz_content, self.return_url)
return self.sign_data(data) def build_body(self, method, biz_content, return_url=None):
data = {
"app_id": self.appid,
"method": method,
"charset": "utf-8",
"sign_type": "RSA2",
"timestamp": datetime.now().strftime("%Y-%m-%d %H:%M:%S"),
"version": "1.0",
"biz_content": biz_content
} if return_url is not None:
data["notify_url"] = self.app_notify_url
data["return_url"] = self.return_url return data def sign_data(self, data):
data.pop("sign", None)
# 排序后的字符串
unsigned_items = self.ordered_data(data)
unsigned_string = "&".join("{0}={1}".format(k, v) for k, v in unsigned_items)
sign = self.sign(unsigned_string.encode("utf-8"))
# ordered_items = self.ordered_data(data)
quoted_string = "&".join("{0}={1}".format(k, quote_plus(v)) for k, v in unsigned_items) # 获得最终的订单信息字符串
signed_string = quoted_string + "&sign=" + quote_plus(sign)
return signed_string def ordered_data(self, data):
complex_keys = []
for key, value in data.items():
if isinstance(value, dict):
complex_keys.append(key) # 将字典类型的数据dump出来
for key in complex_keys:
data[key] = json.dumps(data[key], separators=(',', ':')) return sorted([(k, v) for k, v in data.items()]) def sign(self, unsigned_string):
# 开始计算签名
key = self.app_private_key
signer = PKCS1_v1_5.new(key)
signature = signer.sign(SHA256.new(unsigned_string))
# base64 编码,转换为unicode表示并移除回车
sign = encodebytes(signature).decode("utf8").replace("\n", "")
return sign def _verify(self, raw_content, signature):
# 开始计算签名
key = self.alipay_public_key
signer = PKCS1_v1_5.new(key)
digest = SHA256.new()
digest.update(raw_content.encode("utf8"))
if signer.verify(digest, decodebytes(signature.encode("utf8"))):
return True
return False def verify(self, data, signature):
if "sign_type" in data:
sign_type = data.pop("sign_type")
# 排序后的字符串
unsigned_items = self.ordered_data(data)
message = "&".join(u"{}={}".format(k, v) for k, v in unsigned_items)
return self._verify(message, signature)
alipay.py
from django.contrib import admin
from django.urls import path
from api import views urlpatterns = [
path('admin/', admin.site.urls),
path('index/', views.index),
path('result/', views.pay_result),
path('update_order/', views.update_order), ]
urls.py
import time
from urllib.parse import parse_qs
from django.conf import settings
from django.shortcuts import render, redirect, HttpResponse
from django.views.decorators.csrf import csrf_exempt
from utils.alipay import AliPay def aliPay():
obj = AliPay(
appid="", # 支付宝沙箱里面的APPID
app_notify_url="http://127.0.0.1:8800/update_order/", # 如果支付成功,支付宝会向这个地址发送POST请求(校验是否支付已经完成),此地址要能够在公网进行访问
return_url="http://127.0.0.1:8800/result/", # 如果支付成功,重定向回到你的网站的地址。
alipay_public_key_path="keys/alipay_public_2048.txt", # 支付宝公钥
app_private_key_path="keys/app_private_2048.txt", # 应用私钥
debug=True, # 默认False,True表示使用沙箱环境测试
) # 优化:在settings里面的设置后使用
# obj = AliPay(
# appid=settings.APPID,
# app_notify_url=settings.NOTIFY_URL,
# return_url=settings.RETURN_URL,
# alipay_public_key_path=settings.PUB_KEY_PATH,
# app_private_key_path=settings.PRI_KEY_PATH,
# debug=True,
# )
return obj @csrf_exempt
def index(request):
if request.method == "GET":
return render(request, 'index.html') # 实例化SDK里面的类AliPay
alipay = aliPay() # 对购买的数据进行加密
money = float(request.POST.get('price')) # 保留俩位小数
out_trade_no = "x2" + str(time.time()) # 商户订单号
# 1. 在数据库创建一条数据:状态(待支付) query_params = alipay.direct_pay(
subject="充气式Saber", # 商品简单描述
out_trade_no=out_trade_no, # 商户订单号
total_amount=money, # 交易金额(单位: 元 保留俩位小数)
)
# 拼接url,转到支付宝支付页面
pay_url = "https://openapi.alipaydev.com/gateway.do?{}".format(query_params) return redirect(pay_url) @csrf_exempt
def update_order(request):
"""
支付成功后,支付宝向该地址发送的POST请求(用于修改订单状态)
:param request:
:return:
"""
if request.method == 'POST':
body_str = request.body.decode('utf-8')
post_data = parse_qs(body_str) post_dict = {}
for k, v in post_data.items():
post_dict[k] = v[0] alipay = aliPay() sign = post_dict.pop('sign', None)
status = alipay.verify(post_dict, sign)
if status:
# 1.修改订单状态
out_trade_no = post_dict.get('out_trade_no')
print(out_trade_no)
# 2. 根据订单号将数据库中的数据进行更新 return HttpResponse('支付成功')
else:
return HttpResponse('支付失败')
return HttpResponse('') @csrf_exempt
def pay_result(request):
"""
支付完成后,跳转回的地址
:param request:
:return:
"""
params = request.GET.dict()
sign = params.pop('sign', None) alipay = aliPay() status = alipay.verify(params, sign) if status:
return HttpResponse('支付成功')
return HttpResponse('支付失败')
views.py
d.进行测试
启动项目,访问index页面,输入支付金额,点击支付

使用下载的沙箱钱包扫描付款

付款成功

最后会重定向到return_url

注意:配置文件信息可以在setting中设置,要完成全部测试需要有一个公网IP和服务器,来测试支付宝向app_notify_url发送的POST请求
ALLOWED_HOSTS = ['*', ]
# 支付相关配置
APPID = "***6082500309412"
NOTIFY_URL = "http://127.0.0.1:8800/update_order/"
RETURN_URL = "http://127.0.0.1:8800/pay_result/"
PRI_KEY_PATH = "keys/app_private_2048.txt"
PUB_KEY_PATH = "keys/alipay_public_2048.txt"
Python支付宝在线支付API的更多相关文章
- 第四百零三节,python网站在线支付,支付宝接口集成与远程调试,
第四百零三节,python网站在线支付,支付宝接口集成与远程调试, windows系统安装Python虚拟环境 首先保证你的系统已经安装好了Python 安装virtualenv C:\WINDOWS ...
- php支付宝在线支付接口开发教程【转】
php支付宝在线支付接口开发教程 这篇文章主要为大家详细介绍了php支付宝在线支付接口开发教程,具有一定的参考价值,感兴趣的小伙伴们可以参考一下 1.什么是第三方支付 所谓第三方支付,就是一些和各 ...
- ASP.NET MVC Filters 4种默认过滤器的使用【附示例】 数据库常见死锁原因及处理 .NET源码中的链表 多线程下C#如何保证线程安全? .net实现支付宝在线支付 彻头彻尾理解单例模式与多线程 App.Config详解及读写操作 判断客户端是iOS还是Android,判断是不是在微信浏览器打开
ASP.NET MVC Filters 4种默认过滤器的使用[附示例] 过滤器(Filters)的出现使得我们可以在ASP.NET MVC程序里更好的控制浏览器请求过来的URL,不是每个请求都会响 ...
- php实现支付宝在线支付和扫码支付demo
### php实现支付宝在线支付和扫码支付demo 背景:在做一个公众号时增加了h5端,需要接入支付,非微信环境,选择了支付宝,以下简单记录下实现过程,并做了简单的封装,拿来即可使用,注意:本项目只是 ...
- Python实现支付宝在线支付
windows系统安装Python虚拟环境 首先保证你的系统已经安装好了Python 安装virtualenv C:\WINDOWS\system32>pip3 install virtuale ...
- .net实现支付宝在线支付
流程参考<实物商品交易服务集成技术文档2.0.pdf>网关地址http://paytest.rupeng.cn/AliPay/PayGate.ashx 网关参数说明:partner:商户编 ...
- 调用支付宝PHP接口API实现在线即时支付功能(UTF-8编码)
这次在项目中要实现订单功能,所以要完成在线支付,在线支付一般有网银支付和第三方支付(支付宝.paypal等)这两种途径,未简单起见,先完成支付宝在线支付功能,由于项目基于Yii框架,且使用UTF-8编 ...
- 微信小程序在线支付功能使用总结
最近需要在微信小程序中用到在线支付功能,于是看了一下官方的文档,发现要在小程序里实现微信支付还是很方便的,如果你以前开发过服务号下的微信支付,那么你会发现其实小程序里的微信支付和服务号里的开发过程如出 ...
- 支付宝电脑支付沙箱配置(JAVA)
支付宝电脑支付API地址:https://docs.open.alipay.com/270/105899/.支付宝提供了沙箱环境提供测试,具体配置步骤如下 1.先下载测试DEMO工程 下载地址:htt ...
随机推荐
- Entity Framework 之存储过程篇
最近几天在搞CRUD,使用的是EF这个ORM,最近的项目中上了存储过程,就把在开发中的经验分享出来!我们先创建一个最基本的存储过程,脚本如下,这是一个不带参数的存储过程,我们从最简单的往上走! cre ...
- Java设计模式系列-抽象工厂模式
原创文章,转载请标注出处:https://www.cnblogs.com/V1haoge/p/10755412.html 一.概述 抽象工厂模式是对工厂方法模式的再升级,但是二者面对的场景稍显差别. ...
- 从B站的代码泄露事件中,我们能学到些什么?
先声明一下,本文不聊ISSUE中的七七八八,也不聊代码是否写的好,更不聊是不是跟蔡徐坤有关之类的吃瓜内容.仅站在技术人的角度,从这次的代码泄露事件,聊聊在代码的安全管理上,通常都需要做哪些事来预防此类 ...
- 记一个 DataBindings遇到的坑,当ComboBox同时绑定DataSource与DataBindings的时候,绑定的元素一定要同名
下面的两个member1 一定要一样才行,不然会导致绑定异常 comboBox1.DisplayMember = "member1"; comboBox1.DataBindings ...
- Scss预处理器的使用总结
变量 .嵌套.Mixin混合.function函数.插值 变量及文件导入 通过$定义变量 $white:#fff; $black:#000; 变量引用 .containner{ color:$blac ...
- [SpringBoot guides系列翻译]调用RESTfulWebService
原文 参考链接 CommandLineRunner Bean 翻译如何调用RESTful WebService 这节将演示如何在SpringBoot里面调用RESTful的WebService. 构建 ...
- TensorFlow tutorial
代码示例来自https://github.com/aymericdamien/TensorFlow-Examples tensorflow先定义运算图,在run的时候才会进行真正的运算. run之前需 ...
- 将Xml文件递归加载到TreeView中
#region [通过XDocument的方式将Xml文件递归到TreeView控件中] //读取Xml文件(XDocument) //1.加载Xml文件 XDocument document=XD ...
- git status 显示中文乱码
场景 在使用git命令行查看当前 状态时, git status 显示中文文件乱码: 解决 修改git配置, git config --global core.quotepath false
- 基于windows环境的Flask网站搭建(mysql + conda + redis)
1下载mysql-installer-community-5.7.24.0.msi (https://dev.mysql.com/downloads/windows/installer/8.0.htm ...