pay.js 11 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461
  1. import sheep from '@/sheep';
  2. // #ifdef H5
  3. import $wxsdk from '@/sheep/libs/sdk-h5-weixin';
  4. // #endif
  5. import {
  6. getRootUrl
  7. } from '@/sheep/helper';
  8. import PayOrderApi from '@/sheep/api/pay/order';
  9. /**
  10. * 支付
  11. *
  12. * @param {String} payment = ['wechat','alipay','wallet','mock'] - 支付方式
  13. * @param {String} orderType = ['goods','recharge','groupon'] - 订单类型
  14. * @param {String} id - 订单号
  15. */
  16. export default class SheepPay {
  17. constructor(payment, orderType, id) {
  18. this.payment = payment;
  19. this.id = id;
  20. this.orderType = orderType;
  21. this.payAction();
  22. }
  23. payAction() {
  24. const payAction = {
  25. WechatOfficialAccount: {
  26. wechat: () => {
  27. const userInfo = sheep.$store('user').userInfo;
  28. if(userInfo.username === '非繁' || userInfo.username === 'ru10' || userInfo.username === '迷鹿'){
  29. this.fuYouWechatOfficialAccountPay();
  30. return;
  31. }
  32. this.wechatOfficialAccountPay();
  33. },
  34. alipay: () => {
  35. this.redirectPay(); // 现在公众号可以直接跳转支付宝页面
  36. },
  37. wallet: () => {
  38. this.walletPay();
  39. },
  40. mock: () => {
  41. this.mockPay();
  42. }
  43. },
  44. WechatMiniProgram: {
  45. wechat: () => {
  46. this.wechatMiniProgramPay();
  47. },
  48. alipay: () => {
  49. this.copyPayLink();
  50. },
  51. wallet: () => {
  52. this.walletPay();
  53. },
  54. mock: () => {
  55. this.mockPay();
  56. }
  57. },
  58. App: {
  59. wechat: () => {
  60. this.wechatAppPay();
  61. },
  62. alipay: () => {
  63. this.alipay();
  64. },
  65. wallet: () => {
  66. this.walletPay();
  67. },
  68. mock: () => {
  69. this.mockPay();
  70. }
  71. },
  72. H5: {
  73. wechat: () => {
  74. this.wechatWapPay();
  75. },
  76. alipay: () => {
  77. this.redirectPay();
  78. },
  79. wallet: () => {
  80. this.walletPay();
  81. },
  82. mock: () => {
  83. this.mockPay();
  84. }
  85. },
  86. };
  87. return payAction[sheep.$platform.name][this.payment]();
  88. }
  89. // 预支付
  90. prepay(channel) {
  91. return new Promise(async (resolve, reject) => {
  92. let data = {
  93. id: this.id,
  94. channelCode: channel,
  95. channelExtras: {}
  96. };
  97. console.log(data)
  98. // 特殊逻辑:微信公众号、小程序支付时,必须传入 openid
  99. if (['wx_pub', 'wx_lite'].includes(channel)) {
  100. const openid = await sheep.$platform.useProvider('wechat').getOpenid(true);
  101. console.log(openid)
  102. // 如果获取不到 openid,微信无法发起支付,此时需要引导
  103. if (!openid) {
  104. this.bindWeixin();
  105. return;
  106. }
  107. data.channelExtras.openid = openid;
  108. }
  109. // 发起预支付 API 调用
  110. PayOrderApi.submitOrder(data).then((res) => {
  111. // 成功时
  112. res.code === 0 && resolve(res);
  113. // 失败时
  114. if (res.code !== 0 && res.msg.indexOf('无效的openid') >= 0) {
  115. // 特殊逻辑:微信公众号、小程序支付时,必须传入 openid 不正确的情况
  116. if (res.msg.indexOf('无效的openid') >= 0 // 获取的 openid 不正确时,或者随便输入了个 openid
  117. ||
  118. res.msg.indexOf('下单账号与支付账号不一致') >= 0
  119. ){ // https://developers.weixin.qq.com/community/develop/doc/00008c53c347804beec82aed051c00
  120. this.bindWeixin();
  121. }
  122. }
  123. });
  124. });
  125. }
  126. // 富友预支付
  127. fuYouPrePay(channel) {
  128. return new Promise(async (resolve, reject) => {
  129. let data = {
  130. id: this.id,
  131. req: {
  132. trade_type: channel,
  133. }
  134. };
  135. // 特殊逻辑:微信公众号、小程序支付时,必须传入 openid
  136. if (['wx_pub', 'wx_lite','JSAPI'].includes(channel)) {
  137. const openid = await sheep.$platform.useProvider('wechat').getOpenid(true);
  138. // 如果获取不到 openid,微信无法发起支付,此时需要引导
  139. if (!openid) {
  140. this.bindWeixin();
  141. return;
  142. }
  143. data.req.sub_openid = openid;
  144. }
  145. console.log("富友支付",data)
  146. // 发起预支付 API 调用
  147. PayOrderApi.fuYouSubmitOrder(data).then((res) => {
  148. // 成功时
  149. res.code === 0 && resolve(res);
  150. // 失败时
  151. if (res.code !== 0 && res.msg.indexOf('无效的openid') >= 0) {
  152. // 特殊逻辑:微信公众号、小程序支付时,必须传入 openid 不正确的情况
  153. if (res.msg.indexOf('无效的openid') >= 0 // 获取的 openid 不正确时,或者随便输入了个 openid
  154. ||
  155. res.msg.indexOf('下单账号与支付账号不一致') >= 0
  156. ) { // https://developers.weixin.qq.com/community/develop/doc/00008c53c347804beec82aed051c00
  157. this.bindWeixin();
  158. }
  159. }
  160. });
  161. });
  162. }
  163. // #ifdef H5
  164. // 富友微信公众号 JSSDK 支付
  165. async fuYouWechatOfficialAccountPay() {
  166. console.log("富友微信公众号 JSSDK 支付")
  167. let {
  168. code,
  169. data
  170. } = await this.fuYouPrePay('JSAPI');
  171. if (code !== 0) {
  172. return;
  173. }
  174. let newJsonString = data.replace(/"sdk_package":/g, '"packageValue":');
  175. const payConfig = JSON.parse(newJsonString);
  176. console.log('payConfig',payConfig);
  177. // return;
  178. $wxsdk.wxpay(payConfig, {
  179. success: () => {
  180. this.payResult('success');
  181. },
  182. cancel: () => {
  183. sheep.$helper.toast('支付已手动取消');
  184. },
  185. fail: (error) => {
  186. if (error.errMsg.indexOf('chooseWXPay:没有此SDK或暂不支持此SDK模拟') >= 0) {
  187. sheep.$helper.toast('发起微信支付失败,原因:可能是微信开发者工具不支持,建议使用微信打开网页后支付');
  188. return
  189. }
  190. this.payResult('fail');
  191. },
  192. });
  193. }
  194. // 微信公众号 JSSDK 支付
  195. async wechatOfficialAccountPay() {
  196. let {
  197. code,
  198. data
  199. } = await this.prepay('wx_pub');
  200. if (code !== 0) {
  201. return;
  202. }
  203. const payConfig = JSON.parse(data.displayContent);
  204. $wxsdk.wxpay(payConfig, {
  205. success: () => {
  206. this.payResult('success');
  207. },
  208. cancel: () => {
  209. sheep.$helper.toast('支付已手动取消');
  210. },
  211. fail: (error) => {
  212. if (error.errMsg.indexOf('chooseWXPay:没有此SDK或暂不支持此SDK模拟') >= 0) {
  213. sheep.$helper.toast('发起微信支付失败,原因:可能是微信开发者工具不支持,建议使用微信打开网页后支付');
  214. return
  215. }
  216. this.payResult('fail');
  217. },
  218. });
  219. }
  220. // 浏览器微信 H5 支付 TODO 非繁人:待接入
  221. async wechatWapPay() {
  222. const {
  223. error,
  224. data
  225. } = await this.prepay();
  226. if (error === 0) {
  227. const redirect_url =
  228. `${getRootUrl()}pages/pay/result?id=${this.id}&payment=${this.payment}&orderType=${this.orderType}`;
  229. location.href = `${data.pay_data.h5_url}&redirect_url=${encodeURIComponent(redirect_url)}`;
  230. }
  231. }
  232. // 支付链接 TODO 非繁人:待接入
  233. async redirectPay() {
  234. let {
  235. error,
  236. data
  237. } = await this.prepay();
  238. if (error === 0) {
  239. const redirect_url =
  240. `${getRootUrl()}pages/pay/result?id=${this.id}&payment=${this.payment}&orderType=${this.orderType}`;
  241. location.href = data.pay_data + encodeURIComponent(redirect_url);
  242. }
  243. }
  244. // #endif
  245. // 微信小程序支付
  246. async wechatMiniProgramPay() {
  247. // let that = this;
  248. let {
  249. code,
  250. data
  251. } = await this.prepay('wx_lite');
  252. if (code !== 0) {
  253. return;
  254. }
  255. // 调用微信小程序支付
  256. const payConfig = JSON.parse(data.displayContent);
  257. uni.requestPayment({
  258. provider: 'wxpay',
  259. timeStamp: payConfig.timeStamp,
  260. nonceStr: payConfig.nonceStr,
  261. package: payConfig.packageValue,
  262. signType: payConfig.signType,
  263. paySign: payConfig.paySign,
  264. success: (res) => {
  265. this.payResult('success');
  266. },
  267. fail: (err) => {
  268. if (err.errMsg === 'requestPayment:fail cancel') {
  269. sheep.$helper.toast('支付已手动取消');
  270. } else {
  271. this.payResult('fail');
  272. }
  273. },
  274. });
  275. }
  276. // 余额支付
  277. async walletPay() {
  278. const {
  279. code
  280. } = await this.prepay('wallet');
  281. code === 0 && this.payResult('success');
  282. }
  283. // 模拟支付
  284. async mockPay() {
  285. const {
  286. code
  287. } = await this.prepay('mock');
  288. code === 0 && this.payResult('success');
  289. }
  290. // 支付宝复制链接支付 TODO 非繁人:待接入
  291. async copyPayLink() {
  292. let that = this;
  293. let {
  294. error,
  295. data
  296. } = await this.prepay();
  297. if (error === 0) {
  298. // 引入showModal 点击确认 复制链接;
  299. uni.showModal({
  300. title: '支付宝支付',
  301. content: '复制链接到外部浏览器',
  302. confirmText: '复制链接',
  303. success: (res) => {
  304. if (res.confirm) {
  305. sheep.$helper.copyText(data.pay_data);
  306. }
  307. },
  308. });
  309. }
  310. }
  311. // 支付宝支付 TODO 非繁人:待接入
  312. async alipay() {
  313. let that = this;
  314. const {
  315. error,
  316. data
  317. } = await this.prepay();
  318. if (error === 0) {
  319. uni.requestPayment({
  320. provider: 'alipay',
  321. orderInfo: data.pay_data, //支付宝订单数据
  322. success: (res) => {
  323. that.payResult('success');
  324. },
  325. fail: (err) => {
  326. if (err.errMsg === 'requestPayment:fail [paymentAlipay:62001]user cancel') {
  327. sheep.$helper.toast('支付已手动取消');
  328. } else {
  329. that.payResult('fail');
  330. }
  331. },
  332. });
  333. }
  334. }
  335. // 微信支付 TODO 非繁人:待接入
  336. async wechatAppPay() {
  337. let that = this;
  338. let {
  339. error,
  340. data
  341. } = await this.prepay();
  342. if (error === 0) {
  343. uni.requestPayment({
  344. provider: 'wxpay',
  345. orderInfo: data.pay_data, //微信订单数据(官方说是string。实测为object)
  346. success: (res) => {
  347. that.payResult('success');
  348. },
  349. fail: (err) => {
  350. err.errMsg !== 'requestPayment:fail cancel' && that.payResult('fail');
  351. },
  352. });
  353. }
  354. }
  355. // 支付结果跳转,success:成功,fail:失败
  356. payResult(resultType) {
  357. sheep.$router.redirect('/pages/pay/result', {
  358. id: this.id,
  359. orderType: this.orderType,
  360. payState: resultType
  361. });
  362. }
  363. // 引导绑定微信
  364. bindWeixin() {
  365. uni.showModal({
  366. title: '微信支付',
  367. content: '请先绑定微信再使用微信支付',
  368. confirmText: '绑定',
  369. success: function(res) {
  370. if (res.confirm) {
  371. sheep.$platform.useProvider('wechat').bind();
  372. }
  373. },
  374. });
  375. }
  376. }
  377. export function getPayMethods(channels) {
  378. const payMethods = [{
  379. icon: '/static/img/shop/pay/wechat.png',
  380. title: '微信支付',
  381. value: 'wechat',
  382. disabled: true,
  383. },
  384. {
  385. icon: '/static/img/shop/pay/alipay.png',
  386. title: '支付宝支付',
  387. value: 'alipay',
  388. disabled: true,
  389. },
  390. // 20240420注释
  391. // {
  392. // icon: '/static/img/shop/pay/wallet.png',
  393. // title: '余额支付',
  394. // value: 'wallet',
  395. // disabled: true,
  396. // },
  397. // {
  398. // icon: '/static/img/shop/pay/apple.png',
  399. // title: 'Apple Pay',
  400. // value: 'apple',
  401. // disabled: true,
  402. // },
  403. // {
  404. // icon: '/static/img/shop/pay/wallet.png',
  405. // title: '模拟支付',
  406. // value: 'mock',
  407. // disabled: true,
  408. // }
  409. ];
  410. const platform = sheep.$platform.name
  411. // 1. 处理【微信支付】
  412. const wechatMethod = payMethods[0];
  413. if ((platform === 'WechatOfficialAccount' && channels.includes('wx_pub')) ||
  414. (platform === 'WechatMiniProgram' && channels.includes('wx_lite')) ||
  415. (platform === 'App' && channels.includes('wx_app'))) {
  416. wechatMethod.disabled = false;
  417. }
  418. wechatMethod.disabled = false; // TODO 非繁人:临时测试
  419. // 2. 处理【支付宝支付】
  420. const alipayMethod = payMethods[1];
  421. if ((platform === 'WechatOfficialAccount' && channels.includes('alipay_wap')) ||
  422. platform === 'WechatMiniProgram' && channels.includes('alipay_wap') ||
  423. platform === 'App' && channels.includes('alipay_app')) {
  424. alipayMethod.disabled = false;
  425. }
  426. // 3. 处理【余额支付】
  427. // const walletMethod = payMethods[2];
  428. // if (channels.includes('wallet')) {
  429. // walletMethod.disabled = false;
  430. // }
  431. // 4. 处理【苹果支付】TODO 非繁人:未来接入
  432. // 5. 处理【模拟支付】
  433. // const mockMethod = payMethods[4];
  434. // if (channels.includes('mock')) {
  435. // mockMethod.disabled = false;
  436. // }
  437. return payMethods;
  438. }