Flask与微信小程序数据通讯 第二步 微信支付

mina/pages/my/order_list.wxml

XML 复制代码
<view class="container">
    <view class="status-box">
        <view bindtap="statusTap" class="status-label {{index == currentType ? 'active' : ''}}" wx:for-items="{{statusType}}" wx:key="{{index}}" data-index="{{index}}">
            {{item}}
            <view class="{{tabClass[index]}}"></view>
        </view>
    </view>
    <view class="no-order" wx:if="{{!order_list.length}}">
        <image src="/images/no-order.png" class="no-order-img"></image>
        <view class="text">暂无订单</view>
    </view>
    <view class="order-list" wx:if="{{order_list.length}}">
        <view class="a-order" wx:for="{{order_list}}" wx:key="{{index}}" wx:for-item="item">
            <view class="order-date" data-id="{{item.order_sn}}" bindtap="orderDetail">
                <view class="date-box">下单时间:{{item.date}}</view>
                <view class="status {{(item.status==0 || item.status==1) ? '':'red'}}">{{item.status_desc}}</view>
            </view>
            <view class="goods-info"  data-id="{{item.order_sn}}" bindtap="orderDetail">
                <view class="goods-des">
                   <view>订单号:{{item.order_number}} </view>
                   <view wx:if="{{item.note && item.note != ''}}">备注: {{item.note}}</view>
                </view>
            </view>
            <view >
                <scroll-view class="goods-img-container" scroll-x="true">
                    <view class="img-box" wx:for="{{item.goods_list}}" wx:for-item="itemGood">
                        <image src="{{itemGood.pic_url}}" class="goods-img"></image>
                    </view>
                </scroll-view>
            </view>
            <view class="price-box">
                <view class="total-price">合计:¥ {{item.total_price}}</view>
                <view class="btn cancel-btn" bindtap="orderCancel" data-id="{{item.order_sn}}" wx:if="{{item.status==-8}}">取消订单</view>
                <view class="btn topay-btn" bindtap="toPay" data-id="{{item.order_sn}}" wx:if="{{item.status==-8}}">马上付款</view>

                <view class="btn topay-btn" bindtap="orderConfirm" data-id="{{item.order_sn}}" wx:if="{{item.status==-6}}">确认收货</view>
                <view class="btn topay-btn" bindtap="orderComment" data-id="{{item.order_sn}}" wx:if="{{item.status==-5}}">走,去评价</view>
            </view>
        </view>
    </view>
</view>

首先在wxml中定义一个支付按钮,绑定toPay事件

小程序端js中发出wx.requst给flask服务器

mina/pages/my/order_list.js

javascript 复制代码
var app = getApp();
Page({
    data: {
        order_list:[],
        statusType: ["待付款", "待发货", "待确认", "待评价", "已完成","已关闭"],
        status:[ "-8","-7","-6","-5","1","0" ],
        currentType: 0,
        tabClass: ["", "", "", "", "", ""]
    },
    statusTap: function (e) {
        var curType = e.currentTarget.dataset.index;
        this.setData({
            currentType: curType
        });
        this.getPayOrder();
    },
    orderDetail: function (e) {
        wx.navigateTo({
            url: "/pages/my/order_info?order_sn=" + e.currentTarget.dataset.id
        })
    },
    onLoad: function (options) {
        // 生命周期函数--监听页面加载
    },
    onShow: function () {
        this.getPayOrder();
    },
    orderCancel:function( e ){
        this.orderOps( e.currentTarget.dataset.id,"cancel","确定取消订单?" );
    },
    getPayOrder:function(){
        var that = this;
        wx.request({
            url: app.buildUrl("/my/order"),
            header: app.getRequestHeader(),
            data: {
                status: that.data.status[ that.data.currentType ]
            },
            success: function (res) {
                var resp = res.data;
                if (resp.code != 200) {
                    app.alert({"content": resp.msg});
                    return;
                }

                that.setData({
                   order_list:resp.data.pay_order_list
                });
            }
        });
    },
    toPay:function( e ){
        var that = this;
        wx.request({
            url: app.buildUrl("/order/pay"),
            header: app.getRequestHeader(),
            method: 'POST',
            data: {
                order_sn: e.currentTarget.dataset.id
            },
            success: function (res) {
                var resp = res.data;
                if (resp.code != 200) {
                    app.alert({"content": resp.msg});
                    return;
                }
                var pay_info = resp.data.pay_info;
                wx.requestPayment({
                    'timeStamp': pay_info.timeStamp,
                    'nonceStr': pay_info.nonceStr,
                    'package': pay_info.package,
                    'signType': 'MD5',
                    'paySign': pay_info.paySign,
                    'success': function (res) {
                    },
                    'fail': function (res) {
                    }
                });
            }
        });
    },
    orderConfirm:function( e ){
        this.orderOps( e.currentTarget.dataset.id,"confirm","确定收到?" );
    },
    orderComment:function( e ){
        wx.navigateTo({
            url: "/pages/my/comment?order_sn=" + e.currentTarget.dataset.id
        });
    },
    orderOps:function(order_sn,act,msg){
        var that = this;
        var params = {
            "content":msg,
            "cb_confirm":function(){
                wx.request({
                    url: app.buildUrl("/order/ops"),
                    header: app.getRequestHeader(),
                    method: 'POST',
                    data: {
                        order_sn: order_sn,
                        act:act
                    },
                    success: function (res) {
                        var resp = res.data;
                        app.alert({"content": resp.msg});
                        if ( resp.code == 200) {
                            that.getPayOrder();
                        }
                    }
                });
            }
        };
        app.tip( params );
    }
});

wx.requestPayment(Object object) | 微信开放文档

web/controllers/api/Order.py

python 复制代码
# -*- coding: utf-8 -*-
from web.controllers.api import route_api
from flask import request, jsonify,g
from app import app, db
import json, decimal
from common.models.food.Food import Food
from common.models.pay.PayOrder import PayOrder
from common.libs.UrlManager import UrlManager
from common.libs.Helper import getCurrentDate
from common.libs.pay.PayService import PayService
from common.libs.pay.WeChatService import WeChatService
from common.libs.member.CartService import CartService
from common.models.member.MemberAddress import MemberAddress
from common.models.member.OauthMemberBind import OauthMemberBind


@route_api.route("/order/info", methods=[ "POST" ])
def orderInfo():
	resp = {'code': 200, 'msg': '操作成功~', 'data': {}}
	req = request.values
	params_goods = req['goods'] if 'goods' in req else None
	member_info = g.member_info
	params_goods_list = []
	if params_goods:
		params_goods_list = json.loads(params_goods)

	food_dic = {}
	for item in params_goods_list:
		food_dic[item['id']] = item['number']

	food_ids = food_dic.keys()
	food_list = Food.query.filter(Food.id.in_(food_ids)).all()
	data_food_list = []
	yun_price = pay_price = decimal.Decimal(0.00)
	if food_list:
		for item in food_list:
			tmp_data = {
				"id": item.id,
				"name": item.name,
				"price": str(item.price),
				'pic_url': UrlManager.buildImageUrl(item.main_image),
				'number': food_dic[item.id]
			}
			pay_price = pay_price + item.price * int( food_dic[item.id] )
			data_food_list.append(tmp_data)

	# 获取地址
	address_info = MemberAddress.query.filter_by( is_default = 1,member_id = member_info.id,status = 1 ).first()
	default_address = ''
	if address_info:
		default_address = {
			"id": address_info.id,
			"name": address_info.nickname,
			"mobile": address_info.mobile,
			"address":"%s%s%s%s"%( address_info.province_str,address_info.city_str,address_info.area_str,address_info.address )
		}

	resp['data']['food_list'] = data_food_list
	resp['data']['pay_price'] = str(pay_price)
	resp['data']['yun_price'] = str(yun_price)
	resp['data']['total_price'] = str(pay_price + yun_price)
	resp['data']['default_address'] = default_address
	return jsonify(resp)

@route_api.route("/order/create", methods=[ "POST"])
def orderCreate():
	resp = {'code': 200, 'msg': '操作成功~', 'data': {}}
	req = request.values
	type = req['type'] if 'type' in req else ''
	note = req['note'] if 'note' in req else ''
	express_address_id = int( req['express_address_id'] ) if 'express_address_id' in req and req['express_address_id'] else 0
	params_goods = req['goods'] if 'goods' in req else None

	items = []
	if params_goods:
		items = json.loads(params_goods)

	if len( items ) < 1:
		resp['code'] = -1
		resp['msg'] = "下单失败:没有选择商品~~"
		return jsonify(resp)

	address_info = MemberAddress.query.filter_by( id = express_address_id ).first()
	if not address_info or not address_info.status:
		resp['code'] = -1
		resp['msg'] = "下单失败:快递地址不对~~"
		return jsonify(resp)

	member_info = g.member_info
	target = PayService()
	params = {
		"note":note,
		'express_address_id':address_info.id,
		'express_info':{
			'mobile':address_info.mobile,
			'nickname':address_info.nickname,
			"address":"%s%s%s%s"%( address_info.province_str,address_info.city_str,address_info.area_str,address_info.address )
		}
	}
	resp = target.createOrder( member_info.id ,items ,params)
	#如果是来源购物车的,下单成功将下单的商品去掉
	if resp['code'] == 200 and type == "cart":
		CartService.deleteItem( member_info.id,items )

	return jsonify( resp )

@route_api.route("/order/pay", methods=[ "POST"])
def orderPay():
	resp = {'code': 200, 'msg': '操作成功~', 'data': {}}
	# 获取请求中的订单号(order_sn)和用户信息(member_info)
	member_info = g.member_info
	req = request.values
	order_sn = req['order_sn'] if 'order_sn' in req else ''
	# 根据订单号和用户ID查询支付订单信息(pay_order_info),如果不存在,则返回错误提示信息。
	pay_order_info = PayOrder.query.filter_by( order_sn = order_sn,member_id = member_info.id ).first()
	if not pay_order_info:
		resp['code'] = -1
		resp['msg'] = "系统繁忙。请稍后再试~~"
		return jsonify(resp)
	# 根据用户ID查询第三方登录绑定信息(oauth_bind_info),如果不存在,则返回错误提示信息。
	oauth_bind_info = OauthMemberBind.query.filter_by( member_id =  member_info.id ).first()
	if not oauth_bind_info:
		resp['code'] = -1
		resp['msg'] = "系统繁忙。请稍后再试~~"
		return jsonify(resp)
	# 获取配置文件中的小程序配置(config_mina)和回调URL(notify_url)。
	config_mina = app.config['MINA_APP']
	notify_url = app.config['APP']['domain'] + config_mina['callback_url']
	# 创建WeChatService对象(target_wechat),并传入商户密钥(merchant_key)。
	target_wechat = WeChatService( merchant_key=config_mina['paykey'] )

	# 创建一个包含支付相关信息,其中包括了appid、mch_idnonce_str、body、out_trade_no、total_fee、notify_url、trade_type和openid等字段。
	data = {
		'appid': config_mina['appid'],
		'mch_id': config_mina['mch_id'],
		'nonce_str': target_wechat.get_nonce_str(),
		'body': '订餐',  # 商品描述
		'out_trade_no': pay_order_info.order_sn,  # 商户订单号
		'total_fee': int( pay_order_info.total_price * 100 ),
		'notify_url': notify_url,
		'trade_type': "JSAPI",
		'openid': oauth_bind_info.openid
	}
	# 调用target_wechat对象的get_pay_info方法,传入支付数据data,获取支付信息pay_info。
	pay_info = target_wechat.get_pay_info( pay_data=data)
	# 将prepay_id保存到pay_order_info对象中,并将其添加到数据库中。
	#保存prepay_id为了后面发模板消息
	pay_order_info.prepay_id = pay_info['prepay_id']
	db.session.add( pay_order_info )
	db.session.commit()
	# 将pay_info添加到resp字典的data字段中
	resp['data']['pay_info'] = pay_info
	return jsonify(resp)

@route_api.route("/order/callback", methods=[ "POST"])
def orderCallback():
	result_data = {
		'return_code': 'SUCCESS',
		'return_msg': 'OK'
	}
	header = {'Content-Type': 'application/xml'}
	config_mina = app.config['MINA_APP']
	target_wechat = WeChatService(merchant_key=config_mina['paykey'])
	callback_data = target_wechat.xml_to_dict( request.data )
	app.logger.info( callback_data  )
	sign = callback_data['sign']
	callback_data.pop( 'sign' )
	gene_sign = target_wechat.create_sign( callback_data )
	app.logger.info(gene_sign)
	if sign != gene_sign:
		result_data['return_code'] = result_data['return_msg'] = 'FAIL'
		return target_wechat.dict_to_xml(result_data), header
	if callback_data['result_code'] != 'SUCCESS':
		result_data['return_code'] = result_data['return_msg'] = 'FAIL'
		return target_wechat.dict_to_xml(result_data), header

	order_sn = callback_data['out_trade_no']
	pay_order_info = PayOrder.query.filter_by(order_sn=order_sn).first()
	if not pay_order_info:
		result_data['return_code'] = result_data['return_msg'] = 'FAIL'
		return target_wechat.dict_to_xml(result_data), header

	if int( pay_order_info.total_price * 100  ) != int( callback_data['total_fee'] ):
		result_data['return_code'] = result_data['return_msg'] = 'FAIL'
		return target_wechat.dict_to_xml(result_data), header

	if pay_order_info.status == 1:
		return target_wechat.dict_to_xml(result_data), header

	target_pay = PayService()
	target_pay.orderSuccess( pay_order_id = pay_order_info.id,params = { "pay_sn":callback_data['transaction_id'] } )
	target_pay.addPayCallbackData( pay_order_id = pay_order_info.id, data = request.data)
	return target_wechat.dict_to_xml(result_data), header

@route_api.route("/order/ops", methods=[ "POST"])
def orderOps():
	resp = {'code': 200, 'msg': '操作成功~', 'data': {}}
	req = request.values
	member_info = g.member_info
	order_sn = req['order_sn'] if 'order_sn' in req else ''
	act = req['act'] if 'act' in req else ''
	pay_order_info = PayOrder.query.filter_by(order_sn=order_sn, member_id=member_info.id).first()
	if not pay_order_info:
		resp['code'] = -1
		resp['msg'] = "系统繁忙。请稍后再试~~"
		return jsonify(resp)


	if act == "cancel":
		target_pay = PayService( )
		ret = target_pay.closeOrder( pay_order_id=pay_order_info.id )
		if not ret:
			resp['code'] = -1
			resp['msg'] = "系统繁忙。请稍后再试~~"
			return jsonify(resp)
	elif act == "confirm":
		pay_order_info.express_status = 1
		pay_order_info.updated_time = getCurrentDate()
		db.session.add( pay_order_info )
		db.session.commit()

	return jsonify(resp)
相关推荐
说私域2 小时前
社群经济视域下智能名片链动2+1模式商城小程序的商业价值重构
人工智能·小程序·重构·开源
说私域16 小时前
基于开源AI大模型、AI智能名片与商城小程序的购物中心“人货场车”全面数字化解决方案研究
人工智能·小程序·开源
陈思杰系统思考Jason19 小时前
系统思考:短期反馈与长期后果的冲突
百度·微信·微信公众平台·新浪微博·微信开放平台
计算机毕设指导619 小时前
基于微信小程序图像识别的智能垃圾分类系统【源码文末联系】
java·spring boot·mysql·微信小程序·小程序·分类·maven
qq_124987075320 小时前
基于微信小程序的科技助农系统的设计与实现(源码+论文+部署+安装)
java·大数据·spring boot·后端·科技·微信小程序·毕业设计
lsyhaoshuai21 小时前
微信小程序开发实战:打造一款功能完善的随机决策工具--小转盘-拯救困难选择症
微信小程序·小程序·notepad++
项目題供诗1 天前
微信小程序黑马优购(项目)(十)
微信小程序·小程序
计算机毕设指导61 天前
基于Django的本地健康宝微信小程序系统【源码文末联系】
java·后端·python·mysql·微信小程序·小程序·django
说私域1 天前
定制开发开源AI智能名片S2B2C商城小程序的产品经理职责与发展研究
人工智能·小程序·开源
一 乐2 天前
健身房预约|基于springboot + vue健身房预约小程序系统(源码+数据库+文档)
java·数据库·vue.js·spring boot·后端·学习·小程序