'use strict'; const { CrudService } = require('naf-framework-mongoose-free/lib/service'); const { BusinessError, ErrorCode } = require('naf-core').Error; const _ = require('lodash'); const assert = require('assert'); // class PayService extends CrudService { constructor(ctx) { super(ctx, 'pay'); this.httpUtil = this.ctx.service.util.httpUtil; this.appConfig = 'pointApp'; this.orderModel = this.ctx.model.Trade.Order; this.dictDataModel = this.ctx.model.Dev.DictData; this.payOrderReturnUrl = this.app.config.payReturn.order; this.wxDomain = _.get(this.app, 'config.httpPrefix.wechat'); } /** * 去支付订单 * 1.有支付方式之分; 微信/支付宝 * 2.根据不同方式去请求 * @param {Object} body 请求体 * @param body.order_id 订单id * @param body.type 支付方式 */ async toPayOrder({ order_id, type }) { const payWay = await this.dictDataModel.findOne({ value: type, status: '0' }); if (!payWay) throw new BusinessError(ErrorCode.DATA_INVALID, '该支付方式暂时无法使用'); const order = await this.orderModel.findById(order_id); if (!order) throw new BusinessError(ErrorCode.DATA_NOT_EXIST, '未找到订单数据'); const { no, pay } = order; // 检查是否有支付信息如果有的话,支付方式是否一致 if (Object.keys(pay).length > 0) { const pay_type = _.get(pay, 'pay_type'); // 支付方式不同,则将支付内容刷掉,重新进行数据生成 if (pay_type === type) { // 支付方式相同,则再找有没有支付订单 const pay_no = _.get(pay, 'pay_no'); if (pay_no) { // 有支付订单.则先查支付订单是否可以继续支付 // TODO: // 1.当前用户和之前下单支付的用户的openid是不是一个人.是一个人=>2;不是一个人=>3 // 2.需要关闭之前的支付订单并且重新进行支付: 关闭订单.再放到下面 // 3.查询订单是否过期 没过期=>4; 过期=>5 // 4.继续支付:取出数据,return; // 5.放到下面.重新支付 } // 没有的话,就说明数据有问题.按照没有支付信息处理即可 } } // 没有支付信息(要是有支付信息,上面直接return了.漏下来的都是没有的处理方案) const str = this.ctx.service.util.trade.createNonceStr(); const arr = no.split('-'); // 订单中pay的信息 const payObject = { pay_type: type, pay_no: `${_.last(arr)}-${str}` }; const totalMoney = this.getOrderNeedPay(order); // 找到当前用户的openid:这里涉及问题是: 如果自己下单,自己付款.那没有问题; // 如果是自己下单.如果使用账号密码登录再付款.还用下单的人找到的openid就不能在这个微信号上进行支付了; // 所以此处是需要用当前用户的openid进行支付,如果之前生成单子.还需要检查当前用户的openid和之前的openid是否一致 // 如果不一致.则需要将之前的订单关闭,重新生成 // 请求微信支付接口的数据 if (type === '0') { const toPayData = { config: this.appConfig, money: totalMoney, openid: '', order_no: payObject.pay_no, desc: '购物', notice_url: this.payOrderReturnUrl('order_id') }; } } /** * 支付订单回调函数 * @param {Object} param 请求地址参数 * @param param.order 订单id */ async callBackPayOrder({ order }) {} /** * 计算订单需支付的金额 * @param {Object} order 要支付的订单数据 */ getOrderNeedPay(order) { let total = 0; const { total_detail = {} } = order; for (const key in total_detail) { total = _.floor(total_detail[key] + total); } return total; } /** * 查询订单 * @param {String} order_no 订单号 */ async search(order_no) { assert(order_no, '缺少订单号,无法查询订单信息'); const params = { config: this.appConfig, order_no }; const url = `${this.wxDomain}/pay/searchOrderByOrderNo`; const wxOrderReq = await this.httpUtil.cpost(url, params); return wxOrderReq; } /** * 创建订单,获取微信支付签名 * @param {Object} data 数据 */ async create(data) { const { money, openid, order_no, desc } = data; const wxOrderData = { config: this.appConfig, money, openid, order_no, desc }; const url = `${this.wxDomain}/pay/payOrder`; const res = await this.httpUtil.cpost(url, wxOrderData); if (res) return res; throw new BusinessError(ErrorCode.SERVICE_FAULT, '微信下单失败!'); } /** * 关闭订单 * @param {String} order_no 订单号 */ async close(order_no) { assert(order_no, '缺少订单号,无法查询订单信息'); const params = { config: this.appConfig, order_no }; const url = `${this.wxDomain}/pay/closeOrder`; const res = await this.httpUtil.cpost(url, params); return res || 'ok'; } /** * TODO 退款,金额需要指定.可能是部分退款,也可能是全额退款 * @param {String} order_no 订单号 * @param {String} reason 原因 */ async refund(order_no, reason) { assert(order_no, '缺少订单号,无法查询订单信息'); const url = `${this.wxDomain}/pay/refundOrder`; const params = { config: this.appConfig, order_no, reason }; const wxRefundReq = await this.httpUtil.cpost(url, params); return wxRefundReq || 'ok'; } } module.exports = PayService;