123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175 |
- /* eslint-disable eqeqeq */
- 'use strict';
- const Service = require('egg').Service;
- const WxPay = require('wechatpay-node-v3');
- const fs = require('fs');
- const path = require('path');
- // 微信支付操作类
- class WxPayService extends Service {
- /**
- * 发起商家转账到零钱
- * @return {Promise<void>}
- */
- async transfer(data) {
- const that = this;
- const userInfo = await that.app.model.Users.findOne({
- where: { user_id: data.user_id },
- attributes: [ 'openid' ],
- raw: true,
- });
- const keys = [ 'wx_pay_serial_no', 'wechat_account_appid', 'wechat_pay_key', 'wx_pay_mchid' ];
- const config = await that.service.configs.getConfigMoreValue(keys);
- // 2023/1/11 微信支付配置初始化
- const wxPay = new WxPay({
- appid: config.wechat_account_appid, // 公众号appid
- mchid: config.wx_pay_mchid, // 微信支付商户号
- serial_no: config.wx_pay_serial_no, // 微信支付证书序列号
- key: config.wechat_pay_key, // APIv3密钥
- // publicKey: fs.readFileSync('./apiclient_cert.pem'), // 公钥
- publicKey: fs.readFileSync(path.join(__dirname, './apiclient_cert.pem'), 'utf8'), // 公钥
- // privateKey: fs.readFileSync('./apiclient_key.pem'), // 秘钥
- privateKey: fs.readFileSync(path.join(__dirname, './apiclient_key.pem'), 'utf8'), // 秘钥
- });
- const certificates = await wxPay.get_certificates(config.wechat_pay_key);
- // 取最后一个
- const certificate = certificates.pop();
- // 当前时间戳作为商家批次单号
- const timestamp = parseInt(+new Date() + '')
- .toString();
- // 2023/1/12 构造转账参数
- const cashAmount = Math.floor(data.cash_amount * 100);
- const bodyData = {
- out_batch_no: 'cash' + timestamp,
- batch_name: '佣金提现',
- batch_remark: data.remark ? data.remark : '佣金提现',
- total_amount: cashAmount,
- total_num: 1,
- wx_serial_no: certificate.serial_no, // 当你需要传user_name时 需要传当前参数
- transfer_detail_list: [
- {
- out_detail_no: 'cashd' + timestamp,
- transfer_amount: cashAmount,
- transfer_remark: data.remark ? data.remark : '佣金提现',
- openid: userInfo.openid,
- // user_name: wxPay.publicEncrypt('name', Buffer.from(certificate.publicKey)), // 真实姓名转换
- },
- ],
- };
- const res = await wxPay.batches_transfer(bodyData);
- if (res.status == 200) {
- // 2023/2/1 成功发起转账
- // 2023/2/1 提现记录
- const logData = {
- out_batch_no: bodyData.out_batch_no,
- out_detail_no: 'cashd' + timestamp,
- batch_id: res.data.batch_id,
- detail_status: 'INIT',
- batch_name: '佣金提现',
- batch_remark: data.remark ? data.remark : '佣金提现',
- user_id: data.user_id,
- cash: data.cash_amount,
- type: 2, // 提现中
- create_time: that.app.szjcomo.date('Y-m-d H:i:s'),
- };
- await that.service.cash.addCashLog(logData);
- // 2023/2/1 佣金变化记录(提现转帐中)
- const commParams = {
- user_id: data.user_id, type: 2, commission: -data.cash_amount, log_desc: '提现转帐中...',
- out_batch_no: logData.out_batch_no, out_detail_no: logData.out_detail_no,
- };
- await that.service.commission.addCommissionChangeLog(commParams);
- setTimeout(() => {
- // 请等待批次处理完成后再查询明细单据 大约9s左右后可以查询转账结果
- that.getTransferResult(logData);
- }, 12000);
- } else {
- that.logger.error('用户提现失败:status %s ,errorCode:%s ,msg:%s', res.status, res.error.code, res.error.message);
- }
- return res;
- }
- /**
- * 查询提现状态 并 更新状态
- * @return {Promise<void>}
- */
- async getTransferResult(param) {
- const that = this;
- const keys = [ 'wx_pay_serial_no', 'wechat_account_appid', 'wechat_pay_key', 'wx_pay_mchid' ];
- const config = await that.service.configs.getConfigMoreValue(keys);
- // 2023/1/11 微信支付配置初始化
- const wxPay = new WxPay({
- appid: config.wechat_account_appid, // 公众号appid
- mchid: config.wx_pay_mchid, // 微信支付商户号
- serial_no: config.wx_pay_serial_no, // 微信支付证书序列号
- key: config.wechat_pay_key, // APIv3密钥
- // publicKey: fs.readFileSync('./apiclient_cert.pem'), // 公钥
- publicKey: fs.readFileSync(path.join(__dirname, './apiclient_cert.pem'), 'utf8'), // 公钥
- // privateKey: fs.readFileSync('./apiclient_key.pem'), // 秘钥
- privateKey: fs.readFileSync(path.join(__dirname, './apiclient_key.pem'), 'utf8'), // 秘钥
- });
- // 商家明细单号查询明细单API
- const res = await wxPay.query_batches_transfer_detail({
- out_batch_no: param.out_batch_no,
- out_detail_no: param.out_detail_no,
- });
- if (res.status == 200) {
- let cashType;
- let commissionType;
- let log_desc;
- if (res.data.detail_status == 'SUCCESS') {
- cashType = 1;
- commissionType = 0;
- log_desc = '提现成功';
- // 2023/2/2 更新分佣账户余额
- const updateBean = await that.app.comoBean.instance({
- commission: that.app.Sequelize.literal('commission - ' + param.cash),
- update_time: that.app.szjcomo.date('Y-m-d H:i:s'),
- }, { where: { user_id: param.user_id } });
- await that.app.comoBean.update(updateBean, that.app.model.Users, '用户分佣金额更新失败,请稍候重试');
- } else if (res.data.detail_status == 'FAIL') {
- cashType = 0;
- commissionType = -1;
- log_desc = '提现失败';
- } else {
- cashType = 2;
- commissionType = 2;
- log_desc = '提现转账中...';
- }
- // 2023/2/1 更新提现记录
- const updateBean = await that.app.comoBean.instance({
- type: cashType, // 2023/2/1 提现转账状态
- detail_id: res.data.detail_id,
- detail_status: res.data.detail_status,
- fail_reason: res.data.fail_reason,
- update_time: that.app.szjcomo.date('Y-m-d H:i:s'),
- }, {
- where: {
- out_batch_no: param.out_batch_no,
- out_detail_no: param.out_detail_no,
- },
- });
- await that.service.base.update(updateBean, that.app.model.UsersCashLogs, '更新提现记录失败');
- // 2023/2/1 更新佣金变化状态记录
- const commBean = await that.app.comoBean.instance({
- type: commissionType,
- log_desc,
- }, {
- where: {
- out_batch_no: param.out_batch_no,
- out_detail_no: param.out_detail_no,
- },
- });
- await that.service.base.update(commBean, that.app.model.UsersCommissionLogs, '更新佣金变化失败');
- } else {
- that.logger.error('提现状态查询失败:status %s ,msg:400 PARAM_ERROR参数错误;404 NOT_FOUND记录不存在;429 FREQUENCY_LIMITED频率超限',
- res.status);
- }
- return res;
- }
- }
- module.exports = WxPayService;
|