小程序支付与电商功能是微信小程序中非常重要的一部分,通过支付功能可以实现用户购买商品、支付订单等功能。下面将介绍小程序支付的接入和配置以及实现电商功能和订单管理的方法。
在使用小程序支付功能之前,需要先在微信支付平台注册商户号,并获取商户号和密钥。商户号是用于标识商户的唯一编号,密钥用于加密和签名支付请求。
在小程序开发者工具中,找到项目目录下的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
为密钥。
在小程序中实现支付功能,需要先创建一个支付订单,并将订单信息发送给微信支付平台。下面是一个创建支付订单的示例代码:
// 获取当前时间戳
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
接口进行支付时,需要传入时间戳、随机字符串、预支付订单号等参数,并对这些参数进行签名。
在支付流程中,支付完成后,微信支付平台会向开发者服务器发送一个支付通知,通知开发者订单的支付状态。因此,需要配置支付通知回调的接口。
下面是一个简单的支付通知回调接口的示例代码:
// 引入相关库和模块
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-parser
和xml2js
库来解析支付通知的报文。
在支付通知回调的接口中,首先使用xml2js
库将报文解析为JSON格式的数据。然后,根据解析后的数据进行相应的处理,比如更新订单的支付状态。
最后,需要将处理结果返回给微信支付平台,以确保支付通知的正确处理。示例代码中使用xml2js
库将回复数据转换为XML格式,并通过res.send
方法返回给微信支付平台。
在实现电商功能和订单管理方面,需要考虑以下几个关键点:
下面是一个简单的示例代码,实现了电商功能和订单管理的示例:
// pages/index/index.js
Page({
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章的内容。