vue+drf没公网ip接入支付宝功能 - gmlgxx

vue

vue+drf没公网ip接入支付宝功能

自己没有公网ip接入支付宝

技术是vue+drf

  • vue–主要看创建订单和修改订单支付状态

    balanceCount () { // 结算

    if(this.addrInfo.length==0){

    alert("请选择收货地址")

    }else{

    createOrder(

    {

    post_script:this.post_script,

    address:this.address,

    signer_name:this.signer_name,

    signer_mobile:this.signer_mobile,

    order_mount:this.totalPrice

    }

    ).then((response)=> {

    alert(\'订单创建成功\');

    window.location.href=response.data.alipay_url;

    updateOrder(

    {

    "order_id": response.data.id

    }

    ).then((response)=>{

    alert("订单修改成功");

    }).catch(function (error) {

    console.log(error);

    });

    }).catch(function (error) {

    console.log(error);

    });

  • api–只看创建订单和修改订单支付状态

    //添加订单

    export const createOrder = params => {return axios.post(`${local_host}/orders/`, params)}

    //订单更新

    export const updateOrder = params => {return axios.post(`${local_host}/check_pay/`, params)}

  • 订单序列化–创建订单时去支付宝支付, 所以在序列化类里要创建个alipay_url

    class OrderSerializer(serializers.ModelSerializer):

    """

    订单信息序列化类

    """

    user = serializers.HiddenField(

    default=serializers.CurrentUserDefault()

    )

    add_time = serializers.DateTimeField(read_only=True, format="%Y-%m-%d %H:%M:%S")

    # read_only只返回不提交

    # write_only只提交不反回

    pay_status = serializers.CharField(read_only=True)

    order_sn = serializers.CharField(read_only=True)

    trade_no = serializers.CharField(read_only=True)

    # order_mount = serializers.FloatField(read_only=True)

    pay_time = serializers.DateTimeField(read_only=True)

    # SerializerMethodField 这是一个只读字段。它通过在附加的序列化器类上调用一个方法来获取其值。它可以用于将任何类型的数据添加到对象的序列化表示中。

    # read_only 只返回不提交

    alipay_url = serializers.SerializerMethodField(read_only=True)

    def get_alipay_url(self, obj):

    alipay = AliPay(

    appid="", # 沙箱appid 或 线上appid

    app_notify_url=None, # 默认回调url 不写的话这里用None

    # os.path.dirname(__file__): 获取当前文件所在目录的路径

    app_private_key_path=os.path.join(os.path.dirname(__file__), "keys/app_private_key.pem"), # 私钥

    alipay_public_key_path=os.path.join(os.path.dirname(__file__), "keys/alipay_public_key.pem"),

    # 支付宝的公钥,验证支付宝回传消息使用,不是你自己的公钥,

    sign_type="RSA2", # RSA 或者 RSA2

    debug=True # 默认False 沙箱环境把这里设置为True

    )

    url = alipay.api_alipay_trade_page_pay(

    out_trade_no=obj.order_sn, # 订单id

    total_amount=str(obj.order_mount), # 支付总金额(这里用str 它内部自动将它转换成json)

    subject=obj.order_sn, # 订单标题

    )

    return \'https://openapi.alipaydev.com/gateway.do?\' + url

    def generate_order_sn(self):

    """

    生成订单号

    :return:

    """

    from random import Random

    random_ins = Random()

    # 当前时间+userid+随机数

    # 当前时间并且格式化time.strftime("%Y%m%d%H%M%S")

    # self.request.user.id当前用户的id

    # random_ins.randint(10, 99)生成两位的随机数

    order_sn = "%s%s%s" % (time.strftime("%Y%m%d%H%M%S"), self.context["request"].user.id, random_ins.randint(10, 99))

    return order_sn

    def validate(self, attrs):

    print("attrs", attrs)

    attrs["order_sn"] = self.generate_order_sn()

    return attrs

    class Meta:

    model = OrderInfo

    fields = "__all__"

  • 订单详情序列化–订单的详情页面点击去支付, 所以在序列化类里要创建个alipay_url

    class OrderDetailSerializer(serializers.ModelSerializer):

    """

    订单详情序列化类

    """

    goods = OrderGoodsSerializer(many=True)

    # SerializerMethodField 这是一个只读字段。它通过在附加的序列化器类上调用一个方法来获取其值。它可以用于将任何类型的数据添加到对象的序列化表示中。

    # read_only 只返回不提交

    alipay_url = serializers.SerializerMethodField(read_only=True)

    def get_alipay_url(self, obj):

    alipay = AliPay(

    appid="", # 沙箱appid 或 线上appid

    app_notify_url=None, # 默认回调url 不写的话这里用None

    # os.path.dirname(__file__): 获取当前文件所在目录的路径

    app_private_key_path=os.path.join(os.path.dirname(__file__), "keys/app_private_key.pem"), # 私钥

    alipay_public_key_path=os.path.join(os.path.dirname(__file__), "keys/alipay_public_key.pem"),

    # 支付宝的公钥,验证支付宝回传消息使用,不是你自己的公钥,

    sign_type="RSA2", # RSA 或者 RSA2

    debug=True # 默认False 沙箱环境把这里设置为True

    )

    url = alipay.api_alipay_trade_page_pay(

    out_trade_no=obj.order_sn, # 订单id

    total_amount=str(obj.order_mount), # 支付总金额(这里用str 它内部自动将它转换成json)

    subject=obj.order_sn, # 订单标题

    )

    return \'https://openapi.alipaydev.com/gateway.do?\' + url

    class Meta:

    model = OrderInfo

    fields = "__all__"

  • view–订单

    class OrderViewSet(mixins.ListModelMixin, mixins.RetrieveModelMixin, mixins.DestroyModelMixin, mixins.CreateModelMixin, viewsets.GenericViewSet):

    """

    订单管理

    create:

    创建订单

    list:

    获取订单信息

    delete:

    取消订单

    retrieve:

    查看订单详细信息

    """

    # 动态指定序列化类

    def get_serializer_class(self):

    if self.action == "retrieve":

    return OrderDetailSerializer

    return OrderSerializer

    # IsAuthenticated指定权限, 用户登入才能访问

    # IsOwnerOrReadOnly总是允许GET、HEAD或OPTIONS请求, 其他请求判断当前操作的数据它的user是否为当前用户

    permission_classes = (IsAuthenticated, IsOwnerOrReadOnly)

    # json token的验证 局部大于全局, 就算你在全局设置过, 但是你只要在这里加上authentication_classes 就会替换全局设置

    authentication_classes = (JSONWebTokenAuthentication, SessionAuthentication)

    def get_queryset(self):

    return OrderInfo.objects.filter(user=self.request.user)

    def perform_create(self, serializer):

    """

    保存序列化信息

    :param serializer: 序列化类

    :return: 序列化关联的model的实例

    """

    # 想在保存之前做点操作, 就重写perform_create方法

    # 想在创建时做点操作, 就重写create方法

    order = serializer.save()

    # 1. 把购物车信息保存到OrderGoods模型类里面

    shop_carts = ShoppingCart.objects.filter(user=self.request.user)

    for shop_cart in shop_carts:

    order_goods = OrderGoods.objects.create(goods=shop_cart.goods, goods_num=shop_cart.nums, order=order)

    order_goods.save()

    # 2. 清空购物车

    shop_carts.delete()

    # 3. 返回订单信息

    return order

  • view-checkpay

    class CheckPayView(APIView):

    def post(self, request):

    # 业务处理:使用python SDK调用支付宝的支付接口

    # 初始化

    order_id = request.data.get("order_id", None)

    try:

    order = OrderInfo.objects.get(id=order_id)

    except OrderInfo.DoesNotExist:

    return Response({"order": "无效id"}, status=status.HTTP_404_NOT_FOUND)

    alipay = AliPay(

    appid="2016092500596768", # 使用支付宝沙箱的id(你有实际的id就用实际的)

    app_notify_url=None, # 默认回调url

    app_private_key_path=os.path.join(os.path.dirname(__file__), "keys/app_private_key.pem"), # 应用私钥路径

    # 支付宝的公钥,验证支付宝回传消息使用,不是你自己的公钥,

    alipay_public_key_path=os.path.join(os.path.dirname(__file__), "keys/alipay_public_key.pem"), # 支付宝公钥路径

    sign_type="RSA2", # RSA 或者 RSA2

    debug=True # 默认False(这里用的沙箱所以是True 实际开发是False)

    )

    # 调用支付宝的交易查询接口

    while True:

    response = alipay.api_alipay_trade_query(order.order_sn)

    # 返回的response就是这样的一个字典

    # 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", # 支付结果

    # "total_amount": "20.00"

    # }

    # response里的 code是10000(表示调用成功) 20000(表示不成功) 20001(授权权限不足) 40001(缺少必要的参数) 40002(非法参数)

    # 40004(业务处理失败) 40006(权限不足)

    # response里的 trade_status值为TRADE_SUCCESS(交易支付成功) WAIT_BUYER_PAY(交易创建,等待买家付款)、

    # TRADE_CLOSED(未付款交易超时关闭,或支付完成后全额退款)、TRADE_FINISHED(交易结束,不可退款)

    code = response.get(\'code\')

    trade_status = response.get(\'trade_status\')

    if code == \'10000\' and trade_status == \'TRADE_SUCCESS\':

    # 支付成功

    # 获取支付宝交易号

    trade_no = response.get(\'trade_no\')

    # 更新订单的状态

    order.trade_no = trade_no

    order.pay_time = datetime.now()

    order.pay_status = "success"

    order.save()

    # 返回结果

    from django.shortcuts import redirect

    response = redirect("index")

    # 设置cookie 最长时间为2秒

    response.set_cookie("nextPath", "pay", max_age=2)

    return Response("success")

    elif code == \'40004\' or (code == \'10000\' and trade_status == \'WAIT_BUYER_PAY\'):

    # 等待买家付款

    # 业务处理失败, 可能一会就会成功

    import time

    time.sleep(5)

    continue

    else:

    return Response("failure")

  • url

    from rest_framework.routers import DefaultRouter

    from trade.views import OrderViewSet, CheckPayView

    # 生成一个注册器实例对象

    router = DefaultRouter()

    # 订单

    router.register(r"orders", OrderViewSet, base_name="orders")

    urlpatterns = [

    # 自动生成url

    url(r"^", include(router.urls)),

    url(r"^check_pay/$", CheckPayView.as_view(), name="check_pay"),

    ]

  • 效果图

posted on

2019-09-30 22:29 

gmlgxx 

阅读(31) 

评论(0) 

编辑 

收藏 

举报

以上是 vue+drf没公网ip接入支付宝功能 - gmlgxx 的全部内容, 来源链接: utcz.com/z/380232.html

回到顶部