splitCardPay.vue 3.2 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166
  1. <template>
  2. <Popup isClose ref="popRef">
  3. <template #content>
  4. <view class="split-card__box">
  5. <view class="card_item">
  6. <view class="card_item_label">
  7. <trans _t="银行卡号" />
  8. </view>
  9. <view class="card_item_input" id="split_card_number"></view>
  10. </view>
  11. <view class="card_item">
  12. <view class="card_item_label">
  13. <trans _t="有效期" />
  14. </view>
  15. <view class="card_item_input" id="split_card_expiry"></view>
  16. </view>
  17. <view class="card_item">
  18. <view class="card_item_label">
  19. <trans _t="安全码" />
  20. </view>
  21. <view class="card_item_input" id="split_card_cvc"></view>
  22. </view>
  23. </view>
  24. </template>
  25. <!-- footer -->
  26. <template #footer>
  27. <view class="submit_btn" @click="onConfirm">
  28. <trans _t="确认" />
  29. </view>
  30. </template>
  31. </Popup>
  32. <GlobalLoading :msg="loadingStatus"></GlobalLoading>
  33. </template>
  34. <script setup>
  35. import { reactive, ref, nextTick } from 'vue'
  36. import Popup from '@/components/popup.vue';
  37. import GlobalLoading from '@/components/GlobalLoading.vue'
  38. import { Toast } from "@/utils"
  39. import { t } from "@/locale"
  40. import { useSplitCardInfo } from './hooks'
  41. const props = defineProps({
  42. paramsObj: { type: Object }
  43. })
  44. const emit = defineEmits(['on-confirm', 'on-open', 'on-close', 'on-success', 'on-error']);
  45. const {
  46. elementTypeList,
  47. intent_id,
  48. client_secret,
  49. onInit,
  50. onUnmountElement,
  51. fetchPaymentInfo } = useSplitCardInfo()
  52. const popRef = ref(null);
  53. const loadingStatus = reactive({ show: false })
  54. // 打开回调
  55. const open = (data) => {
  56. onUnmountElement()
  57. emit('on-open')
  58. popRef.value && popRef.value.open()
  59. nextTick(() => {
  60. fetchPaymentInfo(props.paramsObj)
  61. onInit()
  62. })
  63. }
  64. // 关闭回调
  65. const close = () => {
  66. emit('on-close')
  67. popRef.value && popRef.value.close()
  68. onUnmountElement()
  69. }
  70. // “确认按钮” 回调
  71. const onConfirm = () => {
  72. submitPayment()
  73. }
  74. // 提交支付
  75. function submitPayment() {
  76. const cardNumber = elementTypeList.cardNumber
  77. if (!cardNumber.instance) return
  78. loadingStatus.show = true
  79. const options = {
  80. intent_id: intent_id.value,
  81. client_secret: client_secret.value,
  82. payment_method_options: {
  83. card: {
  84. auto_capture: true,
  85. },
  86. },
  87. }
  88. cardNumber.instance.confirm(options).then((response) => {
  89. console.log('--- response ----', response)
  90. const { status } = response
  91. if (status == "SUCCEEDED" || status == "succeeded") {
  92. emit('on-success', response)
  93. }
  94. else {
  95. Toast(status)
  96. }
  97. }).catch((error) => {
  98. console.log('--- error ----', error)
  99. Toast(error.message)
  100. }).finally(() => {
  101. loadingStatus.show = false
  102. });
  103. }
  104. defineExpose({
  105. open,
  106. close
  107. })
  108. </script>
  109. <style lang="less" scoped>
  110. @import url('@/style.less');
  111. .split-card__box {
  112. width: 100%;
  113. height: 40vh;
  114. .card_item {
  115. margin-top: 16px;
  116. width: 100%;
  117. }
  118. .card_item:first-child {
  119. margin-top: 0;
  120. }
  121. .card_item .card_item_label {
  122. font-size: 28rpx;
  123. color: #333;
  124. }
  125. .card_item .card_item_input {
  126. min-height: 40px;
  127. padding: 8rpx 0rpx 8rpx 16rpx;
  128. margin-top: 10px;
  129. border: 1px solid #ccc;
  130. border-radius: 14rpx;
  131. }
  132. }
  133. .submit_btn {
  134. height: 38px;
  135. padding: 16rpx 30rpx;
  136. background-color: var(--black);
  137. color: var(--light);
  138. .flex_center();
  139. border-radius: 16rpx;
  140. .size(24rpx);
  141. }
  142. </style>