326 lines
6.3 KiB
Vue
326 lines
6.3 KiB
Vue
<template>
|
||
<view class="test_page">
|
||
<NavHeader leftTitle="抖音支付测试" leftPathType="navigateTo" />
|
||
<view class="test_container">
|
||
<view class="card_box">
|
||
<view class="card_title">抖音 App 原生支付联调</view>
|
||
<view class="tip_box">
|
||
<text class="tip_text">粘贴 /order/payment 返回的完整 JSON(含 data.orderNum 和 data.douyin)。使用已集成 tb-douyin-pay 的自定义基座或完整安装包。测试将使用真实订单发起支付;最终结果以服务端查单为准。</text>
|
||
</view>
|
||
<view class="form_item">
|
||
<text class="form_label">接口返回 JSON</text>
|
||
<textarea class="form_textarea" v-model="paymentJson" placeholder="粘贴接口返回 JSON;也支持直接粘贴含 orderNum、douyin 的 data 对象" />
|
||
</view>
|
||
<button class="main_pay_btn" :loading="loading" :disabled="loading" @click="handleTestPay">发起该订单支付</button>
|
||
</view>
|
||
<view class="card_box">
|
||
<view class="card_title">联调结果</view>
|
||
<text>{{ resultText }}</text>
|
||
</view>
|
||
</view>
|
||
</view>
|
||
</template>
|
||
|
||
<script>
|
||
import NavHeader from "@/components/header.vue";
|
||
import { appDypayFun } from "@/utils/douyin-pay.js";
|
||
|
||
export default {
|
||
components: { NavHeader },
|
||
data() {
|
||
return { paymentJson: "", loading: false, resultText: "尚未调用支付" };
|
||
},
|
||
methods: {
|
||
async handleTestPay() {
|
||
if (this.loading) return;
|
||
// #ifndef APP-PLUS
|
||
this.resultText = "请使用已集成原生插件的 Android/iOS App 测试";
|
||
return;
|
||
// #endif
|
||
// #ifdef APP-PLUS
|
||
this.loading = true;
|
||
try {
|
||
const response = JSON.parse(this.paymentJson);
|
||
if (response.bizcode != null && response.bizcode !== 100) throw new Error("请使用下单成功的接口返回");
|
||
const payment = response.data || response;
|
||
if (!payment.orderNum || !payment.douyin) throw new Error("缺少 orderNum 或 douyin");
|
||
this.resultText = "正在调用原生 SDK,返回后查询订单状态";
|
||
const result = await appDypayFun(payment);
|
||
const labels = { paid: "服务端确认支付成功", failed: "服务端确认支付未成功", pending: "结果待确认,请稍后查看订单", error: "调用失败" };
|
||
this.resultText = result ? (result.message || labels[result.state] || "结果待确认") : "支付正在处理中";
|
||
} catch (error) {
|
||
this.resultText = error.message || "调用失败";
|
||
} finally {
|
||
this.loading = false;
|
||
}
|
||
// #endif
|
||
},
|
||
},
|
||
};
|
||
</script>
|
||
|
||
<style lang="scss" scoped>
|
||
.test_page {
|
||
min-height: 100vh;
|
||
background-color: #F6F7FB;
|
||
padding-bottom: 60rpx;
|
||
}
|
||
|
||
.test_container {
|
||
padding: 24rpx;
|
||
}
|
||
|
||
.card_box {
|
||
background: #FFFFFF;
|
||
border-radius: 20rpx;
|
||
padding: 28rpx;
|
||
margin-bottom: 24rpx;
|
||
box-shadow: 0 4rpx 16rpx rgba(0, 0, 0, 0.04);
|
||
|
||
.card_title {
|
||
display: flex;
|
||
align-items: center;
|
||
justify-content: space-between;
|
||
margin-bottom: 20rpx;
|
||
|
||
.title_text {
|
||
font-size: 30rpx;
|
||
font-weight: 600;
|
||
color: #1F2937;
|
||
}
|
||
|
||
.tag_badge {
|
||
font-size: 22rpx;
|
||
padding: 4rpx 14rpx;
|
||
border-radius: 20rpx;
|
||
font-weight: 500;
|
||
|
||
&.badge_app {
|
||
background-color: #EDE9FE;
|
||
color: #7934F6;
|
||
}
|
||
|
||
&.badge_h5 {
|
||
background-color: #E0F2FE;
|
||
color: #0284C7;
|
||
}
|
||
}
|
||
|
||
.clear_link {
|
||
font-size: 24rpx;
|
||
color: #7934F6;
|
||
}
|
||
}
|
||
}
|
||
|
||
.info_grid {
|
||
background: #F9FAFB;
|
||
border-radius: 12rpx;
|
||
padding: 16rpx 20rpx;
|
||
|
||
.info_row {
|
||
display: flex;
|
||
justify-content: space-between;
|
||
font-size: 26rpx;
|
||
margin-bottom: 8rpx;
|
||
|
||
&:last-child {
|
||
margin-bottom: 0;
|
||
}
|
||
|
||
.info_label {
|
||
color: #6B7280;
|
||
}
|
||
|
||
.info_val {
|
||
font-weight: 500;
|
||
color: #111827;
|
||
}
|
||
}
|
||
}
|
||
|
||
.btn_row {
|
||
display: flex;
|
||
gap: 16rpx;
|
||
|
||
.mini_btn {
|
||
flex: 1;
|
||
font-size: 24rpx;
|
||
border-radius: 12rpx;
|
||
line-height: 2.2;
|
||
margin: 0;
|
||
border: none;
|
||
|
||
&.check_btn {
|
||
background: #F3F4F6;
|
||
color: #374151;
|
||
}
|
||
|
||
&.open_btn {
|
||
background: #EDE9FE;
|
||
color: #7934F6;
|
||
}
|
||
}
|
||
}
|
||
|
||
.preset_section {
|
||
margin-bottom: 20rpx;
|
||
|
||
.section_label {
|
||
font-size: 24rpx;
|
||
color: #6B7280;
|
||
display: block;
|
||
margin-bottom: 12rpx;
|
||
}
|
||
|
||
.preset_btn_group {
|
||
display: flex;
|
||
flex-wrap: wrap;
|
||
gap: 12rpx;
|
||
|
||
.preset_chip {
|
||
font-size: 24rpx;
|
||
color: #7934F6;
|
||
background: #F4EFFF;
|
||
border: 1rpx solid #E4D4FF;
|
||
border-radius: 30rpx;
|
||
padding: 8rpx 22rpx;
|
||
}
|
||
}
|
||
}
|
||
|
||
.tip_box {
|
||
background: #FFFBEB;
|
||
border: 1rpx solid #FDE68A;
|
||
border-radius: 12rpx;
|
||
padding: 16rpx 20rpx;
|
||
margin-bottom: 24rpx;
|
||
|
||
.tip_text {
|
||
font-size: 24rpx;
|
||
color: #B45309;
|
||
line-height: 1.5;
|
||
}
|
||
}
|
||
|
||
.form_item {
|
||
margin-bottom: 20rpx;
|
||
|
||
.form_label {
|
||
font-size: 26rpx;
|
||
color: #374151;
|
||
font-weight: 500;
|
||
display: block;
|
||
margin-bottom: 10rpx;
|
||
}
|
||
|
||
.form_input {
|
||
background: #F9FAFB;
|
||
border: 1rpx solid #E5E7EB;
|
||
border-radius: 12rpx;
|
||
height: 72rpx;
|
||
padding: 0 20rpx;
|
||
font-size: 26rpx;
|
||
color: #111827;
|
||
}
|
||
|
||
.form_textarea {
|
||
width: 100%;
|
||
box-sizing: border-box;
|
||
background: #F9FAFB;
|
||
border: 1rpx solid #E5E7EB;
|
||
border-radius: 12rpx;
|
||
padding: 16rpx 20rpx;
|
||
font-size: 26rpx;
|
||
color: #111827;
|
||
height: 140rpx;
|
||
}
|
||
|
||
.radio_group {
|
||
display: flex;
|
||
gap: 30rpx;
|
||
|
||
.radio_item {
|
||
display: flex;
|
||
align-items: center;
|
||
font-size: 26rpx;
|
||
color: #374151;
|
||
}
|
||
}
|
||
|
||
&.half {
|
||
flex: 1;
|
||
margin-bottom: 0;
|
||
}
|
||
}
|
||
|
||
.form_row {
|
||
display: flex;
|
||
gap: 20rpx;
|
||
}
|
||
|
||
.action_section {
|
||
margin-bottom: 24rpx;
|
||
|
||
.main_pay_btn {
|
||
background: linear-gradient(135deg, #8B5CF6 0%, #7934F6 100%);
|
||
color: #FFFFFF;
|
||
font-size: 30rpx;
|
||
font-weight: 600;
|
||
height: 88rpx;
|
||
line-height: 88rpx;
|
||
border-radius: 44rpx;
|
||
box-shadow: 0 8rpx 20rpx rgba(121, 52, 246, 0.3);
|
||
border: none;
|
||
|
||
&:active {
|
||
opacity: 0.9;
|
||
}
|
||
}
|
||
}
|
||
|
||
.log_console {
|
||
background: #1E1E2E;
|
||
border-radius: 16rpx;
|
||
padding: 20rpx;
|
||
height: 380rpx;
|
||
box-sizing: border-box;
|
||
|
||
.empty_log {
|
||
color: #6C7086;
|
||
font-size: 24rpx;
|
||
text-align: center;
|
||
padding: 60rpx 0;
|
||
}
|
||
|
||
.log_item {
|
||
font-size: 24rpx;
|
||
font-family: monospace;
|
||
line-height: 1.6;
|
||
margin-bottom: 10rpx;
|
||
word-break: break-all;
|
||
|
||
.log_time {
|
||
color: #A6ADC8;
|
||
margin-right: 12rpx;
|
||
}
|
||
|
||
&.log_info .log_content {
|
||
color: #CDD6F4;
|
||
}
|
||
|
||
&.log_success .log_content {
|
||
color: #A6E3A1;
|
||
}
|
||
|
||
&.log_warn .log_content {
|
||
color: #F9E2AF;
|
||
}
|
||
|
||
&.log_error .log_content {
|
||
color: #F38BA8;
|
||
}
|
||
}
|
||
}
|
||
</style>
|