index.ts 3.7KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138
  1. import { EmitterSubscription, Platform } from "react-native";
  2. import * as RNGSModule from "./module";
  3. export { BackgroundBlurEffectIOS, Lang } from "./module";
  4. export interface IAPI1Result {
  5. success: 0 | 1;
  6. challenge: string;
  7. gt: string;
  8. new_captcha: boolean;
  9. [key: string]: any;
  10. }
  11. export interface IOption {
  12. // API1
  13. api1Result: IAPI1Result;
  14. // debug
  15. debug?: boolean;
  16. // view 加载超时时间,默认10000
  17. loadTimeout?: number;
  18. // 第二步向极验服务器发送请求超时时间,默认10000
  19. reqTimeout?: number;
  20. // 语言
  21. lang?: RNGSModule.Lang;
  22. // 点击背景是否可以取消验证
  23. enableBackgroundCancel?: boolean;
  24. // 背景色 IOS Only
  25. backgroundColorIOS?: any;
  26. // 背景模糊类型 IOS Only
  27. backgroundBlurEffectIOS?: RNGSModule.BackgroundBlurEffectIOS;
  28. // 事件监听
  29. onEvent?: (code: Events, data?: Array<number | string>) => void;
  30. }
  31. export interface IResult {
  32. geetest_challenge: string;
  33. geetest_seccode: string;
  34. geetest_validate: string;
  35. [key: string]: any;
  36. }
  37. export enum Errors {
  38. // 参数解析错误
  39. PARAMETER_PARSE_FAILED = -1,
  40. // 安卓 activity 已经销毁
  41. ANDROID_ACTIVITY_DESTROYED = -2,
  42. // 重复运行
  43. DUPLICATE_START = -3,
  44. }
  45. export enum Events {
  46. // 验证结果
  47. RESULT = 1,
  48. // 验证窗口关闭
  49. CLOSED = 2,
  50. // 验证失败
  51. FAILED = 3,
  52. // 发生错误
  53. ERROR = 0,
  54. }
  55. enum InternalStatus {
  56. None = 0b0,
  57. // 认证中
  58. Running = 0b1,
  59. // 停止认证中
  60. Stoping = 0b1 >> 1,
  61. }
  62. let internalStatus = InternalStatus.None;
  63. let eventListener: EmitterSubscription | null = null;
  64. const DEFAULT_OPTION = {
  65. api1Result: "",
  66. debug: false,
  67. loadTimeout: 10000,
  68. reqTimeout: 10000,
  69. lang: RNGSModule.Lang.System,
  70. enableBackgroundCancel: false,
  71. backgroundColorIOS: 0, // processColor('transparent')
  72. backgroundBlurEffectIOS: RNGSModule.BackgroundBlurEffectIOS.None,
  73. };
  74. // 进行行为认证
  75. export function start(option: IOption): Promise<IResult> {
  76. return new Promise((resolve, reject) => {
  77. if (internalStatus & InternalStatus.Running) {
  78. return reject(new GeetestError(
  79. Errors.DUPLICATE_START, "Duplicate start"));
  80. }
  81. internalStatus |= InternalStatus.Running;
  82. eventListener = RNGSModule.addListener(([code, ...data]) => {
  83. switch (code) {
  84. case Events.RESULT:
  85. resolve(JSON.parse(data[0]));
  86. stop();
  87. break;
  88. case Events.FAILED:
  89. case Events.CLOSED:
  90. stop();
  91. break;
  92. case Events.ERROR:
  93. reject(new GeetestError(data[0], data[1]));
  94. stop();
  95. break;
  96. }
  97. if (typeof option.onEvent === "function") {
  98. option.onEvent(code, data);
  99. }
  100. });
  101. RNGSModule.start(RNGSModule.parseOption(option, DEFAULT_OPTION));
  102. });
  103. }
  104. function stop() {
  105. if (internalStatus & InternalStatus.Stoping) { return; }
  106. internalStatus |= InternalStatus.Stoping;
  107. RNGSModule.stop(() => {
  108. internalStatus = InternalStatus.None;
  109. if (eventListener && typeof eventListener.remove === "function") {
  110. eventListener.remove();
  111. eventListener = null;
  112. }
  113. });
  114. }
  115. export class GeetestError extends Error {
  116. constructor(readonly code: number, readonly message: string) {
  117. super(message);
  118. // @ts-ignore
  119. if (Error.captureStackTrace) {
  120. // @ts-ignore
  121. Error.captureStackTrace(this, GeetestError);
  122. }
  123. this.name = "GeetestError";
  124. }
  125. }