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)
相关推荐
说私域7 小时前
基于AI智能名片链动2+1模式服务预约商城系统的社群运营与顾客二次消费吸引策略研究
大数据·人工智能·小程序·开源·流量运营
StarChainTech12 小时前
无人机租赁平台:开启智能租赁新时代
大数据·人工智能·微信小程序·小程序·无人机·软件需求
计算机毕设指导612 小时前
基于微信小程序的运动场馆服务系统【源码文末联系】
java·spring boot·微信小程序·小程序·tomcat·maven·intellij-idea
码农客栈13 小时前
小程序学习(十一)之uni-app和原生小程序开发区别
学习·小程序·uni-app
说私域14 小时前
基于AI客服链动2+1模式商城小程序的社群运营策略研究——以千人社群活跃度提升为例
人工智能·微信·小程序·私域运营
mqjFKmYf14 小时前
VSC整流系统定功率控制系统的MATLAB仿真模型(支持MATLAB 2014a及以上版本)
小程序
Json____15 小时前
使用uni-app开发抖音小程序遇到previewImage方法图片加载不出来解决方案
小程序·uni-app
枕咸鱼的猫15 小时前
【龙雏晴雨通】实时查看天气小程序
微信小程序
毕设源码-钟学长15 小时前
【开题答辩全过程】以 基于微信小程序教学评价平台的设计与实现为例,包含答辩的问题和答案
微信小程序·小程序
说私域16 小时前
基于AI智能名片链动2+1模式S2B2C商城小程序的流量运营策略研究
人工智能·微信·小程序·产品运营·流量运营