qrcode和Websocket实现在线支付

收营员选择收款方式(现金/支付宝/微信),如果是支付宝/微信,服务端会传给前端一个交易码,前端用 qrcode 生成二维码给客户扫并且支付, websocket 建立持久的连接直到收到服务端返回的true,前端提示交易成功。

HTML5 WebSocket

1.简介

我们已经有了 HTTP 协议,为什么还需要另一个协议?它能带来什么好处?

答案很简单,因为 HTTP 协议有一个缺陷:通信只能由客户端发起。

举例来说,我们想了解今天的天气,只能是客户端向服务器发出请求,服务器返回查询结果。HTTP 协议做不到服务器主动向客户端推送信息。

这种单向请求的特点,注定了如果服务器有连续的状态变化,客户端要获知就非常麻烦。我们只能使用”轮询”:每隔一段时候,就发出一个询问,了解服务器有没有新的信息。最典型的场景就是聊天室。

轮询的效率低,非常浪费资源(因为必须不停连接,或者 HTTP 连接始终打开)。因此,工程师们一直在思考,有没有更好的方法。WebSocket 就是这样发明的。

2.使用

http://jsbin.com/muqamiqimu/edit?js,console

var ws = new WebSocket("wss://echo.websocket.org");

ws.onopen = function(evt) { 
  console.log("Connection open ..."); 
  ws.send("Hello WebSockets!");
};

ws.onmessage = function(evt) {
  console.log( "Received Message: " + evt.data);
  ws.close();
};

ws.onclose = function(evt) {
  console.log("Connection closed.");
};

qrcode-vue

https://www.npmjs.com/package/qrcode-vue

1.安装

npm install –save qrcode.vue

2.使用

<template>
  <div>
    <qrcode-vue 
      :size="size" 
      :value="value" 
      :logo="logo" 
      :bgColor="bgColor" 
      :fgColor="fgColor"
    ></qrcode-vue>
  </div>
</template>
<script>
  import qrcodeVue from '../src/qrcode-vue'
  export default {
    data () {
      return {
        size: 128,
        bgColor: '#fff',
        fgColor: '#000',
        value: 'https://github.com/l-ll/qrcode-vue',
        logo: 'https://avatars3.githubusercontent.com/u/7104141?v=3&s=80'
      }
    },
    components: {
      qrcodeVue
    }
  }
</script>

在线支付场景实例

<style lang="less">
    @import '../../styles/common.less';

    .pay-template {
        .title {
            font-size: 18px;
            font-weight: 700;
        }

        .orderInfo {
            .payType {
                width: 200px
            }
            canvas {
                border-radius: 4px;
            }
        }

        .footer {
            text-align: right;
            .submit {
                margin-left: 5px;
            }
        }
    }
</style>

<template>
    <div class="pay-template">
        <Spin size="large" fix v-if="spinShow"></Spin>
        <p slot="header">
            <span class="title">付款 {{orderInfo.orderNo}}</span>
        </p>
        <div class="orderInfo">
            <p>订单类型:{{orderInfo.orderType|orderType}}</p>
            <p>订单金额:{{orderInfo.totalAmount|money}}</p>
            <p>优惠金额:{{orderInfo.totalAmount - orderInfo.finalAmount|money}}</p>
            <p>实付金额:
                <span>{{orderInfo.finalAmount|money}}</span>
            </p>
            <p>支付方式:
                <Select class="payType" v-model="orderInfo.payType">
                    <Option value="CASH">现金</Option>
                    <Option value="WECHAT">微信</Option>
                    <Option value="ALIPAY">支付宝</Option>
                </Select>
            </p>
            <p style="text-align: center" v-if="orderInfo.payType!='CASH' && message!==''">{{message}}</p>
            <qr-code-vue v-if="orderInfo.payType!='CASH'&&message===''&&qrCodeValue!==''" style="text-align: center;"
                         :value="qrCodeValue" size="150" level="H"></qr-code-vue>
        </div>
        <div class="footer" slot="footer">
            <Button type="ghost" @click="$emit('emitCloseDialog')">取消</Button>
            <Button class="submit" v-if="orderInfo.payType=='CASH'" type="primary"
                    @click="handleSureOrder">
                确定
            </Button>
        </div>
    </div>
</template>

<script>
    import {
        getQrCode,
        sureOrder
    } from '../../api/retail'
    import QrCodeVue from 'qrcode.vue'

    export default {
        props: ['orderInfo', 'orderShow'],
        data() {
            return {
                message: '',
                qrCodeValue: '',
                spinShow: false
            }
        },
        components: {
            QrCodeVue
        },
        watch: {
            'orderInfo.payType'(type) {
                this.makeQrCode(type)
            },
            orderShow(flag) {
                if (flag) {
                    this.webSocketInit()

                } else {
                    this.webSocketClose()
                }
            }
        },
        methods: {
            makeQrCode(type) {
                let _this = this
                if (type !== 'CASH') {
                    _this.spinShow = true
                    return new Promise((resolve, reject) => {
                        getQrCode({
                            orderId: _this.orderInfo.id,
                            payType: type
                        }).then(response => {
                            _this.spinShow = false
                            if (response.status === 200) {
                                _this.qrCodeValue = response.data
                                _this.message = ''
                            } else {
                                _this.message = response.message
                            }
                            resolve(response)
                        }).catch(error => {
                            _this.qrCodeValue = ''
                            _this.message = ''
                            _this.spinShow = false
                            reject(error)
                        })
                    })
                }
            },
            handleSureOrder() {
                let _this = this
                _this.spinShow = true
                return new Promise((resolve, reject) => {
                    sureOrder({
                        orderNo: _this.orderInfo.orderNo,
                        id: _this.orderInfo.id,
                        payType: _this.orderInfo.payType
                    }).then(response => {
                        _this.spinShow = false
                        if (response.status && response.status === 200) {
                            _this.$Notice.success({
                                title: '付款成功通知',
                                desc: '订单' + _this.orderInfo.orderNo + '付款成功',
                                duration: 3
                            })
                            _this.$emit('emitCloseDialog')
                            _this.$store.commit('RELOAD')
                        } else {
                            _this.$Notice.error({
                                title: response.message,
                                desc: '订单' + _this.orderInfo.orderNo + '付款失败',
                                duration: 3
                            })
                        }
                        resolve(response)
                    }).catch(error => {
                        _this.spinShow = false
                        reject(error)
                    })
                })
            },
            webSocketInit() {
                if ('WebSocket' in window) {
                    this.websock = new WebSocket("ws://xxxxxxxxxxxxxxxxxxxx")
                    this.websock.onopen = this.webSocketOnOpen
                    this.websock.onmessage = this.webSocketOnMessage
                    this.websock.onerror = this.webSocketOnError
                    this.websock.onclose = this.webSocketClose
                } else {
                    alert('Not support websocket')
                }
            },
            webSocketOnOpen(event) {
                console.log('websocket open')
            },
            webSocketOnMessage(event) {
                if (event.data) {
                    this.$Notice.success({
                        title: '付款成功通知',
                        desc: '订单' + this.orderInfo.orderNo + '付款成功',
                        duration: 3
                    })
                    this.$emit('emitCloseDialog')
                    this.$store.commit('reloadOrder')
                }
            },
            webSocketOnError(event) {
                this.$Message.error("websocket 连接失败")
            },
            webSocketClose(event) {
                console.log('websocket close')
            }
        }
    }

</script>

深自缄默,如云漂泊 本文链接: http://zc95.github.io/2018/08/16/qrcodeAndWebsocket/

我来评几句
登录后评论

已发表评论数()

相关站点

+订阅
热门文章