• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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 cryptoFramework from '@ohos.security.cryptoFramework';
17import util from '@ohos.util';
18
19export enum PayResult {
20  SUCCESS = 200,
21  FAIL = 400,
22  ERROR = 600,
23}
24
25export interface User {
26  name: string,
27  payPassword: string,
28}
29
30const TAG = 'PayServer';
31const TEXT_DECODER = util.TextDecoder.create('utf-8', { ignoreBOM: true });
32const TEXT_ENCODER = new util.TextEncoder();
33const SIGNER_INPUT = { data: TEXT_ENCODER.encodeInto('This is a test') };
34const BASE64 = new util.Base64Helper();
35// 支付服务端私钥
36const PAY_PRI_KEY = 'MIICdQIBADANBgkqhkiG9w0BAQEFAASCAl8wggJbAgEAAoGBAMMWX1SJUPCshS1NIVVpqkaAfu/baUGqebuSo6NR00JokT54FWEJVPYrcrKQ+4TjGC0p6PavL7YeZ7kxBplnHunE2RcTo/r3LebZVunUqcWCxe1ZiV0YD++uZtegOEpTgd2w8Lib72+wQt68WO43I40wwySUX+X7dF1nSDNGA6YnAgMBAAECgYACZjYJ7h5mt1hz9CzixgfoEhB9lq82tYgFvInyqkD04iBXKlbo+Jpo5KPmek39lmVnuMo6rnDhxoH0DxxLqq8An4Hk6f/G1Eyc681sEicuas4zanpGWtPA3Y+an9ZwwTolVIkiJw6nM4hz8QdEeiFK34Bfl28dz9kg89ZrVomlwQJBAOEJPtA7QPwSuxix2E+BsPVNg/EqXgs+9HoyF+lrH8to5gTAZSjydT03d6FUZOZBsgPB/hL+Avh5YTUjhBV6khcCQQDd7jPFabvcyr5cKyS2TqYGmqTnhDX3LxgB35GE6jLlMO3teIY1HUsQsV2946lE4s7aqcalXa37Dw7yLxwlbGZxAkAggA5TUotzHF1rFpxP90IQW26X0O+eHix+zWdIrdD8tpypyQOTI1ktSyp64U5lNs233zeLlKXnLtiMLSHxXC9nAkAPbZvTwYH5225YYfdvZRBNrTqBjcNip7d3id9H6jAXlsszkwlhb+PkCTCHHuiJjWrr8JmKrXSG24kidPvz7hFBAkABQhnS1b3O4IIs5rdQTwcgBpzUk76csUQFB35g0IMV4jeHE7+84rNJDQ8hgStmyQvrLH8bBjX3xftxvj+q57cd';
37// 商户服务端公钥
38const MERCHANT_PUB_KEY = 'MFkwEwYHKoZIzj0CAQYIKoZIzj0DAQcDQgAE/4Xcag3k5SBGX52KduDPcYBSEanwpo85kzGceENvQkhG0UinwwxSttkXv9os1pikfChaD5vR2BhXsco54SC/rA==';
39// 支付客户端私钥
40const 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=';
41const TEST_USER: User = {
42  name: 'test',
43  payPassword: '123456',
44};
45const HEXADECIMAL = 36;
46const CONTAINS_LETTERS = 2;
47const MIN_LENGTH = 2;
48const INDEX_ZERO = 0;
49
50export class PayServer {
51  private orderString: string;
52  private merchantKey: cryptoFramework.KeyPair;
53  private payKey: cryptoFramework.KeyPair;
54  private payClientKey: cryptoFramework.KeyPair;
55  private static instance: PayServer;
56
57  private constructor() {
58  }
59
60  public static getInstance(): PayServer {
61    if (!PayServer.instance) {
62      PayServer.instance = new PayServer();
63    }
64    return PayServer.instance;
65  }
66
67  public async generatePayOrder(body: string): Promise<string> {
68    if (!this.payKey) {
69      let rsaGenerator = cryptoFramework.createAsyKeyGenerator('RSA1024|PRIMES_2');
70      this.payKey = await rsaGenerator.convertKey(null, { data: BASE64.decodeSync(PAY_PRI_KEY) });
71    }
72    let decoder = cryptoFramework.createCipher('RSA1024|PKCS1');
73    await decoder.init(cryptoFramework.CryptoMode.DECRYPT_MODE, this.payKey.priKey, null);
74    let data = await decoder.doFinal({ data: BASE64.decodeSync(body) });
75    let bodyStr = TEXT_DECODER.decodeWithStream(data.data);
76    this.orderString = bodyStr + '&orderId=' + Array.from({
77      length: 17
78    }, () => Math.random().toString(HEXADECIMAL)[CONTAINS_LETTERS]).join('').toUpperCase();
79    return this.orderString;
80  }
81
82  public async pay(orderString: string, userName: string, password: string): Promise<PayResult> {
83    let temArr = orderString.split('&signer=');
84    if (temArr.length < MIN_LENGTH || temArr[INDEX_ZERO] !== this.orderString) {
85      return PayResult.ERROR;
86    }
87    if (!this.merchantKey) {
88      let eccGenerator = cryptoFramework.createAsyKeyGenerator('ECC256');
89      this.merchantKey = await eccGenerator.convertKey({ data: BASE64.decodeSync(MERCHANT_PUB_KEY) }, null);
90    }
91    let verifyer = cryptoFramework.createVerify('ECC256|SHA256');
92    await verifyer.init(this.merchantKey.pubKey);
93    let verifyOk = await verifyer.verify(SIGNER_INPUT, { data: BASE64.decodeSync(temArr[1]) });
94    if (!verifyOk) {
95      return PayResult.ERROR;
96    }
97    if (!this.payClientKey) {
98      let rsaGenerator = cryptoFramework.createAsyKeyGenerator('RSA1024|PRIMES_2');
99      this.payClientKey = await rsaGenerator.convertKey(null, { data: BASE64.decodeSync(PAY_CLIENT_PRI_KEY) });
100    }
101    let decoder = cryptoFramework.createCipher('RSA1024|PKCS1');
102    await decoder.init(cryptoFramework.CryptoMode.DECRYPT_MODE, this.payClientKey.priKey, null);
103    let userNameData = await decoder.doFinal({ data: BASE64.decodeSync(userName) });
104    if (TEST_USER.name !== TEXT_DECODER.decodeWithStream(userNameData.data)) {
105      return PayResult.FAIL;
106    }
107    let passwordData = await decoder.doFinal({ data: BASE64.decodeSync(password) });
108    if (TEST_USER.payPassword !== TEXT_DECODER.decodeWithStream(passwordData.data)) {
109      return PayResult.FAIL;
110    }
111    return PayResult.SUCCESS;
112  }
113}