|
@@ -0,0 +1,280 @@
|
|
|
+<template>
|
|
|
+ <div class="airwallexPayment">
|
|
|
+ <s-header :name="$t('airwallex.payment')" :noback="false"></s-header>
|
|
|
+ <br>
|
|
|
+ <div class="form-container">
|
|
|
+ <div id="beneficiary-form-container" class="beneficiary-form-container" style="height: 100%;"></div>
|
|
|
+ </div>
|
|
|
+ <div class="button-container" v-if="showButton">
|
|
|
+ <van-button type="primary" class="cancel" @click="handleCancel">取消</van-button>
|
|
|
+ <van-button id="submit-button" type="primary" class="register" @click="handleSubmit">Submit</van-button>
|
|
|
+ </div>
|
|
|
+ </div>
|
|
|
+</template>
|
|
|
+
|
|
|
+<script>
|
|
|
+import sHeader from "@/components/SimpleHeader";
|
|
|
+import { init, createElement } from '@airwallex/payouts-web-sdk';
|
|
|
+import { Base64 } from 'js-base64';
|
|
|
+import { getAuthCode, createBeneficiary } from '@/service/airwallex/index';
|
|
|
+import { AIRWALLEX_ADMIN_CLIENTID } from '@/constants/const.js';
|
|
|
+import { onMounted, ref } from 'vue';
|
|
|
+import { useRouter } from 'vue-router';
|
|
|
+import { styleUrl } from '../../common/js/utils';
|
|
|
+
|
|
|
+export default {
|
|
|
+ components: { sHeader },
|
|
|
+ setup() {
|
|
|
+ const router = useRouter();
|
|
|
+ const ready = ref(false);
|
|
|
+ let beneficiaryComponent;
|
|
|
+ const showButton = ref(false);
|
|
|
+ // const beneficiaryComponent = ref(null);
|
|
|
+
|
|
|
+ onMounted(async () => {
|
|
|
+ try {
|
|
|
+ // 生成 code_verifier
|
|
|
+ const codeVerifier = generateCodeVerifier();
|
|
|
+
|
|
|
+ // 生成 code_challenge
|
|
|
+ const codeChallengeStr = await generateCodeChallengeFromVerifier(codeVerifier);
|
|
|
+
|
|
|
+ // 生成 getAuthCode 接口的参数
|
|
|
+ const getAuthCodeDTO = {
|
|
|
+ code_challenge: codeChallengeStr,
|
|
|
+ scope: [
|
|
|
+ // onboarding component
|
|
|
+ // "w:awx_action:onboarding"
|
|
|
+ // payout or beneficiary component
|
|
|
+ "w:awx_action:transfers_edit"
|
|
|
+ ]
|
|
|
+ };
|
|
|
+
|
|
|
+ console.log("getAuthCodeDTO", getAuthCodeDTO);
|
|
|
+
|
|
|
+ // 调用后端 getAuthCode 接口获取 authCode
|
|
|
+ const authCodeResponse = await getAuthCode(getAuthCodeDTO);
|
|
|
+ const authCodeStr = authCodeResponse.data.authorization_code;
|
|
|
+
|
|
|
+ await init({
|
|
|
+ langKey: 'en',
|
|
|
+ env: 'demo',
|
|
|
+ authCode: authCodeStr,
|
|
|
+ clientId: AIRWALLEX_ADMIN_CLIENTID,
|
|
|
+ codeVerifier: codeVerifier,
|
|
|
+ });
|
|
|
+
|
|
|
+ // 调用 SDK 的 createElement 方法创建付款交易单/收款方模块
|
|
|
+ beneficiaryComponent = await createElement(eleType);
|
|
|
+
|
|
|
+ beneficiaryComponent.mount('#beneficiary-form-container');
|
|
|
+
|
|
|
+ beneficiaryComponent.on('ready', () => {
|
|
|
+ ready.value = true;
|
|
|
+ // 添加组件渲染后的逻辑
|
|
|
+ console.log('组件呈现后的逻辑...');
|
|
|
+ });
|
|
|
+ showButton.value = true;
|
|
|
+ } catch (error) {
|
|
|
+ console.error(error);
|
|
|
+ // 处理异常情况
|
|
|
+ }
|
|
|
+ });
|
|
|
+
|
|
|
+ const handleCancel = async () => {
|
|
|
+ router.push({
|
|
|
+ path: '/airwallex',
|
|
|
+ })
|
|
|
+ }
|
|
|
+
|
|
|
+ const handleSubmit = async () => {
|
|
|
+ if (ready.value) {
|
|
|
+ const formResult = await beneficiaryComponent.submit();
|
|
|
+ // Handle form results
|
|
|
+ console.log('submit 执行结果:', formResult);
|
|
|
+
|
|
|
+ // 提取收款人信息字段
|
|
|
+ const { beneficiary, nickname, payment_methods } = formResult.values;
|
|
|
+ const { company_name, entity_type, address, bank_details } = beneficiary;
|
|
|
+
|
|
|
+ // 验证收款人信息是否完整
|
|
|
+ if (!payment_methods || !entity_type || !address || !bank_details || !company_name) {
|
|
|
+ throw new Error('收款人信息不完整');
|
|
|
+ }
|
|
|
+
|
|
|
+ // 地址信息
|
|
|
+ const {
|
|
|
+ city,
|
|
|
+ country_code,
|
|
|
+ postcode,
|
|
|
+ state,
|
|
|
+ street_address
|
|
|
+ } = address;
|
|
|
+ console.log("地址信息》》》", address);
|
|
|
+ // 验证地址信息是否完整
|
|
|
+ if (
|
|
|
+ // !city ||
|
|
|
+ !country_code ||
|
|
|
+ // !postcode ||
|
|
|
+ // !state ||
|
|
|
+ !street_address
|
|
|
+ ) {
|
|
|
+ throw new Error('地址信息不完整');
|
|
|
+ }
|
|
|
+
|
|
|
+ // 银行信息
|
|
|
+ const {
|
|
|
+ account_currency,
|
|
|
+ account_name,
|
|
|
+ account_number,
|
|
|
+ account_routing_type1,
|
|
|
+ account_routing_value1,
|
|
|
+ bank_country_code,
|
|
|
+ bank_name,
|
|
|
+ swift_code,
|
|
|
+ } = bank_details;
|
|
|
+ console.log("银行信息》》》", bank_details);
|
|
|
+ // 验证银行详细信息是否完整
|
|
|
+ if (
|
|
|
+ !account_currency ||
|
|
|
+ !account_name ||
|
|
|
+ !account_number ||
|
|
|
+ !bank_country_code ||
|
|
|
+ !bank_name ||
|
|
|
+ !swift_code
|
|
|
+ ) {
|
|
|
+ throw new Error('银行详细信息不完整');
|
|
|
+ }
|
|
|
+
|
|
|
+ // 构建请求数据对象
|
|
|
+ const caBeneficiaryReq = {
|
|
|
+ beneficiary: {
|
|
|
+ company_name: company_name,
|
|
|
+ entity_type: entity_type,
|
|
|
+ address: {
|
|
|
+ city: city,
|
|
|
+ country_code: country_code,
|
|
|
+ postcode: postcode,
|
|
|
+ state: state,
|
|
|
+ street_address: street_address,
|
|
|
+ },
|
|
|
+ bank_details: {
|
|
|
+ account_currency: account_currency,
|
|
|
+ account_name: account_name,
|
|
|
+ account_number: account_number,
|
|
|
+ account_routing_type1: account_routing_type1,
|
|
|
+ account_routing_value1: account_routing_value1,
|
|
|
+ bank_country_code: bank_country_code,
|
|
|
+ bank_name: bank_name,
|
|
|
+ swift_code: swift_code,
|
|
|
+ },
|
|
|
+ },
|
|
|
+ nickname: nickname,
|
|
|
+ payment_methods: payment_methods,
|
|
|
+ };
|
|
|
+
|
|
|
+ // const { field1, field2, field3 } = formResult;
|
|
|
+ // let caBeneficiaryReq = {};
|
|
|
+
|
|
|
+ // caBeneficiaryReq.beneficiary = {
|
|
|
+ // companyName: formResult.values.beneficiary.company_name,
|
|
|
+ // entityType: formResult.values.beneficiary.entity_type,
|
|
|
+ // }
|
|
|
+ // caBeneficiaryReq.nickname = formResult.values.nickname;
|
|
|
+ // caBeneficiaryReq.paymentMethods = formResult.values.payment_methods;
|
|
|
+
|
|
|
+ // caBeneficiaryReq.beneficiary.address = {
|
|
|
+ // city: formResult.values.beneficiary.address.city,
|
|
|
+ // countryCode: formResult.values.beneficiary.address.country_code,
|
|
|
+ // postcode: formResult.values.beneficiary.address.postcode,
|
|
|
+ // state: formResult.values.beneficiary.address.state,
|
|
|
+ // streetAddress: formResult.values.beneficiary.address.street_address,
|
|
|
+ // }
|
|
|
+ // caBeneficiaryReq.beneficiary.bankDetails = {
|
|
|
+ // accountCurrency: formResult.values.beneficiary.bank_details.account_currency,
|
|
|
+ // accountName: formResult.values.beneficiary.bank_details.account_name,
|
|
|
+ // accountNumber: formResult.values.beneficiary.bank_details.account_number,
|
|
|
+ // accountRoutingType1: formResult.values.beneficiary.bank_details.account_routing_type1,
|
|
|
+ // accountRoutingValue1: formResult.values.beneficiary.bank_details.account_routing_value1,
|
|
|
+ // bankCountryCode: formResult.values.beneficiary.bank_details.bank_country_code,
|
|
|
+ // bankName: formResult.values.beneficiary.bank_details.bank_name,
|
|
|
+ // swiftCode: formResult.values.beneficiary.bank_details.swift_code,
|
|
|
+ // }
|
|
|
+
|
|
|
+ // 请求后端接口 caBeneficiary
|
|
|
+ const respResult = await createBeneficiary(caBeneficiaryReq);
|
|
|
+ const beneficiaryId = respResult.data.beneficiary_id;
|
|
|
+ console.log("收款人id:", beneficiaryId);
|
|
|
+
|
|
|
+ // if 成功,将 beneficiary_id 缓存下来,跳转到付款单页面
|
|
|
+ if (beneficiaryId) {
|
|
|
+ router.push({
|
|
|
+ path: '/airwallexPayout',
|
|
|
+ query: { beneficiaryId: beneficiaryId }
|
|
|
+ })
|
|
|
+ }
|
|
|
+
|
|
|
+
|
|
|
+ // 收款人发起付款请求,调用后端创建付款接口
|
|
|
+ // const paymentId = await createPayment(caPaymentDTO);
|
|
|
+ // console.log("付款交易id:", paymentId);
|
|
|
+
|
|
|
+ // if (paymentId) {
|
|
|
+ // router.push({
|
|
|
+ // path: '/paymentDetail',
|
|
|
+ // query: { paymentId }
|
|
|
+ // });
|
|
|
+ // }
|
|
|
+ }
|
|
|
+ };
|
|
|
+
|
|
|
+
|
|
|
+ // 生成 code_verifier
|
|
|
+ const dec2hex = (dec) => {
|
|
|
+ return ('0' + dec.toString(16)).slice(-2);
|
|
|
+ };
|
|
|
+
|
|
|
+ const generateCodeVerifier = () => {
|
|
|
+ // 生成 random length for code_verifier which should be between 43 and 128
|
|
|
+ const length = Math.random() * (129 - 43) + 43;
|
|
|
+ const array = new Uint32Array(length / 2);
|
|
|
+ window.crypto.getRandomValues(array);
|
|
|
+
|
|
|
+ return Array.from(array, dec2hex).join('');
|
|
|
+ };
|
|
|
+
|
|
|
+
|
|
|
+ // 生成 code_challenge
|
|
|
+ const sha256 = (plain) => {
|
|
|
+ const encoder = new TextEncoder();
|
|
|
+ const data = encoder.encode(plain);
|
|
|
+ return window.crypto.subtle.digest('SHA-256', data);
|
|
|
+ };
|
|
|
+
|
|
|
+ const base64urlencode = (hashed) => {
|
|
|
+ const bytes = new Uint8Array(hashed);
|
|
|
+ const base64encoded = Base64.fromUint8Array(bytes, true);
|
|
|
+ return base64encoded;
|
|
|
+ };
|
|
|
+
|
|
|
+ const generateCodeChallengeFromVerifier = async (codeVerifier) => {
|
|
|
+ const hashed = await sha256(codeVerifier);
|
|
|
+ const base64encoded = base64urlencode(hashed);
|
|
|
+ return base64encoded;
|
|
|
+ };
|
|
|
+
|
|
|
+ // type 字段:payoutForm(可选),beneficiaryForm
|
|
|
+ const eleType = "beneficiaryForm";
|
|
|
+
|
|
|
+ styleUrl("airwallex");
|
|
|
+
|
|
|
+ return {
|
|
|
+ ready,
|
|
|
+ handleSubmit,
|
|
|
+ showButton,
|
|
|
+ handleCancel
|
|
|
+ }
|
|
|
+ }
|
|
|
+}
|
|
|
+
|
|
|
+</script>
|