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

使用async仍遇await只能在async函数内使用错误及API调用问题排查

Troubleshooting Your Express Route Issues

Let's tackle your two main problems step by step: the await is only valid in async functions error, and the failed external API calls with node-fetch/request.

1. Fixing the "await can only be used in async function" Error

The core issue here is scope mismatch: you marked the top-level router.post callback as async, but the nested successFunc callback inside db.getref is a regular synchronous function. When you try to use await fetch(...) inside that nested callback, it's not wrapped in an async context—hence the error.

Solution: Convert nested callbacks to async functions

Update the nested callbacks to be async so await works as expected, and add critical error handling:

const notify = router.post('/', async (req, res) => {
    console.log(req.body);
    const CLIENT_SECRET = process.env.PAYMENT_TEST_SECRET_KEY;
    let postData = {
        oid: req.body.orderId,
        amt: req.body.orderAmount,
        rsn: req.body.txMsg,
        tt: req.body.txTime
    }
    let signData = req.body.orderId + req.body.orderAmount + req.body.referenceId + req.body.txStatus + req.body.paymentMode + req.body.txMsg + req.body.txTime;
    
    let sdata = util.computeSign(signData);
    if (sdata == req.body.signature) {
        let data = { sts: 'Inprogress' };
        // Convert db.getref's success callback to async
        db.getref(postData.oid, 'txn', async (successFunc) => {
            if (successFunc) {
                const txnid = successFunc.id;
                const appId = successFunc.appid;
                db.updateById(
                    txnid,
                    data,
                    'txn',
                    async (success) => { // Mark this callback as async too
                        if (success) {
                            let payload = { txnId: txnid };
                            let PAYOUT_URI = 'https://ap.moneyorder.ws/api/v1/payout/test'
                            let Token = 'ceobrtoen'
                            let options = {
                                method: 'POST',
                                body: JSON.stringify(payload),
                                headers: {
                                    'Content-Type': 'application/json', // Critical for JSON payloads
                                    appid: appId,
                                    token: Token
                                }
                            }
                            try {
                                let response = await fetch(PAYOUT_URI, options);
                                // Catch HTTP errors (4xx/5xx status codes)
                                if (!response.ok) {
                                    throw new Error(`API request failed: ${response.status} ${response.statusText}`);
                                }
                                let tokenres = await response.json();
                                if (tokenres && tokenres.status === 'SUCCESS') {
                                    let updateObj = { sts: 'Success' };
                                    db.updateById(
                                        txnid,
                                        updateObj,
                                        'txn',
                                        (success) => {
                                            if (success) {
                                                console.log("payout updated") // Fixed typo: cosole → console
                                            } else {
                                                res.status(status.HTTPS.SERVER_ERROR).json({ data: null, msg: 'Something went wrong at our end.', success: false })
                                            }
                                        },
                                        (err) => {
                                            res.status(status.HTTPS.SERVER_ERROR).json({ data: null, msg: 'Something went wrong at our end.', success: false })
                                        }
                                    )
                                } else {
                                    res.status(status.HTTPS.SERVER_ERROR).json({ data: null, msg: "Payout API returned non-success status", success: false })
                                }
                            } catch (error) {
                                console.error('Fetch error details:', error); // Log full error for debugging
                                res.status(status.HTTPS.SERVER_ERROR).json({ data: null, msg: 'Something went wrong at our end.', success: false })
                            }
                        }
                    },
                    (err) => {
                        res.status(status.HTTPS.BAD_REQUEST).json({ success: false, msg: 'error 404', data: null })
                    }
                )
            } else {
                res.status(status.HTTPS.BAD_REQUEST).json({ success: false, msg: "empty response" })
            }
        })
    } else {
        console.log('Signature mismatch details:');
        console.log('Generated sign data:', signData);
        console.log('Computed signature:', sdata);
        console.log('Received signature:', req.body.signature);
        // Send a response to avoid client timeout
        res.status(status.HTTPS.UNAUTHORIZED).json({ success: false, msg: "Invalid signature" })
    }
})

Key fixes here:

  • Marked nested callbacks as async to enable await usage
  • Added Content-Type: application/json header (required for sending JSON payloads to APIs)
  • Fixed the cosole.log typo
  • Added HTTP error checking for node-fetch (it doesn't throw errors for 4xx/5xx status codes by default)
  • Added detailed error logging to debug API issues
  • Added a response for signature mismatch to prevent client hangs

2. Troubleshooting External API Call Failures

Whether you use node-fetch or request, these common fixes will resolve most API call issues:

Critical Checks for Both Libraries:

  • Missing Content-Type Header: Always include Content-Type: application/json when sending JSON payloads—APIs often reject requests without this.
  • Invalid URL: Double-check the payout API URL (your commented request code had a missing closing quote: 'https://ap.moneyorder.ws/api/v1/payout/test → fix this if you revert to request).
  • Credential Validation: Verify that Token and appId are correct. Temporarily log these values to confirm they're being passed properly.
  • Payload Structure: Cross-reference the API documentation to ensure your txnId payload matches the expected format.

Corrected request Module Example:

If you prefer using request, here's a robust version with proper error handling:

let payload = { txnId: txnid };
let Token = 'ceobrtoen';
const PAYOUT_URI = 'https://ap.moneyorder.ws/api/v1/payout/test'; // Fixed quote
let options = {
    method: 'POST',
    url: PAYOUT_URI,
    body: JSON.stringify(payload),
    headers: {
        'Content-Type': 'application/json', // Add this header
        appid: appId,
        token: Token
    }
}
request(options, (err, response, body) => {
    if (err) {
        console.error('Request network error:', err);
        res.status(status.HTTPS.SERVER_ERROR).json({ msg: 'Something went wrong.' })
        return;
    }
    // Catch HTTP errors
    if (response.statusCode >= 400) {
        console.error('API error response:', body);
        res.status(response.statusCode).json({ msg: 'Payout API error', error: body })
        return;
    }
    try {
        let data = JSON.parse(body);
        console.log('Payout API response:', data);
        if (data && data.status === 'SUCCESS') {
            // Update txn record logic here
        } else {
            res.status(status.HTTPS.SERVER_ERROR).json({ data: null, msg: "Payout API failed", success: false })
        }
    } catch (parseErr) {
        console.error('Failed to parse API response:', parseErr);
        res.status(status.HTTPS.SERVER_ERROR).json({ msg: 'Invalid response from payout API' })
    }
})

Debugging Tips:

  • Test the payout API directly with Postman or curl using your credentials and payload. This confirms if the issue is with your code or the API itself.
  • Log the full request options (URL, headers, body) before sending to verify formatting.
  • Check the API's documentation for any additional required headers or fields you might be missing.

内容的提问来源于stack exchange,提问作者Prateek Pareek

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.05.08 07:37:58