settlementSign.ts 3.0 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115
  1. import { defineStore } from 'pinia'
  2. import { uniStorage } from '@/utils/uniStorage'
  3. export interface SettlementSignContext {
  4. signTraceId: string
  5. subjectLocation: string
  6. createdAt: number
  7. }
  8. interface SettlementSignState {
  9. context?: SettlementSignContext
  10. returnedSignTraceId: string
  11. processingSignTraceId: string
  12. }
  13. const SIGN_CONTEXT_EXPIRE_TIME = 30 * 60 * 1000
  14. const createSignTraceId = (subjectLocation: string): string => {
  15. return `${Date.now()}_${subjectLocation}`
  16. }
  17. export const useSettlementSignStore = defineStore('settlementSign', {
  18. state: (): SettlementSignState => ({
  19. context: undefined,
  20. returnedSignTraceId: '',
  21. processingSignTraceId: '',
  22. }),
  23. getters: {
  24. validContext(state): SettlementSignContext | undefined {
  25. if (!state.context?.subjectLocation) return undefined
  26. const isExpired = Date.now() - state.context.createdAt > SIGN_CONTEXT_EXPIRE_TIME
  27. if (isExpired) return undefined
  28. return state.context
  29. },
  30. pendingSubjectLocation(): string {
  31. return this.validContext?.subjectLocation || ''
  32. },
  33. returnedContext(): SettlementSignContext | undefined {
  34. const context = this.validContext
  35. return context?.signTraceId === this.returnedSignTraceId ? context : undefined
  36. },
  37. },
  38. actions: {
  39. createContext(subjectLocation: string): SettlementSignContext {
  40. const context: SettlementSignContext = {
  41. signTraceId: createSignTraceId(subjectLocation),
  42. subjectLocation,
  43. createdAt: Date.now(),
  44. }
  45. this.context = context
  46. this.returnedSignTraceId = ''
  47. return context
  48. },
  49. markReturned(subjectLocation: string, signTraceId: string): void {
  50. const context = this.validContext
  51. if (
  52. !context ||
  53. context.subjectLocation !== subjectLocation ||
  54. context.signTraceId !== signTraceId ||
  55. this.processingSignTraceId === signTraceId
  56. ) {
  57. return
  58. }
  59. this.returnedSignTraceId = signTraceId
  60. },
  61. // query 回跳与 WebView 返回共用同一把锁,避免两个页面实例重复处理。
  62. beginSignRedirect(subjectLocation: string, signTraceId: string): boolean {
  63. if (this.processingSignTraceId) return false
  64. const context = this.validContext
  65. if (
  66. signTraceId &&
  67. (context?.signTraceId !== signTraceId || context.subjectLocation !== subjectLocation)
  68. ) {
  69. return false
  70. }
  71. this.processingSignTraceId =
  72. signTraceId ||
  73. (context?.subjectLocation === subjectLocation ? context.signTraceId : subjectLocation)
  74. this.returnedSignTraceId = ''
  75. return true
  76. },
  77. finishSignRedirect(): void {
  78. this.processingSignTraceId = ''
  79. },
  80. clearContext(signTraceId?: string): void {
  81. if (signTraceId && this.context?.signTraceId !== signTraceId) return
  82. this.context = undefined
  83. this.returnedSignTraceId = ''
  84. },
  85. },
  86. persist: {
  87. key: 'settlement-sign-store',
  88. storage: uniStorage,
  89. pick: ['context'],
  90. },
  91. })