支付宝支付相关开发

开发支付宝的支付功能

1.首先去开放平台进行注册

这里有一个设置应用公钥:

使用支付宝的密钥生成工具进行密钥生成:

把应用公钥复制到沙箱页面内让支付宝生成一个支付宝公钥:

第二步骤:

使用支付宝的官方提供的SDK进行URL的加密:

这里是从GitHub上面找到的python版本的,支付宝官方没有python版本的。

pay.py

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 urllib.parse import urlparse, parse_qs
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 Crypto.PublicKey import RSA

使用pip安装,这里python3好像做了修改,需要到python的包管理内改一下名字。

pip3 install  pycryptodome

这里这个包本来是小写c开头的,自己改成大写就好了。(具体原因不知道,百度说是3版本改版的原因)

准备工具,已经全部准备就绪,现在就基于Django进行开发支付应用。

首先是在view引入那个上面的加密算法:

然后实例化一个对象,放到函数中进行返回。

def aliPay():
    alipay=AliPay(
        appid="2016092200569287",
        app_notify_url="http://119.27.182.182:8000/update_order/",   #如果支付成功,支付宝会向这个地址发送POST请求,(校验是否支付成功)
        return_url="http:/119.27.182.182:8000/pay_result/",          #如果支付成功,跳转的页面
        app_private_key_path="keys/app_private_2048.txt",    #应用私钥
        alipay_public_key_path="keys/alipay_public_2048.txt",#支付宝公钥
        debug=True   #默认false
    )
    return alipay

在index页面进行输入钱数跳转后:

后台对POST请求进行处理。

def index(request):
    if request.method == "GET":
        return render(request,‘index.html‘)

    #实例化alipay对象
    alipay=aliPay()

    money=float(request.POST.get("price"))
    print(money)
    #价格,购买的商品加密,拼接成URL

    query_params=alipay.direct_pay(
        subject="iPhone XS Max(512GB)",     #商品描述
        out_trade_no="x2"+str(time.time()), #随机生成商户订单号
        total_amount=money,                 #交易金额(单位:元 保留2位小数)
    )

    pay_url="https://openapi.alipaydev.com/gateway.do?{}".format(query_params)
    return redirect(pay_url)  #拼接好跳转到支付宝的支付页面去。

支付宝那么扫码验证成功以后,返回一个数据:

def pay_result(request):
    params=request.GET.dict()
    sign=params.pop(‘sign‘,None)

    alipay = aliPay()
    status=alipay.verify(params,sign)          #进行是否真正支付进行验证
    if status:
        #校验是否是阿里返回的数据,而不是别人伪造的
        return HttpResponse("支付成功")
    else:
        return HttpResponse("支付失败")

拿到这个签名sign,进行校验。

最后就是进行订单状态的修改,成功校验通过以后,把订单改为已支付,然后进行订单修改操作。

from django.views.decorators.csrf import csrf_exempt

@csrf_exempt
def update_order(request):
    ‘‘‘
    支付成功后,支付宝向该地址发送POST请求(用于修改订单状态)
    :param rqeuest:
    :return:
    ‘‘‘
    if request.method==‘POST‘:
        from urllib.parse import parse_qs
        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]
        print(post_dict)

        sign=post_dict.pop(‘sign‘,None)

        alipay = aliPay()

        status=alipay.verify(post_dict,sign)
        if status:
            print(post_dict)
            #返回前更改一下订单状态
            #models.object.filter().update()

            #订单号:
            out_trade_no=post_dict.get("out_trade_no")
            print(out_trade_no)
            #拿到这个订单号对数据库的数据把订单改为已支付。
            return HttpResponse("支付成功!")
        else:
            return HttpResponse("支付失败!")

最后因为这个支付宝校验后要向

 app_notify_url="http://119.27.182.182:8000/update_order/",   #如果支付成功,支付宝会向这个地址发送POST请求,(校验是否支付成功)

这个地址发一个POST请求,所以需要云服务器才能。

部署到云服务器上面:

然后经过一顿部署操作,设置等等运行测试一下。

下面是测试效果:

1.扫码进行支付:

 2.支付成功后的页面

这样的话验证成功他们会向我的IP发一个POST请求,这里拿到这个POST请求,验证通过以后,可以打印一下。

这里会有商品信息,会有价格,订单号等等,拿到这些信息对商品的订单状态进行更新!

这里扫码支付使用的是沙箱的APP,可以在蚂蚁金服那里下载:

至此支付宝的所有接口开发全部完毕!

最后附上所有的源码:

views.py

from django.shortcuts import render,redirect,HttpResponse
from utils.pay import AliPay
import time
# Create your views here.

def aliPay():
    alipay=AliPay(
        appid="2016092200569287",
        app_notify_url="http://119.27.182.182:8000/update_order/",   #如果支付成功,支付宝会向这个地址发送POST请求,(校验是否支付成功)
        return_url="http:/119.27.182.182:8000/pay_result/",       #如果支付成功,跳转的页面
        app_private_key_path="keys/app_private_2048.txt",    #应用私钥
        alipay_public_key_path="keys/alipay_public_2048.txt",#支付宝公钥
        debug=True   #默认false
    )
    return alipay

def index(request):
    if request.method == "GET":
        return render(request,‘index.html‘)

    #实例化alipay对象
    alipay=aliPay()

    money=float(request.POST.get("price"))
    print(money)
    #价格,购买的商品加密,拼接成URL

    query_params=alipay.direct_pay(
        subject="iPhone XS Max(512GB)",     #商品描述
        out_trade_no="x2"+str(time.time()), #随机生成商户订单号
        total_amount=money,                 #交易金额(单位:元 保留2位小数)
    )

    pay_url="https://openapi.alipaydev.com/gateway.do?{}".format(query_params)
    return redirect(pay_url)

def pay_result(request):
    params=request.GET.dict()
    sign=params.pop(‘sign‘,None)

    alipay = aliPay()
    status=alipay.verify(params,sign)          #进行是否真正支付进行验证
    if status:
        #校验是否是阿里返回的数据,而不是别人伪造的
        return HttpResponse("支付成功")
    else:
        return HttpResponse("支付失败")

from django.views.decorators.csrf import csrf_exempt

@csrf_exempt
def update_order(request):
    ‘‘‘
    支付成功后,支付宝向该地址发送POST请求(用于修改订单状态)
    :param rqeuest:
    :return:
    ‘‘‘
    if request.method==‘POST‘:
        from urllib.parse import parse_qs
        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]
        print(post_dict)

        sign=post_dict.pop(‘sign‘,None)

        alipay = aliPay()

        status=alipay.verify(post_dict,sign)
        if status:
            print(post_dict)
            #返回前更改一下订单状态
            #models.object.filter().update()

            #订单号:
            out_trade_no=post_dict.get("out_trade_no")
            print(out_trade_no)
            #拿到这个订单号对数据库的数据把订单改为已支付。
            return HttpResponse("支付成功!")
        else:
            return HttpResponse("支付失败!")

url.py

from django.contrib import admin
from django.urls import path
from django.conf.urls import url
from app01 import views

urlpatterns = [
    path(‘admin/‘, admin.site.urls),
    url(r‘^index/$‘,views.index),
    url(r‘^pay_result/$‘,views.pay_result),
    url(r‘^update_order/$‘,views.update_order),

]

pay.py

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 urllib.parse import urlparse, parse_qs
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)

最后还有2个密钥文件,是开发平台上面的。

原文地址:https://www.cnblogs.com/geogre123/p/9810144.html

时间: 2024-11-05 17:17:57

支付宝支付相关开发的相关文章

HostwindsVPS购买、支付宝支付相关

前言 我前几天买了Hostwinds的VPS,当时买的时候支付宝支付就出了问题,最近这两天用支付宝支付又出了问题. 所以想记录一下Hostwinds支付宝支付的相关问题及解决方法,顺便也记录一下关于Hostwinds VPS的更多内容. 正文 支付宝支付 我在第一次用支付宝支付(购买VPS)时的操作没有错误,但没有支付成功,最后发现原因是支付宝余额不足-暴露出自己的贫穷 解决方法:支付宝充钱就行,然后再支付 当时是看了这篇文章才知道的 https://www.vps234.com/usa-vps

支付宝支付接口开发

1.简单点说就是调用支付宝那边的接口方法,然后传递数据过去,之后会返回一个是否成功的值,然后你拿到之后判断就好了 2.首先你得有淘宝的商铺的合作身份ID,和Key,这个key就是你的密钥.当你的表单提交的时候,表单中的参数会根据这个key来md5加密,同明文参数一同发送到支付宝那边的,然后支付宝那边根据你的key(他们是知道你的key的.因为这个key是他们给你的)来再次加密你的明文参数.如果加密后的数据和你一起传递的密文是相同的话则表示数据在传输过程中没有被修改,就会处理你的请求...处理完之

对接支付宝支付接口开发详细步骤(证书签名方式)

对接支付宝支付接口,官方文档已经写的很清楚了,但是也有很多像我一样的小白,第一次对接支付宝支付接口,会有些迷茫,所以我在此写下这篇文章,给我和我一样的同学,一点思路吧.需要思路的可以私聊我 两大支付平台感觉都有坑人之处吧(终归是学艺不精,哈哈哈哈!!) 不过支付宝相做的较好的一点是有技术和你在线调试,这就很舒服,哈哈. 寻找技术地址:支付宝开放平台 - 开发者中心 - 网页&移动应用 - 右边有个立即咨询 - 智能问答(多发送几次就有技术出来了) 第一步:(先要在支付宝进行操做,拿到我们需要开发

开发支付宝支付用DELPHI实现 RSA签名

近来根据业务需求 在ERP中集成了微信支付,支付宝支付,开发支付宝支付时最大的障碍就是RSA签名,找了很多资料,最终用 下了个libeay32.pas  根据网上资料最终解决了问题 [delphi] view plain copy function LoadPrivateKey(filename:string ): PEVP_PKEY; var bp : PBIO  ; A,pkey :PEVP_PKEY ; begin a:=nil; bp := BIO_new(BIO_s_file()) ;

支付宝支付开发—当面付条码支付和扫码支付

关键字:支付宝 当面付 条码支付 扫码支付 二维码支付 订单查询 退款作者:方倍工作室 本文介绍支付宝中当面付下属的条码支付.扫码支付.订单查询.退款申请的集成开发过程. 本文分为以下五个部分: 条码支付和扫码支付介绍 申请应用 密钥生成及配置 API及SDK集成 条码支付.扫码支付.订单查询.退款申请 一.条码支付及二维码支付介绍 1. 条码支付 条码支付是支付宝给到线下传统行业的一种收款方式.商家使用扫码枪等条码识别设备扫描用户支付宝钱包上的条码/二维码,完成收款.用户仅需出示付款码,所有收

支付宝支付开发——当面付条码支付和扫码支付

关键字:支付宝 当面付 条码支付 扫码支付 二维码支付 订单查询 退款作者:方倍工作室原文: http://www.cnblogs.com/txw1958/p/alipay-f2fpay.html 本文介绍支付宝中当面付下属的条码支付.扫码支付.订单查询.退款申请的集成开发过程. 本文分为以下五个部分: 条码支付和扫码支付介绍 申请应用 密钥生成及配置 API及SDK集成 条码支付.扫码支付.订单查询.退款申请 注: 支付宝支付开发有一定的门槛,如果您愿意为知识付费来节省您宝贵的时间,请直接见底

iOS开发笔记14:微博/微信登录与分享、微信/支付宝支付

产品中接入了微博/微信的第三方登录分享功能.微信和支付宝的第三方支付功能,之前在开发过程中涉及到这些部分,于是抽空将接入过程梳理了一遍. 1.微博.微信.支付宝SDK相关接入设置 (1)微博SDK SDK下载 设置URL Scheme,用于从第三方应用或浏览器中启动app 将SDK添加到工程中(支持CocoaPods),app启动时(didFinishLaunchingWithOptions)注册appkey 重写AppDelegate 的handleOpenURL和openURL方法,其它引用

支付宝支付开发——当面付

关键字:支付宝 当面付 条码支付 扫码支付 二维码支付 订单查询 退款作者:方倍工作室原文: http://www.cnblogs.com/txw1958/p/alipay-f2fpay.html 本文介绍支付宝中当面付下属的条码支付.扫码支付.订单查询.退款申请的集成开发过程. 本文分为以下五个部分: 条码支付和扫码支付介绍 申请应用 密钥生成及配置 API及SDK集成 条码支付.扫码支付.订单查询.退款申请 一.条码支付及二维码支付介绍 1. 条码支付 条码支付是支付宝给到线下传统行业的一种

IOS开发之支付宝支付

前言:继上次<IOS开发--微信支付>以来,一直没有太多时间,更新总结详细支付这样的长篇大论,很抱歉.今天,推出支付宝支付的详细流程. 1.开始下载和查看支付宝支付的Demo. 我们直接进入支付宝的支付平台参考来进行集成支付宝支付: https://doc.open.alipay.com/doc2/detail.htm?spm=a219a.7629140.0.0.jIUkAQ&treeId=59&articleId=103675&docType=1 集成过程基本上就是按