@@ -1,9 +1,9 @@ | |||
<!-- | |||
* @Date: 2022-01-19 10:08:58 | |||
* @LastEditors: JinxChen | |||
* @LastEditTime: 2022-02-25 15:28:25 | |||
* @LastEditTime: 2022-03-04 15:52:30 | |||
* @FilePath: \AntpayFrontEnd\README.md | |||
* @description: readme说明文档 | |||
* @description: 项目说明文档 | |||
--> | |||
# alipay-scan-code-front-end | |||
## 项目说明 | |||
@@ -23,10 +23,27 @@ npm run dev | |||
npm run build | |||
``` | |||
### 项目本地调试 | |||
``` | |||
运行成功后 本地调试首次进入会进入到 http://localhost:8080/#/404 404页面 | |||
因为当前url还没有参数, 此时需要手动在url后面添加需要的参数, | |||
例子: http://localhost:8080/#/index?goodsNo=889&userId=1 | |||
其中 goodsNo是商品的no, userId是用户的id, 这两个参数后面接口都会用到 | |||
以上在线上环境不需要配置,因为二维码会自动把这两个参数添加上去 | |||
``` | |||
### 项目代码编写规范(暂时想到这些,后面根据项目情况补充说明) | |||
- css类名: 小写驼峰 中间用 - 隔开 | |||
- js函数方法: 开头小写后面开头大写驼峰 | |||
- .vue 文件命名: 统一大写驼峰 | |||
- 常量命名: 全部大写 以_拼接, 具体例子见: /src/config/models下的文件 | |||
### 项目分支管理 | |||
- master: 不可在此分支做任何修改, 只能合并develop分支, git merge --no-ff develop ; 且部署上线时对应production环境,不可混肴 | |||
- develop: 平时开发使用此分支, 需另开分支并说明是做什么的, 比如fix bug, git checkout -b fix-xxxx, 开发完成自测无问题后合并到develop分支, | |||
- test: 如不必要不在此分支做任何修改, 合并develpo分支, git merge --no-ff develop ; 部署上线时对应test环境,不可混肴 | |||
### git 提交规范 | |||
- feature 新增一个功能 | |||
@@ -43,14 +60,30 @@ npm run build | |||
。 | |||
### 版本控制以及版本迭代说明 | |||
### v1.0.0 | |||
`2022.02.23` | |||
build | |||
- 初版发布 | |||
- 完成 项目搭建 | |||
- 完成 项目迁移 从documentFrontEndWeb 到 AlipayFrontendWeb | |||
- 完成 项目迁移 从documentFrontEndWeb 到 AntpayFrontEnd | |||
- 增加 docker部署脚本 | |||
- 增加 环境设置脚本 | |||
- 增加 nginx.conf文件 | |||
fix | |||
- 修复 路由history模式原因引起的页面空白的问题 | |||
- 修复 路由history模式原因引起的页面空白的问题 | |||
### v1.0.1 | |||
`2022.02.25` | |||
feature | |||
- 增加 非支付宝浏览环境下扫码切换支付宝弹窗提示 | |||
- 增加 android和ios设备支付宝下载链接 | |||
- 增加 android设备复制粘贴下载链接功能 | |||
### v1.0.2 | |||
`2022.03.04` | |||
feature | |||
- 增加 春雨个性化定制 '@/views/chunyu/AliPayForm' | |||
- 增加 Checkbox 组件, '@/components/checkbox' | |||
- 增加 AgreementDialog 组件, '@/components/AgreementDialog' |
@@ -2,9 +2,9 @@ | |||
### | |||
# @Date: 2021-11-15 09:37:49 | |||
# @LastEditors: JinxChen | |||
# @LastEditTime: 2022-02-25 11:36:46 | |||
# @LastEditTime: 2022-03-04 10:47:47 | |||
# @FilePath: \AntpayFrontEnd\antpay_frontend_web_run.sh | |||
# @description: docker部署脚本 | |||
# @description: docker部署脚本, 根据项目具体情况来 修改 docker run -p 8804:80 | |||
### | |||
environment=$1 | |||
version=$2 | |||
@@ -5,8 +5,10 @@ | |||
"requires": true, | |||
"packages": { | |||
"": { | |||
"name": "alipay-scan-code-front-end", | |||
"version": "0.1.0", | |||
"dependencies": { | |||
"@vant/area-data": "^1.2.2", | |||
"axios": "^0.26.0", | |||
"core-js": "^3.6.5", | |||
"nprogress": "^0.2.0", | |||
@@ -2492,6 +2494,11 @@ | |||
"integrity": "sha512-7tFImggNeNBVMsn0vLrpn1H1uPrUBdnARPTpZoitY37ZrdJREzf7I16tMrlK3hen349gr1NYh8CmZQa7CTG6Aw==", | |||
"dev": true | |||
}, | |||
"node_modules/@vant/area-data": { | |||
"version": "1.2.2", | |||
"resolved": "https://registry.npmjs.org/@vant/area-data/-/area-data-1.2.2.tgz", | |||
"integrity": "sha512-efv7Yl/OTHjyy0irhJJPtgZb5mJZmroEtVOa8vkGRNTLY93+NgEcVuIBaC35hYCMsTrPHDQRvQGnI9Hyhtto0Q==" | |||
}, | |||
"node_modules/@vant/icons": { | |||
"version": "1.7.3", | |||
"resolved": "https://registry.npmjs.org/@vant/icons/-/icons-1.7.3.tgz", | |||
@@ -21439,6 +21446,11 @@ | |||
"integrity": "sha512-7tFImggNeNBVMsn0vLrpn1H1uPrUBdnARPTpZoitY37ZrdJREzf7I16tMrlK3hen349gr1NYh8CmZQa7CTG6Aw==", | |||
"dev": true | |||
}, | |||
"@vant/area-data": { | |||
"version": "1.2.2", | |||
"resolved": "https://registry.npmjs.org/@vant/area-data/-/area-data-1.2.2.tgz", | |||
"integrity": "sha512-efv7Yl/OTHjyy0irhJJPtgZb5mJZmroEtVOa8vkGRNTLY93+NgEcVuIBaC35hYCMsTrPHDQRvQGnI9Hyhtto0Q==" | |||
}, | |||
"@vant/icons": { | |||
"version": "1.7.3", | |||
"resolved": "https://registry.npmjs.org/@vant/icons/-/icons-1.7.3.tgz", | |||
@@ -12,6 +12,7 @@ | |||
"test:unit": "vue-cli-service test:unit" | |||
}, | |||
"dependencies": { | |||
"@vant/area-data": "^1.2.2", | |||
"axios": "^0.26.0", | |||
"core-js": "^3.6.5", | |||
"nprogress": "^0.2.0", | |||
@@ -1,8 +1,8 @@ | |||
<!-- | |||
* @Date: 2022-01-19 10:08:26 | |||
* @LastEditors: JinxChen | |||
* @LastEditTime: 2022-02-23 17:23:45 | |||
* @FilePath: \AlipayFrontEnd\src\App.vue | |||
* @LastEditTime: 2022-02-25 16:45:37 | |||
* @FilePath: \AntpayFrontEnd\src\App.vue | |||
* @description: | |||
--> | |||
<template> | |||
@@ -12,7 +12,7 @@ | |||
</template> | |||
<script> | |||
import { VersionModel } from './config/models'; | |||
import { VERSION_MODEL } from './config/models'; | |||
export default { | |||
provide() { | |||
return { | |||
@@ -25,7 +25,7 @@ export default { | |||
} | |||
}, | |||
mounted() { | |||
console.log("当前版本号::", VersionModel, "当前环境::", process.env.NODE_ENV); | |||
console.log("当前版本号::", VERSION_MODEL, "当前环境::", process.env.NODE_ENV); | |||
}, | |||
methods: { | |||
reload() { | |||
@@ -1,9 +1,9 @@ | |||
/* | |||
* @Date: 2022-02-14 15:18:50 | |||
* @LastEditors: JinxChen | |||
* @LastEditTime: 2022-02-14 15:21:05 | |||
* @FilePath: \alipay-scan-code-front-end\src\api\goods.js | |||
* @description: | |||
* @LastEditTime: 2022-03-04 10:50:22 | |||
* @FilePath: \AntpayFrontEnd\src\api\alipay.js | |||
* @description: axios封装 | |||
*/ | |||
import request from '../http/request'; | |||
@@ -0,0 +1,144 @@ | |||
<!-- | |||
* @Date: 2022-02-26 16:40:02 | |||
* @LastEditors: JinxChen | |||
* @LastEditTime: 2022-02-28 17:00:19 | |||
* @FilePath: \AntpayFrontEnd\src\components\AgreementDialog.vue | |||
* @description: 协议弹窗组件 | |||
--> | |||
<template> | |||
<div> | |||
<van-dialog | |||
class="agreement-container" | |||
v-model="show" | |||
:title="title" | |||
confirm-button-color="#1989fa" | |||
:show-confirm-button="false" | |||
> | |||
<div class="agreement-content"> | |||
<h5>一.开通需知及承诺</h5> | |||
<p v-show="isNewCustom">1.感谢用户使用支付宝花呗分期功能。</p> | |||
<p v-show="isNewCustom"> | |||
2.用户自愿开通4G电子学生证资费套餐服务({{count}} | |||
<!-- 24 --> | |||
期)每月自动通过支付宝花呗分期支付资费(话费+流量)套餐费{{(price/count).toFixed(2)}}元/月。 | |||
</p> | |||
<p v-show="isNewCustom">3.用户需连续使用该资费套餐24期,可据此领取4G电子学生证1台、电话卡1张。</p> | |||
<p style="white-space: pre-wrap"> | |||
<span v-show="isNewCustom">4.</span> | |||
{{description}} | |||
</p> | |||
<p v-show="isOldCustom">5.协议期内,电子学生证非人为损坏或进水按“三包”政策进行免费维修或更换。如丢失或人为损坏,按优惠价重新购买。</p> | |||
<p v-show="isOldCustom">6.北京随手精灵科技有限公司接受电子学生证运营销售商委托采用支付宝花呗分期付代收业务货款。</p> | |||
<h5>二.用户承诺</h5> | |||
<p>1.用户已充分了解支付宝花呗付款条款(含支付宝花呗相关规则),充分阅读及理解本协议。</p> | |||
<p>2.用户已经签署业务订购回执,自愿购买并同意签署本协议。</p> | |||
<h5>三.法律适用与管辖</h5> | |||
<p>本协议之效力、解释、变更、执行与争议解决均适用中华人民共和国法律。因本协议产生的争议,均应依照中华人民共和国法律予以处理。</p> | |||
<p v-show="!isButtonShow">{{countDown}}秒后显示按钮</p> | |||
<div class="agreement-button" v-show="isButtonShow"> | |||
<van-button type="warning" @click="onDisAgree" round>不同意</van-button> | |||
<van-button type="info" @click="onAgree" round>同意</van-button> | |||
</div> | |||
</div> | |||
</van-dialog> | |||
</div> | |||
</template> | |||
<script> | |||
export default { | |||
name:'agreement-dialog', | |||
props: { | |||
show: { | |||
default: true, | |||
type: Boolean | |||
}, | |||
title: { | |||
default: '', | |||
type: String | |||
}, | |||
isNewCustom: { | |||
default: true, | |||
type: Boolean | |||
}, | |||
isOldCustom: { | |||
default: false, | |||
type: Boolean | |||
}, | |||
count: { | |||
default: null, | |||
type: Number | |||
}, | |||
price: { | |||
default: null, | |||
type: Number | |||
}, | |||
description: { | |||
default: '', | |||
type: String | |||
}, | |||
countDown: { | |||
default: 3, | |||
type: Number | |||
}, | |||
isButtonShow: { | |||
default: false, | |||
type: Boolean | |||
}, | |||
}, | |||
data(){ | |||
return { | |||
} | |||
}, | |||
methods: { | |||
// 不同意 | |||
onDisAgree() { | |||
this.$bus.$emit('getCheckStatus', false); | |||
this.$bus.$emit('closeButton', false); | |||
this.resetCountDown(); | |||
}, | |||
// 同意 | |||
onAgree() { | |||
this.$bus.$emit('getCheckStatus', true); | |||
this.$bus.$emit('closeButton', false); | |||
this.resetCountDown(); | |||
}, | |||
// 重置倒计时和关闭弹窗 | |||
resetCountDown() { | |||
this.countDown = 3; | |||
}, | |||
} | |||
} | |||
</script> | |||
<style scoped lang="scss"> | |||
.agreement-container { | |||
.agreement-content { | |||
height: 500px; | |||
padding: 5px 10px; | |||
border-top: 0.5px soild; | |||
border-bottom: 0.5px soild; | |||
text-align: left; | |||
overflow: scroll; | |||
h5 { | |||
padding: 5px; | |||
} | |||
p { | |||
padding: 5px; | |||
font-size: 14px; | |||
line-height: 20px; | |||
} | |||
.agreement-button { | |||
padding: 10px; | |||
display: flex; | |||
justify-content: space-around; | |||
align-items: center; | |||
.van-button { | |||
height: 30px; | |||
width: 120px; | |||
border-radius: 10px; | |||
} | |||
} | |||
} | |||
} | |||
</style> |
@@ -0,0 +1,76 @@ | |||
<!-- | |||
* @Date: 2022-02-26 09:26:04 | |||
* @LastEditors: JinxChen | |||
* @LastEditTime: 2022-03-04 11:40:00 | |||
* @FilePath: \AntpayFrontEnd\src\components\Checkbox.vue | |||
* @description: 单选框组件 | |||
--> | |||
<template> | |||
<div class="checkbox-container"> | |||
<van-checkbox v-model="checked" shape="square" @change="onCheckChange"> | |||
<strong >已阅读协议并确认</strong> | |||
</van-checkbox> | |||
</div> | |||
</template> | |||
<script> | |||
export default { | |||
name:'checkbox', | |||
mounted() { | |||
this.getDialogData(); | |||
}, | |||
data(){ | |||
return { | |||
checked: false, | |||
} | |||
}, | |||
methods: { | |||
// 获取从dialog组件传过来的参数 | |||
getDialogData() { | |||
this.$bus.$on('getCheckStatus', (data) => { | |||
this.checked = data; | |||
}) | |||
}, | |||
// 单选框值发生变化时 | |||
onCheckChange(value) { | |||
this.checked = value; | |||
this.$emit('SendCheckStatus', value); | |||
}, | |||
} | |||
} | |||
</script> | |||
<style scoped lang="scss"> | |||
.checkbox-container { | |||
margin: 5px 0; | |||
.agreement-container { | |||
.agreement-content { | |||
height: 500px; | |||
padding: 5px 10px; | |||
border-top: 0.5px soild; | |||
border-bottom: 0.5px soild; | |||
text-align: left; | |||
overflow: scroll; | |||
h5 { | |||
padding: 5px; | |||
} | |||
p { | |||
padding: 5px; | |||
font-size: 14px; | |||
line-height: 20px; | |||
} | |||
.agreement-button { | |||
padding: 10px; | |||
display: flex; | |||
justify-content: space-around; | |||
align-items: center; | |||
.van-button { | |||
height: 30px; | |||
width: 120px; | |||
border-radius: 10px; | |||
} | |||
} | |||
} | |||
} | |||
} | |||
</style> |
@@ -0,0 +1,13 @@ | |||
/* | |||
* @Date: 2022-02-26 15:09:25 | |||
* @LastEditors: JinxChen | |||
* @LastEditTime: 2022-03-04 10:58:12 | |||
* @FilePath: \AntpayFrontEnd\src\config\customize.js | |||
* @description: 个性化定制, 根据不同的商家定制个性化的界面 | |||
* 注意: 后期可以根据接口来实现 | |||
*/ | |||
import store from '../store/index'; | |||
export const CUSTOMIZE_SERVICE = { | |||
isChunyu:() => store.getters.goodsNo === 889, | |||
}; |
@@ -1,13 +1,21 @@ | |||
/* | |||
* @Date: 2021-11-20 10:26:39 | |||
* @LastEditors: JinxChen | |||
* @LastEditTime: 2022-02-23 17:36:43 | |||
* @FilePath: \AlipayFrontEnd\src\config\models.js | |||
* @LastEditTime: 2022-03-04 11:38:20 | |||
* @FilePath: \AntpayFrontEnd\src\config\models.js | |||
* @description: | |||
*/ | |||
export const VersionModel = '1.0.0'; | |||
export const ImageUrl = { | |||
export const VERSION_MODEL = '1.0.2'; //版本号 | |||
export const IMAGE_URL = { | |||
production: 'http://zfb.ssjlai.com/web/', | |||
test: 'http://zfb.ssjlai.com/web/', | |||
development: 'http://zfb.ssjlai.com/web/' | |||
}; | |||
//用户设备 | |||
export const USER_AGENT = window.navigator.userAgent; | |||
// 支付宝下载链接 | |||
export const ALIPAY_DOWN_URL = { | |||
android: 'https://d.alipay.com', | |||
ios: 'https://itunes.apple.com/cn/app/zhi-fu-bao-qian-bao-yu-e-bao/id333206289?mt=8' | |||
}; |
@@ -1,8 +1,8 @@ | |||
/* | |||
* @Date: 2022-01-19 10:08:26 | |||
* @LastEditors: JinxChen | |||
* @LastEditTime: 2022-02-15 17:22:45 | |||
* @FilePath: \alipay-scan-code-front-end\src\main.js | |||
* @LastEditTime: 2022-03-04 15:00:32 | |||
* @FilePath: \AntpayFrontEnd\src\main.js | |||
* @description: | |||
*/ | |||
import Vue from "vue"; | |||
@@ -33,7 +33,12 @@ import { | |||
Empty, | |||
Notify, | |||
Loading, | |||
} from 'vant'; | |||
Toast, | |||
Popup, | |||
Area, | |||
Cascader, | |||
Picker, | |||
} from 'vant'; //按需加载vant组件 | |||
Vue | |||
.use(Button) | |||
@@ -57,10 +62,15 @@ Vue | |||
.use(Empty) | |||
.use(Notify) | |||
.use(Loading) | |||
.use(Toast) | |||
.use(Area) | |||
.use(Popup) | |||
.use(Picker) | |||
.use(Cascader) | |||
.use(Tabs); | |||
Vue.config.productionTip = false; | |||
Vue.prototype.$bus = new Vue(); | |||
new Vue({ | |||
router, | |||
store, | |||
@@ -1,7 +1,7 @@ | |||
/* | |||
* @Date: 2022-01-19 10:08:26 | |||
* @LastEditors: JinxChen | |||
* @LastEditTime: 2022-02-25 15:26:05 | |||
* @LastEditTime: 2022-02-28 09:47:42 | |||
* @FilePath: \AntpayFrontEnd\src\router\index.js | |||
* @description: | |||
*/ | |||
@@ -19,6 +19,10 @@ const routes = [ | |||
{ path: '/redirect', name: 'redirect', component: resolve => require(['@/views/AliPayRedirect'], resolve) }, | |||
{ path: '/result', name: 'result', component: resolve => require(['@/views/AliPayResult'], resolve) }, | |||
{ path: '/404', name: 'page-not-found', component: resolve => require(['@/views/page-not-found/index'], resolve) }, | |||
// 春雨 | |||
{ path: '/chunyuForm', name: 'chunyuForm', component: resolve => require(['@/views/chunyu/AliPayForm'], resolve) }, | |||
// 组件测试页面 | |||
{ path: '/compTest', name: 'compTest', component: resolve => require(['@/views/ComponentsTest'], resolve) }, | |||
]; | |||
@@ -0,0 +1,10 @@ | |||
/* | |||
* @Date: 2022-02-28 15:30:40 | |||
* @LastEditors: JinxChen | |||
* @LastEditTime: 2022-02-28 15:30:43 | |||
* @FilePath: \AntpayFrontEnd\src\utils\bus.js | |||
* @description: | |||
*/ | |||
import Vue from 'vue'; | |||
const bus = new Vue(); | |||
export default bus; |
@@ -1,3 +1,10 @@ | |||
/* | |||
* @Date: 2022-01-19 16:39:51 | |||
* @LastEditors: JinxChen | |||
* @LastEditTime: 2022-02-25 16:55:56 | |||
* @FilePath: \AntpayFrontEnd\src\utils\index.js | |||
* @description: 工具类 | |||
*/ | |||
/** | |||
@@ -20,4 +27,26 @@ export function isNull(o) { | |||
*/ | |||
export function isNotNull(o) { | |||
return !isNull(o); | |||
} | |||
} | |||
// 判断用户是否是支付宝浏览器 | |||
export function isAlipayBrowser(userAgent) { | |||
if (/AlipayClient/.test(userAgent)) { | |||
console.log("当前浏览器是支付宝浏览器"); | |||
return true; | |||
} else { | |||
console.log("当前浏览器是非支付宝浏览器"); | |||
return false; | |||
} | |||
} | |||
// 判断用户的设备是否是android | |||
export function isAndroid(userAgent) { | |||
if (userAgent.indexOf('Android') > -1 || userAgent.indexOf('Linux') > -1) { | |||
console.log("当前用户设备是android"); | |||
return true; | |||
} else if (userAgent.indexOf('iPhone') > -1) { | |||
console.log("当前用户设备是ios"); | |||
return false; | |||
} | |||
} |
@@ -1,22 +1,30 @@ | |||
<!-- | |||
* @Date: 2022-01-19 16:53:16 | |||
* @LastEditors: JinxChen | |||
* @LastEditTime: 2022-02-16 10:47:59 | |||
* @FilePath: \alipay-scan-code-front-end\src\views\AliPayForm.vue | |||
* @description: | |||
* @LastEditTime: 2022-03-04 11:08:17 | |||
* @FilePath: \AntpayFrontEnd\src\views\AliPayForm.vue | |||
* @description: 春雨个性化表单 | |||
--> | |||
<template> | |||
<div class="form-container"> | |||
<!-- 头部 --> | |||
<div class="form-header"> | |||
<div class="img-left"> | |||
<van-image :src="queryGoodsData.imageUrl" height="120"></van-image> | |||
<van-image :src="goodsData.imgPath" height="120"></van-image> | |||
</div> | |||
<div class="content-right"> | |||
<p><strong>套餐名字:</strong></p> | |||
<p>{{queryGoodsData.goodName}}</p> | |||
<p><strong>月套餐费:</strong></p> | |||
<p><span>¥{{ (queryGoodsData.price/queryGoodsData.payCount).toFixed(2) }}</span> x <span>{{queryGoodsData.payCount}}期</span><span v-show="queryGoodsData.isAmountShow">=¥{{queryGoodsData.price}}</span></p> | |||
<p> | |||
<strong>套餐名字:</strong> | |||
</p> | |||
<p>{{goodsData.mainTitle}}</p> | |||
<p> | |||
<strong>月套餐费:</strong> | |||
</p> | |||
<p> | |||
<span>¥{{ (goodsData.price/goodsData.count).toFixed(2) }}</span> x | |||
<span>{{goodsData.count}}期</span> | |||
<span v-show="goodsData.isAmountShow">=¥{{goodsData.price}}</span> | |||
</p> | |||
</div> | |||
</div> | |||
<!-- 中部表单 --> | |||
@@ -69,33 +77,32 @@ | |||
<div class="know-tips"> | |||
<h5>请知悉!</h5> | |||
<p>点击以下按钮,启动支付宝页面"立即支付"</p> | |||
<p>成功后,将分期每月从你的余额扣{{ (queryGoodsData.price/queryGoodsData.payCount).toFixed(2) }}元</p> | |||
<p>成功后,将分期每月从你的余额扣{{ (goodsData.price/goodsData.count).toFixed(2) }}元</p> | |||
</div> | |||
<div class="form-footer"> | |||
<van-button type="info" block :disabled="false" native-type="onSubmit">办理支付宝分期业务</van-button> | |||
<van-button | |||
native-type="onSubmit" | |||
>{{submitText}}</van-button> | |||
</div> | |||
</van-form> | |||
</div> | |||
<!-- 底部 --> | |||
<!-- <div class="form-footer"> | |||
<van-button type="info" block :disabled="false" native-type="onSubmit">办理支付宝分期业务</van-button> | |||
</div> --> | |||
</div> | |||
</template> | |||
<script> | |||
import { APIAlipay } from "../api/alipay"; | |||
import { IMAGE_URL } from '../config/models'; | |||
export default { | |||
name:'alipay-form', | |||
data(){ | |||
return { | |||
queryGoodsData: { | |||
imageUrl: '', | |||
price: '', | |||
payCount: '', | |||
goodsData: { | |||
imgPath: '', | |||
price: null, | |||
count: null, | |||
isAmountShow: '', | |||
goodName: '', | |||
mainTitle: '', | |||
title: '4G电子学生证资费套餐开通服务协议', | |||
}, //接收从首页传过来的数据 | |||
form: { | |||
phoneNumber: '', | |||
@@ -105,28 +112,44 @@ export default { | |||
deviceImei: '' | |||
}, //输入的表单数据 | |||
alipayForm: '', //接收支付宝接口返回的表单 | |||
submitText: '办理支付宝分期业务', //submit标题 | |||
} | |||
}, | |||
mounted() { | |||
this.getQueryParams(); | |||
this.getGoodsDetails(); | |||
}, | |||
methods: { | |||
//获取并拼接从首页传过来的数据 | |||
getQueryParams() { | |||
let queryData = this.$route.query; | |||
console.log("queryData", queryData); | |||
this.queryGoodsData.price = Number(queryData.price); | |||
this.queryGoodsData.payCount = Number(queryData.payCount); | |||
this.queryGoodsData.imageUrl = queryData.imageUrl; | |||
this.queryGoodsData.isAmountShow = JSON.parse(queryData.isAmountShow); | |||
this.queryGoodsData.goodName = queryData.goodName; | |||
}, | |||
// 根据商品编号获取商品详情 | |||
getGoodsDetails() { | |||
APIAlipay.getGoodsDetails(this.$store.getters.goodsNo) | |||
.then(res => { | |||
if(res.data.code === 20000) { | |||
let good = res.data.data.goods; | |||
console.log("good", good); | |||
// 图片路径 | |||
this.goodsData.imgPath = IMAGE_URL[ process.env.NODE_ENV ] + good.goodsImg; | |||
// 价格 | |||
this.goodsData.price = good.price; | |||
// 是否是老用户 | |||
this.isOld = good.descriptionText === '' ? true : false; | |||
// 商品名称 | |||
this.goodsData.mainTitle = good.mainTitle; | |||
// 分期数 | |||
let count = good.periodizationJson.substring(1, good.periodizationJson.length - 1).split(','); | |||
// 是否显示金额总数, todo 后期需从接口获取 | |||
this.goodsData.isAmountShow = JSON.parse(this.$route.query.isAmountShow); | |||
this.goodsData.count = Math.max(...count); | |||
this.goodsData.goodDefCount = Math.max(...count).toString(); | |||
} | |||
}) | |||
}, | |||
// 办理支付宝分期业务表单校验通过后 | |||
onSubmit(values) { | |||
let reg = /^1[3456789]\d{9}$/; | |||
if(!reg.test(values.phoneNumber)) { | |||
onSubmit() { | |||
let reg = /^1[3456789]\d{9}$/; //手机号码正则验证 | |||
if(!reg.test(this.form.phoneNumber)) { | |||
this.$notify({ | |||
message: '请您输入正确的手机号码!', | |||
message: '请输入正确的手机号码', | |||
type: 'warning', | |||
duration: 1500 | |||
}) | |||
@@ -137,16 +160,16 @@ export default { | |||
schoolName: this.form.schoolName, | |||
className: this.form.className, | |||
phoneNumber: this.form.phoneNumber, | |||
periodizationNum: Number(this.queryGoodsData.payCount), | |||
periodizationNum: Number(this.goodsData.count), | |||
goodsNo: this.$store.getters.goodsNo, | |||
alipayStateType: Number(this.queryGoodsData.payType), | |||
alipayStateType: Number(this.goodsData.payType), | |||
userId: this.$store.getters.userId, | |||
} | |||
APIAlipay.getAlipayForm(reqBody) | |||
.then(res => { | |||
this.alipayForm = res.data; | |||
this.$store.commit('price', Number(this.queryGoodsData.price)); | |||
this.$store.commit('count', Number(this.queryGoodsData.payCount)); | |||
this.$store.commit('price', Number(this.goodsData.price)); | |||
this.$store.commit('count', Number(this.goodsData.count)); | |||
// 跳转到一个中转页 form,再通过这个中转页来调起支付宝的收银台 | |||
this.$router.push({path: 'redirect', query: {alipayForm: this.alipayForm}}); | |||
}) | |||
@@ -158,81 +181,88 @@ export default { | |||
// 表单不通过时 | |||
onFailed() { | |||
console.log("表单输入不完整!"); | |||
} | |||
}, | |||
} | |||
} | |||
</script> | |||
<style scoped lang="scss"> | |||
.form-container { | |||
height: 100vh; | |||
width: 100vw; | |||
display: flex; | |||
flex-direction: column; | |||
overflow: hidden; | |||
/* padding: 5px; | |||
.form-container { | |||
height: 100vh; | |||
width: 100vw; | |||
display: flex; | |||
flex-direction: column; | |||
overflow: hidden; | |||
/* padding: 5px; | |||
border-radius: 20px; */ | |||
background-color: #f7f8fa; | |||
.form-header { | |||
height: 25vh; | |||
display: flex; | |||
justify-content: center; | |||
align-items: center; | |||
padding: 10px; | |||
box-shadow: rgba(50, 50, 93, 0.25) 0px 2px 5px -1px, rgba(0, 0, 0, 0.3) 0px 1px 3px -1px; | |||
background-color: rgba(235, 233, 229, 0.726); | |||
.img-left { | |||
width: 120px; | |||
} | |||
.content-right { | |||
flex: 1; | |||
p { | |||
font-size: 14px; | |||
text-align: left; | |||
padding: 5px 10px; | |||
strong { | |||
text-align: left; | |||
} | |||
} | |||
} | |||
background-color: #f7f8fa; | |||
.form-header { | |||
height: 25vh; | |||
display: flex; | |||
justify-content: center; | |||
align-items: center; | |||
padding: 10px; | |||
box-shadow: rgba(50, 50, 93, 0.25) 0px 2px 5px -1px, | |||
rgba(0, 0, 0, 0.3) 0px 1px 3px -1px; | |||
background-color: rgba(235, 233, 229, 0.726); | |||
.img-left { | |||
width: 120px; | |||
} | |||
.form-body { | |||
.content-right { | |||
flex: 1; | |||
position: relative; | |||
overflow: scroll; | |||
/* padding: 10px; */ | |||
box-shadow: rgba(50, 50, 93, 0.25) 0px 2px 5px -1px, rgba(0, 0, 0, 0.3) 0px 1px 3px -1px; | |||
.know-tips { | |||
height: 120px; | |||
width: 100%; | |||
padding: 10px; | |||
h5 { | |||
font-size: 16px; | |||
text-align: left; | |||
padding: 5px; | |||
color: red; | |||
} | |||
p { | |||
font-size: 14px; | |||
padding: 5px; | |||
p { | |||
font-size: 14px; | |||
text-align: left; | |||
padding: 5px 10px; | |||
strong { | |||
text-align: left; | |||
} | |||
} | |||
} | |||
.form-footer { | |||
height: 10vh; | |||
} | |||
.form-body { | |||
flex: 1; | |||
position: relative; | |||
overflow: scroll; | |||
/* padding: 10px; */ | |||
box-shadow: rgba(50, 50, 93, 0.25) 0px 2px 5px -1px, | |||
rgba(0, 0, 0, 0.3) 0px 1px 3px -1px; | |||
.know-tips { | |||
height: 120px; | |||
width: 100%; | |||
position: absolute; | |||
padding: 10px; | |||
bottom: 10px; | |||
left: 0; | |||
display: flex; | |||
justify-content: center; | |||
align-items: center; | |||
.van-button { | |||
box-shadow: rgb(38, 57, 77) 0px 20px 30px -10px; | |||
h5 { | |||
font-size: 16px; | |||
text-align: left; | |||
padding: 5px; | |||
color: red; | |||
} | |||
p { | |||
font-size: 14px; | |||
padding: 5px; | |||
text-align: left; | |||
} | |||
} | |||
} | |||
.form-footer { | |||
height: 15vh; | |||
width: 100%; | |||
position: absolute; | |||
padding: 10px; | |||
bottom: 10px; | |||
left: 0; | |||
display: flex; | |||
justify-content: center; | |||
flex-direction: column; | |||
.van-button { | |||
height: 40px; | |||
background-color: #1989fa; | |||
color: white; | |||
border-radius: 5px; | |||
&.notSubmit { | |||
background-color: rgba(150, 150, 146, 0.904); | |||
} | |||
} | |||
} | |||
} | |||
</style> |
@@ -1,8 +1,8 @@ | |||
<!-- | |||
* @Date: 2022-01-19 16:52:21 | |||
* @LastEditors: JinxChen | |||
* @LastEditTime: 2022-02-16 11:05:34 | |||
* @FilePath: \alipay-scan-code-front-end\src\views\AliPayIndex.vue | |||
* @LastEditTime: 2022-03-04 11:19:26 | |||
* @FilePath: \AntpayFrontEnd\src\views\AliPayIndex.vue | |||
* @description: | |||
--> | |||
<template> | |||
@@ -13,8 +13,8 @@ | |||
</div> | |||
<!-- 中间内容 --> | |||
<div class="index-body"> | |||
<p class="set-meal-title">月套餐费: <span class="set-meal-price">¥{{ (goodsData.price/goodsData.goodCount).toFixed(2) }}</span> x <span>{{goodsData.goodCount}}期</span> <span v-show='isAmountShow'> = ¥{{goodsData.price}}</span></p> | |||
<p class="index-tips">可切换支付方式:</p> | |||
<p class="set-meal-title">月套餐费: <span class="set-meal-price">¥{{ (goodsData.price/goodsData.count).toFixed(2) }}</span> x <span>{{goodsData.count}}期</span> <span v-show='isAmountShow'> = ¥{{goodsData.price}}</span></p> | |||
<p class="index-tips">{{switchPayType}}:</p> | |||
<!-- 花呗or支付宝 --> | |||
<van-radio-group class="radio-group" v-model="radio" @change="onRadioChange"> | |||
<van-cell-group> | |||
@@ -59,21 +59,21 @@ | |||
<!-- 我要开通花呗 --> | |||
<p class="open-antpay" @click="onOpenAntpay">我要开通花呗</p> | |||
<!-- 协议 --> | |||
<p class="agreement" @click="onOpenAgreement">{{agreement.agreementTitle}}</p> | |||
<p class="agreement" @click="onOpenAgreement">{{agreement.title}}</p> | |||
<!-- 协议内容 --> | |||
<van-dialog | |||
class="agreement-container" | |||
v-model="agreement.isAgreementShow" | |||
:title="agreement.agreementTitle" | |||
v-model="agreement.show" | |||
:title="agreement.title" | |||
confirm-button-color="#1989fa" | |||
:show-confirm-button="false" | |||
> | |||
<div class="agreement-content"> | |||
<h5>一.开通需知及承诺</h5> | |||
<p v-show="isNewCustom">1.感谢用户使用支付宝花呗分期功能。</p> | |||
<p v-show="isNewCustom">2.用户自愿开通4G电子学生证资费套餐服务({{goodsData.goodCount}}<!-- 24 -->期)每月自动通过支付宝花呗分期支付资费(话费+流量)套餐费{{(goodsData.price/goodsData.goodCount).toFixed(2)}}元/月。</p> | |||
<p v-show="isNewCustom">2.用户自愿开通4G电子学生证资费套餐服务({{goodsData.count}}<!-- 24 -->期)每月自动通过支付宝花呗分期支付资费(话费+流量)套餐费{{(goodsData.price/goodsData.count).toFixed(2)}}元/月。</p> | |||
<p v-show="isNewCustom">3.用户需连续使用该资费套餐24期,可据此领取4G电子学生证1台、电话卡1张。</p> | |||
<p style="white-space: pre-wrap"><span v-show="isNewCustom">4.</span>{{goodsData.goodDescription}}</p> | |||
<p style="white-space: pre-wrap"><span v-show="isNewCustom">4.</span>{{goodsData.description}}</p> | |||
<p v-show="isOldCustom">5.协议期内,电子学生证非人为损坏或进水按“三包”政策进行免费维修或更换。如丢失或人为损坏,按优惠价重新购买。</p> | |||
<p v-show="isOldCustom">6.北京随手精灵科技有限公司接受电子学生证运营销售商委托采用支付宝花呗分期付代收业务货款。</p> | |||
<h5>二.用户承诺</h5> | |||
@@ -92,21 +92,37 @@ | |||
<!-- 底部 --> | |||
<div class="index-footer-out"> | |||
<div class="index-footer"> | |||
<div class="checkbox-container"> | |||
<div class="checkbox-container" v-show="!isChunyu"> | |||
<van-checkbox v-model="checked" shape="square" @change="onCheckChange"><strong>已阅读协议并确认</strong></van-checkbox> | |||
</div> | |||
<div class="footer-button"> | |||
<van-button :class="['van-button', {notSubmit: !checked}]" block @click="onSubmit">一键下单</van-button> | |||
<van-button :class="['van-button', {notSubmit: !checked && !isChunyu}]" block @click="onSubmit">{{submitText}}</van-button> | |||
</div> | |||
</div> | |||
</div> | |||
<!-- 非支付宝浏览器提示弹窗 --> | |||
<van-dialog v-model="isAlipayBrowser" title="提示您切换支付宝扫码!" | |||
:show-cancel-button="false" | |||
:show-confirm-button="false" | |||
confirm-button-color="#1989fa" | |||
className="alipay-dialog" | |||
:close-on-click-overlay="true"> | |||
<p>1.如果已安装支付宝,请打开支付宝扫码。</p> | |||
<p>2.如果未安装支付宝,请到应用商店下载。 | |||
<span v-show="!isAndroid" @click="onDownAlipay" class="down">点击前往应用商店下载</span> | |||
<span v-show="isAndroid">或复制 {{alipayDownUrl.android}} | |||
[<span @click="onCopy" class="copy-span">点击复制 | |||
</span>],粘贴到浏览器打开下载页面。</span></p> | |||
<p class="close-text">点击屏幕任意地方关闭弹窗</p> | |||
</van-dialog> | |||
</div> | |||
</template> | |||
<script> | |||
import { isNotNull } from "../utils/index"; | |||
import { isNotNull, isAlipayBrowser, isAndroid } from "../utils/index"; | |||
import { APIAlipay } from "../api/alipay"; | |||
import { ImageUrl} from '../config/models'; | |||
import { IMAGE_URL, USER_AGENT, ALIPAY_DOWN_URL} from '../config/models'; | |||
/* import { CUSTOMIZE_SERVICE } from '../config/customize'; */ | |||
export default { | |||
name:'alipay-index', | |||
data(){ | |||
@@ -115,14 +131,14 @@ export default { | |||
goodsData: { | |||
imgPath: null /* || require('../assets/banner_03.jpg') */, //首页图片路径 | |||
price: null, //价格 | |||
goodCount: null, //分期数 | |||
goodDefCount: null, //默认分期数 | |||
count: null, //分期数 | |||
defCount: null, //默认分期数 | |||
amount: 480, //总数 | |||
isOld: null, //是否是老用户 | |||
goodDescription: null, //商品描述 | |||
defGoodDescription: '电子学生证套餐两年内(24个月)内含每月200分钟通话和1.5G流量,超出通话或流量部分,由用户自行交费。', //默认协议内容 | |||
description: null, //商品描述 | |||
defDescription: '电子学生证套餐两年内(24个月)内含每月200分钟通话和1.5G流量,超出通话或流量部分,由用户自行交费。', //默认协议内容 | |||
payType: null, //支付类型, 2是花呗, 1 是支付宝 | |||
goodName: null, //商品名称 | |||
name: null, //商品名称 | |||
}, | |||
radio: '2', //单选框的值,默认是 '2', 2是花呗, 1支付宝 | |||
antPayRadio: '', //花呗分期,默认24期 | |||
@@ -135,8 +151,8 @@ export default { | |||
isAmountShow: true, //是否显示总数, 默认显示,部分客户不需要显示则false | |||
isAntpay: true, //单选是否是花呗, 默认是花呗,否则是支付宝 | |||
agreement: { | |||
agreementTitle: '4G电子学生证资费套餐开通服务协议', //协议标题 | |||
isAgreementShow: false, //是否显示协议内容,默认不显示 | |||
title: '4G电子学生证资费套餐开通服务协议', //协议标题 | |||
show: false, //是否显示协议内容,默认不显示 | |||
isButtonShow: false, //是否显示按钮 | |||
timer: '', //定义一个倒计时 | |||
countDown: 3, //同意/不同意按钮显示倒计时 | |||
@@ -144,6 +160,12 @@ export default { | |||
isNewCustom: true, //是否是新用户 | |||
isOldCustom: false, //是否是新用户 | |||
checkCount: 0, //首次点击同意协议单选框 | |||
isAlipayBrowser: !isAlipayBrowser(USER_AGENT), //是否是支付宝浏览器 | |||
isAndroid: isAndroid(USER_AGENT), //用户设备是否是android | |||
alipayDownUrl: ALIPAY_DOWN_URL, //支付宝app下载链接 | |||
isChunyu: null, //是否是春雨 | |||
submitText: '一键下单' , //submit文字, 默认 一键下单, 可根据客户需求变化 | |||
switchPayType: '可切换支付方式', //默认 可切换支付方式, 可根据客户需求变化 | |||
} | |||
}, | |||
@@ -173,10 +195,15 @@ export default { | |||
} else if(goodsNo === '1462964210433548288' || goodsNo === '1472882092902715392' || goodsNo === '1479390914305277952') { | |||
this.isAmountShow = false; | |||
} else if (goodsNo === '1483687825375969280') { //翼校云定制的商品id | |||
this.agreement.agreementTitle = '电子学生证AI套餐开通服务协议'; | |||
this.agreement.title = '电子学生证AI套餐开通服务协议'; | |||
this.isNewCustom = false; | |||
this.isAmountShow = true; | |||
}else { | |||
} else if (goodsNo === '889') { | |||
this.isChunyu = true; | |||
this.submitText = '下一步'; | |||
this.switchPayType = '支付方案' | |||
} | |||
else { | |||
this.isAmountShow = true; | |||
} | |||
}, | |||
@@ -188,19 +215,19 @@ export default { | |||
let good = res.data.data.goods; | |||
console.log("good", good); | |||
// 图片路径 | |||
this.goodsData.imgPath = ImageUrl[ process.env.NODE_ENV ] + good.goodsImg; | |||
this.goodsData.imgPath = IMAGE_URL[ process.env.NODE_ENV ] + good.goodsImg; | |||
// 价格 | |||
this.goodsData.price = good.price; | |||
// 是否是老用户 | |||
this.isOld = good.descriptionText === '' ? true : false; | |||
// 商品名称 | |||
this.goodsData.goodName = good.mainTitle; | |||
this.goodsData.name = good.mainTitle; | |||
//商品描述 根据\n换行符来把数据进行换行 | |||
this.goodsData.goodDescription = good.descriptionText === '' ? this.goodsData.defGoodDescription : good.descriptionText.replace(/\\n/g,"<br/>"); | |||
this.goodsData.description = good.descriptionText === '' ? this.goodsData.defDescription : good.descriptionText.replace(/\\n/g,"<br/>"); | |||
// 分期数 | |||
let goodCount = good.periodizationJson.substring(1, good.periodizationJson.length - 1).split(','); | |||
this.goodsData.goodCount = Math.max(...goodCount); | |||
this.goodsData.goodDefCount = Math.max(...goodCount).toString(); | |||
this.goodsData.defCount = Math.max(...goodCount).toString(); | |||
this.antPayRadio = Math.max(...goodCount).toString(); | |||
this.countList = goodCount.map(g => { | |||
return { | |||
@@ -226,8 +253,7 @@ export default { | |||
}, | |||
// 选择分期数改变时 | |||
onChange(values) { | |||
console.log("分期数改变", values); | |||
this.goodsData.goodCount = values; | |||
this.goodsData.count = values; | |||
}, | |||
// 我要开通花呗弹窗 | |||
onOpenAntpay() { | |||
@@ -243,7 +269,7 @@ export default { | |||
}, | |||
// 打开协议 | |||
onOpenAgreement() { | |||
this.agreement.isAgreementShow = true; | |||
this.agreement.show = true; | |||
this.checkCount ++; | |||
if(this.checkCount <= 1) { | |||
this.agreement.timer = setInterval(() =>{ | |||
@@ -281,33 +307,40 @@ export default { | |||
}, | |||
// 重置倒计时和关闭弹窗 | |||
resetCountDown() { | |||
this.agreement.isAgreementShow = false; | |||
this.agreement.show = false; | |||
this.agreement.isButtonShow = false; | |||
clearInterval(this.agreement.timer); | |||
this.agreement.countDown = 3; | |||
}, | |||
// 一键下单提交按钮 | |||
onSubmit() { | |||
if(this.checked === false) { | |||
if(this.checked === false && !this.isChunyu) { | |||
this.$notify({ | |||
message: `请阅读并勾选同意${this.agreement.agreementTitle}`, | |||
message: `请阅读并勾选同意${this.agreement.title}`, | |||
type: 'warning', | |||
duration: 1500 | |||
}) | |||
} else { | |||
this.$router.push({ | |||
path: 'form' , | |||
query: { | |||
payType: Number(this.radio), | |||
price: this.goodsData.price, | |||
payCount: this.goodsData.goodCount, | |||
goodName: this.goodsData.goodName, | |||
isAmountShow: this.isAmountShow, | |||
imageUrl: this.goodsData.imgPath | |||
} | |||
}) | |||
}else if( this.isChunyu ) { | |||
this.$router.push({path: 'chunyuForm', query: {isAmountShow: this.isAmountShow}}) | |||
} | |||
else { | |||
this.$router.push({path: 'form', query: {isAmountShow: this.isAmountShow}}) | |||
} | |||
}, | |||
// 点击下载支付宝app | |||
onDownAlipay() { | |||
window.location.href = this.alipayDownUrl.ios; | |||
}, | |||
// 复制网址 | |||
onCopy() { | |||
let oInput = document.createElement('input'); | |||
oInput.value = this.alipayDownUrl.android; | |||
document.body.appendChild(oInput); | |||
oInput.select(); // 选择对象; | |||
console.log(oInput.value) | |||
document.execCommand("Copy"); // 执行浏览器复制命令 | |||
this.$toast.success('已复制到粘贴板!'); | |||
oInput.remove() | |||
} | |||
} | |||
} | |||
@@ -460,6 +493,9 @@ export default { | |||
left: 0; | |||
bottom: 0; | |||
z-index: 999; | |||
display: flex; | |||
justify-content: center; | |||
flex-direction: column; | |||
.checkbox-container { | |||
margin: 5px 0; | |||
} | |||
@@ -476,5 +512,24 @@ export default { | |||
} | |||
} | |||
} | |||
.alipay-dialog { | |||
p { | |||
padding: 10px; | |||
line-height: 20px; | |||
text-align: left; | |||
font-size: 14px; | |||
} | |||
.down { | |||
display: block; | |||
color: #1989fa; | |||
text-decoration: #1989fa; | |||
} | |||
.copy-span { | |||
color: red; | |||
} | |||
.close-text { | |||
text-align: center; | |||
} | |||
} | |||
} | |||
</style> |
@@ -1,8 +1,8 @@ | |||
<!-- | |||
* @Date: 2022-01-19 16:54:08 | |||
* @LastEditors: JinxChen | |||
* @LastEditTime: 2022-02-15 16:05:25 | |||
* @FilePath: \alipay-scan-code-front-end\src\views\AliPayRedirect.vue | |||
* @LastEditTime: 2022-03-04 10:26:29 | |||
* @FilePath: \AntpayFrontEnd\src\views\AliPayRedirect.vue | |||
* @description: | |||
--> | |||
<template> | |||
@@ -14,7 +14,7 @@ export default { | |||
name:'alipay-redirect', | |||
data(){ | |||
return { | |||
queryAlipayForm: this.$route.query.alipayForm, //接收上一个页面传过来的支付宝表单文件 | |||
queryData: this.$route.query.alipayForm, //接收上一个页面传过来的支付宝表单文件 | |||
} | |||
}, | |||
mounted() { | |||
@@ -23,7 +23,7 @@ export default { | |||
methods: { | |||
createAlipayPage() { | |||
const div = document.createElement('div'); //在当前页面创建一个div的节点 | |||
div.innerHTML = this.queryAlipayForm; //将支付宝的form表单数据添加到div里面 | |||
div.innerHTML = this.queryData; //将支付宝的form表单数据添加到div里面 | |||
document.body.appendChild(div); //把这个节点添加到页面的body里面去 | |||
document.forms[0].submit(); //自动调用form表单的submit方法正式调起支付宝的收银台界面 | |||
} | |||
@@ -1,10 +1,13 @@ | |||
<!-- | |||
* @Date: 2022-01-19 16:55:03 | |||
* @LastEditors: JinxChen | |||
* @LastEditTime: 2022-02-16 10:46:46 | |||
* @FilePath: \alipay-scan-code-front-end\src\views\AliPayResult.vue | |||
* @LastEditTime: 2022-03-04 14:11:16 | |||
* @FilePath: \AntpayFrontEnd\src\views\AliPayResult.vue | |||
* @description: | |||
注意:本地调试需要手动在url添加参数 | |||
?tradeno='860009040228082'&outtradeno='860009040228082' | |||
--> | |||
<template> | |||
<div class="pay-result-container"> | |||
<!-- 接口轮询时加载动画以及空状态 --> | |||
@@ -19,6 +22,7 @@ | |||
<p v-if="isPaySuccess">接下来将按分期每月从你的支付宝余额扣{{(price/count).toFixed(2)}}元。</p> | |||
<p>{{isPaySuccess ? checkSuccess.content : checkFail.content}}</p> | |||
</div> | |||
<!-- 页脚 --> | |||
<div class="result-footer"> | |||
<p>商家订单号: </p> | |||
<p>{{alipayOrder.outradeNo}}</p> | |||
@@ -0,0 +1,46 @@ | |||
<!-- | |||
* @Date: 2022-02-28 09:46:25 | |||
* @LastEditors: JinxChen | |||
* @LastEditTime: 2022-03-04 10:14:03 | |||
* @FilePath: \AntpayFrontEnd\src\views\ComponentsTest.vue | |||
* @description: 组件测试页面 | |||
--> | |||
<template> | |||
<div> | |||
<AgreementDialog | |||
:title="title" | |||
:show="true" | |||
:count="count" | |||
:price="price" | |||
:description="description"/> | |||
</div> | |||
</template> | |||
<script> | |||
import AgreementDialog from '../components/AgreementDialog' | |||
export default { | |||
name:'components-test', | |||
components: { AgreementDialog }, | |||
data(){ | |||
return { | |||
title: '标题', | |||
description: 'description', | |||
count: 24, | |||
price: 240 | |||
} | |||
}, | |||
mounted() { | |||
this.getGoodsDetails(); | |||
}, | |||
methods: { | |||
getGoodsDetails() { | |||
} | |||
} | |||
} | |||
</script> | |||
<style scoped lang="scss"> | |||
</style> |
@@ -0,0 +1,501 @@ | |||
<!-- | |||
* @Date: 2022-01-19 16:53:16 | |||
* @LastEditors: JinxChen | |||
* @LastEditTime: 2022-03-04 15:48:09 | |||
* @FilePath: \AntpayFrontEnd\src\views\chunyu\AliPayForm.vue | |||
* @description: 春雨个性化表单 | |||
--> | |||
<template> | |||
<div class="form-container"> | |||
<!-- 头部 --> | |||
<div class="form-header"> | |||
<div class="img-left"> | |||
<van-image :src="goodsData.imgPath" height="120"></van-image> | |||
</div> | |||
<div class="content-right"> | |||
<p> | |||
<strong>套餐名字:</strong> | |||
</p> | |||
<p>{{goodsData.mainTitle}}</p> | |||
<p> | |||
<strong>月套餐费:</strong> | |||
</p> | |||
<p> | |||
<span>¥{{ (goodsData.price/goodsData.count).toFixed(2) }}</span> x | |||
<span>{{goodsData.count}}期</span> | |||
<span v-show="goodsData.isAmountShow">=¥{{goodsData.price}}</span> | |||
</p> | |||
</div> | |||
</div> | |||
<!-- 中部表单 --> | |||
<div class="form-body"> | |||
<van-form @submit="onSubmit" @failed="onFailed"> | |||
<div class="form-box"> | |||
<!-- <van-field | |||
v-model="form.phoneNumber" | |||
name="phoneNumber" | |||
label="电话" | |||
type="tel" | |||
placeholder="必填" | |||
maxlength="11" | |||
required | |||
clearable | |||
:rules="[{ required: true, message: '请填写电话' }]" | |||
/> | |||
<van-field | |||
v-model="form.schoolName" | |||
name="schoolName" | |||
label="学校" | |||
placeholder="必填" | |||
maxlength="30" | |||
required | |||
clearable | |||
:rules="[{ required: true, message: '请填写学校' }]" | |||
/> | |||
<van-field | |||
v-model="form.className" | |||
name="className" | |||
label="班级" | |||
placeholder="必填" | |||
maxlength="10" | |||
required | |||
clearable | |||
:rules="[{ required: true, message: '请填写班级' }]" | |||
/> | |||
<van-field | |||
v-model="form.studentName" | |||
name="studentName" | |||
label="学生" | |||
placeholder="必填" | |||
maxlength="10" | |||
required | |||
clearable | |||
:rules="[{ required: true, message: '请填写学生' }]" | |||
/> --> | |||
<!-- 省市区选择详情见 https://vant-contrib.gitee.io/vant/v2/#/zh-CN/area --> | |||
<van-field | |||
readonly | |||
clickable | |||
name="area" | |||
:value="form.address" | |||
label="地区:" | |||
placeholder="点击选择省市区" | |||
@click="showArea = true" | |||
required | |||
:rules="[{ validator}]" | |||
/> | |||
<van-popup v-model="showArea" position="bottom"> | |||
<van-area | |||
:area-list="areaList" | |||
@confirm="onConfirmAddress" | |||
@cancel="showArea = false" | |||
/> | |||
</van-popup> | |||
<!-- 请选择学校 --> | |||
<van-field | |||
readonly | |||
clickable | |||
name="school" | |||
:value="form.schoolName" | |||
label="学校:" | |||
placeholder="点击选择学校" | |||
@click="showSchool = true" | |||
required | |||
:rules="[{ validator}]" | |||
/> | |||
<van-popup v-model="showSchool" position="bottom"> | |||
<van-picker | |||
show-toolbar | |||
:columns="schoolColumns" | |||
@confirm="onConfirmSchool" | |||
@cancel="showSchool = false" | |||
/> | |||
</van-popup> | |||
<!-- 选择年级班级 --> | |||
<van-field | |||
readonly | |||
clickable | |||
name="class" | |||
:value="form.className" | |||
label="年级班级:" | |||
placeholder="点击选择年级班级" | |||
@click="showClass = true" | |||
required | |||
:rules="[{ validator}]" | |||
/> | |||
<van-popup v-model="showClass" round position="bottom"> | |||
<van-cascader | |||
v-model="form.className" | |||
title="请选择年级班级" | |||
:options="classOptions" | |||
@close="showClass = false" | |||
@finish="onClassFinish" | |||
/> | |||
</van-popup> | |||
<!-- 请选择学生名字 --> | |||
<van-field | |||
readonly | |||
clickable | |||
name="school" | |||
:value="form.studentName" | |||
label="学生:" | |||
placeholder="点击选择学生" | |||
@click="showStudent = true" | |||
required | |||
:rules="[{ validator}]" | |||
/> | |||
<van-popup v-model="showStudent" position="bottom"> | |||
<van-picker | |||
show-toolbar | |||
:columns="studentColumns" | |||
@confirm="onConfirmStudent" | |||
@cancel="showStudent = false" | |||
/> | |||
</van-popup> | |||
<!-- 请选择家长手机号码 --> | |||
<van-field | |||
readonly | |||
clickable | |||
name="school" | |||
:value="form.phoneNumber" | |||
label="手机号码:" | |||
placeholder="点击选择家长手机号码" | |||
@click="showPhone = true" | |||
required | |||
:rules="[{ pattern, message: '请输入正确的手机号码' }]" | |||
/> | |||
<van-popup v-model="showPhone" position="bottom"> | |||
<van-picker | |||
show-toolbar | |||
:columns="phoneColumns" | |||
@confirm="onConfirmPhone" | |||
@cancel="showPhone = false" | |||
/> | |||
</van-popup> | |||
</div> | |||
<!-- '请知悉' 提示, --> | |||
<div class="know-tips"> | |||
<h5>请知悉!</h5> | |||
<p>点击以下按钮,启动支付宝页面"立即支付"</p> | |||
<p>成功后,将分期每月从你的余额扣{{ (goodsData.price/goodsData.count).toFixed(2) }}元</p> | |||
</div> | |||
<div class="form-footer"> | |||
<Checkbox @SendCheckStatus="SendCheckStatus" /> | |||
<AgreementDialog | |||
:show="goodsData.isShow" | |||
:title="goodsData.title" | |||
:count="goodsData.count" | |||
:price="goodsData.price" | |||
:description="goodsData.description" | |||
:countDown="goodsData.countDown" | |||
:isButtonShow="goodsData.isButtonShow" | |||
/> | |||
<van-button | |||
:class="['van-button', {notSubmit: !goodsData.newChecked}]" | |||
native-type="onSubmit" | |||
>{{submitText}}</van-button> | |||
</div> | |||
</van-form> | |||
</div> | |||
</div> | |||
</template> | |||
<script> | |||
import { APIAlipay } from "../../api/alipay"; | |||
import Checkbox from "../../components/Checkbox"; | |||
import AgreementDialog from "../../components/AgreementDialog"; | |||
import { IMAGE_URL } from '../../config/models'; | |||
//Vant 官方提供了一份默认的省市区数据,可以通过 @vant/area-data 引入: | |||
import { areaList } from '@vant/area-data'; | |||
import { isNotNull } from '../../utils'; | |||
export default { | |||
name:'alipay-form', | |||
components: { Checkbox, AgreementDialog }, | |||
data(){ | |||
return { | |||
goodsData: { | |||
imgPath: '', //图片地址 | |||
price: null, //价格 | |||
count: null, //分期数 | |||
isAmountShow: '', //是否显示金额总数, 目前根据首页商品来控制是否需要显示, 后期可根据接口来控制 | |||
mainTitle: '', //商品mainTitle | |||
description: '', //协议说明 | |||
title: '4G电子学生证资费套餐开通服务协议', | |||
newChecked: false, //单选框的值 | |||
checkCount: 0, //点击单选框的次数 | |||
isButtonShow: false, //显示协议组件里面的同意不同意按钮是否需要显示 | |||
countDown: 3, //协议按钮倒计时 | |||
timer: '', //定时器 | |||
isShow: false, //是否显示协议弹窗 | |||
}, //接收从首页传过来的数据 | |||
form: { | |||
phoneNumber: '', //手机号码 | |||
schoolName: '', //学校名字 | |||
className: '', //班级名字 | |||
studentName: '', //学生名字 | |||
deviceImei: '', //设备Imei, 接口参数, 可为空, | |||
address: '', //地址, todo, 接口暂时没有这个字段,待接口实现 | |||
}, //输入的表单数据 | |||
alipayForm: '', //接收支付宝接口返回的表单 | |||
submitText: '一键下单', //submit标题 | |||
showArea: false, | |||
// todo 以下数据以接口实际数据为准 | |||
areaList, //省市区数据 | |||
showSchool: false, | |||
schoolColumns: ['学校1', '学校2', '学校3', '学校4', '学校5'], //学校数据 | |||
showClass: false, | |||
classOptions: [ | |||
{ | |||
text: '高一', | |||
value: '1', | |||
children: [ | |||
{ text: '一班', value: '1' }, | |||
{ text: '二班', value: '1' }, | |||
{ text: '三班', value: '1' } | |||
], | |||
}, | |||
{ | |||
text: '高二', | |||
value: '2', | |||
children: [ | |||
{ text: '一班', value: '2' }, | |||
{ text: '二班', value: '2' }, | |||
{ text: '三班', value: '2' }, | |||
], | |||
}, | |||
], | |||
showStudent: false, | |||
studentColumns: [ | |||
'学生1', '学生2', '学生3', '学生4', '学生5' | |||
], | |||
showPhone: false, | |||
phoneColumns: [ | |||
'18277426712', '18277426712', '18277426712', '18277426712', '18277426712' | |||
], | |||
pattern: /^1[3456789]\d{9}$/, | |||
} | |||
}, | |||
mounted() { | |||
this.getGoodsDetails(); | |||
this.getCheckStatus(); | |||
}, | |||
methods: { | |||
// 获取从协议弹窗传过来的单选框状态 | |||
getCheckStatus() { | |||
this.$bus.$on('getCheckStatus', (data) => { | |||
this.goodsData.newChecked = data; | |||
this.goodsData.isShow = false; | |||
}) | |||
}, | |||
// 根据商品编号获取商品详情 | |||
getGoodsDetails() { | |||
APIAlipay.getGoodsDetails(this.$store.getters.goodsNo) | |||
.then(res => { | |||
if(res.data.code === 20000) { | |||
let good = res.data.data.goods; | |||
console.log("good", good); | |||
// 图片路径 | |||
this.goodsData.imgPath = IMAGE_URL[ process.env.NODE_ENV ] + good.goodsImg; | |||
// 价格 | |||
this.goodsData.price = good.price; | |||
// 是否是老用户 | |||
this.isOld = good.descriptionText === '' ? true : false; | |||
// 商品名称 | |||
this.goodsData.mainTitle = good.mainTitle; | |||
//商品描述 根据\n换行符来把数据进行换行 | |||
this.goodsData.description = good.descriptionText === '' ? this.goodsData.defGoodDescription : good.descriptionText.replace(/\\n/g,"<br/>"); | |||
// 分期数 | |||
let count = good.periodizationJson.substring(1, good.periodizationJson.length - 1).split(','); | |||
// 是否显示金额总数 todo 后期需从接口获取 | |||
this.goodsData.isAmountShow = JSON.parse(this.$route.query.isAmountShow); | |||
this.goodsData.count = Math.max(...count); | |||
this.goodsData.goodDefCount = Math.max(...count).toString(); | |||
} | |||
}) | |||
}, | |||
// 办理支付宝分期业务表单校验通过后 | |||
onSubmit(values) { | |||
if(this.goodsData.newChecked === false) { | |||
this.$notify({ | |||
message: `请阅读并勾选同意${this.goodsData.title}`, | |||
type: 'warning', | |||
duration: 1500 | |||
}); | |||
} else if( values ) { | |||
let reqBody = { | |||
username: this.form.studentName, | |||
deviceImei: this.form.deviceImei === '' ? '123' : this.form.deviceImei, | |||
schoolName: this.form.schoolName, | |||
className: this.form.className, | |||
phoneNumber: this.form.phoneNumber, | |||
periodizationNum: Number(this.goodsData.count), | |||
goodsNo: this.$store.getters.goodsNo, | |||
alipayStateType: Number(this.goodsData.payType), | |||
userId: this.$store.getters.userId, | |||
} | |||
APIAlipay.getAlipayForm(reqBody) | |||
.then(res => { | |||
this.alipayForm = res.data; | |||
this.$store.commit('price', Number(this.goodsData.price)); | |||
this.$store.commit('count', Number(this.goodsData.count)); | |||
// 跳转到一个中转页 form,再通过这个中转页来调起支付宝的收银台 | |||
this.$router.push({path: 'redirect', query: {alipayForm: this.alipayForm}}); | |||
}) | |||
.catch(error => { | |||
console.log(error); | |||
}) | |||
} | |||
}, | |||
// 表单不通过时 | |||
onFailed() { | |||
console.log("表单输入不完整!"); | |||
}, | |||
// 接收 checkbox 组件的SendCheckStatus事件 | |||
SendCheckStatus(value) { | |||
//通知 checkbox 组件改变。 | |||
this.goodsData.newChecked = value; | |||
this.goodsData.isShow = value; | |||
this.initAgreement(); | |||
}, | |||
// 初始化协议组件内容 | |||
initAgreement() { | |||
this.goodsData.checkCount ++; | |||
if(this.goodsData.checkCount <= 1) { | |||
this.goodsData.timer = setInterval(() =>{ | |||
this.goodsData.countDown --; | |||
if(this.goodsData.countDown === 0) { | |||
this.goodsData.isButtonShow = true; | |||
clearInterval(this.goodsData.timer); | |||
this.goodsData.countDown = 3; | |||
} | |||
},1000) | |||
} else if(this.goodsData.checkCount >= 2){ | |||
this.goodsData.isButtonShow = true; | |||
this.goodsData.isShow = false; | |||
} | |||
}, | |||
// 选择省市区 | |||
onConfirmAddress(values) { | |||
this.form.address = values | |||
.filter((item) => !!item) | |||
.map((item) => item.name) | |||
.join('/'); | |||
this.showArea = false; | |||
}, | |||
// 选择学校 | |||
onConfirmSchool(values) { | |||
this.form.schoolName = values; | |||
this.showSchool = false; | |||
}, | |||
// 选择年级班级 | |||
onClassFinish({ selectedOptions }) { | |||
this.showClass = false; | |||
this.form.className = selectedOptions.map((option) => option.text).join('/'); | |||
}, | |||
// 选择学生 | |||
onConfirmStudent(values) { | |||
this.form.studentName = values; | |||
this.showStudent = false; | |||
}, | |||
// 选择家长手机号码 | |||
onConfirmPhone(values) { | |||
this.form.phoneNumber = Number(values); | |||
this.showPhone = false; | |||
}, | |||
// 校验不为空 | |||
validator(value) { | |||
return isNotNull(value); | |||
}, | |||
} | |||
} | |||
</script> | |||
<style scoped lang="scss"> | |||
.form-container { | |||
height: 100vh; | |||
width: 100vw; | |||
display: flex; | |||
flex-direction: column; | |||
overflow: hidden; | |||
/* padding: 5px; | |||
border-radius: 20px; */ | |||
background-color: #f7f8fa; | |||
.form-header { | |||
height: 25vh; | |||
display: flex; | |||
justify-content: center; | |||
align-items: center; | |||
padding: 10px; | |||
box-shadow: rgba(50, 50, 93, 0.25) 0px 2px 5px -1px, | |||
rgba(0, 0, 0, 0.3) 0px 1px 3px -1px; | |||
background-color: rgba(235, 233, 229, 0.726); | |||
.img-left { | |||
width: 120px; | |||
} | |||
.content-right { | |||
flex: 1; | |||
p { | |||
font-size: 14px; | |||
text-align: left; | |||
padding: 5px 10px; | |||
strong { | |||
text-align: left; | |||
} | |||
} | |||
} | |||
} | |||
.form-body { | |||
flex: 1; | |||
position: relative; | |||
overflow: scroll; | |||
/* padding: 10px; */ | |||
box-shadow: rgba(50, 50, 93, 0.25) 0px 2px 5px -1px, | |||
rgba(0, 0, 0, 0.3) 0px 1px 3px -1px; | |||
.know-tips { | |||
height: 120px; | |||
width: 100%; | |||
padding: 10px; | |||
h5 { | |||
font-size: 16px; | |||
text-align: left; | |||
padding: 5px; | |||
color: red; | |||
} | |||
p { | |||
font-size: 14px; | |||
padding: 5px; | |||
text-align: left; | |||
} | |||
} | |||
} | |||
.form-footer { | |||
height: 15vh; | |||
width: 100%; | |||
position: absolute; | |||
padding: 10px; | |||
bottom: 10px; | |||
left: 0; | |||
display: flex; | |||
justify-content: center; | |||
flex-direction: column; | |||
.van-button { | |||
height: 40px; | |||
background-color: #1989fa; | |||
color: white; | |||
border-radius: 5px; | |||
&.notSubmit { | |||
background-color: rgba(150, 150, 146, 0.904); | |||
} | |||
} | |||
} | |||
} | |||
</style> |