From c2476b9f85ec2948311c0949f3d5b83c03e75d4f Mon Sep 17 00:00:00 2001 From: iqudoo Date: Wed, 17 Jun 2026 12:50:02 +0800 Subject: [PATCH] =?UTF-8?q?=E6=94=AF=E4=BB=98?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- dist/index.d.ts | 162 +++++++++++++- dist/index.js | 2 +- package.json | 5 +- pnpm-lock.yaml | 154 ++++++++++++++ src/_core.js | 3 + src/_export.js | 69 ++++-- src/index.js | 3 +- src/services/payment/config.js | 11 + src/services/payment/env.js | 41 ++++ src/services/payment/index.js | 297 ++++++++++++++++++++++++++ src/services/payment/nativeQrView.js | 153 +++++++++++++ src/services/payment/oauth.js | 307 +++++++++++++++++++++++++++ src/services/web/index.js | 22 +- types/index.d.ts | 162 +++++++++++++- 14 files changed, 1338 insertions(+), 53 deletions(-) create mode 100644 src/services/payment/config.js create mode 100644 src/services/payment/env.js create mode 100644 src/services/payment/index.js create mode 100644 src/services/payment/nativeQrView.js create mode 100644 src/services/payment/oauth.js diff --git a/dist/index.d.ts b/dist/index.d.ts index 5613c23..0730d89 100644 --- a/dist/index.d.ts +++ b/dist/index.d.ts @@ -53,14 +53,6 @@ interface ScanConfigOptions { * 是否允许 H5 摄像头扫码:true 强制开启(仍需有媒体 API),false 强制关闭 */ webScanCameraEnabled?: boolean, - /** - * @deprecated 请用 webScanCameraEnabled;保留兼容 - */ - webScanCameraInWechat?: boolean, - /** - * @deprecated 摄像头权限已后置到 startScan,请用 webScanVideoAccessTimeout - */ - webScanCameraProbeTimeout?: number, /** * startScan 走 Web 摄像头前是否展示权限说明弹窗,默认 true */ @@ -196,6 +188,68 @@ interface ScanConfigOptions { * 扫码成功是否播放提示音,默认启用;任意识别模式匹配成功时生效 */ scanBeepEnabled?: boolean, + /** + * PC 微信 Native 扫码支付是否展示内置二维码弹层,默认 true + */ + paymentNativeQrEnabled?: boolean, + /** + * Native 支付二维码弹层标题 + */ + paymentNativeQrTitle?: string, + /** + * Native 支付二维码弹层说明文案 + */ + paymentNativeQrMessage?: string, + /** + * Native 支付二维码底部提示 + */ + paymentNativeQrHint?: string, + /** + * Native 支付二维码边长(像素),默认 220 + */ + paymentNativeQrSize?: number, + /** + * Native 支付二维码弹层遮罩样式 + */ + paymentNativeQrOverlayStyle?: string, + /** + * Native 支付二维码弹层面板样式 + */ + paymentNativeQrPanelStyle?: string, + /** + * Native 支付二维码关闭按钮样式 + */ + paymentNativeQrCloseButtonStyle?: string, + /** + * Native 支付二维码弹层遮罩 class + */ + paymentNativeQrOverlayClass?: string, + /** + * Native 支付二维码弹层面板 class + */ + paymentNativeQrPanelClass?: string, + /** + * 微信支付 OAuth 配置(paymentType 为 wechat 且微信内 JSAPI 时由 requestPayment 自动处理) + */ + initWechatPayment?: { + /** + * 用 code 换 openid,对应 api.biz.wechat.oauth + */ + oauthApiUrl?: string, + /** + * 获取 OAuth 授权信息(含 appId、authorizeUrl),对应 api.biz.wechat.oauthAuthorizeUrl + */ + oauthAuthorizeUrlApiUrl?: string, + /** + * openid 缓存 key,默认 iscan_wechat_openid_${appId}(appId 来自授权接口响应) + */ + storageKey?: string, + /** + * OAuth 授权回跳完整 URL(redirectUri),须与当前页域名一致且已在公众号登记; + * 未配置时默认使用当前页 location.href(不含 hash) + */ + redirectUri?: string, + }, /** * 微信JSSDK配置,微信环境才会生效,配置后会自动初始化微信JSSDK */ @@ -319,6 +373,79 @@ interface ScanErrorListenerInfo { */ type ScanStatusCallback = (status: ScanStatus) => any; +/** + * 支付渠道 + */ +type PaymentType = 'wechat' | 'alipay'; + +/** + * JSAPI 收银台交互结果(仅表示用户在收银台的操作,非支付到账结果) + */ +type PaymentCashierResult = 'ok' | 'cancel' | 'fail'; + +/** + * 微信支付场景 + */ +type PayScene = 'jsapi' | 'h5' | 'native'; + +/** + * SDK 传给业务支付函数的参数(OAuth、环境判断由 SDK 自动完成) + */ +interface PaymentPrepareParams { + /** 微信 JSAPI 场景下的 openid,其他场景为空字符串 */ + openid: string; + /** 当前环境对应的微信支付场景 */ + payScene: PayScene; + /** navigator.userAgent */ + userAgent: string; + /** 用户 IP,默认空字符串 */ + clientIp: string; + /** 支付完成回跳地址 */ + returnUrl: string; + /** 支付渠道 */ + paymentType: PaymentType; +} + +/** + * 业务支付函数:调用自己的支付接口,返回 paymentFormData + */ +type PaymentFormDataProvider = ( + params: PaymentPrepareParams +) => string | Record | Promise>; + +/** + * SDK 发起支付后的返回(不代表支付成功,业务须自行查单) + */ +interface PaymentInvokeResult { + payType?: 'jsapi' | 'h5' | 'native' | 'alipay'; + /** SDK 是否已发起支付流程 */ + invoked: boolean; + /** 微信 OAuth 授权跳转中(页面将刷新,业务函数尚未执行) */ + oauthRedirecting?: boolean; + /** 支付未发起(含微信 OAuth 失败) */ + failed?: boolean; + /** 微信 OAuth / openid 获取失败 */ + oauthFailed?: boolean; + /** OAuth 或调起失败时的错误信息 */ + error?: string; + /** H5 / 支付宝是否已跳转 */ + redirected?: boolean; + /** Native 场景是否展示了二维码弹层 */ + qrShown?: boolean; + /** 微信 JSAPI 收银台交互结果(非支付到账结果) */ + cashierResult?: PaymentCashierResult; +} + +/** + * 支付请求选项 + */ +interface RequestPaymentOptions { + /** 支付完成回跳地址,未传时使用当前页 URL */ + returnUrl?: string; + /** OAuth 授权回跳完整 URL(redirectUri),覆盖 initWechatPayment.redirectUri */ + redirectUri?: string; +} + /** IScan */ interface IScan { /** @@ -377,12 +504,29 @@ interface IScan { * @param key 可选,指定后结果仅分发给同 key 的 onScanListener */ scanImage(key?: string): void; - /** 由业务/原生传入已选图片 File 识别(WebView input.files 异常时使用) */ + /** + * 由业务/原生传入已选图片 File 识别(WebView input.files 异常时使用) + * @param file 已选图片 File + * @param key 可选,指定后结果仅分发给同 key 的 onScanListener + */ scanImageFromFile(file: File | Blob, key?: string): void; /** * 清除全部监听 */ clear(): void; + /** + * 发起支付:按 paymentType 决定是否走微信 OAuth,再将参数传给业务函数获取 paymentFormData 并调起支付。 + * 不代表支付成功,业务须自行查单。 + */ + requestPayment( + paymentType: PaymentType, + fetchPaymentFormData: PaymentFormDataProvider, + options?: RequestPaymentOptions + ): Promise; + /** + * 关闭 SDK 管理的支付相关 UI(如 PC Native 二维码弹层) + */ + closePaymentDialog(): void; } diff --git a/dist/index.js b/dist/index.js index c0c7af5..acd4965 100644 --- a/dist/index.js +++ b/dist/index.js @@ -1 +1 @@ -!function(e){var t={};function r(n){if(t[n])return t[n].exports;var o=t[n]={i:n,l:!1,exports:{}};return e[n].call(o.exports,o,o.exports,r),o.l=!0,o.exports}r.m=e,r.c=t,r.d=function(e,t,n){r.o(e,t)||Object.defineProperty(e,t,{enumerable:!0,get:n})},r.r=function(e){"undefined"!=typeof Symbol&&Symbol.toStringTag&&Object.defineProperty(e,Symbol.toStringTag,{value:"Module"}),Object.defineProperty(e,"__esModule",{value:!0})},r.t=function(e,t){if(1&t&&(e=r(e)),8&t)return e;if(4&t&&"object"==typeof e&&e&&e.__esModule)return e;var n=Object.create(null);if(r.r(n),Object.defineProperty(n,"default",{enumerable:!0,value:e}),2&t&&"string"!=typeof e)for(var o in e)r.d(n,o,function(t){return e[t]}.bind(null,o));return n},r.n=function(e){var t=e&&e.__esModule?function(){return e.default}:function(){return e};return r.d(t,"a",t),t},r.o=function(e,t){return Object.prototype.hasOwnProperty.call(e,t)},r.p="",r(r.s=14)}([function(e,t,r){"use strict";t.__esModule=!0;var n="function"==typeof Symbol&&"symbol"==typeof Symbol.iterator?function(e){return typeof e}:function(e){return e&&"function"==typeof Symbol&&e.constructor===Symbol&&e!==Symbol.prototype?"symbol":typeof e};t.getVersion=function(){return o},t.getConfig=function(e){if(Object.prototype.hasOwnProperty.call(a,e))return a[e];if(Object.prototype.hasOwnProperty.call(i,e))return i[e];return},t.setConfig=function(e){e&&"object"==(void 0===e?"undefined":n(e))&&Object.assign(a,e)};var o="0.0.1.0609.1236",i={embedProxyMode:"auto"},a={}},function(e,t,r){"use strict";t.__esModule=!0,t.printError=function(e){for(var t,r=arguments.length,n=Array(r>1?r-1:0),o=1;o1?r-1:0),o=1;o1?r-1:0),o=1;o