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

Flutter环境下Razorpay退款功能实现失败问题求助

问题描述

我正在使用Razorpay Flutter包在测试模式下实现支付功能,已完成事件处理逻辑并将paymentId保存至数据库。现需基于该paymentId为用户办理退款,但对具体实现流程不够清晰,且自行编写的退款代码无法正常运行。

支付请求代码

Razorpay? _razorpay = Razorpay();
void openPaymentPortal() async {
var options = {
  'key': 'My_key',
  'amount': 100000,
  'name': 'test',
  'description': 'Payment for Pro account',
  'prefill': {'contact': '9999999999', 'email': 'build@test.com'},
  'external': {
    'wallets': ['paytm']
  }
};
try {
  _razorpay?.open(options);
} catch (e) {
  debugPrint(e.toString());
}
}

void _handlePaymentSuccess(PaymentSuccessResponse response) {
Fluttertoast.showToast(
    msg: "SUCCESS PAYMENT: ${response.paymentId}", timeInSecForIosWeb: 5);
onSubmit(false, response.paymentId.toString());
}

void _handlePaymentError(PaymentFailureResponse response) {
Fluttertoast.showToast(
    msg: "ERROR HERE: ${response.code} - ${response.message}",
    timeInSecForIosWeb: 4);
}

void _handleExternalWallet(ExternalWalletResponse response) {
Fluttertoast.showToast(
    msg: "EXTERNAL_WALLET IS : ${response.walletName}",
    timeInSecForIosWeb: 4);
}

尝试的退款代码

void processRefund(String paymentId) async {
var url =
    Uri.parse('https://api.razorpay.com/v1/payments/$paymentId/refund');

try {
  var response = await http.post(
    url,
    headers: {
      'Authorization': 'Bearer My_Key',
      'Content-Type': 'application/json'
    },
  );

  if (response.statusCode == 200) {
    // Refund processed successfully
    print('Refund processed successfully');
  } else {
    // Refund failed
    print('Refund failed with status code: ${response.statusCode}');
    print('Response body: ${response.body}');
  }
} catch (e) {
  // Error occurred while making the refund request
  print('Error occurred during refund process: $e');
}
}

烦请告知如何正确实现退款功能?


正确实现退款的步骤和修正代码

1. 修正API授权方式

Razorpay退款API要求使用Basic Auth,而非Bearer Token。需将测试Key ID和Key Secret用冒号拼接后做Base64编码,格式为:
Basic <Base64编码后的KeyID:KeySecret>

比如Key ID是rzp_test_ABC123,Key Secret是xyz789,拼接成rzp_test_ABC123:xyz789后进行Base64编码,得到的结果就是Authorization头的有效值。

2. 补充必要请求参数(可选但推荐)

  • 若为部分退款,必须在请求体传入amount字段(单位为最小货币单位,和支付时一致,比如100000代表1000卢比)
  • 全额退款可不传,但建议明确传值避免歧义

3. 修正后的退款代码

import 'dart:convert';
import 'package:http/http.dart' as http;

void processRefund(String paymentId, {int? refundAmount}) async {
  var url = Uri.parse('https://api.razorpay.com/v1/payments/$paymentId/refund');
  
  // 替换为你的测试Key ID和Key Secret
  String keyId = "rzp_test_your_key_id";
  String keySecret = "your_key_secret";
  
  // 生成Basic Auth的Base64编码
  String basicAuth = 'Basic ' + base64Encode(utf8.encode('$keyId:$keySecret'));

  Map<String, dynamic> body = {};
  if (refundAmount != null) {
    body['amount'] = refundAmount; // 部分退款时传入金额
  }

  try {
    var response = await http.post(
      url,
      headers: {
        'Authorization': basicAuth,
        'Content-Type': 'application/json',
      },
      body: jsonEncode(body),
    );

    if (response.statusCode == 200 || response.statusCode == 201) {
      var responseData = jsonDecode(response.body);
      print('退款成功,退款ID: ${responseData['id']}');
      // 可在此处将退款ID保存到数据库,更新订单状态等
    } else {
      var errorData = jsonDecode(response.body);
      print('退款失败,状态码: ${response.statusCode}');
      print('错误信息: ${errorData['error']['description']}');
    }
  } catch (e) {
    print('退款请求出错: $e');
  }
}

测试模式注意事项

  • 测试环境退款即时生效,无需等待清算周期
  • 仅能对测试模式下生成的paymentId发起退款,生产与测试环境密钥不通用
  • 可使用Razorpay官方提供的测试卡片完成支付后,测试退款流程

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.07.18 00:55:25