Skip to content

JSAPI 支付接口

接口说明

JSAPI 支付接口用于在 H5 页面小程序 内发起支付请求,支持微信支付和支付宝两种支付渠道。商户通过统一接口传入支付参数,平台返回对应渠道的支付凭证,前端调用相应 SDK 完成支付。

接口信息

  • 接口地址: POST /v1/pay/jsapi
  • Content-Type: application/json
  • 字符编码: UTF-8
  • 签名方式: RSA-SHA256

请求参数

认证信息

请在 HTTP Header 中携带 Authorization 字段,格式详见 接口概览

业务参数

参数名类型必填说明
merchant_noString商户号
out_trade_noString商户订单号,服务商自定义,商户系统内部唯一,建议 32 位以内
total_amountInteger订单总金额,单位:分
subjectString商品名称,显示在支付页面,128 字符以内
pay_methodString支付方式:wechat(微信)或 alipay(支付宝)
sub_appidString条件微信公众号或小程序的AppID,微信支付必填
sub_openidString条件用户标识:微信支付为用户openid,支付宝为用户userid
notify_urlString异步通知地址,必须为公网可访问的 HTTPS 地址
time_expireInteger订单过期时间(秒),从创建时开始计算,如 300 表示5分钟

请求示例

http
POST /v1/pay/jsapi
Content-Type: application/json
Authorization: RSA service_id=SVC1234567890,timestamp=1704067200,nonce_str=abc123,sign=签名值

{
  "merchant_no": "1234567890",
  "out_trade_no": "ORDER20240101120000",
  "total_amount": 100,
  "subject": "测试商品",
  "pay_method": "wechat",
  "sub_appid": "wx1234567890",
  "sub_openid": "oUpF8uMuAJO_M2pxb1Q9zNjWeS6o",
  "notify_url": "https://your-domain.meepay.org/api/notify",
  "time_expire": 300
}

响应参数

成功响应

参数名类型说明
codeString响应码,00000 表示成功
msgString响应消息
dataObject业务数据
data.pay_trade_noString商户单号,对应用户支付凭证里的商户单号
data.out_trade_noString商户订单号,服务商自定义
data.transaction_idString交易单号,对应用户支付凭证里的交易单号(支付宝返回)
data.pay_methodString支付方式: wechat 或 alipay
data.jspay_paramsObjectJSAPI支付参数(用于前端调起支付,仅微信支付返回)

jspay_params 说明

微信支付

参数名说明
appId微信公众号/小程序 AppID
timeStamp时间戳
nonceStr随机字符串
package预支付交易会话标识,格式:prepay_id=xxx
signType签名类型,固定值:RSA
paySign支付签名

支付宝

支付宝支付不返回 jspay_params,商户直接通过 transaction_id 或支付渠道SDK完成支付。

通用返回参数

响应示例

微信支付响应

json
{
  "code": "00000",
  "msg": "success",
  "data": {
    "out_trade_no": "ORDER20240101120000",
    "pay_trade_no": "WX20240101120000001",
    "pay_method": "wechat",
    "jspay_params": {
      "appId": "wx1234567890",
      "timeStamp": "1704067200",
      "nonceStr": "5K8264ILTKCH16CQ2502SI8ZNMTM67VS",
      "package": "prepay_id=wx20240101120000",
      "signType": "RSA",
      "paySign": "微信支付签名"
    }
  }
}

支付宝响应

json
{
  "code": "00000",
  "msg": "success",
  "data": {
    "out_trade_no": "ORDER20240101120000",
    "pay_trade_no": "ALI20240101120000001",
    "transaction_id": "2024010122001234567890",
    "pay_method": "alipay"
  }
}

前端调用示例

微信支付(H5/小程序)

javascript
// 1. 后端请求 JSAPI 接口,获取 jspay_params
const response = await fetch('https://your-backend.meepay.org/api/pay/jsapi', {
  method: 'POST',
  headers: { 'Content-Type': 'application/json' },
  body: JSON.stringify({
    out_trade_no: 'ORDER20240101120000',
    total_amount: 100,
    subject: '测试商品',
    pay_method: 'wechat',
    sub_appid: 'wx1234567890',
    sub_openid: 'oUpF8uMuAJO_M2pxb1Q9zNjWeS6o'
  })
});

const result = await response.json();

// 2. 调用微信支付
if (result.code === '00000') {
  const jspayParams = result.data.jspay_params;
  
  // H5 环境
  if (typeof WeixinJSBridge !== 'undefined') {
    WeixinJSBridge.invoke('getBrandWCPayRequest', {
      appId: jspayParams.appId,
      timeStamp: jspayParams.timeStamp,
      nonceStr: jspayParams.nonceStr,
      package: jspayParams.package,
      signType: jspayParams.signType,
      paySign: jspayParams.paySign
    }, function(res) {
      if (res.err_msg === 'get_brand_wcpay_request:ok') {
        // 支付成功
        alert('支付成功');
        window.location.href = 'https://your-domain.meepay.org/pay/success';
      } else {
        // 支付失败或取消
        alert('支付失败');
      }
    });
  }
  
  // 小程序环境
  wx.requestPayment({
    timeStamp: jspayParams.timeStamp,
    nonceStr: jspayParams.nonceStr,
    package: jspayParams.package,
    signType: jspayParams.signType,
    paySign: jspayParams.paySign,
    success: function(res) {
      // 支付成功
      wx.showToast({ title: '支付成功' });
    },
    fail: function(err) {
      // 支付失败
      wx.showToast({ title: '支付失败', icon: 'error' });
    }
  });
}

支付宝支付

javascript
// 1. 后端请求 JSAPI 接口
const response = await fetch('https://your-backend.meepay.org/api/pay/jsapi', {
  method: 'POST',
  headers: { 'Content-Type': 'application/json' },
  body: JSON.stringify({
    out_trade_no: 'ORDER20240101120000',
    total_amount: 100,
    subject: '测试商品',
    pay_method: 'alipay',
    sub_openid: '20881234567890'
  })
});

const result = await response.json();

// 2. 使用 transaction_id 或跳转支付
if (result.code === '00000') {
  const transactionId = result.data.transaction_id;
  
  // 根据业务需求处理
  console.log('支付宝交易单号:', transactionId);
  
  // 可使用 transaction_id 查询支付状态
}

异步通知

通知地址

商户需在请求参数中提供 notify_url,支付完成后平台将向该地址发送异步通知。

通知参数

json
{
  "service_id": "SVC1234567890",
  "merchant_no": "1234567890",
  "out_trade_no": "ORDER20240101120000",
  "trade_no": "MF20240101120000001",
  "total_amount": 100,
  "pay_amount": 100,
  "trade_state": "SUCCESS",
  "pay_method": "wechat",
  "pay_time": "20240101120000",
  "notify_time": "20240101120001"
}

处理流程

  1. 验证签名: 从 HTTP Header 中获取 Authorization,使用平台公钥验证通知签名
  2. 验证数据: 检查 out_trade_nototal_amount 等关键信息
  3. 处理业务: 更新订单状态、发货等
  4. 返回响应: 返回 success 字符串(不含引号)

通知重试机制

  • 通知频率:0s、15s、15s、30s、3min、10min、20min、30min、30min
  • 最多重试 10 次
  • 只有在接收到 success 响应后才停止重试

通知处理示例(Node.js)

javascript
const express = require('express');
const router = express.Router();

router.post('https://api.meepay.org/notify', async (req, res) => {
  try {
    const notifyData = req.body;
    const authorization = req.headers.authorization;
    
    // 1. 验证签名(从 Authorization Header 中)
    const isValid = verifySign(authorization, platformPublicKey);
    if (!isValid) {
      console.error('签名验证失败');
      res.send('failure');
      return;
    }
    
    // 2. 验证订单金额
    const order = await getOrder(notifyData.out_trade_no);
    if (order.total_amount !== notifyData.total_amount) {
      console.error('订单金额不匹配');
      res.send('failure');
      return;
    }
    
    // 3. 更新订单状态
    if (notifyData.trade_state === 'SUCCESS' || notifyData.trade_state === 'TRADE_FINISHED') {
      await updateOrderStatus(notifyData.out_trade_no, 'PAID');
      // 执行业务逻辑:发货、发送通知等
    }
    
    // 4. 返回成功
    res.send('success');
  } catch (error) {
    console.error('处理通知失败:', error);
    res.send('failure');
  }
});

module.exports = router;

支付流程

错误码

错误码说明处理建议
00000成功-
10001参数错误检查请求参数是否完整、格式是否正确
10002签名验证失败检查签名算法、密钥是否正确
10003服务商号不存在确认 service_id 是否正确
10004商户未开通该支付方式联系平台开通相应方式
10005订单号重复更换唯一的订单号
10006订单金额错误确认金额为正整数,单位:分
10007时间戳过期检查服务器时间是否同步
10008支付方式错误检查 pay_method 参数是否正确
10009sub_openid 无效确认 sub_openid/sub_appid 是否正确
10010系统繁忙稍后重试或联系客服

注意事项

  1. 订单号唯一性: out_trade_no 在商户系统内必须唯一,重复订单号将返回错误
  2. 金额单位: 金额单位统一为,避免浮点数精度问题
  3. 时间戳: 请求时间戳与服务器时间相差超过 5 分钟将被拒绝
  4. 签名安全: 私钥必须严格保密,不可在前端暴露
  5. 异步通知: 必须正确处理异步通知,不能仅依赖前端回调
  6. 幂等性: 同一订单号多次请求将返回相同结果,确保接口幂等
  7. HTTPS: 所有接口必须使用 HTTPS 协议
  8. 通知地址: notify_url 必须为公网可访问的 HTTPS 地址

常见问题

Q: 微信支付提示"签名错误"怎么办?

  1. 检查商户 API 密钥是否正确
  2. 确认签名算法是否为 RSA-SHA256
  3. 检查参数排序和拼接是否正确

Q: 支付宝支付无法调起?

  1. 检查是否正确提交表单
  2. 确认付款方 ID(payer_id)是否正确
  3. 检查支付宝公钥是否配置正确

Q: 异步通知收不到怎么办?

  1. 确认 notify_url 是否为公网可访问地址
  2. 检查服务器防火墙是否拦截了请求
  3. 查看服务器日志,确认是否正常接收通知
  4. 可在商户平台查看通知发送记录

Q: 如何测试支付功能?

  1. 使用测试环境进行开发调试
  2. 微信支付可使用沙箱环境
  3. 支付宝可使用沙箱账号测试
  4. 测试完成后切换到生产环境

米付科技版权所有,保留所有权利