feat(支付): 添加微信支付接口并实现支付流程
添加 WX_PAY 接口并实现小程序支付功能,当金额大于零时调用微信支付,否则直接跳转成功页 同时新增 API 文档转换功能,将原始文档转换为可用的 API 接口文件 更新首页轮播图图片
Showing
6 changed files
with
196 additions
and
37 deletions
doc/api/可预约时段列表.md
0 → 100644
| 1 | +# 可预约时段列表 | ||
| 2 | + | ||
| 3 | +## OpenAPI Specification | ||
| 4 | + | ||
| 5 | +```yaml | ||
| 6 | +openapi: 3.0.1 | ||
| 7 | +info: | ||
| 8 | + title: '' | ||
| 9 | + version: 1.0.0 | ||
| 10 | +paths: | ||
| 11 | + /srv/: | ||
| 12 | + get: | ||
| 13 | + summary: 可预约时段列表 | ||
| 14 | + deprecated: false | ||
| 15 | + description: '' | ||
| 16 | + tags: | ||
| 17 | + - 西园寺预约 | ||
| 18 | + parameters: | ||
| 19 | + - name: f | ||
| 20 | + in: query | ||
| 21 | + description: '' | ||
| 22 | + required: true | ||
| 23 | + example: reserve | ||
| 24 | + schema: | ||
| 25 | + type: string | ||
| 26 | + - name: a | ||
| 27 | + in: query | ||
| 28 | + description: '' | ||
| 29 | + required: true | ||
| 30 | + example: api | ||
| 31 | + schema: | ||
| 32 | + type: string | ||
| 33 | + - name: t | ||
| 34 | + in: query | ||
| 35 | + description: '' | ||
| 36 | + required: true | ||
| 37 | + example: can_reserve_time_list | ||
| 38 | + schema: | ||
| 39 | + type: string | ||
| 40 | + - name: client_name | ||
| 41 | + in: query | ||
| 42 | + description: 主体客户名称,测试环境和正式环境保持一致 | ||
| 43 | + required: true | ||
| 44 | + example: 西园寺 | ||
| 45 | + schema: | ||
| 46 | + type: string | ||
| 47 | + - name: month_date | ||
| 48 | + in: query | ||
| 49 | + description: 日期,格式yyyy-mm-dd | ||
| 50 | + required: true | ||
| 51 | + example: '2024-01-17' | ||
| 52 | + schema: | ||
| 53 | + type: string | ||
| 54 | + responses: | ||
| 55 | + '200': | ||
| 56 | + description: '' | ||
| 57 | + content: | ||
| 58 | + application/json: | ||
| 59 | + schema: | ||
| 60 | + type: object | ||
| 61 | + properties: | ||
| 62 | + code: | ||
| 63 | + type: integer | ||
| 64 | + msg: | ||
| 65 | + type: string | ||
| 66 | + data: | ||
| 67 | + type: array | ||
| 68 | + items: | ||
| 69 | + type: object | ||
| 70 | + properties: | ||
| 71 | + month_date: | ||
| 72 | + type: string | ||
| 73 | + title: 日期 | ||
| 74 | + begin_time: | ||
| 75 | + type: string | ||
| 76 | + title: 时段起始时间 | ||
| 77 | + end_time: | ||
| 78 | + type: string | ||
| 79 | + title: 时段结束时间 | ||
| 80 | + price: | ||
| 81 | + type: string | ||
| 82 | + title: 价格 | ||
| 83 | + rest_qty: | ||
| 84 | + type: string | ||
| 85 | + title: 余量 | ||
| 86 | + description: 说明: >0表示有余量,可约;=0表示没有余量,约满不可约;<0表示不限,无需续约; | ||
| 87 | + x-apifox-orders: | ||
| 88 | + - month_date | ||
| 89 | + - begin_time | ||
| 90 | + - end_time | ||
| 91 | + - price | ||
| 92 | + - rest_qty | ||
| 93 | + required: | ||
| 94 | + - code | ||
| 95 | + - msg | ||
| 96 | + - data | ||
| 97 | + x-apifox-orders: | ||
| 98 | + - code | ||
| 99 | + - msg | ||
| 100 | + - data | ||
| 101 | + headers: {} | ||
| 102 | + x-apifox-name: 成功 | ||
| 103 | + x-apifox-ordering: 0 | ||
| 104 | + security: [] | ||
| 105 | + x-apifox-folder: 西园寺预约 | ||
| 106 | + x-apifox-status: tested | ||
| 107 | + x-run-in-apifox: https://app.apifox.com/web/project/1753326/apis/api-140900863-run | ||
| 108 | +components: | ||
| 109 | + schemas: {} | ||
| 110 | + responses: {} | ||
| 111 | + securitySchemes: {} | ||
| 112 | +servers: | ||
| 113 | + - url: https://oa.jcedu.org | ||
| 114 | + description: 西园 | ||
| 115 | +security: [] | ||
| 116 | + | ||
| 117 | +``` |
doc/转换API文档.md
0 → 100644
| 1 | +读取原始接口文档, 参考原始文档的参数和返回值, 根据 index.js 接口文档编写方式, 把原始文档转换之后写到 test.js 里面. |
| 1 | /* | 1 | /* |
| 2 | * @Date: 2023-08-24 09:42:27 | 2 | * @Date: 2023-08-24 09:42:27 |
| 3 | * @LastEditors: hookehuyr hookehuyr@gmail.com | 3 | * @LastEditors: hookehuyr hookehuyr@gmail.com |
| 4 | - * @LastEditTime: 2026-01-07 17:43:26 | 4 | + * @LastEditTime: 2026-01-12 18:38:52 |
| 5 | * @FilePath: /xyxBooking-weapp/src/api/index.js | 5 | * @FilePath: /xyxBooking-weapp/src/api/index.js |
| 6 | * @Description: 文件描述 | 6 | * @Description: 文件描述 |
| 7 | */ | 7 | */ |
| ... | @@ -26,6 +26,7 @@ const Api = { | ... | @@ -26,6 +26,7 @@ const Api = { |
| 26 | BILL_PAY_STATUS: '/srv/?a=api&t=bill_pay_status', | 26 | BILL_PAY_STATUS: '/srv/?a=api&t=bill_pay_status', |
| 27 | QUERY_QR_CODE: '/srv/?a=api&t=id_number_query_qr_code', | 27 | QUERY_QR_CODE: '/srv/?a=api&t=id_number_query_qr_code', |
| 28 | ICBC_ORDER_QRY: '/srv/?a=icbc_orderqry', | 28 | ICBC_ORDER_QRY: '/srv/?a=icbc_orderqry', |
| 29 | + WX_PAY: '/srv/?a=icbc_pay_wxamp', | ||
| 29 | VOLUNTEER_LOGIN: '/srv/?a=api&t=volunteer_login', | 30 | VOLUNTEER_LOGIN: '/srv/?a=api&t=volunteer_login', |
| 30 | VERIFY_TICKET: '/srv/?a=api&t=verify_ticket', | 31 | VERIFY_TICKET: '/srv/?a=api&t=verify_ticket', |
| 31 | GET_USER_INFO: '/srv/?a=api&t=get_user_info', | 32 | GET_USER_INFO: '/srv/?a=api&t=get_user_info', |
| ... | @@ -215,3 +216,10 @@ export const queryQrCodeAPI = (params) => fn(fetch.get(Api.QUERY_QR_CODE, params | ... | @@ -215,3 +216,10 @@ export const queryQrCodeAPI = (params) => fn(fetch.get(Api.QUERY_QR_CODE, params |
| 215 | * @returns {String} | 216 | * @returns {String} |
| 216 | */ | 217 | */ |
| 217 | export const icbcOrderQryAPI = (params) => fn(fetch.get(Api.ICBC_ORDER_QRY, params)); | 218 | export const icbcOrderQryAPI = (params) => fn(fetch.get(Api.ICBC_ORDER_QRY, params)); |
| 219 | + | ||
| 220 | +/** | ||
| 221 | + * @description: 微信支付接口 | ||
| 222 | + * @param {*} pay_id 预约单支付凭证 | ||
| 223 | + * @returns {*} 微信支付参数 | ||
| 224 | + */ | ||
| 225 | +export const wxPayAPI = (params) => fn(fetch.post(Api.WX_PAY, params)); | ... | ... |
src/api/test.js
0 → 100644
| 1 | +/* | ||
| 2 | + * @Date: 2026-01-10 | ||
| 3 | + * @Description: 从原始文档转换生成的 API 接口文件 | ||
| 4 | + */ | ||
| 5 | +import { fn, fetch } from '@/api/fn'; | ||
| 6 | + | ||
| 7 | +const Api = { | ||
| 8 | + CAN_RESERVE_DATE_LIST: '/srv/?a=api&t=can_reserve_date_list', | ||
| 9 | + CAN_RESERVE_TIME_LIST: '/srv/?a=api&t=can_reserve_time_list', | ||
| 10 | +}; | ||
| 11 | + | ||
| 12 | +/** | ||
| 13 | + * @description: 可预约日期列表 | ||
| 14 | + * @param {String} month 月份,格式yyyy-mm | ||
| 15 | + * @returns {Promise<{ | ||
| 16 | + * code: number, | ||
| 17 | + * msg: string, | ||
| 18 | + * data: Array<{ | ||
| 19 | + * month_date: string, // 日期,格式yyyy-mm-dd | ||
| 20 | + * week_day: string, // 星期几 | ||
| 21 | + * full: string, // 是否约满,1=约满,0=未约满 | ||
| 22 | + * }> | ||
| 23 | + * }>} | ||
| 24 | + */ | ||
| 25 | +export const canReserveDateListAPI = (params) => fn(fetch.get(Api.CAN_RESERVE_DATE_LIST, params)); | ||
| 26 | + | ||
| 27 | +/** | ||
| 28 | + * @description: 可预约时段列表 | ||
| 29 | + * @param {String} month_date 日期,格式yyyy-mm-dd | ||
| 30 | + * @returns {Promise<{ | ||
| 31 | + * code: number, | ||
| 32 | + * msg: string, | ||
| 33 | + * data: Array<{ | ||
| 34 | + * month_date: string, // 日期 | ||
| 35 | + * begin_time: string, // 时段起始时间 | ||
| 36 | + * end_time: string, // 时段结束时间 | ||
| 37 | + * price: string, // 价格 | ||
| 38 | + * rest_qty: string // 余量 说明: >0表示有余量,可约;=0表示没有余量,约满不可约;<0表示不限,无需续约; | ||
| 39 | + * }> | ||
| 40 | + * }>} | ||
| 41 | + */ | ||
| 42 | +export const canReserveTimeListAPI = (params) => fn(fetch.get(Api.CAN_RESERVE_TIME_LIST, params)); |
| 1 | <!-- | 1 | <!-- |
| 2 | * @Date: 2023-06-21 10:23:09 | 2 | * @Date: 2023-06-21 10:23:09 |
| 3 | * @LastEditors: hookehuyr hookehuyr@gmail.com | 3 | * @LastEditors: hookehuyr hookehuyr@gmail.com |
| 4 | - * @LastEditTime: 2026-01-09 18:06:06 | 4 | + * @LastEditTime: 2026-01-09 18:08:03 |
| 5 | * @FilePath: /xyxBooking-weapp/src/pages/index/index.vue | 5 | * @FilePath: /xyxBooking-weapp/src/pages/index/index.vue |
| 6 | * @Description: 预约页首页 | 6 | * @Description: 预约页首页 |
| 7 | --> | 7 | --> |
| ... | @@ -11,7 +11,7 @@ | ... | @@ -11,7 +11,7 @@ |
| 11 | <view style="height: 28vh;"> | 11 | <view style="height: 28vh;"> |
| 12 | <swiper class="my-swipe" :autoplay="true" :interval="3000" indicator-dots indicator-color="white" :circular="true"> | 12 | <swiper class="my-swipe" :autoplay="true" :interval="3000" indicator-dots indicator-color="white" :circular="true"> |
| 13 | <swiper-item> | 13 | <swiper-item> |
| 14 | - <image style="height: 28vh; width: 100vw;" src="https://cdn.ipadbiz.cn/xys/booking/banner02.png?imageMogr2/thumbnail/500x/strip/quality/100" /> | 14 | + <image style="height: 28vh; width: 100vw;" src="https://cdn.ipadbiz.cn/xys/booking/banner01.png?imageMogr2/thumbnail/500x/strip/quality/100" /> |
| 15 | </swiper-item> | 15 | </swiper-item> |
| 16 | </swiper> | 16 | </swiper> |
| 17 | </view> | 17 | </view> | ... | ... |
| 1 | <!-- | 1 | <!-- |
| 2 | * @Date: 2024-01-15 16:25:51 | 2 | * @Date: 2024-01-15 16:25:51 |
| 3 | * @LastEditors: hookehuyr hookehuyr@gmail.com | 3 | * @LastEditors: hookehuyr hookehuyr@gmail.com |
| 4 | - * @LastEditTime: 2026-01-06 21:22:54 | 4 | + * @LastEditTime: 2026-01-12 18:42:42 |
| 5 | - * @FilePath: /git/xyxBooking-weapp/src/pages/submit/index.vue | 5 | + * @FilePath: /xyxBooking-weapp/src/pages/submit/index.vue |
| 6 | * @Description: 预约人员信息 | 6 | * @Description: 预约人员信息 |
| 7 | --> | 7 | --> |
| 8 | <template> | 8 | <template> |
| ... | @@ -53,7 +53,7 @@ import { IconFont } from '@nutui/icons-vue-taro' | ... | @@ -53,7 +53,7 @@ import { IconFont } from '@nutui/icons-vue-taro' |
| 53 | import { useGo } from '@/hooks/useGo' | 53 | import { useGo } from '@/hooks/useGo' |
| 54 | import icon_check1 from '@/assets/images/多选01@2x.png' | 54 | import icon_check1 from '@/assets/images/多选01@2x.png' |
| 55 | import icon_check2 from '@/assets/images/多选02@2x.png' | 55 | import icon_check2 from '@/assets/images/多选02@2x.png' |
| 56 | -import { personListAPI, addReserveAPI } from '@/api/index' | 56 | +import { personListAPI, addReserveAPI, wxPayAPI } from '@/api/index' |
| 57 | 57 | ||
| 58 | const router = useTaroRouter(); | 58 | const router = useTaroRouter(); |
| 59 | const go = useGo(); | 59 | const go = useGo(); |
| ... | @@ -129,37 +129,28 @@ const submitBtn = async () => { | ... | @@ -129,37 +129,28 @@ const submitBtn = async () => { |
| 129 | Taro.hideLoading(); | 129 | Taro.hideLoading(); |
| 130 | 130 | ||
| 131 | if (code) { | 131 | if (code) { |
| 132 | - // H5 逻辑: const pay_url = `/srv/?f=reserve&a=icbc_pay&pay_id=${data.pay_id}`; location.href = pay_url; | 132 | + // 如果金额大于零, 走微信支付, 如果等于零直接跳转成功页 |
| 133 | - // 小程序逻辑: | 133 | + if (total.value > 0) { |
| 134 | - // 1. 如果支持小程序支付,应该调用获取支付参数接口 | 134 | + const payParams = await wxPayAPI({ pay_id: data.pay_id }); // 参数接口 |
| 135 | - // 2. 暂时提示不支持,或尝试模拟 | 135 | + |
| 136 | - | 136 | + if (payParams.code) { |
| 137 | - // 假设 payPrepareAPI 可用 | 137 | + let pay = payParams.data; |
| 138 | - // const payParams = await payPrepareAPI({ bill_id: data.pay_id }); // 假设接口 | 138 | + Taro.requestPayment({ |
| 139 | - | 139 | + timeStamp: pay.timeStamp, |
| 140 | - Taro.showModal({ | 140 | + nonceStr: pay.nonceStr, |
| 141 | - title: '提示', | 141 | + package: pay.package, |
| 142 | - content: '订单提交成功。由于小程序支付暂未配置,请联系管理员或前往H5完成支付。', | 142 | + signType: pay.signType, |
| 143 | - showCancel: false, | 143 | + paySign: pay.paySign, |
| 144 | - success: () => { | 144 | + success (res) { |
| 145 | - go('/bookingList'); | 145 | + go('/success', { pay_id: data.pay_id }); |
| 146 | - } | 146 | + }, |
| 147 | - }); | 147 | + fail (res) { } |
| 148 | - | 148 | + }) |
| 149 | - // 如果后端有返回支付参数,可以使用 requestPayment | 149 | + } |
| 150 | - /* | 150 | + } else { |
| 151 | - Taro.requestPayment({ | 151 | + // 金额等于零, 直接跳转成功页 |
| 152 | - timeStamp: '', | 152 | + go('/success', { pay_id: data.pay_id }); |
| 153 | - nonceStr: '', | 153 | + } |
| 154 | - package: '', | ||
| 155 | - signType: 'MD5', | ||
| 156 | - paySign: '', | ||
| 157 | - success (res) { | ||
| 158 | - go('/success'); | ||
| 159 | - }, | ||
| 160 | - fail (res) { } | ||
| 161 | - }) | ||
| 162 | - */ | ||
| 163 | } | 154 | } |
| 164 | } | 155 | } |
| 165 | } | 156 | } | ... | ... |
-
Please register or login to post a comment