Browse Source

对接 查询支付结果、关闭支付订单、查询第三方订单 接口

master
DU 2 months ago
parent
commit
7eeadec17d
  1. 56
      src/api/order.ts
  2. 60
      src/pageScan/couponStart/index.tsx
  3. 56
      src/pageScan/renewFee/index.tsx
  4. 59
      src/pageScan/selfStart/index.tsx
  5. 58
      src/pageScan/timedStart/index.tsx
  6. 56
      src/pageScan/turnOffRestart/index.tsx
  7. 63
      src/types/order.ts

56
src/api/order.ts

@ -0,0 +1,56 @@ @@ -0,0 +1,56 @@
/**
* / API
*/
import { get, post } from '../services/request'
import { PaymentResult, QueryPaymentRequest, CloseOrderDto } from '../types/order'
/**
* outTradeNo tradeNo
* @param dto
*/
export const queryPaymentResult = (dto: QueryPaymentRequest) => {
return post<PaymentResult>('/Order/query', dto)
}
/**
*
* @param outTradeNo
*/
export const closeOrder = (outTradeNo: string) => {
return post<boolean>('/Order/close', { outTradeNo } as CloseOrderDto)
}
/**
* ID查询//
* @param consumptionId ID startDevice
*/
export const queryPaymentByConsumptionId = (consumptionId: number) => {
return get<PaymentResult>(`/Order/query/${consumptionId}`)
}
/**
*
* data.success === true data.tradeState === 'SUCCESS'
* @param consumptionId ID
* @param maxRetries 5
* @param intervalMs 2000ms
* @returns
*/
export const pollTablePaymentStatus = async (
consumptionId: number,
maxRetries = 5,
intervalMs = 2000
): Promise<boolean> => {
for (let i = 0; i < maxRetries; i++) {
await new Promise(resolve => setTimeout(resolve, intervalMs))
try {
const res = await queryPaymentByConsumptionId(consumptionId)
if (res.data?.success || res.data?.tradeState === 'SUCCESS') {
return true
}
} catch (e) {
console.warn(`查询支付状态第${i + 1}次异常:`, e)
}
}
return false
}

60
src/pageScan/couponStart/index.tsx

@ -6,6 +6,7 @@ import Taro, { useLoad, useRouter } from '@tarojs/taro' @@ -6,6 +6,7 @@ import Taro, { useLoad, useRouter } from '@tarojs/taro'
import { useState } from 'react'
import { observer } from 'mobx-react'
import { couponStart, invokeWechatPay } from '../../api/startDevice'
import { closeOrder, pollTablePaymentStatus } from '../../api/order'
import { userStore, tableStore } from '../../store'
import './index.scss'
@ -173,53 +174,50 @@ const CouponStart = observer(() => { @@ -173,53 +174,50 @@ const CouponStart = observer(() => {
tableStore.setCurrentOperationId(result.data.consumptionId)
}
// 判断是否需要支付(团购券一般不需要支付,但可能需要补差价)
const consumptionId = result.data.consumptionId
const outTradeNo = result.data.paymentResponseDto?.outTradeNo
// 判断是否需要支付(团购券一般无需支付,但可能需要补差价)
if (result.data.paymentResponseDto?.payParameters) {
// 调起微信支付
try {
await invokeWechatPay(result.data.paymentResponseDto.payParameters)
// 支付成功
Taro.showToast({
title: '开台成功',
icon: 'success',
duration: 2000
})
// 跳转到关台页面
setTimeout(() => {
Taro.redirectTo({
url: `/pageScan/closeTable/index?grpSn=${grpSn}&operationId=${result.data.consumptionId}`
// 轮询服务端确认支付结果
Taro.showLoading({ title: '确认支付中...', mask: true })
const paid = await pollTablePaymentStatus(consumptionId)
Taro.hideLoading()
if (paid) {
Taro.showToast({ title: '开台成功', icon: 'success', duration: 2000 })
setTimeout(() => {
Taro.redirectTo({
url: `/pageScan/closeTable/index?grpSn=${grpSn}&operationId=${consumptionId}`
})
}, 2000)
} else {
Taro.showModal({
title: '支付确认中',
content: '支付结果尚未到账,请稍后至"关台"页查看状态,如有疑问请联系店长。',
showCancel: false,
confirmText: '知道了',
})
}, 2000)
}
} catch (payError: any) {
console.log('支付错误:', payError)
// 用户取消支付或支付失败
if (outTradeNo) closeOrder(outTradeNo).catch(() => {})
if (payError.errMsg?.includes('cancel')) {
Taro.showToast({
title: '已取消支付',
icon: 'none',
duration: 2000
})
Taro.showToast({ title: '已取消支付', icon: 'none', duration: 2000 })
} else {
Taro.showToast({
title: payError.errMsg || '支付失败',
icon: 'none',
duration: 2000
})
Taro.showToast({ title: payError.errMsg || '支付失败', icon: 'none', duration: 2000 })
}
}
} else {
// 无需支付
Taro.showToast({
title: '兑换成功,开台成功',
icon: 'success',
duration: 2000
})
Taro.showToast({ title: '兑换成功,开台成功', icon: 'success', duration: 2000 })
setTimeout(() => {
Taro.redirectTo({
url: `/pageScan/closeTable/index?grpSn=${grpSn}&operationId=${result.data.consumptionId}`
url: `/pageScan/closeTable/index?grpSn=${grpSn}&operationId=${consumptionId}`
})
}, 2000)
}

56
src/pageScan/renewFee/index.tsx

@ -7,6 +7,7 @@ import { useState } from 'react' @@ -7,6 +7,7 @@ import { useState } from 'react'
import { observer } from 'mobx-react'
import { Stepper } from '@taroify/core'
import { renewFee, invokeWechatPay, PayType } from '../../api/startDevice'
import { closeOrder, pollTablePaymentStatus } from '../../api/order'
import { userStore, tableStore } from '../../store'
import './index.scss'
@ -100,51 +101,44 @@ const RenewFee = observer(() => { @@ -100,51 +101,44 @@ const RenewFee = observer(() => {
console.log('续费接口返回:', result)
const consumptionId = result.data.consumptionId
const outTradeNo = result.data.paymentResponseDto?.outTradeNo
// 判断是否需要支付
if (result.data.paymentResponseDto?.payParameters) {
// 调起微信支付
try {
await invokeWechatPay(result.data.paymentResponseDto.payParameters)
// 支付成功
Taro.showToast({
title: '续费成功',
icon: 'success',
duration: 2000
})
// 返回关台页面
setTimeout(() => {
Taro.navigateBack()
}, 2000)
// 轮询服务端确认支付结果
Taro.showLoading({ title: '确认支付中...', mask: true })
const paid = await pollTablePaymentStatus(consumptionId)
Taro.hideLoading()
if (paid) {
Taro.showToast({ title: '续费成功', icon: 'success', duration: 2000 })
setTimeout(() => Taro.navigateBack(), 2000)
} else {
Taro.showModal({
title: '支付确认中',
content: '支付结果尚未到账,请稍后刷新页面查看,如有疑问请联系店长。',
showCancel: false,
confirmText: '知道了',
})
}
} catch (payError: any) {
console.log('支付错误:', payError)
// 用户取消支付或支付失败
if (outTradeNo) closeOrder(outTradeNo).catch(() => {})
if (payError.errMsg?.includes('cancel')) {
Taro.showToast({
title: '已取消支付',
icon: 'none',
duration: 2000
})
Taro.showToast({ title: '已取消支付', icon: 'none', duration: 2000 })
} else {
Taro.showToast({
title: payError.errMsg || '支付失败',
icon: 'none',
duration: 2000
})
Taro.showToast({ title: payError.errMsg || '支付失败', icon: 'none', duration: 2000 })
}
}
} else {
// 无需支付
Taro.showToast({
title: '续费成功',
icon: 'success',
duration: 2000
})
setTimeout(() => {
Taro.navigateBack()
}, 2000)
Taro.showToast({ title: '续费成功', icon: 'success', duration: 2000 })
setTimeout(() => Taro.navigateBack(), 2000)
}
} catch (error: any) {
console.error('续费失败:', error)

59
src/pageScan/selfStart/index.tsx

@ -7,6 +7,7 @@ import { useState } from 'react' @@ -7,6 +7,7 @@ import { useState } from 'react'
import { observer } from 'mobx-react'
import { Stepper } from '@taroify/core'
import { depositStart, balanceStart, invokeWechatPay, PayType } from '../../api/startDevice'
import { closeOrder, pollTablePaymentStatus } from '../../api/order'
import { userStore, tableStore } from '../../store'
import './index.scss'
@ -142,53 +143,51 @@ const SelfStart = observer(() => { @@ -142,53 +143,51 @@ const SelfStart = observer(() => {
tableStore.setCurrentOperationId(result.data.consumptionId)
}
const consumptionId = result.data.consumptionId
const outTradeNo = result.data.paymentResponseDto?.outTradeNo
// 判断是否需要支付
if (result.data.paymentResponseDto?.payParameters) {
// 调起微信支付
try {
await invokeWechatPay(result.data.paymentResponseDto.payParameters)
// 支付成功
Taro.showToast({
title: '开台成功',
icon: 'success',
duration: 2000
})
// 跳转到关台页面
setTimeout(() => {
Taro.redirectTo({
url: `/pageScan/closeTable/index?grpSn=${grpSn}&operationId=${result.data.consumptionId}`
// 轮询服务端确认支付结果
Taro.showLoading({ title: '确认支付中...', mask: true })
const paid = await pollTablePaymentStatus(consumptionId)
Taro.hideLoading()
if (paid) {
Taro.showToast({ title: '开台成功', icon: 'success', duration: 2000 })
setTimeout(() => {
Taro.redirectTo({
url: `/pageScan/closeTable/index?grpSn=${grpSn}&operationId=${consumptionId}`
})
}, 2000)
} else {
Taro.showModal({
title: '支付确认中',
content: '支付结果尚未到账,请稍后至"关台"页查看状态,如有疑问请联系店长。',
showCancel: false,
confirmText: '知道了',
})
}, 2000)
}
} catch (payError: any) {
console.log('支付错误:', payError)
// 用户取消支付或支付失败
// 关闭服务端未支付订单,避免产生悬挂订单
if (outTradeNo) closeOrder(outTradeNo).catch(() => {})
if (payError.errMsg?.includes('cancel')) {
Taro.showToast({
title: '已取消支付',
icon: 'none',
duration: 2000
})
Taro.showToast({ title: '已取消支付', icon: 'none', duration: 2000 })
} else {
Taro.showToast({
title: payError.errMsg || '支付失败',
icon: 'none',
duration: 2000
})
Taro.showToast({ title: payError.errMsg || '支付失败', icon: 'none', duration: 2000 })
}
}
} else {
// 无需支付(余额支付等场景)
Taro.showToast({
title: '开台成功',
icon: 'success',
duration: 2000
})
Taro.showToast({ title: '开台成功', icon: 'success', duration: 2000 })
setTimeout(() => {
Taro.redirectTo({
url: `/pageScan/closeTable/index?grpSn=${grpSn}&operationId=${result.data.consumptionId}`
url: `/pageScan/closeTable/index?grpSn=${grpSn}&operationId=${consumptionId}`
})
}, 2000)
}

58
src/pageScan/timedStart/index.tsx

@ -6,6 +6,7 @@ import Taro, { useLoad, useRouter } from '@tarojs/taro' @@ -6,6 +6,7 @@ import Taro, { useLoad, useRouter } from '@tarojs/taro'
import { useState } from 'react'
import { observer } from 'mobx-react'
import { timedStart, invokeWechatPay, PayType } from '../../api/startDevice'
import { closeOrder, pollTablePaymentStatus } from '../../api/order'
import { userStore, tableStore } from '../../store'
import './index.scss'
@ -118,53 +119,50 @@ const TimedStart = observer(() => { @@ -118,53 +119,50 @@ const TimedStart = observer(() => {
tableStore.setCurrentOperationId(result.data.consumptionId)
}
const consumptionId = result.data.consumptionId
const outTradeNo = result.data.paymentResponseDto?.outTradeNo
// 判断是否需要支付
if (result.data.paymentResponseDto?.payParameters) {
// 调起微信支付
try {
await invokeWechatPay(result.data.paymentResponseDto.payParameters)
// 支付成功
Taro.showToast({
title: '开台成功',
icon: 'success',
duration: 2000
})
// 跳转到关台页面
setTimeout(() => {
Taro.redirectTo({
url: `/pageScan/closeTable/index?grpSn=${grpSn}&operationId=${result.data.consumptionId}`
// 轮询服务端确认支付结果
Taro.showLoading({ title: '确认支付中...', mask: true })
const paid = await pollTablePaymentStatus(consumptionId)
Taro.hideLoading()
if (paid) {
Taro.showToast({ title: '开台成功', icon: 'success', duration: 2000 })
setTimeout(() => {
Taro.redirectTo({
url: `/pageScan/closeTable/index?grpSn=${grpSn}&operationId=${consumptionId}`
})
}, 2000)
} else {
Taro.showModal({
title: '支付确认中',
content: '支付结果尚未到账,请稍后至"关台"页查看状态,如有疑问请联系店长。',
showCancel: false,
confirmText: '知道了',
})
}, 2000)
}
} catch (payError: any) {
console.log('支付错误:', payError)
// 用户取消支付或支付失败
if (outTradeNo) closeOrder(outTradeNo).catch(() => {})
if (payError.errMsg?.includes('cancel')) {
Taro.showToast({
title: '已取消支付',
icon: 'none',
duration: 2000
})
Taro.showToast({ title: '已取消支付', icon: 'none', duration: 2000 })
} else {
Taro.showToast({
title: payError.errMsg || '支付失败',
icon: 'none',
duration: 2000
})
Taro.showToast({ title: payError.errMsg || '支付失败', icon: 'none', duration: 2000 })
}
}
} else {
// 无需支付
Taro.showToast({
title: '开台成功',
icon: 'success',
duration: 2000
})
Taro.showToast({ title: '开台成功', icon: 'success', duration: 2000 })
setTimeout(() => {
Taro.redirectTo({
url: `/pageScan/closeTable/index?grpSn=${grpSn}&operationId=${result.data.consumptionId}`
url: `/pageScan/closeTable/index?grpSn=${grpSn}&operationId=${consumptionId}`
})
}, 2000)
}

56
src/pageScan/turnOffRestart/index.tsx

@ -6,6 +6,7 @@ import Taro, { useLoad, useRouter } from '@tarojs/taro' @@ -6,6 +6,7 @@ import Taro, { useLoad, useRouter } from '@tarojs/taro'
import { useState } from 'react'
import { observer } from 'mobx-react'
import { turnOffRestart, invokeWechatPay } from '../../api/startDevice'
import { closeOrder, pollTablePaymentStatus } from '../../api/order'
import { userStore, tableStore } from '../../store'
import './index.scss'
@ -86,51 +87,44 @@ const TurnOffRestart = observer(() => { @@ -86,51 +87,44 @@ const TurnOffRestart = observer(() => {
console.log('关灯重开接口返回:', result)
const consumptionId = result.data.consumptionId
const outTradeNo = result.data.paymentResponseDto?.outTradeNo
// 判断是否需要支付
if (result.data.paymentResponseDto?.payParameters) {
// 调起微信支付
try {
await invokeWechatPay(result.data.paymentResponseDto.payParameters)
// 支付成功
Taro.showToast({
title: '结算成功',
icon: 'success',
duration: 2000
})
// 返回关台页面或跳转到首页
setTimeout(() => {
Taro.navigateBack()
}, 2000)
// 轮询服务端确认支付结果
Taro.showLoading({ title: '确认支付中...', mask: true })
const paid = await pollTablePaymentStatus(consumptionId)
Taro.hideLoading()
if (paid) {
Taro.showToast({ title: '结算成功', icon: 'success', duration: 2000 })
setTimeout(() => Taro.navigateBack(), 2000)
} else {
Taro.showModal({
title: '支付确认中',
content: '支付结果尚未到账,请稍后刷新页面查看,如有疑问请联系店长。',
showCancel: false,
confirmText: '知道了',
})
}
} catch (payError: any) {
console.log('支付错误:', payError)
// 用户取消支付或支付失败
if (outTradeNo) closeOrder(outTradeNo).catch(() => {})
if (payError.errMsg?.includes('cancel')) {
Taro.showToast({
title: '已取消支付',
icon: 'none',
duration: 2000
})
Taro.showToast({ title: '已取消支付', icon: 'none', duration: 2000 })
} else {
Taro.showToast({
title: payError.errMsg || '支付失败',
icon: 'none',
duration: 2000
})
Taro.showToast({ title: payError.errMsg || '支付失败', icon: 'none', duration: 2000 })
}
}
} else {
// 无需支付
Taro.showToast({
title: '结算成功',
icon: 'success',
duration: 2000
})
setTimeout(() => {
Taro.navigateBack()
}, 2000)
Taro.showToast({ title: '结算成功', icon: 'success', duration: 2000 })
setTimeout(() => Taro.navigateBack(), 2000)
}
} catch (error: any) {
console.error('关灯重开失败:', error)

63
src/types/order.ts

@ -0,0 +1,63 @@ @@ -0,0 +1,63 @@
/**
* /
*/
/**
*
*/
export type PaymentChannel = 'WechatPay' | 'Alipay' | 'UnionPay' | 'Balance' | 'BankCard'
/**
*
*/
export interface PaymentResult {
/** 是否成功 */
success: boolean
/** 消息 */
message: string
/** 商户订单号 */
outTradeNo: string
/** 支付渠道订单号 */
tradeNo: string
/** 支付金额 */
amount: number
/** 支付时间 */
payTime: string
/** 支付渠道 */
channel: PaymentChannel
/** 前端调起支付所需参数 */
payParameters: unknown
/** 支付URL(扫码支付等) */
payUrl: string
/** H5支付URL */
mwebUrl: string
/** 预支付ID(小程序/JSAPI支付) */
prepayId: string
/**
*
* SUCCESS- / REFUND-退 / NOTPAY- / CLOSED- / REVOKED- / USERPAYING- / PAYERROR-
*/
tradeState: string
/** 原始响应数据 */
rawResponse: unknown
}
/**
* POST /Order/query
*/
export interface QueryPaymentRequest {
/** 商户订单号 */
outTradeNo?: string
/** 微信支付订单号 */
tradeNo?: string
/** 支付渠道 */
channel?: PaymentChannel
}
/**
* POST /Order/close
*/
export interface CloseOrderDto {
/** 商户订单号 */
outTradeNo: string
}
Loading…
Cancel
Save