安装python-alipay-sdk
pip install python-alipay-sdk --upgrade
配置
视图函数orders/views.py
# 订单支付 # /order/pay from alipay import AliPay, ISVAliPay import os from django.conf import settings class OrderPayView(View): def post(self, request): \'\'\'支付页面\'\'\' # 判断用户是否登录 user = request.user if not user.is_authenticated(): return JsonResponse({\'res\':0, \'errmsg\':\'用户尚未登录\'}) # 接收订单id order_id = request.POST.get(\'order_id\') # 校验订单id if not order_id: return JsonResponse({\'res\':1, \'errmsg\':\'无效的订单id\'}) # 查询订单信息 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\':\'订单错误\'}) # 业务处理 使用python sdk调用支付宝的支付接口 # 支付宝信息 不能放在settings里 会报错 alipay = AliPay( appid="2016101200665304", app_notify_url=None, # 默认回调url 如果为空的话不能用\'\' 要用None # 个人私钥 app_private_key_string=os.path.join(settings.BASE_DIR, \'apps/orders/app_private_key.pem\'), # 支付宝的公钥,验证支付宝回传消息使用,不是你自己的公钥, alipay_public_key_string=os.path.join(settings.BASE_DIR, \'apps/orders/alipay_public_key.pem\'), # 加密方式 sign_type="RSA2", # RSA 或者 RSA2 # 沙箱是True 正式环境是False debug=True # 默认False ) # 调用支付接口 # 电脑网站支付,需要跳转到https://openapi.alipay.com/gateway.do? + order_string 实际地址 # 沙箱地址 https://openapi.alipaydev.com/gateway.do? + order_string 沙箱地址在alipay后面加上dev total_price = order.total_price + order.transit_price # Decimal order_string = alipay.api_alipay_trade_page_pay( out_trade_no=order_id, # 订单id total_amount=str(total_price), # 支付总金额 因为Decimal格式不能序列化 所以先转成字符串 subject=\'天天生鲜%s\'%order_id, return_url=None, notify_url=None # 可选, 不填则使用默认notify url ) # 返回应答 pay_url = \'https://openapi.alipaydev.com/gateway.do?\' + order_string return JsonResponse({\'res\':3, \'pay_url\':pay_url})
配置路由urls.py
from django.conf.urls import url from orders.views import OrderPlaceView, OrderCommitView, OrderPayView urlpatterns = [ url(r\'^place$\', OrderPlaceView.as_view(), name=\'place\'), # 提交订单页面 url(r\'^commit$\', OrderCommitView.as_view(), name=\'commit\'), # 提交订单处理 url(r\'^pay$\', OrderPayView.as_view(), name=\'pay\'), # 订单支付 ]
用户订单页面user_center_order.html
{% block bottomfiles %} <script src="{% static \'js/jquery-1.12.4.min.js\' %}"></script> <script> $(\'.oper_btn\').each(function(){ //获取支付状态 status = $(this).attr(\'status\') if (status == 1){ $(this).text(\'去付款\') }else if (status == 4){ $(this).text(\'去评价\') }else if (status == 5){ $(this).text(\'已完成\') } }) $(\'.oper_btn\').click(function () { // 获取status status = $(this).attr(\'status\') // 获取订单id order_id = $(this).attr(\'order_id\') console.log(status) if (status == 1){ // 进行支付 csrf = $(\'input[name="csrfmiddlewaretoken"]\').val() // 组织参数 params = {\'order_id\':order_id, \'csrfmiddlewaretoken\':csrf} // 发起ajax post请求,访问/order/pay, 传递参数:order_id $.post(\'/order/pay\', params, function (data) { if (data.res == 3){ // 引导用户到支付页面 window.open(data.pay_url) } else{ alert(data.errmsg) } }) } else if (status == 4){ // 其他情况 // 跳转到评价页面 location.href = \'/order/comment/\'+order_id } }) </script> {% endblock bottomfiles %}
点击去付款,报错
ValueError at /order/pay
RSA key format is not supported
Request Method: POST
Request URL: http://192.168.199.130:8000/order/pay
Django Version: 1.8.2
Python Executable: /home/python/.virtualenvs/bj19/bin/python
Python Version: 3.5.2
Python Path: [\'/home/python/bj19/ttsx/dailyfresh/apps\', \'/home/python/bj19/ttsx/dailyfresh\', \'/home/python/.virtualenvs/bj19/lib/python35.zip\', \'/home/python/.virtualenvs/bj19/lib/python3.5\', \'/home/python/.virtualenvs/bj19/lib/python3.5/plat-x86_64-linux-gnu\', \'/home/python/.virtualenvs/bj19/lib/python3.5/lib-dynload\', \'/usr/lib/python3.5\', \'/usr/lib/python3.5/plat-x86_64-linux-gnu\', \'/home/python/.virtualenvs/bj19/lib/python3.5/site-packages\', \'/home/python/bj19/ttsx/dailyfresh\']
Server time: 星期四, 17 åæœˆ 2019 15:21:03 +0800
Installed Applications:
(\'django.contrib.admin\',
\'django.contrib.auth\',
\'django.contrib.contenttypes\',
\'django.contrib.sessions\',
\'django.contrib.messages\',
\'django.contrib.staticfiles\',
\'tinymce\',
\'user\',
\'cart\',
\'goods\',
\'orders\',
\'haystack\')
Installed Middleware:
(\'django.contrib.sessions.middleware.SessionMiddleware\',
\'django.middleware.common.CommonMiddleware\',
\'django.middleware.csrf.CsrfViewMiddleware\',
\'django.contrib.auth.middleware.AuthenticationMiddleware\',
\'django.contrib.auth.middleware.SessionAuthenticationMiddleware\',
\'django.contrib.messages.middleware.MessageMiddleware\',
\'django.middleware.clickjacking.XFrameOptionsMiddleware\',
\'django.middleware.security.SecurityMiddleware\')
Traceback:
File "/home/python/.virtualenvs/bj19/lib/python3.5/site-packages/django/core/handlers/base.py" in get_response
132. response = wrapped_callback(request, *callback_args, **callback_kwargs)
File "/home/python/.virtualenvs/bj19/lib/python3.5/site-packages/django/views/generic/base.py" in view
71. return self.dispatch(request, *args, **kwargs)
File "/home/python/.virtualenvs/bj19/lib/python3.5/site-packages/django/views/generic/base.py" in dispatch
89. return handler(request, *args, **kwargs)
File "/home/python/bj19/ttsx/dailyfresh/apps/orders/views.py" in post
374. debug=True # 默认False
File "/home/python/.virtualenvs/bj19/lib/python3.5/site-packages/alipay/__init__.py" in __init__
81. self._load_key()
File "/home/python/.virtualenvs/bj19/lib/python3.5/site-packages/alipay/__init__.py" in _load_key
89. self._app_private_key = RSA.importKey(content)
File "/home/python/.virtualenvs/bj19/lib/python3.5/site-packages/Cryptodome/PublicKey/RSA.py" in import_key
754. raise ValueError("RSA key format is not supported")
Exception Type: ValueError at /order/pay
Exception Value: RSA key format is not supported
Request information:
GET: No GET data
查找原因 视图函数中Alipay{}中
alipay = AliPay( appid="2016101200665304", app_notify_url=None, # 默认回调url 如果为空的话不能用\'\' 要用None # 个人私钥 app_private_key_path=os.path.join(settings.BASE_DIR, \'keys/app_private_key.pem\'), # 此处是路径用path 不是string # 支付宝的公钥,验证支付宝回传消息使用,不是你自己的公钥, alipay_public_key_path=os.path.join(settings.BASE_DIR, \'keys/alipay_public_key.pem\'), # 此处是路径用path 不是string # 加密方式 sign_type="RSA2", # RSA 或者 RSA2 # 沙箱是True 正式环境是False debug=True # 默认False )
OK,解决问题,继续
让网站知道已经支付成功
视图函数views.py中添加支付查询功能
class OrderCheckView(View): def post(self, request): \'\'\'支付查询页面\'\'\' # 判断用户是否登录 user = request.user if not user.is_authenticated(): return JsonResponse({\'res\':0, \'errmsg\':\'用户尚未登录\'}) # 接收订单id order_id = request.POST.get(\'order_id\') # 校验订单id if not order_id: return JsonResponse({\'res\':1, \'errmsg\':\'无效的订单id\'}) # 查询订单信息 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\':\'订单错误\'}) # 业务处理 使用python sdk调用支付宝的支付接口 # 支付宝信息 不能放在settings里 会报错 alipay = AliPay( appid="2016101200665304", app_notify_url=None, # 默认回调url 如果为空的话不能用\'\' 要用None # 个人私钥 app_private_key_path=os.path.join(settings.BASE_DIR, \'keys/app_private_key.pem\'), # 支付宝的公钥,验证支付宝回传消息使用,不是你自己的公钥, alipay_public_key_path=os.path.join(settings.BASE_DIR, \'keys/alipay_public_key.pem\'), # 加密方式 sign_type="RSA2", # RSA 或者 RSA2 # 沙箱是True 正式环境是False debug=True # 默认False ) # 调用支付宝交易查询接口 while True: response = alipay.api_alipay_trade_query(order_id) # response = { # "alipay_trade_query_response": { # "trade_no": "2017032121001004070200176844", # 支付宝交易号 # "code": "10000", # 返回码 # "invoice_amount": "20.00", # "open_id": "20880072506750308812798160715407", # "fund_bill_list": [ # { # "amount": "20.00", # "fund_channel": "ALIPAYACCOUNT" # } # ], # "buyer_logon_id": "csq***@sandbox.com", # "send_pay_date": "2017-03-21 13:29:17", # "receipt_amount": "20.00", # "out_trade_no": "out_trade_no15", # "buyer_pay_amount": "20.00", # "buyer_user_id": "2088102169481075", # "msg": "Success", # "point_amount": "0.00", # "trade_status": "TRADE_SUCCESS", # 交易状态:WAIT_BUYER_PAY(交易创建,等待买家付款)、TRADE_CLOSED(未付款交易超时关闭,或支付完成后全额退款)、TRADE_SUCCESS(交易支付成功)、TRADE_FINISHED(交易结束,不可退款) # "total_amount": "20.00" # }, # "sign": "" # } code = response.get(\'code\') if code == \'10000\' and response.get(\'trade_status\') == \'TRADE_SUCCESS\': # 支付成功 # 获取支付宝交易号 trade_no = response.get(\'trade_no\') # 更新订单状态 order.trade_no = trade_no order.order_status = 4 order.save() # 更新 # 返回结果 return JsonResponse({\'res\':3, \'message\':\'支付成功\'}) elif code ==\'40004\' or (code == \'10000\' and response.get(\'trade_status\') == \'WAIT_BUYER_PAY\'): # 等待买家付款 import time time.sleep(5) continue # 跳过本次循环 重新开始循环 else: # 支付出错 return JsonResponse({\'res\':4, \'errmsg\':\'支付失败\'})
模板中ajax转到查询
{% block bottomfiles %} <script src="{% static \'js/jquery-1.12.4.min.js\' %}"></script> <script> $(\'.oper_btn\').each(function(){ //获取支付状态 status = $(this).attr(\'status\') if (status == 1){ $(this).text(\'去付款\') }else if (status == 4){ $(this).text(\'去评价\') }else if (status == 5){ $(this).text(\'已完成\') } }) $(\'.oper_btn\').click(function () { // 获取status status = $(this).attr(\'status\') // 获取订单id order_id = $(this).attr(\'order_id\') console.log(status) if (status == 1){ // 进行支付 csrf = $(\'input[name="csrfmiddlewaretoken"]\').val() // 组织参数 params = {\'order_id\':order_id, \'csrfmiddlewaretoken\':csrf} // 发起ajax post请求,访问/order/pay, 传递参数:order_id $.post(\'/order/pay\', params, function (data) { if (data.res == 3){ // 引导用户到支付页面 window.open(data.pay_url) // 浏览器访问/order/check, 获取支付交易的结果 // ajax post 传递参数:order_id $.post(\'/order/check\', params, function (data){ if (data.res == 3){ alert(data.message) // 刷新页面 location.reload() } else{ alert(data.errmsg) } }) } else{ alert(data.errmsg) } }) } else if (status == 4){ // 其他情况 // 跳转到评价页面 location.href = \'/order/comment/\'+order_id } }) </script> {% endblock bottomfiles %}