Files
medicine_app/pages/mine/wallet/recharge/index.vue
2025-04-16 08:57:34 +08:00

935 lines
23 KiB
Vue
Raw Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
<template>
<view class="container commonPageBox">
<!-- 公共组件-每个页面必须引入 -->
<public-module></public-module>
<z-nav-bar title="充值" bgColor="#258feb" fontColor="#fff" :homeState="options.source == 'order' ? 1000 : 2000"
:backState="options.source == 'order' ? 2000 : 1000" @click-home="handleHomeClick"></z-nav-bar>
<view>
<view class="cha_jine">
<view class="cj_title PM_font">充值金额
</view>
<view class="cj_xiang">
<view v-for="(item, index) in cjList" @click="chosPric(item)" :class="
stepsCj.priceTypeId == item.priceTypeId
? 'Tab_cj cj_price'
: 'cj_price'
">
<view
class="pr_jg"
style="display: flex; align-items: center; justify-content: center"
>
<image
src="@/static/icon/currency.png"
alt=""
style="width: 40rpx; height: 40rpx; margin-right: 10rpx"
/>
{{ item.money }}
</view>
<view class="pr_yl" style="color: #565455"
>{{ item.realMoney }}</view
>
<view class="pr_lj" v-if="item.description&&item.description!=''"
> {{item.description}}</view
>
</view>
<br clear="both" />
</view>
<view
><text style="font-size: 24rpx; color: #8e8e8e; font-weight: 500"
>说明 : 天医币属于虚拟产品一经购买概不退还</text
></view
>
</view>
<view class="cha_fangsh">
<view class="cf_title PM_font">支付方式</view>
<view class="cf_radio">
<u-radio-group v-model="payType">
<view style="width: 100%" v-if="isAndroid">
<view v-for="(item, index) in paylist" :key="index" @click="choseType(item.id)"
:class="payType == item.id ? 'Tab_xf cf_xuanx' : 'cf_xuanx'">
<image class="pay_item_img" :src="item.imgUrl" mode="aspectFil">
</image>
{{ item.title }}
<u-radio :key="index" activeColor="#258feb" :name="item.id"
style="float: right; margin-top: 5rpx"></u-radio>
</view>
</view>
<view style="width: 100%" v-else>
<view v-for="(item, index) in iosPaylist" @click="choseType(item.id)"
:class="payType == item.id ? 'Tab_xf cf_xuanx' : 'cf_xuanx'">
<image class="pay_item_img" :src="item.imgUrl" mode="aspectFil">
</image>
{{ item.title }}
<u-radio :key="index" activeColor="#258feb" :name="item.id"
style="float: right; margin-top: 5rpx"></u-radio>
</view>
</view>
</u-radio-group>
</view>
</view>
<view class="agree_wo flexbox" style="float: left; display: flex">
<radio-group class="agree">
<view v-for="(item, index) in argee" :key="index">
<radio class="agreeRadio" :value="item.id" :checked="item.id == radioValue" color="#258feb"
@click="radioCheck(index)"></radio>
</view>
</radio-group>
<view>* 我已阅读并同意<span class="highlight" @click="showXieyi">增值服务协议</span></view>
</view>
<view class="char_btn">
<view @click="goToPay">立即充值</view>
<!-- <view @click="iosPay" >立即充值</view> -->
</view>
</view>
<!-- 充值协议 -->
<u-popup :show="xieyiShow" :round="10" @close="xieyiShow = false">
<view class="tanchu">
<view class="dp_title">{{ xieyi.title }}</view>
<view style="max-height: 1000rpx; overflow-y: scroll">
<view v-html="xieyi.content"></view>
</view>
</view>
</u-popup>
<music-play :playData="playData"></music-play>
</view>
</template>
<script>
import musicPlay from "@/components/music.vue";
import $http from "@/config/requestConfig.js";
import {
checkIapOrder
} from "@/store/modules/common.js";
// import { // 引入ios支付
// Iap,
// IapTransactionState
// } from "@/utils/iap.js"
import {
mapState,
mapMutations
} from "vuex";
import {
setPay,
setPayAssign,
setWXPay
} from "@/config/utils";
// const IAPOrders = [ // 根据这些ids获取到苹果app内商品信息这些ids就是你上面设置的产品id
// 'add69'
// ]
export default {
data() {
return {
checking : false,
playData: {},
options: {},
xieyi: {
title: "",
content: "",
},
chargeOrderSn: "", // 通过query传过来的orderSN二次支付情况
xieyiShow: false,
stepsCj: {},
cjList: [],
argee: [{
value: false,
id: "1",
}, ], // 同意权限
radioValue: "",
orderSn: "", // 订单sn
productid: "",
isAndroid: true, // 是否为安卓环境
payType: 2,
// #ifdef APP-IOS
payType: 3,
// #endif
paylist: [{
title: "支付宝",
id: 2,
imgUrl: require("@/static/icon/pay_1.png"),
},
{
title: "微信",
id: 1,
imgUrl: require("@/static/icon/pay_2.png"),
},
],
iosPaylist: [{
title: "IAP支付",
id: 3,
imgUrl: require("@/static/icon/pay_2.png"),
}, ],
transaction: {
// 成功回调
},
urlList: {
list: "common/bookBuyConfig/getBookBuyConfigList",
},
};
},
//第一次加载
onLoad(options) {
this.options = options;
// 隐藏原生的tabbar
uni.hideTabBar();
this.chargeOrderSn = options.orderSn;
// console.log(e.orderSn,'orderSn')
},
//页面显示
onShow() {
// 隐藏原生的tabbar
// this.iphonepay()
uni.hideTabBar();
this.getDevName();
// setTimeout(()=>{
// uni.navigateTo({
// url:'/pages/user/persCount'
// })
// },2000)
},
computed: {
...mapState(["userInfo"]),
},
components: {
musicPlay,
},
//方法
methods: {
...mapMutations(["setUserInfo"]),
// 查询未关闭iap订单
async restoreComplateRequest() {
let that = this
console.log('检测未完成订单')
// if (!that.checking) {
// that.checking = true
// console.log(this.iapChannel, 'this.iapChannel')
await this.iapChannel.restoreCompletedTransactions({
manualFinishTransaction: true
}, function(results) {
// console.log(that.checking)
// results 格式为数组存放恢复的IAP商品交易信息对象 IAPTransaction通用需将返回的支付凭证传给后端进行二次认证
that.ComplateRequestArr = results
console.log('未完成订单数组共有:=》',that.ComplateRequestArr.length )
if (results && results.length > 0) {
results.map((item, index) => {
// "0"为正在支付;"1"为支付成功;"2"为支付失败;"3"为支付已恢复。
if (item.transactionState == '1') {
// 已经支付,但是没有走逻辑的内购订单 就发给后台做验证
that.iapCheck('未完成订单的验证',item, index)
// that.finishTransaction(item)
} else if(item.transactionState != '1' || item.transactionState != '0') {
// 不是正在支付订单,也不是已经支付订单就关闭掉
// 其他状态的内购订单
that.finishTransaction(item)
}
})
}
});
},
//回到首页
handleHomeClick(){
uni.switchTab({
url: '/pages/peanut/home'
});
},
// 关闭交易订单
finishTransaction(trans) {
this.iapChannel.finishTransaction(
trans,
(success) => {
console.log("关闭订单成功");
},
(fail) => {
console.log("关闭订单失败");
}
);
},
async showXieyi() {
var data = await this.$commonJS.getAgreement(106);
if (data.content) {
data.content = data.content.replace(
/<h5>/g,
'<view style="font-weight: bold;font-size: 32rpx;margin-top: 20rpx;margin-bottom: 20rpx;">'
);
data.content = data.content.replace(
/<\/h5>/g,
"</view>"
);
}
this.xieyi = data
this.xieyiShow = true;
},
radioCheck(index) {
// 勾选用户协议
this.argee.forEach((item) => {
item.isCheck = false;
});
if (this.radioValue == this.argee[index].id) {
this.radioValue = null;
} else {
this.radioValue = this.argee[index].id;
}
// console.log(this.radioValue)
},
requestPayment(orderInfo) {
let that = this
return new Promise((resolve, reject) => {
uni.requestPayment({
provider: 'appleiap',
orderInfo: orderInfo,
success: (res) => {
that.iapCheck(res);
resolve(res);
},
fail: (err) => {
uni.hideLoading()
// console.log('其他支付错误', err);
that.restoreComplateRequest()
if (err.code == 2) {
uni.showToast({
title: '取消支付,内购订单即将关闭',
icon: 'none'
})
} else {
uni.showToast({
title: '支付失败,内购订单即将关闭',
icon: 'none'
})
}
reject(err);
}
});
})
},
getProvider() {
return new Promise((resolve, reject) => {
uni.getProvider({
service: 'payment',
success: (res) => {
const iapChannel = res.providers.find((channel) => {
return (channel.id === 'appleiap')
})
resolve(iapChannel);
// 如果 iapChannel 为 null说明当前包没有包含iap支付模块。注意HBuilder基座不包含 iap 通道
}
});
})
},
async iphonepay() {
const that = this;
uni.showLoading({
title:"检测支付环境"
})
console.log("检测支付环境...");
this.iapChannel = await this.getProvider()
console.log('that.iapChannel',this.iapChannel);
if(this.iapChannel){
this.requestOrder();
}else{
uni.hideLoading()
uni.showToast({
title:'不支持内购支付',
icon:'none'
})
console.log("获取iap支付通道失败" + e.message, that.iapChannel);
}
},
requestOrder() {
uni.showLoading({
title: "获取商品信息",
mask: true,
});
const that = this;
console.log(that.stepsCj.priceTypeId, 88888888);
// ['xxxxx'] 是平台申请拿到的内购商品的id
let IAPOrders = [];
IAPOrders.push('p' + that.stepsCj.priceTypeId);
// console.log(IAPOrders, "IAPOrders");
// 新建订单
uni.showLoading({
title: "正在创建订单",
mask: true,
});
that.iapChannel.requestProduct(
IAPOrders,
function(event) {
// uni.hideLoading()
console.log(event, "event");
for (var index in event) {
var OrderItem = event[index];
// console.log(OrderItem, 'OrderItem')
console.log(OrderItem.productid, "OrderItem.productid");
that.topay(OrderItem.productid);
}
},
function(erroemsg) {
uni.showToast({
title: "商品获取失败",
icon: "none",
});
}
);
},
async topay(id) {
const that = this;
uni.showLoading({
title: "正在支付",
mask: true,
});
let orderInfo = {
productid: id,
username: that.orderSn, // 用户标识/订单标识
quantity:1,
manualFinishTransaction: true, // 3.5.1+ 支持,设置此参数后需要开发者主动关闭订单,参见下面的关闭订单方法 finishTransaction()
}
this.transaction = await this.requestPayment(orderInfo)
console.log('支付后的that.transaction',this.transaction);
},
iapCheck(result) {
let that = this;
console.log("进入后台验证");
uni.showLoading({
title:'正在验证订单结果'
})
let data = {
transactionId: result.transactionIdentifier, // 支付交易id
customerOid: that.userInfo.id,
productId: result.payment.productid.slice(1), // 产品id
orderId: result.payment.username, // 系统订单号
receiptData: result.transactionReceipt, // 苹果返回收据
// isSandBox:true
// body: that.stepsCj.priceTypeId // 充值类型id
};
console.log("提交给后台的数据",data);
$http
.request({
url: "/Ipa/veri",
method: "POST", // POST、GET、PUT、DELETE具体说明查看官方文档
data,
header: {
//默认 无 说明:请求头
"Content-Type": "application/json",
},
})
.then((res) => {
console.log(JSON.stringify(res));
if (res.code == 0) {
uni.hideLoading()
uni.showToast({
title:'充值成功!',
icon:'success'
})
console.log("充值订单已处理,请留意账户金额变动....");
// 服务器验证票据有效后在客户端关闭订单 (iapChannel.finishTransaction)
that.finishTransaction(result);
}
})
.catch((e) => {
uni.hideLoading()
console.log('后台验证失败=>',e);
uni.showModal({
title: "提示",
showCancel: false,
content: "支付验证失败请稍后重启app如不能解决您的问题可联系官方客服",
success: function(res) {
if (res.confirm) {
console.log("用户点击确定");
}
},
});
});
},
getDevName() {
// 获取使用环境
if (uni.getSystemInfoSync().platform === "android") {
this.isAndroid = true;
// console.log('运行Android上')
} else {
this.isAndroid = false;
// console.log('运行iOS上')
}
this.getData();
},
// 获取充值金额
getData() {
// console.log(this.isAndroid)
if (this.isAndroid) {
this.getAndorList();
} else {
this.getAppleList();
}
},
// 安卓充值列表
getAndorList() {
var data = {
type: "point",
qudao: "Android",
};
$http
.request({
url: this.urlList.list,
method: "POST", // POST、GET、PUT、DELETE具体说明查看官方文档
data,
header: {
//默认 无 说明请求头1
"Content-Type": "application/json",
},
})
.then((res) => {
console.log("res at line 389:", res);
console.log("res at line 388:", res);
this.cjList = res.bookBuyConfigList;
console.log("this.cjList at line 389:", this.cjList);
this.stepsCj = res.bookBuyConfigList[0];
});
},
// 苹果充值列表
getAppleList() {
var data = {
type: "point",
qudao: "IOS",
};
$http
.request({
url: this.urlList.list,
method: "POST", // POST、GET、PUT、DELETE具体说明查看官方文档
data,
header: {
//默认 无 说明请求头1
"Content-Type": "application/json",
},
})
.then((res) => {
console.log("res at line 403:", res);
this.cjList = res.bookBuyConfigList;
this.stepsCj = res.bookBuyConfigList[0];
});
},
// 点击充值金额
chosPric(e) {
this.stepsCj = e;
console.log(e);
},
// 选择支付方式1
choseType(e) {
let that = this;
that.payType = e;
},
//ios充值
iosPay() {
// 苹果内购实现思路:
// 1.先确认支付通道是否包含苹果内购
// 2.检查一下是否存在上次未处理完的订单(主要是支付成功没有走回调的订单),异常订单直接关闭掉,成功没有走回调的提交给后台进行验证
// 3.请求并创建新的订单
this.iphonepay();
},
// 充值
goToPay() {
this.kaiChar();
},
// 正常充值
kaiChar() {
// 常规充值
if (this.radioValue == "1") {
uni.showLoading({
title: "支付中,请勿离开",
icon: "loading",
});
let that = this;
let data = {
userId: that.userInfo.id, //下单人ID
userPhone: that.userInfo.tel, //收货人手机号
paymentMethod: that.payType, //2支付宝1微信3ios内购
orderMoney: that.stepsCj.money * 1, //订单金额
districtMoney: 0, //优惠金额
realMoney: that.stepsCj.money * 1, //实收金额
orderStatus: 0, //订单状态
orderType: "point", //订单类型
appName: "wumen",
come: "2",
productId: that.stepsCj.priceTypeId, // 充值的类型id
};
$http
.request({
url: "book/buyOrder/rechargeSave",
method: "POST", // POST、GET、PUT、DELETE具体说明查看官方文档
data,
header: {
//默认 无 说明请求头1
"Content-Type": "application/json",
},
})
.then((res) => {
that.orderSn = res.orderSn;
uni.hideLoading();
if (res.code == 0) {
if (that.payType == 2) {
setPay({
typePay: "alipay",
subject: "point",
totalAmount: that.stepsCj.money,
type: that.payType,
relevanceoid: res.orderSn,
body: that.stepsCj.priceTypeId,
},
(res) => {
if (res.success) {
uni.showToast({
title: "支付成功",
});
setTimeout(() => {
uni.navigateTo({
url: "/pages/mine/wallet/index/index?source=recharge",
});
}, 2000);
} else {
uni.showToast({
title: "支付失败",
icon: "none",
image: "../../../static/icon/ic_close.png",
});
}
}
);
} else if (that.payType == 1) {
// 微信支付
that.orderSn = res.orderSn;
let data1 = {
orderSn: res.orderSn,
buyOrderId: that.stepsCj.priceTypeId,
totalAmount: that.stepsCj.money,
};
console.log(data1, "data1");
// console.log(this.userInfo.channelList,'channelList')
// this.userInfo.channelList.map(item => {
// if(item.id == "wxpay"){
// console.log('支持微信支付')
setWXPay(data1, (res) => {
if (res.success) {
uni.showToast({
title: "支付成功",
});
setTimeout(() => {
uni.navigateTo({
url: "/pages/mine/wallet/index/index?source=recharge",
});
}, 2000);
} else {
console.log(res);
if (res.data.errMsg.indexOf("User canceled") != -1) {
uni.showToast({
title: "用户取消支付",
icon: "none",
image: "../../../static/icon/ic_close.png",
});
} else {
uni.showToast({
title: "支付失败",
icon: "none",
image: "../../../static/icon/ic_close.png",
});
}
}
});
// }
// })
} else if (that.payType == 3) {
console.log("苹果支付");
that.iosPay();
}
}
});
} else {
uni.showToast({
title: "请勾选 已阅读会员服务协议",
icon: "none",
});
return false;
}
},
// 跳转
onPageJump(url) {
uni.navigateTo({
url: url,
});
},
},
};
</script>
<style lang="scss" scoped>
@import "@/style/mixin.scss";
.tanchu {
padding: 40rpx 30rpx 40rpx 30rpx;
position: relative;
.dp_title {
font-size: 32rpx;
margin-bottom: 50rpx;
color: #555;
text-align: center;
font-weight: bold;
}
.dp_add {
position: absolute;
top: 40rpx;
right: 30rpx;
font-size: 22rpx;
background-color: #fd6004;
color: #fff;
border-radius: 10rpx;
padding: 5rpx 10rpx;
.u-icon {
display: inline-block;
margin-right: 5rpx;
}
}
.addressItem {
border: 2px dashed #d9d9d9;
border-radius: 10rpx;
width: 100%;
display: flex;
padding: 20rpx 10rpx;
margin: 25rpx 0 0 0;
align-items: center;
background-color: #fff;
.addrContent {
margin-left: 40rpx;
flex: 1;
.addrContentTop {
display: flex;
align-items: flex-end;
margin: 0 0 15rpx 0;
position: relative;
.userName {
font-size: 35rpx;
font-weight: bold;
margin-right: 30rpx;
}
.userTel {
font-size: 25rpx;
color: #888;
}
.userMoren {
border: 1px solid #fd6004;
color: #fd6004;
padding: 3rpx 10rpx;
font-size: 22rpx;
border-radius: 10rpx;
margin: 0 0 0 20rpx;
}
.chooseCheck {
position: absolute;
top: 3rpx;
right: 6rpx;
}
}
.addrContentBottom {
font-size: 32rpx;
}
}
}
.addressItem.addItem_style {
border-color: #fd6004;
}
.youhuiItem {
border: 1px solid #d9d9d9;
border-radius: 10rpx;
width: 100%;
display: flex;
padding: 20rpx 10rpx;
margin: 25rpx 0 0 0;
align-items: center;
background-color: #fff;
font-size: 30rpx;
}
.youhuiItem>view {
float: left;
}
.youhuiItem.youItem_style {
border-color: #fd6004;
}
}
.agreeRadio {
zoom: 0.8;
}
.cha_jine {
margin: 40rpx 30rpx 0 30rpx;
.cj_title {
font-size: 36rpx;
font-weight: bold;
}
.cj_xiang {
margin-top: 40rpx;
.cj_price {
border: 4rpx solid #ebebeb;
// box-shadow: 0 0 20rpx 0 #0000001a;
float: left;
width: 31%;
margin: 0 3% 30rpx 0;
text-align: center;
padding: 25rpx 0 30rpx 0;
border-radius: 15rpx;
position: relative;
color: #2d2d2d;
.pr_jg {
font-size: 38rpx;
margin: 0rpx 0 10rpx 0;
font-weight: bold;
}
.pr_yl {
font-size: 28rpx;
// text-decoration: line-through;
color: #575555;
}
.pr_lj {
background-image: linear-gradient(90deg, #258feb 0%, $themeColor 100%);
color: #fff;
position: absolute;
top: -22rpx;
right: -22rpx;
font-size: 24rpx;
padding: 5rpx 4rpx;
border-top-left-radius: 20rpx;
border-bottom-right-radius: 20rpx;
}
}
.cj_price:nth-child(3n) {
margin-right: 0;
}
.Tab_cj {
// box-shadow: 0 0 20rpx 0 #fe700bcc;
box-shadow: 0px 0px 3px 0px $themeColor !important;
border: 4rpx solid $themeColor;
color: #258feb;
background: #e3f7ff !important;
.pr_yl {
color: #258feb !important;
}
}
}
}
.highlight {
color: $uni-color-primary;
}
.cha_fangsh {
padding: 40rpx 30rpx;
.cf_title {
font-size: 46rpx;
color: $themeColor;
}
.cf_radio {
margin-top: 20rpx;
.cf_xuanx {
font-size: 32rpx;
padding: 20rpx 0;
margin-bottom: 20rpx;
border-bottom: 1px solid #ededed;
image {
width: 40rpx;
height: 40rpx;
display: inline-block;
margin-right: 20rpx;
vertical-align: bottom;
}
}
.Tab_xf {
// background-color: #fdf1e9cc;
}
}
}
.agree_wo {
color: #aaa;
font-size: 25rpx;
margin-top: 30rpx;
padding: 30rpx;
// margin: 40rpx 50rpx 0 50rpx;
padding-bottom: 180rpx;
}
.char_btn {
position: fixed;
left: 0;
right: 0;
bottom: 30rpx;
view {
background-image: linear-gradient(90deg, #258feb 0%, $themeColor 100%);
color: #fff;
width: 90%;
margin: 0 auto;
text-align: center;
font-size: 35rpx;
font-weight: bold;
padding: 25rpx 0;
border-radius: 50rpx;
}
}
.pay_item_img {
width: 50rpx;
height: 50rpx;
float: left;
margin-right: 20rpx;
}
.agree {
width: auto !important;
}
.commonPageBox {
background-color: #fff !important;
}
</style>