新增企业微信登录

This commit is contained in:
dzq 2025-04-02 09:33:47 +08:00
parent 7835ed46af
commit 9e15542d82
9 changed files with 165 additions and 57 deletions

View File

@ -29,8 +29,9 @@ onMounted(() => {
console.log('urlParams', urlParams);
const code = urlParams.get('code') || undefined;
const state = urlParams.get('state') || undefined;
const corpid = urlParams.get('corpid') || undefined;
if (code || state) {
wxStore.handleWxCallback({ code, state })
wxStore.handleWxCallback({ corpid, code, state })
}
})
</script>

View File

@ -1,8 +1,9 @@
import { request } from "@/http/axios"
import { GetOrdersByOpenIdDTO, ShopGoodsResponseData, SubmitOrderRequestData, SubmitOrderResponseData } from './type'
import { GetBalanceResponse, GetOrdersByOpenIdDTO, QyLoginDTO, QyLoginRequestParams, ShopGoodsResponseData, SubmitOrderRequestData, SubmitOrderResponseData } from './type'
import { GetOpenIdRequestParams } from './type'
/** 获取当前登录用户详情 */
export function getShopGoodsApi() {
return request<ShopGoodsResponseData>({
@ -28,6 +29,14 @@ export function getOpenIdApi(params: GetOpenIdRequestParams) {
params
})
}
/** 企业微信登录 */
export function qyLogin(params: QyLoginRequestParams) {
return request<ApiResponseData<QyLoginDTO>>({
url: "common/login/qy",
method: "get",
params
})
}
/** 根据openid获取用户订单信息 */
export function getOrdersByOpenIdApi(openid: string) {
@ -44,3 +53,19 @@ export function openCabinetApi(orderId: number, orderGoodsId: number) {
method: "post"
})
}
/** 获取用户余额接口 */
export function getBalanceApi(openid: string) {
return request<ApiResponseData<GetBalanceResponse>>({
url: "payment/getBalance",
method: "get",
params: { openid }
})
}
export function getBalanceByQyUserid(corpid: string, userid: string) {
return request<ApiResponseData<GetBalanceResponse>>({
url: "payment/getBalanceByQyUserid",
method: "get",
params: { corpid, userid }
})
}

View File

@ -16,7 +16,10 @@ export type category = {
}
export interface SubmitOrderRequestData {
openid: string
openid: string;
userid: string;
corpid: string;
paymentType: 'wechat' | 'balance';
goodsList: Array<{
goodsId: number
quantity: number
@ -26,6 +29,7 @@ export interface SubmitOrderRequestData {
export type SubmitOrderResponseData = ApiResponseMsgData<{
orderId: number
totalAmount: number
newBalance: number
paymentInfo: WxJsApiPreCreateResponse
}>
@ -46,6 +50,11 @@ export interface WxJsApiPreCreateResponse {
export interface GetOpenIdRequestParams {
code: string
}
export interface QyLoginRequestParams {
corpid: string
code: string
state?: string
}
export interface ShopOrderEntity {
orderId: number
@ -72,3 +81,15 @@ export interface GetOrdersByOpenIdDTO {
orderGoods: ShopOrderGoodsEntity[]
goods: Goods[]
}
export interface GetBalanceResponse {
userid: string
corpid: string
balance: number
}
export interface QyLoginDTO {
userid: string
openid: string
isCabinetAdmin: number
}

View File

@ -1,6 +1,11 @@
<script setup lang="ts">
import { useRouter } from 'vue-router'
import { useWxStore } from '@/pinia/stores/wx'
import { computed } from 'vue'
const router = useRouter()
const wxStore = useWxStore()
const balance = computed(() => wxStore.balance)
</script>
<template>
@ -31,10 +36,10 @@ const router = useRouter()
<van-grid :column-num="4" :gutter="12" class="func-buttons un-mt-20px">
<van-grid-item
v-for="(item, index) in [
{ icon: 'idcard', text: '身份证', color: 'linear-gradient(to right, #ff6034, #ee0a24)' },
{ icon: 'phone-o', text: '手机号', color: 'linear-gradient(to right, #3f87ff, #1989fa)' },
{ icon: 'wechat', text: '微信', color: 'linear-gradient(to right, #07c160, #4b0)' },
{ icon: 'card', text: '银行卡', color: 'linear-gradient(to right, #ffd700, #ffb300)' }
{ icon: 'idcard', text: '身份证', color: 'transparent' },
{ icon: 'phone-o', text: '手机号', color: 'transparent' },
{ icon: 'wechat', text: '微信', color: 'transparent' },
{ icon: 'card', text: '银行卡', color: 'transparent' }
]"
:key="index"
>
@ -51,7 +56,7 @@ const router = useRouter()
<!-- 余额区域 -->
<van-cell
title="账户余额"
:value="`¥${0}`"
:value="`¥${balance}`"
class="un-mt-16px! un-rounded-8px!"
title-class="un-text-14px! un-color-hex-333!"
value-class="un-text-16px! un-fw-600! un-color-primary!"

View File

@ -101,6 +101,7 @@ watch(() => orderId.value, async (newVal) => {
type="default"
block
class="detail-button"
@click="router.push('/order/' + orderId)"
>
查看订单详情
</van-button>

View File

@ -67,7 +67,7 @@ const throttledUpdate = throttle(() => {
break
}
}
activeCategory.value = activeIndex
// activeCategory.value = activeIndex
}, 100)
//
@ -134,9 +134,6 @@ function handleCheckout() {
<!-- 右侧商品列表 -->
<div ref="scrollContainer" class="product-list">
<div :ref="el => categoryRefs[0] = el as HTMLElement" class="category-section">
<h3 class="category-title">
{{ labels[activeCategory].name }}
</h3>
<van-cell v-for="product in currentProducts" :key="product.id" class="product-item">
<template #icon>
<van-image :src="product.image" width="80" height="80" @click.stop="showProductDetail(product.id)"

View File

@ -13,8 +13,9 @@ const cartStore = useCartStore()
const { cartItems, totalPrice } = storeToRefs(cartStore)
const wxStore = useWxStore()
const { openid } = storeToRefs(wxStore)
const { openid, balance } = storeToRefs(wxStore)
const selectedPayment = ref<'wechat' | 'balance'>('wechat')
const contact = ref("")
const remark = ref("")
const submitting = ref(false)
@ -67,44 +68,48 @@ async function handleSubmit() {
})
}
//
submitting.value = true
try {
//
const requestData: SubmitOrderRequestData = {
openid: openid.value, // openid
openid: openid.value,
userid: wxStore.userid,
corpid: wxStore.corpid,
goodsList: cartItems.value.map(item => ({
goodsId: item.product.id,
quantity: item.quantity
}))
})),
paymentType: selectedPayment.value
}
//
const { data } = await submitOrderApi(requestData)
const { code, data } = await submitOrderApi(requestData)
// await showConfirmDialog({
// title: "",
// message: `${data.orderId}...`
// })
if (code !== 0) {
throw new Error("订单提交失败")
}
//
if (selectedPayment.value === 'wechat') {
if (data.paymentInfo) {
await callWxJsApi(data.paymentInfo);
//
}
} else {
//
wxStore.setBalance(data.newBalance || 0);
try {
await showConfirmDialog({
title: "支付成功",
message: `余额支付成功,剩余余额:¥${data.newBalance?.toFixed(2)}`
})
} catch (error) {
}
}
router.push({
path: '/order-success',
query: {
orderId: data.orderId
}
query: { orderId: data.orderId }
});
} else {
throw new Error('无法获取支付信息');
}
//
cartStore.clearCart()
// paymentInfo
// JSAPI
} catch (error) {
if (error !== 'user_cancel') {
showConfirmDialog({
@ -146,13 +151,21 @@ async function handleSubmit() {
</van-cell>
</van-cell-group>
<!-- 联系方式与备注 -->
<van-cell-group class="contact-form">
<!-- <van-field v-model="contact" label="联系方式" placeholder="请输入手机号" :rules="[
{ required: true, message: '请填写联系方式' },
{ pattern: /^1[3-9]\d{9}$/, message: '手机号格式不正确' },
]" />
<van-field v-model="remark" label="备注" type="textarea" placeholder="选填,可备注特殊需求" rows="2" autosize /> -->
<van-field label="支付方式" :model-value="selectedPayment" readonly>
<template #input>
<van-radio-group v-model="selectedPayment" direction="horizontal">
<van-radio name="wechat">
<van-icon name="wechat" class="method-icon" />
微信支付
</van-radio>
<van-radio name="balance" :disabled="balance < totalPrice">
<van-icon name="balance-o" class="method-icon" />
余额支付当前¥{{ balance.toFixed(2) }}
</van-radio>
</van-radio-group>
</template>
</van-field>
</van-cell-group>
<!-- 提交订单栏 -->

View File

@ -1,5 +1,5 @@
import { pinia } from "@/pinia"
import { getOpenIdApi } from "@/common/apis/shop"
import { getOpenIdApi, getBalanceApi, qyLogin, getBalanceByQyUserid } from "@/common/apis/shop"
export const useWxStore = defineStore("wx", () => {
@ -9,34 +9,76 @@ export const useWxStore = defineStore("wx", () => {
const state = ref<string>("")
// 用户 openid
const openid = ref<string>("")
// 用户 userid
const userid = ref<string>("");
// 用户余额
const balance = ref<number>(0);
// 企业id
const corpid = ref<string>("");
// 是否是柜子管理员
const isCabinetAdmin = ref<boolean>(false);
// 设置 openid
const setOpenid = (id: string) => {
openid.value = id
}
const handleWxCallback = async (params: { code?: string; state?: string }) => {
const setBalance = (amount: number) => {
balance.value = amount;
}
const handleWxCallback = async (params: { corpid?: string; code?: string; state?: string }) => {
console.log('handleWxCallback:', params)
if (params.code) {
code.value = params.code
state.value = params.state || state.value
corpid.value = params.corpid || corpid.value
try {
if (!corpid.value) {
// 调用获取 openid 的接口
const res = await getOpenIdApi({ code: params.code })
console.log('获取 openid 成功:', res)
const res = await getOpenIdApi({ code: params.code });
if (res && res.code == 0) {
openid.value = res.data
}
} else {
// 企业微信登录
const res = await qyLogin({ corpid: corpid.value, code: params.code, state: params.state})
if (res && res.code == 0) {
userid.value = res.data.userid;
openid.value = res.data.openid;
isCabinetAdmin.value = res.data.isCabinetAdmin === 1;
}
}
if (openid.value) {
// 获取用户余额
let balanceRes = null;
if(corpid.value) {
balanceRes = await getBalanceByQyUserid(corpid.value, userid.value);
} else {
balanceRes = await getBalanceApi(openid.value)
}
console.log('获取余额成功:', balanceRes)
if (balanceRes && balanceRes.code == 0) {
balance.value = balanceRes.data.balance
if (!userid.value) {
userid.value = balanceRes.data.userid;
}
if (!corpid.value) {
corpid.value = balanceRes.data.corpid;
}
}
}
} catch (err) {
console.error('获取 openid 失败:', err)
}
}
}
(window as any).testWxSetOpenid = setOpenid
return { code, state, openid, setOpenid, handleWxCallback }
return { code, state, openid, corpid, userid, balance, setOpenid, setBalance, handleWxCallback }
})
/**

View File

@ -16,12 +16,15 @@ declare module 'vue' {
VanCellGroup: typeof import('vant/es')['CellGroup']
VanConfigProvider: typeof import('vant/es')['ConfigProvider']
VanDivider: typeof import('vant/es')['Divider']
VanField: typeof import('vant/es')['Field']
VanGrid: typeof import('vant/es')['Grid']
VanGridItem: typeof import('vant/es')['GridItem']
VanIcon: typeof import('vant/es')['Icon']
VanImage: typeof import('vant/es')['Image']
VanLoading: typeof import('vant/es')['Loading']
VanNavBar: typeof import('vant/es')['NavBar']
VanRadio: typeof import('vant/es')['Radio']
VanRadioGroup: typeof import('vant/es')['RadioGroup']
VanSidebar: typeof import('vant/es')['Sidebar']
VanSidebarItem: typeof import('vant/es')['SidebarItem']
VanTabbar: typeof import('vant/es')['Tabbar']