项目接口总结


支付宝支付
-正式:申请支付宝支付,需要营业执照
-测试:沙箱环境
-appid:
-沙箱帐号,密码,android登录
-数据发送需要加密
-开发程序:(官方提供接口,自己写)
-提供sdk,
-python没有,git上有
-pip3 install pycryptodome

-公钥私钥(RSA加密)
-应用公钥
-应用私钥
-支付宝公钥(填上自己的公钥,会自动生成)
---把应用私钥,和支付宝公钥放上(如果用应用公钥,支付宝回调的状态一直是false)

微信消息推送:
-短信
-邮箱
-微信推送
-公众号(每天只能发一篇文章,不能主动给用户推送,但是可以给用户回复)
-已认证的公众号
-服务号(做支付,关注了服务号,会主动推送)
-已认证的服务号
-企业号(企业里用,企业内部聊天)
-不同号有不同功能:https://mp.weixin.qq.com/wiki?t=resource/res_main&id=mp1433401084
-基于微信认证服务号,主动推送消息
-前提:要关注服务号
-沙箱环境:
-用户唯一id,可以直接发消息
-执行流程
-先有帐号,登录
-一开始微信id为空
-uid唯一标识
-登录成功,关注服务号(从官网下的二维码)
-诱导用户把唯一id存到咱们数据库
-生成url,让微信访问,手动输入麻烦,通过扫描二维码访问
-微信会向我重定向的地址发请求(是否允许获取个人信息),会带着数据回来,但是用户唯一id不在里面
-把用户的uid带回来
-带着code去微信地址发请求,就会拿到用户唯一id
-***设置,网页授权获取用户基本信息,设置回调地址
-发送消息
-先去获取token,默认有效2小时(放到redis中,超时时间2小时)
-朝微信固定地址发送post请求
-可以发送模版消息(自定义模版)

购物车:
-往后台传输数据(价格策略id,课程id)
-{"course_id":"1","policy_id":"3"}
-为什么要放到redis
-存储数据方式:(key值为:shopping_card_userid)
shopping_card_userid={
"1":{
"title":"Django从入门到放弃",
"img":"django.png",
"default_policy":"3",
"policy":{
"1":{
"period":3,
"period_display":"3天",
"price":200
},
"3":{
"period":60,
"period_display":"2个月",
"price":1000
},
"4":{
"period":30,
"period_display":"1个月",
"price":500
}
}
},
"2":{
"title":"Git操作",
"img":"git.png",
"default_policy":"2",
"policy":{
"2":{
"period":30,
"period_display":"1个月",
"price":60
},
"5":{
"period":1,
"period_display":"1天",
"price":0
},
"6":{
"period":90,
"period_display":"3个月",
"price":50
}
}
}
}
-校验规则:
-校验课程是否存在
-校验价格策略是否合法
-把价格策略拼成一个字典,直接用id in 字典,判断价格策略是否合法
-取出原来购物车的商品,更新,或者新增
-传过来的id 在购物车字典中,只要修改默认价格策略即可
-传过来的id不在购物车字典中,直接新增
-存到redis


-购物车整个逻辑:
-(1)添加购物车 ----post:{"course_id":"1","policy_id":"1"}
-1 校验课程是否存在
-2 获取所有价格策略
-3 从redis中取出当前登录用户的购物车
shoping_card_byte=self.conn.get(redis_str)
shoping_card_dic=json.loads(shoping_card_byte) if shoping_card_byte else {}
-4 循环价格策略组装成以下形式
{
"period":3,
"period_display":"3天",
"price":200
}
polic_dict[str(item.id)] = {
"period": item.valid_period,
"period_display": item.get_valid_period_display(),
"price": item.price,
}
-5 校验价格策略是否是该课程的价格策略(判断传入的policy_id是否在上面的字典中)
-6 价格策略合法,构造出购物车字典(如果购物车中有该课程,修改的是默认策略)
shoping_card_dic[course_id] = {
'title': course.name,
'img': course.course_img,
'default_policy': policy_id,
'policy': polic_dict
}
-7 转成json,存入redis name值为:'shopping_%s' % (request.user.id,)
-(2)修改购物车中某个课程价格策略---patch:{"course_id":"1","policy_id":"1"}
-1 从redis中取出购物车
-2 判断价格策略是否合法(也就是是否在当前课程的policy字典中)
-3 在的话,直接修改default_policy为传入的policy_id
shopping_card[course_id]['default_policy'] = policy_id
-4 把数据写回redis
self.conn.set(redis_str, json.dumps(shopping_card))
-(3)删除购物车中课程---delete:{"course_id":"1"}
-1 从redis中取出购物车
-2 从购物车中pop掉当前传入的course_id
-3 把数据写会redis
-(4)获取购物车---get
-1 从redis中取出购物车
-2 把购物车放到res.data 中返回


优惠券表介绍:

结算中心:
-请求格式:
{"course_list":[{"course_id":"1","policy_id":"1"},{"course_id":"2","policy_id":"2"}]}
-存储格式(结算中心和全局优惠券格式):
{
"1":{
"coupon":{
"7":{
"coupon_type":0,
"coupon_display":"立减券",
"money_equivalent_value":10
},
"8":{
"coupon_type":1,
"coupon_display":"满减券",
"money_equivalent_value":10,
"minimum_consume":100
},
"9":{
"coupon_type":2,
"coupon_display":"折扣券",
"off_percent":90
}
},
"title":"Django从入门到放弃",
"img":"django.png",
"default_policy":"3",
"policy":{
"1":{
"period":3,
"period_display":"3天",
"price":200
},
"3":{
"period":60,
"period_display":"2个月",
"price":1000
},
"4":{
"period":30,
"period_display":"1个月",
"price":500
}
}
},
"2":{
"coupon":{

},
"title":"Git操作",
"img":"git.png",
"default_policy":"2",
"policy":{
"2":{
"period":30,
"period_display":"1个月",
"price":60
},
"5":{
"period":1,
"period_display":"1天",
"price":0
},
"6":{
"period":90,
"period_display":"3个月",
"price":50
}
}
}
}
-全局优惠券格式:
{
"coupon":{
"4":{
"coupon_type":1,
"coupon_display":"满减券",
"money_equivalent_value":10,
"minimum_consume":100
},
"5":{
"coupon_type":0,
"coupon_display":"立减券",
"money_equivalent_value":10
},
"6":{
"coupon_type":2,
"coupon_display":"折扣券",
"off_percent":80
}
},
"default_coupon":0
}
-结算中心逻辑分析:
-(1)添加到结算中心--post---{"course_list":[{"course_id":"1","policy_id":"1"},{"course_id":"2","policy_id":"2"}]}
-1 定义结算中心的字典,定义全局优惠券的字典
payment_dict_userid={}
global_coupon_dict = {
"coupon": {},
"default_coupon": 0
}
-2 拿到购物车,循环取出传入的课程id,判断是否在购物车中,不在直接抛异常
-3 构造单个课程详情的字典,把购物车中的当前课程,update到该字典中
course_detail={
'coupon':{}
}
course_detail.update(shopping_cart[course_id])
-4 将该课程详情,加入到结算中心(现在里面没有优惠券相关信息)(为了效率,不在for循环中查询数据库,查出优惠券)
payment_dict_userid[course_id]=course_detail
-5 一次性查出当前用户的所有优惠券信息(用户为当前用户,状态为未使用,优惠券起始时间小于当前时间,优惠券结束时间大于当前时间)
ctime=datetime.datetime.today().strftime('%Y-%m-%d')
print(ctime)
coupon_list=models.CouponRecord.objects.filter(
user=request.user,
status=0,
coupon__valid_begin_date__lte=ctime,
coupon__valid_end_date__gte=ctime,
)
-6 循环所有优惠券
-7 构造出单个优惠券的空字典,拿到优惠券类型(1立减 2 满减 3折扣),拿到优惠券id,拿到该优惠券绑定的课程id(有可能为空)
coupon_detail = {}
coupon_type = item.coupon.coupon_type
coupon_id = item.id
coupon_course_id = item.coupon.object_id
-8 构造单个优惠券字典,将数据填充进去,格式如下:
{
"7":{"coupon_type":0,"coupon_display":"立减券","money_equivalent_value":10},
"8":{"coupon_type":1,"coupon_display":"满减券","money_equivalent_value":10,"minimum_consume":100},
"9":{"coupon_type":2,"coupon_display":"折扣券","off_percent":90}
}
coupon_detail['coupon_type'] = coupon_type
coupon_detail['coupon_display'] = item.coupon.get_coupon_type_display()
if coupon_type == 0: #立减券,构造出等值金额
coupon_detail['money_equivalent_value'] = item.coupon.money_equivalent_value
elif coupon_type == 1:#满减券,构造出等值金额,和最低消费金额
coupon_detail['money_equivalent_value'] = item.coupon.money_equivalent_value
coupon_detail['minimum_consume'] = item.coupon.minimum_consume
else:#其他情况,构造出打折(如打八折,80)
coupon_detail['off_percent'] = item.coupon.off_percent
-9 判断是全站优惠券还是课程优惠券
if not coupon_course_id:#全站优惠券放到全站优惠券字典里
global_coupon_dict['coupon'][str(coupon_id)]=coupon_detail
else:
#其它情况,说明是绑定给课程的优惠券
coupon_course_id=str(coupon_course_id)
if coupon_course_id not in payment_dict_userid:#当前课程优惠券对应的可能如果不在结算中心字典里,continue
continue
#在结算中心字典中的,对应放入到课程优惠券字段上
payment_dict_userid[str(coupon_course_id)]['coupon'][coupon_id]=coupon_detail
payment_dict_userid[str(coupon_course_id)]['default_coupon'] = 0
-10 讲结算中心字典和全局优惠券字典,放入redis中
elf.conn.set('payment_dict_%s'%request.user.id,json.dumps(payment_dict_userid))
self.conn.set('global_coupon_dict_%s'%request.user.id,json.dumps(global_coupon_dict))
-11 返回成功

-(2)修改结算中心某个课程的优惠券信息---patch--{"course_id":"1","coupon_id":"1"}
-1 从reids中取出结算中心数据
-2 先校验coupon_id是否合法,也就是是否在结算中心的优惠券信息中
if coupon_id not in payment_dict_userid[course_id]['coupon']:
raise Exception('该优惠不合法')
-3 合法,直接修改,返回正确信息
payment_dict_userid[course_id]['default_coupon']=coupon_id
-(3)获取结算中心数据----get
-1 从redis中取出本人的结算中心数据 ('payment_dict_%s'%request.user.id))
-2 从redis中取出本人的全局优惠券数据 ('global_coupon_dict_%s'%request.user.id))
-3 构造数据返回前台
res.data={
'payment':payment_dict_userid,
'global_coupon_dict':global_coupon_dict
}


-去支付:
-前端传递数据格式:
{
"price":600
"bely":100
}
-去支付逻辑:
-从支付中心拿出字典
-payment_dic = self.conn.get('payment_dic_%s' % request.user.id)
-循环结算中心字典,得到课程和课程id
-for course_id,course_detail in payment_dic.items():
-取出默认价格策略,取出默认价格,取出默认优惠券id
default_policy_id=course_detail['default_policy']
price=course_detail['policy'][str(default_policy_id)]['price']
default_coupon_id=course_detail['default_coupon']
-判断如果默认优惠券不为0,表示使用了优惠券:取出默认优惠券的字典,调用计算价格函数得到价格,把价格放到价格列表中(后面直接用sum函数计算总价格)
if default_coupon_id!=0:
coupon_dic=course_detail['coupon'][str(default_coupon_id)]
price= self.account_price(price,coupon_dic)
price_list.append(price)
-取出全局默认优惠券id,根据默认优惠券id取出全局优惠券字典,调用计算价格函数得到实际支付价格
default_coupon_id=global_coupon['default_coupon']
global_coupon_dic=global_coupon['coupon'][str(default_coupon_id)]
debate_price=self.account_price(sum(price_list),global_coupon_dic)
-判断贝利数大于传入的贝利数,用实际价格减去贝利数,如果得到结果小于0,直接等于0,判断最终价格和传如的价格是否相等,不相等抛异常
if bely>request.user.bely:
raise MyException('贝利数不合法')
final_price=debate_price-bely
if final_price<0:
final_price=0
if price!=final_price:
raise MyException('传入的价格有问题')
-如果实际支付价格大于0,生成支付宝url地址,返回给前端,让前端跳转
if final_price>0:
# 拼凑支付宝url
alipay = ali()
# 生成支付的url
query_params = alipay.direct_pay(
subject="路飞学成课程", # 商品简单描述
out_trade_no="x2" + str(time.time()), # 商户订单号
total_amount=final_price, # 交易金额(单位: 元 保留俩位小数)
)
pay_url = "https://openapi.alipaydev.com/gateway.do?{}".format(query_params)
response.url=pay_url
-计算价格方法:
#传入价格和优惠券字典
def account_price(self,price,coupon_dic):
#设置总价格为price
total_price=price
#取出优惠券类型
coupon_type=coupon_dic['coupon_type']
#优惠券类型是0,立减
if coupon_type==0:
total_price=price-coupon_dic['money_equivalent_value']
##优惠券类型是1,满减,必须大于最低消费金额
elif coupon_type==1:
if price>=coupon_dic['minimum_consume']:
total_price=price-coupon_dic['money_equivalent_value']
else:
raise MyException('优惠券不满足最低使用金额')
##优惠券类型是2,直接打折
elif coupon_type==2:
total_price=price*coupon_dic['off_percent']/100

return total_price





def ali():
# 沙箱环境地址:https://openhome.alipay.com/platform/appDaily.htm?tab=info
app_id = "2016092000554611"
# POST请求,用于最后的检测
notify_url = "http://47.52.195.206:80/page2/"
# notify_url = "http://www.wupeiqi.com:8804/page2/"
# GET请求,用于页面的跳转展示
return_url = "http://47.52.195.206:80/page2/"
# return_url = "http://www.wupeiqi.com:8804/page2/"
merchant_private_key_path = "keys/app_private_2048.txt"
alipay_public_key_path = "keys/alipay_public_2048.txt"

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

class Pay(APIView):
authentication_classes=[LoginAuth,]
conn = get_redis_connection('default')
def post(self,request):
# {"course_list":[{"course_id":"1","policy_id":"1"},{"course_id":"2","policy_id":"2"}]}
reponse=MyResponse()
course_list=request.data.get('course_list')
try:
#1 定义结算中心的字典,定义全局优惠券的字典
payment_dic_userid={}
global_copon = {
"coupon": {},
"default_coupon": 0
}
# 2拿到购物车,循环取出传入的课程id,判断是否在购物车中,不在直接抛异常
shopping_cart_bytes=self.conn.get('shopping_cart_%s'%request.user.id)
shopping_cart_dic=json.loads(shopping_cart_bytes) if shopping_cart_bytes else {}
for course_de in course_list:
in_course_id=course_de.get('course_id')
if str(in_course_id) not in shopping_cart_dic:
raise MyException('该课程不再购物车中')
#3 构造单个课程详情的字典,把购物车中的当前课程,update到该字典中
course_detail={
'coupon':{},
'default_coupon':0
}
# 字典更新,把购物车对应的课程所有数据,直接更新到这里面course_detail
course_detail.update(shopping_cart_dic[str(in_course_id)])
#4 将该课程详情,加入到结算中心(现在里面没有优惠券相关信息)(为了效率,不在for循环中查询数据库,查出优惠券)
payment_dic_userid[str(in_course_id)]=course_detail
# 5一次性查出当前用户的所有优惠券信息(用户为当前用户,状态为未使用,优惠券起始时间小于当前时间,优惠券结束时间大于当前时间)
ctime=datetime.datetime.now().date()
copon_list=models.CouponRecord.objects.filter(
user=request.user,
status=0,
coupon__valid_begin_date__lte=ctime,
coupon__valid_end_date__gte=ctime
)
for coupon_record in copon_list:
# 6构造出单个优惠券的空字典,拿到优惠券类型(1立减 2 满减 3折扣),拿到优惠券id,拿到该优惠券绑定的课程id(有可能为空)
coupon={}
coupon_type=coupon_record.coupon.coupon_type
coupon_record_id=coupon_record.pk
coupon_course_id=coupon_record.coupon.object_id
# 7构造单个优惠券字典,将数据填充进去,格式如下
'''
{
"coupon_type":1,
"coupon_display":"满减券",
"money_equivalent_value":10,
"minimum_consume":100
}
'''
coupon_detail={
'coupon_type':coupon_type,
'coupon_display':coupon_record.coupon.get_coupon_type_display()
}
# 9 判断优惠券类型((0, '立减券'), (1, '满减券'), (2, '折扣券'))
if coupon_type==0:
coupon_detail['money_equivalent_value']=coupon_record.coupon.money_equivalent_value
elif coupon_type==1:
coupon_detail['money_equivalent_value'] = coupon_record.coupon.money_equivalent_value
coupon_detail['minimum_consume'] = coupon_record.coupon.minimum_consume
elif coupon_type==2:
coupon_detail['off_percent'] = coupon_record.coupon.off_percent

# 10 判断是全站优惠券还是课程优惠券
if not coupon_course_id:
global_copon['coupon'][str(coupon_record_id)]=coupon_detail
else:
payment_dic_userid[str(coupon_course_id)]['coupon'][str(coupon_course_id)]=coupon_detail
# payment_dic_userid[str(coupon_course_id)]['default_coupon'] = 0
self.conn.set('payment_dic_%s'%request.user.id,json.dumps(payment_dic_userid))
self.conn.set('global_coupon_%s'%request.user.id,json.dumps(global_copon))

except MyException as e:
reponse.status=1001
reponse.msg=e.msg
except Exception as e:
reponse.status = 1001
reponse.msg = str(e)
return Response(reponse.get_dic())

def get(self,request):
response=MyResponse()
try:
# 拿出购物车字典
payment_dic=self.conn.get('payment_dic_%s'%request.user.id)
global_coupon=self.conn.get('global_coupon_%s'%request.user.id)

response.msg='查询成功'
response.payment_dic=json.loads(payment_dic)
response.global_coupon=json.loads(global_coupon)
response.bely=request.user.bely
except Exception as e:
response.msg=str(e)

return Response(response.get_dic())


from rest_framework.request import Request
class PayFinal(APIView):
authentication_classes=[LoginAuth,]
conn = get_redis_connection('default')
def post(self,request):
'''
{"price":600"bely":100}
'''
price=request.data.get('price')
bely=request.data.get('bely')
response=MyResponse()
# 1 拿出结算中新字典
try:
payment_dic = self.conn.get('payment_dic_%s' % request.user.id)
'''
"payment_dic": {
"1": {
"coupon": {

},
"title": "Django从入门到放弃",
"img": "/media/lhf.jpg",
"default_policy": "1",
"policy": {

},
"default_coupon": 0
}
},
'''
global_coupon = self.conn.get('global_coupon_%s' % request.user.id)
# 2循环结算中心字典
price_list=[]
for course_id,course_detail in payment_dic.items():
default_policy_id=course_detail['default_policy']
price=course_detail['policy'][str(default_policy_id)]['price']
# 拿课程优惠券
default_coupon_id=course_detail['default_coupon']
if default_coupon_id!=0:
coupon_dic=course_detail['coupon'][str(default_coupon_id)]
price= self.account_price(price,coupon_dic)
price_list.append(price)

# 计算全局优惠券
default_coupon_id=global_coupon['default_coupon']
global_coupon_dic=global_coupon['coupon'][str(default_coupon_id)]
debate_price=self.account_price(sum(price_list),global_coupon_dic)
# 减掉贝利数
if bely>request.user.bely:
raise MyException('贝利数不合法')
final_price=debate_price-bely
if final_price<0:
final_price=0
if price!=final_price:
raise MyException('传入的价格有问题')

# 所有校验通过
# 创建订单。。。。。

if final_price>0:
# 拼凑支付宝url
alipay = ali()
# 生成支付的url
query_params = alipay.direct_pay(
subject="路飞学成课程", # 商品简单描述
out_trade_no="x2" + str(time.time()), # 商户订单号
total_amount=final_price, # 交易金额(单位: 元 保留俩位小数)
)
pay_url = "https://openapi.alipaydev.com/gateway.do?{}".format(query_params)
response.url=pay_url
else:
response.success = 1
except MyException as e:
response.msg=e.msg
response.status=1001
except Exception as e:
response.msg=str(e)
response.status = 1001
return Response(response.get_dic())


def account_price(self,price,coupon_dic):
total_price=price
coupon_type=coupon_dic['coupon_type']
if coupon_type==0:
total_price=price-coupon_dic['money_equivalent_value']
elif coupon_type==1:
if price>=coupon_dic['minimum_consume']:
total_price=price-coupon_dic['money_equivalent_value']
else:
raise MyException('优惠券不满足最低使用金额')
elif coupon_type==2:
total_price=price*coupon_dic['off_percent']/100

return total_price
-


posted @ 2018-12-29 12:08  不沉之月  阅读(450)  评论(0编辑  收藏  举报