Day23 - [丰收款] 以Django Web框架实作永丰API线上支付模拟情境(4) - 信用卡刷卡结果

昨天写完两种付款方式,有提到原先信用卡刷卡後的结果导回页ReturnURL我们还没实作,今天就把这一页完成。

先说明一下,信用卡刷卡时,不会立即得到结果,会透过我们在建立订单时传入的ReturnURL参数,待转入永丰线上刷卡页面後,会再透过这个网址导回我们的电商结果页。细部流程如下

流程说明

  1. [电商] 呼叫永丰API,建立信用卡付款方式的订单,从response取回card_pay_url结果,我们将顾客导到这个网址去刷卡
  2. [永丰] 在永丰的网页进行刷卡,因此使用者的信用卡机敏资讯不会留在电商平台上
  3. [永丰] 进行信用卡刷卡处理,先无论结果,完成後会将PayToken值传入ReturnURL
  4. [电商] 这时候会透过ReturnURL将PayToken值带回,我们将此值取出
  5. [电商] 以PayToken呼叫永丰API讯息查询服务(OrderPayQuery)
  6. [永丰] 回传付款状态相关资讯
  7. [电商] 将付款状态结果显示於页面上,会分别显示刷卡成功以及刷卡失败不同状态的资讯,若刷卡失败我们可再提供一次刷卡连结果顾客

View的card_return修改

先前我们有写过View中的card_return(),当时只验证一些资讯往来正不正确,现在要作一些小调整,但幅度不大。

def card_return(request):
    pay_token_dic = {"PayToken": request.POST.get("PayToken"), "ShopNo": request.POST.get("ShopNo")}
    create_new_paytoken(pay_token_dic["PayToken"])
    result = update_order_by_paytoken(pay_token_dic)
    return render(request, 'order/card_return.html', result)
程序说明

主要是当初我们呼叫update_order_by_paytoken()时,没有回传值,我们希望把整理过必要的资讯回传值拿回来,在等一下的Template中作为判断以及显示相关结果的讯息

而另外我们把当初的HttpResponse改成了render方式导引到新准备的order/card_return.html中。

Model中的update_order_by_paytoken()修改

def update_order_by_paytoken(paytoken_json):
    result = {}
    if paytoken_json:
        pay_token = paytoken_json["PayToken"]
        create_new_paytoken(pay_token)

        paytoken_api = QueryByPaytokenMessage()
        paytoken_api.set_paytoken_json(paytoken_json)
        resp = ResponsePayToken(paytoken_api.send_query(), paytoken_api.hash_id)
        print("-- Response: " + str(resp.dec_resp_json))

        order = Payment.objects.get(order_no=resp.orderno)
        order.pay_status = resp.status
        order.pay_token = pay_token
        order.lm_time = datetime.now()
        order.save()

        result["order_no"] = order.order_no
        result["status_code"] = order.pay_status
        if order.pay_status == "S":
            result["pay_status"] = "刷卡成功"
        else:
            result["pay_status"] = "刷卡失败"
        result["card_pay_url"] = order.card_pay_url

        print(" Update Order Successfully.")
    else:
        print(" Update Order Fail.")
    return result
程序说明

update_order_by_paytoken()中,我们主要准备了一个result作为回传,把所需要的必要资讯整理成dictionary回传回去,在这里顺便把pay_status中的代码换成了可阅读的显示文字。

不过我必须再三强调,这样的写法并非产品等级的撰写方法,这也不是在这系列文章中我打算实作的,那样只会对主要要介绍永丰API的串接失焦了。但我们可以谈一谈可以怎麽做会比较好。

  1. 在Model里面即使使用了原本代码要转成可阅读文字,并不会直接这样处理,无论你的网站一开始是不是单一语言,这种最终要显示在UI上的文字,不会在Model里直接替换,至少需考量到i18n多国语系。
  2. 即使没有要做多国语系,这样的UI文字替换,也不会在处理专职功能的商业逻辑中实作,好一点的方式会写在回传之後,再呼叫另一个专门处理代码转文字的Converter逻辑。
  3. 上面这个Converter,另一个呼叫阶段可摆在View的那层来处理(我说的是View,不是Template),但不是在View层直接作代码转文字,而是在View那层"再呼叫处理转换的逻辑",毕竟这个最终的内容是属於偏UI的内容。

但为了范例方便,我们就直接在Model里处理掉了,但这绝对不是最好的作法。

可以来看Template了

{% extends "base.html" %}

{% block title %}{{ title }}{% endblock %}

{% block body %}
<div id="app" class="row g-3 align-self-center">
<h1 class="display-4 text-center  mb-3 mt-5">信用卡刷卡结果</h1>
<p class="lead  text-center">感谢您使用永丰线上信用卡刷卡服务,以下是您的刷卡结果喔!</p>
<hr/>
<div class="container-fluid">
    <h3 class="mb-5">
      订单号码 <small class="text-muted">{{ order_no }}</small>
    </h3>
    <div class="border border-secondary rounded m-2 {% if status_code == 'S' %}bg-success{% else %}bg-danger{% endif %}
    text-white p-3">
        <h6>您的刷卡结果</h6>
        <p>
            <span class="primary fs-4">{{ pay_status }}</span>
        </p>
        {% if status_code != 'S' %}
            <a href="{{ card_pay_url }}" class="btn btn-light btn-lg" tabindex="-1" role="button" aria-disabled="true">再次使用永丰信用卡刷卡</a>
        {% endif %}

    </div>
    <br/><br/><br/><br/>
    <hr/>
    <div class="row mt-3">
        <div class="col text-center">
            <a href="{% url 'order_create_entrance' %}" class="btn btn-primary btn-lg" tabindex="-1" role="button" aria-disabled="true">继续购买</a>
            &nbsp
            <a href="{% url 'my_orders' %}" class="btn btn-secondary btn-lg" tabindex="-1" role="button" aria-disabled="true">回到订单</a>
        </div>
    </div>
</div>
</div>
{% endblock %}

{% block script %}
{% endblock %}
程序说明

刷卡结果当然就直接把刚刚上面谈半天的刷卡结果的UI文字直接以{{ pay_status }}显示出来。但我们希望在结果的二分世界中,以颜色来作明显的区隔,因此就可以拿status_code结果代码对刷卡成功或失败改变颜色,这里透过Bootstrap的基本几个色调来调整div的背景颜色。

  • 成功:bg-success
  • 失败:bg-danger

然後在失败的时候,再次将刷卡网址按钮附上,让顾客有机会再执行一次刷卡。

以下就是执行的UI画面,我们先刻意刷一次错误的卡片:
https://ithelp.ithome.com.tw/upload/images/20211008/20130354MSoC0oll9t.png

https://ithelp.ithome.com.tw/upload/images/20211008/20130354i9eWyjVYdN.png

所以立刻可以验证那个重刷卡的按钮,很好,又再次导入刷卡页面,这次小心翼翼的输入永丰提供给我们的测试信用卡卡号。如先前说明,因为非完全公开资料,为了怕有心人事拿去乱刷,我们就不在此公开这个测试页面的内容和卡号。

https://ithelp.ithome.com.tw/upload/images/20211008/20130354N5EtYIUk6Q.png

https://ithelp.ithome.com.tw/upload/images/20211008/20130354ljybM9gioZ.png

刷卡成功了!看到绿绿颜色的就觉得很安全呀 (咦,股市的话好像就不是这种感觉...)

今天头非常痛呀,原本想继续写订单查询状态等的部份,但状态不好只能写到这里了,明天再继续吧。


<<:  学习笔记:一起进入 PixiJS 的世界 (四)

>>:  Day23 - 在 XState 中的平行式状态 Parallel States

从 JavaScript 角度学 Python(1) - 目录与废话

前言 这是我今年第三次挑战 iThome 铁人赛,除此之外这也是我的第四篇铁人赛系列文章,其实我有点...

DAY 22 『 连接 API 实作 - 天气 APP 』Part4

昨天介绍了如何将资料显示在手机画面上,今天会介绍如何辨别点选到哪一个城市,以及将城市天气资讯回传到手...

Day15:今天来聊一下Microsoft Defender for Endpoint的威胁分析

随着敌人越来越复杂、新威胁频繁出现且越来越普遍,一定要能快速完成以下工作: -评估新威胁的影响 -检...

Cloud Monitor

Cloud Monitor 如果使用了GCP平台,要如何捕捉以及监控错误,我想大概多半会使用Clo...

Day 13 实作调色盘App(1/3)

我们可以藉由小小的调色盘App专案来加强我们对一些元件的认识 1.先新增一个专案 -> Cr...