You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

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

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.06.21 13:09:51