pay.js 5.4 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141
  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. //
  7. class PayService extends CrudService {
  8. constructor(ctx) {
  9. super(ctx, 'pay');
  10. this.httpUtil = this.ctx.service.util.httpUtil;
  11. this.appConfig = 'pointApp';
  12. this.orderModel = this.ctx.model.Trade.Order;
  13. this.dictDataModel = this.ctx.model.Dev.DictData;
  14. this.payOrderReturnUrl = this.app.config.payReturn.order;
  15. this.wxDomain = _.get(this.app, 'config.httpPrefix.wechat');
  16. }
  17. /**
  18. * 去支付订单
  19. * 1.有支付方式之分; 微信/支付宝
  20. * 2.根据不同方式去请求
  21. * @param {Object} body 请求体
  22. * @param body.order_id 订单id
  23. * @param body.type 支付方式
  24. */
  25. async toPayOrder({ order_id, type }) {
  26. const payWay = await this.dictDataModel.findOne({ value: type, status: '0' });
  27. if (!payWay) throw new BusinessError(ErrorCode.DATA_INVALID, '该支付方式暂时无法使用');
  28. const order = await this.orderModel.findById(order_id);
  29. if (!order) throw new BusinessError(ErrorCode.DATA_NOT_EXIST, '未找到订单数据');
  30. const { no, pay } = order;
  31. // 检查是否有支付信息如果有的话,支付方式是否一致
  32. if (Object.keys(pay).length > 0) {
  33. const pay_type = _.get(pay, 'pay_type');
  34. // 支付方式不同,则将支付内容刷掉,重新进行数据生成
  35. if (pay_type === type) {
  36. // 支付方式相同,则再找有没有支付订单
  37. const pay_no = _.get(pay, 'pay_no');
  38. if (pay_no) {
  39. // 有支付订单.则先查支付订单是否可以继续支付
  40. // TODO:
  41. // 1.当前用户和之前下单支付的用户的openid是不是一个人.是一个人=>2;不是一个人=>3
  42. // 2.需要关闭之前的支付订单并且重新进行支付: 关闭订单.再放到下面
  43. // 3.查询订单是否过期 没过期=>4; 过期=>5
  44. // 4.继续支付:取出数据,return;
  45. // 5.放到下面.重新支付
  46. }
  47. // 没有的话,就说明数据有问题.按照没有支付信息处理即可
  48. }
  49. }
  50. // 没有支付信息(要是有支付信息,上面直接return了.漏下来的都是没有的处理方案)
  51. const str = this.ctx.service.util.trade.createNonceStr();
  52. const arr = no.split('-');
  53. // 订单中pay的信息
  54. const payObject = { pay_type: type, pay_no: `${_.last(arr)}-${str}` };
  55. const totalMoney = this.getOrderNeedPay(order);
  56. // 找到当前用户的openid:这里涉及问题是: 如果自己下单,自己付款.那没有问题;
  57. // 如果是自己下单.如果使用账号密码登录再付款.还用下单的人找到的openid就不能在这个微信号上进行支付了;
  58. // 所以此处是需要用当前用户的openid进行支付,如果之前生成单子.还需要检查当前用户的openid和之前的openid是否一致
  59. // 如果不一致.则需要将之前的订单关闭,重新生成
  60. // 请求微信支付接口的数据
  61. if (type === '0') {
  62. const toPayData = { config: this.appConfig, money: totalMoney, openid: '', order_no: payObject.pay_no, desc: '购物', notice_url: this.payOrderReturnUrl('order_id') };
  63. }
  64. }
  65. /**
  66. * 支付订单回调函数
  67. * @param {Object} param 请求地址参数
  68. * @param param.order 订单id
  69. */
  70. async callBackPayOrder({ order }) {}
  71. /**
  72. * 计算订单需支付的金额
  73. * @param {Object} order 要支付的订单数据
  74. */
  75. getOrderNeedPay(order) {
  76. let total = 0;
  77. const { total_detail = {} } = order;
  78. for (const key in total_detail) {
  79. total = _.floor(total_detail[key] + total);
  80. }
  81. return total;
  82. }
  83. /**
  84. * 查询订单
  85. * @param {String} order_no 订单号
  86. */
  87. async search(order_no) {
  88. assert(order_no, '缺少订单号,无法查询订单信息');
  89. const params = { config: this.appConfig, order_no };
  90. const url = `${this.wxDomain}/pay/searchOrderByOrderNo`;
  91. const wxOrderReq = await this.httpUtil.cpost(url, params);
  92. return wxOrderReq;
  93. }
  94. /**
  95. * 创建订单,获取微信支付签名
  96. * @param {Object} data 数据
  97. */
  98. async create(data) {
  99. const { money, openid, order_no, desc } = data;
  100. const wxOrderData = { config: this.appConfig, money, openid, order_no, desc };
  101. const url = `${this.wxDomain}/pay/payOrder`;
  102. const res = await this.httpUtil.cpost(url, wxOrderData);
  103. if (res) return res;
  104. throw new BusinessError(ErrorCode.SERVICE_FAULT, '微信下单失败!');
  105. }
  106. /**
  107. * 关闭订单
  108. * @param {String} order_no 订单号
  109. */
  110. async close(order_no) {
  111. assert(order_no, '缺少订单号,无法查询订单信息');
  112. const params = { config: this.appConfig, order_no };
  113. const url = `${this.wxDomain}/pay/closeOrder`;
  114. const res = await this.httpUtil.cpost(url, params);
  115. return res || 'ok';
  116. }
  117. /**
  118. * TODO 退款,金额需要指定.可能是部分退款,也可能是全额退款
  119. * @param {String} order_no 订单号
  120. * @param {String} reason 原因
  121. */
  122. async refund(order_no, reason) {
  123. assert(order_no, '缺少订单号,无法查询订单信息');
  124. const url = `${this.wxDomain}/pay/refundOrder`;
  125. const params = { config: this.appConfig, order_no, reason };
  126. const wxRefundReq = await this.httpUtil.cpost(url, params);
  127. return wxRefundReq || 'ok';
  128. }
  129. }
  130. module.exports = PayService;