此项目已开源 赶快来围观 Start支持下吧
包名下
】
此篇文章来详细介绍下支付宝APP支付
目录
1、支付宝与微信对比(申请、费率、结算周期)
2、支付宝上线应用
3、支付宝App支付Android集成流程详解
4、服务端实现(建议直接官方提供的服务端SDK)
5、客户端实现
6、常见错误解决方案(ALI40247、AL38173)
EnvUtils.setEnv(EnvUtils.EnvEnum.SANDBOX);
使用沙箱环境测试
1、支付宝与微信对比
费率:
结算周期:
2、支付宝上线应用
1、注册账号并实名认证
注册账号了没有实名认证进入开发平台的管理中心会提示如下图
实名认证
为什么要实名认证
商家认证流程
2、创建应用开通支付并上线
资源下载汇总
签名工具
注意签名工具目录不能包含中文
签名工具的使用
上传密钥
这里上传的是rsa_public_key.pemJava版签名使用的密钥是rsa_private_key_pkcs8.pem
3、支付宝App支付Android集成流程详解
1、导入支付宝SDK 其中SDK在图资源下载汇总的WS.APP_PAY_SDK_BASE_20.zip中
2、修改Manifest
在商户应用工程的AndroidManifest.xml文件里面添加声明:
android:name="com.alipay.sdk.app.H5PayActivity"
android:configChanges="orientation|keyboardHidden|navigation"
android:exported="false"
android:screenOrientation="behind" >
android:name="com.alipay.sdk.auth.AuthActivity"
android:configChanges="orientation|keyboardHidden|navigation"
android:exported="false"
android:screenOrientation="behind" >
3、权限声明
4、如需混洗、添加混淆规则
在商户应用工程的proguard-project.txt里添加以下相关规则:
alipaySDK-xxxxx.jar根据下载的做响应的修改
-libraryjars libs/alipaySDK-xxxxx.jar
-keep class com.alipay.android.app.IAlixPay{*;}
-keep class com.alipay.android.app.IAlixPay$Stub{*;}
-keep class com.alipay.android.app.IRemoteServiceCallback{*;}
-keep class com.alipay.android.app.IRemoteServiceCallback$Stub{*;}
-keep class com.alipay.sdk.app.PayTask{ public *;}
-keep class com.alipay.sdk.app.AuthTask{ public *;}
5、支付接口调用
获取PayTask支付对象调用支付(支付行为需要在独立的非ui线程中执行
)具体实现参考客户端实现,调用支付需要使用到orderInfo具体实现参考服务端实现。
6、支付结果获取和处理
调用pay方法支付后,将通过2种途径获得支付结果:
1、同步返回商户应用客户端通过当前调用支付的Activity的Handler对象,通过它的回调函数获取支付结果。
4、服务端实现
代码来自Demo 并做简单的封装
具体实现截图
设置支付宝业务参数
设置支付宝业务参数
注意:支付宝App支付不支持沙盒模式(此坑纠结了很长时间),使用沙盒模式会出现ALI40247错误,文末有错误的详细说明。
核心实现代码如下
/**
* App支付
*/
public void appPay(){
String orderInfo;
try {
String body="我是测试数据";
String passback_params="123";
String subject="1";
String total_amount="0.01";
String appId;
String rsa_private;
if (isDebug) {
appId=prop.get("test_appId").trim();
rsa_private=prop.get("test_rsa_private").trim();
System.out.println("test。。。。");
}else {
appId=prop.get("appId").trim();
rsa_private=prop.get("rsa_private").trim();
}
System.out.println("appId:"+appId);
System.out.println("rsa_private:"+rsa_private);
BizContent content = new BizContent();
content.setBody(body);
content.setOut_trade_no(OrderInfoUtil2_0.getOutTradeNo());;
content.setPassback_params(passback_params);
content.setSubject(subject);
content.setTotal_amount(total_amount);
content.setProduct_code("QUICK_MSECURITY_PAY");
Map params = OrderInfoUtil2_0.buildOrderParamMap(appId,notify_url,content);
String orderParam = OrderInfoUtil2_0.buildOrderParam(params);
String sign = OrderInfoUtil2_0.getSign(params, rsa_private);
orderInfo = orderParam + "&" + sign;
log.info("orderInfo>"+orderInfo);
result.success(orderInfo);
renderJson(result);
} catch (Exception e) {
e.printStackTrace();
result.addError("system error");
}
}
补充 使用支付服务端SDK实现获取预付订单
1、先获取到AlipayClient
alipayClient = new DefaultAlipayClient(serverUrl, appId, privateKey, format, charset, alipayPulicKey, signType);
2、使用AlipayTradeAppPayRequest封装请求
/**
* App支付
* @param model
* @param notifyUrl
* @return
* @throws AlipayApiException
*/
public static String startAppPayStr(AlipayTradeAppPayModel model, String notifyUrl) throws AlipayApiException{
AlipayTradeAppPayResponse response = appPay(model,notifyUrl);
return response.getBody();
}
/**
* App 支付
* @param model
* @param notifyUrl
* @return
* @throws AlipayApiException
*/
public static AlipayTradeAppPayResponse appPay(AlipayTradeAppPayModel model, String notifyUrl) throws AlipayApiException{
//实例化具体API对应的request类,类名称和接口名称对应,当前调用接口名称:alipay.trade.app.pay
AlipayTradeAppPayRequest request = new AlipayTradeAppPayRequest();
//SDK已经封装掉了公共参数,这里只需要传入业务参数。以下方法为sdk的model入参方式(model和biz_content同时存在的情况下取biz_content)。
request.setBizModel(model);
request.setNotifyUrl(notifyUrl);
//这里和普通的接口调用不同,使用的是sdkExecute
AlipayTradeAppPayResponse response = alipayClient.sdkExecute(request);
return response;
}
3、控制器封装数据给客户端
/**
* app支付
*/
public void appPay(){
try {
AlipayTradeAppPayModel model = new AlipayTradeAppPayModel();
model.setBody("我是测试数据");
model.setSubject("App支付测试-By Javen");
model.setOutTradeNo(StringUtils.getOutTradeNo());
model.setTimeoutExpress("30m");
model.setTotalAmount("0.01");
model.setPassbackParams("callback params");
model.setProductCode("QUICK_MSECURITY_PAY");
String orderInfo = AliPayApi.startAppPayStr(model,AliPayApi.notify_domain+"/alipay/app_pay_notify");
result.success(orderInfo);
renderJson(result);
} catch (AlipayApiException e) {
e.printStackTrace();
result.addError("system error");
}
}
服务端异步通知
/**
* App支付支付回调通知
* docType=1#s3
*/
public void app_pay_notify() {
try {
// 获取支付宝POST过来反馈信息
Map params = AliPayApi.toMap(getRequest());
for (Map.Entry entry : params.entrySet()) {
System.out.println(entry.getKey() + " = " + entry.getValue());
}
// boolean AlipaySignature.rsaCheckV1(Map params,
// String publicKey, String charset, String sign_type)
boolean flag = AlipaySignature.rsaCheckV1(params, AliPayApi.ALIPAY_PUBLIC_KEY, AliPayApi.CHARSET,
AliPayApi.SIGN_TYPE);
if (flag) {
// TODO
System.out.println("success");
renderText("success");
return;
} else {
// TODO
System.out.println("failure");
renderText("failure");
}
} catch (AlipayApiException e) {
e.printStackTrace();
renderText("failure");
}
}
将异步通知的参数转化为Map
/**
* 将异步通知的参数转化为Map
* @param request
* @return
*/
public static Map toMap(HttpServletRequest request) {
System.out.println(">>>>" + request.getQueryString());
Map params = new HashMap();
Map requestParams = request.getParameterMap();
for (Iterator iter = requestParams.keySet().iterator(); iter.hasNext();) {
String name = (String) iter.next();
String[] values = (String[]) requestParams.get(name);
String valueStr = "";
for (int i = 0; i < values.length; i++) {
valueStr = (i == values.length - 1) ? valueStr + values[i] : valueStr + values[i] + ",";
}
// 乱码解决,这段代码在出现乱码时使用。
// valueStr = new String(valueStr.getBytes("ISO-8859-1"), "utf-8");
params.put(name, valueStr);
}
return params;
}
5、客户端实现
成功将返回:
{
"code": 0,
"message": null
}
/**
* 获取支付宝App支付订单信息
* @return
*/
public String getAliPayOrderInfo(Order order){
String result=HttpKit.get(Constants.ALIPAY_URL);
return result;
}
异步获取orderInfo
public class AliPay extends AsyncTask {
private Activity mContext;
public AliPay(Activity context) {
this.mContext = context;
}
@Override
protected String doInBackground(Object... params) {
return IPayLogic.getIntance(mContext).getAliPayOrderInfo((Order)params[0]);
}
@Override
protected void onPostExecute(String result) {
try {
if (result!=null) {
System.out.println("AliPay result>"+result);
JSONObject data = new JSONObject(result);
String message = data.getString("message");
int code = data.getInt("code");
if(code == 0){
String orderInfo = data.getString("data");
Toast.makeText(mContext, "正在调起支付", Toast.LENGTH_SHORT).show();
IPayLogic.getIntance(mContext).startAliPay(orderInfo);
}else{
Log.d("PAY_GET", "返回错误"+message);
// Toast.makeText(mContext, "返回错误:"+message, Toast.LENGTH_SHORT).show();
}
}else {
System.out.println("get AliPay exception, is null");
}
} catch (Exception e) {
Log.e("PAY_GET", "异常:"+e.getMessage());
Toast.makeText(mContext, "异常:"+e.getMessage(), Toast.LENGTH_SHORT).show();
}
super.onPostExecute(result);
}
}
支付接口调用
public void startAliPay(final String orderInfo){
Runnable payRunnable = new Runnable() {
@Override
public void run() {
PayTask alipay = new PayTask(mContext);
Map result = alipay.payV2(orderInfo, true);
Message msg = new Message();
msg.obj = result;
mHandler.sendMessage(msg);
}
};
Thread payThread = new Thread(payRunnable);
payThread.start();
}
客户端通过回调函数获取支付结果
private Handler mHandler = new Handler(Looper.getMainLooper()) {
@SuppressWarnings("unchecked")
public void handleMessage(Message msg) {
PayResult payResult = new PayResult((Map) msg.obj);
System.out.println("alipay call "+payResult.toString());
String resultStatus = payResult.getResultStatus();
String memo = payResult.getMemo();
if (Constants.payListener !=null){
//返回状态以及详细的描述参考
Constants.payListener.onPay(-2,resultStatus,memo);
}
}
};
客户端具体使用方法
public void testAliPay(View view){
Toast.makeText(this, "支付宝测试", Toast.LENGTH_SHORT).show();
Order order = new Order();
order.setParaTradeNo(System.currentTimeMillis()+"");
order.setTotalFee(20);
order.setAttach("json");//附加参数
IPay.getIntance(MainActivity.this).toPay(IPay.PayMode.ALIPAY,order,new IPay.IPayListener() {
@Override
public void onPay(int wxcode, String alicode, String message) {
System.out.println("回调过来的状态》"+alicode+" message>"+((message!=null && message.isEmpty())?"":message));
Toast.makeText(MainActivity.this, "回调过来的状态》" + alicode, Toast.LENGTH_SHORT).show();
}
});
}
6、常见错误解决方案
APP支付报错ALI40247处理方案
ALI40247的错误
有2种情况 1、没有权限 2、签名失败
AL38173的错误一般是参数问题造成的,建议检查请求参数,对照文档查看,比如:参数少了、多了、乱码、名称不对,还有必传参数是否都请求提交给支付宝了等等.
此项目已开源 赶快来围观 Start支持下吧
作者:Javen205
來源:简书
著作权归作者所有。商业转载请联系作者获得授权,非商业转载请注明出处。