记录微信jsapi公众号支付全程
程序员文章站
2022-07-01 16:32:57
<template>
<view class="content">
<div class="content-2">
<bar @isModalShow="isModalShow"></bar>
</div>
<div class="content-1">
<user :user="user" :context="context" :addTime="addTime"></user>
</div>
<div class="content-special" >
<component v-for="(item,index) in context" :key="index" :is="item.type == 0 ? 'pageText': item.type == 1 ? 'pagetImg': item.type == 2 ? 'shareAudio' : item.type == 3 ? 'pagetVideo' : 'pagetPpt'" :textContext="item.content" :userCharge="item.isFree" :contextImg="item.url" :imageHeight="item.imageHeight" :imageWidth="item.imageWidth" :classNameA="index" :contextAudio="item.recordTime" :contextVideo="item.url" :contextPoster="item.thumbUrl" :contextPpt="item.url" :fileContent="item.fileName" :likeCount="likeCount" :commentCount="commentCount"/>
<paget-comment :likeCount="likeCount" :commentCount="commentCount"></paget-comment>
</div>
<div class="content-3">
<group-card></group-card>
</div>
<!-- <div class="content-4">
<no-data></no-data>
</div> -->
<comment-mask v-show="false"></comment-mask>
<view class="content-5" v-show="isBuyTheme">
<no-data></no-data>
<view class="button-container">
<view class="button" @click="openInfo(0)">
<span class="button-content">加入社群所有内容免费看</span>
<text class="limitMask-content-t1">
<span class="limitMask-content-t1-p1">¥</span>
<span class="limitMask-content-t1-p2">{{cardInfo.entryFee}}</span>
<span class="limitMask-content-t1-p3">/{{cardInfo.feeType == 1 ? '月' : cardInfo.feeType == 2? '季' : '年'}}</span>
</text>
<div class="div1"></div>
</view>
</view>
</view>
<view class="content-6" v-show="isBuyTheme">
<view class="content-6-button-container">
<view class="content-6-button-container-button" @click="openInfo(1)">¥{{cardInfo.entryFee}} 查看更多内容</view>
</view>
</view>
<show-modal :isShow="isShow" @isModalShowT="isModalShowT" @isModalShowS="isModalShowS"></show-modal>
<!-- <show-modals :isShow="isShows" @isModalShowT="isModalShowTs" @isModalShowS="isModalShowSs"></show-modals> -->
</view>
</template>
<script>
import noData from "../../components/noData/noData.vue"
import user from "../../components/page1/content1/user.vue"
import commentMask from "../../components/wuxiaobo/commentMask.vue"
import bar from "../../components/wuxiaobo/bar.vue"
import axios from 'axios'
import md5 from 'js-md5'
import showModal from '../../components/zhangxu-showModal/show-modal.vue'
import showModals from '../../components/zhangxu-showModal/show-modals.vue'
// import link from '../../static/link.js'
export default {
data () {
return {
unifyPayId: '',
activeItem:'',
user: {},
context: [],
contextPoster: '',
contextPpt: '',
addTime: "",
likeCount: 0,
commentCount: 0,
cardInfo: {},
time: '',
nums: '',
mweb_url: '',
resXml: {},
openId: '',
sign: '',
signB: '',
isShow: false,
isShows: false,
isBuyTheme: true,
communityPrice: 0,
totalFee: "",
token: ''
}
},
props: {
},
components: {
noData,
user,
commentMask,
showModal,
showModals,
bar,
pagetImg: ()=>import("../../components/page2/pagetImg.vue"),
pagetVideo: ()=>import("../../components/page2/pagetVideo.vue"),
pagetPpt: ()=>import("../../components/page2/pagetPpt.vue"),
pagetComment:()=>import("../../components/page2/pagetComment.vue"),
groupCard:()=>import("../../components/page3/groupCard.vue"),
shareAudio:()=>import('../../components/page2/shareAudio.vue'),
pageText:()=>import('../../components/page2/pageText.vue')
},
methods: {
isModalShow () {
this.isShow = true
},
isModalShowT () {
this.isShow = false
},
isModalShowS () {
this.isShow = false
},
// isModalShowTs () {
// this.isShows = false
// },
// isModalShowSs () {
// this.isShows = false
// let that = this
// setTimeout(function () {
// that.checkOrder()
// }, 3000)
// },
request () {
var sHref = window.location.href;
var argsb = sHref.split('?')[sHref.split("?").length-1]
let args = []
args.push(argsb)
if(args[0] == sHref){
return "";
}
var arr = args[0].split('&');
var obj = {};
for(var i = 0;i< arr.length;i++){
var arg = arr[i].split('=');
obj[arg[0]] = arg[1];
}
let communityId = obj.communityId
uni.request({
url: 'http://121.196.178.39:8000/api/community/card', //仅为示例,并非真实接口地址。
data: {
"id": communityId
},
method: 'POST',
header: {
header: { 'content-type': 'application/x-www-form-urlencoded'}
},
success: (res) => {
this.cardInfo = res.data.data
this.communityPrice = res.data.data.entryFee
},
fail: function(res) {
console.log(res.data);
}
});
},
getInfo() {
var sHref = window.location.href;
var argsb = sHref.split('?')[sHref.split("?").length-1]
let args = []
args.push(argsb)
if(args[0] == sHref){
return "";
}
var arr = args[0].split('&');
var obj = {};
for(var i = 0;i< arr.length;i++){
var arg = arr[i].split('=');
obj[arg[0]] = arg[1];
}
let themeId = obj.themeId
uni.request({
url: 'http://121.196.178.39:8000/api/theme/detail', //仅为示例,并非真实接口地址。
data: {
"id": themeId
},
method: 'POST',
header: {
header: { 'content-type': 'application/x-www-form-urlencoded'}
},
success: (res) => {
if (res.data.status == 200) {
this.isAll = true
// user
this.user = res.data.data.user
this.$set(this.user, 0, res.data.data.user)
// addTime
this.addTime = res.data.data.addTime
// context
this.context = res.data.data.context
this.context = JSON.parse(this.context)
// debugger
let arr = []
let arrPic = []
this.context.forEach(item => {
if (item.type == 0) {
// 第一部分 文本
arr.push('pageText')
} else if (item.type == 1) {
// 第二部分 图片
arr.push('pagetImg')
arrPic.push('pagetImg')
console.log(arrPic.length, "pic size")
// this.arrPicLength = arrPic.length
}else if (item.type == 2) {
// 第二部分 音频
arr.push('shareAudio')
}else if (item.type == 3) {
// 第二部分 视频
arr.push('pagetVideo')
}else if (item.type == 4) {
// 第二部分 ppt文件
arr.push('pagetPpt')
}
})
// likeCount
this.likeCount = res.data.data.likeCount
// commentCount
this.commentCount = res.data.data.commentCount
} else {
this.$router.push({ path: '../../pages/delete/noData'});
}
},
fail: function(res) {
console.log(res.data);
}
});
},
GetRequest(url) {
var obj = {}
var arr1 = url.split("?")
var arr2 = arr1[1].split("&")
for(var i=0 ; i < arr2.length; i++){
var res = arr2[i].split("=")
obj[res[0]] = res[1]
}
return obj
},
isWeiXin() {
var browser = {
versions: (function () {
var u = navigator.userAgent
var app = navigator.appVersion
return { // 移动终端浏览器版本信息
trident: u.indexOf('Trident') > -1, // IE内核
presto: u.indexOf('Presto') > -1, // opera内核
webKit: u.indexOf('AppleWebKit') > -1, // 苹果、谷歌内核
gecko: u.indexOf('Gecko') > -1 && u.indexOf('KHTML') === -1, // 火狐内核
mobile: !!u.match(/AppleWebKit.*Mobile.*/), // 是否为移动终端
ios: !!u.match(/\(i[^;]+;( U;)? CPU.+Mac OS X/), // ios终端
android: u.indexOf('Android') > -1 || u.indexOf('Linux') > -1, // android终端或uc浏览器
iPhone: u.indexOf('iPhone') > -1, // 是否为iPhone或者QQHD浏览器
iPad: u.indexOf('iPad') > -1, // 是否iPad
webApp: u.indexOf('Safari') === -1 // 是否web应该程序,没有头部与底部
}
}()),
language: (navigator.browserLanguage || navigator.language).toLowerCase()
}
// window.navigator.userAgent属性包含了浏览器类型、版本、操作系统类型、浏览器引擎类型等信息,这个属性可以用来判断浏览器类型
if (browser.versions.mobile) { // 判断是否是移动设备打开。browser代码在下面
var ua = navigator.userAgent.toLowerCase() // 获取判断用的对象
if (ua.indexOf('micromessenger') != -1) {
return 0
} else {
return 1
}
} else {
// 否则就是PC浏览器打开
return 2
}
},
getCode() {
if (this.isWeiXin() === 1 || this.isWeiXin() === 2) {
alert('请在微信中打开')
} else {
var result = this.isWeiXin()
if (result === 0) {
var that = this
setTimeout(function () {
window.location.href = 'https://open.weixin.qq.com/connect/oauth2/authorize?appid=wxcdbe7983be8fb746&redirect_uri=' + encodeURIComponent(window.location.href) + '&response_type=code&scope=snsapi_userinfo#wechat_redirect'
}, 500)
} else {
setTimeout(function () {
this.$layer.toast({
// className: 'icon-check', // 图标className 如果为空 toast位置位于下方,否则居中
content: '请在微信中打开',
time: 2000 // 自动消失时间 toast类型默认消失时间为2000毫秒
})
}, 500)
}
}
},
login() {
axios.post(
'http://121.196.178.39:8000/api/auth/otherLogin',
{ code: window.location.href.split('code=')[1].split('&state=')[0], loginType: 2 },
{
headers: {
'content-type': 'application/json'
}
}
).then(res => {
if (res.data.status == 503) {
this.isShow = true
} else if (res.data.status == 200) {
this.isBuyThemes()
this.openId = res.data.data.offiOpenid
this.token = res.data.data.token
localStorage.setItem('token', this.token)
this.getInfo()
} else {
}
})
},
isBuyThemes() {
var url = window.location.href
let urlData = this.GetRequest(url)
let detailId = urlData.themeId
uni.request({
url: 'http://121.196.178.39:8000/api/theme/isbuy', //仅为示例,并非真实接口地址。
data: {
"id": detailId
},
method: 'POST',
header: {
header: { 'content-type': 'application/x-www-form-urlencoded'}
},
success: (res) => {
var url = window.location.href
let urlData = this.urlObj(url)
let isBuy = res.data.data
if (isBuy) {
this.isBuyTheme = false
}
},
fail: function(res) {
console.log(res.data);
}
});
},
getNum(){
var chars = ['0','1','2','3','4','5','6','7','8','9','a','b','c','d','e','f','g','h','i','j','k','l','m','n','o','p','q','r','s','t','u','v','w','x','y','z'];
var nums="";
for(var i=0;i<32;i++){
var id = parseInt(Math.random()*35);
nums+=chars[id];
}
this.nums = nums
return nums;
},
openInfo (whichButton) {
this.getNum()
let timestamp = Math.round(new Date() / 1000)
this.time = timestamp.toString()
// 社群0 主题1
if (whichButton == 0) {
this.totalFee = "2"
} else if (whichButton == 1) {
this.totalFee = "1"
}
let dataBeforeSign = {
"appid": "wxcdbe7983be8fb746",
"body": "微信支付",
"mch_id": "1594545781",
"nonce_str": this.nums,
"notify_url": "http://121.196.178.39:8000/api/callBack/wx_pay_callBack",
"out_trade_no": this.time,
"openid": this.openId,
"spbill_create_ip": "121.196.178.39",
"total_fee": this.totalFee,
"trade_type": "JSAPI"
}
localStorage.setItem('time', this.time)
let arr = [];
for (var key in dataBeforeSign) {
arr.push(key)
}
arr.sort();
let str = '';
for (var i in arr) {
str += arr[i] + "=" + dataBeforeSign[arr[i]] + "&"
}
let stringA = str.substr(0, str.length - 1)
let stringSignTemp=stringA+"&key=ecde02f1dc9bbed7bf39ea922952bdf4"
this.sign=md5(stringSignTemp).toUpperCase()
let data = {
"appid": "wxcdbe7983be8fb746",
"body": "微信支付",
"mch_id": "1594545781",
"nonce_str": this.nums,
"notify_url": "http://121.196.178.39:8000/api/callBack/wx_pay_callBack",
"out_trade_no": this.time,
"openid": this.openId,
"spbill_create_ip": "121.196.178.39",
"total_fee": this.totalFee,
"trade_type": "JSAPI",
"sign": this.sign
}
// debugger
let xmll = this.$x2js.js2xml(data)
let xmlq = `<root>`+ xmll+ `</root>`
let xml = "\`"+xmlq+"\`"
uni.request({
url: 'http://121.196.178.39:8000/api/pay/unifiedorder', //仅为示例,并非真实接口地址。
data: {
"xml": xml
},
method: 'POST',
header: {
header: { 'content-type': 'application/x-www-form-urlencoded'}
},
success: (res) => {
let ress = res.data
let resXml = this.$x2js.xml2js(ress)
this.resXml = resXml
localStorage.setItem('unifyPayId', resXml.xml.prepay_id)
//!!! 一个新的随机戳 必须 踩坑
let timestamp = Math.round(new Date() / 1000)
let timeB = timestamp.toString()
// !!!一个新的随机串 必须 踩坑
let chars = ['0','1','2','3','4','5','6','7','8','9','a','b','c','d','e','f','g','h','i','j','k','l','m','n','o','p','q','r','s','t','u','v','w','x','y','z'];
let nums="";
for(let i=0;i<32;i++){
let id = parseInt(Math.random()*35);
nums+=chars[id];
}
let numsB = nums
// 不要有空格 或者两次都有空格 两次格式要相同
let dataBeforeSignAAA = {
"appId":"wxcdbe7983be8fb746",
"timeStamp":timeB,
"nonceStr":numsB,
"package":"prepay_id=" + resXml.xml.prepay_id,
"signType":"MD5"
}
let arr = [];
for (var key in dataBeforeSignAAA) {
arr.push(key)
}
arr.sort();
let str = '';
for (var i in arr) {
str += arr[i] + "=" + dataBeforeSignAAA[arr[i]] + "&"
}
let stringA = str.substr(0, str.length - 1)
let stringSignTemp=stringA+"&key=ecde02f1dc9bbed7bf39ea922952bdf4"
let signB=md5(stringSignTemp).toUpperCase()
function onBridgeReady() {
WeixinJSBridge.invoke(
'getBrandWCPayRequest', {
"appId":"wxcdbe7983be8fb746",
"timeStamp":timeB,
"nonceStr":numsB,
"package":"prepay_id=" + resXml.xml.prepay_id,
"signType":"MD5",
"paySign":signB
},
function(res){
if(res.err_msg == "get_brand_wcpay_request:ok" ){
alert(res.err_msg)
setTimeout( function (){
alert(res.err_msg)
try{
axios.post(
'http://121.196.178.39:8000/api/order/payQuery',
{ unifyPayId: localStorage.getItem('unifyPayId'), payType: "2"},
{
headers: {
'content-type': 'application/json',
'Authorization': localStorage.getItem('token') // token换成从缓存获取 改过了
}
}
).then(res => {
alert(res.data.msg)
if (res.data.data == "支付成功") {
alert(res.data.data )
}
})
}catch(e){
console.log(e)
}
}, 2000)
} else {
alert(res.err_msg)
}
});
}
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();
}
},
fail: function(res) {
console.log(res.data);
}
});
},
},
mounted() {
const that = this
this.$layer.toast({
// className: 'icon-check', // 图标className 如果为空 toast位置位于下方,否则居中
content: '请点击右上角在浏览器中打开',
time: 2000 // 自动消失时间 toast类型默认消失时间为2000毫秒
})
uni.setNavigationBarTitle({
title: '主题详情'
})
this.request()
var url = window.location.href
let urlData = this.GetRequest(url)
if (!urlData.code) {
this.id = urlData.id
this.getCode()
} else {
this.id = urlData.id
this.login()
}
}
}
</script>
<style scoped>
.content {
display: flex;
flex-direction: column;
}
.content-2 {
width: 100%;
height: 72rpx;
background: rgba(229,249,253,1);
}
.content-1 {
/* height: 1038rpx; */
width: 100%;
}
.content-special {
/* height: 1664rpx; */
width: 100%;
padding: 0 32rpx 0;
box-sizing: border-box;
}
.content-3 {
/* height: 526rpx; */
width: 100%;
background: #F5F7FA;
padding: 24rpx 32rpx;
box-sizing: border-box;
}
.content-4 {
height: 572rpx;
width: 100%;
}
.content-5 {
height: 624rpx;
width: 100%;
position: relative;
}
.button-container {
position: absolute;
top: 540rpx;
left: 32rpx;
height: 84rpx;
width: 382rpx;
background: #FFFFFF;
}
.button {
width: 382rpx;
height: 68rpx;
background:rgba(250,100,0,1);
box-shadow:0px 0px 10rpx 0px rgba(247,181,0,0.25);
border-radius: 50rpx;
position: relative;
}
.limitMask-content-t1 {
height: 44rpx;
width: 72rpx;
position: absolute;
color: #FFFFFF;
left: 294rpx;
top: 4rpx;
}
.limitMask-content-t1-p1 {
width: 16rpx;
height: 34rpx;
font-size:12px;
font-family:PingFangSC-Regular,PingFang SC;
font-weight:400;
color:#FFFFFF;
line-height: 34rpx;
}
.limitMask-content-t1-p2 {
width: 42rpx;
height: 44rpx;
font-size:16px;
font-family:PingFangSC-Medium,PingFang SC;
font-weight:500;
color:#FFFFFF;
line-height: 44rpx;
}
.limitMask-content-t1-p3 {
width: 36rpx;
height: 34rpx;
font-size:12px;
font-family:PingFangSC-Regular,PingFang SC;
font-weight:400;
color:#FFFFFF;
line-height:17px;
}
.div1{
width: 0;
height: 0;
border: 30rpx solid;
border-color:rgba(250,100,0,1) transparent transparent;
/* position: absolute;
left: 0;
bottom: 0; */
/* position:absolute; */
/* bottom:-14px; */
/* left:3px; */
position: absolute;
bottom: -42rpx;
left: 6rpx;
}
.div1::before {
/* content: '';
width:0;
height:0;
display:block;
border-style:solid;
border-width: 15px; */
/* border-color:rgba(250,100,0,1) transparent transparent; */
/* position:absolute;
bottom:-14px;
left:3px; */
}
.button-content {
width: 264rpx;
height: 34rpx;
font-size:12px;
font-family:PingFangSC-Regular,PingFang SC;
font-weight:400;
color:rgba(255,255,255,1);
line-height:17px;
position: absolute;
left: 24rpx;
top: 18rpx;
}
.content-6 {
height: 116rpx;
width: 100%;
position: relative;
background: #FFFFFF;
border-top: 2rpx solid #EBEEF5;
}
.content-6-button-container-button {
position: absolute;
top: 14rpx;
left: 32rpx;
width: 686rpx;
height: 84rpx;
background:linear-gradient(315deg,rgba(33,186,189,1) 0%,rgba(28,203,176,1) 100%);
box-shadow:0px 4rpx 16rpx 0px rgba(33,186,189,0.36);
border-radius: 42rpx;
text-align: center;
box-sizing: border-box;
padding-top: 20rpx;
font-size: 36rpx;
font-family:PingFangSC-Regular,PingFang SC;
font-weight:400;
color:rgba(255,255,255,1);
line-height: 50rpx;
}
</style>
本文地址:https://blog.csdn.net/weixin_44500533/article/details/107365202