Django调用支付宝接口代码实例详解


Posted in Python onApril 04, 2020

支付宝支付

正式环境:用营业执照,申请商户号,appid

测试环境:沙箱环境:https://openhome.alipay.com/platform/appDaily.htm?tab=info

支付宝提供接口:给商户使用,收钱

  • -Java,php,C#的demo,没有python的demo
  • -git有人封装了
  • -需要安装模块:pip3 install
  • -应用私钥---自己保存,一定不能丢
  • -应用公钥---给别人用
  • -支付宝公钥---支付宝用的
  • -生成公钥私钥:https://docs.open.alipay.com/291/105971
  • -把应用公钥配置在支付宝上:应用公钥,配置完成以后,支付宝自动生成一个支付宝公钥
  • -在程序中:配置应用私钥,支付宝公钥
  • -如果支付成功,支付宝会回调,但是如果你的服务器挂掉了怎么办?
  • -支付宝24小时以内不定时再给你发,你修改掉订单状态即可
  • -支付成功,支付宝会有一个get回调,一个post回调:修改订单状态

支付宝接口

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)

视图函数

from django.shortcuts import render, redirect, HttpResponse
from utils.pay import AliPay
import json
import time
def ali():
  # 沙箱环境地址:https://openhome.alipay.com/platform/appDaily.htm?tab=info
  app_id = "2016092000554611"
  # 支付宝收到用户的支付,会向商户发两个请求,一个get请求,一个post请求
  # POST请求,用于最后的检测
  notify_url = "http://42.56.89.12:80/page2/"
  # GET请求,用于页面的跳转展示
  return_url = "http://42.56.89.12:80/page2/"
  merchant_private_key_path = "keys/app_private_2048.txt"
  alipay_public_key_path = "keys/alipay_public_2048.txt"
  # 生成一个AliPay的对象
  alipay = AliPay(
    appid=app_id,
    app_notify_url=notify_url,
    return_url=return_url,
    app_private_key_path=merchant_private_key_path,
    alipay_public_key_path=alipay_public_key_path, # 支付宝的公钥,验证支付宝回传消息使用,不是你自己的公钥
    debug=True, # 默认False,
  )
  return alipay


def page1(request):
  if request.method == "GET":

    return render(request, 'page1.html')
  else:
    money = float(request.POST.get('money'))
    # 生成一个对象
    alipay = ali()
    # 生成支付的url
    # 对象调用direct_pay
    query_params = alipay.direct_pay(
      subject="充气娃娃", # 商品简单描述
      out_trade_no="x2" + str(time.time()), # 商户订单号
      total_amount=money, # 交易金额(单位: 元 保留俩位小数)
    )

    pay_url = "https://openapi.alipaydev.com/gateway.do?{}".format(query_params)
    print(pay_url)
    # 朝这个地址发get请求
    return redirect(pay_url)


def page2(request):
  alipay = ali()
  if request.method == "POST":
    # 检测是否支付成功
    # 去请求体中获取所有返回的数据:状态/订单号
    from urllib.parse import parse_qs
    body_str = request.body.decode('utf-8')
    print(body_str)

    post_data = parse_qs(body_str)
    print('支付宝给我的数据:::---------',post_data)
    post_dict = {}
    for k, v in post_data.items():
      post_dict[k] = v[0]
    print('转完之后的字典',post_dict)

    sign = post_dict.pop('sign', None)
    status = alipay.verify(post_dict, sign)
    print('POST验证', status)
    return HttpResponse('POST返回')

  else:
    params = request.GET.dict()
    sign = params.pop('sign', None)
    status = alipay.verify(params, sign)
    print('GET验证', status)
    return HttpResponse('支付成功')

以上就是本文的全部内容,希望对大家的学习有所帮助,也希望大家多多支持三水点靠木。

Python 相关文章推荐
python抓取网页时字符集转换问题处理方案分享
Jun 19 Python
Python的Flask框架中实现登录用户的个人资料和头像的教程
Apr 20 Python
将Emacs打造成强大的Python代码编辑工具
Nov 20 Python
Linux RedHat下安装Python2.7开发环境
May 20 Python
浅析Python装饰器以及装饰器模式
May 28 Python
Python循环结构的应用场景详解
Jul 11 Python
Python3 pandas 操作列表实例详解
Sep 23 Python
Spring实战之使用util:命名空间简化配置操作示例
Dec 09 Python
解决pyCharm中 module 调用失败的问题
Feb 12 Python
python 如何将office文件转换为PDF
Sep 22 Python
解决python 输出到csv 出现多空行的情况
Mar 24 Python
python ansible自动化运维工具执行流程
Jun 24 Python
基于python检查SSL证书到期情况代码实例
Apr 04 #Python
python zip,lambda,map函数代码实例
Apr 04 #Python
Python关键字及可变参数*args,**kw原理解析
Apr 04 #Python
150行Python代码实现带界面的数独游戏
Apr 04 #Python
Python decorator拦截器代码实例解析
Apr 04 #Python
浅谈Python中os模块及shutil模块的常规操作
Apr 03 #Python
Python实现多线程下载脚本的示例代码
Apr 03 #Python
You might like
WINDOWS 2000下使用ISAPI方式安装PHP
2006/09/05 PHP
PHP中调用JAVA
2006/10/09 PHP
php 获取一个月第一天与最后一天的代码
2010/05/16 PHP
PHP预定义超全局数组变量小结
2018/08/20 PHP
javaScript 读取和设置文档元素的样式属性
2009/04/14 Javascript
分享27款非常棒的jQuery 表单插件
2011/03/28 Javascript
超漂亮的jQuery图片轮播特效
2015/11/24 Javascript
jQuery+PHP实现微信转盘抽奖功能的方法
2016/05/25 Javascript
jQuery animate easing使用方法图文详解
2016/06/17 Javascript
Javascript动画效果(2)
2016/10/11 Javascript
微信小程序框架wepy之动态控制类名
2018/09/14 Javascript
详解Vue之父子组件传值
2019/04/01 Javascript
详解vue beforeRouteEnter 异步获取数据给实例问题
2019/08/09 Javascript
微信小程序激励式视频广告组件使用详解
2019/12/06 Javascript
[02:45]DOTA2英雄敌法师基础教程
2013/11/25 DOTA
[51:26]VP vs VG 2018国际邀请赛小组赛BO2 第二场 8.19
2018/08/21 DOTA
[00:18]天涯墨客三技能展示
2018/08/25 DOTA
python的dataframe和matrix的互换方法
2018/04/11 Python
浅谈pyqt5在QMainWindow中布局的问题
2019/06/21 Python
python opencv 批量改变图片的尺寸大小的方法
2019/06/28 Python
Django 实现图片上传和显示过程详解
2019/07/18 Python
tensorflow2.0与tensorflow1.0的性能区别介绍
2020/02/07 Python
python zip,lambda,map函数代码实例
2020/04/04 Python
Goodee官方商店:迷你投影仪
2021/03/15 全球购物
Deichmann英国:德国鞋类零售商
2021/01/30 全球购物
电子商务专业个人的自我评价
2013/11/19 职场文书
国际贸易毕业生求职信范文
2014/02/21 职场文书
房屋租赁协议书(标准版)
2014/10/02 职场文书
安阳殷墟导游词
2015/02/10 职场文书
2015年小学英语教师工作总结
2015/05/12 职场文书
常住证明范本
2015/06/23 职场文书
防震减灾主题班会
2015/08/14 职场文书
销售口号霸气押韵
2015/12/24 职场文书
浅谈如何提高PHP代码的质量
2021/05/28 PHP
Java反应式框架Reactor中的Mono和Flux
2021/07/25 Java/Android
Python中的socket网络模块介绍
2022/07/23 Python