微信小程序开发教学系列(13)- 小程序支付与电商功能

13. 小程序支付与电商功能

小程序支付与电商功能是微信小程序中非常重要的一部分,通过支付功能可以实现用户购买商品、支付订单等功能。下面将介绍小程序支付的接入和配置以及实现电商功能和订单管理的方法。

13.1 小程序支付的接入和配置

13.1.1 获取微信支付商户号和密钥

在使用小程序支付功能之前,需要先在微信支付平台注册商户号,并获取商户号和密钥。商户号是用于标识商户的唯一编号,密钥用于加密和签名支付请求。

13.1.2 配置小程序支付

在小程序开发者工具中,找到项目目录下的project.config.json文件,添加以下配置项:

{"appid": "Your AppID","projectname": "Your Project Name","setting": {"urlCheck": true,"es6": false,"postcss": false,"minified": true,"newFeature": true},"payment": {"merchantId": "Your Merchant ID","key": "Your Merchant Key"}
}

其中,appid为小程序的AppID,merchantId为商户号,key为密钥。

13.1.2 创建支付订单

在小程序中实现支付功能,需要先创建一个支付订单,并将订单信息发送给微信支付平台。下面是一个创建支付订单的示例代码:

// 获取当前时间戳
function getTimestamp() {return parseInt(Date.now() / 1000).toString();
}// 生成随机字符串
function getRandomString(len) {len = len || 32;var chars = 'ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789';var maxPos = chars.length;var randomString = '';for (var i = 0; i < len; i++) {randomString += chars.charAt(Math.floor(Math.random() * maxPos));}return randomString;
}// 创建支付订单
function createPaymentOrder(totalPrice) {// 生成随机订单号var orderNo = getRandomString(16);// 获取当前时间戳var timestamp = getTimestamp();// 构造支付参数var params = {appid: 'Your AppID',mch_id: 'Your Merchant ID',nonce_str: getRandomString(),body: '订单支付',out_trade_no: orderNo,total_fee: totalPrice * 100, // 将价格转换为分spbill_create_ip: '127.0.0.1',notify_url: 'https://yourdomain.com/pay/notify',trade_type: 'JSAPI',openid: 'Your User OpenID'};// 对支付参数进行签名params.sign = createSign(params);// 发送请求到后端生成预支付订单wx.request({url: 'https://yourdomain.com/pay/create',method: 'POST',data: params,success: function(res) {// 获取预支付订单号var prepayId = res.data.prepay_id;// 调用微信支付接口wx.requestPayment({timeStamp: timestamp,nonceStr: params.nonce_str,package: 'prepay_id=' + prepayId,signType: 'MD5',paySign: createSign({timeStamp: timestamp,nonceStr: params.nonce_str,package: 'prepay_id=' + prepayId,signType: 'MD5',appId: 'Your AppID',key: 'Your Merchant Key'}),success: function(res) {// 支付成功回调console.log('支付成功');},fail: function(res) {// 支付失败回调console.log('支付失败');}});},fail: function(res) {console.log('生成预支付订单失败');}});
}

以上代码中的createSign函数用于对支付参数进行签名,createSign函数的具体实现可以参考微信支付官方文档。

在调用wx.requestPayment接口进行支付时,需要传入时间戳、随机字符串、预支付订单号等参数,并对这些参数进行签名。

13.1.3 配置支付通知回调

在支付流程中,支付完成后,微信支付平台会向开发者服务器发送一个支付通知,通知开发者订单的支付状态。因此,需要配置支付通知回调的接口。

下面是一个简单的支付通知回调接口的示例代码:

// 引入相关库和模块
const express = require('express');
const bodyParser = require('body-parser');
const xml2js = require('xml2js');const app = express();
app.use(bodyParser.raw({ type: 'text/xml' }));// 支付通知回调接口
app.post('/pay/notify', (req, res) => {var parser = new xml2js.Parser({ explicitArray: false });parser.parseString(req.body.toString('utf-8'), (err, result) => {if (err) {console.log('解析支付通知报文失败');res.send('FAIL');} else {var responseData = {return_code: 'SUCCESS',return_msg: 'OK'};var xmlBuilder = new xml2js.Builder({ cdata: true, rootName: 'xml' });var xmlData = xmlBuilder.buildObject(responseData);res.send(xmlData);// 处理订单的支付状态var orderNo = result.xml.out_trade_no;var totalFee = parseFloat(result.xml.total_fee) / 100;var transactionId = result.xml.transaction_id;// 更新订单的支付状态updateOrderStatus(orderNo, totalFee, transactionId);}});
});// 启动服务器
app.listen(80, () => {console.log('Server started on port 80');
});

以上代码中,示例代码使用的是Node.js的Express框架来搭建一个简单的服务器,并使用了body-parserxml2js库来解析支付通知的报文。

在支付通知回调的接口中,首先使用xml2js库将报文解析为JSON格式的数据。然后,根据解析后的数据进行相应的处理,比如更新订单的支付状态。

最后,需要将处理结果返回给微信支付平台,以确保支付通知的正确处理。示例代码中使用xml2js库将回复数据转换为XML格式,并通过res.send方法返回给微信支付平台。

13.2 实现电商功能和订单管理

在实现电商功能和订单管理方面,需要考虑以下几个关键点:

  • 商品列表展示:展示商品的名称、价格、图片等信息,并提供购买按钮。
  • 购物车功能:用户可以将商品添加到购物车,并进行数量的调整和删除等操作。
  • 订单生成和管理:用户可以将购物车中的商品生成订单,并管理订单的支付状态和物流信息等。

下面是一个简单的示例代码,实现了电商功能和订单管理的示例:

// pages/index/index.jsPage({data: {productList: [{id: 1,name: "商品1",price: 10,image: "http://example.com/product1.jpg"},{id: 2,name: "商品2",price: 20,image: "http://example.com/product2.jpg"},// 其他商品...],cartList: [],orderList: []},// 添加商品到购物车addToCart(e) {const productId = e.currentTarget.dataset.id;const product = this.data.productList.find(item => item.id === productId);// 将商品添加到购物车const cartItem = this.data.cartList.find(item => item.id === productId);if (cartItem) {cartItem.quantity += 1;} else {this.data.cartList.push({id: product.id,name: product.name,price: product.price,quantity: 1});}// 更新购物车数据this.setData({cartList: this.data.cartList});},// 从购物车移除商品removeFromCart(e) {const productId = e.currentTarget.dataset.id;// 从购物车中移除指定商品const cartIndex = this.data.cartList.findIndex(item => item.id === productId);if (cartIndex >= 0) {this.data.cartList.splice(cartIndex,1);// 更新购物车数据this.setData({cartList: this.data.cartList});}},// 生成订单createOrder() {// 生成订单号const orderNo = Date.now().toString();// 将购物车中的商品生成订单const orderItems = this.data.cartList.map(item => ({id: item.id,name: item.name,price: item.price,quantity: item.quantity}));// 创建订单对象const order = {orderNo: orderNo,items: orderItems,totalAmount: this.calculateTotalAmount(),status: '待支付'};// 将订单添加到订单列表中this.data.orderList.push(order);// 清空购物车this.setData({cartList: []});// 更新订单列表数据this.setData({orderList: this.data.orderList});},// 计算购物车中商品总金额calculateTotalAmount() {let total = 0;this.data.cartList.forEach(item => {total += item.price * item.quantity;});return total;},// 支付订单payOrder(e) {const orderNo = e.currentTarget.dataset.orderno;const orderIndex = this.data.orderList.findIndex(item => item.orderNo === orderNo);if (orderIndex >= 0) {const order = this.data.orderList[orderIndex];// 调用支付接口wx.requestPayment({timeStamp: '',nonceStr: '',package: '',signType: '',paySign: '',success: res => {// 支付成功,更新订单状态为已支付order.status = '已支付';// 更新订单列表数据this.setData({orderList: this.data.orderList});// 弹窗提示支付成功wx.showToast({title: '支付成功',icon: 'success'});},fail: res => {// 支付失败,更新订单状态为支付失败order.status = '支付失败';// 更新订单列表数据this.setData({orderList: this.data.orderList});// 弹窗提示支付失败wx.showToast({title: '支付失败',icon: 'none'});}});},// 取消订单cancelOrder(e) {const orderNo = e.currentTarget.dataset.orderno;const orderIndex = this.data.orderList.findIndex(item => item.orderNo === orderNo);if (orderIndex >= 0) {// 从订单列表中移除订单this.data.orderList.splice(orderIndex, 1);// 更新订单列表数据this.setData({orderList: this.data.orderList});// 弹窗提示取消成功wx.showToast({title: '取消成功',icon: 'success'});}}
})

在上述代码中,我们定义了一些与电商功能相关的函数。

  • createOrder函数用于生成订单。首先生成订单号,然后将购物车中的商品转换为订单项,并计算订单的总金额。接下来,将订单添加到订单列表中,并清空购物车。最后,更新订单列表的数据。

  • calculateTotalAmount函数用于计算购物车中商品的总金额。

  • payOrder函数用于支付订单。首先获取需要支付的订单号和订单索引,然后调用wx.requestPayment接口进行支付。支付成功后,更新订单状态为已支付,并更新订单列表数据。支付失败时,更新订单状态为支付失败。

  • cancelOrder函数用于取消订单。首先获取需要取消的订单号和订单索引,然后从订单列表中移除该订单。最后,更新订单列表数据并弹出提示框显示取消成功。

以上是一个简单的电商功能示例,包括生成订单、支付订单和取消订单。你可以根据自己的需求进行修改和扩展。

接下来,需要在小程序的页面中添加相应的布局和交互,以及页面跳转和数据传递的逻辑。详细的页面设计和布局步骤可以参考前面的第3章和第4章的内容。

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.mzph.cn/news/56968.shtml

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

Pygame编程(1)初始化和退出模块

初始化和退出模块 pygame使用基础流程 初始化模块设置主屏窗口程序主循环&#xff08;处理键盘、鼠标、游戏杆、触摸屏等事件&#xff09;退出模块终止程序 import sys import pygame from pygame.locals import *# 1.初始化模块 pygame.init()# 2.设置主屏窗口 display pyg…

SocketTools.NET 11.0.2148.1554 Crack

添加新功能以简化使用 URL 建立 TCP 连接的过程。 2023 年 8 月 23 日 - 12:35新版本 特征 添加了“HttpGetTextEx”函数&#xff0c;该函数在返回字符串缓冲区中的文本内容时提供附加选项。添加了对“FileTransfer”.NET 类和 ActiveX 控件中的“GetText”和“PutText”方法的…

HDLBits-Verilog学习记录 | Verilog Language-Modules(1)

文章目录 20.Module21.Connecting ports by position | Moudle pos22.Connecting ports by name | Module name23.Three modules | Module shift24.Modules and vectors | Module shift8 20.Module practice:You may connect signals to the module by port name or port posi…

FFmpeg支持多线程编码并保存mp4文件示例

之前介绍的示例&#xff1a; (1).https://blog.csdn.net/fengbingchun/article/details/132129988 中对编码后数据保存成mp4 (2).https://blog.csdn.net/fengbingchun/article/details/132128885 中通过AVIOContext实现从内存读取数据 (3).https://blog.csdn.net/fengbingchun/…

几个nlp的小任务(机器翻译)

几个nlp的小任务(机器翻译) 安装依赖库数据集介绍与模型介绍加载数据集看一看数据集的样子评测测试数据预处理测试tokenizer处理目标特殊的token预处理函数对数据集的所有数据进行预处理微调预训练模型设置训练参数需要一个数据收集器,把处理好数据喂给模型设置评估方法参数…

美团面试拷打:ConcurrentHashMap 为何不能插入 null?HashMap 为何可以?

周末的时候,有一位小伙伴提了一些关于 ConcurrentHashMap 的问题,都是他最近面试遇到的。原提问如下(星球原贴地址:https://t.zsxq.com/11jcuezQs ): 整个提问看着非常复杂,其实归纳来说就是两个问题: ConcurrentHashMap 为什么 key 和 value 不能为 null?ConcurrentH…

【C++ 学习 ⑱】- 多态(上)

目录 一、多态的概念和虚函数 1.1 - 用基类指针指向派生类对象 1.2 - 虚函数和虚函数的重写 1.3 - 多态构成的条件 1.4 - 多态的应用场景 二、协变和如何析构派生类对象 2.1 - 协变 2.2 - 如何析构派生类对象 三、C11 的 override 和 final 关键字 一、多态的概念和虚…

mysql建表问题

问题 例如用户表,我们需要建一个字段是创建时间, 一个字段是更新时间. 解决办法可以是指定插入时间,也可以使用数据库的默认时间. 在mysql中如果设置两个默认CURRENT_TIMESTAMP,会出现这样的错误. Error Code: 1293. Incorrect table definition; there can be only one TIMES…

算法通关村第十一关——位运算实现加减乘除

在计算机中&#xff0c;位运算的效率比加减乘除效率更高。 1.位运算实现加法 力扣371题&#xff0c; 给你两个整数 a 和 b &#xff0c;不使用 运算符 和-&#xff0c;计算并返回两整数之和。 分析&#xff1a;不让用运算符&#xff0c;就只能使用位运算。先来看一下两位二进…

【面试经典150题】删除有序数组中的重复项Ⅱ JavaScript

题目来源。 给你一个有序数组 nums &#xff0c;请你** 原地** 删除重复出现的元素&#xff0c;使得出现次数超过两次的元素只出现两次 &#xff0c;返回删除后数组的新长度。 不要使用额外的数组空间&#xff0c;你必须在 原地 修改输入数组 并在使用 O(1) 额外空间的条件下…

程序自动分析——并查集+离散化

在实现程序自动分析的过程中&#xff0c;常常需要判定一些约束条件是否能被同时满足。考虑一个约束满足问题的简化版本&#xff1a;假设 x1,x2,x3,… 代表程序中出现的变量&#xff0c;给定 n 个形如 xixj 或 xi≠xj 的变量相等/不等的约束条件&#xff0c;请判定是否可以分别为…

Matlab 生成一定信噪比的信号

文章目录 【 1. 信噪比 】【 2. 功率归一化 】2.1 实信号+实噪声2.2 实信号+复噪声【 3. 能量归一化 】3.1 实信号+实噪声3.2 实信号+复噪声【 4. 小结 】【 1. 信噪比 】 信噪比公式 1 : S N R = 10 ∗ l o g 10 P s P n 信噪比公式1:SNR=10*log_{10}\frac{P_s}{P_n} 信噪比…

webrtc的Sdp中的Plan-b和UnifiedPlan

在一些类似于视频会议场景下&#xff0c;媒体会话参与者需要接收或者发送多个流&#xff0c;例如一个源端&#xff0c;同时发送多个左右音轨的音频&#xff0c;或者多个摄像头的视频流&#xff1b;在2013年&#xff0c;提出了2个不同的SDP IETF草案Plan B和Unified Plan&#x…

【uniapp 上传图片示例】

以下是 uniapp 上传图片的详细步骤示例&#xff1a; 定义一个方法&#xff0c;用于选择图片并上传&#xff1a; methods: {chooseImage() {uni.chooseImage({count: 1, // 最多选择的图片数量sizeType: [original, compressed], // 可以指定原图或压缩图sourceType: [album, …

android framework之Applicataion启动流程分析

Application启动流程分析 启动方式一&#xff1a;通过Launcher启动app 启动方式二&#xff1a;在某一个app里启动第二个app的Activity. 以上两种方式均可触发app进程的启动。但无论哪种方式&#xff0c;最终通过通过调用AMS的startActivity()来启动application的。 根据上图…

ABeam×Startup | 德硕管理咨询(深圳)创新研究团队拜访微漾创客空间

近日&#xff0c;德硕管理咨询&#xff08;深圳&#xff09;&#xff08;以下简称&#xff1a;“ABeam-SZ”&#xff09;创新研究团队前往微漾创客空间&#xff08;以下简称&#xff1a;微漾&#xff09;拜访参观&#xff0c;并展开合作交流。会议上&#xff0c;双方相互介绍了…

每日一题 57. 插入区间

读研了&#xff0c;开始用python刷题 今天的题目是力扣 每日一题 57. 插入区间 难度&#xff1a;中等 思路&#xff1a; 处理新区间起点&#xff0c;要么在两个老区间之间&#xff0c;要么被一个老区间包含处理新区间中点&#xff0c;同起点一样 我的代码如下 class Solut…

解锁市场进入成功:GTM 策略和即用型示例

在最初的几年里&#xff0c;创办一家初创公司可能会充满挑战。根据美国小企业管理局的数据&#xff0c;大约三分之二的新成立企业存活了两年&#xff0c;几乎一半的企业存活了五年以上。导致创业失败的因素有市场需求缺失、资金短缺、团队不合适、成本问题等。由此&#xff0c;…

合宙Air724UG LuatOS-Air LVGL API控件--按钮 (Button)

按钮 (Button) 按钮控件&#xff0c;这个就不用多说了&#xff0c;界面的基础控件之一。 示例代码 – 按键回调函数 event_handler function(obj, event) if event lvgl.EVENT_CLICKED then print(“Clicked\n”) elseif event lvgl.EVENT_VALUE_CHANGED then print(“To…

服务器数据库中了locked勒索病毒怎么办,locked勒索病毒恢复工具

最近一段时间网络上的locked勒索病毒非常嚣张&#xff0c;自从6月份以来&#xff0c;很多企业的计算机服务器数据库遭到了locked勒索病毒的攻击&#xff0c;起初locked勒索病毒攻击用友畅捷通T用户&#xff0c;后来七月份开始攻击金蝶云星空客户&#xff0c;导致企业的财务系统…