网站 扫码 支付

目标问题

  1. 支持个人办理
  2. 支持个人网站扫码付费
  3. 本文章只是给出了通过网站扫码付款的一种实现方案,欢迎技术讨论交流,请勿用于非法用途.

实战

流程描述:
用户发起支付后,网站申请获取二维码,用户扫码后支付结果返回给回调链接,网站处理回调,完成支付流程.

运营准备

  1. 备案域名+https服务 target 正式提供服务+扫码付款的前提
  2. 外网可访问服务器 target 作为支付结果的回调链接.可获取用户的支付结果.

开发准备

本次实战使用的架构为:

Python.Tornado+MongoDB+Jquery

代码分3部分

  1. html页面
  2. 后台路由处理
  3. 网站自有业务处理-新增订单,确认付款结果,提供对应服务

步骤列下:

  1. 先写路由代码和业务处理代码
""" 常规 导包 """

import sys
import os
import codecs
import json
import io
import base64
import hashlib


import pymongo

bsdir = os.path.dirname(os.path.abspath(__file__))
sys.path.append(bsdir)

# tornado
import tornado.web as tweb
import tornado.ioloop as tIO

db = pymongo.MongoClient(host='localhost', port=27017)
cdbname = '数据库名称'
collectionname = '集合名称'
# 默认移除未支付订单

db.get_database(cdbname).get_collection(collectionname).remove({'ispay': False})
class op(object):
	# mongodb数据库实例,用于数据的增删改查接口
	cdb = MongodbClient()
	def create_order(**kwargs):
		# 根据提供的参数处理业务
		# 并返回处理结果
		# 建议在此处添加out_trade_no 并保存到数据库,作为网站支付记录查询参数
		# 添加total_fee 作为支付价格
		out_trade_no = hashlib.md5(str(time.time()).encode('utf-8')).hexdigest().upper()
		return {
			"out_trade_no" : out_trade_no,
			"total_fee": kwargs.get("total_fee"),
		}
	def process(self, **kwargs):
		""" 网站业务处理部分
			包含订单生成,服务处理,服务提供接口
		"""
		obj = cdb.insert(self.create_order(**kwargs)}
		return obj.insert_id
	
	def not_pay():
		return "等待支付/支付失败"

class BusinessHandle(tweb.RequestHandle):
	""" 处理支付相关业务
	"""
	# 生成订单所需参数
	params = ["param1"]
	def post(self):
		res = op().process({name:self.get_argument(name) for name in self.params})
		self.write(res)

class notify_url(tweb.RequestHandle):
	""" 得到支付结果后 服务商回调链接,网站应当以此来更新订单是否完成支付"""
	def post(self):
		""" 支付结果判断,根据对接的服务商提供的文档添加判断"""
		if self.get_argument("return_code") != 1:
			self.write("支付失败")

		# 并将此结果与out_trade_no对应的业务处理中ispay改为True
		item = op().cdb.find_one({"out_trade_no":self.get_arguments("out_trade_no")})
		item["ispay"] = True
		op().cdb.update_one({"_id":item.get("_id")},{"$set":item})

class confirm(tweb.RequestHandle):
	""" 网站页面轮询判断支付是否完成,并在完成后处理后续逻辑"""
	def post(self):
		out_trade_no = self.get_argument("out_trade_no")
		if item and item.get('ispay', None):
			self.write(op().result(item))
		else:
			self.write(op().not_pay())
		

class Pay(tweb.RequestHandle):
	def post(self):
		item = op().cdb.find_one({"out_trade_no":self.get_argument("out_trade_no")})
		if item and item.get("ispay", None):
			# 订单已支付/未查询到订单
			return 
		total_fee = item.get("total_fee")
		my_notify_url = "" # 此回调链接只能真机测试,即访问上述notify_url类
		# 调用服务商扫码支付接口获取二维码和订单号
		return your_qrcode(total_fee=total_fee)

路由部分

urls = [
        (r'/businesshandle', BusinessHandle),
        (r'/pay', Pay),
        (r'/notify_url', notify_url),
        (r'/confirm', confirm),
    ]
configuration = {
	# 通用配置
    'template_path'    : '/'.join([bsdir, 'templates']),
    'static_path'      : '/'.join([bsdir, 'static']),
    'autoreload'       : True,
    'static_hash_cache': False,
}
app = tweb.Application(urls, **configuration)
port = 8035
print('http://localhost:{port}'.format(port=port))

app.listen(port=port, address='0.0.0.0')
tIO.IOLoop.instance().start()
  1. HTML部分通过点击按钮发起调用
<button οnclick="pay()">发起支付</button>

    function submitimage() {
        $.ajax({
            url: 'businesshandle',
            method: 'post',
            async: false,
            data: {
            // 业务参数,与params对应
            },
            success: function (res) {
            	// 发起支付后页面处理
            	...
            	// 开启轮询查询支付结果
                confirm(res);
                $.ajax({
                    url: '/pay',
                    method: 'post',
                    data: {
                        out_trade_no: res.out_trade_no,
                    },
                    success: resp => {
                    // 回显付款二维码,根据服务商参数指定
                    },
                    error: err => {
                    },
                })
            },
            error: function (err) {
                console.log("error");
            }
        })
    }
     function confirm(obj) {
        $.ajax({
            url: '/confirm',
            method: 'post',
            data: {
                out_trade_no: obj.out_trade_no
            },
            success: resp => {
                if (resp.ispay) {
	                // 隐藏付款二维码
	                // 提供服务
                } else {
	                // 等待付款部分,每隔1.5秒,确认一次是否付款
                    setTimeout(() => {
                        confirm(obj);
                    }, 1500);
                }
            },
            error: err => {
            }
        });
    }
  1. 测试部分
    本地可测试功能: 订单创建成功,假设支付成功的前提下完整提供服务
    外网测试功能: 成功发起支付获得付款二维码,并在用户扫码付款/取消支付后,业务订单逻辑完整

后续

python代码部分只给出了框架,业务如何处理还需要自己添加.
代码纯手敲,未经测试.可访问Demo查看效果
需要完整代码或技术交流加博主微信在这里插入图片描述

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

大霸王龙

+V来点难题

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值