Swish API提现请求报错PA01:参数不正确,求排查方案
Swish API提现请求触发401未授权错误(错误码PA01)
错误响应详情:
{ "errorCode": "PA01", "errorMessage": "Parameter is not correct.", "additionalInformation": null }
我基于Node.js和Express框架集成Swish API的提现功能,严格按照官方文档操作,但始终触发401未授权错误,错误码为PA01,提示参数不正确。我已确认payload格式符合要求,签名生成遵循规范,且证书与密钥配置无误,现请求协助排查该错误的原因及解决方法。
实现代码
const express = require('express'); const fs = require('fs'); const crypto = require('crypto'); const https = require('https'); const path = require('path'); const fetch = (...args) => import('node-fetch').then(({ default: fetch }) => fetch(...args)); const forge = require('node-forge'); const { execSync } = require('child_process'); const app = express(); app.use(express.json()); const basePath = '/Users/xx/downloads/mss_test_2.0/Getswish_Test_Certificates/'; const authCertPath = path.join(basePath, 'Swish_Merchant_TestCertificate_1234679304.p12'); const signingCertPath = path.join(basePath, 'Swish_Merchant_TestSigningCertificate_1234679304.p12'); const caCertPath = path.join(basePath, 'Swish_TLS_RootCA.pem'); const passphrase = 'swish'; // 假设两个证书的密码一致 const getCertAndKeyFromP12 = (p12Path, passphrase) => { const p12Content = fs.readFileSync(p12Path, 'binary'); const p12Asn1 = forge.asn1.fromDer(p12Content); const p12 = forge.pkcs12.pkcs12FromAsn1(p12Asn1, false, passphrase); const keyObj = p12.getBags({ bagType: forge.pki.oids.pkcs8ShroudedKeyBag })[forge.pki.oids.pkcs8ShroudedKeyBag][0]; const certObj = p12.getBags({ bagType: forge.pki.oids.certBag })[forge.pki.oids.certBag][0]; const key = forge.pki.privateKeyToPem(keyObj.key); const cert = forge.pki.certificateToPem(certObj.cert); return { cert, key }; }; const getCertificateSerialNumber = (certPath, passphrase) => { const certContent = fs.readFileSync(certPath, 'binary'); const p12Asn1 = forge.asn1.fromDer(certContent); const p12 = forge.pkcs12.pkcs12FromAsn1(p12Asn1, false, passphrase); const certObj = p12.getBags({ bagType: forge.pki.oids.certBag })[forge.pki.oids.certBag][0]; const cert = forge.pki.certificateToPem(certObj.cert); const serialNumber = certObj.cert.serialNumber.toUpperCase(); console.log(`Extracted Serial Number: ${serialNumber}`); return serialNumber; }; const getHashedPayload = (payload) => { return crypto.createHash('sha512').update(payload).digest(); }; const getCertificateSignature = (hash, privateKey) => { const sign = crypto.createSign('RSA-SHA512'); sign.update(hash); sign.end(); return sign.sign(privateKey, 'base64'); }; app.post('/create-payout', (req, res) => { const { cert, key: signingPrivateKey } = getCertAndKeyFromP12(signingCertPath, passphrase); const payload = { amount: parseFloat(req.body.amount,2).toString(), currency: 'SEK', instructionDate: new Date().toISOString(), message: req.body.message, payeeAlias: '0728648607', payeeSSN: '196702234292', payerAlias: '1234679304', payerPaymentReference: 'mockedPayerPaymentReference', payoutInstructionUUID: '822735C159A944DBB2B3546717BC919F', payoutType: 'PAYOUT', signingCertificateSerialNumber: getCertificateSerialNumber(signingCertPath, passphrase) }; const payloadString = JSON.stringify(payload); const payloadHash = getHashedPayload(payloadString); const signature = getCertificateSignature(payloadHash, signingPrivateKey); const requestBody = { payload, signature, callbackUrl: 'https://xxxx.ngrok-free.app/swishcallback' }; console.log(JSON.stringify(requestBody)) const requestOptions = { method: 'POST', headers: { 'Content-Type': 'application/json' }, body: JSON.stringify(requestBody), agent: new https.Agent({ pfx: fs.readFileSync(authCertPath), passphrase: passphrase, ca: fs.readFileSync(caCertPath) }) }; fetch('https://mss.cpc.getswish.net/swish-cpcapi/api/v1/payouts', requestOptions) .then(response => response.json()) .then(data => res.json(data)) .catch(error => res.status(500).json({ error: error.message })); }); app.listen(3000, () => { console.log('Server is running on http://localhost:3000'); });
请求体示例
{ "amount": 100.00, "message": "example message" }
参考官方文档:
- Swish开发者平台环境配置说明
- MSS v1 API提现请求接口规范
内容的提问来源于stack exchange,提问作者hpryda
相关产品推荐
相关产品推荐

