refactor: replace direct WeChat/Alipay with unified pay-api gateway

Switch from direct WeChat Pay / Alipay integrations to the unified
宇之然 pay-api gateway (HMAC-SHA256 auth). Removes wechat_pay.py,
keeps PaymentGateway abstraction, adds UnifiedPayService. Simplifies
payment.py create_order to {plan, pay_type} params. Single webhook
endpoint replaces separate WeChat/Alipay notify handlers.
This commit is contained in:
TradeMate Dev
2026-05-29 18:36:50 +08:00
parent 5d2bced39f
commit 3e39cf0170
34 changed files with 973 additions and 424 deletions
Binary file not shown.

After

Width:  |  Height:  |  Size: 1.4 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 203 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 27 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 48 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 27 KiB

+60 -3
View File
@@ -92,14 +92,47 @@
</el-main>
<el-footer class="footer">
<span>TradeMate 外贸小助手 &copy; {{ new Date().getFullYear() }}</span>
<div class="footer-content">
<div class="footer-section">
<div class="footer-brand">TradeMate</div>
<p class="footer-tagline">AI 外贸小助手 · 让外贸更简单</p>
<div class="qrcode-row">
<div class="qrcode-item">
<img src="/images/yzr/yuzhiran.jpg" alt="微信公众号" class="qrcode-img" />
<span>微信公众号</span>
</div>
<div class="qrcode-item">
<img src="/images/yzr/yuzhiran-tech.jpg" alt="微信服务号" class="qrcode-img" />
<span>微信服务号</span>
</div>
<div class="qrcode-item">
<img src="/images/yzr/yuzhiran-yhl.jpg" alt="小程序" class="qrcode-img" />
<span>小程序</span>
</div>
<div class="qrcode-item">
<img src="/images/yzr/kefu.png" alt="客服" class="qrcode-img" />
<span>微信客服</span>
</div>
</div>
</div>
<div class="footer-bottom">
<p>&copy; {{ new Date().getFullYear() }} TradeMate 外贸小助手. 保留所有权利.</p>
<div class="footer-links">
<a href="http://beian.miit.gov.cn/" target="_blank">{{ beianInfo.icp }}</a>
<a v-if="beianInfo.showGongan" :href="beianInfo.gonganLink" target="_blank" rel="noreferrer" class="gongan-link">
<img src="/images/beian/gongan-beian.png" alt="公安备案" class="gongan-icon" />
{{ beianInfo.gongan }}
</a>
</div>
</div>
</div>
</el-footer>
</el-container>
</el-container>
</template>
<script setup>
import { ref } from 'vue'
import { ref, computed } from 'vue'
import { useRoute, useRouter } from 'vue-router'
import { useAuthStore } from '@/stores/auth'
@@ -107,6 +140,17 @@ const route = useRoute()
const router = useRouter()
const auth = useAuthStore()
const collapsed = ref(false)
const beianInfo = computed(() => {
const hostname = window.location.hostname
if (hostname === 'yuzhiran.com' || hostname === 'www.yuzhiran.com') {
return { icp: '京ICP备2026007249号-1', gongan: '京公网安备11011502039545号', gonganLink: 'https://beian.mps.gov.cn/#/query/webSearch?code=11011502039545', showGongan: true }
}
if (hostname === 'yuzhiran.com.cn' || hostname === 'www.yuzhiran.com.cn') {
return { icp: '京ICP备2026007249号-2', gongan: '京公网安备11011502039622号', gonganLink: 'https://beian.mps.gov.cn/#/query/webSearch?code=11011502039622', showGongan: true }
}
return { icp: '京ICP备2026007249号-1', gongan: '京公网安备11011502039545号', gonganLink: 'https://beian.mps.gov.cn/#/query/webSearch?code=11011502039545', showGongan: true }
})
</script>
<style scoped>
@@ -125,5 +169,18 @@ const collapsed = ref(false)
.user-info { display: flex; align-items: center; gap: 8px; cursor: pointer; }
.user-name { font-size: 14px; color: #333; }
.main-content { background: #f5f5f5; padding: 20px; overflow-y: auto; }
.footer { display: flex; align-items: center; justify-content: center; height: 48px; background: #fff; border-top: 1px solid #e8e8e8; color: #999; font-size: 12px; }
.footer { padding: 0; background: #fff; border-top: 1px solid #e8e8e8; color: #666; font-size: 12px; }
.footer-content { padding: 20px 24px 16px; }
.footer-section { margin-bottom: 16px; }
.footer-brand { font-size: 15px; font-weight: 700; color: #1890ff; margin-bottom: 4px; }
.footer-tagline { color: #999; font-size: 12px; margin-bottom: 12px; }
.qrcode-row { display: flex; gap: 16px; flex-wrap: wrap; }
.qrcode-item { display: flex; flex-direction: column; align-items: center; gap: 4px; color: #999; font-size: 11px; }
.qrcode-img { width: 48px; height: 48px; border-radius: 6px; }
.footer-bottom { border-top: 1px solid #eee; padding-top: 12px; display: flex; justify-content: center; align-items: center; gap: 16px; flex-wrap: wrap; }
.footer-links { display: flex; gap: 16px; align-items: center; }
.footer-links a { color: #999; text-decoration: none; }
.footer-links a:hover { color: #1890ff; }
.gongan-link { display: inline-flex; align-items: center; gap: 4px; }
.gongan-icon { height: 16px; vertical-align: middle; }
</style>