feat: 接入微信小程序支付
This commit is contained in:
@@ -1,7 +1,5 @@
|
||||
{
|
||||
"pages": [
|
||||
"pages/web-view/index"
|
||||
],
|
||||
"pages": ["pages/web-view/index", "pages/wechat-pay/index"],
|
||||
"window": {
|
||||
"navigationBarTitleText": "百梦",
|
||||
"navigationBarBackgroundColor": "#0b0f14",
|
||||
|
||||
@@ -343,7 +343,7 @@ Page({
|
||||
},
|
||||
|
||||
handleWebViewMessage(event) {
|
||||
// 中文注释:H5 如需和小程序壳通信,可通过 wx.miniProgram.postMessage 发送轻量消息。
|
||||
// 中文注释:支付由独立 native 页面承接,web-view 消息只保留调试输出。
|
||||
console.info('[web-view] message', event.detail);
|
||||
},
|
||||
});
|
||||
|
||||
83
miniprogram/pages/wechat-pay/index.js
Normal file
83
miniprogram/pages/wechat-pay/index.js
Normal file
@@ -0,0 +1,83 @@
|
||||
function parsePayParams(rawValue) {
|
||||
try {
|
||||
const params = JSON.parse(decodeURIComponent(String(rawValue || '')));
|
||||
if (!params || typeof params !== 'object') {
|
||||
return null;
|
||||
}
|
||||
return params;
|
||||
} catch (error) {
|
||||
console.error('[wechat-pay] parse params failed', error);
|
||||
return null;
|
||||
}
|
||||
}
|
||||
|
||||
function requestPayment(payParams) {
|
||||
return new Promise((resolve) => {
|
||||
wx.requestPayment({
|
||||
timeStamp: String(payParams.timeStamp || ''),
|
||||
nonceStr: String(payParams.nonceStr || ''),
|
||||
package: String(payParams.package || ''),
|
||||
signType: payParams.signType || 'RSA',
|
||||
paySign: String(payParams.paySign || ''),
|
||||
success() {
|
||||
resolve('success');
|
||||
},
|
||||
fail(error) {
|
||||
const errMsg = error && error.errMsg ? error.errMsg : '';
|
||||
resolve(/cancel/i.test(errMsg) ? 'cancel' : 'fail');
|
||||
},
|
||||
});
|
||||
});
|
||||
}
|
||||
|
||||
function appendPayResult(url, requestId, status) {
|
||||
const value = `${requestId}:${status}`;
|
||||
const hashIndex = String(url || '').indexOf('#');
|
||||
const baseUrl =
|
||||
hashIndex >= 0 ? String(url).slice(0, hashIndex) : String(url || '');
|
||||
const rawHash = hashIndex >= 0 ? String(url).slice(hashIndex + 1) : '';
|
||||
const params = new URLSearchParams(rawHash);
|
||||
params.set('wx_pay_result', value);
|
||||
return `${baseUrl}#${params.toString()}`;
|
||||
}
|
||||
|
||||
function notifyPreviousWebView(requestId, status) {
|
||||
const pages = getCurrentPages();
|
||||
const previousPage = pages.length >= 2 ? pages[pages.length - 2] : null;
|
||||
if (previousPage && typeof previousPage.setData === 'function') {
|
||||
previousPage.setData({
|
||||
webViewUrl: appendPayResult(
|
||||
previousPage.data.webViewUrl,
|
||||
requestId,
|
||||
status,
|
||||
),
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
Page({
|
||||
data: {
|
||||
title: '正在拉起支付',
|
||||
errorMessage: '',
|
||||
},
|
||||
|
||||
async onLoad(query) {
|
||||
const requestId = String(query.requestId || '');
|
||||
const payParams = parsePayParams(query.payParams);
|
||||
if (!requestId || !payParams) {
|
||||
this.setData({
|
||||
title: '支付失败',
|
||||
errorMessage: '缺少支付参数。',
|
||||
});
|
||||
return;
|
||||
}
|
||||
|
||||
const status = await requestPayment(payParams);
|
||||
notifyPreviousWebView(requestId, status);
|
||||
wx.navigateBack();
|
||||
},
|
||||
|
||||
handleBack() {
|
||||
wx.navigateBack();
|
||||
},
|
||||
});
|
||||
3
miniprogram/pages/wechat-pay/index.json
Normal file
3
miniprogram/pages/wechat-pay/index.json
Normal file
@@ -0,0 +1,3 @@
|
||||
{
|
||||
"navigationBarTitleText": "微信支付"
|
||||
}
|
||||
11
miniprogram/pages/wechat-pay/index.wxml
Normal file
11
miniprogram/pages/wechat-pay/index.wxml
Normal file
@@ -0,0 +1,11 @@
|
||||
<view class="pay-screen">
|
||||
<view class="pay-card">
|
||||
<view class="pay-title">{{title}}</view>
|
||||
<view wx:if="{{errorMessage}}" class="pay-text pay-text--danger">
|
||||
{{errorMessage}}
|
||||
</view>
|
||||
<button wx:if="{{errorMessage}}" class="ghost-button" bindtap="handleBack">
|
||||
返回
|
||||
</button>
|
||||
</view>
|
||||
</view>
|
||||
48
miniprogram/pages/wechat-pay/index.wxss
Normal file
48
miniprogram/pages/wechat-pay/index.wxss
Normal file
@@ -0,0 +1,48 @@
|
||||
.pay-screen {
|
||||
min-height: 100vh;
|
||||
display: flex;
|
||||
align-items: center;
|
||||
justify-content: center;
|
||||
padding: 48rpx;
|
||||
background: #0b0f14;
|
||||
box-sizing: border-box;
|
||||
}
|
||||
|
||||
.pay-card {
|
||||
width: 100%;
|
||||
max-width: 560rpx;
|
||||
padding: 36rpx;
|
||||
border: 1rpx solid rgba(255, 255, 255, 0.14);
|
||||
border-radius: 12rpx;
|
||||
background: rgba(255, 255, 255, 0.06);
|
||||
box-sizing: border-box;
|
||||
}
|
||||
|
||||
.pay-title {
|
||||
font-size: 34rpx;
|
||||
font-weight: 600;
|
||||
line-height: 1.35;
|
||||
color: #f5f7fb;
|
||||
}
|
||||
|
||||
.pay-text {
|
||||
margin-top: 16rpx;
|
||||
font-size: 26rpx;
|
||||
line-height: 1.55;
|
||||
color: rgba(245, 247, 251, 0.72);
|
||||
}
|
||||
|
||||
.pay-text--danger {
|
||||
color: #ffb4a9;
|
||||
}
|
||||
|
||||
.ghost-button {
|
||||
margin-top: 28rpx;
|
||||
width: 100%;
|
||||
border-radius: 8rpx;
|
||||
border: 1rpx solid rgba(255, 255, 255, 0.24);
|
||||
background: transparent;
|
||||
color: rgba(245, 247, 251, 0.86);
|
||||
font-size: 26rpx;
|
||||
line-height: 2.6;
|
||||
}
|
||||
Reference in New Issue
Block a user