mirror of
https://gitee.com/bootx/dax-pay-h5.git
synced 2025-10-13 21:50:26 +00:00
feat(daxpay): 实现微信和支付宝聚合支付功能
- 新增 AliAggregate 和 WechatAggregate组件用于聚合支付页面 - 实现了获取聚合配置、认证、支付等核心逻辑 - 优化了错误处理和页面跳转逻辑 - 重构了部分 API接口和数据结构
This commit is contained in:
1
components.d.ts
vendored
1
components.d.ts
vendored
@@ -17,6 +17,7 @@ declare module 'vue' {
|
||||
VanLoading: typeof import('vant/es')['Loading']
|
||||
VanNumberKeyboard: typeof import('vant/es')['NumberKeyboard']
|
||||
VanOverlay: typeof import('vant/es')['Overlay']
|
||||
VanSubmitBar: typeof import('vant/es')['SubmitBar']
|
||||
VanTextEllipsis: typeof import('vant/es')['TextEllipsis']
|
||||
}
|
||||
}
|
||||
|
@@ -19,6 +19,14 @@ export enum PayMethodEnum {
|
||||
JSAPI = 'jsapi',
|
||||
}
|
||||
|
||||
/**
|
||||
* 收银台类型
|
||||
*/
|
||||
export enum CashierTypeEnum {
|
||||
WECHAT_PAY = 'wechat_pay',
|
||||
ALIPAY = 'alipay',
|
||||
}
|
||||
|
||||
/**
|
||||
* 收银台类型
|
||||
*/
|
||||
@@ -29,8 +37,7 @@ export enum CheckoutTypeEnum {
|
||||
AGGREGATE = 'aggregate',
|
||||
}
|
||||
|
||||
export enum AggregateEnum{
|
||||
ALI = 'ali',
|
||||
export enum AggregateTypeEnum {
|
||||
ALI = 'alipay',
|
||||
WECHAT = 'wechat_pay',
|
||||
}
|
||||
|
||||
|
@@ -82,7 +82,7 @@ import { useKeyboard } from '@/hooks/daxpay/useKeyboard'
|
||||
|
||||
const route = useRoute()
|
||||
const { code } = route.params
|
||||
const { code : authCode } = route.query
|
||||
const { code: authCode } = route.query
|
||||
|
||||
const show = ref<boolean>(false)
|
||||
const showRemark = ref<boolean>(false)
|
||||
@@ -94,8 +94,8 @@ const openId = ref<string>('')
|
||||
|
||||
// 认证参数
|
||||
const authParam = ref<CashierAuthParam>({
|
||||
code: code as string,
|
||||
type: CashierTypeEnum.WECHAT_PAY,
|
||||
cashierCode: code as string,
|
||||
cashierType: CashierTypeEnum.WECHAT_PAY,
|
||||
})
|
||||
const { input, del } = useKeyboard(amount)
|
||||
|
||||
@@ -110,7 +110,7 @@ function init() {
|
||||
// 如果不是重定向跳转过来, 跳转到到重定向授权地址
|
||||
if (!authCode) {
|
||||
// 重定向跳转到微信授权地址
|
||||
generateAuthUrl({ cashierType: CashierTypeEnum.WECHAT_PAY, cashierCode: code as string}).then((res) => {
|
||||
generateAuthUrl({ cashierType: CashierTypeEnum.WECHAT_PAY, cashierCode: code as string }).then((res) => {
|
||||
const url = res.data
|
||||
location.replace(url)
|
||||
}).catch((res) => {
|
||||
|
@@ -1,7 +1,7 @@
|
||||
import { http } from '@/utils/http/axios'
|
||||
import type { Result } from '#/axios'
|
||||
import type { AuthResult } from '@/views/daxpay/auth/ChannelAuth.api'
|
||||
import {PayResult} from "@/views/daxpay/cashier/CashierCode.api";
|
||||
import type { PayResult } from '@/views/daxpay/cashier/CashierCode.api'
|
||||
|
||||
/**
|
||||
* 获取收银台订单和配置信息
|
||||
@@ -43,7 +43,7 @@ export function generateAuthUrl(param: CheckoutAuthUrlParam) {
|
||||
* 获取授权结果
|
||||
*/
|
||||
export function auth(param: CheckoutAuthCodeParam) {
|
||||
return http.request<AuthResult>({
|
||||
return http.request<Result<AuthResult>>({
|
||||
url: '/unipay/checkout/auth',
|
||||
method: 'post',
|
||||
data: param,
|
||||
@@ -53,7 +53,7 @@ export function auth(param: CheckoutAuthCodeParam) {
|
||||
* 发起普通支付
|
||||
*/
|
||||
export function checkoutPay(param: CheckoutPayParam) {
|
||||
return http.request<Result<CheckoutPayResult>>({
|
||||
return http.request<Result<PayResult>>({
|
||||
url: '/unipay/checkout/pay',
|
||||
method: 'post',
|
||||
data: param,
|
||||
@@ -75,30 +75,20 @@ export function aggregatePay(param: CheckoutAggregatePayParam) {
|
||||
* 收银台认证链接生成参数
|
||||
*/
|
||||
export interface CheckoutAuthUrlParam {
|
||||
/**
|
||||
* 要支付的订单号
|
||||
*/
|
||||
/** 要支付的订单号 */
|
||||
orderNo?: string
|
||||
/**
|
||||
* 聚合支付类型
|
||||
*/
|
||||
/** 聚合支付类型 */
|
||||
aggregateType?: string
|
||||
}
|
||||
/**
|
||||
* 获取收银台认证结果参数
|
||||
*/
|
||||
export interface CheckoutAuthCodeParam {
|
||||
/**
|
||||
* 要支付的订单号
|
||||
*/
|
||||
/** 要支付的订单号 */
|
||||
orderNo?: string
|
||||
/**
|
||||
* 聚合支付类型
|
||||
*/
|
||||
/** 聚合支付类型 */
|
||||
aggregateType?: string
|
||||
/**
|
||||
* 认证Code
|
||||
*/
|
||||
/** 认证Code */
|
||||
authCode?: string
|
||||
}
|
||||
|
||||
@@ -106,25 +96,16 @@ export interface CheckoutAuthCodeParam {
|
||||
* 收银台支付参数
|
||||
*/
|
||||
export interface CheckoutPayParam {
|
||||
/**
|
||||
* 订单号
|
||||
*/
|
||||
/** 订单号 */
|
||||
orderNo?: string
|
||||
/**
|
||||
* 支付配置项ID
|
||||
*/
|
||||
/** 支付配置项ID */
|
||||
itemId?: string
|
||||
/**
|
||||
* 唯一标识
|
||||
*/
|
||||
/** 唯一标识 */
|
||||
openId?: string
|
||||
/**
|
||||
* 付款码
|
||||
*/
|
||||
/** 付款码 */
|
||||
barCode?: string
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* 聚合支付参数
|
||||
*/
|
||||
@@ -137,22 +118,27 @@ export interface CheckoutAggregatePayParam {
|
||||
openId?: string
|
||||
}
|
||||
|
||||
/**
|
||||
* 收银台配置
|
||||
*/
|
||||
export interface CheckoutOrderAndConfigResult {
|
||||
/** 订单信息 */
|
||||
order: CheckoutOrderResult
|
||||
/** 收银台配置信息 */
|
||||
config: CheckoutConfigResult
|
||||
/** 收银台分类配置信息 */
|
||||
groupConfigs: CheckoutGroupConfigResult[]
|
||||
}
|
||||
|
||||
/**
|
||||
* 收银台聚合支付配置
|
||||
*/
|
||||
export interface AggregateOrderAndConfigResult {
|
||||
|
||||
/**
|
||||
* 订单信息
|
||||
*/
|
||||
/** 订单信息 */
|
||||
order: CheckoutOrderResult
|
||||
/**
|
||||
* 收银台配置信息
|
||||
*/
|
||||
/** 收银台配置信息 */
|
||||
config: CheckoutConfigResult
|
||||
/**
|
||||
* 收银台聚合配置信息
|
||||
*/
|
||||
/** 收银台聚合配置信息 */
|
||||
aggregateConfig: AggregateConfigResult
|
||||
}
|
||||
|
||||
@@ -183,6 +169,33 @@ export interface CheckoutConfigResult {
|
||||
/** h5收银台自动升级聚合支付 */
|
||||
h5AutoUpgrade?: boolean
|
||||
}
|
||||
|
||||
/**
|
||||
* 收银台分类配置
|
||||
*/
|
||||
export interface CheckoutGroupConfigResult {
|
||||
/** 类型 */
|
||||
type?: string
|
||||
/** 名称 */
|
||||
name?: string
|
||||
/** 配置项列表 */
|
||||
items?: CheckoutItemConfigResult[]
|
||||
}
|
||||
|
||||
/**
|
||||
* 收银台配置项
|
||||
*/
|
||||
export interface CheckoutItemConfigResult {
|
||||
/** 发起调用的类型 */
|
||||
callType?: string
|
||||
/** 名称 */
|
||||
name?: string
|
||||
/** 支付通道 */
|
||||
channel?: string
|
||||
/** 支付方式 */
|
||||
payMethod?: string
|
||||
}
|
||||
|
||||
/**
|
||||
* 收银台聚合配置信息
|
||||
*/
|
||||
@@ -196,18 +209,3 @@ export interface AggregateConfigResult {
|
||||
/** 自动拉起支付 */
|
||||
autoLaunch?: boolean
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* 收银台支付结果
|
||||
*/
|
||||
export interface CheckoutPayResult {
|
||||
/**
|
||||
* 链接
|
||||
*/
|
||||
url?: string
|
||||
/**
|
||||
* 支付状态
|
||||
*/
|
||||
payStatus?: string
|
||||
}
|
||||
|
@@ -1,19 +1,67 @@
|
||||
<template>
|
||||
<div>
|
||||
|
||||
</div>
|
||||
</template>
|
||||
|
||||
<script setup lang="ts">
|
||||
import { useRoute } from 'vue-router'
|
||||
import { onMounted, ref } from 'vue'
|
||||
import type { CheckoutOrderAndConfigResult } from './CheckoutPay.api'
|
||||
import { getOrderAndConfig } from './CheckoutPay.api'
|
||||
import { CheckoutTypeEnum } from '@/enums/daxpay/DaxPayEnum'
|
||||
import router from '@/router'
|
||||
|
||||
const route = useRoute()
|
||||
const { orderNo } = route.params
|
||||
|
||||
const { orderNo } = route.params
|
||||
const ua = navigator.userAgent
|
||||
|
||||
onMounted(()=>{
|
||||
|
||||
const orderAndConfig = ref<CheckoutOrderAndConfigResult>({
|
||||
order: {},
|
||||
config: {},
|
||||
groupConfigs: [],
|
||||
})
|
||||
|
||||
/**
|
||||
* 初始化
|
||||
*/
|
||||
onMounted(() => {
|
||||
initData()
|
||||
})
|
||||
|
||||
/**
|
||||
* 初始化数据
|
||||
*/
|
||||
async function initData() {
|
||||
// 获取收银台配置
|
||||
await getOrderAndConfig(orderNo, CheckoutTypeEnum.H5).then(({ data }) => {
|
||||
orderAndConfig.value = data
|
||||
})
|
||||
// 判断是否自动升级为聚合控制台
|
||||
if (orderAndConfig.value.config.h5AutoUpgrade) {
|
||||
goAggregate()
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* 跳转到聚合收银台
|
||||
*/
|
||||
function goAggregate() {
|
||||
if (ua.includes('MicroMessenger')) {
|
||||
router.push({ path: `/checkout/wechat/${orderNo}`, replace: true })
|
||||
}
|
||||
else if (ua.includes('Alipay')) {
|
||||
router.push({ path: `/checkout/alipay/${orderNo}`, replace: true })
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* 发起支付
|
||||
*/
|
||||
function pay(){
|
||||
|
||||
}
|
||||
</script>
|
||||
|
||||
<style scoped lang="less">
|
||||
|
@@ -6,13 +6,14 @@
|
||||
</div>
|
||||
<div class="amount-display">
|
||||
<p style="font-size: 20px">
|
||||
付款金额
|
||||
订单
|
||||
</p>
|
||||
<p style="font-size: 32px;">
|
||||
¥ {{ aggregateInfo.order.amount || 0.00 }}
|
||||
</p>
|
||||
</div>
|
||||
</div>
|
||||
<van-submit-bar :price="aggregateInfo.order.amount || 0.00" button-text="支付" @submit="pay" />
|
||||
</div>
|
||||
</template>
|
||||
|
||||
@@ -20,14 +21,16 @@
|
||||
import { onMounted, ref } from 'vue'
|
||||
import { useRoute } from 'vue-router'
|
||||
|
||||
import { AggregateEnum } from '@/enums/daxpay/DaxPayEnum'
|
||||
import { AggregateTypeEnum } from '@/enums/daxpay/DaxPayEnum'
|
||||
import router from '@/router'
|
||||
import {
|
||||
import type {
|
||||
AggregateOrderAndConfigResult,
|
||||
aggregatePay,
|
||||
CheckoutAggregatePayParam,
|
||||
getAggregateConfig
|
||||
} from "@/views/daxpay/checkout/CheckoutPay.api";
|
||||
} from '@/views/daxpay/checkout/CheckoutPay.api'
|
||||
import {
|
||||
aggregatePay,
|
||||
getAggregateConfig,
|
||||
} from '@/views/daxpay/checkout/CheckoutPay.api'
|
||||
|
||||
const route = useRoute()
|
||||
const { orderNo } = route.params
|
||||
@@ -36,7 +39,7 @@ const loading = ref<boolean>(false)
|
||||
const aggregateInfo = ref<AggregateOrderAndConfigResult>({
|
||||
aggregateConfig: {},
|
||||
config: {},
|
||||
order: {}
|
||||
order: {},
|
||||
})
|
||||
|
||||
onMounted(() => {
|
||||
@@ -48,7 +51,7 @@ onMounted(() => {
|
||||
*/
|
||||
async function initData() {
|
||||
// 查询订单和配置
|
||||
await getAggregateConfig(orderNo, AggregateEnum.ALI).then(({ data }) => {
|
||||
await getAggregateConfig(orderNo, AggregateTypeEnum.ALI).then(({ data }) => {
|
||||
aggregateInfo.value = data
|
||||
}).catch((res) => {
|
||||
router.push({ name: 'ErrorResult', query: { msg: res.message } })
|
||||
@@ -57,7 +60,6 @@ async function initData() {
|
||||
if (aggregateInfo.value.aggregateConfig.autoLaunch) {
|
||||
pay()
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -67,7 +69,7 @@ function pay() {
|
||||
loading.value = true
|
||||
const from = {
|
||||
orderNo: aggregateInfo.value.order.orderNo,
|
||||
aggregateType: AggregateEnum.ALI,
|
||||
aggregateType: AggregateTypeEnum.ALI,
|
||||
} as CheckoutAggregatePayParam
|
||||
aggregatePay(from)
|
||||
.then(({ data }) => {
|
||||
|
@@ -1,11 +1,145 @@
|
||||
<script setup lang="ts">
|
||||
|
||||
</script>
|
||||
|
||||
<template>
|
||||
|
||||
<div>
|
||||
<div class="container">
|
||||
<div style="font-size: 28px;margin-top: 10px;">
|
||||
{{ aggregateInfo.config.name || '微信收银台' }}
|
||||
</div>
|
||||
<div class="amount-display">
|
||||
<p style="font-size: 20px">
|
||||
付款金额
|
||||
</p>
|
||||
<p style="font-size: 32px;">
|
||||
¥ {{ aggregateInfo.order.amount || 0.00 }}
|
||||
</p>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</template>
|
||||
|
||||
<script setup lang="ts">
|
||||
import { onMounted, ref } from 'vue'
|
||||
import { useRoute } from 'vue-router'
|
||||
|
||||
import { AggregateTypeEnum } from '@/enums/daxpay/DaxPayEnum'
|
||||
import router from '@/router'
|
||||
import type {
|
||||
AggregateOrderAndConfigResult,
|
||||
CheckoutAuthCodeParam,
|
||||
CheckoutPayParam,
|
||||
} from '@/views/daxpay/checkout/CheckoutPay.api'
|
||||
import { auth, checkoutPay, generateAuthUrl, getAggregateConfig } from '@/views/daxpay/checkout/CheckoutPay.api'
|
||||
|
||||
import type { WxJsapiSignResult } from '@/views/daxpay/cashier/CashierCode.api'
|
||||
|
||||
const route = useRoute()
|
||||
const { orderNo } = route.params
|
||||
const { code: authCode } = route.query
|
||||
|
||||
const show = ref<boolean>(false)
|
||||
const loading = ref<boolean>(false)
|
||||
|
||||
const openId = ref<string>('')
|
||||
|
||||
// 认证参数
|
||||
const authParam = ref<CheckoutAuthCodeParam>({
|
||||
aggregateType: AggregateTypeEnum.WECHAT,
|
||||
})
|
||||
|
||||
const aggregateInfo = ref<AggregateOrderAndConfigResult>({
|
||||
aggregateConfig: {},
|
||||
config: {},
|
||||
order: {},
|
||||
})
|
||||
|
||||
onMounted(() => {
|
||||
init()
|
||||
})
|
||||
|
||||
/**
|
||||
* 进入页面的初始化
|
||||
*/
|
||||
function init() {
|
||||
// 如果不是重定向跳转过来, 跳转到到重定向授权地址
|
||||
if (!authCode) {
|
||||
// 重定向跳转到微信授权地址
|
||||
generateAuthUrl({ orderNo: orderNo as string, aggregateType: AggregateTypeEnum.WECHAT }).then((res) => {
|
||||
const url = res.data
|
||||
location.replace(url)
|
||||
}).catch((res) => {
|
||||
router.push({ name: 'ErrorResult', query: { msg: res.message } })
|
||||
})
|
||||
}
|
||||
else {
|
||||
authParam.value.authCode = authCode as string
|
||||
// 初始化数据
|
||||
initData()
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* 初始化数据
|
||||
*/
|
||||
async function initData() {
|
||||
show.value = true
|
||||
// 获取聚合配置
|
||||
getAggregateConfig(orderNo, AggregateTypeEnum.WECHAT).then(({ data }) => {
|
||||
aggregateInfo.value = data
|
||||
}).catch((res) => {
|
||||
router.push({ name: 'ErrorResult', query: { msg: res.message } })
|
||||
})
|
||||
|
||||
// 认证获取OpenId
|
||||
await auth(authParam.value).then(({ data }) => {
|
||||
openId.value = data.openId as string
|
||||
}).catch((res) => {
|
||||
router.push({ name: 'ErrorResult', query: { msg: res.message } })
|
||||
})
|
||||
// 判断是否自动拉起支付
|
||||
if (aggregateInfo.value.aggregateConfig.autoLaunch) {
|
||||
pay()
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* 微信jsapi方式支付
|
||||
*/
|
||||
function pay() {
|
||||
loading.value = true
|
||||
const from = {
|
||||
orderNo: orderNo as string,
|
||||
openId: openId.value,
|
||||
} as CheckoutPayParam
|
||||
checkoutPay(from)
|
||||
.then(({ data }) => {
|
||||
loading.value = false
|
||||
// 拉起jsapi支付
|
||||
const json = JSON.parse(data.payBody)
|
||||
jsapiPay(json)
|
||||
})
|
||||
}
|
||||
|
||||
/**
|
||||
* 拉起Jsapi支付窗口
|
||||
*/
|
||||
function jsapiPay(data: WxJsapiSignResult) {
|
||||
const form = {
|
||||
appId: data.appId, // 公众号ID,由商户传入
|
||||
timeStamp: data.timeStamp, // 时间戳,自1970年以来的秒数
|
||||
nonceStr: data.nonceStr, // 随机串
|
||||
package: data.package, // 预支付ID
|
||||
signType: data.signType, // 微信签名方式:
|
||||
paySign: data.paySign, // 微信签名
|
||||
}
|
||||
// 使用微信JsSdk拉起支付
|
||||
WeixinJSBridge.invoke('getBrandWCPayRequest', form, (res) => {
|
||||
if (res.err_msg === 'get_brand_wcpay_request:ok') {
|
||||
// 跳转到成功页面
|
||||
router.push({ name: 'SuccessResult', query: { msg: '支付成功' }, replace: true })
|
||||
}
|
||||
})
|
||||
}
|
||||
</script>
|
||||
|
||||
<style scoped lang="less">
|
||||
|
||||
</style>
|
||||
|
Reference in New Issue
Block a user