安卓 App 接入支付宝二维码付款需要申请什么权限?
明确结论
这种场景通常需要开通支付宝的 当面付 产品,并调用 扫码支付(预下单) 接口 alipay.trade.precreate 生成二维码。
已经开通的 App 支付、手机网站支付(H5) 和 电脑网站支付(PC) 是不同的支付产品,无法直接提供当面付的付款二维码能力。
不同的 VIP 套餐不用分别申请权限。每次购买时,服务端创建一笔独立订单,设置对应的金额、标题和业务参数,即可生成相应的付款二维码。
为什么需要当面付
这几种支付方式适用于不同场景:
App 支付:唤起用户手机中的支付宝 App 完成付款。手机网站支付:在手机浏览器或 WebView 中进入支付宝收银台。电脑网站支付:主要用于 PC 网页收银台。当面付-扫码支付:商户服务端创建订单,支付宝返回二维码内容,再由商户展示给用户扫码付款。
如果需要由服务端生成订单,再由客户端展示付款二维码,应使用当面付的预下单接口,不能从 App 支付接口中获取二维码。
能否开通当面付,取决于商户主体、签约地区、经营类目以及支付宝当前的产品准入规则。产品名称和入口可能随开放平台调整,请以商户后台实际可签约的产品为准。
接入步骤
1. 开通当面付
登录支付宝开放平台或商家平台,在对应的应用和商户主体下检查是否可以签约 当面付。
签约后还要确认以下配置:
- 应用已绑定正确的商户账号。
- 应用具有
alipay.trade.precreate接口权限。 - 应用公钥或支付宝公钥配置正确。
- 应用的签名方式、网关环境和应用 ID 配置一致。
创建开放平台应用不代表已经签约相应的支付产品。
2. 由服务端创建订单
Android 客户端不能保存应用私钥,也不应直接调用预下单接口。完整流程如下:
- Android App 将 VIP 套餐编号提交给业务服务端。
- 服务端根据套餐编号查询真实价格。
- 服务端生成唯一的商户订单号。
- 服务端调用
alipay.trade.precreate。 - 支付宝返回
qr_code。 - 服务端将二维码内容返回给 Android App。
- Android App 将该内容编码成二维码并展示。
- 服务端通过异步通知或主动查询确认付款结果。
套餐价格必须由服务端确定,不能直接采用客户端上传的金额。
Java 服务端示例
下面是使用支付宝 Java SDK 创建预下单的简化示例。不同版本的 SDK 可能采用不同的构造方式,请以当前支付宝开放平台文档为准。
import com.alipay.api.AlipayApiException;
import com.alipay.api.AlipayClient;
import com.alipay.api.DefaultAlipayClient;
import com.alipay.api.domain.AlipayTradePrecreateModel;
import com.alipay.api.request.AlipayTradePrecreateRequest;
import com.alipay.api.response.AlipayTradePrecreateResponse;
public class AlipayQrService {
private final AlipayClient alipayClient;
public AlipayQrService(
String appId,
String merchantPrivateKey,
String alipayPublicKey) {
this.alipayClient = new DefaultAlipayClient(
"https://openapi.alipay.com/gateway.do",
appId,
merchantPrivateKey,
"json",
"UTF-8",
alipayPublicKey,
"RSA2"
);
}
public String createQrCode(
String outTradeNo,
String totalAmount,
String subject,
String notifyUrl) throws AlipayApiException {
AlipayTradePrecreateModel model = new AlipayTradePrecreateModel();
model.setOutTradeNo(outTradeNo);
model.setTotalAmount(totalAmount);
model.setSubject(subject);
model.setTimeoutExpress("15m");
AlipayTradePrecreateRequest request =
new AlipayTradePrecreateRequest();
request.setBizModel(model);
request.setNotifyUrl(notifyUrl);
AlipayTradePrecreateResponse response =
alipayClient.execute(request);
if (!response.isSuccess()) {
throw new IllegalStateException(
"支付宝预下单失败: code=" + response.getCode()
+ ", msg=" + response.getMsg()
+ ", subCode=" + response.getSubCode()
+ ", subMsg=" + response.getSubMsg()
);
}
return response.getQrCode();
}
}
response.getQrCode() 返回的是二维码内容,不一定是图片地址。Android 客户端需要使用二维码库将这个字符串生成二维码图片。
不同的 VIP 套餐只需传入不同的订单信息,例如:
String qrCode = alipayQrService.createQrCode(
"VIP_ORDER_202609090001",
"99.00",
"年度 VIP",
"https://example.com/payment/alipay/notify"
);
Android 展示二维码示例
以下代码以 ZXing 为例:
import android.graphics.Bitmap;
import com.google.zxing.BarcodeFormat;
import com.google.zxing.MultiFormatWriter;
import com.google.zxing.common.BitMatrix;
public Bitmap createQrBitmap(String content, int size) throws Exception {
BitMatrix matrix = new MultiFormatWriter().encode(
content,
BarcodeFormat.QR_CODE,
size,
size
);
Bitmap bitmap = Bitmap.createBitmap(
size,
size,
Bitmap.Config.ARGB_8888
);
for (int x = 0; x < size; x++) {
for (int y = 0; y < size; y++) {
bitmap.setPixel(
x,
y,
matrix.get(x, y) ? 0xFF000000 : 0xFFFFFFFF
);
}
}
return bitmap;
}
客户端从业务服务端取得 qrCode 后,将其显示到 ImageView:
Bitmap bitmap = createQrBitmap(qrCode, 800);
imageView.setImageBitmap(bitmap);
支付结果不能以客户端页面为准
二维码展示后,不能因为用户关闭页面、跳转回来或点击”我已付款”,就在客户端直接发放 VIP。
服务端需要完成以下处理:
- 接收支付宝异步通知。
- 验证通知签名。
- 校验
app_id、out_trade_no、金额和收款商户信息。 - 确认交易状态符合业务要求。
- 必要时调用
alipay.trade.query主动查询。 - 使用幂等逻辑发放 VIP,避免重复通知引起重复处理。
向支付宝的异步通知返回成功前,必须完成验签和订单校验。
同一部手机展示二维码的限制
如果二维码显示在用户当前使用的手机上,而这部手机没有安装支付宝,用户就无法直接在同一部手机上使用支付宝扫码。通常只有以下几种处理方式:
- 使用另一台安装了支付宝的设备扫码。
- 截图后在支付宝中识别图片,但仍然需要安装支付宝。
- 改用手机网站支付或其他能在浏览器中完成的支付方式。
因此,“未安装支付宝时显示二维码”不代表用户能在同一设备上完成支付宝付款。二维码更适合显示在 PC 页面、收银台屏幕或另一台设备上。
如果业务要求用户仅用一部没有安装支付宝的手机完成付款,应优先评估手机网站支付,而不是当面付二维码。
注意事项
- 不要为不同的 VIP 套餐制作长期固定且写死金额的收款码。
- 每次付款都要创建新的商户订单号和二维码。
- 订单金额使用字符串传递,例如
"99.00",并由服务端校验。 - 为二维码设置合理的订单有效期,过期后重新创建订单。
- 应用私钥只能保存在服务端,不能打包进 APK。
- 正式环境与沙箱环境的网关、应用 ID 和密钥不能混用。
- 开通当面付后仍无法调用接口时,检查签约状态、应用授权关系以及接口返回的
sub_code和sub_msg。这些字段通常会说明具体原因。
备注:内容仅供参考。
