09 调用支付宝接口

安装

pip install python-alipay-sdk

  

生成密钥文件

openssl

  

生成私钥

genrsa -out app_private_key.pem 2048

  

ctr + d退出

ls 查看生成的私钥文件

cat app_private_key.pem

生成公钥

rsa -in app_private_key.pem -pubout -out app_public_key.pem

  

可以在另一个终端ls查看

私钥保存在程序中,公钥放到支付宝中

cat app_public_key.pem

把上面的公钥放到支付宝的沙箱应用的查看公钥中,除去上下的修饰

MIIBIjANBgkqhkiG9w0BAQEFAAOCAQ8AMIIBCgKCAQEAtL8j5quexGUn5dGTdO76
vx+yfkpOQFkTymk1FALj0FSWucrM7u8+8O5DJtbRI+Skt9tGRNU/ZjG6IlQUBzmM
xIB3b0I3I5GCg2ZaFWmqblzcqo3RZ9aC+kOX9h3o/xeaq5aemwRsPxezJoFmF38f
6YwR8YIWWnqsFw93MWahbeSt02qnZPwKnq41zUSV/iPogUubLud2D7Dg+cgREfm8
pflbTL4utt41PU7O+tbGUet9fQKpliTESs7Gda/IMZf9KtbBKQCjxiVKiLHcMQje
0FcaaYWtyEebE02E4qIqnHRUklKExj1/mQfXQsum0wO6+EQPuN9VSQUaAMSfqQiq

把家目录中的私钥放到程序中的orders应用中

把支付宝的公钥复制到程序中

在orders应用中新建一个文件alipay_public_key.pem

将公钥的内容复制保存到一个文本文件中(alipay_pubilc_key.pem),注意需要在文本的首尾添加标记位(-----BEGIN PUBLIC KEY-----和-----END PUBLIC KEY-----) ,形如:

-----BEGIN PUBLIC KEY-----
MIIBIjANBgkqhkiG9w0BAQEFAAOCAQ8AMIIBCgKCAQEAzkXJrjPbdu2DdCygEChuLzuBq0Hhvp2SOoe4LzPR0LyKcQF3TM/5O/K5YlNuspeZgMqm+mNLmpp6ahfo6RrMSrnZ9f5jN81mz7ZAIe7PAG0Fj1lTzkBNLu2Ab2NVgkHT9wf/Qgug+Vef4bSVyVdED9cCxsZq76BdSKHKoSufts1YK8QzEg7oX4f/FcRyo1afuqXl2HV+LSTstw0nLq9VkaOawP5bewTg4L7yIIjsb+RLDO7mwTOe3HoGxmWOTU+EIJk2AWqaQWAIGpRQrQZ54T/B8K0wcuGsTt6Ru5Z2XcGvZ6Mk1drQsZ6u1AuOPIvlR7FM8+azGbQmADLevseYOwIDAQAB
-----END PUBLIC KEY-----

用户通过支付宝完成提交订单

支付宝接口文档   https://github.com/fzlee/alipay/blob/master/README.zh-hans.md

前端的页面如下所示:

因为后端要向支付宝发送请求,需要向支付宝传递的参数有

  订单的编号

  订单的金额

所以前端需要向后端传送这两个参数,因为后端可以根据订单的编号找到订单的信息表,所以订单的金额可以不传,只需传送订单的标号即可,

后端会给前端返回一个支付宝的页面地址,可以引导用户在这个页面付款

前端的js代码:

必须是待支付的状态,才会发送请求

    <script type="text/javascript">
        $(‘.oper_btn‘).click(function() {
            var order_id = $(this).attr("order_id");
            var order_status = $(this).attr("order_status");
            order_status = parseInt(order_status);
            if (1 == order_status) {
                // 表示待支付
                var req_data ={
                    order_id:order_id,
                    csrfmiddlewaretoken: "{{ csrf_token }}"
                }
                $.post(‘/orders/pay‘, req_data, function(data){
                    if ( 1 == data.code ) {
                        // 用户未登录
                        location.href = "/users/login";
                    } else if (0 == data.code ) {
                        // 发起支付请求成功,跳转的地址
                        window.open(data.url);
                    } else {
                        alert(data.message);
                    }
                });
            }
        });

 后端视图业务逻辑

用户必须是登陆的状态,通过继承自定义的装饰器

    1 接受前端传送的订单编号

   2 判断编号是否为空

    为空返回缺少订单的编号

     3  通过(订单的编号,用户,支付的方式,支付的状态),获取订单的信息表

       没查到返回订单有误

   下面睡固定的写法

   4  构建alipay支付工具对象(固定)

    

   alipay = AliPay(
            appid=settings.ALIPAY_APPID,  # 沙箱模式中的appid
            app_notify_url=None,  # 默认回调url
            app_private_key_path=os.path.join(settings.BASE_DIR, "apps/orders/app_private_key.pem"),
            alipay_public_key_path=os.path.join(settings.BASE_DIR, "apps/orders/alipay_public_key.pem"),  # 支付宝的公钥,验证支付宝回传消息使用,不是你自己的公钥,
            sign_type="RSA2",  # RSA 或者 RSA2
            debug=True  # 默认False, 沙箱模式配置为true
        )

   

5 借助alipay对象向支付宝发起支付请求 电脑网站支付,需要跳转到https://openapi.alipaydev.com/gateway.do? + order_string (固定)

 order_string = alipay.api_alipay_trade_page_pay(
            out_trade_no=order_id,  # 订单编号
            total_amount=str(order.total_amount),   # 订单金额
            subject="天天生鲜%s" % order_id,   # 订单描述信息
            return_url=None, # 订单成功返回的信息
            notify_url=None  # 可选, 不填则使用默认notify url
        )

 

6返回 电脑网站支付,需要跳转到https://openapi.alipaydev.com/gateway.do? + order_string

在orders.models中的OrderInfo类中添加以下的属性,表示订单的状态

ORDER_STATUS_ENUM = {
        "UNPAID": 1,
        "UNSEND": 2,
        "UNRECEIVED": 3,
        "UNCOMMENT": 4,
        "FINISHED": 5
    }

 

在orders.models中的OrderInfo类中添加以下的属性,表示支付方式的序号

 PAY_METHODS_ENUM = {
        "CASH": 1,
        "ALIPAY": 2
    }

  

在settiing中添加访问支付宝的网址和支付宝的沙箱模式中的id

# 支付宝的网址
ALIPAY_URL = "https://openapi.alipaydev.com/gateway.do"
ALIPAY_APPID = "2016081600258081"

代码如下:

class PayView(LoginRequiredJsonMixin, View):
    """支付宝支付视图"""
    def post(self, request):
        # 订单编号  order_id
        order_id = request.POST.get("order_id")

        if not order_id:
            return JsonResponse({"code": 2, "message": "缺失订单编号"})

        # 获取订单信息
        try:
            order = OrderInfo.objects.get(order_id=order_id, user=request.user,
                                          status=OrderInfo.ORDER_STATUS_ENUM["UNPAID"],
                                          pay_method=OrderInfo.PAY_METHODS_ENUM["ALIPAY"])
        except OrderInfo.DoesNotExist:
            return JsonResponse({"code": 3, "message": "订单信息错误"})

        # 构建alipay支付工具对象
        alipay = AliPay(
            appid=settings.ALIPAY_APPID,  # 沙箱模式中的appid
            app_notify_url=None,  # 默认回调url
            app_private_key_path=os.path.join(settings.BASE_DIR, "apps/orders/app_private_key.pem"),
            alipay_public_key_path=os.path.join(settings.BASE_DIR, "apps/orders/alipay_public_key.pem"),  # 支付宝的公钥,验证支付宝回传消息使用,不是你自己的公钥,
            sign_type="RSA2",  # RSA 或者 RSA2
            debug=True  # 默认False, 沙箱模式配置为true
        )

        # 借助alipay对象,向支付宝发起支付请求
        # 电脑网站支付,需要跳转到https://openapi.alipaydev.com/gateway.do? + order_string
        order_string = alipay.api_alipay_trade_page_pay(
            out_trade_no=order_id,  # 订单编号
            total_amount=str(order.total_amount),   # 订单金额
            subject="天天生鲜%s" % order_id,   # 订单描述信息
            return_url=None,
            notify_url=None  # 可选, 不填则使用默认notify url
        )

        # 返回json数据
        alipay_url = settings.ALIPAY_URL + "?" + order_string
        return JsonResponse({"code": 0, "message": "发起支付成功", "url": alipay_url})

配置url

url(‘^pay$‘, views.PayView.as_view(), name="pay"),

当用户点击待支付按钮,就可以完成支付了

检查支付的结果

这个是没有公网,需要自己去向支付宝发送请求询问支付成功还是失败

前端js的代码如下:

红色区域表示新增的代码 :支付成功重新加载页面,失败显示失败的信息

<script type="text/javascript">   $(‘.oper_btn‘).click(function() {      var order_id = $(this).attr("order_id");      var order_status = $(this).attr("order_status");      order_status = parseInt(order_status);       // 只有待支付的状态才可以点击      if (1 == order_status) {          // 表示待支付               var req_data ={                   order_id:order_id,                   csrfmiddlewaretoken: "{{ csrf_token }}"               }         $.post(‘/orders/pay‘, req_data, function(data){                   if ( 1 == data.code ) {                       // 用户未登录                       location.href = "/users/login";                   } else if (0 == data.code ) {                       // 发起支付请求成功                       window.open(data.url);                       // 向后端发起查询支付状态的请求                       $.get("/orders/check_pay?order_id="+order_id, function (resp_data) {                           if (0 == resp_data) {                               // 支付成功                               location.reload();                           } else {                               alert(resp_data.message);                           }                       });                   } else {                       alert(data.message);                   }         });      } else if (4 == order_status) {         location.href = ("/orders/comment/" + order_id);      }    });</script>

后端视图业务逻辑

支付宝开发者文档 https://openhome.alipay.com/developmentDocument.htm

后端视图的业务逻辑  

  1 用户必须是登陆的状态,

   2 通过get请求的方式接受用户传送过来的订单编号

    如果订单的编号不存在,返回订单信心缺少

   3 通过订单的(编号,用户,交易的状态是否为待支付和支付的方式是否为支付宝),查询对应的订单信息表

    如果不存在,返回订单信息错误

  4 通过whileTrue循环遍历查询用户交易的状态

    如果交易的状态码为10000和交易的状态为TRADE_SUCCESS说明交易成功,把支付宝的交易号保存在订单信息表的trade_id,订单的状态设为待评价,返回给前端

    如果交易的状态码为40004(表示支付宝还没生成订单)或者交易的状态码为10000并且交易的状态为用户待支付(WAIT_BUYER_PAY),延迟10scontinue

    else 返回支付失败

完整的代码如下:

class CheckPayStatusView(LoginRequiredJsonMixin, View):
    """检查支付结果"""
    def get(self, request):
        order_id = request.GET.get("order_id")

        if not order_id:
            return JsonResponse({"code": 2, "message": "缺少订单号"})

        # 获取订单信息
        try:
            order = OrderInfo.objects.get(order_id=order_id, user=request.user,
                                          status=OrderInfo.ORDER_STATUS_ENUM["UNPAID"],
                                          pay_method=OrderInfo.PAY_METHODS_ENUM["ALIPAY"])
        except OrderInfo.DoesNotExist:
            return JsonResponse({"code": 3, "message": "订单信息错误"})

        # 构建alipay支付工具对象
        alipay = AliPay(
            appid=settings.ALIPAY_APPID,  # 沙箱模式中的appid
            app_notify_url=None,  # 默认回调url
            app_private_key_path=os.path.join(settings.BASE_DIR, "apps/orders/app_private_key.pem"),
            alipay_public_key_path=os.path.join(settings.BASE_DIR, "apps/orders/alipay_public_key.pem"),  # 支付宝的公钥,验证支付宝回传消息使用,不是你自己的公钥,
            sign_type="RSA2",  # RSA 或者 RSA2
            debug=True  # 默认False, 沙箱模式配置为true
        )

        # 借助alipay工具查询支付结果
        while True:
            response = alipay.api_alipay_trade_query(order_id)
            code = response.get("code")
            trade_status = response.get("trade_status")
            if code == "10000" and trade_status == "TRADE_SUCCESS":
                # 表示用户支付成功
                order.trade_id = response.get("trade_no") # 支付宝的交易标号
                order.status = OrderInfo.ORDER_STATUS_ENUM["UNCOMMENT"]  # 设置订单状态为待评价
                order.save()
                return JsonResponse({"code": 0, "message": "支付成功"})
            elif code == "40004" or (code == "10000" and trade_status == "WAIT_BUYER_PAY"):
                # 表示支付宝订单还没创建好, 或者用户还未支付
                time.sleep(10)
                continue
            else:
                return JsonResponse({"code": 4, "message": "支付失败"})

配置url路径

url(‘^check_pay$‘, views.CheckPayStatusView.as_view(), name="check_pay"),

  

  

原文地址:https://www.cnblogs.com/aaronthon/p/9347835.html

时间: 2024-11-05 22:52:30

09 调用支付宝接口的相关文章

Android 开发之Android 应用程序如何调用支付宝接口

1.到支付宝官网,下载支付宝集成开发包 由于android设备一般用的都是无线支付,所以我们申请的就是支付宝无线快捷支付接口.下面是申请的地址以及下载接口开发包的网址:https://b.alipay.com/order/productDetail.htm?productId=2014110308141993(如果链接失效,你可以到支付宝官网商家服务模块中找到 快捷支付(无线)这个服务.)  下载集成开发包(http://download.alipay.com/public/api/base/W

调用支付宝接口Android客户端没有支付宝APP的情况下解决无法调用支付宝页面的问题

这几天一直研究支付宝接口调用,因为当前应用中需要调用支付宝接口作移动支付. 遇到一个问题困扰几天,就是当我们的手机端未安装支付宝APP的时候,需要在自己应用中调用支付宝的登陆网页进行支付.我是Android开发,网上有很多小伙伴都遇到了无法调起网页支付宝登陆页面的问题,在此给大家分享一个解决方案,希望能帮助遇到同样问题困扰的小伙伴. 网上也有很多贴,都是说要加入H5PayActivity和AuthActivity的配置来解决,但是并不起作用,我的就是,虽然有跳转的动作,但是直接一个白板页面招呼,

android应用程序如何调用支付宝接口

最近在做一个关于购物商城的项目,项目里面付款这块我选的是调用支付宝的接口,因为用的人比较多. 在网上搜索了以下,有很多这方面的教程,但大部分教程过于陈旧,而且描述的过于简单.而且支付宝提供的接口一直在更新,可能支付宝那边是为了让接口更容易被调用吧,以前有些老的教程稍微跟现在接口有些不能“对号入座”,于是,我决定抽空写一篇关于调用支付宝接口的文章,跟大家分享,让大家以最快的速度掌握如何调用支付宝接口的方法.如果写的不好,请大家多多指教哦. 不多说了,开写. 1,到支付宝官网,下载支付宝集成开发包,

Django 调用支付宝接口

目录 一  支付宝接口 二  视图函数 支付宝支付 正式环境:用营业执照,申请商户号,appid 测试环境:沙箱环境:https://openhome.alipay.com/platform/appDaily.htm?tab=info 支付宝提供接口:给商户使用,收钱 -Java,php,C#的demo,没有python的demo -git有人封装了 -需要安装模块:pip3 install  -应用私钥---自己保存,一定不能丢 -应用公钥---给别人用 -支付宝公钥---支付宝用的 -生成公

【框架】调用支付宝接口支付

第一步,下载工具包 第二步,将下图中的libs.res.src和自己的工程合并 第三步,在下图位置中生成密钥 第四步,修改工程中的密钥,运行即可

通过调用支付宝查询对账单接口返回bill_download_url下载zip,解压缩

通过url下载zip对账单文件,进行解压. 读取压缩文件内容 import java.io.BufferedOutputStream; import java.io.BufferedReader; import java.io.BufferedWriter; import java.io.File; import java.io.FileInputStream; import java.io.FileOutputStream; import java.io.FileWriter; import

ASP.NET实现支付宝接口功能

最近做系统,需要实现在线支付功能,毫不犹豫,选择的是支付宝的接口支付功能.这里我用的是即时到帐的接口,具体实现的步骤如下: 一.下载支付宝接口包 下载地址: https://b.alipay.com/order/productDetail.htm?productId=2012111200373124&tabId=4#ps-tabinfo-hash 具体如何下载,我就不在罗嗦了-- 很多人反映,用支付宝的接口到最后面会出现验证错误.其实,这里需要对接口程序进行一下改造.需要添加几个自定义函数.为了

ThinkPHP实现支付宝接口功能

最近做系统,需要实现在线支付功能,毫不犹豫,选择的是支付宝的接口支付功能.这里我用的是即时到帐的接口,具体实现的步骤如下:一.下载支付宝接口包 下载地址: https://doc.open.alipay.com/doc2/detail?treeId=62&articleId=103566&docType=1 具体如何下载,我就不在罗嗦了-- 很多人反映,用支付宝的接口到最后面会出现验证错误.其实,这里需要对接口程序进行一下改造.需要添加几个自定义函数.为了让大家以后避免出现同样的问题,我把

Thinkphp集成手机支付宝接口功能

最近做微商城,需要实现手机wap支付功能,选择的是支付宝的接口支付功能.这里是我用的是支付宝“手机网站支付”产品(注:该产品要支付宝企业账号才能申请),具体步骤如下: 一.下载支付宝接口包 https://b.alipay.com/order/productDetail.htm?productId=2013080604609688 二.重新整理接口包文件 下载下来的接口包文件有很多语言的源码 注:openssl用来生成公私钥,RSA签名才使用.这里我们用的MD5签名,所有该文件用不到. 我们选择