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

PhonePe支付API跨域问题求助:本地及线上环境请求失败

PhonePe支付API前端请求CORS问题排查与解决

问题描述

调用PhonePe预生产环境支付API(接口地址:https://api-preprod.phonepe.com/apis/merchant-simulator/pg/v1/pay)时遇到以下问题:

  • 请求体为Base64编码的payload,请求头携带Sha256加密的x-verify参数
  • 在PhonePe官网提供的Postman示例中调用完全正常,可获取交易初始化响应
  • 但在本地localhost环境和正式网站上发起请求时,均触发CORS拦截,报错信息:

Access to fetch at 'https://api-preprod.phonepe.com/apis/merchant-simulator/pg/v1/pay' from origin 'https://www.wearmiho.com' has been blocked by CORS policy: Response to preflight request doesn't pass access control check: No 'Access-Control-Allow-Origin' header is present on the requested resource. If an opaque response serves your needs, set the request's mode to 'no-cors' to fetch the resource with CORS disabled.

尝试添加mode: "no-cors"参数后,请求依然失败。目前已排查两个方向:

  1. 怀疑需在PhonePe平台预注册域名,但PhonePe团队明确表示测试凭证支持任意URL(本地或线上网站)
  2. 代码严格遵循PhonePe开发者文档中的Postman示例编写,暂未发现明显错误

核心原因

浏览器同源策略会拦截前端直接发起的跨域请求,PhonePe预生产API服务器未配置允许前端跨域的响应头(如Access-Control-Allow-Origin),导致预飞(OPTIONS)请求失败。添加no-cors仅能让请求不报错,但会返回不透明响应,无法获取交易初始化数据,无法满足业务需求。

可行解决方案

1. 搭建后端代理服务(推荐)

前端不直接请求PhonePe API,改为请求自身后端接口,由后端转发请求到PhonePe API(后端请求不受浏览器同源策略限制):

  • 后端在响应中添加允许前端域名的CORS头(如Access-Control-Allow-Origin: https://www.wearmiho.com或*)
  • 前端请求后端代理接口,获取返回的交易数据

示例Node.js代理代码(基于Express):

const express = require('express');
const axios = require('axios');
const cors = require('cors');
const app = express();

// 配置允许的前端域名
app.use(cors({ origin: ['http://localhost:3000', 'https://www.wearmiho.com'] }));
app.use(express.json());

// 代理接口
app.post('/api/phonepe/pay', async (req, res) => {
  try {
    const phonePeResponse = await axios.post(
      'https://api-preprod.phonepe.com/apis/merchant-simulator/pg/v1/pay',
      req.body,
      { headers: req.headers }
    );
    res.send(phonePeResponse.data);
  } catch (error) {
    res.status(error.response?.status || 500).send(error.response?.data || '代理请求失败');
  }
});

app.listen(4000, () => console.log('代理服务运行在4000端口'));

前端修改请求地址为代理接口:

fetch('/api/phonepe/pay', {
  method: 'POST',
  headers: {
    'Content-Type': 'application/json',
    'x-verify': '你的Sha256加密值'
  },
  body: JSON.stringify({ base64Payload: '你的Base64编码payload' })
})
.then(res => res.json())
.then(data => console.log(data))
.catch(err => console.error(err));

2. 验证请求参数细节

即使代码与Postman一致,仍需核对以下内容:

  • 确认x-verify参数生成逻辑:Sha256加密内容是否包含payload、salt等必要信息,加密后是否拼接了###{saltIndex}后缀
  • 检查Base64编码的payload是否无额外空格、换行符
  • 确认请求头Content-Type符合PhonePe要求(通常为application/json)

3. 再次确认PhonePe平台配置

尽管对方表示测试凭证支持任意域名,仍可向PhonePe团队确认:

  • 预生产环境API是否开启前端跨域支持
  • 是否存在隐藏的域名白名单配置需手动添加
  • 测试凭证权限是否允许发起前端跨域请求

内容的提问来源于stack exchange,提问作者ProXiMa Akash

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.07.31 11:56:34