Android Studio集成Razorpay支付成功后插入数据库报错
Razorpay支付回调中写入数据库失败修复
问题场景
在Android Studio集成Razorpay支付SDK时,需要在支付成功后将订单业务数据写入数据库。在onPaymentSuccess回调中调用自定义save()方法执行入库逻辑时抛出错误,无法完成数据写入,原有问题代码如下:
//@Override public void onPaymentSuccess(String s, PaymentData paymentData) { paymentData.getData(); razorpay_payment_id= paymentData.getPaymentId(); save(paymentData); } public void save(PaymentData paymentData) { userid=user_id; property_type = ptype1.getText().toString().trim(); from_date = txtchkin.getText().toString().trim(); to_date = txtchkout.getText().toString().trim(); no_of_adults = no_of_adult.getText().toString().trim(); no_of_childrens = no_of_children.getText().toString().trim(); price=amount.getText().toString().trim(); razorpay_payment_id=paymentData.getPaymentId(); razorpay_order_id=paymentData.getOrderId(); payment_status="success"; status="Active"; isAllFieldsChecked = validate(); if (isAllFieldsChecked) { StringRequest stringRequest = new StringRequest(Request.Method.POST, url, new Response.Listener<String>() { @Override public void onResponse(String response) { Toast.makeText(getApplicationContext(), "Data Inserted Successfully", Toast.LENGTH_LONG).show(); } }, new Response.ErrorListener() { @Override public void onErrorResponse(VolleyError error) { Toast.makeText(getApplicationContext(), error.toString().trim(), Toast.LENGTH_LONG).show(); } }) } }
报错核心原因
- Razorpay的
onPaymentSuccess回调默认运行在子工作线程,直接在该线程内调用getText()访问UI控件、弹Toast,会触发Android的非主线程禁止操作UI的崩溃 - 现有Volley请求代码不完整:既没有重写
getParams()方法传递POST入库参数,也没有将构建好的请求加入Volley请求队列,请求根本不会实际发送 - 直接在长时间运行的网络请求逻辑里持有Activity控件引用,支付过程中如果页面旋转、Activity销毁,会触发空指针异常
修复代码
- 回调触发后先切到主线程,提前取出所有需要的表单值,避免子线程访问UI
- 补全Volley请求的参数传递、入队逻辑
- 避免在网络请求层直接持有控件引用
@Override public void onPaymentSuccess(String s, PaymentData paymentData) { // 先在子线程取支付相关的非UI数据 final String payId = paymentData.getPaymentId(); final String orderId = paymentData.getOrderId(); // 切主线程取UI表单值、做校验 runOnUiThread(() -> { String propertyType = ptype1.getText().toString().trim(); String fromDate = txtchkin.getText().toString().trim(); String toDate = txtchkout.getText().toString().trim(); String adultCount = no_of_adult.getText().toString().trim(); String childCount = no_of_children.getText().toString().trim(); String payAmount = amount.getText().toString().trim(); if (validate()) { submitOrderToServer(payId, orderId, propertyType, fromDate, toDate, adultCount, childCount, payAmount); } }); } private void submitOrderToServer(String razorpayPayId, String razorpayOrderId, String propertyType, String fromDate, String toDate, String adultCount, String childCount, String price) { StringRequest stringRequest = new StringRequest(Request.Method.POST, url, response -> Toast.makeText(YourActivity.this, "订单入库成功", Toast.LENGTH_LONG).show(), error -> { String errTip = error.getMessage() == null ? "订单入库失败,请稍后重试" : error.getMessage(); Toast.makeText(YourActivity.this, errTip, Toast.LENGTH_LONG).show(); }) { @Override protected Map<String, String> getParams() { Map<String, String> orderParams = new HashMap<>(); orderParams.put("userid", String.valueOf(user_id)); orderParams.put("property_type", propertyType); orderParams.put("from_date", fromDate); orderParams.put("to_date", toDate); orderParams.put("no_of_adults", adultCount); orderParams.put("no_of_childrens", childCount); orderParams.put("price", price); orderParams.put("razorpay_payment_id", razorpayPayId); orderParams.put("razorpay_order_id", razorpayOrderId); orderParams.put("payment_status", "success"); orderParams.put("status", "Active"); return orderParams; } }; // 必须将请求加入队列,否则请求不会发送 Volley.newRequestQueue(this).add(stringRequest); }
额外优化建议
- 发起支付前就把用户填写的表单数据暂存到ViewModel或者本地变量中,不要等到支付成功回调里再去控件取值,避免支付过程中页面销毁导致空指针
- 支付成功后建议先在本地做支付状态标记,再上传服务器,避免网络波动导致用户付了钱但订单没记录的问题
- 服务器端必须做支付签名校验,不要完全信任客户端传的支付成功状态,避免伪造请求
内容的提问来源于stack exchange,提问作者user18468640
相关产品推荐
相关产品推荐

