1/* 2* Copyright (c) 2023 Hunan OpenValley Digital Industry Development Co., Ltd. 3* Licensed under the Apache License, Version 2.0 (the "License"); 4* you may not use this file except in compliance with the License. 5* You may obtain a copy of the License at 6* 7* http://www.apache.org/licenses/LICENSE-2.0 8* 9* Unless required by applicable law or agreed to in writing, software 10* distributed under the License is distributed on an "AS IS" BASIS, 11* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 12* See the License for the specific language governing permissions and 13* limitations under the License. 14*/ 15 16import CreateOrGet from './SingleInstanceHelper'; 17import cryptoFramework from '@ohos.security.cryptoFramework'; 18import util from '@ohos.util'; 19 20export enum PayResult { 21 SUCCESS = 200, 22 FAIL = 400, 23 ERROR = 600, 24} 25 26export interface User { 27 name: string, 28 payPassword: string, 29} 30 31const TAG = 'PayServer'; 32const TEXT_DECODER = util.TextDecoder.create('utf-8', { ignoreBOM: true }); 33const TEXT_ENCODER = new util.TextEncoder(); 34const SIGNER_INPUT = { data: TEXT_ENCODER.encodeInto('This is a test') }; 35const BASE64 = new util.Base64Helper(); 36// 支付服务端私钥 37const PAY_PRI_KEY = 'MIICdQIBADANBgkqhkiG9w0BAQEFAASCAl8wggJbAgEAAoGBAMMWX1SJUPCshS1NIVVpqkaAfu/baUGqebuSo6NR00JokT54FWEJVPYrcrKQ+4TjGC0p6PavL7YeZ7kxBplnHunE2RcTo/r3LebZVunUqcWCxe1ZiV0YD++uZtegOEpTgd2w8Lib72+wQt68WO43I40wwySUX+X7dF1nSDNGA6YnAgMBAAECgYACZjYJ7h5mt1hz9CzixgfoEhB9lq82tYgFvInyqkD04iBXKlbo+Jpo5KPmek39lmVnuMo6rnDhxoH0DxxLqq8An4Hk6f/G1Eyc681sEicuas4zanpGWtPA3Y+an9ZwwTolVIkiJw6nM4hz8QdEeiFK34Bfl28dz9kg89ZrVomlwQJBAOEJPtA7QPwSuxix2E+BsPVNg/EqXgs+9HoyF+lrH8to5gTAZSjydT03d6FUZOZBsgPB/hL+Avh5YTUjhBV6khcCQQDd7jPFabvcyr5cKyS2TqYGmqTnhDX3LxgB35GE6jLlMO3teIY1HUsQsV2946lE4s7aqcalXa37Dw7yLxwlbGZxAkAggA5TUotzHF1rFpxP90IQW26X0O+eHix+zWdIrdD8tpypyQOTI1ktSyp64U5lNs233zeLlKXnLtiMLSHxXC9nAkAPbZvTwYH5225YYfdvZRBNrTqBjcNip7d3id9H6jAXlsszkwlhb+PkCTCHHuiJjWrr8JmKrXSG24kidPvz7hFBAkABQhnS1b3O4IIs5rdQTwcgBpzUk76csUQFB35g0IMV4jeHE7+84rNJDQ8hgStmyQvrLH8bBjX3xftxvj+q57cd'; 38// 商户服务端公钥 39const MERCHANT_PUB_KEY = 'MFkwEwYHKoZIzj0CAQYIKoZIzj0DAQcDQgAE/4Xcag3k5SBGX52KduDPcYBSEanwpo85kzGceENvQkhG0UinwwxSttkXv9os1pikfChaD5vR2BhXsco54SC/rA=='; 40// 支付客户端私钥 41const PAY_CLIENT_PRI_KEY = 'MIICdwIBADANBgkqhkiG9w0BAQEFAASCAmEwggJdAgEAAoGBAPvx0A4ex864EDiA8wDwY7/kqVDjzvsoC9pOSkkgMCRoBuWEADHiYoZrgrg9NLtPHONd0SD8Jk4B2eqym4ylB/bk87Jy4bbIdajeM86tvuS2R/RqPlOdFbeRoGFnlPITozGdQImH4eRfwRCnpYZqooIHDkPUWD2gDSuBmKCLqcP/AgMBAAECgYEAlrVgsoGhHjwmn9YrBp3F3Y0H53ZOYxjidjUs5K9XfP+pWHPstepo62W2bUVXnNBHRI7jQWrz8ufSlj0/JRO3Pb6CJp4u3Qw4ty/GAXtNUaaEb8Ll0SFkwu7TiUkHCEjnjF/aCkFVOAxwa2RT0GWs1uj+uqF7KyMylL4RZCyAnCkCQQD+74SDaTomcNHzPpVXyumZpmIxWpkP6GbcA0yjV3aw+K7IIHs20cYiNRXWw51Uh1aHTwqd8+/Ywq6IP9VHZT27AkEA/P8ZIoUZ/QsvIu0eUZRE9JaB4bcfD8RUGetqZhZA6J6Nd6uJ1nut/XG0JGa4wqSqBWGs8BBV6aDNuJzrzOYMjQJBAMMMwphAhEsw+pFfCqhXCY+Ta4FTTdSL/VbL93Dp1FfmjON1ZpA0w6EceI8Or2si+SMhaIAdSR7RJPP90tKDNU0CQExxX8zYXsPgjzuEXfbUUAl/OHtU82O2NJsoUJvL+YzP63rPL/TIpgfARWgCSa02R9EcdD6NEQhoeABiGbVthTkCQF8gsjNa6KIpfqEf4+DZFNO2o28ELyniY4O6xUKHWfiU7vKxRQ2DFYQ8Hv9Q07HB69kXc0p/XLJxjpX0K/Wpn2k='; 42const TEST_USER: User = { 43 name: 'test', 44 payPassword: '123456', 45}; 46const HEXADECIMAL = 36; 47const CONTAINS_LETTERS = 2; 48const MIN_LENGTH = 2; 49const INDEX_ZERO = 0; 50 51class PayServer { 52 private orderString: string; 53 private merchantKey: cryptoFramework.KeyPair; 54 private payKey: cryptoFramework.KeyPair; 55 private payClientKey: cryptoFramework.KeyPair; 56 57 public async generatePayOrder(body: string): Promise<string> { 58 if (!this.payKey) { 59 let rsaGenerator = cryptoFramework.createAsyKeyGenerator('RSA1024|PRIMES_2'); 60 this.payKey = await rsaGenerator.convertKey(null, { data: BASE64.decodeSync(PAY_PRI_KEY) }); 61 } 62 let decoder = cryptoFramework.createCipher('RSA1024|PKCS1'); 63 await decoder.init(cryptoFramework.CryptoMode.DECRYPT_MODE, this.payKey.priKey, null); 64 let data = await decoder.doFinal({ data: BASE64.decodeSync(body) }); 65 let bodyStr = TEXT_DECODER.decodeWithStream(data.data); 66 this.orderString = bodyStr + '&orderId=' + Array.from({ 67 length: 17 68 }, () => Math.random().toString(HEXADECIMAL)[CONTAINS_LETTERS]).join('').toUpperCase(); 69 return this.orderString; 70 } 71 72 public async pay(orderString: string, userName: string, password: string): Promise<PayResult> { 73 let temArr = orderString.split('&signer='); 74 if (temArr.length < MIN_LENGTH || temArr[INDEX_ZERO] !== this.orderString) { 75 return PayResult.ERROR; 76 } 77 if (!this.merchantKey) { 78 let eccGenerator = cryptoFramework.createAsyKeyGenerator('ECC256'); 79 this.merchantKey = await eccGenerator.convertKey({ data: BASE64.decodeSync(MERCHANT_PUB_KEY) }, null); 80 } 81 let verifyer = cryptoFramework.createVerify('ECC256|SHA256'); 82 await verifyer.init(this.merchantKey.pubKey); 83 let verifyOk = await verifyer.verify(SIGNER_INPUT, { data: BASE64.decodeSync(temArr[1]) }); 84 if (!verifyOk) { 85 return PayResult.ERROR; 86 } 87 if (!this.payClientKey) { 88 let rsaGenerator = cryptoFramework.createAsyKeyGenerator('RSA1024|PRIMES_2'); 89 this.payClientKey = await rsaGenerator.convertKey(null, { data: BASE64.decodeSync(PAY_CLIENT_PRI_KEY) }); 90 } 91 let decoder = cryptoFramework.createCipher('RSA1024|PKCS1'); 92 await decoder.init(cryptoFramework.CryptoMode.DECRYPT_MODE, this.payClientKey.priKey, null); 93 let userNameData = await decoder.doFinal({ data: BASE64.decodeSync(userName) }); 94 if (TEST_USER.name !== TEXT_DECODER.decodeWithStream(userNameData.data)) { 95 return PayResult.FAIL; 96 } 97 let passwordData = await decoder.doFinal({ data: BASE64.decodeSync(password) }); 98 if (TEST_USER.payPassword !== TEXT_DECODER.decodeWithStream(passwordData.data)) { 99 return PayResult.FAIL; 100 } 101 return PayResult.SUCCESS; 102 } 103} 104 105let mPayServer = CreateOrGet(PayServer, TAG); 106 107export default mPayServer as PayServer;