Browse Source

feat:提交支付项目

jhy 7 tháng trước cách đây
mục cha
commit
26652c0234
56 tập tin đã thay đổi với 4819 bổ sung442 xóa
  1. 0 1
      .env
  2. 1 1
      App.vue
  3. 1 1
      manifest.json
  4. 21 0
      pages.json
  5. 1 1
      pages/XDHome/homePage/homePage.vue
  6. 18 0
      pages/XDHome/orderInfoList/orderInfoList.vue
  7. 1 1
      pages/XDHome/technician/grabOrders/grabOrders.vue
  8. 266 241
      pages/XDHome/technician/itemList/itemList.vue
  9. 276 0
      pages/XDHome/technician/newAddress/newAddress.vue
  10. 1 1
      pages/XDHome/technician/orderGrabbingTechnician/orderGrabbingTechnician.vue
  11. 11 3
      pages/XDHome/technician/reservationPlaceOrder/reservationPlaceOrder.vue
  12. 1 1
      pages/XDHome/technician/serviceTimePage/serviceTimePage.vue
  13. 12 182
      pages/index/cart.vue
  14. 1 1
      pages/index/index.vue
  15. 1 1
      pages/index/user.vue
  16. 1 1
      pages/moban.vue
  17. 3 3
      sheep/components/s-layout/s-layout.vue
  18. 3 0
      sheep/platform/provider/wechat/officialAccount.js
  19. 2 0
      sheep/router/index.js
  20. 5 0
      sheep/scss/_tools.scss
  21. 7 3
      static/iconfont.css
  22. 1 0
      static/payDemo/MP_verify_ioJ6xLg1sgvV28Kc.txt
  23. 121 0
      static/payDemo/README.md
  24. 1193 0
      static/payDemo/cashier.html
  25. 49 0
      static/payDemo/config/index.js
  26. 88 0
      static/payDemo/css/reset.css
  27. BIN
      static/payDemo/fonts/DIN_Alternate_Bold.ttf
  28. 183 0
      static/payDemo/goodsDetail.html
  29. 48 0
      static/payDemo/http.js
  30. BIN
      static/payDemo/img/QR_img.png
  31. BIN
      static/payDemo/img/accountClose.png
  32. BIN
      static/payDemo/img/alipay.png
  33. BIN
      static/payDemo/img/bankpay.png
  34. BIN
      static/payDemo/img/close.png
  35. BIN
      static/payDemo/img/combinepay.png
  36. BIN
      static/payDemo/img/datarmbpay.png
  37. BIN
      static/payDemo/img/defaultLogo.png
  38. BIN
      static/payDemo/img/fail1.png
  39. BIN
      static/payDemo/img/fail2.png
  40. BIN
      static/payDemo/img/fail3.png
  41. BIN
      static/payDemo/img/huabeipay.png
  42. BIN
      static/payDemo/img/loading.png
  43. BIN
      static/payDemo/img/logo.png
  44. BIN
      static/payDemo/img/mouse.png
  45. BIN
      static/payDemo/img/quickpasspay.png
  46. BIN
      static/payDemo/img/success1.png
  47. BIN
      static/payDemo/img/success2.png
  48. BIN
      static/payDemo/img/success3.png
  49. BIN
      static/payDemo/img/unionpay.png
  50. BIN
      static/payDemo/img/wxpay.png
  51. 390 0
      static/payDemo/monitor.js
  52. 481 0
      static/payDemo/orderConfirm.html
  53. 638 0
      static/payDemo/pay.js
  54. 435 0
      static/payDemo/payFail.html
  55. 433 0
      static/payDemo/paySuccess.html
  56. 126 0
      static/payDemo/util.js

+ 0 - 1
.env

@@ -6,7 +6,6 @@ SHOPRO_BASE_URL = https://saas.niusenyun.com
 
 # 后端接口 - 测试环境(通过 process.env.NODE_ENV = development)
 SHOPRO_DEV_BASE_URL = https://saas.niusenyun.com
-
 # 后端接口前缀(一般不建议调整)
 SHOPRO_API_PATH = /app-api
 

+ 1 - 1
App.vue

@@ -4,7 +4,7 @@
 
   onLaunch(() => {
     // 隐藏原生导航栏 使用自定义底部导航
-    uni.hideTabBar();
+    // uni.hideTabBar();
 
     // 加载Shopro底层依赖
     ShoproInit();

+ 1 - 1
manifest.json

@@ -184,7 +184,7 @@
     "versionCode": 100
   },
   "mp-weixin": {
-    "appid": "wx66186af0759f47c9",
+    "appid": "wx5ddd341854ee3d15",
     "setting": {
       "urlCheck": false,
       "minified": true,

+ 21 - 0
pages.json

@@ -34,6 +34,19 @@
 				"group": "商城"
 			}
 		},
+		{
+			"path" : "pages/XDHome/orderInfoList/orderInfoList",
+			"style" : 
+			{
+				"navigationBarTitleText" : "订单",
+				"enablePullDownRefresh": true
+			},
+			"meta": {
+				"sync": true,
+				"title": "订单",
+				"group": "商城"
+			}
+		},
 		{
 			"path": "pages/index/category",
 			"style": {
@@ -727,6 +740,14 @@
 						"navigationBarTitleText" : "预约服务",
 						"navigationStyle": "custom"
 					}
+				},
+				{
+					"path" : "newAddress/newAddress",
+					"style" : 
+					{
+						"navigationBarTitleText" : "新增地址",
+						"navigationStyle": "custom"
+					}
 				}
 			]
 		}

+ 1 - 1
pages/XDHome/homePage/homePage.vue

@@ -305,7 +305,7 @@
 	import sheep from '@/sheep';
 	import $share from '@/sheep/platform/share';
 	// 隐藏原生tabBar
-	uni.hideTabBar();
+	// uni.hideTabBar();
 
 
 

+ 18 - 0
pages/XDHome/orderInfoList/orderInfoList.vue

@@ -0,0 +1,18 @@
+<!-- 订单列表 -->
+<template>
+	<web-view :src="url"></web-view>
+</template>
+
+<script setup>
+	import {
+		reactive,
+		ref
+	} from 'vue';
+	const price = ref(0.01)
+	const url = ref('https://massage.niusenyun.com/static/payDemo/cashier.html?price='+price.value+'&code='+localStorage.getItem('code')+'&type='+localStorage.getItem('type')+'&state='+localStorage.getItem('state'))
+	console.log(url, 'ssssssssssssssssss')
+</script>
+
+<style>
+
+</style>

+ 1 - 1
pages/XDHome/technician/grabOrders/grabOrders.vue

@@ -296,7 +296,7 @@
 	import sheep from '@/sheep';
 	import $share from '@/sheep/platform/share';
 	// 隐藏原生tabBar
-	uni.hideTabBar();
+	// uni.hideTabBar();
 	// 返回上一页
 	const backPage = async () => {
 		uni.redirectTo({

+ 266 - 241
pages/XDHome/technician/itemList/itemList.vue

@@ -1,96 +1,93 @@
 <!-- 项目列表 -->
 <template>
-	<view class="body" :style="'padding-top:'+bottomHeight">
-		<!-- 导航 -->
-		<view class="ss-flex-2 ss-col-center ss-margin-width2" style="position: relative;">
-			<view class="ss-flex-2 ss-col-center">
-				<text class="textIcon icon-fanhui icon-navigation" @click="backPage"></text>
-				<view style="margin-left: 15rpx;color:#fff;font-size:28rpx;">项目列表</view>
+	<s-layout class='homepage-wrap ss-w-100 box-sizing' title="首页" navbar="custom"
+		tabbar="/pages/XDHomePage/technician/itemList/itemList">
+		<view class="body" :style="'padding-top:'+bottomHeight">
+			<!-- 导航 -->
+			<view class="ss-flex-2 ss-col-center ss-margin-width2" style="position: relative;">
+				<view class="ss-flex-2 ss-col-center">
+					<text class="textIcon icon-fanhui icon-navigation" @click="backPage"></text>
+					<view style="margin-left: 15rpx;color:#fff;font-size:28rpx;">项目列表</view>
+				</view>
+				<view class="ss-flex-1"></view>
+				<text class="textIcon icon-kefu icon-navigation"></text>
+				<text class="textIcon icon-tongzhiguanli icon-navigation" style="margin-left: 30rpx;"></text>
 			</view>
-			<view class="ss-flex-1"></view>
-			<text class="textIcon icon-kefu icon-navigation"></text>
-			<text class="textIcon icon-tongzhiguanli icon-navigation" style="margin-left: 30rpx;"></text>
-		</view>
-		<!-- 搜索框 -->
-		<view class="ss-margin-width2" style="margin-top:1rpx;">
-			<uni-search-bar radius="30" v-model="searchInfo" placeholder="请输入搜索关键字" cancelButton="none" clearButton="none" @confirm="onSearch" ></uni-search-bar>
-		</view>
-		<!-- 选择地址 -->
-		<view class="ss-flex-2 ss-col-center public-box" style="margin-top: -15rpx;">
-			<text class="textIcon icon-ditu" style="margin-left:30rpx;color: #fff;font-size: 26rpx;"></text>
-			<uni-data-select
-				style="font-size: 22rpx;margin-left: 10rpx;"
-			    v-model="address"
-			    :localdata="range"
-				:clear="false"
-			    @change="changeAddress"
-			></uni-data-select>
-			<view class="ss-flex-1"></view>
-		</view>
-		
-		
-		
-		
-		
-		<!-- 中部 -->
-		<view class="list-wrap">
-			<scroll-view scroll-y="true" class="list">
-				<view class="list-scroll-view" v-for="item in listData">
-					<!-- 左右布局 -->
-					<view style="width:200rpx;">
-						<image class="wh" referrerpolicy="no-referrer"
-							src="/static/lanhu_shouye/pskrims113novhztuh3djro4dewm6siic9cbfccd-f457-4e94-a2a5-bf7808d1dd3f.png" />
-					</view>
-					<!-- 上下布局 -->
-					<view class="ss-flex-1" style="margin-left: 10rpx;margin-top: 5rpx;">
-						<!-- 服务大项 -->
-						<view class="ss-flex-2 ss-col-center">
-							<view>精油按摩</view>
-							<view class="ss-flex-1"></view>
-							<view class="ss-flex-2 ss-col-center ss-row-center">
-								<text class="textIcon icon-fenzhong" style="font-size: 22rpx;color:#3A4450;"></text>
-								<view style="font-size: 20rpx;color:#3A4450;margin-left: 10rpx;padding-top: 5rpx;">80分钟</view>
-							</view>
-							<view style="margin-left: 20rpx;font-size: 20rpx;color:#8F8F93;padding-top: 5rpx;">已预约11636单</view>
-						</view>
-						<!-- 服务小项 -->
-						<view class="ss-flex-2 event-wrap" style="margin-top: 5rpx;flex-wrap: wrap;">
-							<view class="ss-flex-2" v-for="i in 4">
-								<view class="event-box">舒缓疲劳{{i}}</view>
-								<view class="line-box"></view>
-							</view>
+			<!-- 搜索框 -->
+			<view class="ss-margin-width2" style="margin-top:1rpx;">
+				<uni-search-bar radius="30" v-model="searchInfo" placeholder="请输入搜索关键字" cancelButton="none"
+					clearButton="none" @confirm="onSearch"></uni-search-bar>
+			</view>
+			<!-- 选择地址 -->
+			<view class="ss-flex-2 ss-col-center public-box" style="margin-top: -15rpx;">
+				<text class="textIcon icon-ditu" style="margin-left:30rpx;color: #fff;font-size: 26rpx;"></text>
+				<uni-data-select style="font-size: 22rpx;margin-left: 10rpx;" v-model="address" :localdata="range"
+					:clear="false" @change="changeAddress"></uni-data-select>
+				<view class="ss-flex-1"></view>
+			</view>
+			<!-- 中部 -->
+			<view class="list-wrap">
+				<scroll-view scroll-y="true" class="list">
+					<view class="list-scroll-view" v-for="item in listData">
+						<!-- 左右布局 -->
+						<view style="width:200rpx;">
+							<image class="wh" referrerpolicy="no-referrer"
+								src="/static/lanhu_shouye/pskrims113novhztuh3djro4dewm6siic9cbfccd-f457-4e94-a2a5-bf7808d1dd3f.png" />
 						</view>
-						<!-- 加减 -->
-						<view class="ss-flex-2">
-							<view class="ss-flex-1"></view>
-							<!-- 手写一个加减计算器 -->
+						<!-- 上下布局 -->
+						<view class="ss-flex-1" style="margin-left: 10rpx;margin-top: 5rpx;">
+							<!-- 服务大项 -->
 							<view class="ss-flex-2 ss-col-center">
-								<view @click="minusNumber($event,item)">
-									<text class="textIcon icon-jianhao- count-icon"></text>
+								<view>精油按摩</view>
+								<view class="ss-flex-1"></view>
+								<view class="ss-flex-2 ss-col-center ss-row-center">
+									<text class="textIcon icon-fenzhong" style="font-size: 22rpx;color:#3A4450;"></text>
+									<view style="font-size: 20rpx;color:#3A4450;margin-left: 10rpx;padding-top: 5rpx;">
+										80分钟</view>
 								</view>
-								<view class="count-number">{{item.number}}</view>
-								<view @click="addNumber($event,item)">
-									<text class="textIcon icon-jiahao- count-icon" style="color: #2DAFD1;"></text>
+								<view style="margin-left: 20rpx;font-size: 20rpx;color:#8F8F93;padding-top: 5rpx;">
+									已预约11636单</view>
+							</view>
+							<!-- 服务小项 -->
+							<view class="ss-flex-2 event-wrap" style="margin-top: 5rpx;flex-wrap: wrap;">
+								<view class="ss-flex-2" v-for="i in 4">
+									<view class="event-box">舒缓疲劳{{i}}</view>
+									<view class="line-box"></view>
 								</view>
 							</view>
-						</view>
-						<!-- 价格以及预约 -->
-						<view class="ss-flex-2 ss-col-center" style="margin-top: 10rpx;">
-							<view class="ss-flex-2 ss-col-center ss-row-center">
-								<text class="textIcon icon-renminbi1688 icon-rmb"></text>
-								<view class="maney-number-box">498.00</view>
+							<!-- 加减 -->
+							<view class="ss-flex-2">
+								<view class="ss-flex-1"></view>
+								<!-- 手写一个加减计算器 -->
+								<view class="ss-flex-2 ss-col-center">
+									<view @click="minusNumber($event,item)">
+										<text class="textIcon icon-jianhao- count-icon"></text>
+									</view>
+									<view class="count-number">{{item.number}}</view>
+									<view @click="addNumber($event,item)">
+										<text class="textIcon icon-jiahao- count-icon" style="color: #2DAFD1;"></text>
+									</view>
+								</view>
+							</view>
+							<!-- 价格以及预约 -->
+							<view class="ss-flex-2 ss-col-center" style="margin-top: 10rpx;">
+								<view class="ss-flex-2 ss-col-center ss-row-center">
+									<text class="textIcon icon-renminbi1688 icon-rmb"></text>
+									<view class="maney-number-box">498.00</view>
+								</view>
+								<view class="ss-flex-1"></view>
+								<view class="reservation-box" @click="placeOrder(item)">立即预约</view>
 							</view>
-							<view class="ss-flex-1"></view>
-							<view class="reservation-box" @click="placeOrder(item)">立即预约</view>
 						</view>
 					</view>
-                </view>
-            </scroll-view>
-        </view>
-	</view>
+				</scroll-view>
+			</view>
+		</view>
+	</s-layout>
+
 </template>
 <script setup>
-import {
+	import {
 		reactive,
 		ref
 	} from 'vue';
@@ -108,31 +105,39 @@ import {
 	import sheep from '@/sheep';
 	import $share from '@/sheep/platform/share';
 	// 隐藏原生tabBar
-	uni.hideTabBar();
-	
+	// uni.hideTabBar();
+
 	// 返回首页
-	const backPage=async()=>{
+	const backPage = async () => {
 		uni.reLaunch({
 			url: '/pages/XDHome/homePage/homePage'
 		});
 	}
-	
+
 	// 搜索框
-	const searchInfo=ref('')
-	const onSearch=async(e)=>{
-		console.log(e,searchInfo.value,'搜索信息')
+	const searchInfo = ref('')
+	const onSearch = async (e) => {
+		console.log(e, searchInfo.value, '搜索信息')
 	}
 	// 选择地址
-	const address=ref(0)
-	const range=ref([
-	    { value: 0, text: "华庭路橡树湾小区10-909" },
-	    { value: 1, text: "足球" },
-	    { value: 2, text: "游泳" },
-	  ])
-	const changeAddress=async(e)=>{
-		console.log(e,'获取地址信息')
+	const address = ref(0)
+	const range = ref([{
+			value: 0,
+			text: "华庭路橡树湾小区10-909"
+		},
+		{
+			value: 1,
+			text: "足球"
+		},
+		{
+			value: 2,
+			text: "游泳"
+		},
+	])
+	const changeAddress = async (e) => {
+		console.log(e, '获取地址信息')
 	}
-	
+
 	// 项目列表
 	const listData = ref([{
 			id: 1,
@@ -162,20 +167,20 @@ import {
 	// 每个项目的加减
 	const minusNumber = async (e, item) => {
 		item.number--
-		if(item.number<=0){
-			item.number=0
+		if (item.number <= 0) {
+			item.number = 0
 		}
 	}
 	const addNumber = async (e, item) => {
 		item.number++
-		if(item.number>=5){
-			item.number=5
+		if (item.number >= 5) {
+			item.number = 5
 		}
 	}
-	
+
 	// 预约下单
-	const placeOrder=async(item)=>{
-		console.log(item,'传递的参数')
+	const placeOrder = async (item) => {
+		console.log(item, '传递的参数')
 		uni.navigateTo({
 			url: '/pages/XDHome/technician/reservationPlaceOrder/reservationPlaceOrder?item='
 		});
@@ -186,149 +191,169 @@ import {
 	const bottomHeight = ref(bottomHeightOne)
 </script>
 <style scoped lang="scss">
-.reservation-box{
-	font-size: 22rpx;
-	background-color: #2AB0D5;
-	padding: 5rpx 20rpx;
-	color: #fff;
-	border-radius: 5rpx;
-}
-.icon-rmb{
-	font-size: 30rpx;
-	color:#E60012;
-	font-weight: 700;
-}
-.maney-number-box{
-	font-size: 30rpx;
-	color:#E60012;
-	margin-left: 5rpx;
-	padding-top: 5rpx;
-	font-weight: 650;
-}
-.count-number{
-	font-size: 24rpx;
-	color: #555;
-	padding-left: 10rpx;
-	padding-right: 10rpx;
-	box-sizing: border-box;
-}
-.count-icon{
-	font-size: 30rpx;
-	color: #999;
-}
-.line-box{
-	width: 2rpx;
-	height: 30rpx;
-	background-color: #D2D3D5;
-	margin-left: 10rpx;
-	margin-right: 10rpx;
-}
-.event-box{
-	font-size: 22rpx;
-	color: #909295;
-	height: 30rpx;
-	line-height: 30rpx;
-	box-sizing: border-box;
-}
-.event-wrap{
-	width: 100%;
-	max-height: 60rpx;
-	min-height: 60rpx;
-	overflow-y: auto;
-}
-.icon-navigation{
-	font-size: 32rpx;
-	color: #fff;
-	font-weight:700;
-}
-// 上中下布局样式
-.body {
-	display: flex;
-	flex-direction: column;
-	height: 100vh;
-	background: linear-gradient(to bottom, #08A3E9, #F8FCFF);
-	box-sizing: border-box;
-}
-// 中部滚动
-.list-wrap {
-	flex-grow: 1;
-	position: relative;
-	width: 95%;
-	margin-left: 2.5%;
-	box-sizing: border-box;
-}
-.list {
-	position: absolute;
-	top: 0;
-	left: 0;
-	right: 0;
-	bottom: 50rpx;
-	padding: 10rpx;
-	border-radius: 15rpx;
-	background-color: #fff;
-	box-sizing: border-box;
-}
-.list-scroll-view {
-	display: flex;
-	flex-direction: row;
-	flex-wrap: nowrap;
-	width:100%;
-	padding-bottom: 20rpx;
-	margin-bottom: 20rpx;
-	border-bottom: 1rpx solid #999BA2;
-	box-sizing: border-box;
-}
-.course-card {
-	width: 47vw;
-	margin-top: 10px;
-	margin-bottom: 10px;
-}
-// 底部
-.tools {
-	display: flex;
-	flex-direction: row;
-	justify-content: space-between;
-}
-.tools-item {
-	width: 45px;
-	text-align: center;
-	font-size: 14px;
-	padding: 20px;
-}
+	.reservation-box {
+		font-size: 22rpx;
+		background-color: #2AB0D5;
+		padding: 5rpx 20rpx;
+		color: #fff;
+		border-radius: 5rpx;
+	}
+
+	.icon-rmb {
+		font-size: 30rpx;
+		color: #E60012;
+		font-weight: 700;
+	}
+
+	.maney-number-box {
+		font-size: 30rpx;
+		color: #E60012;
+		margin-left: 5rpx;
+		padding-top: 5rpx;
+		font-weight: 650;
+	}
+
+	.count-number {
+		font-size: 24rpx;
+		color: #555;
+		padding-left: 10rpx;
+		padding-right: 10rpx;
+		box-sizing: border-box;
+	}
+
+	.count-icon {
+		font-size: 30rpx;
+		color: #999;
+	}
+
+	.line-box {
+		width: 2rpx;
+		height: 30rpx;
+		background-color: #D2D3D5;
+		margin-left: 10rpx;
+		margin-right: 10rpx;
+	}
+
+	.event-box {
+		font-size: 22rpx;
+		color: #909295;
+		height: 30rpx;
+		line-height: 30rpx;
+		box-sizing: border-box;
+	}
+
+	.event-wrap {
+		width: 100%;
+		max-height: 60rpx;
+		min-height: 60rpx;
+		overflow-y: auto;
+	}
+
+	.icon-navigation {
+		font-size: 32rpx;
+		color: #fff;
+		font-weight: 700;
+	}
+
+	// 上中下布局样式
+	.body {
+		display: flex;
+		flex-direction: column;
+		height: calc(100vh - 50px);
+		background: linear-gradient(to bottom, #08A3E9, #F8FCFF);
+		box-sizing: border-box;
+	}
+
+	// 中部滚动
+	.list-wrap {
+		flex-grow: 1;
+		position: relative;
+		width: 95%;
+		margin-left: 2.5%;
+		box-sizing: border-box;
+	}
+
+	.list {
+		position: absolute;
+		top: 0;
+		left: 0;
+		right: 0;
+		bottom: 50rpx;
+		padding: 10rpx;
+		border-radius: 15rpx;
+		background-color: #fff;
+		box-sizing: border-box;
+	}
+
+	.list-scroll-view {
+		display: flex;
+		flex-direction: row;
+		flex-wrap: nowrap;
+		width: 100%;
+		padding-bottom: 20rpx;
+		margin-bottom: 20rpx;
+		border-bottom: 1rpx solid #999BA2;
+		box-sizing: border-box;
+	}
+
+	.course-card {
+		width: 47vw;
+		margin-top: 10px;
+		margin-bottom: 10px;
+	}
+
+	// 底部
+	.tools {
+		display: flex;
+		flex-direction: row;
+		justify-content: space-between;
+	}
+
+	.tools-item {
+		width: 45px;
+		text-align: center;
+		font-size: 14px;
+		padding: 20px;
+	}
 </style>
 <style scoped>
-/deep/.uni-select__input-text {
-	font-size: 22rpx !important;
-	color: #fff !important;
-}
-/deep/uni-slider .uni-slider-handle-wrapper{
-	height:18rpx !important;
-}
-.distance{
-	/deep/.uni-select__input-text{
-		width:130rpx;
-		color:#fff;
+	/deep/.uni-select__input-text {
+		font-size: 22rpx !important;
+		color: #fff !important;
+	}
+
+	/deep/uni-slider .uni-slider-handle-wrapper {
+		height: 18rpx !important;
+	}
+
+	.distance {
+		/deep/.uni-select__input-text {
+			width: 130rpx;
+			color: #fff;
+			overflow: hidden;
+			white-space: nowrap;
+			text-overflow: ellipsis;
+			font-size: 24rpx;
+			text-align: right;
+		}
+	}
+
+	/deep/.uni-select__input-text {
+		width: 180rpx;
+		color: #fff;
 		overflow: hidden;
 		white-space: nowrap;
 		text-overflow: ellipsis;
-		font-size:24rpx;
+		font-size: 24rpx;
 		text-align: right;
 	}
-}
-/deep/.uni-select__input-text{
-	width:180rpx;
-	color:#fff;
-	overflow: hidden;
-	white-space: nowrap;
-	text-overflow: ellipsis;
-	font-size:24rpx;
-	text-align: right;
-}
-/deep/.uni-searchbar__box{
-	height:100% !important;
-}
-/deep/.uni-select{
-	border: none !important;
-	padding-left: 0rpx;
-}
+
+	/deep/.uni-searchbar__box {
+		height: 100% !important;
+	}
+
+	/deep/.uni-select {
+		border: none !important;
+		padding-left: 0rpx;
+	}
 </style>

+ 276 - 0
pages/XDHome/technician/newAddress/newAddress.vue

@@ -0,0 +1,276 @@
+<!-- 新增地址 -->
+<template>
+	<view class="body" :style="'padding-top:'+bottomHeight">
+		<view class="bg-box">
+			<!-- 导航 -->
+			<view class="ss-flex-2 ss-col-center ss-margin-width2" style="position: relative;">
+				<view class="ss-flex-2 ss-col-center">
+					<text class="textIcon icon-fanhui icon-navigation" @click="backPage"></text>
+					<view style="margin-left: 15rpx;color:#fff;font-size:28rpx;">新增地址</view>
+				</view>
+				<view class="ss-flex-1"></view>
+				<text class="textIcon icon-kefu icon-navigation"></text>
+				<text class="textIcon icon-tongzhiguanli icon-navigation" style="margin-left: 30rpx;"></text>
+			</view>
+		</view>
+		<!-- 填写表单 -->
+		<view class="form-box-info">
+			<uni-forms ref="baseForm" :modelValue="baseFormData" label-position="left" label-width="80px">
+				<!-- 左右布局 -->
+				<view class="ss-flex-2">
+					<view style="width: 60%;">
+						<uni-forms-item label="联系人" required name="userName">
+							<uni-easyinput v-model="baseFormData.userName" placeholder="请填写姓名" />
+						</uni-forms-item>
+					</view>
+					<view style="width: 35%;margin-left: 5%;margin-bottom: 35rpx;" name="sex">
+						<uni-data-checkbox v-model="baseFormData.sex" :localdata="sexs" />
+					</view>
+				</view>
+				<view class="ss-flex-2">
+					<view style="width: 60%;">
+						<uni-forms-item label="联系方式" required name="phone">
+							<uni-easyinput v-model="baseFormData.phone" placeholder="请填写联系方式" />
+						</uni-forms-item>
+					</view>
+					<view style="width: 35%;margin-left: 5%;" class="ss-flex-2 ss-col-center">
+						<text class="textIcon icon-tongxunlu"
+							style="font-size: 32rpx;color:#36B0CA;margin-bottom: 30rpx;"></text>
+						<view style="font-size: 24rpx;color:#36B0CA;margin-left: 10rpx;margin-bottom: 30rpx;">通讯录</view>
+					</view>
+				</view>
+				<view style="font-size: 18rpx;color: #9E9E9E;padding-left: 40rpx;">温馨提示:请确保当前手机号可以联系到您</view>
+				<uni-forms-item label="服务地址" required name="address">
+					<uni-easyinput v-model="baseFormData.address" placeholder="请填写服务地址" />
+				</uni-forms-item>
+				<uni-forms-item label="详细地址" required name="detailedAddress">
+					<uni-easyinput v-model="baseFormData.detailedAddress" placeholder="请填写详细门牌号" />
+				</uni-forms-item>
+			</uni-forms>
+		</view>
+		<!-- 中部 -->
+		<view class="list-wrap">
+			<scroll-view scroll-y="true" class="list">
+				<view class="list-scroll-view">
+					<view class="course-card">
+					</view>
+				</view>
+			</scroll-view>
+		</view>
+		<view class="baoc-box" @click="submitForm">保存</view>
+	</view>
+</template>
+<script setup>
+	import {
+		reactive,
+		ref
+	} from 'vue';
+	import {
+		computed
+	} from 'vue';
+	import {
+		onLoad,
+		onPageScroll,
+		onPullDownRefresh,
+		onReady,
+		onReachBottom,
+		onShow
+	} from '@dcloudio/uni-app';
+	import sheep from '@/sheep';
+	import $share from '@/sheep/platform/share';
+	// 隐藏原生tabBar
+	// uni.hideTabBar();
+
+	//表单
+	const sexs = ref([{
+		text: '先生',
+		value: 0
+	}, {
+		text: '女士',
+		value: 1
+	}])
+	const baseFormData = ref({
+		userName: '', //姓名
+		sex: 0, //性别
+		phone: '', //联系方式
+		address: '', //服务地址
+		detailedAddress: "" //详细地址
+	})
+	// 校验规则
+	const rules=ref({
+		userName:{
+			rules:[
+				{
+					required:true,
+					errorMessage:'请填写姓名'
+				}
+			]
+		},
+		sex:{
+			rules:[
+				{
+					required:true,
+					errorMessage:'请填选择性别'
+				}
+			]
+		},
+		phone:{
+			rules:[
+				{
+					required:true,
+					errorMessage:'请填写正确的手机号'
+				}
+			]
+		},
+		address:{
+			rules:[
+				{
+					required:true,
+					errorMessage:'请填写地址'
+				}
+			]
+		}
+	})
+	const baseForm = ref()
+
+	// 返回上一页
+	const backPage = async () => {
+		uni.navigateBack({
+			delta: 1
+		});
+	}
+	
+	const submitForm=async()=>{
+		const isFlag= await baseForm.value.validate()
+		console.log(isFlag,'uuuuuu')
+	}
+
+	//获取顶部安全距离
+	const app = uni.getSystemInfoSync()
+	const bottomHeightOne = (app.statusBarHeight) + 'rpx'
+	const bottomHeight = ref(bottomHeightOne)
+	
+	onReady(()=>{
+		baseForm.value.setRules(rules.value)
+	})
+</script>
+<style scoped>
+	/deep/.uni-data-checklist .checklist-group .checklist-box{
+		margin-right: 10rpx;
+	}
+	/deep/.is-input-border{
+		border: none;
+	}
+	/deep/.uni-easyinput__content-input{
+		padding-left: 0rpx !important;
+	}
+	/deep/.uni-forms-item{
+		margin-bottom: 25rpx !important;
+	}
+	/deep/.uni-data-checklist .checklist-group .checklist-box .checklist-content .checklist-text{
+		font-size: 22rpx !important;
+	}
+	/deep/.uni-forms-item__label{
+		font-size: 26rpx !important;
+	}
+	/deep/.uni-forms-item__error{
+		font-size: 18rpx !important;
+	}
+	/deep/.uni-easyinput__content-input{
+		height: 40rpx !important;
+	}
+	/deep/.uni-forms-item__label{
+		height: 40rpx !important;
+	}
+</style>
+<style scoped lang="scss">
+	.baoc-box{
+		width: 80%;
+		margin-left: 10%;
+		box-sizing: border-box;
+		padding: 10rpx;
+		background-color: #36AFCA;
+		color: #fff;
+		text-align: center;
+		margin-bottom: 100rpx;
+		border-radius: 10rpx;
+	}
+	.form-box-info {
+		width: 90%;
+		margin-left: 5%;
+		background-color: #fff;
+		box-sizing: border-box;
+		border-radius: 10rpx;
+		margin-top: -150rpx;
+		z-index: 999;
+		padding: 20rpx 10rpx;
+		font-size: 24rpx;
+		color: #646A72;
+		min-height: 450rpx;
+	}
+
+	.bg-box {
+		position: relative;
+		width: 100%;
+		height: 300rpx;
+		background: url('@/static/top-bg.png') no-repeat;
+		background-size: 100% 100%;
+		box-sizing: border-box;
+	}
+
+	// 上中下布局样式
+	.body {
+		display: flex;
+		flex-direction: column;
+		height: 100vh;
+		// background: linear-gradient(to bottom, #08A3E9, #F8FCFF);
+		background-color: #EEEEF0;
+	}
+
+	.head {
+		text-align: center;
+	}
+
+	// 中部滚动
+	.list-wrap {
+		flex-grow: 1;
+		position: relative;
+	}
+
+	.list {
+		position: absolute;
+		top: 0;
+		left: 0;
+		right: 0;
+		bottom: 0;
+	}
+
+	.list-scroll-view {
+		display: flex;
+		flex-direction: row;
+		flex-wrap: wrap;
+		justify-content: space-between;
+		margin-left: 2vw;
+		margin-right: 2vw;
+	}
+
+	.course-card {
+		width: 47vw;
+		margin-top: 10px;
+		margin-bottom: 10px;
+	}
+
+	// 底部
+	.tools {
+		display: flex;
+		flex-direction: row;
+		justify-content: space-between;
+	}
+
+	.tools-item {
+		width: 45px;
+		text-align: center;
+		font-size: 14px;
+		padding: 20px;
+	}
+</style>

+ 1 - 1
pages/XDHome/technician/orderGrabbingTechnician/orderGrabbingTechnician.vue

@@ -82,7 +82,7 @@
 	import sheep from '@/sheep';
 	import $share from '@/sheep/platform/share';
 	// 隐藏原生tabBar
-	uni.hideTabBar();
+	// uni.hideTabBar();
 	
 	// 跳转到抢单页面
 	const jumpGrab=async()=>{

+ 11 - 3
pages/XDHome/technician/reservationPlaceOrder/reservationPlaceOrder.vue

@@ -13,7 +13,7 @@
 				<text class="textIcon icon-tongzhiguanli icon-navigation" style="margin-left: 30rpx;"></text>
 			</view>
 			<!-- 选择地址框 -->
-			<view class="public-box top-box-info ss-flex-2 ss-col-center" style="padding:20rpx 10rpx;">
+			<view class="public-box top-box-info ss-flex-2 ss-col-center" style="padding:20rpx 10rpx;" @click="jumpNewAddress">
 				<text class="textIcon icon-ditu" style="font-size: 30rpx;color: #35AEC9;"></text>
 				<view class="ss-flex-2" style="flex-wrap:wrap;margin-left:20rpx;">
 					<view class="add-title">选择您的地址与联系方式</view>
@@ -253,7 +253,7 @@
 	import sheep from '@/sheep';
 	import $share from '@/sheep/platform/share';
 	// 隐藏原生tabBar
-	uni.hideTabBar();
+	// uni.hideTabBar();
 	// 返回上一页
 	const backPage = async () => {
 		uni.redirectTo({
@@ -288,7 +288,15 @@
 	    { value: 2, text: "3" },
 		{ value: 3, text: "4" },
 		{ value: 4, text: "5" },
-	  ])
+	])
+	// 跳转到新增地址
+	const jumpNewAddress=async()=>{
+		uni.navigateTo({
+			url: '/pages/XDHome/technician/newAddress/newAddress'
+		});
+	}
+	  
+	  
 	//获取顶部安全距离
 	const app = uni.getSystemInfoSync()
 	const bottomHeightOne = (app.statusBarHeight) + 'rpx'

+ 1 - 1
pages/XDHome/technician/serviceTimePage/serviceTimePage.vue

@@ -54,7 +54,7 @@ import {
 	import sheep from '@/sheep';
 	import $share from '@/sheep/platform/share';
 	// 隐藏原生tabBar
-	uni.hideTabBar();
+	// uni.hideTabBar();
 	
 	// 返回上一页
 	const backPage = async () => {

+ 12 - 182
pages/index/cart.vue

@@ -1,192 +1,22 @@
+<!-- 订单列表 -->
 <template>
-	<s-layout title="购物车" tabbar="/pages/index/cart" navbar="haha" class="ss-w-100 ss-h-100">
-		<s-empty v-if="state.list.length === 0" text="购物车空空如也,快去逛逛吧~" icon="/static/cart-empty.png" />
-
-		<!-- 头部 -->
-		<view class="cart-box ss-flex ss-flex-col ss-row-between" v-if="state.list.length">
-			<view class="cart-header ss-flex ss-col-center ss-row-between ss-p-x-30">
-				<view class="header-left ss-flex ss-col-center ss-font-26">
-					共
-					<text class="goods-number ui-TC-Main ss-flex">{{ state.list.length }}</text>
-					件商品
-				</view>
-				<view class="header-right">
-					<button v-if="state.editMode" class="ss-reset-button" @tap="state.editMode = false">
-						取消
-					</button>
-					<button v-else class="ss-reset-button ui-TC-Main" @tap="state.editMode = true">
-						编辑
-					</button>
-				</view>
-			</view>
-			<!-- 内容 -->
-			<view class="cart-content ss-flex-1 ss-p-x-30 ss-m-b-40">
-				<view class="goods-box ss-r-10 ss-m-b-14" v-for="item in state.list" :key="item.id">
-					<view class="ss-flex ss-col-center">
-						<label class="check-box ss-flex ss-col-center ss-p-l-10" @tap="onSelectSingle(item.id)">
-							<radio :checked="state.selectedIds.includes(item.id)" color="var(--ui-BG-Main)"
-								style="transform: scale(0.8)" @tap.stop="onSelectSingle(item.id)" />
-						</label>
-						<s-goods-item :title="item.spu.name" :img="item.spu.picUrl || item.goods.image"
-							:price="item.sku.price"
-							:skuText="item.sku.properties.length>1? item.sku.properties.reduce((items2,items)=>items2.valueName+' '+items.valueName):item.sku.properties[0].valueName"
-							priceColor="#FF3000" :titleWidth="400">
-							<template v-if="!state.editMode" v-slot:tool>
-								<su-number-box :min="0" :max="item.sku.stock" :step="1" v-model="item.count" @change="onNumberChange($event, item)" />
-							</template>
-						</s-goods-item>
-					</view>
-				</view>
-			</view>
-			<!-- 底部 -->
-			<su-fixed bottom :val="48" placeholder v-if="state.list.length > 0" :isInset="false">
-				<view class="cart-footer ss-flex ss-col-center ss-row-between ss-p-x-30 border-bottom">
-					<view class="footer-left ss-flex ss-col-center">
-						<label class="check-box ss-flex ss-col-center ss-p-r-30" @tap="onSelectAll">
-							<radio :checked="state.isAllSelected" color="var(--ui-BG-Main)"
-								style="transform: scale(0.8)" @tap.stop="onSelectAll" />
-							<view class="ss-m-l-8"> 全选 </view>
-						</label>
-						<text>合计:</text>
-						<view class="text-price price-text">
-							{{ fen2yuan(state.totalPriceSelected) }}
-						</view>
-					</view>
-					<view class="footer-right">
-						<button v-if="state.editMode" class="ss-reset-button ui-BG-Main-Gradient pay-btn ui-Shadow-Main"
-							@tap="onDelete">
-							删除
-						</button>
-						<button v-else class="ss-reset-button ui-BG-Main-Gradient pay-btn ui-Shadow-Main"
-							@tap="onConfirm">
-							去结算
-							{{ state.selectedIds?.length ? `(${state.selectedIds.length})` : '' }}
-						</button>
-					</view>
-				</view>
-			</su-fixed>
+	<s-layout title="收银台">
+		<view style="width: 100%;height: 100%;">
+			<iframe :src="url" width="100%" height="98%"></iframe>
 		</view>
 	</s-layout>
 </template>
 
 <script setup>
-	import sheep from '@/sheep';
-	import { computed, reactive } from 'vue';
-  import { fen2yuan } from '../../sheep/hooks/useGoods';
-
-	const sys_navBar = sheep.$platform.navbar;
-	const cart = sheep.$store('cart');
-
-	const state = reactive({
-		editMode: false,
-		list: computed(() => cart.list),
-		selectedList: [],
-		selectedIds: computed(() => cart.selectedIds),
-		isAllSelected: computed(() => cart.isAllSelected),
-		totalPriceSelected: computed(() => cart.totalPriceSelected),
-	});
-
-	// 单选选中
-	function onSelectSingle(id) {
-		cart.selectSingle(id);
-	}
-
-  // 全选
-	function onSelectAll() {
-		cart.selectAll(!state.isAllSelected);
-	}
-
-	// 结算
-	function onConfirm() {
-		let items = []
-		let goods_list = [];
-		state.selectedList = state.list.filter((item) => state.selectedIds.includes(item.id));
-		state.selectedList.map((item) => {
-			// 此处前端做出修改
-			items.push({
-				skuId: item.sku.id,
-				count: item.count,
-				cartId: item.id,
-				categoryId: item.spu.categoryId
-			})
-			goods_list.push({
-				// goods_id: item.goods_id,
-				goods_id: item.spu.id,
-				// goods_num: item.goods_num,
-				goods_num: item.count,
-				// 商品价格id真没有
-				// goods_sku_price_id: item.goods_sku_price_id,
-			});
-		});
-		// return;
-		if (goods_list.length === 0) {
-			sheep.$helper.toast('请选择商品');
-			return;
-		}
-		sheep.$router.go('/pages/order/confirm', {
-			data: JSON.stringify({
-				items
-			}),
-		});
-	}
-
-	function onNumberChange(e, cartItem) {
-		if (e === 0) {
-			cart.delete(cartItem.id);
-			return;
-		}
-		if (cartItem.goods_num === e) return;
-		cartItem.goods_num = e;
-		cart.update({
-			goods_id: cartItem.id,
-			goods_num: e,
-			goods_sku_price_id: cartItem.goods_sku_price_id,
-		});
-	}
-	async function onDelete() {
-		cart.delete(state.selectedIds);
-	}
+	import {
+		reactive,
+		ref
+	} from 'vue';
+	const price = ref(0.01)
+	const url = ref('https://mall.niusenyun.com/static/payDemo/cashier.html?price='+price.value)
+	console.log(url, 'ssssssssssssssssss')
 </script>
 
-<style lang="scss" scoped>
-	:deep(.ui-fixed) {
-		height: 72rpx;
-	}
-
-	.cart-box {
-		width: 100%;
-
-		.cart-header {
-			height: 70rpx;
-			background-color: #f6f6f6;
-			width: 100%;
-			position: fixed;
-			left: 0;
-			top: v-bind('sys_navBar') rpx;
-			z-index: 1000;
-			box-sizing: border-box;
-		}
-
-		.cart-footer {
-			height: 100rpx;
-			background-color: #fff;
-
-			.pay-btn {
-				width: 180rpx;
-				height: 70rpx;
-				font-size: 28rpx;
-				line-height: 28rpx;
-				font-weight: 500;
-				border-radius: 40rpx;
-			}
-		}
-
-		.cart-content {
-			margin-top: 70rpx;
+<style>
 
-			.goods-box {
-				background-color: #fff;
-			}
-		}
-	}
 </style>

+ 1 - 1
pages/index/index.vue

@@ -21,7 +21,7 @@
 	import sheep from '@/sheep';
 	import $share from '@/sheep/platform/share';
 	// 隐藏原生tabBar
-	uni.hideTabBar();
+	// uni.hideTabBar();
 
 	const template = computed(() => sheep.$store('app').template?.home);
 	// 在此处拦截改变一下首页轮播图 此处先写死后期复活 放到启动函数里

+ 1 - 1
pages/index/user.vue

@@ -20,7 +20,7 @@
   import sheep from '@/sheep';
 
   // 隐藏原生tabBar
-  uni.hideTabBar();
+  // uni.hideTabBar();
 
   const template = computed(() => sheep.$store('app').template.user);
   const isLogin = computed(() => sheep.$store('user').isLogin);

+ 1 - 1
pages/moban.vue

@@ -35,7 +35,7 @@ import {
 	import sheep from '@/sheep';
 	import $share from '@/sheep/platform/share';
 	// 隐藏原生tabBar
-	uni.hideTabBar();
+	// uni.hideTabBar();
 	
 	//获取顶部安全距离
 	const app = uni.getSystemInfoSync()

+ 3 - 3
sheep/components/s-layout/s-layout.vue

@@ -1,5 +1,5 @@
 <template>
-	<view class="page-app" :class="['theme-' + sys.mode, 'main-' + sys.theme, 'font-' + sys.fontSize]">
+	<view class="page-app-box" :class="['theme-' + sys.mode, 'main-' + sys.theme, 'font-' + sys.fontSize]">
 		<view class="page-main" :style="[bgMain]">
 			<!-- 顶部导航栏-情况1:默认通用顶部导航栏 -->
 			<su-navbar v-if="navbar === 'normal'" :title="title" statusBar :color="color" :tools="tools"
@@ -199,10 +199,10 @@
 </script>
 
 <style lang="scss" scoped>
-	.page-app {
+	.page-app-box {
 		position: relative;
 		color: var(--ui-TC);
-		background-color: var(--ui-BG-1) !important;
+		// background-color: var(--ui-BG-1) !important;
 		z-index: 2;
 		display: flex;
 		width: 100%;

+ 3 - 0
sheep/platform/provider/wechat/officialAccount.js

@@ -21,6 +21,9 @@ async function login(code = '', state = '') {
     }
   // 情况二:有 code 时,使用 code 去自动登录
   } else {
+	localStorage.setItem('code',code)
+	localStorage.setItem('type',socialType)
+	localStorage.setItem('state',state)
     // 解密 code 发起登陆
     const loginResult = await AuthUtil.socialLogin(socialType, code, state);
     if (loginResult.code === 0) {

+ 2 - 0
sheep/router/index.js

@@ -47,9 +47,11 @@ const _go = (
       query = paramsToQuery(path.params);
     }
   }
+  console.log(page,ROUTES_MAP,'aaaaaaaaa')
   const nextRoute = ROUTES_MAP[page];
   // 未找到指定跳转页面
   // mark: 跳转404页
+  console.log(nextRoute,'ppppppppp')
   if (!nextRoute) {
     console.log(`%c跳转路径参数错误<${page || 'EMPTY'}>`, 'color:red;background:yellow');
     return;

+ 5 - 0
sheep/scss/_tools.scss

@@ -194,6 +194,11 @@
 	width: 100%;
 	height:100%;
 }
+.icon-navigation {
+	font-size: 32rpx;
+	color: #fff;
+	font-weight: 700;
+}
 /* ==================
 
     margin padding: 内外边距

+ 7 - 3
static/iconfont.css

@@ -1,8 +1,8 @@
 @font-face {
   font-family: "iconfont"; /* Project id 4663271 */
-  src: url('https://at.alicdn.com/t/c/font_4663271_23srq9bgl39.woff2?t=1725260301402') format('woff2'),
-       url('https://at.alicdn.com/t/c/font_4663271_23srq9bgl39.woff?t=1725260301402') format('woff'),
-       url('https://at.alicdn.com/t/c/font_4663271_23srq9bgl39.ttf?t=1725260301402') format('truetype');
+  src: url('https://at.alicdn.com/t/c/font_4663271_o908y05kuoh.woff2?t=1725502372345') format('woff2'),
+       url('https://at.alicdn.com/t/c/font_4663271_o908y05kuoh.woff?t=1725502372345') format('woff'),
+       url('https://at.alicdn.com/t/c/font_4663271_o908y05kuoh.ttf?t=1725502372345') format('truetype');
 }
 
 .iconfont {
@@ -13,6 +13,10 @@
   -moz-osx-font-smoothing: grayscale;
 }
 
+.icon-tongxunlu:before {
+  content: "\e8fb";
+}
+
 .icon-chenghao:before {
   content: "\e619";
 }

+ 1 - 0
static/payDemo/MP_verify_ioJ6xLg1sgvV28Kc.txt

@@ -0,0 +1 @@
+ioJ6xLg1sgvV28Kc

+ 121 - 0
static/payDemo/README.md

@@ -0,0 +1,121 @@
+# checkout 收银台-H5
+
+## 1.基本概述
+
+此项目为商户提供快速接入 checkout 收银台功能,集成了微信,支付宝,银联云闪付,花呗分期等多种支付方式,商户只需要配置相关的支付参数即可用微信,支付宝,银联等 app 进行 h5 扫码支付。
+
+## 2.目录结构介绍
+
+```js
+|-MP_verify_ioJ6xLg1sgvV28Kc.txt  //微信支付需要上产到服务器验证的文件
+|-cashier.html                    //收银台支付页面
+|-config
+| |-index.js                      //项目基本配置,包括支付,页面跳转等
+|-css
+| |-reset.css                     //页面重置的样式表
+|-fonts                           //页面字体文件
+|-goodsDetail.html                //商品详情页面
+|-http.js                         //前端ajax请求封装
+|-img                             //项目的图片资源
+|-monitor.js                      //项目的前端监控SDK
+|-orderConfirm.html               //订单确认页面
+|-pay.js                          //支付页面处理逻辑
+|-payFail.html                    //支付失败页面
+|-paySuccess.html                 //支付成功页面
+|-util.js                         //项目用到的工具函数,如获取参数,授权跳转函数等
+```
+
+## 3.接入指南
+
+### 3.1 全屏接入指南
+
+在斗拱收银台若模版中选择独立页面,则下载的模板中则为全屏收银台模版页面,只需要在 config/index.js 配置相关的支付配置信息即可拉起支付
+
+<img src="https://us1.myximage.com/2021/12/22/68a52a3563fdb8a6da3240fcc88c5c03.png" alt="image" style="zoom:20%" />
+
+### 3.2 半屏接入指南
+
+若在斗拱收银台若模版中选择底部弹出,则下载的模板中则为半屏收银台模版页面,只需要在 config/index.js 配置相关的支付配置信息即可拉起支付
+
+<img src="https://us1.myximage.com/2021/12/22/fc9e1c7a93580471aecb82a8f3966657.png" alt="image" style="zoom:20%;" />
+
+### 3.3 前端监控 SDK 调用
+
+```js
+// SDK初始化
+MonitorMinSDK.init({
+  pid: 'dg-checkout',
+  appToken: 'app-226f04f1-f5ae-4ac3-b420-032b518cd0e9',
+  appKey: '24e67f6771036c5cd6225eebe1a99671',
+  isDev: false,
+});
+// SDK自定义埋点上报
+MonitorMinSDK.track(
+  '0090_00006404',
+  {
+    huifu_id: 'huifuId', //汇付商户号
+    os: 'h5',
+    page: 'full', //full:全屏,half:半屏
+  },
+  true
+);
+//以上参数无需修改
+```
+
+### 3.4 下单成功调用活动埋点数据
+
+```js
+function uploadPayInfo() {
+  var params = {
+    product_id: 'productId', //产品号
+    sys_id: 'sysId', //系统号
+    data: {
+      huifu_id: 'huifuId', //汇付商户号
+      resource: 'H5',
+      id_code: 'co',
+      action: 'CALL',
+      ref_req_date: dayjs().format('YYYYMMDD'),
+      ref_req_seqid: mer_ord_id, //orderID
+    },
+  };
+  var baseURL = '';
+  if (location.host.indexOf(configObj.productionEnvHost) > -1) {
+    baseURL = configObj.prodUploadPayAPI;
+  } else {
+    baseURL = configObj.testUploadPayAPI;
+  }
+  axios.post(baseURL, params);
+}
+```
+
+### 3.4 注意事项
+
+* 当用户在自己页面跳转到收银台页面,则需要给收银台页面 url 传递 price 金额,如:http://xxx.xx/cashier.html?price=9.99
+
+## 4.配置参数介绍
+
+带有*的配置项以实际的业务进行调整,可查看 config/index.js
+|参数|类型|说明|
+|:---- |:---|:---- |
+huifuId|string|汇付天下斗拱平台商户号
+productId|string|汇付天下斗拱平台产品号
+sysId|string|汇付天下斗拱平台系统号码
+mobile.payTime|string|移动端收银台支付剩余时间倒计时,单位 min
+mobile.backHomeUrl|string|移动端收银台支付完回跳地址(若在微信,支付宝,银联等 app 内完成支付,此链接无效)
+isDebug|boolean|默认在 h5 的测试服引入调试插件
+api.createPay| string|下单接口(*)
+api.queryPay| string|下单查询接口(_)
+api.wxAuth|string |获取微信 openId(_)
+api.unionpayAuth|string |获取银联 userId(_)
+testEnvHost| string|收银台页面测试环境域名(_)
+productionEnvHost|string |收银台页面生产环境域名(_)
+testBaseURL|string |接口测试 API 前缀(_)
+prodBaseURL| string|接口生产 API 前缀(\*)
+prodUploadPayAPI| string|下单成功标识 API,必须调用此接口上传数据成功,才可获得对应的奖励
+
+## 参考资料
+
+1.项目流程图
+<img src="https://us1.myximage.com/2021/08/26/64e942fb7811a714e80c3c66c3063e03.jpg" style="zoom:50%;" />
+
+2.[微信公众号支付参考文档](https://pay.weixin.qq.com/wiki/doc/apiv3_partner/apis/chapter4_1_4.shtml)

+ 1193 - 0
static/payDemo/cashier.html

@@ -0,0 +1,1193 @@
+<!DOCTYPE html>
+<html lang="en">
+	<head>
+		<meta charset="UTF-8" />
+		<meta http-equiv="X-UA-Compatible" content="IE=edge" />
+		<meta name="viewport" content="width=device-width, initial-scale=1.0,maximum-scale=1.0, minimum-scale=1.0" />
+		<!-- 清除缓存 -->
+		<meta http-equiv="Content-Type" content="text/html; charset=UTF-8">
+		<meta http-equiv="X-UA-Compatible" content="IE=8">
+		<meta http-equiv="Expires" content="0">
+		<meta http-equiv="Pragma" content="no-cache">
+		<meta http-equiv="Cache-control" content="no-cache, no-store, must-revalidate">
+		<meta http-equiv="Cache" content="no-cache">
+		<title>收银台</title>
+		<link rel="stylesheet" href="./css/reset.css" />
+		<script>
+			(function(WIN) {
+				var setFontSize = (WIN.setFontSize = function(_width) {
+					var docEl = document.documentElement;
+					// 获取当前窗口的宽度
+					var width = _width || docEl.clientWidth || docEl.getBoundingClientRect().width;
+
+					if (width > 420) {
+						width = 420;
+					}
+					// 在375px上,1rem = 20px
+					var rem = width / 18.75;
+
+					docEl.style.fontSize = rem + 'px';
+
+					// // 部分机型上的误差、兼容性处理
+					var actualSize =
+						WIN.getComputedStyle && parseFloat(WIN.getComputedStyle(docEl)['font-size']);
+					if (actualSize !== rem && actualSize > 0 && Math.abs(actualSize - rem) > 1) {
+						var remScaled = (rem * rem) / actualSize;
+						docEl.style.fontSize = rem + 'px';
+					}
+				});
+				var timer;
+				//函数节流
+				function dbcRefresh() {
+					clearTimeout(timer);
+					timer = setTimeout(setFontSize, 100);
+				}
+
+				//窗口更新动态改变 font-size
+				WIN.addEventListener('resize', dbcRefresh, false);
+				//页面显示时计算一次
+				WIN.addEventListener(
+					'pageshow',
+					function(e) {
+						if (e.persisted) {
+							dbcRefresh();
+						}
+					},
+					false
+				);
+				setFontSize();
+			})(window);
+		</script>
+		<style>
+			@font-face {
+				font-display: auto;
+				font-family: 'DIN_Alternate_Bold';
+				font-style: normal;
+				font-weight: 400;
+				src: local('DIN_Alternate_Bold'), url('./fonts/DIN_Alternate_Bold.ttf') format('ttf');
+			}
+
+			@media only screen and (min-width: 400px) {
+				body {
+					font-size: 21.33333333px !important;
+				}
+			}
+
+			@media only screen and (min-width: 414px) {
+				body {
+					font-size: 21px !important;
+				}
+			}
+
+			@media only screen and (min-width: 480px) {
+				body {
+					font-size: 25.6px !important;
+				}
+			}
+
+			* {
+				padding: 0;
+				margin: 0;
+			}
+
+			li {
+				list-style: none;
+			}
+
+			body,
+			html {
+				width: 100%;
+				height: 100%;
+				background: #fff;
+			}
+
+			.h5Container {
+				width: 18.75rem;
+				max-width: 18.75rem;
+				height: 100vh;
+				box-sizing: border-box;
+				margin: 0 auto;
+				font-size: 0.7rem;
+				text-align: center;
+			}
+
+			/* 独立页面样式 */
+			.cashier_headerTitle {
+				color: #050505;
+				font-size: 0.9rem;
+				font-weight: 400;
+			}
+
+			.cashier_cashierDivider {
+				height: 0.5rem;
+				background: #f5f5f5;
+			}
+
+			.cashier_logo {
+				padding-top: 1.85rem;
+				margin-bottom: 1rem;
+			}
+
+			.cashier_logoImg {
+				max-width: 10rem;
+				min-height: 2rem;
+				max-height: 3rem;
+				object-fit: contain;
+			}
+
+			.cashier_price {
+				margin-bottom: 1rem;
+				color: #333;
+				font-size: 1.2rem;
+			}
+
+			.cashier_priceNumber {
+				margin-left: 0.2rem;
+				font-family: DIN_Alternate_Bold;
+				font-size: 1.5rem;
+				font-weight: 500;
+			}
+
+			.cashier_payTimeRemaining {
+				margin-bottom: 0.3rem;
+			}
+
+			.cashier_payTxt {
+				margin-right: 0.5rem;
+				color: #999;
+			}
+
+			.cashier_time {
+				color: #999;
+				font-weight: 500;
+			}
+
+			.cashier_timeItem {
+				padding: 0.1rem;
+				background: rgba(0, 0, 0, 0.04);
+				border-radius: 0.1rem;
+				color: #000;
+			}
+
+			.cashier_timeSplit {
+				margin: 0 0.2rem;
+				color: #000;
+			}
+
+			.cashier_order {
+				margin-bottom: 2.5rem;
+				color: #999;
+			}
+
+			.cashier_orderTxt {
+				margin-right: 0.4rem;
+			}
+
+			.cashier_payType {
+				box-sizing: border-box;
+				text-align: left;
+			}
+
+			.checkout-list-item {
+				display: none;
+				overflow: hidden;
+				padding: 0.85rem 0;
+				border-bottom: 1px solid #e9eaeb;
+				margin: 0 1rem;
+			}
+
+			.checkout-list-item-inner {
+				display: flex;
+				align-items: center;
+				float: left;
+				pointer-events: none;
+			}
+
+			.checkout-payIcon {
+				width: 1rem;
+				height: 1rem;
+				margin-right: 0.5rem;
+			}
+
+			.checkout-pay-title {
+				margin-right: 0.5rem;
+				font-size: 0.7rem;
+			}
+
+			.checkout-recommend {
+				width: 1.9rem;
+				height: 1rem;
+				border: 1px solid var(--theme);
+				border-radius: 0.15rem;
+				color: var(--theme);
+				font-size: 0.7rem;
+				font-weight: 400;
+				line-height: 1rem;
+				text-align: center;
+				display: none;
+			}
+
+			.checkout-list-item:nth-of-type(1) .checkout-recommend {
+				display: block;
+			}
+
+			.checkout-radio {
+				position: relative;
+				display: block;
+				width: 1rem;
+				height: 1rem;
+				padding: 0;
+				border: 0.1rem solid #ccc;
+				margin: 0;
+				-webkit-appearance: none;
+				background-color: #fff;
+				-webkit-border-radius: 50%;
+				border-radius: 50%;
+
+				/* vertical-align: top; */
+				cursor: default;
+				float: right;
+				font-size: 0.7rem;
+				-webkit-transition: background-color ease 0.1s;
+				transition: background-color ease 0.1s;
+				-webkit-user-select: none;
+				user-select: none;
+				pointer-events: none;
+			}
+
+			.checkout-radio:checked,
+			.checked-radio {
+				border: solid 0.1rem var(--theme);
+				background-color: var(--theme);
+				text-align: center;
+			}
+
+			.checkout-radio:checked::before,
+			.checkout-radio.checkout-checked::before,
+			.checkout-radio:checked::after,
+			.checkout-radio.checkout-checked::after,
+			.checked-radio::before,
+			.checked-radio::after {
+				position: absolute;
+				z-index: 2;
+				top: 50%;
+				left: 50%;
+				width: 0.5rem;
+				height: 0.3rem;
+				border: 1px solid #fff;
+				border-top: none;
+				border-right: none;
+				margin-top: -0.25rem;
+				margin-left: -0.25rem;
+				background: transparent;
+				-webkit-border-radius: 0;
+				border-radius: 0;
+				content: '';
+				-webkit-transform: rotate(-45deg);
+				transform: rotate(-45deg);
+			}
+
+			.cashier_payTypeTitle {
+				padding: 1rem 0 1rem 1rem;
+				font-weight: 500;
+			}
+
+			.cashier_footer {
+				position: absolute;
+				z-index: 10;
+				bottom: 0;
+				left: 0;
+				display: flex;
+				width: 100%;
+				flex-direction: column;
+				align-items: center;
+				padding-bottom: 1rem;
+				cursor: pointer;
+				text-align: center;
+			}
+
+			.cashier_payBtn {
+				width: 17.15rem;
+				height: 2.2rem;
+				margin-bottom: 1rem;
+				background: rgb(133, 133, 133);
+				border-radius: 0.2rem;
+				color: rgba(255, 255, 255, 0.85);
+				font-size: 0.8rem;
+				line-height: 2.2rem;
+			}
+
+			.cashier_brand {
+				display: flex;
+				width: 100%;
+				align-items: center;
+				justify-content: center;
+			}
+
+			.cashier_brandImg {
+				max-width: 5rem;
+				height: 1rem;
+				margin-right: 0.2rem;
+				object-fit: contain;
+			}
+
+			.cashier_brandtxt {
+				color: rgba(0, 0, 0, 0.45);
+				font-size: 0.6rem;
+			}
+
+			/* 底部弹出样式 */
+			.dialogMask {
+				position: absolute;
+				z-index: 999;
+				top: 0;
+				right: 0;
+				bottom: 0;
+				left: 0;
+				width: 100%;
+				height: 100%;
+				background: rgba(0, 0, 0, 0.5);
+			}
+
+			.confirmDialog {
+				position: absolute;
+				top: 50%;
+				left: 50%;
+				display: flex;
+				overflow: hidden;
+				width: 15rem;
+				flex-direction: column;
+				align-items: center;
+				background: #fff;
+				border-radius: 0.2rem;
+				text-align: center;
+				transform: translate(-50%, -50%);
+			}
+
+			.confirmHeader {
+				padding: 1.55rem 0.6rem 0;
+				color: #22242e;
+				font-size: 0.9rem;
+				line-height: 1.2rem;
+			}
+
+			.confimContent {
+				display: flex;
+				width: 100%;
+				justify-content: center;
+				padding: 0.55rem 1rem 1.55rem;
+				color: #6c6e75;
+				font-size: 0.7rem;
+				font-weight: 400;
+				text-align: justify;
+			}
+
+			.contentTxt {
+				line-height: 1.05rem;
+			}
+
+			.confimFooter {
+				position: relative;
+				display: flex;
+				width: 100%;
+				height: 2.5rem;
+				align-items: center;
+				border-top: 1px solid #eee;
+			}
+
+			/* .confimFooter::after {
+        position: absolute;
+        content: '';
+        height: 100%;
+        width: 1px;
+        background: #eeeeee;
+        left: 50%;
+        top: 0;
+      } */
+
+			.confimBtn {
+				display: flex;
+				height: 100%;
+				flex: 1;
+				align-items: center;
+				justify-content: center;
+				color: #22242e;
+				font-size: 0.7rem;
+				line-height: 0.95rem;
+				text-align: center;
+			}
+
+			.leaveBtn {
+				position: relative;
+			}
+
+			.leaveBtn::after {
+				position: absolute;
+				top: 0;
+				right: 0;
+				width: 1px;
+				height: 100%;
+				background: #eee;
+				content: '';
+			}
+
+			.payBtn {
+				color: #5568d5;
+			}
+
+			.hide {
+				display: none;
+			}
+
+			.show {
+				display: block;
+			}
+
+			/* 取消支付 */
+			.cancelMask {
+				position: absolute;
+				z-index: 9999;
+				top: 0;
+				right: 0;
+				bottom: 0;
+				left: 0;
+				width: 100%;
+				height: 100%;
+				background: rgba(0, 0, 0, 0.5);
+			}
+
+			.cancelMask .confirmDialog {
+				position: absolute;
+				top: 50%;
+				left: 50%;
+				display: flex;
+				overflow: hidden;
+				width: 15rem;
+				flex-direction: column;
+				align-items: center;
+				background: #fff;
+				border-radius: 0.2rem;
+				text-align: center;
+				transform: translate(-50%, -50%);
+			}
+
+			.cancelMask .confirmHeader {
+				padding: 1.55rem 0.6rem 0;
+				color: #22242e;
+				font-size: 0.9rem;
+				line-height: 1.2rem;
+			}
+
+			.cancelMask .confimContent {
+				display: flex;
+				width: 100%;
+				justify-content: center;
+				padding: 0.55rem 1rem 1.55rem;
+				color: #6c6e75;
+				font-size: 0.7rem;
+				font-weight: 400;
+				text-align: justify;
+			}
+
+			.cancelMask .contentTxt {
+				line-height: 1.05rem;
+			}
+
+			.cancelMask .confimFooter {
+				position: relative;
+				display: flex;
+				width: 100%;
+				height: 2.5rem;
+				align-items: center;
+				border-top: 1px solid #eee;
+			}
+
+			.cancelMask .confimFooter::after {
+				position: absolute;
+				top: 0;
+				left: 50%;
+				width: 1px;
+				height: 100%;
+				background: #eee;
+				content: '';
+			}
+
+			.cancelMask .confimBtn {
+				display: flex;
+				height: 100%;
+				flex: 1;
+				align-items: center;
+				justify-content: center;
+				color: #22242e;
+				font-size: 0.7rem;
+				line-height: 0.95rem;
+				text-align: center;
+			}
+
+			.cancelMask .payBtn {
+				color: #5568d5;
+			}
+
+			/* loading */
+			.loadingMask {
+				position: absolute;
+				z-index: 99;
+				top: 0;
+				right: 0;
+				bottom: 0;
+				left: 0;
+				width: 100%;
+				max-width: 18.75rem;
+				height: 100%;
+				margin: 0 auto;
+				background: rgba(0, 0, 0, 0.5);
+				border-radius: 0 0 0.2rem 0.2rem;
+			}
+
+			.loadingMask .content {
+				position: absolute;
+				top: 50%;
+				left: 50%;
+				display: flex;
+				width: 15rem;
+				flex-direction: column;
+				align-items: center;
+				background: #fff;
+				border-radius: 0.2rem;
+				box-shadow:
+					0 12px 48px 16px rgba(0, 0, 0, 0.03),
+					0 9px 28px 0 rgba(0, 0, 0, 0.05),
+					0 6px 16px -8px rgba(0, 0, 0, 0.08);
+				transform: translate(-50%, -50%);
+			}
+
+			.loadingMask .loadingImg {
+				width: 1.6rem;
+				height: 1.6rem;
+				margin-top: 2rem;
+				animation: 1.6s linear ratate infinite;
+			}
+
+			@keyframes ratate {
+				0% {
+					transform: rotate(0deg);
+				}
+
+				40% {
+					transform: rotate(144deg);
+				}
+
+				80% {
+					transform: rotate(288deg);
+				}
+
+				100% {
+					transform: rotate(360deg);
+				}
+			}
+
+			.loadingMask .loadingTxt {
+				margin-top: 1.2rem;
+				margin-bottom: 2rem;
+				color: #22242e;
+				font-size: 0.7rem;
+			}
+
+			/* 底部弹出收银台 */
+			.cashier_mask_mb16 {
+				margin-bottom: 0.8rem;
+			}
+
+			.cashier_mask_headerTitle {
+				position: relative;
+				margin-top: 0.8rem;
+				color: rgba(0, 0, 0, 0.85);
+				font-size: 0.8rem;
+				font-weight: 500;
+				text-align: center;
+			}
+
+			.cashier_mask_cancel {
+				position: absolute;
+				left: 0.8rem;
+				color: rgba(0, 0, 0, 0.45);
+				font-size: 0.7rem;
+				font-weight: 400;
+			}
+
+			.cashier_mask_divider {
+				height: 1px;
+				background: #eee;
+			}
+
+			.cashier_mask_logo {
+				padding-top: 1.6rem;
+				margin-bottom: 0.75rem;
+			}
+
+			.cashier_mask_logoImg {
+				max-width: 2rem;
+				max-width: 10rem;
+				min-height: 1.2rem;
+				object-fit: contain;
+			}
+
+			.cashier_mask_price {
+				margin-bottom: 1rem;
+				color: rgba(0, 0, 0, 0.85);
+			}
+
+			.cashier_mask_priceNumber {
+				margin-left: 0.2rem;
+				font-size: 1.2rem;
+				font-weight: 500;
+			}
+
+			.cashier_mask_payTxt {
+				margin-right: 0.4rem;
+				color: rgba(0, 0, 0, 0.65);
+			}
+
+			.cashier_mask_time {
+				color: rgba(0, 0, 0, 0.65);
+				font-weight: 500;
+			}
+
+			.cashier_mask_order {
+				margin-bottom: 2rem;
+				color: rgba(0, 0, 0, 0.65);
+			}
+
+			.cashier_mask_orderTxt {
+				margin-right: 0.2rem;
+			}
+
+			.cashier_mask_payType {
+				box-sizing: border-box;
+				margin-bottom: 1rem;
+				text-align: left;
+			}
+
+			.cashier_mask_payTypeTitle {
+				padding: 1rem 0 1rem 1rem;
+				font-weight: 500;
+			}
+
+			.cashier_mask_payTxt {
+				margin: 0 1rem;
+			}
+
+			.cashier_mask_footer {
+				display: flex;
+				width: 100%;
+				flex-direction: column;
+				align-items: center;
+				padding-bottom: 1.2rem;
+				cursor: pointer;
+				text-align: center;
+			}
+
+			.cashier_mask_payBtn {
+				width: 17.15rem;
+				height: 2.2rem;
+				background: #0b5afe;
+				border-radius: 0.2rem;
+				color: rgba(255, 255, 255, 0.85);
+				line-height: 2.2rem;
+			}
+
+			.cashier_mask_brand {
+				display: flex;
+				width: 100%;
+				align-items: center;
+				justify-content: center;
+			}
+
+			.cashier_mask_brandImg {
+				height: 1rem;
+				margin-right: 0.2rem;
+				object-fit: contain;
+			}
+
+			.cashier_mask_brandtxt {
+				color: rgba(0, 0, 0, 0.45);
+				font-size: 0.6rem;
+			}
+
+			.cashier_mask_content {
+				position: absolute;
+				z-index: 99;
+				bottom: 0;
+				left: 50%;
+				width: 100%;
+				background: #fff;
+				border-radius: 0.4rem 0.4rem 0 0;
+				box-shadow:
+					0 12px 48px 16px rgba(0, 0, 0, 0.03),
+					0 9px 28px 0 rgba(0, 0, 0, 0.05),
+					0 6px 16px -8px rgba(0, 0, 0, 0.08);
+				transform: translateX(-50%);
+			}
+
+			.cashier_mask_mask {
+				position: absolute;
+				z-index: 10;
+				top: 0;
+				right: 0;
+				bottom: 0;
+				left: 0;
+				width: 100%;
+				max-width: 18.75rem;
+				height: 100%;
+				margin: 0 auto;
+				background: rgba(0, 0, 0, 0.5);
+				border-radius: 0 0 0.2rem 0.2rem;
+			}
+
+			/* page loading */
+			.pageLoadingMask {
+				position: absolute;
+				z-index: 99;
+				top: 0;
+				right: 0;
+				bottom: 0;
+				left: 0;
+				width: 100%;
+				width: 18.75rem;
+				height: 100%;
+				margin: 0 auto;
+				background: #fff;
+			}
+
+			.pageLoadingImg {
+				position: absolute;
+				top: 30%;
+				left: 46%;
+				width: 1.6rem;
+				height: 1.6rem;
+				animation: 1.6s linear ratate infinite;
+				transform: translate(-50%, -50%);
+			}
+
+			.pageLoadingText {
+				position: absolute;
+				top: 37%;
+				width: 100%;
+				text-align: center;
+				transform: translateY(-50%);
+			}
+
+			/* 弹出层-订单页面 */
+			.content {
+				position: fixed;
+				top: 0;
+				left: 0;
+				margin-bottom: 129px;
+			}
+
+			.itemContent {
+				display: flex;
+				justify-content: center;
+			}
+
+			.actImg {
+				margin-top: 10px;
+			}
+
+			.address {
+				width: 100%;
+				margin-top: 20px;
+				text-align: left;
+			}
+
+			.contact {
+				width: 100%;
+				margin-top: 10px;
+				margin-bottom: 10px;
+				color: #818489;
+				font-size: 14px;
+				text-align: left;
+			}
+
+			.cashier_priceNumber-order {
+				margin-left: 20px;
+				font-size: 14px;
+			}
+
+			.dliver {
+				width: 100%;
+				height: 10px;
+				background-color: #ecf1f4;
+			}
+
+			.goodsTitle {
+				margin-left: 20px;
+				color: #595a5b;
+				font-size: 15px;
+				text-align: left;
+			}
+
+			.orderContent {
+				display: flex;
+				width: 100%;
+				flex-direction: row;
+				justify-content: space-between;
+				margin-top: 15px;
+			}
+
+			.orderImg {
+				width: 85px;
+				height: 85px;
+				margin-left: 20px;
+			}
+
+			.orderLeft {
+				margin-left: 20px;
+				font-size: 13px;
+			}
+
+			.orderRight {
+				margin-right: 20px;
+				font-size: 14px;
+				font-weight: 500;
+			}
+
+			.detail {
+				display: flex;
+				flex-direction: column;
+				margin-top: 15px;
+				margin-right: 20px;
+				margin-bottom: 15px;
+				margin-left: 20px;
+				color: #818489;
+				font-size: 13px;
+			}
+
+			.orderDetail {
+				display: flex;
+				height: 85px;
+				flex-direction: column;
+				justify-content: space-between;
+				margin-right: 15px;
+				margin-left: 15px;
+				text-align: left;
+			}
+
+			.pTitle {
+				color: #595a5b;
+				font-size: 14px;
+				text-align: left;
+			}
+
+			.colorType {
+				color: #818489;
+				font-size: 12px;
+				text-align: left;
+			}
+
+			.payView {
+				display: flex;
+				flex-direction: row;
+				justify-content: space-between;
+			}
+
+			.payPrice {
+				color: red;
+				font-size: 16px;
+				text-align: left;
+			}
+
+			.stepper {
+				display: flex;
+				width: 100px;
+				height: 20px;
+				flex-direction: row;
+				background: white;
+				border-radius: 3px;
+			}
+
+			/* 加号和减号 */
+			.stepper .sign {
+				width: 40px;
+				float: left;
+				line-height: 20px;
+				text-align: center;
+			}
+
+			/* 数值 */
+			.stepper .number {
+				width: 45px;
+				height: 20px;
+				margin: 0 auto;
+				background-color: #ecf1f4;
+				color: #000;
+				float: left;
+				font-size: 15px;
+				text-align: center;
+			}
+
+			/* 普通样式 */
+			.sign_normal {
+				width: 30px;
+				color: black;
+				float: left;
+				line-height: 20px;
+				text-align: center;
+			}
+
+			/* 禁用样式 */
+			.sign_disabled {
+				width: 30px;
+				color: #ccc;
+				float: left;
+				line-height: 20px;
+				text-align: center;
+			}
+
+			.logo {
+				width: 100px;
+				height: 100px;
+				margin-top: 100px;
+				margin-right: auto;
+				margin-bottom: 25px;
+				margin-left: auto;
+			}
+
+			.text-area {
+				display: flex;
+				justify-content: center;
+			}
+
+			.title {
+				color: #8f8f94;
+				font-size: 18px;
+			}
+
+			.btnView {
+				display: flex;
+				width: 80%;
+				height: 33px;
+				justify-content: center;
+				border: #1296db solid 1px;
+				margin-top: 30px;
+				border-radius: 10px;
+				color: #366092;
+				line-height: 33px;
+			}
+
+			.cashier_footer {
+				position: fixed;
+				z-index: 10;
+				bottom: 0;
+				left: 0;
+				display: flex;
+				width: 100%;
+				flex-direction: column;
+				align-items: center;
+				padding-bottom: 5px;
+				background-color: #fff;
+				text-align: center;
+			}
+
+			.cashier_payBtn-order {
+				width: 113px;
+				height: 44px;
+				background: rgb(133, 133, 133);
+				color: rgba(255, 255, 255, 0.85);
+				cursor: pointer;
+				font-size: 16px;
+				line-height: 44px;
+			}
+
+			.footerPay {
+				display: flex;
+				width: calc(100vw - 40px);
+				height: 44px;
+				flex-direction: row;
+				align-items: center;
+				justify-content: space-between;
+				margin-bottom: 20px;
+			}
+
+			.payPrice {
+				display: flex;
+				flex-direction: row;
+				align-items: center;
+				justify-content: flex-start;
+				color: red;
+				font-size: 12px;
+			}
+		</style>
+	</head>
+
+	<body>
+		<div class="h5Container">
+			<div class="cashier_logo">
+				<img class="cashier_logoImg" src="img/logo.png" alt="Logo" title="Logo" />
+			</div>
+			<div class="cashier_price">
+				<span>¥</span>
+				<span class="cashier_priceNumber" id="cashier_priceNumber">793.21</span>
+			</div>
+			<div class="cashier_payTimeRemaining">
+				<span class="cashier_payTxt">支付剩余时间</span>
+				<span class="cashier_time">
+					<span class="cashier_timeItem" id="pay_minute">05</span><span
+						class="cashier_timeSplit">:</span><span class="cashier_timeItem" id="pay_second">00</span>
+				</span>
+			</div>
+			<div class="cashier_order">
+				<span class="cashier_orderTxt">订单编号:</span>
+				<span class="cashier_orderNumber" id="cashier_orderNumber">207084835060</span>
+			</div>
+			<div class="cashier_cashierDivider"></div>
+			<div class="cashier_payType">
+				<div class="cashier_payTypeTitle">选择支付方式</div>
+				<ul class="checkout-list">
+					<li class="checkout-list-item" id="alipayItem">
+						<div class="checkout-list-item-inner">
+							<img class="checkout-payIcon" src="img/alipay.png" />
+							<span class="checkout-pay-title">支付宝</span>
+							<span style="--theme: #e74e4e" class="checkout-recommend">推荐</span>
+						</div>
+						<input style="--theme: #0B5AFE" class="checkout-radio" type="radio" name="radio"
+							id="alipayInput" />
+					</li>
+					<li class="checkout-list-item" id="wxpayItem">
+						<div class="checkout-list-item-inner">
+							<img class="checkout-payIcon" src="img/wxpay.png" />
+							<span class="checkout-pay-title">微信支付</span>
+							<span style="--theme: #e74e4e" class="checkout-recommend">推荐</span>
+						</div>
+						<input style="--theme: #0B5AFE" class="checkout-radio" type="radio" name="radio"
+							id="wxpayInput" />
+					</li>
+					<li class="checkout-list-item" id="unionpayItem">
+						<div class="checkout-list-item-inner">
+							<img class="checkout-payIcon" src="img/unionpay.png" />
+							<span class="checkout-pay-title">银联</span>
+							<span style="--theme: #e74e4e" class="checkout-recommend">推荐</span>
+						</div>
+						<input style="--theme: #0B5AFE" class="checkout-radio" type="radio" name="radio"
+							id="unionpayInput" />
+					</li>
+					<li class="checkout-list-item" id="huabeipayItem">
+						<div class="checkout-list-item-inner">
+							<img class="checkout-payIcon" src="img/huabeipay.png" />
+							<span class="checkout-pay-title">花呗分期</span>
+							<span style="--theme: #e74e4e" class="checkout-recommend">推荐</span>
+						</div>
+						<input style="--theme: #0B5AFE" class="checkout-radio" type="radio" name="radio"
+							id="huabeipayInput" />
+					</li>
+					<li class="checkout-list-item" id="bankpayItem">
+						<div class="checkout-list-item-inner">
+							<img class="checkout-payIcon" src="img/bankpay.png" />
+							<span class="checkout-pay-title">银行卡分期</span>
+							<span style="--theme: #e74e4e" class="checkout-recommend">推荐</span>
+						</div>
+						<input style="--theme: #0B5AFE" class="checkout-radio" type="radio" name="radio"
+							id="bankpayInput" />
+					</li>
+				</ul>
+			</div>
+			<div class="cashier_footer">
+				<div class="cashier_payBtn" id="pay-button" style="background: #0B5AFE">
+					支付¥<span id="pay_amount">793.21</span>
+				</div>
+				<div class="cashier_brand">
+					<img class="cashier_brandImg" src="img/defaultLogo.png" alt="" />
+					<span class="cashier_brandtxt">提供技术支持</span>
+				</div>
+			</div><!-- 超时提醒 -->
+			<div class="dialogMask hide" id="timeoutRemind">
+				<div class="confirmDialog">
+					<div class="confirmHeader">订单已取消</div>
+					<div class="confimContent">
+						<p class="contentTxt">交易超时已关闭,请重新下单支付。</p>
+					</div>
+					<div class="confimFooter">
+						<div id="continuePayBtn" class="confimBtn payBtn" style="color: #0B5AFE">
+							重新下单
+						</div>
+					</div>
+				</div>
+			</div>
+			<!-- 取消支付 -->
+			<div class="cancelMask hide" id="cancelPay">
+				<div class="confirmDialog">
+					<div class="confirmHeader">确定离开收银台?</div>
+					<div class="confimContent">
+						<p class="contentTxt">订单尚未完成支付,请尽快支付。</p>
+					</div>
+					<div class="confimFooter">
+						<div class="confimBtn" id="confirmLeaveBtn">确认离开</div>
+						<div id="continuePay" class="confimBtn payBtn" style="color: #0B5AFE">
+							继续支付
+						</div>
+					</div>
+				</div>
+			</div>
+			<!-- loading -->
+			<div class="loadingMask hide" id="loadingMask">
+				<div class="content">
+					<img class="loadingImg" src="img/loading.png" alt="" />
+					<div class="loadingTxt">处理中,请耐心等待</div>
+				</div>
+			</div>
+			<!-- 页面初始化loading -->
+			<div class="pageLoadingMask" id="pageLoadingMask">
+				<img class="pageLoadingImg" src="img/loading.png" alt="" />
+				<div class="pageLoadingText">加载中...</div>
+			</div>
+		</div>
+	</body>
+	<script src="https://cdn.cloudpnr.com/opps/libs/jquery/jquery-2.1.2.min.js"></script>
+	<script src="https://cdn.cloudpnr.com/opps/libs/vconsole/vconsole-3.4.0.min.js"></script>
+	<script src="https://cdn.cloudpnr.com/opps/libs/axios/axios-0.21.1.min.js"></script>
+	<script src="https://cdn.cloudpnr.com/opps/libs/dayjs/dayjs-1.10.4.min.js"></script>
+	<script src="https://cdn.cloudpnr.com/opps/libs/fastclick/fastclick-1.0.6.min.js"></script>
+
+	<script src="./monitor.js"></script>
+	<script src="./config/index.js"></script>
+	<script src="./http.js"></script>
+	<script src="./util.js"></script>
+	<script>
+		window.addEventListener('load', () => {
+			const state = {
+				title: 'init',
+				url: '#'
+			};
+			window.history.pushState(state, 'init', '#');
+		});
+		window.addEventListener('popstate', () => {
+			$('#cancelPay').show();
+		});
+
+		function jumpLink(urlName) {
+			const origin = location.origin;
+			const pathname = location.pathname;
+			const urlAry = pathname.split('/');
+			urlAry.pop();
+			urlAry.push(urlName);
+			const urlStr = urlAry.join('/');
+			const link = origin + urlStr;
+			return link;
+		}
+		let totalPrice = GetQueryString('price');
+		$('#cashier_priceNumber').text(totalPrice);
+		$('#pay_amount').text(totalPrice);
+
+		// 取消支付,返回商品确认页面,修复微信中无法返回上一页
+		$('#confirmLeaveBtn').click(function() {
+			location.href = jumpLink('goodsDetail.html');
+		});
+		$('#continuePay').click(function() {
+			$('#cancelPay').hide();
+		});
+		var mer_ord_id = dayjs().format('YYYYMMDDHHmmssSSS') + '' + randomNum(100, 999);
+		localStorage.setItem('mer_ord_id', mer_ord_id);
+		$('#cashier_orderNumber').text(localStorage.getItem('mer_ord_id'));
+	</script>
+	<script src="./pay.js"></script>
+</html>

+ 49 - 0
static/payDemo/config/index.js

@@ -0,0 +1,49 @@
+// 说明:以下配置文件中xx只做演示,使用时请替换
+var configObj = {
+  mobile: {
+    // 支付剩余时间倒计时,单位min
+    payTime: 3,
+    // 支付完成返回的页面地址,需要加协议,http/https
+    backHomeUrl: '',
+    // 微信支付相关配置 
+    wxConfig: {
+      // 微信appid
+      appid: 'wxb87ea37680c6dc2e',
+    },
+  },
+  pc: {
+    // 支付剩余时间倒计时,单位min
+    payTime: 3,
+    // 支付完成返回的页面地址,需要加协议,http/https
+    backHomeUrl: '',
+  },
+  // 汇付商户ID
+  huifuId: '6666000122864432',
+  // 您自己的产品ID
+  productId: 'PAYUN',
+  // 渠道商id
+  sysId: '6666000122864432',
+  // 测试环境h5是否开启调试模式
+  isDebug: true,
+  // 接口名称集合
+  api: {
+    // 下单
+    createPay: 'xx4',
+    // 查询下单
+    queryPay: 'xx3',
+    // 获取微信openId,
+    wxAuth: '/member/auth/social-login',
+    // 获取银联userId,
+    unionpayAuth: 'xx2',
+  },
+  // 测试环境域名
+  testEnvHost: '',
+  // 测试API前缀:
+  testBaseURL: 'https://saas.niusenyun.com/app-api',
+  // 生产环境域名
+  productionEnvHost: '',
+  // 生产API前缀
+  prodBaseURL: 'https://saas.niusenyun.com/app-api',
+  // 下单成功标识生产API,必须调用此接口上传数据成功,才可获得对应的奖励
+  prodUploadPayAPI: 'https://api.huifu.com/v2/trade/casherinsert',
+};

+ 88 - 0
static/payDemo/css/reset.css

@@ -0,0 +1,88 @@
+body,
+h1,
+h2,
+h3,
+h4,
+h5,
+h6,
+hr,
+p,
+blockquote,
+dl,
+dt,
+dd,
+ul,
+ol,
+li,
+pre,
+form,
+fieldset,
+legend,
+button,
+input,
+textarea,
+th,
+td {
+  margin: 0;
+  padding: 0;
+}
+body,
+button,
+input,
+select,
+textarea {
+  font: 12px/1.5tahoma, arial, \5b8b\4f53;
+}
+h1,
+h2,
+h3,
+h4,
+h5,
+h6 {
+  font-size: 100%;
+}
+address,
+cite,
+dfn,
+em,
+var {
+  font-style: normal;
+}
+code,
+kbd,
+pre,
+samp {
+  font-family: couriernew, courier, monospace;
+}
+small {
+  font-size: 12px;
+}
+ul,
+ol {
+  list-style: none;
+}
+a {
+  text-decoration: none;
+}
+a:hover {
+  text-decoration: underline;
+}
+sup {
+  vertical-align: text-top;
+}
+sub {
+  vertical-align: text-bottom;
+}
+legend {
+  color: #000;
+}
+fieldset,
+img {
+  border: 0;
+}
+button,
+input,
+select,
+textarea {
+  font-size: 100%;
+}

BIN
static/payDemo/fonts/DIN_Alternate_Bold.ttf


+ 183 - 0
static/payDemo/goodsDetail.html

@@ -0,0 +1,183 @@
+<!DOCTYPE html>
+<html lang="en">
+
+<head>
+  <meta charset="UTF-8" />
+  <meta http-equiv="X-UA-Compatible" content="IE=edge" />
+  <meta name="viewport" content="width=device-width, initial-scale=1.0, minimum-scale=1, maximum-scale=1, user-scalable=no" />
+  <title>商品详情</title>
+</head>
+<style>
+  .content {
+    display: flex;
+    flex-direction: column;
+    align-items: center;
+    justify-content: center;
+    padding-bottom: 129px;
+
+  }
+
+  .itemContent {
+    display: flex;
+    justify-content: center;
+  }
+
+  .actImg {
+    width: 355px;
+    height: 290px;
+  }
+
+  .goodsTitle {
+    margin-left: 20px;
+    margin-right: 20px;
+    margin-top: 10px;
+  }
+
+  .cashier_price {
+    margin-top: 10px;
+    color: red;
+    margin-bottom: 10px;
+    font-size: 20px;
+  }
+
+  .cashier_priceNumber {
+    font-size: 30px;
+    font-weight: 400;
+    margin-left: 4px;
+  }
+
+  .dliver {
+    width: 100%;
+    height: 10px;
+    background-color: #ECF1F4;
+  }
+
+  .orderContent {
+    width: 100%;
+    display: flex;
+    flex-direction: row;
+    margin-top: 15px;
+  }
+
+  .orderLeft {
+    margin-left: 20px;
+    margin-right: 25px;
+    color: #818489;
+  }
+
+  .detail {
+    margin-left: 20px;
+    margin-right: 20px;
+    margin-top: 15px;
+    margin-bottom: 15px;
+    font-size: 14px;
+  }
+
+  .logo {
+    height: 100px;
+    width: 100px;
+    margin-top: 100px;
+    margin-left: auto;
+    margin-right: auto;
+    margin-bottom: 25px;
+  }
+
+  .text-area {
+    display: flex;
+    justify-content: center;
+  }
+
+  .title {
+    font-size: 18px;
+    color: #8f8f94;
+  }
+
+  .btnView {
+    width: 80%;
+    margin-top: 30px;
+    height: 33px;
+    display: flex;
+    line-height: 33px;
+    color: #366092;
+    justify-content: center;
+    border: #1296db solid 1px;
+    border-radius: 10px;
+  }
+
+  .cashier_footer {
+    position: fixed;
+    bottom: 0;
+    left: 0;
+    width: 100%;
+    z-index: 10;
+    text-align: center;
+    display: flex;
+    flex-direction: column;
+    align-items: center;
+    padding-bottom: 5px;
+    background-color: white;
+    /* cursor: pointer; */
+  }
+
+  .cashier_payBtn {
+    width: 343px;
+    height: 44px;
+    background: rgb(133, 133, 133);
+    border-radius: 4px;
+    color: rgba(255, 255, 255, 0.85);
+    line-height: 44px;
+    margin-bottom: 20px;
+    font-size: 16px;
+    cursor: pointer;
+  }
+
+</style>
+
+<body>
+  <script language="javascript" type="text/javascript">
+    function gotoOrder() {
+      window.location.href = "orderConfirm.html";
+    }
+
+  </script>
+  <div class="content">
+    <swiper style="height: 300px;display: flex;align-items: center;justify-content: center;">
+      <block>
+        <swiper-item class="itemContent"><img class="actImg" mode="aspectFill"
+            src="./img/mouse.png"></img>
+        </swiper-item>
+      </block>
+    </swiper>
+    <div class="goodsTitle">无线鼠标静音无声笔记本台式电脑游戏</div>
+    <div class="cashier_price">
+      <span>¥</span>
+      <span class="cashier_priceNumber">0.01</span>
+    </div>
+    <div class="dliver"></div>
+    <div class="orderContent">
+      <div class="orderLeft">已选</div>
+      <div>银色</div>
+    </div>
+    <div class="orderContent" style="margin-bottom: 15px;">
+      <div class="orderLeft">送至</div>
+      <div>上海 嘉定区</div>
+    </div>
+    <div class="dliver"></div>
+    <div class="detail">
+      按键采用竞技游戏级别的微动开发,零延迟,回弹利索,提高工作效能。<br />
+      高品质静音按键,轻松使用不扰人。
+    </div>
+    <div class="cashier_footer">
+      <div class="dliver"
+        style="text-align: center;height:45px ;font-size: 13px;color: #F5A478;align-items: center;display: flex;justify-content: center;margin-bottom: 15px;">
+        本页面只用于演示收银台支付,不发货、不退款
+      </div>
+      <div class="cashier_payBtn" style="background: #FEAD0B" onclick="gotoOrder()">
+        立即购买
+      </div>
+    </div>
+  </div>
+</body>
+
+</html>
+<script src="https://cdn.cloudpnr.com/opps/libs/jquery/jquery-2.1.2.min.js"></script>

+ 48 - 0
static/payDemo/http.js

@@ -0,0 +1,48 @@
+/* eslint-disable */
+var baseURL = '';
+if (location.host.indexOf(configObj.productionEnvHost) > -1) {
+  baseURL = configObj.prodBaseURL;
+} else {
+  baseURL = configObj.testBaseURL;
+}
+var service = axios.create({
+  baseURL: baseURL,
+  withCredentials: false, // send cookies when cross-domain requests
+  timeout: 20000, // request timeout
+  headers: {
+    'Content-Type': 'application/json;charset=uft-8',
+	"tenant-id":1
+  },
+});
+
+// request interceptor
+service.interceptors.request.use(
+  (config) => {
+    return config;
+  },
+  (error) => {
+    console.log(error); // for debug
+    return Promise.reject(error);
+  }
+);
+
+// response interceptor
+service.interceptors.response.use(
+  (response) => {
+    const res = response.data;
+    console.log('-log- ~ res', res);
+    if (res.code !== 0) {
+      console.log('---error-res--', res);
+      // 查询接口不弹出
+      // if (response.config.url !== configObj.queryPayURL) {
+      //   alert(res.resp_msg || 'api error');
+      // }
+      return Promise.reject(new Error(res));
+    } else {
+      return res;
+    }
+  },
+  (error) => {
+    console.log('--error--', error);
+  }
+);

BIN
static/payDemo/img/QR_img.png


BIN
static/payDemo/img/accountClose.png


BIN
static/payDemo/img/alipay.png


BIN
static/payDemo/img/bankpay.png


BIN
static/payDemo/img/close.png


BIN
static/payDemo/img/combinepay.png


BIN
static/payDemo/img/datarmbpay.png


BIN
static/payDemo/img/defaultLogo.png


BIN
static/payDemo/img/fail1.png


BIN
static/payDemo/img/fail2.png


BIN
static/payDemo/img/fail3.png


BIN
static/payDemo/img/huabeipay.png


BIN
static/payDemo/img/loading.png


BIN
static/payDemo/img/logo.png


BIN
static/payDemo/img/mouse.png


BIN
static/payDemo/img/quickpasspay.png


BIN
static/payDemo/img/success1.png


BIN
static/payDemo/img/success2.png


BIN
static/payDemo/img/success3.png


BIN
static/payDemo/img/unionpay.png


BIN
static/payDemo/img/wxpay.png


+ 390 - 0
static/payDemo/monitor.js

@@ -0,0 +1,390 @@
+! function(t, e) {
+	"object" == typeof exports && "undefined" != typeof module ? module.exports = e() : "function" == typeof define &&
+		define.amd ? define(e) : (t = "undefined" != typeof globalThis ? globalThis : t || self).MonitorMinSDK = e()
+}(this, (function() {
+	"use strict";
+
+	function t(e) {
+		return t = "function" == typeof Symbol && "symbol" == typeof Symbol.iterator ? function(t) {
+			return typeof t
+		} : function(t) {
+			return t && "function" == typeof Symbol && t.constructor === Symbol && t !== Symbol.prototype ?
+				"symbol" : typeof t
+		}, t(e)
+	}
+
+	function e(t, e) {
+		for (var n = 0; n < e.length; n++) {
+			var i = e[n];
+			i.enumerable = i.enumerable || !1, i.configurable = !0, "value" in i && (i.writable = !0), Object
+				.defineProperty(t, i.key, i)
+		}
+	}
+	var n, i, r = r || function(t, e) {
+		var n = {},
+			i = n.lib = {},
+			r = function() {},
+			o = i.Base = {
+				extend: function(t) {
+					r.prototype = this;
+					var e = new r;
+					return t && e.mixIn(t), e.hasOwnProperty("init") || (e.init = function() {
+						e.$super.init.apply(this, arguments)
+					}), e.init.prototype = e, e.$super = this, e
+				},
+				create: function() {
+					var t = this.extend();
+					return t.init.apply(t, arguments), t
+				},
+				init: function() {},
+				mixIn: function(t) {
+					for (var e in t) t.hasOwnProperty(e) && (this[e] = t[e]);
+					t.hasOwnProperty("toString") && (this.toString = t.toString)
+				},
+				clone: function() {
+					return this.init.prototype.extend(this)
+				}
+			},
+			s = i.WordArray = o.extend({
+				init: function(t, e) {
+					t = this.words = t || [], this.sigBytes = null != e ? e : 4 * t.length
+				},
+				toString: function(t) {
+					return (t || c).stringify(this)
+				},
+				concat: function(t) {
+					var e = this.words,
+						n = t.words,
+						i = this.sigBytes;
+					if (t = t.sigBytes, this.clamp(), i % 4)
+						for (var r = 0; r < t; r++) e[i + r >>> 2] |= (n[r >>> 2] >>> 24 - r % 4 *
+							8 & 255) << 24 - (i + r) % 4 * 8;
+					else if (65535 < n.length)
+						for (r = 0; r < t; r += 4) e[i + r >>> 2] = n[r >>> 2];
+					else e.push.apply(e, n);
+					return this.sigBytes += t, this
+				},
+				clamp: function() {
+					var e = this.words,
+						n = this.sigBytes;
+					e[n >>> 2] &= 4294967295 << 32 - n % 4 * 8, e.length = t.ceil(n / 4)
+				},
+				clone: function() {
+					var t = o.clone.call(this);
+					return t.words = this.words.slice(0), t
+				},
+				random: function(e) {
+					for (var n = [], i = 0; i < e; i += 4) n.push(4294967296 * t.random() | 0);
+					return new s.init(n, e)
+				}
+			}),
+			a = n.enc = {},
+			c = a.Hex = {
+				stringify: function(t) {
+					var e = t.words;
+					t = t.sigBytes;
+					for (var n = [], i = 0; i < t; i++) {
+						var r = e[i >>> 2] >>> 24 - i % 4 * 8 & 255;
+						n.push((r >>> 4).toString(16)), n.push((15 & r).toString(16))
+					}
+					return n.join("")
+				},
+				parse: function(t) {
+					for (var e = t.length, n = [], i = 0; i < e; i += 2) n[i >>> 3] |= parseInt(t
+						.substr(i, 2), 16) << 24 - i % 8 * 4;
+					return new s.init(n, e / 2)
+				}
+			},
+			u = a.Latin1 = {
+				stringify: function(t) {
+					var e = t.words;
+					t = t.sigBytes;
+					for (var n = [], i = 0; i < t; i++) n.push(String.fromCharCode(e[i >>> 2] >>> 24 -
+						i % 4 * 8 & 255));
+					return n.join("")
+				},
+				parse: function(t) {
+					for (var e = t.length, n = [], i = 0; i < e; i++) n[i >>> 2] |= (255 & t.charCodeAt(
+						i)) << 24 - i % 4 * 8;
+					return new s.init(n, e)
+				}
+			},
+			f = a.Utf8 = {
+				stringify: function(t) {
+					try {
+						return decodeURIComponent(escape(u.stringify(t)))
+					} catch (t) {
+						throw Error("Malformed UTF-8 data")
+					}
+				},
+				parse: function(t) {
+					return u.parse(unescape(encodeURIComponent(t)))
+				}
+			},
+			l = i.BufferedBlockAlgorithm = o.extend({
+				reset: function() {
+					this._data = new s.init, this._nDataBytes = 0
+				},
+				_append: function(t) {
+					"string" == typeof t && (t = f.parse(t)), this._data.concat(t), this
+						._nDataBytes += t.sigBytes
+				},
+				_process: function(e) {
+					var n = this._data,
+						i = n.words,
+						r = n.sigBytes,
+						o = this.blockSize,
+						a = r / (4 * o);
+					if (e = (a = e ? t.ceil(a) : t.max((0 | a) - this._minBufferSize, 0)) * o, r = t
+						.min(4 * e, r), e) {
+						for (var c = 0; c < e; c += o) this._doProcessBlock(i, c);
+						c = i.splice(0, e), n.sigBytes -= r
+					}
+					return new s.init(c, r)
+				},
+				clone: function() {
+					var t = o.clone.call(this);
+					return t._data = this._data.clone(), t
+				},
+				_minBufferSize: 0
+			});
+		i.Hasher = l.extend({
+			cfg: o.extend(),
+			init: function(t) {
+				this.cfg = this.cfg.extend(t), this.reset()
+			},
+			reset: function() {
+				l.reset.call(this), this._doReset()
+			},
+			update: function(t) {
+				return this._append(t), this._process(), this
+			},
+			finalize: function(t) {
+				return t && this._append(t), this._doFinalize()
+			},
+			blockSize: 16,
+			_createHelper: function(t) {
+				return function(e, n) {
+					return new t.init(n).finalize(e)
+				}
+			},
+			_createHmacHelper: function(t) {
+				return function(e, n) {
+					return new p.HMAC.init(t, n).finalize(e)
+				}
+			}
+		});
+		var p = n.algo = {};
+		return n
+	}(Math);
+	! function(t) {
+		for (var e = r, n = (o = e.lib).WordArray, i = o.Hasher, o = e.algo, s = [], a = [], c = function(t) {
+				return 4294967296 * (t - (0 | t)) | 0
+			}, u = 2, f = 0; 64 > f;) {
+			var l;
+			t: {
+				l = u;
+				for (var p = t.sqrt(l), h = 2; h <= p; h++)
+					if (!(l % h)) {
+						l = !1;
+						break t
+					} l = !0
+			}
+			l && (8 > f && (s[f] = c(t.pow(u, .5))), a[f] = c(t.pow(u, 1 / 3)), f++), u++
+		}
+		var d = [];
+		o = o.SHA256 = i.extend({
+			_doReset: function() {
+				this._hash = new n.init(s.slice(0))
+			},
+			_doProcessBlock: function(t, e) {
+				for (var n = this._hash.words, i = n[0], r = n[1], o = n[2], s = n[3], c = n[4], u =
+						n[5], f = n[6], l = n[7], p = 0; 64 > p; p++) {
+					if (16 > p) d[p] = 0 | t[e + p];
+					else {
+						var h = d[p - 15],
+							y = d[p - 2];
+						d[p] = ((h << 25 | h >>> 7) ^ (h << 14 | h >>> 18) ^ h >>> 3) + d[p - 7] + (
+							(y << 15 | y >>> 17) ^ (y << 13 | y >>> 19) ^ y >>> 10) + d[p - 16]
+					}
+					h = l + ((c << 26 | c >>> 6) ^ (c << 21 | c >>> 11) ^ (c << 7 | c >>> 25)) + (
+							c & u ^ ~c & f) + a[p] + d[p], y = ((i << 30 | i >>> 2) ^ (i << 19 |
+							i >>> 13) ^ (i << 10 | i >>> 22)) + (i & r ^ i & o ^ r & o), l = f, f =
+						u, u = c, c = s + h | 0, s = o, o = r, r = i, i = h + y | 0
+				}
+				n[0] = n[0] + i | 0, n[1] = n[1] + r | 0, n[2] = n[2] + o | 0, n[3] = n[3] + s | 0,
+					n[4] = n[4] + c | 0, n[5] = n[5] + u | 0, n[6] = n[6] + f | 0, n[7] = n[7] + l |
+					0
+			},
+			_doFinalize: function() {
+				var e = this._data,
+					n = e.words,
+					i = 8 * this._nDataBytes,
+					r = 8 * e.sigBytes;
+				return n[r >>> 5] |= 128 << 24 - r % 32, n[14 + (r + 64 >>> 9 << 4)] = t.floor(i /
+						4294967296), n[15 + (r + 64 >>> 9 << 4)] = i, e.sigBytes = 4 * n.length,
+					this._process(), this._hash
+			},
+			clone: function() {
+				var t = i.clone.call(this);
+				return t._hash = this._hash.clone(), t
+			}
+		});
+		e.SHA256 = i._createHelper(o), e.HmacSHA256 = i._createHmacHelper(o)
+	}(Math), i = (n = r).enc.Utf8, n.algo.HMAC = n.lib.Base.extend({
+		init: function(t, e) {
+			t = this._hasher = new t.init, "string" == typeof e && (e = i.parse(e));
+			var n = t.blockSize,
+				r = 4 * n;
+			e.sigBytes > r && (e = t.finalize(e)), e.clamp();
+			for (var o = this._oKey = e.clone(), s = this._iKey = e.clone(), a = o.words, c = s
+					.words, u = 0; u < n; u++) a[u] ^= 1549556828, c[u] ^= 909522486;
+			o.sigBytes = s.sigBytes = r, this.reset()
+		},
+		reset: function() {
+			var t = this._hasher;
+			t.reset(), t.update(this._iKey)
+		},
+		update: function(t) {
+			return this._hasher.update(t), this
+		},
+		finalize: function(t) {
+			var e = this._hasher;
+			return t = e.finalize(t), e.reset(), e.finalize(this._oKey.clone().concat(t))
+		}
+	});
+	var o = r.HmacSHA256;
+
+	function s(t, e, n, i) {
+		return new Promise((function(r, o) {
+			try {
+				var s = new XMLHttpRequest;
+				s && (s.withCredentials = !1, s.onreadystatechange = function() {
+					if (4 === s.readyState)
+						if (s.status >= 200 && s.status < 300 || 304 == s.status) {
+							var t = JSON.parse(s.responseText);
+							n(t, r, o)
+						} else i(s.status, r, o)
+				}, s.open("POST", t, !0), s.setRequestHeader("Content-type",
+					"application/json; charset=UTF-8"), s.send(JSON.stringify(e) || null))
+			} catch (t) {
+				i("请求异常", r, o)
+			}
+		}))
+	}
+	var a = {
+			INIT_CONFIG: "monitorsdk_config",
+			BASE_INFO: "monitorsdk_base_info",
+			PENDING_DATA: "monitorsdk_pending_data",
+			MAIN_APP_MONITORED: "monitorsdk_main_app"
+		},
+		c = function(t) {
+			var e;
+			try {
+				e = JSON.parse(window.localStorage.getItem(t)) || null
+			} catch (n) {
+				e = window.localStorage.getItem(t)
+			}
+			return e
+		},
+		u = function(e, n) {
+			"object" === t(n) && (n = JSON.stringify(n)), window.localStorage.setItem(e, n)
+		},
+		f = window.localStorage.clear;
+	window.localStorage.clear = function() {
+		var t = {},
+			e = Object.values(a);
+		e.forEach((function(e) {
+			t[e] = c(e)
+		})), f.apply(this, arguments), e.forEach((function(e) {
+			u(e, t[e])
+		}))
+	};
+	var l = ["token", "deviceId", "appId", "platform", "reportTime"],
+		p = function() {
+			var t = c("monitorsdk_base_info");
+			if (null != t && t.deviceId) return t.deviceId;
+			var e = "xxxxxxxx-xxxx-4xxx-yxxx-xxxxxxxxxxxx".replace(/[xy]/g, (function(t) {
+				var e = 16 * Math.random() | 0;
+				return ("x" == t ? e : 3 & e | 8).toString(16)
+			}));
+			return u("monitorsdk_base_info", {
+				deviceId: e
+			}), e
+		};
+
+	function h(t, e) {
+		var n = l.sort().filter((function(e) {
+			return t[e]
+		})).map((function(e) {
+			return e + "=" + t[e]
+		})).join("&");
+		return o("POST" + n, e).toString()
+	}
+	var d = function() {
+		function n() {
+			! function(t, e) {
+				if (!(t instanceof e)) throw new TypeError("Cannot call a class as a function")
+			}(this, n), this.version = "min-1.0.3", this.initPrams = null, this.postbeUrl = {
+				dev: "http://jpostbe.huifutest.com",
+				pro: "https://jua.cloudpnr.com"
+			}
+		}
+		var i, r, o;
+		return i = n, r = [{
+			key: "init",
+			value: function(e) {
+				if ("object" === t(e)) {
+					var n = e.pid,
+						i = e.appKey,
+						r = e.appToken,
+						o = e.isDev,
+						s = void 0 !== o && o;
+					if (n && i && r) return this.initPrams = {
+						pid: n,
+						appKey: i,
+						appToken: r,
+						isDev: s,
+						deviceId: p()
+					}, this;
+					console.error("配置信息缺少必填字段!")
+				} else console.error("初始化配置信息错误")
+			}
+		}, {
+			key: "track",
+			value: function(t, e) {
+				var n = arguments.length > 2 && void 0 !== arguments[2] && arguments[2],
+					i = this.initPrams,
+					r = i.pid,
+					o = i.appKey,
+					a = i.appToken,
+					c = i.isDev,
+					u = i.deviceId,
+					f = {
+						actionCode: t,
+						sensorAttr: e,
+						actionType: 2,
+						occurTime: Date.now()
+					};
+				n && (f.sensorNo = t, f.actionCode = "");
+				var l = {
+					appId: r,
+					token: a,
+					deviceId: u,
+					platform: 3,
+					reportTime: Date.now(),
+					sensorData: [f]
+				};
+				l.sign = h(l, o);
+				var p = this.postbeUrl.pro;
+				return c && (p = this.postbeUrl.dev), s(p + "/api/jpostbeApi/autoTrack/save", l,
+					(function(t, e) {
+						"90000" === (null == t ? void 0 : t.respCode) ? e(!0): e(!1)
+					}), (function(t, e) {
+						e(!1)
+					}))
+			}
+		}], r && e(i.prototype, r), o && e(i, o), n
+	}();
+	return new d
+}));

+ 481 - 0
static/payDemo/orderConfirm.html

@@ -0,0 +1,481 @@
+<!DOCTYPE html>
+<html lang="en">
+
+<head>
+	<meta charset="UTF-8" />
+	<meta http-equiv="X-UA-Compatible" content="IE=edge" />
+  <meta name="viewport" content="width=device-width, initial-scale=1.0, minimum-scale=1, maximum-scale=1, user-scalable=no" />
+	<title>订单确认</title>
+</head>
+<style>
+	.content {
+		display: flex;
+		flex-direction: column;
+		align-items: center;
+		justify-content: center;
+		margin-bottom: 6.45rem;
+	}
+
+	.itemContent {
+		display: flex;
+		justify-content: center;
+	}
+
+	.actImg {
+		margin-top: .5rem;
+	}
+
+	.address {
+		width: 100%;
+		margin-top: 1rem;
+		text-align: left;
+	}
+
+	.contact {
+		margin-top: .5rem;
+		width: 100%;
+		margin-bottom: .5rem;
+		font-size: 14px;
+		color: #818489;
+	}
+
+	.cashier_priceNumber {
+		font-size: 14px;
+		margin-left: 1rem;
+	}
+
+	.dliver {
+		width: 100%;
+		height: .5rem;
+		background-color: #ecf1f4;
+	}
+
+	.goodsTitle {
+		margin-left: 1rem;
+		text-align: left;
+		font-size: 15px;
+		color: #595a5b;
+	}
+
+	.orderContent {
+		width: 100%;
+		display: flex;
+		justify-content: space-between;
+		flex-direction: row;
+		margin-top: .75rem;
+	}
+
+	.orderImg {
+		width: 4.25rem;
+		height: 4.25rem;
+		margin-left: 1rem;
+	}
+
+	.orderLeft {
+		margin-left: 1rem;
+		font-size: 13px;
+	}
+
+	.orderRight {
+		margin-right: 1rem;
+		font-size: 14px;
+		font-weight: 500;
+	}
+
+	.detail {
+		margin-left: 1rem;
+		margin-right: 1rem;
+		margin-top: .75rem;
+		margin-bottom: .75rem;
+		font-size: 13px;
+		display: flex;
+		flex-direction: column;
+		color: #818489;
+	}
+
+	.orderDetail {
+		display: flex;
+		flex-direction: column;
+		height: 4.25rem;
+		margin-left: .75rem;
+		margin-right: .75rem;
+		justify-content: space-between;
+		text-align: left;
+	}
+
+	.pTitle {
+		text-align: left;
+		font-size: 14px;
+		color: #595a5b;
+	}
+
+	.colorType {
+		text-align: left;
+		font-size: 12px;
+		color: #818489;
+	}
+
+	.payView {
+		display: flex;
+		flex-direction: row;
+		justify-content: space-between;
+	}
+
+	.payPrice {
+		font-size: 16px;
+		color: red;
+		text-align: left;
+	}
+
+	.stepper {
+		width: 5rem;
+		border-radius: .15rem;
+		background: white;
+		display: flex;
+		flex-direction: row;
+		height: 1rem;
+	}
+
+	/*加号和减号*/
+	.stepper .sign {
+		width: 2rem;
+		line-height: 1rem;
+		text-align: center;
+		float: left;
+	}
+
+	/*数值*/
+	.stepper .number {
+		width: 2.25rem;
+		height: 1rem;
+		float: left;
+		background-color: #ecf1f4;
+		margin: 0 auto;
+		text-align: center;
+		font-size: 15px;
+		color: #000000;
+	}
+
+	/*普通样式*/
+	.sign_normal {
+		color: black;
+		width: 1.5rem;
+		line-height: 1rem;
+		text-align: center;
+		float: left;
+	}
+
+	/*禁用样式*/
+	.sign_disabled {
+		color: #ccc;
+		width: 1.5rem;
+		line-height: 1rem;
+		text-align: center;
+		float: left;
+	}
+
+	.logo {
+		height: 5rem;
+		width: 5rem;
+		margin-top: 5rem;
+		margin-left: auto;
+		margin-right: auto;
+		margin-bottom: 1.25rem;
+	}
+
+	.text-area {
+		display: flex;
+		justify-content: center;
+	}
+
+	.title {
+		font-size: 18px;
+		color: #8f8f94;
+	}
+
+	.btnView {
+		width: 80%;
+		margin-top: 1.5rem;
+		height: 1.65rem;
+		display: flex;
+		line-height: 1.65rem;
+		color: #366092;
+		justify-content: center;
+		border: #1296db solid 1px;
+		border-radius: .5rem;
+	}
+
+	.cashier_footer {
+		position: fixed;
+		bottom: 0;
+		left: 0;
+		width: 100%;
+		z-index: 10;
+		text-align: center;
+		display: flex;
+		flex-direction: column;
+		align-items: center;
+		padding-bottom: .25rem;
+		background-color: #FFFFFF;
+	}
+
+	.cashier_payBtn {
+		width: 5.65rem;
+		height: 2.2rem;
+		background: rgb(133, 133, 133);
+		color: rgba(255, 255, 255, 0.85);
+		line-height: 2.2rem;
+		font-size: 16px;
+		cursor: pointer;
+	}
+
+	.footerPay {
+		width: calc(100vw - 2rem);
+		display: flex;
+		flex-direction: row;
+		align-items: center;
+		justify-content: space-between;
+		height: 2.2rem;
+		margin-bottom: 1rem;
+	}
+
+	.payPrice {
+		font-size: 12px;
+		color: red;
+		display: flex;
+		flex-direction: row;
+		align-items: center;
+		justify-content: flex-start;
+	}
+  .actionSheetWrap{
+    position: fixed;
+    top: 0;
+    left: 0;
+    z-index: 999;
+    width: 100%;
+    height: 100%;
+    background-color: rgba(0, 0, 0, 0.7);
+    display: none;
+  }
+  .popup{
+    position: fixed;
+    background-color: #ffffff;
+    bottom: 0;
+    left: 0;
+    width: 100%;
+    border-radius: .4rem .4rem 0 0;
+    display: flex;
+    -webkit-box-orient: vertical;
+    -webkit-box-direction: normal;
+    -webkit-flex-direction: column;
+    flex-direction: column;
+    overflow: hidden;
+    color: #323233;
+    z-index: 1000;
+    animation: up 0.5s ease;
+  }
+  @keyframes up{
+    from{
+      bottom: -10rem;
+    }
+    to{
+      bottom: 0;
+    }
+  }
+  .contentItem{
+    height: 3rem;
+    line-height: 3rem;
+    font-size: 14px;
+    background-color: #fff;
+    text-align: center;
+    color: #666;
+  }
+  .contentItem:nth-of-type(1){
+    border-bottom: 1px solid #f7f8fa;
+  }
+  .popupDivider{
+    height: .4rem;
+    background-color: #f7f8fa;
+  }
+</style>
+<script>
+  (function (WIN) {
+    var setFontSize = (WIN.setFontSize = function (_width) {
+      var docEl = document.documentElement;
+      // 获取当前窗口的宽度
+      var width = _width || docEl.clientWidth || docEl.getBoundingClientRect().width;
+
+      if (width > 420) {
+        width = 420;
+      }
+      // 在375px上,1rem = 20px
+      var rem = width / 18.75;
+
+      docEl.style.fontSize = rem + 'px';
+
+      // // 部分机型上的误差、兼容性处理
+      var actualSize =
+        WIN.getComputedStyle && parseFloat(WIN.getComputedStyle(docEl)['font-size']);
+      if (actualSize !== rem && actualSize > 0 && Math.abs(actualSize - rem) > 1) {
+        var remScaled = (rem * rem) / actualSize;
+        docEl.style.fontSize = rem + 'px';
+      }
+    });
+    var timer;
+    //函数节流
+    function dbcRefresh() {
+      clearTimeout(timer);
+      timer = setTimeout(setFontSize, 100);
+    }
+
+    //窗口更新动态改变 font-size
+    WIN.addEventListener('resize', dbcRefresh, false);
+    //页面显示时计算一次
+    WIN.addEventListener(
+      'pageshow',
+      function (e) {
+        if (e.persisted) {
+          dbcRefresh();
+        }
+      },
+      false
+    );
+    setFontSize();
+  })(window);
+</script>
+<script src="https://cdn.cloudpnr.com/opps/libs/jquery/jquery-2.1.2.min.js"></script>
+<script src="./util.js"></script>
+<body style="width: 100%;margin: 0px;">
+	<div class="content">
+		<div class="address"><span style="margin-left: 1rem;font-size: 16px;">上海市嘉定区红宝石路915弄41号1002</span></div>
+		<div class="contact">
+			<span class="cashier_priceNumber">王*华</span>
+			<span class="cashier_priceNumber">177****8846</span>
+		</div>
+		<div class="dliver"></div>
+
+		<div class="orderContent">
+			<div class="goodsTitle">无线鼠标</div>
+		</div>
+		<div class="orderContent" style="margin-bottom: .75rem;">
+			<img src="./img/mouse.png"
+				class="orderImg"></img>
+			<div class="orderDetail">
+				<div class="pTitle">无线鼠标静音无声笔记本台式电脑游戏</div>
+				<div class="colorType">银色</div>
+				<div class="payView">
+					<div class="payPrice">¥<span class="totalPrice">0.01</span></div>
+					<div class="stepper">
+						<!-- 减号 -->
+						<span class="sign_disabled" style="text-align:left" id="decreaseBtn">-</span>
+						<!-- 数值 -->
+						<span class="number" id="count">1</span>
+						<!-- 加号 -->
+						<span class="sign_normal" style="text-align: right;" id="addBtn">+</span>
+					</div>
+				</div>
+			</div>
+		</div>
+		<div class="dliver"></div>
+
+		<div class="orderContent">
+			<div class="orderLeft">商品金额</div>
+			<div class="orderRight">¥<span class="totalPrice">0.01</span></div>
+		</div>
+		<div class="orderContent" style="margin-bottom: .75rem;">
+			<div class="orderLeft">次日达(19:00前下单,预计明日24:00前送达)</div>
+			<div class="orderRight">¥<span  class="totalPrice">0.01</span> </div>
+		</div>
+		<div class="dliver"></div>
+		<div class="detail">
+			<span style="font-size: 13px;margin-bottom: .7rem;color: #000000;">买家须知</span>
+			<span style="margin-bottom: .7rem;">鼠标出厂前会进行相关质量测试,产品底部脚垫的保护膜上会留下细微痕迹,首次拆封后,移除保护膜即可正常使用。</span>
+			<span style="margin-bottom: .7rem;">适用于Windows 7/8/10、Mac OS X 10.8 或更高版本、Chrome OS 多种系统。</span>
+			<span style="margin-bottom: .7rem;">内部实验室测算数据,电池使用寿命依用户及计算条件而异。</span>
+			<span>提交订单即表示同意买家须知。</span>
+
+		</div>
+		<div class="cashier_footer">
+			<div class="dliver"
+				style="text-align: center;height:2.25rem ;font-size: 13px;color: #F5A478;align-items: center;display: flex;justify-content: center;margin-bottom: .75rem;">
+				本页面只用于演示收银台支付,不发货、不退款
+			</div>
+			<div class="footerPay">
+				<div class="payPrice">
+					实付款:¥<div style="font-size: 18px;font-weight: 600;" class="totalPrice">0.01</div>
+				</div>
+				<div id="cashierPayBtn" class="cashier_payBtn" style="background: #FEAD0B">立即购买</div>
+			</div>
+		</div>
+    <div class="actionSheetWrap" id="actionSheetWrap">
+      <div class="popup" id="popup">
+        <div class="contentItem" id="fullScreen">打开全屏收银台</div>
+        <div class="contentItem" id="halfScreen">弹出半屏收银台</div>
+        <div class="popupDivider"></div>
+        <div class="contentItem" id="cancelBtn">取消</div>
+      </div>
+    </div>
+	</div>
+</body>
+</html>
+<script>
+  $(function(){
+    function delCount() {
+			var num = document.getElementById('count').innerText;
+			// 商品总数量-1
+			if (num > 1) {
+				num--;
+				document.getElementById('addBtn').className = 'sign_normal'
+			}
+			// 将数值与状态写回
+			document.getElementById('count').innerText = num;
+			if (num === 1) {
+				document.getElementById('decreaseBtn').className = 'sign_disabled'
+			}
+      setTotalPrice(0.01 * num)
+		}
+
+		function addCount() {
+			console.log('刚刚您点击了加1');
+			var num = document.getElementById('count').innerText;
+			// 总数量-1
+			if (num < 10) {
+				num++;
+				document.getElementById('decreaseBtn').className = 'sign_normal'
+			}
+			document.getElementById('count').innerText = num;
+			if(num === 10) {
+				document.getElementById('addBtn').className = 'sign_disabled'
+			}
+      setTotalPrice(0.01 * num)
+		}
+    function setTotalPrice (totalPrice){
+      $('.totalPrice').each((ele,item)=>{
+        item.textContent = Number(totalPrice)
+        })
+    }
+		function gotoPay() {
+			var price =$('.totalPrice')[0].textContent
+			var origin = location.origin;
+      var pathname = location.pathname;
+      var urlAry = pathname.split('/');
+      urlAry.pop();
+      urlAry.push('cashier.html');
+      let urlStr = urlAry.join('/');
+      location.href = origin +''+ urlStr +'?price='+price;
+		}
+    var totalPrice = GetQueryString('price') || '0.01';
+    setTotalPrice(totalPrice)
+    $('#count').text( Number(totalPrice)*100 )
+    $('#addBtn').click(function(){
+      addCount()
+    })
+    $('#decreaseBtn').click(function(){
+      delCount()
+    })
+    $('#cashierPayBtn').click(function(){
+      gotoPay()
+    })
+  })
+
+</script>

+ 638 - 0
static/payDemo/pay.js

@@ -0,0 +1,638 @@
+/* eslint-disable */
+
+// h5调试
+var hostName = location.host;
+if (!(hostName.indexOf(configObj.productionEnvHost) > -1)) {
+	if (configObj.isDebug) {
+		new window.VConsole();
+	}
+}
+$(document).ready(function() {
+	// 解决移动端300ms延迟
+	FastClick.attach(document.body);
+	// 微信授权码
+	var code = '',
+		// 订单页面设置的金额
+		amount = GetQueryString('price'),
+		// 微信SDK的URL
+		wxPaySDKURL = 'https://res.wx.qq.com/open/js/jweixin-1.6.0.js',
+		// 支付宝SDK的URL
+		aliPaySDKURL =
+		'https://gw.alipayobjects.com/as/g/h5-lib/alipayjsapi/3.1.1/alipayjsapi.inc.min.js',
+		// 订单号
+		mer_ord_id =
+		localStorage.getItem('mer_ord_id') ||
+		dayjs().format('YYYYMMDDHHmmssSSS') + '' + randomNum(100, 999),
+		// 流水号
+		hf_seq_id = '',
+		// 轮训支付状态定时标识
+		timer = null,
+		// 银联授权码
+		userAuthCode = '',
+		// IP
+		client_ip = '',
+		// 银联userID
+		union_user_id = '',
+		// 银联授权码状态码
+		respCode = '',
+		// 倒计时时间
+		effectTime = configObj.mobile.payTime * 60,
+		pay_minute = '20',
+		pay_second = '00',
+		// 支付类型
+		tradeType = '';
+	// 埋点
+	MonitorMinSDK.init({
+		pid: 'dg-checkout',
+		appToken: 'app-226f04f1-f5ae-4ac3-b420-032b518cd0e9',
+		appKey: '24e67f6771036c5cd6225eebe1a99671',
+	});
+	const params = {
+		huifu_id: configObj.huifuId,
+		os: 'h5',
+		page: 'full'
+	};
+
+
+	MonitorMinSDK.track('0090_00006404', params, true);
+
+
+	// 订单倒计时,全屏幕版才会有倒计时
+	if ($('#pay_minute') && $('#pay_minute').length) {
+		startCountDown();
+	}
+	// 弹层收银台时,订单页面显示
+	if ($('#orderPage') && $('#orderPage').length) {
+		$('#priceOrder').text(amount);
+		$('#countOrder').text(amount * 100);
+	}
+	// 支付环境判断
+	payEnvHandle();
+	// 取消事件
+	$('#cashierCancelBtn').click(function() {
+		location.href = jumpLink('orderConfirm.html?price=' + amount);
+	});
+	// 支付点击事件
+	$('#pay-button').click(function() {
+		console.log('触发点击')
+		payType();
+	});
+	// 重新下单
+	$('#continuePayBtn').click(function() {
+		reOrder();
+	});
+
+	// 切换支付类型
+	var list = document.getElementsByTagName('li');
+	for (let i = 0; i < list.length; i++) {
+		list[i].onclick = function(e) {
+			$(`#${list[i].id} input`).prop('checked', false);
+			$(`#${e.target.id} input`).prop('checked', true);
+			if (e.target.id === 'huabeipayItem') {
+				tradeType = 'FQ_ALIPAY';
+			} else if (e.target.id === 'bankpayItem') {
+				tradeType = 'FQ_BANK';
+			}
+		};
+	}
+
+	// 上传标识
+	function uploadPayInfo() {
+		var params = {
+			product_id: configObj.productId,
+			sys_id: configObj.sysId,
+			data: {
+				//
+				huifu_id: configObj.huifuId,
+				resource: 'H5',
+				id_code: 'co',
+				action: 'CALL',
+				ref_req_date: dayjs().format('YYYYMMDD'), //YYYYMMDD
+				// 交易的订单号
+				ref_req_seqid: mer_ord_id, //orderID
+			},
+		};
+		axios.post(configObj.prodUploadPayAPI, params);
+	}
+	// 环境判断,加载不同支付选项
+	function payEnvHandle() {
+		if (isInWeiXinApp) {
+			loadPaySDK(wxPaySDKURL);
+			$('#wxpayItem').show();
+			$('#bankpayItem').show();
+			$('#wxpayInput').attr('checked', true);
+			code = GetQueryString('code');
+			let type = GetQueryString('type');
+			let state = GetQueryString('state');
+			if (!code) {
+				// url重定向带上当前金额
+				// 微信code获取
+				weixinAuth();
+			} else {
+				if (!localStorage.getItem('openid')) {
+					try {
+						// var paymentData = {
+						//   auth_code: code,
+						//   client_type: '1',
+						// };
+						var paymentData = {
+							type: type,
+							code: code,
+							state: state,
+						};
+						// 获取openid
+						service
+							.post(configObj.api.wxAuth, paymentData)
+							.then((res) => {
+								console.log('-log- ~weixin- data', res.data);
+								const {
+									openid
+								} = res.data;
+								if (res.data && openid) {
+									$('#pageLoadingMask').hide();
+									localStorage.setItem('openid', openid);
+								}
+							})
+							.catch((error) => {
+								console.log('-log- weixin~ error', error);
+								alert(error);
+							});
+					} catch (error) {
+						console.log('weixin---', error);
+					}
+				} else {
+					$('#pageLoadingMask').hide();
+				}
+			}
+			console.log('到此处了')
+		} else if (isInUnionApp) {
+			console.log('---union--env--');
+			$('#quickpasspayItem').show();
+			$('#bankpayItem').show();
+			$('#quickpasspayInput').attr('checked', true);
+			respCode = GetQueryString('respCode');
+			userAuthCode = GetQueryString('userAuthCode');
+			if (!respCode || respCode.length === 0) {
+				unionPayReady();
+			} else {
+				getUnionUserId(userAuthCode);
+			}
+		} else {
+			console.log('---alipay env---');
+			loadPaySDK(aliPaySDKURL);
+			$('#alipayItem').show();
+			$('#huabeipayItem').show();
+			$('#bankpayItem').show();
+			$('#alipayInput').attr('checked', true);
+			// 页面加载完,隐藏页面loading
+			$('#pageLoadingMask').hide();
+		}
+		console.log('yyyyyyyyyyyyy55555555555')
+	}
+
+	// 点击支付时,支付逻辑判断
+	function payType() {
+		// 银行卡分期 花呗分期
+		if (tradeType === 'FQ_BANK' || tradeType === 'FQ_ALIPAY') {
+			fenqiPay(tradeType);
+			return;
+		}
+		if (isInWeiXinApp) {
+			wxPay();
+		} else if (isInUnionApp) {
+			$('#loadingMask').show();
+			// 银联云闪付,需要传递用户IP
+			axios
+				.get('https://api.ipify.org/?format=json')
+				.then((res) => {
+					const {
+						data: ipInfo
+					} = res;
+					client_ip = ipInfo.ip;
+					unionPay();
+				})
+				.catch(() => {
+					client_ip = '172.31.19.51';
+					unionPay();
+				});
+		} else {
+			aliPay();
+		}
+	}
+
+	// 分期支付
+	function fenqiPay(tradeType) {
+		try {
+			let goods_desc =
+				tradeType == 'FQ_BANK' ? '银行卡分期测试商品-无线鼠标' : '花呗分期测试商品-无线鼠标';
+			var paymentCreateData = {
+				amount: amount,
+				trade_type: tradeType,
+				goods_desc,
+				extra_info: {
+					mer_ord_id,
+				},
+				user_id: '',
+			};
+			$('#loadingMask').show();
+			service
+				.post(configObj.createPayURL, paymentCreateData)
+				.then((res) => {
+					console.log('-log-alipay ~ res', res);
+					if (res && res.resp_code === '000000') {
+						const {
+							json_data
+						} = res;
+						if (json_data.req_seq_id) {
+							hf_seq_id = json_data.req_seq_id;
+							let payType = tradeType === 'FQ_BANK' ? 'unionpay' : 'alipay';
+							var url =
+								`https://hfenqi.cloudpnr.com/h5/qrcode/?huifuId=${configObj.huifuId}&productId=${configObj.productId}&reqSeqId=${json_data.req_seq_id}&payType=${payType}&transAmt=${amount}`;
+							window.location.href = url;
+						}
+					} else {
+						$('#loadingMask').hide();
+					}
+				})
+				.catch((error) => {
+					console.log('--fenqiPay--error--', error);
+					$('#loadingMask').hide();
+				});
+		} catch (error) {
+			console.log(error.toString());
+		}
+	}
+
+	// 支付方式-支付宝
+	function aliPay() {
+		try {
+			var paymentData = {
+				amount: amount,
+				trade_type: 'A_NATIVE',
+				goods_desc: '支付宝测试商品-无线鼠标',
+				extra_info: {
+					mer_ord_id,
+				},
+				user_id: '',
+			};
+			$('#loadingMask').show();
+			service
+				.post(configObj.api.createPay, paymentData)
+				.then((res) => {
+					console.log('-log-alipay ~ res', res);
+					// 下单成功上传凭证,获取对应奖励
+					uploadPayInfo();
+					const {
+						json_data,
+						pay_info
+					} = res;
+					if (res && res.resp_code === '000000') {
+						if (pay_info && json_data.hf_seq_id) {
+							hf_seq_id = json_data.hf_seq_id;
+							timer = setInterval(function() {
+								queryOrder(hf_seq_id);
+							}, 5000);
+							window.location.href =
+								'alipays://platformapi/startapp?saId=10000007&qrcode=' + pay_info;
+						} else {
+							alert(json_data.resp_desc);
+						}
+					} else {
+						$('#loadingMask').hide();
+					}
+				})
+				.catch((error) => {
+					console.log('--alipay--error--', error);
+					$('#loadingMask').hide();
+				});
+		} catch (error) {
+			console.log(error.toString());
+		}
+	}
+	// 支付方式-微信
+	function wxPay() {
+		$('#loadingMask').show();
+		try {
+			// 生成订单
+			// 当前页面取消支付,重新生成订单号
+			mer_ord_id = dayjs().format('YYYYMMDDHHmmssSSS') + '' + randomNum(100, 999);
+			localStorage.setItem('mer_ord_id', mer_ord_id);
+			var paymentData = {
+				amount: amount,
+				trade_type: 'T_JSAPI',
+				goods_desc: '微信测试商品-无线鼠标',
+				extra_info: {
+					mer_ord_id,
+				},
+				// 微信openID
+				user_id: localStorage.getItem('openid'),
+			};
+			service
+				.post(configObj.api.createPay, paymentData)
+				.then((res) => {
+					console.log('-log-wxPay ~ res', res);
+					const {
+						json_data
+					} = res;
+					// 下单成功上传凭证,获取对应奖励
+					uploadPayInfo();
+					if (json_data && json_data.pay_info && json_data.hf_seq_id) {
+						hf_seq_id = json_data.hf_seq_id;
+						let pay_info = JSON.parse(json_data.pay_info);
+						// JSAPI调起支付
+						if (typeof WeixinJSBridge == 'undefined') {
+							if (document.addEventListener) {
+								document.addEventListener('WeixinJSBridgeReady', onBridgeReady, false);
+							} else if (document.attachEvent) {
+								document.attachEvent('WeixinJSBridgeReady', onBridgeReady);
+								document.attachEvent('onWeixinJSBridgeReady', onBridgeReady);
+							}
+						} else {
+							onBridgeReady(pay_info, queryOrder, hf_seq_id);
+						}
+					}
+				})
+				.catch((error) => {
+					console.log('--weixinPay--error--', error);
+				});
+		} catch (error) {
+			$('#loadingMask').hide();
+			alert(error);
+			console.log(error.toString());
+		}
+	}
+	// 支付方式-云闪付
+	function unionPay() {
+		var paymentData = {
+			amount: amount,
+			trade_type: 'U_JSAPI',
+			goods_desc: '银联测试商品-无线鼠标',
+			extra_info: {
+				mer_ord_id,
+				user_id: union_user_id,
+			},
+			user_id: union_user_id,
+			client_ip,
+		};
+		console.log('-log- ~ paymentData', paymentData);
+		$('#loadingMask').show();
+		service
+			.post(configObj.api.createPay, paymentData)
+			.then((res) => {
+				console.log('-log-unionPay ~ res', res);
+				// 下单成功上传凭证,获取对应奖励
+				uploadPayInfo();
+				if (res && res.resp_code === '000000') {
+					$('#loadingMask').hide();
+					const {
+						pay_info
+					} = res;
+					console.log('-log- ~ pay_info', pay_info);
+					if (pay_info) {
+						window.location.href = pay_info;
+					}
+				} else {
+					$('#loadingMask').hide();
+				}
+			})
+			.catch((error) => {
+				$('#loadingMask').hide();
+				console.log('--unionPay--error--', error);
+			});
+	}
+	// 银联环境跳转
+	function unionPayReady() {
+		userAuthCode = GetQueryString('userAuthCode');
+		console.log('-log- unionPayReady~ userAuthCode', userAuthCode);
+		let urlNow = encodeURIComponent(window.location.href);
+		let url = 'https://qr.95516.com/qrcGtwWeb-web/api/userAuth?version=1.0.0&redirectUrl=' + urlNow;
+		window.location = url;
+	}
+	// 获取银联用户ID
+	function getUnionUserId(userAuthCode) {
+		// 隐藏page loading
+		$('#pageLoadingMask').show();
+		var params = {
+			auth_code: decodeURIComponent(userAuthCode),
+		};
+		console.log('-log- union-getUserId~ params', params);
+		service
+			.post(configObj.api.unionpayAuth, params)
+			.then((res) => {
+				console.log('-log- ~union-userInfo- data', res);
+				const {
+					jsonData,
+					resp_code,
+					json_data
+				} = res;
+				if (resp_code == '000000') {
+					$('#pageLoadingMask').hide();
+					if (jsonData && jsonData.user_id) {
+						union_user_id = jsonData.user_id;
+					} else if (json_data && json_data.user_id) {
+						union_user_id = json_data.user_id;
+					}
+				} else {
+					// alert(jsonData.return_desc);
+					$('#pageLoadingMask').hide();
+				}
+			})
+			.catch((error) => {
+				$('#pageLoadingMask').hide();
+				console.log('union--getUserId--error', error);
+				// alert(JSON.stringify(error));
+			});
+	}
+
+	// 拉起微信支付
+	function onBridgeReady(pay_info, callback, hf_seq_id) {
+		if (typeof WeixinJSBridge !== 'undefined') {
+			WeixinJSBridge.invoke(
+				'getBrandWCPayRequest', {
+					'appId': pay_info.appId, //appid
+					'timeStamp': pay_info.timeStamp, //时间戳,自1970年以来的秒数
+					'nonceStr': pay_info.nonceStr, //随机串
+					'package': pay_info.package,
+					'signType': pay_info.signType, //微信签名方式:
+					'paySign': pay_info.paySign, //微信签名
+				},
+				function(res) {
+					console.log('====>: onBridgeReady -> res', res);
+					if (res.err_msg == 'get_brand_wcpay_request:ok') {
+						// 使用以上方式判断前端返回,微信团队郑重提示:
+						//res.err_msg将在用户支付成功后返回ok,但并不保证它绝对可靠。
+						callback(hf_seq_id);
+					} else if (res.err_msg == 'get_brand_wcpay_request:cancel') {
+						$('#loadingMask').hide();
+						$('#cancelPay').show();
+						$('#continuePay').click(function() {
+							$('#cancelPay').hide();
+						});
+					} else {
+						callback(hf_seq_id);
+					}
+				}
+			);
+		} else {
+			console.log('不是在微信app内');
+		}
+	}
+	// 加载支付SDK
+	function loadPaySDK(url) {
+		return new Promise((resolve, reject) => {
+			let script = document.createElement('script');
+			script.type = 'text/javascript';
+			script.src = url;
+			script.onload = () => {
+				resolve(true);
+			};
+			script.onerror = reject;
+			document.head.appendChild(script);
+		});
+	}
+
+	// 支付成功
+	function paySuccess() {
+		location.href = jumpLink('paySuccess.html?price=' + amount);
+	}
+	// 支付失败
+	function payFail() {
+		location.href = jumpLink('payFail.html?price=' + amount);
+	}
+	// 查询订单详情
+	function queryOrder(hf_seq_id) {
+		var queryOrderData;
+		if (tradeType === 'FQ_ALIPAY') {
+			queryOrderData = {
+				org_req_seq_id: hf_seq_id,
+			};
+		} else {
+			queryOrderData = {
+				hf_seq_id,
+			};
+		}
+		service
+			.post(configObj.api.queryPay, queryOrderData)
+			.then((res) => {
+				console.log('-log-queryOrder ~ res', res);
+				const {
+					json_data,
+					resp_code
+				} = res;
+				if (json_data && (resp_code === '000000' || resp_code === '00000000')) {
+					if (json_data.trans_stat == 'S') {
+						// 支付成功
+						clearInterval(timer);
+						// 支付成功时间
+						localStorage.setItem('end_time', json_data.end_time);
+						$('#loadingMask').hide();
+						paySuccess();
+					} else if (json_data.trans_stat == 'F') {
+						// 支付失败
+						clearInterval(timer);
+						$('#loadingMask').hide();
+						payFail();
+					}
+				} else {
+					$('#loadingMask').hide();
+					clearInterval(timer);
+				}
+			})
+			.catch((error) => {
+				console.log('--queryOrder--error--', error);
+			});
+	}
+
+	// 查询 online 订单详情 针对分期支付订单
+	function queryOnlineOrder(hf_seq_id) {
+		var queryOrderData = {
+			org_req_seq_id: hf_seq_id,
+		};
+		service
+			.post(configObj.onlineQueryPayURL, queryOrderData)
+			.then((res) => {
+				console.log('-log-query OnlineOrder ~ res', res);
+				const {
+					json_data,
+					resp_code
+				} = res;
+				if (json_data && (resp_code === '000000' || resp_code === '00000000')) {
+					if (json_data.trans_stat == 'S') {
+						// 支付成功
+						clearInterval(timer);
+						// 支付成功时间
+						localStorage.setItem('end_time', json_data.end_time);
+						$('#loadingMask').hide();
+						paySuccess();
+					} else if (json_data.trans_stat == 'F') {
+						// 支付失败
+						clearInterval(timer);
+						$('#loadingMask').hide();
+						payFail();
+					}
+				}
+			})
+			.catch((error) => {
+				console.log('--query OnlineOrder--error--', error);
+			});
+	}
+
+
+	// 倒计时
+	function startCountDown() {
+		let count = 0;
+		const startTime = Date.now();
+		const fixed = () => {
+			count++;
+			effectTime -= 1;
+			if (effectTime < 0) return;
+			const offset = Date.now() - (startTime + count * 1000);
+			let nextTime = 1000 - offset;
+			if (nextTime < 0) nextTime = 0;
+			formatSeconds(effectTime);
+			timeoutRemind(effectTime);
+			setTimeout(fixed, nextTime);
+		};
+		setTimeout(fixed, 1000);
+	}
+
+	// 格式化时间
+	function formatSeconds(seconds) {
+		if (seconds < 0) return;
+		pay_minute = String((seconds / 60) % 60 | 0).padStart(2, '0');
+		pay_second = String(seconds % 60 | 0).padStart(2, '0');
+		document.getElementById('pay_minute').innerText = pay_minute;
+		document.getElementById('pay_second').innerText = pay_second;
+	}
+
+	// 超时提醒
+	function timeoutRemind(seconds) {
+		if (seconds <= 0) {
+			document.getElementById('timeoutRemind').classList.remove('hide');
+		}
+	}
+
+	// 重新下单
+	function reOrder() {
+		$('#timeoutRemind').hide();
+		const toUrl = jumpLink('goodsDetail.html');
+		if (history.replaceState) {
+			history.replaceState(null, document.title, toUrl);
+			history.go(0);
+		} else {
+			location.replace(toUrl);
+		}
+	}
+
+	// 跳转链接
+	function jumpLink(urlName) {
+		const origin = location.origin;
+		const pathname = location.pathname;
+		const urlAry = pathname.split('/');
+		urlAry.pop();
+		urlAry.push(urlName);
+		const urlStr = urlAry.join('/');
+		const link = origin + urlStr;
+		return link;
+	}
+});

+ 435 - 0
static/payDemo/payFail.html

@@ -0,0 +1,435 @@
+<!DOCTYPE html>
+<html lang="en">
+  <head>
+    <meta charset="UTF-8" />
+    <meta http-equiv="X-UA-Compatible" content="IE=edge" />
+    <meta
+      name="viewport"
+      content="width=device-width, initial-scale=1.0,maximum-scale=1.0, minimum-scale=1.0"
+    />
+    <title>支付结果</title>
+    <script>
+      (function (WIN) {
+        var setFontSize = (WIN.setFontSize = function (_width) {
+          var docEl = document.documentElement;
+          // 获取当前窗口的宽度
+          var width = _width || docEl.clientWidth || docEl.getBoundingClientRect().width;
+          if (width > 420) {
+            width = 420;
+          }
+          // 在375px上,1rem = 20px
+          var rem = width / 18.75;
+          docEl.style.fontSize = rem + 'px';
+          // 部分机型上的误差、兼容性处理
+          var actualSize =
+            WIN.getComputedStyle && parseFloat(WIN.getComputedStyle(docEl)['font-size']);
+          if (actualSize !== rem && actualSize > 0 && Math.abs(actualSize - rem) > 1) {
+            var remScaled = (rem * rem) / actualSize;
+            docEl.style.fontSize = rem + 'px';
+          }
+        });
+
+        var timer;
+        //函数节流
+        function dbcRefresh() {
+          clearTimeout(timer);
+          timer = setTimeout(setFontSize, 100);
+        }
+        //窗口更新动态改变 font-size
+        WIN.addEventListener('resize', dbcRefresh, false);
+        //页面显示时计算一次
+        WIN.addEventListener(
+          'pageshow',
+          function (e) {
+            if (e.persisted) {
+              dbcRefresh();
+            }
+          },
+          false
+        );
+        setFontSize();
+      })(window);
+    </script>
+    <script src="./util.js"></script>
+    <style>
+      @media only screen and (min-width: 400px) {
+        body {
+          font-size: 21.33333333px !important;
+        }
+      }
+
+      @media only screen and (min-width: 414px) {
+        body {
+          font-size: 21px !important;
+        }
+      }
+
+      @media only screen and (min-width: 480px) {
+        body {
+          font-size: 25.6px !important;
+        }
+      }
+
+      * {
+        padding: 0;
+        margin: 0;
+      }
+
+      body,
+      html {
+        height: 100%;
+        width: 100%;
+        background: #ffffff;
+      }
+
+      .h5Container {
+        width: 100%;
+        max-width: 18.75rem;
+        margin: 0 auto;
+        height: 100%;
+        left: 0;
+        right: 0;
+        top: 0;
+        bottom: 0;
+        text-align: center;
+        box-sizing: border-box;
+        font-size: 0.7rem;
+      }
+
+      .mb16 {
+        margin-bottom: 2rem;
+      }
+
+      .headerTitle {
+        padding-top: 2.7rem;
+        display: flex;
+        align-items: center;
+        justify-content: center;
+        font-size: 0.8rem;
+        font-weight: 500;
+        height: 2.2rem;
+        line-height: 2.2px;
+        color: rgba(0, 0, 0, 0.85);
+      }
+
+      .el-icon-close {
+        position: absolute;
+        left: 0.8rem;
+        top: 3rem;
+        width: 0.7rem;
+        height: 0.7rem;
+        opacity: 1;
+        color: rgba(0, 0, 0, 0.45);
+      }
+
+      .divider {
+        height: 1px;
+        background: rgba(0, 0, 0, 0.04);
+      }
+
+      .logo {
+        margin-bottom: 2rem;
+        padding-top: 4rem;
+        display: flex;
+        flex-direction: column;
+      }
+
+      .logoImg {
+        object-fit: contain;
+        height: 2.4rem;
+        margin-bottom: 1rem;
+      }
+
+      .failTip {
+        opacity: 1;
+        font-size: 0.8rem;
+        font-family: PingFangSC, PingFangSC-Semibold;
+        font-weight: 400;
+        text-align: center;
+        color: #e74e4e;
+        margin-bottom: 0.5rem;
+      }
+
+      .failInfo {
+        opacity: 1;
+        font-size: 0.7rem;
+        font-family: PingFangSC, PingFangSC-Regular;
+        font-weight: 400;
+        text-align: center;
+        color: #6c6e75;
+        line-height: 1.1rem;
+        letter-spacing: 1px;
+      }
+
+      .price {
+        color: #333333;
+      }
+
+      .priceNumber {
+        font-size: 1.2rem;
+        font-weight: 700;
+        margin-left: 0.2rem;
+        font-family: DINAlternate, DINAlternate-Bold;
+      }
+
+      .payTxt {
+        color: rgba(0, 0, 0, 0.65);
+        margin-right: 0.4rem;
+      }
+
+      .time {
+        color: rgba(0, 0, 0, 0.65);
+        font-weight: 500;
+      }
+
+      .timeItem {
+        background: rgba(0, 0, 0, 0.04);
+        border-radius: 0.1rem;
+        padding: 0.1rem;
+      }
+
+      .timeSplit {
+        margin: 0 0.2rem;
+      }
+
+      .order {
+        color: rgba(0, 0, 0, 0.65);
+        margin-bottom: 0.8rem;
+        margin-left: 1rem;
+        margin-right: 1rem;
+        text-align: left;
+        display: flex;
+        align-items: center;
+        justify-content: space-between;
+      }
+
+      .orderTxt {
+        opacity: 1;
+        font-size: 0.7rem;
+        font-family: MicrosoftYaHei, MicrosoftYaHei-Regular;
+        font-weight: 400;
+        text-align: right;
+        color: #22242e;
+      }
+
+      .orderTxt_l {
+        opacity: 1;
+        font-size: 0.7rem;
+        font-family: MicrosoftYaHei, MicrosoftYaHei-Regular;
+        font-weight: 400;
+        text-align: left;
+        color: #6c6e75;
+      }
+
+      .payType {
+        text-align: left;
+        box-sizing: border-box;
+      }
+
+      .checkout-list-item {
+        display: flex;
+        align-items: center;
+        padding: 0.75rem 0;
+        margin: 0 0.8rem;
+        border-bottom: 1px solid rgba(0, 0, 0, 0.04);
+        justify-content: space-between;
+      }
+
+      .checkout-list-item-inner {
+        display: flex;
+        align-items: center;
+      }
+
+      .checkout-payIcon {
+        margin-right: 0.8rem;
+      }
+
+      .checkout-pay-title {
+        margin-right: 0.75rem;
+      }
+
+      .checkout-recommend {
+        width: 2rem;
+        height: 1.2rem;
+        border: 1px solid var(--theme);
+        border-radius: 0.1rem;
+        color: var(--theme);
+        font-weight: 400;
+        font-size: 0.6rem;
+        line-height: 1.2rem;
+        text-align: center;
+      }
+
+      .checkout-list-item:last-of-type {
+        border-bottom: none;
+      }
+
+      .checkout-radio {
+        width: 0.8rem;
+        height: 0.8rem;
+        background-color: #ffffff;
+        border: solid 1px #dddddd;
+        -webkit-border-radius: 50%;
+        border-radius: 50%;
+        font-size: 0.7rem;
+        margin: 0;
+        padding: 0;
+        position: relative;
+        display: inline-block;
+        vertical-align: top;
+        cursor: default;
+        -webkit-appearance: none;
+        -webkit-user-select: none;
+        user-select: none;
+        -webkit-transition: background-color ease 0.1s;
+        transition: background-color ease 0.1s;
+      }
+
+      .checkout-radio:checked {
+        background-color: var(--theme);
+        border: solid 1px var(--theme);
+        text-align: center;
+        background-clip: padding-box;
+      }
+
+      .checkout-radio:checked:before,
+      .checkout-radio.checkout-checked:before,
+      .checkout-radio:checked:after,
+      .checkout-radio.checkout-checked:after {
+        content: '';
+        width: 0.4rem;
+        height: 0.25rem;
+        position: absolute;
+        top: 50%;
+        left: 50%;
+        margin-left: -0.2rem;
+        margin-top: -0.15rem;
+        background: transparent;
+        border: 1px solid #ffffff;
+        border-top: none;
+        border-right: none;
+        z-index: 2;
+        -webkit-border-radius: 0;
+        border-radius: 0;
+        -webkit-transform: rotate(-45deg);
+        transform: rotate(-45deg);
+      }
+
+      .title {
+        font-weight: 500;
+        padding: 0.8rem 0 0.8rem 0.8rem;
+      }
+
+      .payTxt {
+        margin: 0 0.8rem;
+      }
+
+      .footer {
+        position: absolute;
+        bottom: 1.7rem;
+        left: 0;
+        width: 100%;
+        z-index: 10;
+        text-align: center;
+        display: flex;
+        flex-direction: column;
+        align-items: center;
+        cursor: pointer;
+      }
+
+      .payBtn {
+        width: 18rem;
+        height: 2.5rem;
+        background: #5568d5;
+        border-radius: 0.2rem;
+        color: rgba(255, 255, 255, 0.85);
+        line-height: 2.5rem;
+        margin-bottom: 0.8rem;
+        border: none;
+        cursor: pointer;
+        appearance: none;
+      }
+
+      .brand {
+        display: flex;
+        align-items: center;
+        width: 100%;
+        justify-content: center;
+      }
+
+      .brandImg {
+        height: 1rem;
+        min-height: 0.8rem;
+        object-fit: contain;
+        margin-right: 0.3rem;
+      }
+
+      .brandtxt {
+        font-size: 0.6rem;
+        font-family: MicrosoftYaHei, MicrosoftYaHei-Regular;
+        font-weight: 400;
+        text-align: left;
+        color: #999999;
+      }
+    </style>
+  </head>
+
+  <body>
+    <div class="h5Container">
+      <div class="logo">
+        <img class="logoImg" src="img/fail1.png" alt="Logo" />
+        <div class="failTip">支付失败</div>
+        <div class="failInfo">订单超时自动关闭,请重新发起支付。</div>
+      </div>
+      <div class="price mb16">
+        <span>¥</span>
+        <span class="priceNumber" id="priceNumber">793.21</span>
+      </div>
+      <div class="order">
+        <span class="orderTxt">订单编号</span>
+        <span class="orderTxt" id="orderId">207084835060</span>
+      </div>
+      <div class="footer">
+        <div onClick="toHome()" style="background-color: #0B5AFE" class="payBtn">
+          返回商家
+        </div><div class="brand">
+          <img class="brandImg" src="img/defaultLogo.png" alt="logo" title="logo" />
+          <span class="brandtxt">提供技术支持</span>
+        </div></div>
+    </div>
+  </body>
+  <script src="https://cdn.cloudpnr.com/opps/libs/jquery/jquery-2.1.2.min.js"></script>
+  <script src="https://cdn.cloudpnr.com/opps/libs/dayjs/dayjs-1.10.4.min.js"></script>
+  <script src="./config/index.js"></script>
+  <script>
+    function toHome() {
+      var backHomeUrl = configObj.mobile.backHomeUrl;
+      location.href = backHomeUrl ? backHomeUrl : jumpLink('goodsDetail.html');
+    }
+    function jumpLink(urlName) {
+      const origin = location.origin;
+      const pathname = location.pathname;
+      const urlAry = pathname.split('/');
+      urlAry.pop();
+      urlAry.push(urlName);
+      const urlStr = urlAry.join('/');
+      const link = origin + urlStr;
+      return link;
+    }
+    window.addEventListener('load', () => {
+      const state = { title: 'init', url: '#' };
+      window.history.pushState(state, 'init', '#');
+    });
+    window.addEventListener('popstate', () => {
+      toHome();
+    });
+
+    $(function () {
+      var price = GetQueryString('price');
+      console.log('-log- ~ price', price);
+      var mer_ord_id = localStorage.getItem('mer_ord_id');
+      $('#priceNumber').text(price);
+      $('#orderId').text(mer_ord_id);
+    });
+  </script>
+</html>

+ 433 - 0
static/payDemo/paySuccess.html

@@ -0,0 +1,433 @@
+<!DOCTYPE html>
+<html lang="en">
+  <head>
+    <meta charset="UTF-8" />
+    <meta http-equiv="X-UA-Compatible" content="IE=edge" />
+    <meta
+      name="viewport"
+      content="width=device-width, initial-scale=1.0,maximum-scale=1.0, minimum-scale=1.0"
+    />
+    <title>支付结果</title>
+    <script>
+      (function (WIN) {
+        var setFontSize = (WIN.setFontSize = function (_width) {
+          var docEl = document.documentElement;
+          // 获取当前窗口的宽度
+          var width = _width || docEl.clientWidth || docEl.getBoundingClientRect().width;
+          if (width > 420) {
+            width = 420;
+          }
+          // 在375px上,1rem = 20px
+          var rem = width / 18.75;
+          docEl.style.fontSize = rem + 'px';
+          // 部分机型上的误差、兼容性处理
+          var actualSize =
+            WIN.getComputedStyle && parseFloat(WIN.getComputedStyle(docEl)['font-size']);
+          if (actualSize !== rem && actualSize > 0 && Math.abs(actualSize - rem) > 1) {
+            var remScaled = (rem * rem) / actualSize;
+            docEl.style.fontSize = rem + 'px';
+          }
+        });
+
+        var timer;
+        //函数节流
+        function dbcRefresh() {
+          clearTimeout(timer);
+          timer = setTimeout(setFontSize, 100);
+        }
+        //窗口更新动态改变 font-size
+        WIN.addEventListener('resize', dbcRefresh, false);
+        //页面显示时计算一次
+        WIN.addEventListener(
+          'pageshow',
+          function (e) {
+            if (e.persisted) {
+              dbcRefresh();
+            }
+          },
+          false
+        );
+        setFontSize();
+      })(window);
+    </script>
+    <script src="./util.js"></script>
+    <style>
+      @media only screen and (min-width: 400px) {
+        body {
+          font-size: 21.33333333px !important;
+        }
+      }
+
+      @media only screen and (min-width: 414px) {
+        body {
+          font-size: 21px !important;
+        }
+      }
+
+      @media only screen and (min-width: 480px) {
+        body {
+          font-size: 25.6px !important;
+        }
+      }
+
+      * {
+        padding: 0;
+        margin: 0;
+      }
+
+      body,
+      html {
+        height: 100%;
+        width: 100%;
+        background: #ffffff;
+      }
+
+      .h5Container {
+        width: 100%;
+        max-width: 18.75rem;
+        margin: 0 auto;
+        height: 100%;
+        left: 0;
+        right: 0;
+        top: 0;
+        bottom: 0;
+        text-align: center;
+        box-sizing: border-box;
+        font-size: 0.7rem;
+      }
+
+      .mb16 {
+        margin-bottom: 2rem;
+      }
+
+      .headerTitle {
+        padding-top: 2.7rem;
+        display: flex;
+        align-items: center;
+        justify-content: center;
+        font-size: 0.9rem;
+        font-weight: 500;
+        height: 2.2rem;
+        line-height: 2.2px;
+        color: #050505;
+      }
+
+      .el-icon-close {
+        position: absolute;
+        left: 0.8rem;
+        top: 3rem;
+        width: 0.7rem;
+        height: 0.7rem;
+        opacity: 1;
+        color: rgba(0, 0, 0, 0.45);
+      }
+
+      .divider {
+        height: 1px;
+        background: rgba(0, 0, 0, 0.04);
+      }
+
+      .logo {
+        margin-bottom: 1.5rem;
+        padding-top: 2rem;
+        display: flex;
+        flex-direction: column;
+      }
+
+      .logoImg {
+        object-fit: contain;
+        height: 2rem;
+        margin-bottom: 1rem;
+      }
+
+      .successTip {
+        height: 1.2rem;
+        opacity: 1;
+        font-size: 0.8rem;
+        font-family: PingFangSC, PingFangSC-Semibold;
+        font-weight: 600;
+        text-align: center;
+        color: #0b5afe;
+        line-height: 1.2rem;
+      }
+
+      .price {
+        font-size: 20px;
+        color: #333333;
+      }
+
+      .priceNumber {
+        font-size: 1.2rem;
+        font-weight: 700;
+        margin-left: 0.2rem;
+        font-family: DINAlternate, DINAlternate-Bold;
+      }
+
+      .payTxt {
+        color: rgba(0, 0, 0, 0.65);
+        margin-right: 0.4rem;
+      }
+
+      .time {
+        color: rgba(0, 0, 0, 0.65);
+        font-weight: 500;
+      }
+
+      .timeItem {
+        background: rgba(0, 0, 0, 0.04);
+        border-radius: 0.1rem;
+        padding: 0.1rem;
+      }
+
+      .timeSplit {
+        margin: 0 0.2rem;
+      }
+
+      .order {
+        color: rgba(0, 0, 0, 0.65);
+        margin-bottom: 0.8rem;
+        margin-left: 1.5rem;
+        margin-right: 1.5rem;
+        text-align: left;
+        display: flex;
+        align-items: center;
+        justify-content: space-between;
+      }
+
+      .orderTxt {
+        opacity: 1;
+        font-size: 0.7rem;
+        font-family: MicrosoftYaHei, MicrosoftYaHei-Regular;
+        font-weight: 400;
+        text-align: right;
+        color: #22242e;
+      }
+
+      .orderTxt_l {
+        opacity: 1;
+        font-size: 0.7rem;
+        font-family: MicrosoftYaHei, MicrosoftYaHei-Regular;
+        font-weight: 400;
+        text-align: left;
+        color: #6c6e75;
+      }
+
+      .payType {
+        text-align: left;
+        box-sizing: border-box;
+      }
+
+      .checkout-list-item {
+        display: flex;
+        align-items: center;
+        padding: 0.75rem 0;
+        margin: 0 0.8rem;
+        border-bottom: 1px solid rgba(0, 0, 0, 0.04);
+        justify-content: space-between;
+      }
+
+      .checkout-list-item-inner {
+        display: flex;
+        align-items: center;
+      }
+
+      .checkout-payIcon {
+        margin-right: 0.8rem;
+      }
+
+      .checkout-pay-title {
+        margin-right: 0.75rem;
+      }
+
+      .checkout-recommend {
+        width: 2rem;
+        height: 1.2rem;
+        border: 1px solid var(--theme);
+        border-radius: 0.1rem;
+        color: var(--theme);
+        font-weight: 400;
+        font-size: 0.6rem;
+        line-height: 1.2rem;
+        text-align: center;
+      }
+
+      .checkout-list-item:last-of-type {
+        border-bottom: none;
+      }
+
+      .checkout-radio {
+        width: 0.8rem;
+        height: 0.8rem;
+        background-color: #ffffff;
+        border: solid 1px #dddddd;
+        -webkit-border-radius: 50%;
+        border-radius: 50%;
+        font-size: 0.7rem;
+        margin: 0;
+        padding: 0;
+        position: relative;
+        display: inline-block;
+        vertical-align: top;
+        cursor: default;
+        -webkit-appearance: none;
+        -webkit-user-select: none;
+        user-select: none;
+        -webkit-transition: background-color ease 0.1s;
+        transition: background-color ease 0.1s;
+      }
+
+      .checkout-radio:checked {
+        background-color: var(--theme);
+        border: solid 1px var(--theme);
+        text-align: center;
+        background-clip: padding-box;
+      }
+
+      .checkout-radio:checked:before,
+      .checkout-radio.checkout-checked:before,
+      .checkout-radio:checked:after,
+      .checkout-radio.checkout-checked:after {
+        content: '';
+        width: 0.4rem;
+        height: 0.25rem;
+        position: absolute;
+        top: 50%;
+        left: 50%;
+        margin-left: -0.2rem;
+        margin-top: -0.15rem;
+        background: transparent;
+        border: 1px solid #ffffff;
+        border-top: none;
+        border-right: none;
+        z-index: 2;
+        -webkit-border-radius: 0;
+        border-radius: 0;
+        -webkit-transform: rotate(-45deg);
+        transform: rotate(-45deg);
+      }
+
+      .title {
+        font-weight: 500;
+        padding: 0.8rem 0 0.8rem 0.8rem;
+      }
+
+      .payTxt {
+        margin: 0 0.8rem;
+      }
+
+      .footer {
+        position: absolute;
+        bottom: 1.7rem;
+        left: 0;
+        width: 100%;
+        z-index: 10;
+        text-align: center;
+        display: flex;
+        flex-direction: column;
+        align-items: center;
+        cursor: pointer;
+      }
+
+      .payBtn {
+        width: 18rem;
+        height: 2.5rem;
+        background: #5568d5;
+        border-radius: 0.2rem;
+        color: rgba(255, 255, 255, 0.85);
+        line-height: 2.5rem;
+        margin-bottom: 0.8rem;
+        border: none;
+        cursor: pointer;
+        appearance: none;
+      }
+
+      .brand {
+        display: flex;
+        align-items: center;
+        width: 100%;
+        justify-content: center;
+      }
+
+      .brandImg {
+        height: 1rem;
+        min-height: 0.8rem;
+        object-fit: contain;
+        margin-right: 0.3rem;
+      }
+
+      .brandtxt {
+        font-size: 0.6rem;
+        color: rgba(0, 0, 0, 0.45);
+      }
+    </style>
+  </head>
+
+  <body>
+    <div class="h5Container">
+      <div class="logo">
+        <img class="logoImg" src="img/success1.png" alt="Logo" />
+        <div class="successTip">支付成功</div>
+      </div>
+      <div class="price mb16">
+        <span>¥</span>
+        <span class="priceNumber" id="priceNumber">793.21</span>
+      </div>
+      <div class="order">
+        <span class="orderTxt">订单编号</span>
+        <span class="orderTxt" id="orderId">207084835060</span>
+      </div>
+      <div class="order">
+        <span class="orderTxt">支付时间</span>
+        <span class="orderTxt" id="payTime">2021-06-25 11:21</span>
+      </div>
+      <div class="order">
+        <span class="orderTxt">支付方式</span>
+        <span class="orderTxt" id="payType">微信支付</span>
+      </div>
+      <div class="footer">
+        <div onClick="toHome()" style="background-color: #0B5AFE" class="payBtn">
+          返回商家
+        </div><div class="brand">
+          <img class="brandImg" src="img/defaultLogo.png" alt="logo" title="logo" />
+          <span class="brandtxt">提供技术支持</span>
+        </div></div>
+    </div>
+  </body>
+  <script src="https://cdn.cloudpnr.com/opps/libs/jquery/jquery-2.1.2.min.js"></script>
+  <script src="https://cdn.cloudpnr.com/opps/libs/dayjs/dayjs-1.10.4.min.js"></script>
+  <script src="./config/index.js"></script>
+  <script>
+    function toHome() {
+      var backHomeUrl = configObj.mobile.backHomeUrl;
+      location.href = backHomeUrl ? backHomeUrl : jumpLink('goodsDetail.html');
+    }
+    function jumpLink(urlName) {
+      const origin = location.origin;
+      const pathname = location.pathname;
+      const urlAry = pathname.split('/');
+      urlAry.pop();
+      urlAry.push(urlName);
+      const urlStr = urlAry.join('/');
+      const link = origin + urlStr;
+      return link;
+    }
+    window.addEventListener('load', () => {
+      const state = { title: 'init', url: '#' };
+      window.history.pushState(state, 'init', '#');
+    });
+    window.addEventListener('popstate', () => {
+      toHome();
+    });
+
+    $(function () {
+      var price = GetQueryString('price');
+      var mer_ord_id = localStorage.getItem('mer_ord_id');
+      var payTime = dayjs(localStorage.getItem('end_time')).format('YYYY-MM-DD HH:mm:ss');
+      $('#priceNumber').text(price);
+      $('#orderId').text(mer_ord_id);
+      $('#payTime').text(payTime);
+      var payTypeText = isInWeiXinApp ? '微信支付' : isInUnionApp ? '云闪付' : '支付宝';
+      $('#payType').text(payTypeText);
+    });
+  </script>
+</html>

+ 126 - 0
static/payDemo/util.js

@@ -0,0 +1,126 @@
+/*eslint-disable*/
+// 获取URL中参数值
+function GetQueryString(name) {
+  var reg = new RegExp('(^|&)' + name + '=([^&]*)(&|$)');
+  var r = window.location.search.substr(1).match(reg);
+  if (r != null) return decodeURI(r[2]);
+  return null;
+}
+function deepClone(source) {
+  if (!source && typeof source !== 'object') {
+    throw new Error('error arguments', 'deepClone');
+  }
+  const targetObj = source.constructor === Array ? [] : {};
+  Object.keys(source).forEach((keys) => {
+    if (source[keys] && typeof source[keys] === 'object') {
+      targetObj[keys] = deepClone(source[keys]);
+    } else {
+      targetObj[keys] = source[keys];
+    }
+  });
+  return targetObj;
+}
+
+// 微信授权
+function weixinAuth() {
+  let urlNow = encodeURIComponent(window.location.href);
+  let scope = 'snsapi_base'; //snsapi_userinfo   //静默授权 用户无感知
+  let appid = configObj.mobile.wxConfig.appid;
+  console.log(urlNow,'进行微信授权')
+  let url = `https://open.weixin.qq.com/connect/oauth2/authorize?appid=${appid}&redirect_uri=${urlNow}&response_type=code&scope=${scope}&state=STATE&connect_redirect=1#wechat_redirect`;
+   console.log(url,'授权地址')
+  window.location.replace(url);
+}
+// 银联授权
+function unionAuth() {
+  let urlNow = encodeURIComponent(window.location.href);
+  let url = 'https://qr.95516.com/qrcGtwWeb-web/api/userAuth?version=1.0.0&redirectUrl=' + urlNow;
+  window.location.replace(url);
+}
+var isInWeiXinApp = window.navigator.userAgent.toLowerCase().search(/MicroMessenger/i) > -1;
+var isInAliPayApp = window.navigator.userAgent.toLowerCase().search(/AlipayClient/i) > -1;
+var isInUnionApp = window.navigator.userAgent.toLowerCase().search(/CloudPay/i) > -1;
+//生成自定义位数随机数
+function randomNum(minNum, maxNum) {
+  switch (arguments.length) {
+    case 1:
+      return parseInt(Math.random() * minNum + 1);
+    case 2:
+      return parseInt(Math.random() * (maxNum - minNum + 1) + minNum);
+    default:
+      return 0;
+  }
+}
+// 支付状态
+var mods = {};
+// 支付渠道
+// alipay_wap: 支付宝H5支付
+// wx_pub: 微信H5支付
+mods.channelConfig = {
+  alipay_qr: 'alipay_qr',
+  alipay_wap: 'alipay_wap',
+  wx_pub: 'wx_pub',
+};
+
+// payment参数校验结果
+mods.chackMsg = {
+  orderError: '发起支付失败',
+  channelError: '支付渠道参数错误',
+  amountError: '支付金额参数错误',
+  queryUrlError: '支付结果url参数未知',
+};
+
+// 支付状态值
+mods.payStatus = {
+  succeeded: 'succeeded',
+  failed: 'failed',
+  pending: 'pending',
+  timeout: 'timeout',
+  cancel: 'unknown',
+  unknown: 'unknown',
+  paramError: 'paramError',
+};
+// 支付结果对象
+mods.payResult = {
+  succeeded: {
+    result_status: mods.payStatus.succeeded,
+    result_message: '订单支付成功',
+    result_info: {},
+  },
+
+  failed: {
+    result_status: mods.payStatus.failed,
+    result_message: '订单支付失败',
+    result_info: {},
+  },
+
+  pending: {
+    result_status: mods.payStatus.pending,
+    result_message: '订单支付中',
+    result_info: {},
+  },
+
+  timeout: {
+    result_status: mods.payStatus.timeout,
+    result_message: '订单支付超时',
+    result_info: {},
+  },
+
+  cancel: {
+    result_status: mods.payStatus.cancel,
+    result_message: '支付取消',
+    result_info: {},
+  },
+
+  unknown: {
+    result_status: mods.payStatus.unknown,
+    result_message: '订单结果未知',
+    result_info: {},
+  },
+
+  paramError: {
+    result_status: mods.payStatus.paramError,
+    result_message: '参数错误',
+    result_info: {},
+  },
+};