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

如何实现Razorpay API仅在支付成功时执行指定代码

问题根因

你当前的逻辑错误来自两点:

  1. Razorpay的checkout.open()是异步调用,拉起支付页后不会阻塞等待支付结果,会立刻执行后续代码,所以你写在RazorPayAPI()调用后的跳转逻辑会在支付页刚弹出时就执行
  2. 你在RazorPayAPI()方法内刚调用完open()就把flag设为true,此时支付流程才刚启动,完全没有拿到支付结果,这个标记逻辑完全无效
修复方案

核心原则:所有依赖支付成功结果的业务逻辑,必须全部放到Razorpay SDK提供的onPaymentSuccess回调中执行,不要写在拉起支付的调用链路后面

具体修改点:

  • 删除按钮点击回调中,RazorPayAPI(amount)调用之后的所有座位拼接、Intent跳转、flag判断代码,点击按钮时只做参数校验、金额计算、拉起支付页三个动作
  • 移除无用的flag变量,支付结果完全由SDK的两个回调方法分发,不需要自行维护状态标记
  • 在onPaymentSuccess回调中完成座位拼接、参数传值、跳转Ticket页面、finish当前页的逻辑,建议同时把回调返回的支付ID一并传到出票页留存
  • 在onPaymentError回调中仅做支付失败/取消的用户提示,不执行任何页面跳转、业务状态修改操作
  • 修正RazorPayAPI()方法:删除方法内flag=true的错误赋值,仅在JSON参数构造异常时弹出初始化失败提示即可

修正后的核心代码如下:

buttonDone.setOnClickListener(new View.OnClickListener() {
    @Override
    public void onClick(View view) {
        if (SeatAL.size()==24) {
            Toast.makeText(Book_Bus.this, "Select a minimum of 1 seat to pay", Toast.LENGTH_SHORT).show();
        } else{
            Toast.makeText(Book_Bus.this, "Redirecting...", Toast.LENGTH_SHORT).show();
            int amount=count*Integer.valueOf(price)*100;
            count=0;
            // 仅执行拉起支付动作,后续逻辑全部移到支付成功回调
            RazorPayAPI(amount);
        }
    }

    private void RazorPayAPI(int amount) {
        Checkout checkout=new Checkout();
        checkout.setKeyID("<keyID>");
        JSONObject object=new JSONObject();
        try {
            object.put("name","<name>");
            object.put("Description","Bus Ticket");
            object.put("theme.color",bg_yellow);
            object.put("currency","INR");
            object.put("amount",amount);
            object.put("prefill.contact","<phone>");
            object.put("prefill.email","<email>");
            checkout.open(Book_Bus.this,object);
        } catch (JSONException e) {
            e.printStackTrace();
            Toast.makeText(Book_Bus.this, "Payment initialization failed, please try again", Toast.LENGTH_SHORT).show();
        }
    }
});

@Override
public void onPaymentSuccess(String paymentId) {
    // 仅支付成功会进入该方法,在此执行所有后续业务逻辑
    Toast.makeText(this, "Payment Successful", Toast.LENGTH_SHORT).show();
    
    // 拼接选中座位信息
    String FinalSeats="";
    for(int i=0;i<SeatsAL.size();i++){
        FinalSeats+=SeatsAL.get(i);
        if(i!=SeatsAL.size()-1){
            FinalSeats+=",";
        }
    }

    // 跳转出票页
    Intent intent = new Intent(Book_Bus.this, Ticket.class);
    intent.putExtra("BusID", busRVModel.getBusID());
    intent.putExtra("Source", busRVModel.getSrc());
    intent.putExtra("Destination", busRVModel.getDest());
    intent.putExtra("Timings", busRVModel.getTimings());
    intent.putExtra("Seats", FinalSeats);
    intent.putExtra("PaymentID", paymentId); // 建议同步传递支付ID留存
    startActivity(intent);
    finish();
}

@Override
public void onPaymentError(int errorCode, String errorMsg) {
    // 支付取消、失败都会进入该方法,仅做提示不跳转
    Toast.makeText(getApplicationContext(), "Payment failed or cancelled, please try again", Toast.LENGTH_SHORT).show();
}
可选优化
  • 点击完成按钮后可暂时将按钮置为不可点击,避免用户重复点击拉起多个支付页,在onPaymentError回调中再恢复按钮可点击状态
  • 座位选中状态、计数等业务数据的重置操作,建议放到onPaymentSuccess中执行,避免用户支付取消/失败后返回页面需要重新选座
  • 可以在onPaymentSuccess中先把订单信息、支付ID提交到自有服务端存证,拿到服务端确认后再跳转到出票页,避免客户端回调伪造导致的订单异常

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.08.28 01:54:23