| 123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155 |
- const cloud = require('wx-server-sdk');
- cloud.init({ env: cloud.DYNAMIC_CURRENT_ENV });
- const db = cloud.database();
- // 支付成功回调(微信支付结果通知)
- // 处理:能量师订阅升级 + 佣金结算
- exports.main = async (event) => {
- const {
- outTradeNo, // 订单号
- transactionId, // 微信支付订单号
- totalFee, // 支付金额(分)
- attach, // 附加数据
- } = event;
- // 获取支付用户的 openId
- const { OPENID } = cloud.getWXContext();
- try {
- // 1. 查询订单是否已处理(幂等)
- const orderRes = await db.collection('orders').where({
- outTradeNo,
- }).get();
- if (orderRes.data.length > 0) {
- return { code: 0, message: '订单已处理' };
- }
- // 2. 写订单记录
- const orderData = {
- outTradeNo,
- transactionId,
- userId: OPENID,
- type: 'practitioner_annual',
- amount: totalFee,
- paymentMethod: 'wechat_pay',
- status: 'paid',
- paidAt: db.serverDate(),
- createdAt: db.serverDate(),
- };
- await db.collection('orders').add({ data: orderData });
- // 3. 更新用户为能量师(有效期 1 年)
- const now = new Date();
- const expireDate = new Date(now);
- expireDate.setFullYear(expireDate.getFullYear() + 1);
- // 查询已有用户
- const userRes = await db.collection('users').where({
- _openid: OPENID,
- }).get();
- const userData = {
- role: 'practitioner',
- practitionerExpireAt: expireDate.toISOString(),
- updatedAt: db.serverDate(),
- };
- if (userRes.data.length === 0) {
- // 新用户注册(一般不会走到这里,但以防万一)
- userData._openid = OPENID;
- userData.referralCode = generateReferralCode();
- userData.createdAt = db.serverDate();
- await db.collection('users').add({ data: userData });
- } else {
- // 已有用户,生成或保留推广码
- const user = userRes.data[0];
- if (!user.referralCode) {
- userData.referralCode = generateReferralCode();
- }
- await db.collection('users').doc(user._id).update({ data: userData });
- }
- // 4. 佣金结算:查用户的上级
- const user = (await db.collection('users').where({ _openid: OPENID }).get()).data[0];
- const invitedBy = user.invitedBy;
- if (invitedBy) {
- // 查上级是否为有效的能量师
- const parentRes = await db.collection('users').where({ _openid: invitedBy }).get();
- if (parentRes.data.length > 0) {
- const parent = parentRes.data[0];
- const isParentPractitioner = parent.practitionerExpireAt
- && new Date(parent.practitionerExpireAt).getTime() > Date.now();
- if (isParentPractitioner) {
- // 一级佣金:30%
- const level1Amount = Math.round(totalFee * 0.30);
- await db.collection('commissions').add({
- data: {
- fromUser: OPENID,
- toUser: invitedBy,
- level: 1,
- amount: level1Amount,
- sourceOrderId: outTradeNo,
- status: 'pending',
- createdAt: db.serverDate(),
- updatedAt: db.serverDate(),
- },
- });
- // 更新上级的推广统计
- const stats = parent.referralStats || {};
- await db.collection('users').doc(parent._id).update({
- data: {
- 'referralStats.convertedCount': (stats.convertedCount || 0) + 1,
- },
- });
- // 查上上级(二级佣金)
- const grandParentInvitedBy = parent.invitedBy;
- if (grandParentInvitedBy) {
- const gpRes = await db.collection('users').where({ _openid: grandParentInvitedBy }).get();
- if (gpRes.data.length > 0) {
- const gp = gpRes.data[0];
- const isGpPractitioner = gp.practitionerExpireAt
- && new Date(gp.practitionerExpireAt).getTime() > Date.now();
- if (isGpPractitioner) {
- // 二级佣金:10%
- const level2Amount = Math.round(totalFee * 0.10);
- await db.collection('commissions').add({
- data: {
- fromUser: OPENID,
- toUser: grandParentInvitedBy,
- level: 2,
- amount: level2Amount,
- sourceOrderId: outTradeNo,
- status: 'pending',
- createdAt: db.serverDate(),
- updatedAt: db.serverDate(),
- },
- });
- }
- }
- }
- }
- }
- }
- return { code: 0, message: 'success' };
- } catch (err) {
- console.error('[paymentCallback] error:', err);
- return { code: 500, error: err.message };
- }
- };
- // 生成唯一6位推广码
- function generateReferralCode() {
- const chars = 'ABCDEFGHJKLMNPQRSTUVWXYZ23456789';
- let code = '';
- for (let i = 0; i < 6; i++) {
- code += chars[Math.floor(Math.random() * chars.length)];
- }
- return code;
- }
|