前言

微信、快手、h5支付步骤大致相同,只有抖音是有自己的支付组件 项目同时支持多个(微信、快手、h5)平台支付,后端那边代码可以封装的

各平台支付大致流程都是相同的,总结了一下分为五个步骤

点击支付创建订单生成密钥和支付所需要的参数支付成功查询订单状态

一、微信支付

1.支付按钮

2.支付事件

payTap() {

let that = this

// 这些参数后端一般要的

let data = {

openid: this.openId, //用户id 必需

courseId: this.detailsObj.id, //课程id(商品id)必需

promoterId: this.promoterShareId ? this.promoterShareId : '', // 分销员id

couponId: this.detailsObj.receiveCouponId ? this.detailsObj.receiveCouponId : '', // 优惠卷id

}

// 如果一个项目里有多个平台支付,可以用传值来区分

// #ifdef MP-WEIXIN

data.platform = 1

// #endif

// #ifdef MP-KUAISHOU

data.platform = 2

// #endif

//创建订单

createWendaoOrder(data).then(res => {

// 返回密钥

createOrder({

orderId: res.data.orderId, // 订单id

openid: this.openId, // 用户id

}).then(res1 => {

// #ifdef MP-WEIXIN

let twoData = res1.data

// 微信支付api

// 参数向后端要 要确保每个值就有

uni.requestPayment({

appId: twoData.appId,

timeStamp: twoData.timeStamp,

nonceStr: twoData.nonceStr,

package: twoData.packageValue,

signType: twoData.signType,

paySign: twoData.paySign,

success(result) {

// 调起支付密码

if (result.errMsg == "requestPayment:ok") {

// 支付成功

uni.showLoading({

title: '获取订单状态..',

mask: true,

})

orderSuccess({

openid: that.openId, // 用户id

orderId: res.data.orderId // 订单id

}).then(res=>{

uni.hideLoading();

uni.showToast({

title: '支付成功',

icon: 'none'

});

// 重新请求下商品详情

that.detailFn()

})

} else {

uni.showModal({

title: '',

content: '支付失败',

showCancel: false,

icon: 'none',

success(res) {}

})

}

},

fail(result) {

console.log(result)

uni.showModal({

title: '',

content: '支付失败',

showCancel: false,

icon: 'none',

success(res) {}

})

},

})

// #endif

}).catch(res => {

console.log(res)

})

})

}

二、快手支付

1.支付按钮

2.支付事件

payTap() {

let that = this

// 这些参数后端一般要的

let data = {

openid: this.openId, //用户id 必需

courseId: this.detailsObj.id, //课程id(商品id)必需

promoterId: this.promoterShareId ? this.promoterShareId : '', // 分销员id

couponId: this.detailsObj.receiveCouponId ? this.detailsObj.receiveCouponId : '', // 优惠卷id

}

// 如果一个项目里有多个平台支付,可以用传值来区分

// #ifdef MP-WEIXIN

data.platform = 1

// #endif

// #ifdef MP-KUAISHOU

data.platform = 2

// #endif

//创建订单

createWendaoOrder(data).then(res => {

// 返回密钥

createOrder({

orderId: res.data.orderId, // 订单id

openid: this.openId, // 用户id

}).then(res1 => {

// 后端返回的是这些数据

// res1.data = {

// order_no: "1231xxxxxxxxxxxxxxx450"

// order_info_token: "ChJrc01wUGF5LmxxxxxxxxxxxxxxxWYYeulijTrRyDdowh6Lvtp2MIm-t5nlq4s3xxxxxxxxxxxxxxxxxxxuh217_-giIIHDQ8yTqZqghjVraGC_NjxxxxxxxxxxxxxxKAUwAQ"

// {

// 快手支付api

// #ifdef MP-KUAISHOU

ks.pay({

serviceId: '1',

orderInfo: res1.data,

success: function success(res2) {

// 调起支付密码

// 支付成功

uni.showLoading({

title: '获取订单状态..',

mask: true,

})

orderSuccess({

openid: that.openId, // 用户id

orderId: res.data.orderId // 订单id

}).then(res=>{

uni.hideLoading();

uni.showToast({

title: '支付成功',

icon: 'none'

});

// 重新请求下商品详情

that.detailFn()

})

},

fail: function fail(res) {

uni.showToast({

title: '支付失败',

icon: 'none'

})

}

})

// #endif

}).catch(res => {

console.log(res)

})

})

}

三、抖音支付

抖音有自己的支付组件和自己的下单页面,所以需要创建一个专属于抖音的组件,并把需要的参数进行传递

1.创建组件

1.新建ttcomponents文件夹,创建完后在ttcomponents下面再新建DyPayButton文件夹,然后在DyPayButton下面创建四个文件,分别为index.js、index.json、index.ttml、index.ttss 2.要创建在App.vue同级

先在App.vue 写baseUrl和getPhoneNumber函数

下面是那四个文件的内容 index.js

// 可以调用到app.vue里的方法

const app = getApp();

Component({

properties: {

mode: Number,

openId: {

type: [String, Number],

},

orderStatus:{

type: [String, Number],

},

detailsObj: {

type: Object,

},

goodsId: {

type: String,

value: "",

},

promoterShareId: Number,

},

data: {

},

methods: {

// 提交商品信息 这个函数一进页面就会调用的

getGoodsInfo(event) {

const that = this

return new Promise(resolve => {

// 定时器是为解决 优惠卷id获取不到问题

setTimeout(()=>{

tt.getSystemInfo({

success: (resPlatform)=> {

let pay = that.data.detailsObj.price * 100 // 价格单位是分

let promoterShareId = that.data.promoterShareId // 分销员id

let required = that.data.detailsObj.giveEntityIsNeedPhone // 是否强制获取手机号

let CouponId = that.data.detailsObj.receiveCouponId // 优惠卷id

// 用不到的值就不用传

let data = {

currentPrice: pay,

GoodsLabel: [{

type: 'NON_REFUNDABLE'

}

],

minLimits: 1,

maxLimits: 1,

dateRule: '周一至周日可用',

extra: {

promoterId: promoterShareId,

receiveCouponId: CouponId

},

validation: {

phoneNumber: {

required: required // 手机号是否必填

}

},

marketingVersion: 1,

}

// im客服需要提前开通

// 判断如果用户手机是ios就走客服支付, 把imId传上就自动跳转im客服页面了,安卓不要传这个id,否则可能会导致支付不了

if(resPlatform.platform == 'ios'){

data.imId = '3xxxxxxxx42'

}

// 然后将商品信息传入 resolve 函数

resolve(data);

}

});

},600)

})

},

onError(e) {

const {

errNo,

errMsg

} = e.detail;

if (errNo === 21514) {

tt.showToast({

title: "失败", // 内容

icon: "none", // 图标

});

} else if (errNo === 21513) {

tt.showToast({

title: "获取中", // 内容

icon: "none", // 图标

});

}

},

userLogin(event) {

const {

goodsId,

goodsType

} = event.detail

return new Promise((resolve, reject) => {

tt.login({

success(e) {

// 用户登录成功并获取信息,则调用 resolve 函数,跳转至提单页

resolve();

},

fail() {

// 用户登录失败,则跳转提单页失败

_this.showTost("登录失败")

}

});

});

},

payError(event) {

this.showTost(event.errMsg)

},

// 继续支付

handleContinutePay(event) {

const { status, outOrderNo, result } = event.detail;

if (status === 'success') {

const { code } = result;

if (code === 0) {

// 继续支付成功

// 刷新页面

this.triggerEvent("refreshData")

tt.showToast({

title: "支付成功",

});

}

} else {

// 继续支付失败

tt.showToast({

title: "继续支付失败",

icon: "none"

});

}

},

// 正式支付

newButtonPay(event) {

const {

status,

orderId,

outOrderNo,

result

} = event.detail;

if (status === 'success') {

const {

code

} = result;

if (code === 0) {

tt.showLoading({

title: "订单确认中...",

});

this.getOrderIsHaveData(outOrderNo)

} else {

// 支付失败(超时、取消、关闭)

this.showTost('支付失败(超时、取消、关闭)')

}

} else {

const {

errMsg

} = result;

this.showTost(errMsg)

}

},

showTost(tit, timeMs) {

let time = timeMs > 0 ? timeMs : 1500;

tt.showToast({

title: tit,

icon: "none",

duration: time,

});

},

// 重新订单

getOrderIsHaveData(orderId) {

let data = {

openid: this.data.openId,

orderId,

}

tt.request({

url: app.baseUrl() + "/order/order_success",

method: 'POST',

data,

success: (res) => {

this.setOrderIsHaveData(res.data.orderStatus, orderId)

}

})

},

setOrderIsHaveData(data, orderId) {

if (data == 0) {

setTimeout(() => {

_this.getOrderIsHaveData(orderId)

}, 1000);

} else {

tt.hideLoading();

tt.navigateBack(-1);

this.triggerEvent("refreshData")

}

},

// 退款

onApplyrefund(event) {

console.log(event)

const {

orderId

} = event.detail;

const extra = {

orderId

}; // 开发者需要透传的参数,可自定义内容

return new Promise(resolve => {

resolve(extra);

});

},

onRefund(event) {

console.log(event)

const {

status,

result

} = event.detail;

if (status === 'success') {

const {

refundId,

outRefundNo

} = result;

} else {

const {

errMsg

} = result;

tt.showToast({

title: e.detail.errMsg ? e.detail.errMsg : '失败',

icon: "none"

});

}

},

refundError(e) {

console.log(e)

if (e.detail.errNo == 21531) {

tt.showToast({

title: "不符合退款要求",

icon: "none"

});

} else {

tt.showToast({

title: e.detail.errMsg ? e.detail.errMsg : '失败',

icon: "none"

});

}

},

},

});

index.json

{

"component": true,

"usingComponents": {}

}

index.ttml

biz-line="{{2}}" bind:getgoodsinfo="getGoodsInfo" bind:placeorder="userLogin" marketing-ready="{{true}}"

bind:pay="newButtonPay" bind:error="onError">

bind:pay="handleContinutePay">

:refund-total-amount="{{orderData.coursePrice}}" biz-line="{{2}}" marketing-ready="{{true}}"

catch:applyrefund="onApplyrefund" catch:refund="onRefund" catch:error="refundError"

tt:if="{{orderData.orderStatus==1}}">

order-status="{{orderData.orderStatus=='4'?2:orderData.orderStatus=='2'?3:orderData.orderStatus=='5'?4:4 }}"

refund-id="{{orderData.orderId}}" biz-line="{{2}}" marketing-ready="{{true}}" catch:applyrefund="onApplyrefund"

catch:refund="onRefund" catch:error="refundError"

tt:if="{{orderData.orderStatus!=1 && orderData.orderStatus!=0}}">

index.ttss

按钮样式根据自己的来

.save_one {

width: 100%;

height: 100%;

}

.payButton {

display: flex;

align-items: center;

justify-content: center;

width: 310rpx;

height: 90rpx;

border-radius: 45rpx;

box-sizing: border-box;

background-color: #E10000;

color: #fff;

border: 2rpx solid #E10000;

}

.payButtonItem {

display: flex;

align-items: center;

justify-content: center;

width: 183rpx;

height: 57rpx;

background: #E10000;

border-radius: 29rpx;

border: 1rpx solid #E10000;

font-size: 26rpx;

font-family: "Noto Sans SC";

font-weight: 600;

color: #fff;

line-height: 37rpx;

box-sizing: border-box;

margin-right: 16rpx;

}

2.在pages.json给商品详情页面注册组件

"pages": [{

"path": "details/details",

"style": {

// #ifdef MP-TOUTIAO

// 这个是需要加的,否则显示不出来

"usingComponents": {

"zijie-pay-button": "/ttcomponents/DyPayButton/index"

},

//#endif

"navigationBarTitleText": "xxxx",

"enablePullDownRefresh": false

}

}]

3.在商品详情页面中使用组件

components:{

// #ifdef MP-TOUTIAO

"zijie-pay-button": "../../ttcomponents/DyPayButton/index",

//#endif

}

v-if="detailsObj.productId"

:openId="openId"

:mode='2'

:detailsObj="detailsObj"

:classsname="'save_one'"

:promoterShareId="promoterShareId"

@refreshData="refreshData"

>

>

// v-if: 判断有没有商品id

// openId: 用户id

// mode: 商品类型

// detailsObj: 商品详情页的数据

// classsname: 按钮类名

// promoterShareId: 分销员id

// @refreshData: 用于支付成功回调刷新页面

4.h5支付

主要是为解决微信ios无法支付的问题,ios走h5支付渠道

1.创建按钮

// 这个按钮是uView组件

text="联系老师"

v-if="isIosDouYin"

shape="circle"

color="#E10000"

:send-message-title="detailsObj.title?detailsObj.title:''"

:send-message-img="detailsObj.coverPicUrl"

:send-message-path="'/pages_details/details/details?courseId=' + detailsObj.id + '&promoterId=' + promoterShareId + '&couponId=' + detailsObj.receiveCouponId + '&appNameType=1&platform=1&openid=' + openId"

show-message-card="true"

open-type="contact">

// isIosDouYin: 判断是否为ios系统

// send-message-title: 商品标题

// :send-message-img: 商品封面

// :send-message-path: 跳转路径

// show-message-card: 发送卡片

2.创建页面

在详情页同级目录创建一个页面detailsContact.vue,后端可以重定向到这个页面

var _this;

export default {

data() {

return {

openid: '', // 用户id

h5PayData:{}, // h5提交的参数

h5OrderId: '' // 订单id

}

},

onLoad(options) {

_this = this

// 页面一进来就调用支付 带上路径传的值

this.payTap(options)

},

methods:{

payTap(queryObj) {

let that = this

that.openid = queryObj.openid

let data = {

openid: queryObj.openid, // 用户id

courseId: queryObj.courseId, // 课程id

promoterId: queryObj.promoterId ? queryObj.promoterId : 0, // 推广员id

couponId: queryObj.couponId ? queryObj.couponId : 0, // 优惠卷id

appNameType: queryObj.appNameType, // 区分哪个小程序

platform : queryObj.platform // 区分平台

}

createWendaoOrder1(data).then(res => {

createOrder1({

orderId: res.data.orderId,

openid: queryObj.openid,

}).then(res1 => {

// #ifdef H5

that.h5PayData = res1.data

that.h5OrderId = res.data.orderId

that.getWxOfficePay()

// #endif

}).catch(res => {

console.log(res)

})

})

},

getWxOfficePay() {

if (typeof WeixinJSBridge == "undefined") {

if (document.addEventListener) {

document.addEventListener('WeixinJSBridgeReady', _this.getWxOfficePayPage, false);

} else if (document.attachEvent) {

document.attachEvent('WeixinJSBridgeReady', _this.getWxOfficePayPage);

document.attachEvent('onWeixinJSBridgeReady', _this.getWxOfficePayPage);

}

} else {

_this.getWxOfficePayPage()

}

},

getWxOfficePayPage() {

const that = this

console.log("h5支付调起支付面板 ")

WeixinJSBridge.invoke(

'getBrandWCPayRequest', {

appId: _this.h5PayData.appId,

timeStamp: _this.h5PayData.timeStamp,

nonceStr: _this.h5PayData.nonceStr,

package: _this.h5PayData.packageValue,

signType: _this.h5PayData.signType,

paySign: _this.h5PayData.paySign,

},

function(res) {

if (res.err_msg == "get_brand_wcpay_request:ok") {

uni.showLoading({

title: '获取订单状态..',

mask: true,

})

// 确认订单

uni.request({

url: app.baseUrl() + "/order/order_success",

method: 'POST',

data: {

openid: that.openId,

orderId: that.h5OrderId

},

success: (res) => {

uni.hideLoading();

uni.showModal({

title: '',

content: '支付成功,请返回小程序查看课程',

showCancel: false,

icon: 'none'

})

}

})

} else {

uni.showModal({

title: '',

content: '支付失败',

showCancel: false,

icon: 'none',

success(res) {}

})

}

}

);

},

}

}

文章链接

评论可见,请评论后查看内容,谢谢!!!
 您阅读本篇文章共花了: