payOrder.js 6.1 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172
  1. 'use strict';
  2. const { CrudService } = require('naf-framework-mongoose-free/lib/service');
  3. const { BusinessError, ErrorCode } = require('naf-core').Error;
  4. const _ = require('lodash');
  5. const assert = require('assert');
  6. const moment = require('moment');
  7. //
  8. class PayOrderService extends CrudService {
  9. constructor(ctx) {
  10. super(ctx, 'payorder');
  11. this.model = this.ctx.model.Business.PayOrder;
  12. this.payService = this.ctx.service.wxpay;
  13. this.lessonStudentModel = this.ctx.model.Business.LessonStudent;
  14. this.chargeModel = this.ctx.model.Business.Charge;
  15. this.tempLessonApplyModel = this.ctx.model.Apply.TempLessonApply;
  16. this.userModel = this.ctx.model.User.User;
  17. this.studentModel = this.ctx.model.User.Student;
  18. this.coachModel = this.ctx.model.User.Coach;
  19. }
  20. async beforeCreate(data) {
  21. if (!_.get(data, 'order_no')) data.order_no = this.getOrderNo();
  22. return data;
  23. }
  24. async afterCreate(body, data) {
  25. await this.syncData(data);
  26. const wxSign = await this.payService.create(data);
  27. return { data, wxSign };
  28. }
  29. async afterUpdate(filter, body, data) {
  30. await this.syncData(data);
  31. return data;
  32. }
  33. /**
  34. * 支付同步
  35. * @param {Object} data 支付单数据
  36. */
  37. async syncData(data) {
  38. const pay_for = _.get(data, 'pay_for');
  39. if (!pay_for) {
  40. // 不知道该去同步哪个表的支付状态,不处理
  41. return;
  42. }
  43. const { from_id: _id, status: is_pay } = data;
  44. if (pay_for === 'lessonStudent') {
  45. // 因为上课产生的支付,去找lessonStudent,修改指定学生的支付状态
  46. await this.lessonStudentModel.updateOne({ _id }, { is_pay });
  47. } else if (pay_for === 'tempLessonApply') {
  48. // 私教课临时上课,需要到临时申请那找到相关数据,再修改lessonStudent
  49. const tempApply = await this.tempLessonApplyModel.findById(_id);
  50. if (!tempApply) return;
  51. const { lesson_id, student_id } = tempApply;
  52. await this.lessonStudentModel.updateOne({ lesson_id, student_id }, { is_pay });
  53. } else if (pay_for === 'charge') {
  54. // 充值
  55. await this.chargeModel.updateOne({ _id }, { is_pay });
  56. }
  57. }
  58. /**
  59. * 重新支付
  60. * @param {String} body 参数体
  61. * @property {String} id 数据id
  62. */
  63. async toRePay({ id }) {
  64. const data = await this.model.findById(id);
  65. if (!data) throw new BusinessError(ErrorCode.DATA_NOT_EXIST, '未找到支付的信息');
  66. // 找到这个订单,然后获取到订单号
  67. const { order_no } = data;
  68. // 利用订单号去查询微信那边,该订单是否还存在
  69. const wxOrder = await this.payService.search(order_no);
  70. let wxSign;
  71. if (_.get(wxOrder, 'trade_state') === 'NOTPAY') {
  72. // 未支付就用原数据,去支付
  73. wxSign = await this.payService.create(data);
  74. } else if (_.get(wxOrder, 'trade_state') === 'SUCCESS') {
  75. throw new BusinessError(ErrorCode.SERVICE_FAULT, '订单已支付,无需重复支付');
  76. } else if (_.get(wxOrder, 'trade_state') === 'USERPAYING') {
  77. throw new BusinessError(ErrorCode.SERVICE_FAULT, '订单支付中');
  78. } else {
  79. // 其他情况就当订单被关闭了.直接新订单
  80. const order_no = this.getOrderNo();
  81. data.order_no = order_no;
  82. await data.save();
  83. wxSign = await this.payService.create(data);
  84. }
  85. return { data, wxSign };
  86. }
  87. /**
  88. * 申请退款
  89. * @param {Object} body 参数体
  90. * @property {String} id 支付单的数据id
  91. */
  92. async toRefund({ id }) {
  93. // 查询支付
  94. const data = await this.model.findById(id);
  95. if (!data) throw new BusinessError(ErrorCode.DATA_NOT_EXIST, '未找到要退款的支付数据');
  96. const wxOrderReq = await this.payService.search(data.order_no);
  97. if (wxOrderReq) {
  98. if (!wxOrderReq) throw new BusinessError(ErrorCode.DATA_NOT_EXIST, '未查询到微信支付订单');
  99. const wxRefundReq = await this.payService.refund(data.order_no, '退赛');
  100. if (wxRefundReq) {
  101. if (wxRefundReq.status !== 'REFUND') throw new BusinessError(ErrorCode.SERVICE_FAULT, '退款失败');
  102. // 退款成功
  103. data.status = '-3';
  104. await data.save();
  105. await this.syncData(data);
  106. return 'ok';
  107. }
  108. }
  109. throw new BusinessError(ErrorCode.SERVICE_FAULT, '查询微信支付订单失败');
  110. }
  111. /**
  112. * 关闭订单
  113. * @param {String} id 支付id
  114. * @return {Object} 关闭订单结果
  115. */
  116. async closeOrder(id) {
  117. const data = await this.model.findById(id);
  118. if (!data) throw new BusinessError(ErrorCode.DATA_NOT_EXIST, '未找到要退款的支付数据');
  119. const res = await this.payService.close(data.order_no);
  120. return res;
  121. }
  122. getOrderNo() {
  123. return `ONCAPP${moment().format('YYYYMMDDHHmmss')}-${_.random(1, 999999)}`;
  124. }
  125. // 二维码扫码
  126. async toPayNative(body) {
  127. body = await this.beforeCreate(body);
  128. const data = await this.model.create(body);
  129. const qrcode = await this.payService.createNative({ ...body, notice_url: '/newCourt/v2/api/payOrder/nativeReturn' });
  130. return qrcode;
  131. }
  132. // 二维码扫码回调
  133. async nativeReturn(body) {
  134. const result = _.get(body, 'result');
  135. if (!result) throw new BusinessError(ErrorCode.BADPARAM, '参数错误');
  136. const { out_trade_no: order_no, trade_state, payer } = result;
  137. const obj = {};
  138. if (trade_state === 'SUCCESS') obj.status = '1';
  139. else if (trade_state === 'REFUND') obj.status = '-3';
  140. const openid = _.get(payer, 'openid');
  141. if (openid) {
  142. obj.openid = openid;
  143. // 找payer_id的信息,学员,教练
  144. const user = await this.userModel.findOne({ openid });
  145. if (user) {
  146. const { _id: user_id } = user;
  147. let roleUser = await this.studentModel.findOne({ user_id });
  148. if (!roleUser) {
  149. roleUser = await this.coachModel.findOne({ user_id });
  150. if (roleUser) {
  151. obj.payer_role = 'Coach';
  152. obj.payer_id = roleUser._id;
  153. }
  154. } else {
  155. obj.payer_role = 'Student';
  156. obj.payer_id = roleUser._id;
  157. }
  158. }
  159. }
  160. await this.model.updateOne({ order_no }, obj);
  161. }
  162. }
  163. module.exports = PayOrderService;