index.obj.js 7.6 KB

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