[DAY29] 接上金流系统,串接建立订单功能

本日将完成从Line控制购物车品项,建立订单,产生付款连结,通知付款人

替购物车加上送出订单按钮

传送附带按钮的讯息,减少操作繁琐,按钮传送一PostBackAction,通知服务器执行产生订单

# APIModel.py
def ShoppingCartTemp(cart_info_text):
    template_message = TemplateSendMessage(
        alt_text='Buttons alt text', template=ButtonsTemplate(
            text=cart_info_text, actions=[
            PostbackAction(label='点我下订单', display_text='确认购物车OK,我要下订单', data='action=buy')
        ]
    ))
    return template_message

# Server.py
if(data == 'action=ShowShoppingCartContents'):
    cart_info, cart_amount = dbpm.QUY_Shopping_Cart_info_by_uid(event.source.user_id)
    app.logger.debug(f"{prof.display_name} 查询购物车, uid:{event.source.user_id}, {cart_info}")
    replay_text = '\n'.join(str(v) for v in cart_info) + f"\n总共:{cart_amount}元"
    template_msg = APIModel.ShoppingCartTemp(replay_text)
    line_bot_api.reply_message(
        event.reply_token, template_msg
    )

产生订单

订单产生完成後,将传送付款网址给使用者,记得预留订单产生失败的错误处理

# Server.py
if(datapath == "action=ShowProductList"):
    .....
# 新增一PostEvent功能处理
elif(datapath == "action=buy"):
    isSucc, msg = Handler.MakeOrder(event.source.user_id)
    if(isSucc):
        template_msg = APIModel.OrderPayURLTemp(msg)
        line_bot_api.reply_message(
            event.reply_token,
            template_msg
        )
    else:
        line_bot_api.reply_message(
            event.reply_token,
            TextSendMessage(text=msg)
        )

# APIMode.py

# 付款按钮
def OrderPayURLTemp(msg):
    template_message = TemplateSendMessage(
        alt_text='Buttons alt text', template=ButtonsTemplate(
        title='付款通知', text=f"订单{msg.OrderNo},总金额 {msg.Amount / 100}", actions=[
            URIAction(label='点我付款', uri=msg.CardParam.CardPayURL)
        ]
    ))
    return template_message

# OrderHandler.py
def MakeOrder(uid):
    scid = dbpm.INS_QUY_SC(uid)
    prodlist = []
    tot_price = 0
    shopping_list = dbpm.QUY_Shopping_Cart_by_scid(scid)
    if(not shopping_list):
        return False, "购物车内没有商品喔"
    for prod in shopping_list:
        # print(f"商品:{prod[0]}, 数量:{prod[1]}")
        current_quantity = dbpm.QUY_Prod_Quantity_by_pid(prod[0])
        if(current_quantity - prod[1] < 0):
            dbpm.UPD_Cart_items(scid, prod[0], current_quantity)
            app.logger.error(f"商品{prod[0]},库存不足无法满足订单需求数量({prod[1]})")
            return False, "部分商品库存不足,请稍後重试"
        else:
            new_quantity = current_quantity - prod[1]
            dbpm.UPD_Prod_Quantity(prod[0], new_quantity)
            product_name, product_price = dbpm.QUY_Prod_Name_and_Price_by_pid(prod[0])
            prodlist.append(f"{product_name} * {prod[1]}")
            tot_price = tot_price + product_price * prod[1]

    # 锁定购物车 
    dbpm.UPD_Shopping_Cart_lock_bY_scid(True, scid)

    # 建立订单
    oid = dbpm.INS_Order(os.environ['Me'], scid, ostatus="初始化订单")

    # 建立信用卡付款交易编号
    paid = dbpm.INS_payment_req('C-1', tot_price)
    neworder = APIModel.ReqOrderCreate(ShopNo=os.environ['ShopNo'], OrderNo=oid, Amount=tot_price*100, \
        PrdtName='IT铁人赛虚拟商店', ReturnURL=os.environ['ReturnURL'], BackendURL=os.environ['BackendURL'], PayType="C")
    msg = GenApi.OrderCreate(neworder)
    app.logger.debug(f"MakeOrder:{msg}")

    if(msg):
        if(msg.Status == 'S'):
            print(f"建立订单: 编号:{msg.OrderNo}:{prodlist}, 请款金额 = {tot_price}, 付款ID:{paid}, {msg.Description}", {msg.CardParam.CardPayURL})
            dbpm.UPD_payment_bypaid(paid=paid, tsno=msg.TSNo, ts_decp=msg.Description, ts_status=True, cardpayurl=msg.CardParam.CardPayURL)
            dbpm.UPD_Order_by_oid(paid=paid, ostatus="已产生付款请求", oid=oid)
            return True, msg
        else:
            dbpm.UPD_payment_bypaid(paid=paid, tsno=msg.TSNo, ts_decp=msg.Description, ts_status=False)
            dbpm.UPD_Order_by_oid(paid=paid, ostatus="产生付款请求失败", oid=oid)
            dbpm.UPD_Shopping_Cart_lock_bY_scid(False, scid)
    return False, "与金流系统通讯,建立订单时发生错误"

付款後通知使用者

加上订单付款後的处理

# OrderHandler.py

def OrderPayQueryHandler(resp:APIModel.ResOrderPayQuery, line_bot_api:LineBotApi):
    app.logger.debug(f"ResOrderPayQuery:{resp}")
    payinfo = resp.TSResultContent
    if(payinfo.Status != 'S'):
        dbpm.UPD_payment_bytsno(ispaid=False, paytoken=resp.PayToken, tsno=payinfo.TSNo, aptype=payinfo.APType)
        app.logger.info(f"订单付款失败, 订单编号:{payinfo.OrderNo} - {resp.Description}")
        uid = dbpm.UPD_Order_status_by_oid(ostatus=f"付款失败-{resp.Description}", oid = payinfo.OrderNo)
        line_bot_api.push_message(uid, TextSendMessage(text=f"您的订单{payinfo.OrderNo}付款失败,原因可能为:\n{resp.Description}"))
    else:
        dbpm.UPD_payment_bytsno(ispaid=True, paytoken=resp.PayToken, tsno=payinfo.TSNo, aptype=payinfo.APType)
        app.logger.info(f"订单付款成功, 订单编号:{payinfo.OrderNo} - {resp.Description}")
        uid = dbpm.UPD_Order_status_by_oid(ostatus=f"付款成功-{resp.Description}", oid = payinfo.OrderNo)
        line_bot_api.push_message(uid, TextSendMessage(text=f"您的订单{payinfo.OrderNo}付款成功罗"))

订单流程执行结果

https://ithelp.ithome.com.tw/upload/images/20211012/20140853h2mSQFeOfF.jpg
https://ithelp.ithome.com.tw/upload/images/20211012/201408530eprCfJnTW.jpg

明天做几个小修正跟收尾,补充一点TODO


<<:  Day 26 - 影像处理篇 - 用Canvas实作在IE上也可运行的模糊滤镜II - 成为Canvas Ninja ~ 理解2D渲染的精髓

>>:  [第二十六只羊] 迷雾森林舞会XV 继续整理房间

Day 4:Kotlin 程序设计基础入门 (3)

本篇文章同步发表在 HKT 线上教室 部落格,线上影音教学课程已上架至 Udemy 和 Youtu...

资料分析成熟度模型(Data Analytics Maturity Model, DAMM)

资料平台的建构从基础设施建设开始,配合业务需求,以大数据技术作为战略的基石。 基础设施 包括硬体资源...

元件基本使用

Vue.js 的网页是由元件组合而成,利用 HTML 元素重复使用元件。 图取自What are ...

Day33 ( 电子元件 ) 长条图显示土壤湿度

长条图显示土壤湿度 教学原文参考:长条图显示土壤湿度 这篇文章会介绍如何使用土让湿度感测器,搭配「点...

Day26:终於要进去新手村了-Javascript-函式-物件-建构式

今天文章会延续昨天的程序码去做建构式的学习纪录 我们先看看原本的程序码: var player=ne...