本文旨在深入探讨华为鸿蒙HarmonyOS Next系统(截止目前 API12)在开发多语言电商平台方面的技术细节,基于实际开发实践进行总结。主要作为技术分享与交流载体,难免错漏,欢迎各位同仁提出宝贵意见和问题,以便共同进步。本文为原创内容,任何形式的转载必须注明出处及原作者。
在数字化金融蓬勃发展的今天,在线支付应用的安全性和稳定性至关重要。本次,我们将基于鸿蒙 Next 系统,深入探讨如何开发一个功能完备的在线支付应用,涵盖从架构设计到核心功能实现的全过程,全面展现鸿蒙 Next 在金融科技领域的强大实力。
一、架构设计:Clean Architecture 的应用
(一)Clean Architecture 概述
Clean Architecture 是一种分层架构模式,将应用划分为多个独立的层次,每个层次都有明确的职责,使得代码结构清晰、易于维护和测试。在在线支付应用中,这种架构能够有效隔离业务逻辑、数据存储和用户界面,提高应用的安全性和稳定性。
(二)表现层(Presentation Layer)
表现层负责与用户进行交互,展示应用的界面和接收用户输入。在在线支付应用中,包括登录界面、银行卡绑定界面、支付密码设置界面、支付订单界面等。我们将使用 ArkUI 框架构建美观、易用的用户界面,确保用户能够流畅地进行操作。例如,通过TextField
组件接收用户输入的银行卡号、密码等信息,Button
组件实现各种操作按钮的功能。
(三)应用层(Application Layer)
应用层作为表现层和领域层之间的桥梁,负责协调业务逻辑的执行。它接收表现层的用户请求,调用领域层的业务逻辑处理方法,并将处理结果返回给表现层。例如,当用户点击银行卡绑定按钮时,应用层负责验证用户输入的信息格式,然后调用领域层的银行卡绑定方法进行实际的绑定操作。
(四)领域层(Domain Layer)
领域层包含了应用的核心业务逻辑,如银行卡绑定逻辑、支付密码验证逻辑、支付订单处理逻辑等。它不依赖于任何外部框架或技术,只专注于业务规则的实现。例如,在银行卡绑定逻辑中,验证银行卡号的有效性、与银行系统进行交互验证等操作都在领域层完成。
(五)数据层(Data Layer)
数据层负责数据的存储和获取,与数据库、网络服务等进行交互。在在线支付应用中,它负责存储用户的银行卡信息、支付密码等敏感数据(经过加密处理),以及与支付服务器进行通信,获取支付结果等信息。我们将使用鸿蒙 Next 的安全存储 API 和网络通信 API 来实现数据层的功能。
(六)各层之间的依赖关系
Clean Architecture 强调各层之间的单向依赖,表现层依赖于应用层,应用层依赖于领域层,领域层依赖于数据层。这种依赖关系确保了各层的独立性和可测试性,使得应用的维护和扩展更加容易。
二、权限申请与安全机制
(一)权限机制与安全原则
在线支付应用涉及用户的敏感信息和资金交易,安全是首要任务。鸿蒙 Next 的权限机制为我们提供了坚实的安全保障,确保应用在合法、安全的前提下获取用户授权,保护用户数据和资金安全。
(二)用户授权的应用
读取剪贴板权限(用于粘贴银行卡号)
当用户在银行卡绑定界面选择粘贴银行卡号时,应用需要申请读取剪贴板权限(ohos.permission.READ_PASTEBOARD
)。在用户点击粘贴按钮时,应用应动态申请该权限。例如:import { abilityAccessCtrl, common, Permissions } from '@kit.AbilityKit'; import { BusinessError } from '@kit.BasicServicesKit'; const clipboardPermission: Permissions = 'ohos.permission.READ_PASTEBOARD'; async function checkClipboardPermissionGrant(): Promise<abilityAccessCtrl.GrantStatus> { let atManager: abilityAccessCtrl.AtManager = abilityAccessCtrl.createAtManager(); let grantStatus: abilityAccessCtrl.GrantStatus = abilityAccessCtrl.GrantStatus.PERMISSION_DENIED; // 获取应用程序的 accessTokenID let tokenId: number = 0; try { let bundleInfo: bundleManager.BundleInfo = await bundleManager.getBundleInfoForSelf(bundleManager.BundleFlag.GET_BUNDLE_INFO_WITH_APPLICATION); let appInfo: bundleManager.ApplicationInfo = bundleInfo.appInfo; tokenId = appInfo.accessTokenId; } catch (error) { const err: BusinessError = error as BusinessError; console.error(`Failed to get bundle info for self. Code is ${err.code}, message is ${err.message}`); } // 校验应用是否被授予权限 try { grantStatus = await atManager.checkAccessToken(tokenId, clipboardPermission); } catch (error) { const err: BusinessError = error as BusinessError; console.error(`Failed to check access token. Code is ${err.code}, message is ${err.message}`); } return grantStatus; } async function requestClipboardPermission(): Promise<void> { let grantStatus: abilityAccessCtrl.GrantStatus = await checkClipboardPermissionGrant(); if (grantStatus === abilityAccessCtrl.GrantStatus.PERMISSION_GRANTED) { // 已获得读取剪贴板权限,可以进行粘贴操作 console.log('已获得读取剪贴板权限,可以继续操作。'); } else { // 申请读取剪贴板权限 const permissions: Array<Permissions> = [clipboardPermission]; let atManager: abilityAccessCtrl.AtManager = abilityAccessCtrl.createAtManager(); atManager.requestPermissionsFromUser(globalThis.context as common.UIAbilityContext, permissions).then((data) => { let grantStatus: Array<number> = data.authResults; let length: number = grantStatus.length; for (let i = 0; i < length; i++) { if (grantStatus[i] === 0) { // 用户授权,可以继续访问目标操作 console.log('用户已授权读取剪贴板权限,可以继续操作。'); } else { // 用户拒绝授权,提示用户必须授权才能访问相关功能,并引导用户到系统设置中打开相应权限 console.log('用户拒绝授权读取剪贴板权限,请前往系统设置中手动授予权限。'); return; } } // 授权成功 }).catch((err: BusinessError) => { console.error(`Failed to request clipboard permission from user. Code is ${err.code}, message is ${err.message}`); }); } } // 在用户点击粘贴银行卡号按钮时调用 requestClipboardPermission() 函数 requestClipboardPermission();
(三)安全控件的使用
粘贴控件(读取银行卡号)
为了方便用户输入银行卡号,我们使用粘贴控件。当用户在银行卡号输入框点击粘贴按钮时,应用调用粘贴控件读取剪贴板中的银行卡号。例如:import { pasteboard, BusinessError } from '@kit.BasicServicesKit'; import { Component, State, ClickEvent, PasteButtonOnClickResult } from '@ohos.arkui.extension.component'; @Entry @Component struct Index { @State cardNumber: string = ''; build() { Row() { Column({ space: 10 }) { TextField({ placeholder: '请输入银行卡号', text: this.cardNumber }) PasteButton() .padding({ top: 12, bottom: 12, left: 24, right: 24 }) .onClick((event: ClickEvent, result: PasteButtonOnClickResult) => { if (PasteButtonOnClickResult.SUCCESS === result) { pasteboard.getSystemPasteboard().getData((err: BusinessError, pasteData: pasteboard.PasteData) => { if (err) { console.error(`Failed to get paste data. Code is ${err.code}, message is ${err.message}`); return; } this.cardNumber = pasteData.getPrimaryText(); }); } }) } .width('100%') } .height('100%') } }
用户点击粘贴控件后,应用将读取到的银行卡号填充到输入框中,方便用户操作。
三、核心功能实现
(一)银行卡绑定功能
- 信息验证
在用户输入银行卡号、开户行、持卡人姓名等信息后,应用在应用层进行初步的信息格式验证,如银行卡号的位数、开户行的有效性等。然后在领域层,通过与银行系统的接口(假设通过网络通信 API 与银行服务器进行交互)进行更严格的验证,确保银行卡信息的准确性和可用性。 数据加密与存储
验证通过后,在数据层对银行卡信息进行加密处理,然后存储到本地安全存储区域(使用鸿蒙 Next 的安全存储 API)。加密算法可以选择行业标准的加密算法,如 AES 等,确保用户银行卡信息的安全性。例如:import { secureStorage } from '@kit.SecurityKit'; // 加密并存储银行卡信息 async function storeBankCardInfo(cardNumber: string, bankName: string, cardholderName: string): Promise<void> { let encryptedCardNumber = encryptData(cardNumber); let encryptedBankName = encryptData(bankName); let encryptedCardholderName = encryptData(cardholderName); await secureStorage.put('bank_card_number', encryptedCardNumber); await secureStorage.put('bank_name', encryptedBankName); await secureStorage.put('cardholder_name', encryptedCardholderName); } // 加密数据的函数(假设使用 AES 加密算法) function encryptData(data: string): string { // 这里实现 AES 加密逻辑,返回加密后的字符串 return encryptedData; }
(二)支付密码设置功能
密码强度验证
用户设置支付密码时,在应用层对密码强度进行验证,要求密码包含字母、数字、特殊字符等,且长度符合要求。例如:function validatePasswordStrength(password: string): boolean { // 密码强度验证逻辑,返回 true 或 false return password.length >= 8 && /[a-zA-Z]/.test(password) && /\d/.test(password) && /[^\w\s]/.test(password); }
密码加密与存储
支付密码同样需要进行加密处理后存储到本地安全存储区域。加密方式与银行卡信息加密类似,确保密码的安全性。例如:// 加密并存储支付密码 async function storePaymentPassword(password: string): Promise<void> { let encryptedPassword = encryptData(password); await secureStorage.put('payment_password', encryptedPassword); }
(三)支付订单功能
订单信息生成与加密
当用户发起支付订单时,应用在应用层生成订单信息,包括商品信息、金额、订单号等,然后在领域层对订单信息进行加密处理(可以使用与银行卡信息不同的加密密钥)。例如:import { uuid } from '@kit.UtilKit'; // 生成支付订单 async function createPaymentOrder(productInfo: string, amount: number): Promise<string> { let orderId = uuid.generate(); let orderInfo = { orderId, productInfo, amount }; let encryptedOrderInfo = encryptData(JSON.stringify(orderInfo)); return encryptedOrderInfo; }
发送支付请求与接收结果
使用网络通信 API 将加密后的订单信息发送到支付服务器,支付服务器进行解密和验证后,返回支付结果。应用接收支付结果并在表现层展示给用户。例如:import { net } from '@kit.NetworkKit'; // 发送支付请求 async function sendPaymentRequest(encryptedOrderInfo: string): Promise<void> { let request = net.createHttpRequest(); request.method = 'POST'; request.url = 'https://your-payment-server-url/pay'; request.headers = { 'Content-Type': 'application/json' }; request.requestBody = encryptedOrderInfo; try { await request.send(); if (request.responseCode === 200) { let paymentResult = JSON.parse(request.responseData); if (paymentResult.success) { console.log('支付成功。'); // 在表现层展示支付成功信息 } else { console.error('支付失败,原因:', paymentResult.errorMessage); // 在表现层展示支付失败信息 } } else { console.error('支付请求失败,错误码:', request.responseCode); } } catch (error) { console.error('支付请求过程中出错:', error); } }
(四)安全功能
- 防止数据泄露
除了对敏感数据进行加密存储外,应用在运行过程中要确保数据在内存中的安全。例如,在处理银行卡信息和支付密码时,尽量减少数据在内存中的停留时间,使用后及时清除。同时,防止应用被调试或反编译,通过鸿蒙 Next 的安全机制,如代码混淆、加固等手段,增加攻击者获取数据的难度。 - 防止恶意攻击
在网络通信方面,使用安全的网络协议(如 HTTPS),对网络请求进行签名和验证,防止中间人攻击和数据篡改。在应用层和领域层,对用户输入进行严格的验证和过滤,防止 SQL 注入、XSS 攻击等常见的网络攻击手段。例如,在处理用户输入的订单信息时,对特殊字符进行转义处理,防止 SQL 注入攻击。
四、总结与展望
通过本次实战,我们成功构建了一个基于鸿蒙 Next 系统的在线支付应用,涵盖了银行卡绑定、支付密码设置和支付订单等核心功能。在开发过程中,我们深入运用了鸿蒙 Next 的 Clean Architecture 架构、权限机制、安全控件、剪贴板操作和网络操作等关键技术,确保了应用的安全性、稳定性和功能性。
展望未来,随着金融科技的不断发展和用户需求的日益多样化,我们可以进一步优化在线支付应用的功能。例如,引入生物识别技术(如指纹识别、人脸识别),提升支付的便捷性和安全性。同时,加强与更多金融机构和商家的合作,拓展支付场景,为用户提供更加全面、便捷的支付服务。希望本文能够为鸿蒙 Next 同行者在金融应用开发领域提供有益的参考和借鉴,共同推动鸿蒙 Next 在金融科技领域的应用发展。
**粗体** _斜体_ [链接](http://example.com) `代码` - 列表 > 引用
。你还可以使用@
来通知其他用户。