index.obj.js 7.2 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305
  1. /**
  2. * uni-pay-co 统一支付云对象
  3. */
  4. // 加载服务
  5. const service = require('./service');
  6. // 加载全局错误码
  7. const { UniCloudError, isUniPayError, ERROR } = require('./common/error');
  8. // 加载全局中间件
  9. const middleware = require('./middleware/index');
  10. // 加载uniId公共模块
  11. const uniIdCommon = require('uni-id-common');
  12. module.exports = {
  13. /**
  14. * 中间件(请求前执行)
  15. */
  16. async _before() {
  17. const params = this.getParams();
  18. let clientInfo;
  19. if (params && params[0] && params[0].clientInfo) {
  20. clientInfo = params[0].clientInfo;
  21. } else {
  22. clientInfo = this.getClientInfo();
  23. }
  24. if (['zh-Hans','en'].indexOf(clientInfo.locale) === -1) {
  25. clientInfo.locale = 'zh-Hans';
  26. }
  27. // 挂载uni-id实例到this上,方便后续调用
  28. this.uniIdCommon = uniIdCommon.createInstance({
  29. clientInfo
  30. });
  31. // 国际化开始
  32. const i18n = uniCloud.initI18n({
  33. locale: clientInfo.locale || 'zh-Hans',
  34. fallbackLocale: 'zh-Hans',
  35. messages: require('./lang/index')
  36. })
  37. this.t = i18n.t.bind(i18n);
  38. // 国际化结束
  39. // 挂载中间件
  40. this.middleware = {}
  41. for (const mwName in middleware) {
  42. this.middleware[mwName] = middleware[mwName].bind(this);
  43. }
  44. const methodName = this.getMethodName();
  45. // 支付回调接口没有token,不需要获取用户信息
  46. if (methodName !== "payNotify") {
  47. // 尝试从token获取用户信息
  48. await this.middleware.auth(false);
  49. // 通用权限校验模块
  50. await this.middleware.accessControl();
  51. }
  52. // 设置全局获取userId公共函数(可在此云对象的任意其他函数内通过 this.getUserId() 获取当前登录用户的id
  53. this.getUserId = () => {
  54. return this.authInfo && this.authInfo.uid ? this.authInfo.uid : undefined;
  55. }
  56. },
  57. /**
  58. * 中间件(请求后执行)
  59. */
  60. _after(error, result) {
  61. if (error) {
  62. if (error.errCode) {
  63. let errCode = error.errCode
  64. if (!isUniPayError(errCode)) {
  65. // 如果不是插件预设的错误码,则原样返回错误信息
  66. return error;
  67. }
  68. return new UniCloudError({
  69. code: errCode,
  70. message: error.errMsg || this.t(errCode, error.errMsgValue),
  71. });
  72. }
  73. throw error
  74. }
  75. return result;
  76. },
  77. /**
  78. * 创建支付订单
  79. */
  80. async createOrder(data) {
  81. let {
  82. provider, // 支付供应商 如 wxpay alipay 参考 https://uniapp.dcloud.net.cn/api/plugins/provider.html#
  83. total_fee, // 订单总金额,单位为分,100等于1元
  84. openid, // 发起支付的用户openid
  85. order_no, // 业务系统订单号 建议控制在20-28位(不可以是24位,24位在阿里云空间可能会有问题)(可重复,代表1个业务订单会有多次付款的情况)
  86. out_trade_no, // 支付插件订单号(需控制唯一,不传则由插件自动生成)
  87. description, // 支付描述,如:uniCloud个人版包月套餐
  88. type, // 订单类型 goods:订单付款 recharge:余额充值付款 vip:vip充值付款 等等,可自定义
  89. qr_code, // true 强制开启二维码支付模式
  90. custom, // 自定义参数(不会发送给第三方支付服务器)(由于custom在前端调用时是不可信任的,因此此参数后续需要优化)
  91. other, // 其他请求参数(会发送给第三方支付服务器)
  92. clientInfo, // 兼容云对象调用云对象模式
  93. cloudInfo, // 兼容云对象调用云对象模式
  94. wxpay_virtual, // 仅用于微信虚拟支付
  95. } = data;
  96. if (!clientInfo) clientInfo = this.getClientInfo();
  97. if (!cloudInfo) cloudInfo = this.getCloudInfo();
  98. // 获取当前登录的user_id
  99. let user_id = this.getUserId();
  100. let res = await service.pay.createOrder({
  101. provider,
  102. total_fee,
  103. user_id,
  104. openid,
  105. order_no,
  106. out_trade_no,
  107. description,
  108. type,
  109. qr_code,
  110. custom,
  111. other,
  112. clientInfo,
  113. cloudInfo,
  114. wxpay_virtual,
  115. });
  116. return res;
  117. },
  118. /**
  119. * 接收支付异步通知
  120. */
  121. async payNotify(data) {
  122. const httpInfo = this.getHttpInfo();
  123. const clientInfo = this.getClientInfo();
  124. const cloudInfo = this.getCloudInfo();
  125. return service.pay.paymentNotify({
  126. httpInfo,
  127. clientInfo,
  128. cloudInfo
  129. });
  130. },
  131. /**
  132. * 查询支付状态
  133. */
  134. async getOrder(data) {
  135. let {
  136. out_trade_no, // 插件订单号
  137. transaction_id, // 第三方支付交易单号
  138. await_notify = false, // 是否需要等待异步通知执行完成,若为了响应速度,可以设置为false,若需要等待异步回调执行完成,则设置为true
  139. } = data;
  140. res = await service.pay.getOrder({
  141. out_trade_no,
  142. transaction_id,
  143. await_notify
  144. });
  145. return res;
  146. },
  147. /**
  148. * 发起退款
  149. * 此api只有admin角色可以访问
  150. */
  151. async refund(data) {
  152. let {
  153. out_trade_no, // 插件订单号
  154. out_refund_no, // 插件退款订单号
  155. refund_desc, // 退款描述
  156. refund_fee, // 退款金额
  157. } = data;
  158. res = await service.pay.refund({
  159. out_trade_no,
  160. out_refund_no,
  161. refund_desc,
  162. refund_fee,
  163. });
  164. return res;
  165. },
  166. /**
  167. * 查询退款(查询退款情况)
  168. */
  169. async getRefund(data) {
  170. let {
  171. out_trade_no, // 插件订单号
  172. } = data;
  173. res = await service.pay.getRefund({
  174. out_trade_no,
  175. });
  176. return res;
  177. },
  178. /**
  179. * 关闭订单(只有订单未支付时,才可以关闭,关闭后,用户即使在付款页面也无法付款)
  180. */
  181. async closeOrder(data) {
  182. let {
  183. out_trade_no, // 插件订单号
  184. } = data;
  185. res = await service.pay.closeOrder({
  186. out_trade_no,
  187. });
  188. return res;
  189. },
  190. /**
  191. * 根据code获取openid
  192. */
  193. async getOpenid(data = {}) {
  194. let {
  195. provider,
  196. code,
  197. clientInfo, // 兼容云对象调用云对象模式
  198. } = data;
  199. if (!clientInfo) clientInfo = this.getClientInfo();
  200. res = await service.pay.getOpenid({
  201. provider,
  202. code,
  203. clientInfo
  204. });
  205. return res;
  206. },
  207. /**
  208. * 获取当前支持的支付方式
  209. */
  210. async getPayProviderFromCloud() {
  211. return await service.pay.getPayProviderFromCloud();
  212. },
  213. /**
  214. * 获取支付配置内的appid(主要用于获取获取微信公众号的appid,用以获取code)
  215. */
  216. async getProviderAppId(data) {
  217. let {
  218. provider,
  219. provider_pay_type
  220. } = data;
  221. // 注意,前往不要直接把 conifg 内的所有内容返回给前端
  222. let conifg = service.pay.getConfig();
  223. try {
  224. return {
  225. errorCode: 0,
  226. appid: conifg[provider][provider_pay_type].appId,
  227. }
  228. } catch (err) {
  229. return {
  230. errorCode: 0,
  231. appid: null
  232. };
  233. }
  234. },
  235. /**
  236. * 验证iosIap苹果内购支付凭据
  237. */
  238. async verifyReceiptFromAppleiap(data) {
  239. let {
  240. out_trade_no,
  241. transaction_receipt,
  242. transaction_identifier,
  243. } = data;
  244. return await service.pay.verifyReceiptFromAppleiap({
  245. out_trade_no,
  246. transaction_receipt,
  247. transaction_identifier
  248. });
  249. },
  250. /**
  251. * 接收微信小程序虚拟支付异步通知
  252. */
  253. async wxpayVirtualNotify(data) {
  254. const httpInfo = this.getHttpInfo();
  255. const clientInfo = this.getClientInfo();
  256. const cloudInfo = this.getCloudInfo();
  257. return service.pay.wxpayVirtualNotify({
  258. httpInfo,
  259. clientInfo,
  260. cloudInfo
  261. });
  262. },
  263. /**
  264. * 请求微信小程序虚拟支付API
  265. */
  266. async requestWxpayVirtualApi(data) {
  267. const clientInfo = this.getClientInfo();
  268. if (clientInfo.source !== "function") {
  269. throw new Error("requestWxpayVirtualApi只能通过云端调云端的方式调用");
  270. }
  271. let res = await service.pay.requestWxpayVirtualApi(data);
  272. return res;
  273. },
  274. }