邮储奶茶积分支付对接

This commit is contained in:
xiaogang 2024-10-29 10:02:45 +08:00
parent fd7f59740f
commit c656192050
13 changed files with 241 additions and 156 deletions

View File

@ -1,4 +1,5 @@
# 兴业优酷 # 兴业优酷
# VITE_BASE_URL = 'http://192.168.110.50:8083' # VITE_BASE_URL = 'http://192.168.110.50:8083'
# 邮储奶茶活动 # 邮储奶茶活动
VITE_BASE_URL = 'http://milk.api.test.86698.cn' # VITE_BASE_URL = 'http://milk.api.test.86698.cn'
VITE_BASE_URL = 'http://milk.test.api.cdlsxd.cn'

View File

@ -2,8 +2,9 @@
# VITE_BASE_URL = 'http://192.168.110.50:8083' # VITE_BASE_URL = 'http://192.168.110.50:8083'
# 邮储奶茶活动(测试环境) # 邮储奶茶活动(测试环境)
# VITE_BASE_URL = 'http://milk.api.test.86698.cn' VITE_BASE_URL = 'http://milk.test.api.cdlsxd.cn'
# VITE_YCNC_MERCH_CODE = '100610100019029' # VITE_YCNC_MERCH_CODE = '100310100018908'
VITE_YCNC_MERCH_CODE = '100610100019042'
# 邮储奶茶活动(正式环境) # 邮储奶茶活动(正式环境)
VITE_BASE_URL = 'https://milk.api.cdlsxd.cn' # VITE_BASE_URL = 'https://milk.api.cdlsxd.cn'
VITE_YCNC_MERCH_CODE = '100510102294138' # VITE_YCNC_MERCH_CODE = '100510102303326'

View File

@ -51,3 +51,10 @@ export const refundOrder = (params) => http({
}) })
//查询订单状态,主要针对短连接
export const queryOrderState = (params) => http({
url:'/api/v1/auth/order/state',
method:'POST',
...params
})

View File

@ -1,5 +1,5 @@
<template> <template>
<scroll-view scroll-y class="pro-container box-border" :style="{backgroundImage: 'url('+config[brandName].src+')',height:`${config[brandName].height}rpx`}"> <scroll-view scroll-y class="pro-container box-border" :style="{backgroundImage: 'url('+config[brandName]?.src+')',height:`${config[brandName].height}rpx`}">
<view class="pro-wrapper flex flex-wrap"> <view class="pro-wrapper flex flex-wrap">
<view v-for="(item,index) in products" :key="index" class="product-container"> <view v-for="(item,index) in products" :key="index" class="product-container">
<ProductItem :detail="item" :index="index"/> <ProductItem :detail="item" :index="index"/>

View File

@ -26,7 +26,7 @@
<view class="btns flex flex-justify-end"> <view class="btns flex flex-justify-end">
<view class="btn del" @click="goDel">删除订单</view> <view class="btn del" @click="goDel">删除订单</view>
<view class="btn pay" v-if="[1].includes(detail.state)" @click="goPay">立即付款</view> <view class="btn pay" v-if="[1].includes(detail.state)" @click="goPay">立即付款</view>
<view class="btn view" v-if="[3].includes(detail.state) && !!detail.voucher_link" @click="goPwd">查看卡</view> <view class="btn view" v-if="[3].includes(detail.state) && !!detail.voucher_link" @click="goPwd">查看卡</view>
<view class="btn pay" @click="goRefund" v-if="[4].includes(detail.state)">申请退款</view> <view class="btn pay" @click="goRefund" v-if="[4].includes(detail.state)">申请退款</view>
</view> </view>
</view> </view>

View File

@ -2,7 +2,7 @@
<view class="pro-item-wrapper flex flex-col box-border flex-justify-between" @click="toDetail"> <view class="pro-item-wrapper flex flex-col box-border flex-justify-between" @click="toDetail">
<view class="img-container"> <view class="img-container">
<image <image
:src="detail.voucherIcon" :src="detail?.voucherIcon"
mode="scaleToFill" mode="scaleToFill"
class="img" class="img"
/> />

View File

@ -22,7 +22,7 @@ const config = {
height:584, height:584,
}, },
"CoCo":{ "CoCo":{
name:'COCO', name:'CoCo',
src:CoCo, src:CoCo,
height:584, height:584,
}, },

View File

@ -82,9 +82,9 @@
product_id:unref(id) product_id:unref(id)
} }
goPay({params}).then(res => { goPay({params}).then(res => {
const {order_no,notify_url} = res; const {order_no,notify_url,sign,plain_text} = res;
const {payFunc} = usePay(); const {payFunc} = usePay();
payFunc({order_no,notify_url,TranAmt:detailObj.price}) payFunc({order_no,notify_url,TranAmt:detailObj.price,MerName:detailObj.brand,sign,plain_text})
}).catch(err => { }).catch(err => {
console.log(err); console.log(err);
}) })

View File

@ -1,5 +1,5 @@
import dayjs from "dayjs"; import dayjs from "dayjs";
import md5 from 'js-md5';
const handleParams = (obj) => Object.entries(obj).reduce((total,curr) => { const handleParams = (obj) => Object.entries(obj).reduce((total,curr) => {
if(!total){ if(!total){
total += `${curr[0]}=${curr[1]}` total += `${curr[0]}=${curr[1]}`
@ -12,20 +12,29 @@ const handleParams = (obj) => Object.entries(obj).reduce((total,curr) => {
export default function usePay(){ export default function usePay(){
const payFunc = (args) => { const payFunc = (args) => {
const {order_no,notify_url,TranAmt} = args; const {order_no,notify_url,TranAmt,MerName,sign,plain_text} = args;
const MercCode = import.meta.env.VITE_YCNC_MERCH_CODE
const tranAmt = Number(TranAmt).toFixed(2)
// const plainText = handleParams({MercCode,TranAmt:tranAmt,TermSsn:order_no})
const Plain = { const Plain = {
MercUrl:notify_url, MercUrl:notify_url,
TranAmt:Number(TranAmt).toFixed(2), TranAmt:tranAmt,
TermSsn:order_no, TermSsn:order_no,
BackLink:encodeURIComponent(`${window.location.origin}/#/pages/ycnc/orderDetail?order_no=${order_no}`), BackLink:encodeURIComponent(`${window.location.origin}/#/pages/ycnc/orderDetail?order_no=${order_no}&isPayBack=true`),
psbcmcc:'LSXD', psbcmcc:'LSXD',
TxnDt:dayjs(Date.now()).format('YYYY-MM-DD'), TxnDt:dayjs(Date.now()).format('YYYY-MM-DD'),
MercCode:import.meta.env.VITE_YCNC_MERCH_CODE MercCode:MercCode,
IsIntegral:'1',
MerName:MerName,
} }
const params = { const params = {
Plain:handleParams(Plain), Plain:handleParams(Plain),
plainText:plain_text,
sign:sign,
Signature: '',
} }
console.log('handCodePay-params',Plain); console.log('handCodePay-plain',Plain);
console.log('handCodePay-params',params);
Fw.device.api.handCodePay(params); Fw.device.api.handCodePay(params);
} }
return {payFunc} return {payFunc}

View File

@ -27,7 +27,7 @@
// import { getQueryString , isIOS, isAndroid } from '../../utils/utils'; // import { getQueryString , isIOS, isAndroid } from '../../utils/utils';
import useCode from './hooks/useCode'; import useCode from './hooks/useCode';
import usePay from './hooks/usePay'; import usePay from './hooks/usePay';
import config from './config';
const productList = ref([]); const productList = ref([]);
const authCode = ref(''); const authCode = ref('');
@ -43,15 +43,15 @@
} }
const pay = (productData) => { const pay = (productData) => {
const {ProductId,voucherAmount} = productData const {ProductId,voucherAmount,brandFlag} = productData
console.log('商品数据',productData); console.log('商品数据',productData);
const params = { const params = {
product_id:ProductId product_id:ProductId
} }
goPay({params}).then(res => { goPay({params}).then(res => {
const {order_no,notify_url} = res; const {order_no,notify_url,sign,plain_text} = res;
const {payFunc} = usePay(); const {payFunc} = usePay();
payFunc({order_no,notify_url,TranAmt:voucherAmount}) payFunc({order_no,notify_url,TranAmt:voucherAmount,MerName:config[brandFlag].name,sign,plain_text})
}).catch(err => { }).catch(err => {
console.log(err); console.log(err);
}) })

View File

@ -119,9 +119,9 @@
function pay(orderData){ function pay(orderData){
console.log(orderData); console.log(orderData);
const {order_no,notify_url,price} = orderData; const {order_no,notify_url,price,brand,sign,plain_text} = orderData;
const {payFunc} = usePay(); const {payFunc} = usePay();
payFunc({order_no,notify_url,TranAmt:price}) payFunc({order_no,notify_url,TranAmt:price,MerName:brand,sign,plain_text})
} }
function viewDetail(orderData){ function viewDetail(orderData){

View File

@ -9,15 +9,12 @@
</route> </route>
<template> <template>
<view class="w-full h-full flex flex-col flex-items-center page"> <view class="w-full h-full flex flex-col flex-items-center page">
<view class="wrapper"> <view class="wrapper" v-if="pageType === 1">
<view class="pro-info"> <view class="pro-info">
<view class="title">订单详情</view> <view class="title">订单详情</view>
<view class="content flex"> <view class="content flex">
<image <image class="pro-img" :src="orderDetail.main_image" />
class="pro-img"
:src="orderDetail.main_image"
/>
<view class="flex flex-1 flex-col"> <view class="flex flex-1 flex-col">
<view class="flex flex-justify-between name" style="margin-bottom:12rpx"> <view class="flex flex-justify-between name" style="margin-bottom:12rpx">
<view class="text-over">{{ orderDetail.product_name }}</view> <view class="text-over">{{ orderDetail.product_name }}</view>
@ -32,174 +29,242 @@
</view> </view>
<view class="order-info"> <view class="order-info">
<view class="info-item">订单编号{{ orderDetail.order_no }}</view> <view class="info-item">订单编号{{ orderDetail.order_no }}</view>
<view class="info-item" v-if="!!orderDetail.exchange_time && ![9].includes(orderDetail.state)">支付时间{{ orderDetail.exchange_time }}</view> <view class="info-item" v-if="!!orderDetail.exchange_time && ![9].includes(orderDetail.state)">支付时间{{
orderDetail.exchange_time }}</view>
<view class="info-item">下单时间{{ orderDetail.create_time }}</view> <view class="info-item">下单时间{{ orderDetail.create_time }}</view>
<view class="info-item" style="margin-bottom: 24rpx;">订单金额{{ orderDetail.price }}</view> <view class="info-item" style="margin-bottom: 24rpx;">订单金额{{ orderDetail.price }}</view>
</view> </view>
</view> </view>
<view class="btns"> <view class="btns" v-if="pageType === 1">
<view class="btn pwd" @click="viewPwd(orderDetail)" v-if="[3].includes(orderDetail.state) && !!orderDetail.voucher_link">查看卡密</view> <view class="btn pwd" @click="viewPwd(orderDetail)"
v-if="[3].includes(orderDetail.state) && orderDetail.voucher_link">查看卡券</view>
<view class="btn pwd" @click="pay(orderDetail)" v-if="[1].includes(orderDetail.state)">立即付款</view> <view class="btn pwd" @click="pay(orderDetail)" v-if="[1].includes(orderDetail.state)">立即付款</view>
<view class="btn pwd" v-if="[4].includes(orderDetail.state)" @click="goRefund">申请退款</view> <view class="btn pwd" v-if="[4].includes(orderDetail.state)" @click="goRefund">申请退款</view>
<view class="btn back" @click="backIndex">返回首页</view> <view class="btn back" @click="backIndex">返回首页</view>
</view> </view>
</view> </view>
</template> </template>
<script setup> <script setup>
import { onShow } from '@dcloudio/uni-app'; import { onShow, onHide, onUnload } from '@dcloudio/uni-app';
import { onMounted, reactive, ref, unref } from 'vue'; import { onMounted, reactive, ref, unref } from 'vue';
import { queryOrderDetail,refundOrder} from '../../api/ycnc'; import { queryOrderDetail, refundOrder, queryOrderState } from '../../api/ycnc';
import {getQueryString} from '../../utils/utils' import { getQueryString } from '../../utils/utils'
import usePay from './hooks/usePay'; import usePay from './hooks/usePay';
const id = ref(''); const id = ref('');
const orderNo = ref(''); const orderNo = ref('');
const orderDetail = reactive({}); const orderDetail = reactive({});
const pageType = ref(0)
let timer = undefined
// onshow h5 // onshow h5
onShow(()=>{ onShow(() => {
const url = window.location.href const url = window.location.href
console.log('url-->',url); console.log('url-->', url);
const order_id = getQueryString('order_id') const order_id = getQueryString('order_id')
const order_no = getQueryString('order_no') const order_no = getQueryString('order_no')
console.log(order_id,order_no); const isPayBack = getQueryString('isPayBack')
if(!order_id && !order_no) return console.log(order_id, order_no);
console.log('isPayBack', isPayBack);
if (!order_id && !order_no) return
id.value = order_id id.value = order_id
orderNo.value = order_no; orderNo.value = order_no;
if (isPayBack) {
queryEvent()
} else {
getDetail(); getDetail();
})
const backIndex = () => {
uni.navigateTo({
url:`/pages/ycnc/index`
})
} }
})
const viewPwd = (detailData) => { onHide(() => {
const {voucher_link} = detailData timer && clearInterval(timer)
})
onUnload(() => {
timer && clearInterval(timer)
})
const backIndex = () => {
uni.navigateTo({
url: `/pages/ycnc/index`
})
}
const timerEvent = () => {
timer && clearInterval(timer)
uni.showLoading({
title: "加载中",
mask: true,
});
timer = setInterval(()=>{
queryEvent()
}, 2500)
}
const queryEvent = () => {
uni.hideLoading()
const params = {
order_id: unref(id),
order_no: unref(orderNo)
}
queryOrderState({ params }).then(res => {
const { state, voucher_link } = res
if([3].includes(state)){
if(voucher_link){ if(voucher_link){
timer && clearInterval(timer)
window.location.replace(voucher_link)
}else{
timerEvent()
}
}else if([1,2].includes(state)){
timerEvent()
}else{
timer && clearInterval(timer)
getDetail()
}
})
}
const viewPwd = (detailData) => {
const { voucher_link } = detailData
if (voucher_link) {
console.log(`跳转外部链接-->${voucher_link}`); console.log(`跳转外部链接-->${voucher_link}`);
window.location.href = voucher_link window.location.href = voucher_link
}else{ } else {
console.error(`voucher_link无有效值`); console.error(`voucher_link无有效值`);
} }
} }
const goRefund = () => { const goRefund = () => {
const {id} = orderDetail const { id } = orderDetail
if(!id){ if (!id) {
uni.showToast({ uni.showToast({
icon:'none', icon: 'none',
title: '无有效的订单id', title: '无有效的订单id',
}); });
return return
} }
const params = {order_id:id} const params = { order_id: id }
refundOrder({params}).then(res => { refundOrder({ params }).then(res => {
uni.showToast({ uni.showToast({
icon:'success', icon: 'success',
title: '退款成功', title: '退款成功',
}); });
}).catch(err => { }).catch(err => {
console.log(err); console.log(err);
}) })
} }
function pay(orderData){ function pay(orderData) {
console.log(orderData); console.log(orderData);
const {order_no,notify_url,price} = orderData; const { order_no, notify_url, price,brand,sign,plain_text } = orderData;
const {payFunc} = usePay(); const { payFunc } = usePay();
payFunc({order_no,notify_url,TranAmt:price}) payFunc({ order_no, notify_url, TranAmt: price,MerName:brand,sign,plain_text })
} }
onMounted(() => { onMounted(() => {
// getDetail() // getDetail()
}) })
const getDetail = () => { const getDetail = () => {
const params = { const params = {
order_id:unref(id), order_id: unref(id),
order_no:unref(orderNo) order_no: unref(orderNo)
} }
queryOrderDetail({params}).then(res => { pageType.value = 1
Object.assign(orderDetail,res) queryOrderDetail({ params }).then(res => {
Object.assign(orderDetail, res)
}) })
} }
</script> </script>
<style lang="scss" scoped> <style lang="scss" scoped>
.page{ .page {
background-color: #fafafa; background-color: #fafafa;
} }
.wrapper{
.wrapper {
width: 702rpx; width: 702rpx;
height: 486rpx; height: 486rpx;
background: #FFFFFF; background: #FFFFFF;
border-radius: 24rpx; border-radius: 24rpx;
margin-top:24rpx; margin-top: 24rpx;
box-sizing: border-box; box-sizing: border-box;
padding:32rpx 24rpx; padding: 32rpx 24rpx;
.pro-info{
.pro-info {
border-bottom: 1rpx solid #F0E1E1; border-bottom: 1rpx solid #F0E1E1;
.title{
.title {
font-weight: 500; font-weight: 500;
font-size: 28rpx; font-size: 28rpx;
color: #333333; color: #333333;
margin-bottom: 28rpx; margin-bottom: 28rpx;
} }
.content{
margin-bottom:24rpx; .content {
margin-bottom: 24rpx;
font-weight: 400; font-weight: 400;
.pro-img{
.pro-img {
display: block; display: block;
width:90rpx; width: 90rpx;
height:90rpx; height: 90rpx;
margin-right:34rpx; margin-right: 34rpx;
} }
.text-over{
max-width:80%; .text-over {
max-width: 80%;
text-overflow: ellipsis; text-overflow: ellipsis;
overflow: hidden; overflow: hidden;
white-space: nowrap; white-space: nowrap;
} }
.name{
.name {
font-size: 24rpx; font-size: 24rpx;
color: #333333; color: #333333;
font-weight: 700; font-weight: 700;
} }
.amount{
.amount {
color: #333333; color: #333333;
font-weight: 400; font-weight: 400;
font-size:24rpx; font-size: 24rpx;
text:nth-child(1){ text:nth-child(1) {
font-size:20rpx; font-size: 20rpx;
} }
text:nth-child(2){
font-size:22rpx; text:nth-child(2) {
font-size: 22rpx;
} }
} }
.num{
.num {
font-weight: 400; font-weight: 400;
font-size: 24rpx; font-size: 24rpx;
color: #9E9E9E; color: #9E9E9E;
} }
} }
} }
.order-info{
.order-info {
border-bottom: 1rpx solid #F0E1E1; border-bottom: 1rpx solid #F0E1E1;
.info-item{
.info-item {
font-weight: 400; font-weight: 400;
font-size: 22rpx; font-size: 22rpx;
color: #6C6C6C; color: #6C6C6C;
margin-top:24rpx; margin-top: 24rpx;
} }
} }
} }
.btns{
margin-top:146rpx; .btns {
margin-top: 146rpx;
display: flex; display: flex;
.btn{
.btn {
width: 312rpx; width: 312rpx;
height: 76rpx; height: 76rpx;
border-radius: 38rpx; border-radius: 38rpx;
@ -208,14 +273,16 @@
align-items: center; align-items: center;
justify-content: center; justify-content: center;
} }
.pwd{
.pwd {
font-weight: 500; font-weight: 500;
font-size: 32rpx; font-size: 32rpx;
color: #FFFFFF; color: #FFFFFF;
background: #EA0000; background: #EA0000;
margin-right:10rpx; margin-right: 10rpx;
} }
.back{
.back {
font-weight: 400; font-weight: 400;
font-size: 32rpx; font-size: 32rpx;
color: #B9C8C7; color: #B9C8C7;

View File

@ -35,7 +35,7 @@ export default defineConfig(({ command, mode }) => {
}), }),
], ],
esbuild: { esbuild: {
drop: ["console", "debugger"], //打包去掉console,debugger // drop: ["console", "debugger"], //打包去掉console,debugger
}, },
} }
}) })