edit.vue 14 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443
  1. <template>
  2. <view class="app">
  3. <view style="padding-bottom: 0.5rem;">
  4. <view class="label">可用服务点数:{{user.wallet}}</view>
  5. </view>
  6. <view>
  7. <view class="label">兑现数量(1个兑现1元人民币):</view>
  8. <view><input v-model.number="total_fee" type="number" /></view>
  9. </view>
  10. <button type="primary" @click="createOrder('wxpay')">发起兑现</button>
  11. </view>
  12. </template>
  13. <script>
  14. export default {
  15. data() {
  16. return {
  17. total_fee: 1000, // 支付金额,单位分 100 = 1元
  18. order_no: "", // 业务系统订单号(即你自己业务系统的订单表的订单号)
  19. out_trade_no: "", // 插件支付单号
  20. description: "测试订单", // 支付描述
  21. type: "test", // 支付回调类型 如 recharge 代表余额充值 goods 代表商品订单(可自定义,任意英文单词都可以,只要你在 uni-pay-co/notify/目录下创建对应的 xxx.js文件进行编写对应的回调逻辑即可)
  22. //qr_code: true, // 是否强制使用扫码支付
  23. openid:"", // 微信公众号需要
  24. custom:{
  25. a: "a",
  26. b: 1
  27. },
  28. adpid: "1000000001", // uni-ad的广告位id
  29. transaction_id:"", // 查询订单接口的查询条件
  30. getOrderRes:{}, // 查询订单支付成功后的返回值
  31. }
  32. },
  33. onLoad(options={}) {
  34. this.user = this.getUser();
  35. // #ifdef H5
  36. // 微信公众号特殊逻辑开始-----------------------------------------------------------
  37. // 以下代码仅为获取openid,正常你自己项目应该是登录后才能支付,登录后已经拿到openid,无需编写下面的代码
  38. if (this.h5Env === 'h5-weixin') {
  39. let openid = uni.getStorageSync("uni-pay-weixin-h5-openid");
  40. let code = uni.getStorageSync("uni-pay-weixin-h5-code");
  41. if (openid) {
  42. this.openid = openid;
  43. }
  44. // 如果code和state有值,且此code没有被使用过,则执行获取微信公众号的openid
  45. if (options.code && options.state && code !== options.code) {
  46. // 获取微信公众号的openid
  47. setTimeout(() => {
  48. this.getOpenid({
  49. provider: "wxpay",
  50. code: options.code
  51. });
  52. }, 300);
  53. } else if (!openid){
  54. // 如果openid为空,则执行微信公众号的网页授权登录逻辑
  55. setTimeout(() => {
  56. this.getWeiXinJsCode('snsapi_base');
  57. }, 300);
  58. }
  59. }
  60. this.order_no = `test`+Date.now();
  61. this.out_trade_no = `${this.order_no}-1`;
  62. // 微信公众号特殊逻辑结束-----------------------------------------------------------
  63. // #endif
  64. },
  65. methods: {
  66. /**
  67. * 发起支付(唤起收银台,如果只有一种支付方式,则收银台不会弹出来,会直接使用此支付方式)
  68. * 在调用此api前,你应该先创建自己的业务系统订单,并获得订单号 order_no,把order_no当参数传给此api,而示例中为了简化跟支付插件无关的代码,这里直接已时间戳生成了order_no
  69. */
  70. open() {
  71. this.order_no = `test`+Date.now();
  72. this.out_trade_no = `${this.order_no}-1`;
  73. // 打开支付收银台
  74. this.$refs.pay.open({
  75. total_fee: this.total_fee, // 支付金额,单位分 100 = 1元
  76. order_no: this.order_no, // 业务系统订单号(即你自己业务系统的订单表的订单号)
  77. out_trade_no: this.out_trade_no, // 插件支付单号
  78. description: this.description, // 支付描述
  79. type: this.type, // 支付回调类型
  80. qr_code: this.qr_code, // 是否强制使用扫码支付
  81. openid: this.openid, // 微信公众号需要
  82. custom: this.custom, // 自定义数据
  83. });
  84. },
  85. /**
  86. * 发起支付(不唤起收银台,手动指定支付方式)
  87. * 在调用此api前,你应该先创建自己的业务系统订单,并获得订单号 order_no,把order_no当参数传给此api,而示例中为了简化跟支付插件无关的代码,这里直接已时间戳生成了order_no
  88. */
  89. createOrder(provider){
  90. /*
  91. // 发起支付
  92. this.$refs.pay.createOrder({
  93. provider: provider, // 支付供应商
  94. total_fee: this.total_fee, // 支付金额,单位分 100 = 1元
  95. order_no: this.order_no, // 业务系统订单号(即你自己业务系统的订单表的订单号)
  96. out_trade_no: this.out_trade_no, // 插件支付单号
  97. description: this.description, // 支付描述
  98. type: this.type, // 支付回调类型
  99. qr_code: this.qr_code, // 是否强制使用扫码支付
  100. openid: this.openid, // 微信公众号需要
  101. custom: this.custom, // 自定义数据
  102. });
  103. */
  104. this.http.request({
  105. url: '/level-one-server/app/WalletManage/topdownSave',
  106. data: {
  107. amount: this.total_fee,
  108. goodsName: '服务点对象'
  109. },
  110. success: res => {
  111. this.user.wallet = this.user.wallet - this.total_fee/100;
  112. console.log("this.user",this.user)
  113. uni.setStorageSync('info', this.user);
  114. uni.showToast({
  115. title: '提现成功!'
  116. });
  117. uni.navigateBack({
  118. data:1
  119. });
  120. }
  121. });
  122. },
  123. /**
  124. * 生成支付独立二维码(只返回支付二维码)
  125. * 在调用此api前,你应该先创建自己的业务系统订单,并获得订单号 order_no,把order_no当参数传给此api,而示例中为了简化跟支付插件无关的代码,这里直接已时间戳生成了order_no
  126. */
  127. createQRcode(provider){
  128. this.order_no = `test`+Date.now();
  129. this.out_trade_no = `${this.order_no}-1`;
  130. // 发起支付
  131. this.$refs.pay.createOrder({
  132. provider: provider, // 支付供应商
  133. total_fee: this.total_fee, // 支付金额,单位分 100 = 1元
  134. order_no: this.order_no, // 业务系统订单号(即你自己业务系统的订单表的订单号)
  135. out_trade_no: this.out_trade_no, // 插件支付单号
  136. description: this.description, // 支付描述
  137. type: this.type, // 支付回调类型
  138. qr_code: true, // 是否强制使用扫码支付
  139. cancel_popup: true, // 配合qr_code:true使用,是否只生成支付二维码,没有二维码弹窗
  140. openid: this.openid, // 微信公众号需要
  141. custom: this.custom, // 自定义数据
  142. });
  143. },
  144. /**
  145. * 前往自定义收银台页面
  146. * 在调用此api前,你应该先创建自己的业务系统订单,并获得订单号 order_no,把order_no当参数传给此api,而示例中为了简化跟支付插件无关的代码,这里直接已时间戳生成了order_no
  147. */
  148. toPayDesk(){
  149. this.order_no = `test`+Date.now();
  150. this.out_trade_no = `${this.order_no}-1`;
  151. let options = {
  152. total_fee: this.total_fee, // 支付金额,单位分 100 = 1元
  153. order_no: this.order_no, // 业务系统订单号(即你自己业务系统的订单表的订单号)
  154. out_trade_no: this.out_trade_no, // 插件支付单号
  155. description: this.description, // 支付描述
  156. type: this.type, // 支付回调类型
  157. qr_code: this.qr_code, // 是否强制使用扫码支付
  158. openid: this.openid, // 微信公众号需要
  159. custom: this.custom, // 自定义数据
  160. };
  161. let optionsStr = encodeURI(JSON.stringify(options));
  162. uni.navigateTo({
  163. url:`/uni_modules/uni-pay/pages/pay-desk/pay-desk?options=${optionsStr}`
  164. });
  165. },
  166. // 打开查询订单的弹窗
  167. getOrderPopup(key){
  168. if (key) {
  169. this.$refs.getOrderPopup.open();
  170. } else {
  171. this.$refs.getOrderPopup.close();
  172. }
  173. },
  174. // 查询支付状态
  175. async getOrder() {
  176. this.getOrderRes = {};
  177. let res = await this.$refs.pay.getOrder({
  178. //out_trade_no: this.out_trade_no, // 插件支付单号 两者传1个即可
  179. transaction_id: this.transaction_id, // 第三方单号 两者传1个即可
  180. await_notify: true
  181. });
  182. if (res) {
  183. this.getOrderRes = res.pay_order;
  184. let obj = {
  185. "-1": "已关闭",
  186. "1": "已支付",
  187. "0": "未支付",
  188. "2": "已部分退款",
  189. "3": "已全额退款"
  190. };
  191. uni.showToast({
  192. title: obj[res.status] || res.errMsg,
  193. icon: "none"
  194. });
  195. }
  196. },
  197. // 发起退款
  198. async refund() {
  199. let res = await this.$refs.pay.refund({
  200. out_trade_no: this.out_trade_no, // 插件支付单号
  201. });
  202. if (res) {
  203. uni.showToast({
  204. title: res.errMsg,
  205. icon: "none"
  206. });
  207. }
  208. },
  209. // 查询退款状态
  210. async getRefund() {
  211. let res = await this.$refs.pay.getRefund({
  212. out_trade_no: this.out_trade_no, // 插件支付单号
  213. });
  214. if (res) {
  215. uni.showModal({
  216. content: res.errMsg,
  217. showCancel: false
  218. });
  219. }
  220. },
  221. // 关闭订单
  222. async closeOrder() {
  223. let res = await this.$refs.pay.closeOrder({
  224. out_trade_no: this.out_trade_no, // 插件支付单号
  225. });
  226. if (res) {
  227. uni.showModal({
  228. content: res.errMsg,
  229. showCancel: false
  230. });
  231. }
  232. },
  233. // 获取公众号code
  234. async getWeiXinJsCode(scope="snsapi_base") {
  235. let res = await this.$refs.pay.getProviderAppId({
  236. provider: "wxpay",
  237. provider_pay_type: "jsapi"
  238. });
  239. if (res.appid) {
  240. let appid = res.appid;
  241. let redirect_uri = window.location.href.split("?")[0];
  242. let url = `https://open.weixin.qq.com/connect/oauth2/authorize?appid=${appid}&redirect_uri=${redirect_uri}&response_type=code&scope=${scope}&state=STATE#wechat_redirect`;
  243. window.location.href = url;
  244. }
  245. },
  246. // 获取公众号openid
  247. async getOpenid(data={}) {
  248. let res = await this.$refs.pay.getOpenid(data);
  249. if (res) {
  250. this.openid = res.openid;
  251. // 将openid缓存到本地
  252. uni.setStorageSync("uni-pay-weixin-h5-openid", this.openid);
  253. uni.setStorageSync("uni-pay-weixin-h5-code", data.code);
  254. uni.showToast({
  255. title: "已获取到openid,可以开始支付",
  256. icon: "none"
  257. });
  258. }
  259. },
  260. // 监听事件 - 支付订单创建成功(此时用户还未支付)
  261. onCreate(res){
  262. console.log('create: ', res);
  263. // 如果只是想生成支付二维码,不需要组件自带的弹窗,则在这里可以获取到支付二维码 qr_code_image
  264. },
  265. // 监听事件 - 支付成功
  266. onSuccess(res){
  267. console.log('success: ', res);
  268. if (res.user_order_success) {
  269. // 代表用户已付款,且你自己写的回调成功并正确执行了
  270. } else {
  271. // 代表用户已付款,但你自己写的回调执行失败(通常是因为你的回调代码有问题)
  272. }
  273. },
  274. onFail(err){
  275. console.log('err: ', err)
  276. },
  277. pageTo(url){
  278. uni.navigateTo({
  279. url
  280. });
  281. },
  282. providerFormat(provider){
  283. let providerObj = {
  284. "wxpay":"微信支付",
  285. "alipay":"支付宝支付",
  286. "appleiap":"ios内购"
  287. };
  288. let providerStr = providerObj[provider] || "未知";
  289. return providerStr;
  290. },
  291. /**
  292. * 日期格式化
  293. * @params {Date || Number} date 需要格式化的时间
  294. * timeFormat(new Date(),"yyyy-MM-dd hh:mm:ss");
  295. */
  296. timeFormat(time, fmt = 'yyyy-MM-dd hh:mm:ss', targetTimezone = 8){
  297. try {
  298. if (!time) {
  299. return "";
  300. }
  301. if (typeof time === "string" && !isNaN(time)) time = Number(time);
  302. // 其他更多是格式化有如下:
  303. // yyyy-MM-dd hh:mm:ss|yyyy年MM月dd日 hh时MM分等,可自定义组合
  304. let date;
  305. if (typeof time === "number") {
  306. if (time.toString().length == 10) time *= 1000;
  307. date = new Date(time);
  308. } else {
  309. date = time;
  310. }
  311. const dif = date.getTimezoneOffset();
  312. const timeDif = dif * 60 * 1000 + (targetTimezone * 60 * 60 * 1000);
  313. const east8time = date.getTime() + timeDif;
  314. date = new Date(east8time);
  315. let opt = {
  316. "M+": date.getMonth() + 1, //月份
  317. "d+": date.getDate(), //日
  318. "h+": date.getHours(), //小时
  319. "m+": date.getMinutes(), //分
  320. "s+": date.getSeconds(), //秒
  321. "q+": Math.floor((date.getMonth() + 3) / 3), //季度
  322. "S": date.getMilliseconds() //毫秒
  323. };
  324. if (/(y+)/.test(fmt)) {
  325. fmt = fmt.replace(RegExp.$1, (date.getFullYear() + "").substr(4 - RegExp.$1.length));
  326. }
  327. for (let k in opt) {
  328. if (new RegExp("(" + k + ")").test(fmt)) {
  329. fmt = fmt.replace(RegExp.$1, (RegExp.$1.length == 1) ? (opt[k]) : (("00" + opt[k]).substr(("" + opt[k]).length)));
  330. }
  331. }
  332. return fmt;
  333. } catch (err) {
  334. // 若格式错误,则原值显示
  335. return time;
  336. }
  337. },
  338. },
  339. computed: {
  340. h5Env(){
  341. // #ifdef H5
  342. let ua = window.navigator.userAgent.toLowerCase();
  343. if (ua.match(/MicroMessenger/i) == 'micromessenger' && (ua.match(/miniprogram/i) == 'miniprogram')) {
  344. // 微信小程序
  345. return "mp-weixin";
  346. }
  347. if (ua.match(/MicroMessenger/i) == 'micromessenger') {
  348. // 微信公众号
  349. return "h5-weixin";
  350. }
  351. if (ua.match(/alipay/i) == 'alipay' && ua.match(/miniprogram/i) == 'miniprogram') {
  352. return "mp-alipay";
  353. }
  354. if (ua.match(/alipay/i) == 'alipay') {
  355. return "h5-alipay";
  356. }
  357. // 外部 H5
  358. return "h5";
  359. // #endif
  360. },
  361. // 计算当前是否是ios app
  362. isIosAppCom(){
  363. let info = uni.getSystemInfoSync();
  364. return info.uniPlatform === 'app' && info.osName === 'ios' ? true : false;
  365. },
  366. // 计算当前是否是PC环境
  367. isPcCom(){
  368. // #ifdef H5
  369. let info = uni.getSystemInfoSync();
  370. return info.deviceType === 'pc' ? true : false;
  371. // #endif
  372. return false;
  373. }
  374. },
  375. }
  376. </script>
  377. <style lang="scss" scoped>
  378. .app{
  379. padding: 30rpx;
  380. }
  381. input {
  382. border: 1px solid #f3f3f3;
  383. padding: 10rpx;
  384. width: 100%;
  385. box-sizing: border-box;
  386. height: 80rpx;
  387. }
  388. button {
  389. margin-top: 20rpx;
  390. }
  391. .label{
  392. margin: 10rpx 0;
  393. }
  394. .tips{
  395. margin-top: 20rpx;
  396. font-size: 24rpx;
  397. color: #565656;
  398. }
  399. .get-order-popup{
  400. background-color: #ffffff;
  401. padding: 30rpx;
  402. height: 60vh;
  403. border-radius: 30rpx 30rpx 0 0;
  404. overflow: hidden;
  405. }
  406. .mt20{
  407. margin-top: 20rpx;
  408. }
  409. .pd2030{
  410. padding: 20rpx 30rpx;
  411. }
  412. .table{
  413. font-size: 24rpx;
  414. }
  415. .align-left{
  416. text-align: left;
  417. width: 50%;
  418. }
  419. .align-right{
  420. text-align: right;
  421. width: 50%;
  422. }
  423. </style>