微信支付需要服务号、商户号和HTTPS域名,以下是具体说明:
一、服务号
-
申请服务号:必须申请微信服务号,且需以企业身份申请,服务号认证费用为300元每年。申请地址为:https://mp.weixin.qq.com/cgi。
-
开通权限:要实现服务号对接微信支付功能,需到微信公众平台>开发>接口权限页面,开通网页授权和微信支付权限。
二、商户号
-
获取商户号:登录微信公众号或微信小程序后台,确认“微信支付”部分的状态是“已申请”。申请通过后,会收到一封来自微信支付的邮件,邮件中有微信支付商户号等信息。也可在微信支付商户后台(pay.weixin.qq.com)->【账户中心】->【账户设置-商户信息】查看微信支付商户号。
-
配置密钥:到微信支付商户平台>账户中心>API安全页面的API密钥处设置密钥。
三、HTTPS域名
-
域名要求:域名必须通过ICP备案,且填写格式不包含“HTTP://”或“HTTPS://”。同时,域名必须支持SSL/TLS,即必须启用HTTPS协议,确保域名在公网可正常访问,且服务器稳定。
-
配置方法:
-
准备域名:若没有域名,可在域名注册服务商购买,并完成ICP备案。
-
设置HTTPS:为域名配置HTTPS证书,可通过Let’s Encrypt免费证书或云服务商提供的免费证书服务获取,并将证书部署到服务器上。
-
配置域名解析:登录域名服务商控制台,设置A记录,将域名指向服务器公网IP地址。
-
微信支付后台配置:登录微信支付商户平台,根据具体支付类型(如H5支付等)的配置路径,设置相应的支付域名,配置后一般10分钟内生效。
-
四、小程序开发
开发之前要选择对应的支付方式,不同的方式对应不同场景。
-
安装依赖:
-
推荐使用uni-app官方提供的uni-pay插件,或者从uni-app插件市场选择其他可靠的支付插件。
-
使用unified-payment插件,可在项目根目录中打开终端并输入以下命令进行安装:
npm install unified-payment
。安装完成后,需要在main.js
文件中引入插件。
-
-
获取登录凭证(code):
在小程序端,调用wx.login()
接口获取用户的登录凭证(code)。这个code是临时登录凭证,用于后续换取用户的openid。
wx.login({
success: function(res) {
if (res.code) {
// 发送 res.code 到后台换取 openId, sessionKey, unionId
}
}
});
3、获取openid:将获取的code发送到服务器端,服务器端使用code向微信服务器请求,获取用户的openid。openid是用户的唯一标识,用于后续创建订单和支付。
4、创建订单:
-
在服务器端,根据业务需求创建订单,并生成订单号。订单信息通常包括商品ID、数量、价格等
5、获取支付参数:
-
服务器端调用微信支付API,使用openid、订单号等信息生成预支付订单,并获取支付参数。这些参数包括:
-
appId
:公众账号ID。 -
timeStamp
:时间戳。 -
nonceStr
:随机字符串。 -
package
:数据包,格式为prepay_id=预支付会话标识
。 -
signType
:签名算法,目前支持MD5
。 -
paySign
:签名。
-
-
以下是一个服务器端获取微信支付参数的示例代码(使用Node.js + Koa):
const Koa = require('koa');
const Router = require('koa-router');
const request = require('request');
const crypto = require('crypto');
const app = new Koa();
const router = new Router();
router.post('/getWxPayParams', async (ctx) => {
const { openid, total_fee } = ctx.request.body;
const appid = '你的微信公众平台应用ID';
const mch_id = '你的商户号';
const nonce_str = Math.random().toString(36).substr(2, 15);
const body = '商品描述';
const out_trade_no = '订单号';
const spbill_create_ip = '用户IP';
const notify_url = '回调通知地址';
const trade_type = 'JSAPI';
const key = '你的API密钥';
const sign = createSign({
appid,
mch_id,
nonce_str,
body,
out_trade_no,
total_fee,
spbill_create_ip,
notify_url,
trade_type,
openid,
}, key);
const formData = `<xml>
<appid>${appid}</appid>
<mch_id>${mch_id}</mch_id>
<nonce_str>${nonce_str}</nonce_str>
<sign>${sign}</sign>
<body>${body}</body>
<out_trade_no>${out_trade_no}</out_trade_no>
<total_fee>${total_fee}</total_fee>
<spbill_create_ip>${spbill_create_ip}</spbill_create_ip>
<notify_url>${notify_url}</notify_url>
<trade_type>${trade_type}</trade_type>
<openid>${openid}</openid>
</xml>`;
const result = await new Promise((resolve, reject) => {
request({
url: 'https://api.mch.weixin.qq.com/pay/unifiedorder',
method: 'POST',
body: formData
}, (error, response, body) => {
if (!error && response.statusCode === 200) {
resolve(body);
} else {
reject(error);
}
});
});
const parseString = require('xml2js').parseString;
let res;
parseString(result, (err, json) => {
if (err) {
throw err;
}
res = json.xml;
});
const timeStamp = Math.floor(Date.now() / 1000).toString();
const nonceStr = res.nonce_str[0];
const prepay_id = res.prepay_id[0];
const paySign = createSign({
appId: appid,
timeStamp,
nonceStr,
package: `prepay_id=${prepay_id}`,
signType: 'MD5'
}, key);
ctx.body = {
appId: appid,
timeStamp,
nonceStr,
package: `prepay_id=${prepay_id}`,
signType: 'MD5',
paySign,
};
});
function createSign(params, key) {
const string = Object.keys(params).sort().map(k => `${k}=${params[k]}`).join('&') + `&key=${key}`;
return crypto.createHash('md5').update(string).digest('hex').toUpperCase();
}
app.use(router.routes());
app.listen(3000);
6、前端调用支付接口:
-
在前端(uni-app项目),当用户点击支付按钮时,前端将向服务器发送请求,获取上述支付参数。然后,使用uni-pay插件或其他支付插件,调用微信支付API的
wx.requestPayment()
方法,传入支付参数,拉起支付密码框,完成支付。
uni.requestPayment({
timeStamp: '时间戳',
nonceStr: '随机字符串',
package: 'prepay_id=预支付会话标识',
signType: '签名算法',
paySign: '签名',
success: function (res) {
console.log('支付成功', res);
},
fail: function (err) {
console.error('支付失败', err);
}
});
7、处理支付结果:根据支付成功或失败的回调函数中的逻辑进行处理,例如弹出提示框告知用户支付结果。