vue+drf没公网ip接入支付宝功能 - gmlgxx
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