import pem from 'pem' import { readFileSync } from 'fs' import crypto from 'crypto' import axios from 'axios' import { format, addSeconds } from 'date-fns' import qs from 'querystring' const privateKey = crypto.createPrivateKey({ key: readFileSync('certs/6888806043057.key') }) const publicKey = crypto.createPublicKey({ key: readFileSync('certs/sand.crt') }) function privSign(str) { const signer = crypto.createSign('SHA1') signer.update(str) signer.end() const signature = signer.sign(privateKey) return signature.toString('base64') } function verifySign(str, sign) { const verifier = crypto.createVerify('SHA1') verifier.update(str) verifier.end() return verifier.verify(publicKey, Buffer.from(sign.replace(/\s/g, '+'), 'base64')) } async function request(header, body, url) { const data = { head: header, body } const dataStr = JSON.stringify(data) console.log(JSON.stringify(data, null, 4)) const sign = await privSign(dataStr) const postBody = { charset: 'UTF-8', data: dataStr, signType: '01', sign, extend: '' } console.log(qs.stringify(postBody)) return await axios.post(url, qs.stringify(postBody), { headers: { 'Content-Type': 'application/x-www-form-urlencoded;charset=UTF-8' }, timeout: 30000, timeoutErrorMessage: '请求超时' }) } const algorithm = 'aes-128-ecb' async function pay() { const data = { cityNo: '', productId: '00000004', bankType: '', payMode: '', accNo: '6222024301070380165', accName: '熊竹', bankName: '', remark: '消费', channelType: '', accAttr: '0', version: '01', timeOut: '20230506150701', extend: '', extendParams: '', tranTime: '20230506150401', provNo: '', phone: '', tranAmt: '000000000100', reqReserved: '', orderCode: new Date().getTime() + '', accType: '4', currencyCode: '156' } const dataStr = JSON.stringify(data) // 加密密钥,必须是 16、24 或 32 个字符长(分别对应 AES-128、AES-192 或 AES-256) const key = crypto.randomBytes(16) // 加密算法使用 AES-256-ECB // 将要加密的数据转换为一个 Buffer 对象 const dataBuffer = Buffer.from(dataStr, 'utf8') // 创建一个加密器对象,使用 PKCS5Padding 进行补位 const cipher = crypto.createCipheriv(algorithm, key, null) cipher.setAutoPadding(true) // 加密数据,并返回加密后的 Buffer 对象 const encryptedBuffer = Buffer.concat([cipher.update(dataBuffer), cipher.final()]) // 将加密后的 Buffer 对象转换为十六进制字符串 const encrypted = encryptedBuffer.toString('base64') const sign = await privSign(dataStr) console.log(encrypted) const encryptKey = crypto .publicEncrypt( { key: publicKey, padding: crypto.constants.RSA_PKCS1_PADDING }, key ) .toString('base64') console.log(encryptKey) const body = { transCode: 'RTPM', accessType: '0', merId: '6888806043057', encryptKey: encryptKey, encryptData: encrypted, sign, extend: '' } const res = await axios.post('http://120.78.171.194:11223/agent-main/openapi/agentpay', qs.stringify(body)) const retData = qs.parse(qs.unescape(res.data)) console.log(retData) const decryptKey = crypto.privateDecrypt( { key: privateKey, padding: crypto.constants.RSA_PKCS1_PADDING }, Buffer.from(retData.encryptKey.replace(/\s/g, '+'), 'base64') ) console.log(decryptKey.toString()) const decipher = crypto.createDecipheriv(algorithm, decryptKey, null) decipher.setAutoPadding(true) const decryptedBuffer = Buffer.concat([ decipher.update(Buffer.from(retData.encryptData.replace(/\s/g, '+'), 'base64')), decipher.final() ]) const decrypted = decryptedBuffer.toString('utf8') console.log(decrypted) const verify = verifySign(decrypted, retData.sign) console.log(verify) } await pay()