Android版-支付宝APP支付
2017-01-04 20:57
417 查看
此项目已开源欢迎Start、PR、发起Issues一起讨论交流共同进步
【客户端开源地址-JPay】
https://github.com/Javen205/IJPay
http://git.oschina.net/javen205/IJPay
上一篇详细介绍了微信APP支付 点击这里
此篇文章来详细介绍下支付宝APP支付
目录
1、支付宝与微信对比(申请、费率、结算周期)
2、支付宝上线应用
3、支付宝App支付Android集成流程详解
4、服务端实现(建议直接官方提供的服务端SDK)
5、客户端实现
6、常见错误解决方案(ALI40247、AL38173)
补充(20170513) 支付宝APP支付可以使用沙箱环境测试。如需开启测试模式只需要在
费率:
【微信签约汇率参考质料】【支付宝签约汇率参考质料】
结算周期:
微信结算周期: 话费通讯、财经资讯、股票软件类、网络虚拟服务以及互联网相关行业 T+7 众筹 T+3 其他T+1,结算款项自动提现到商户的结算账户,一般从结算日起3个工作日到账(具体到账时间视不同银行到账情况而定)
支付宝结算周期:及时到支付宝账号
注册账号了没有实名认证进入开发平台的管理中心会提示如下图
【账户认证-商家认证流程介绍】
2、创建应用开通支付并上线
官方文档有详细的介绍-创建应用、配置应用、上线应用
【资源下载:App支付DEMO&SDK、生成与配置密钥】
注意签名工具目录不能包含中文
这里上传的是
1、导入支付宝SDK 其中SDK在图
2、修改Manifest
在商户应用工程的AndroidManifest.xml文件里面添加声明:
3、权限声明
4、如需混洗、添加混淆规则
在商户应用工程的proguard-project.txt里添加以下相关规则:
5、支付接口调用
获取PayTask支付对象调用支付(支付行为需要在独立的非ui线程中执行
)
6、支付结果获取和处理
调用pay方法支付后,将通过2种途径获得支付结果:
1、
2、
设置支付宝业务参数
注意: 支付宝App支付不支持沙盒模式(此坑纠结了很长时间),使用沙盒模式会出现ALI40247 错误,文末有错误的详细说明。
核心实现代码如下
具体实现参考【开源项目】
补充 使用支付服务端SDK实现获取预付订单
1、先获取到
2、使用
3、控制器封装数据给客户端
服务端异步通知
将异步通知的参数转化为Map
成功将返回:
异步获取orderInfo
支付接口调用
客户端通过回调函数获取支付结果
客户端具体使用方法
ALI40247的错误
有2种情况 1、没有权限 2、签名失败
可以查看论坛提供的这个解决方案
AL38173的错误一般是参数问题造成的,建议检查请求参数,对照文档查看,比如:参数少了、多了、乱码、名称不对,还有必传参数是否都请求提交给支付宝了等等.
如果在网上查阅质料还未解决,可以寻求阿里的在线支持【支持中心】
此项目已开源 赶快来围观 Start支持下吧
【客户端开源地址-JPay】【服务端端开源地址-在
推荐阅读
Android版-微信APP支付
极速开发微信公众号之微信买单
极速开发微信公众号之公众号支付
极速开发微信公众号之扫码支付
极速开发微信公众号之刷卡支付
极速开发微信公众号之现金红包
记录学习的点滴,以此勉励不断奋斗的自己✌️✌️✌️ 如果对你有帮助记得点喜欢告诉我哈
【客户端开源地址-JPay】
https://github.com/Javen205/IJPay
http://git.oschina.net/javen205/IJPay
上一篇详细介绍了微信APP支付 点击这里
此篇文章来详细介绍下支付宝APP支付
目录
1、支付宝与微信对比(申请、费率、结算周期)
2、支付宝上线应用
3、支付宝App支付Android集成流程详解
4、服务端实现(建议直接官方提供的服务端SDK)
5、客户端实现
6、常见错误解决方案(ALI40247、AL38173)
补充(20170513) 支付宝APP支付可以使用沙箱环境测试。如需开启测试模式只需要在
OnCreate中添加如下代码。沙箱环境测试APP支付中请使用沙箱版钱包测试:点击开发者中心-沙箱环境-沙箱工具
EnvUtils.setEnv(EnvUtils.EnvEnum.SANDBOX);
1、支付宝与微信对比
申请:【微信开发平台】注册的邮箱不能与腾讯其他产品同号,需要开发者资质认证(需要¥300,而且支付商户与公众号不公用)而支付宝只需要企业实名认证,其他质料类似(营业执照、组织机构代码(现在都三证合一了))。费率:
【微信签约汇率参考质料】【支付宝签约汇率参考质料】
结算周期:
微信结算周期: 话费通讯、财经资讯、股票软件类、网络虚拟服务以及互联网相关行业 T+7 众筹 T+3 其他T+1,结算款项自动提现到商户的结算账户,一般从结算日起3个工作日到账(具体到账时间视不同银行到账情况而定)
支付宝结算周期:及时到支付宝账号
2、支付宝上线应用
1、注册账号并实名认证注册账号了没有实名认证进入开发平台的管理中心会提示如下图
【账户认证-商家认证流程介绍】
2、创建应用开通支付并上线
官方文档有详细的介绍-创建应用、配置应用、上线应用
【资源下载:App支付DEMO&SDK、生成与配置密钥】
注意签名工具目录不能包含中文
这里上传的是
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文件里面添加声明:
<activity android:name="com.alipay.sdk.app.H5PayActivity" android:configChanges="orientation|keyboardHidden|navigation" android:exported="false" android:screenOrientation="behind" > </activity> <activity android:name="com.alipay.sdk.auth.AuthActivity" android:configChanges="orientation|keyboardHidden|navigation" android:exported="false" android:screenOrientation="behind" > </activity>
3、权限声明
<uses-permission android:name="android.permission.INTERNET" /> <uses-permission android:name="android.permission.ACCESS_NETWORK_STATE" /> <uses-permission android:name="android.permission.ACCESS_WIFI_STATE" /> <uses-permission android:name="android.permission.READ_PHONE_STATE" /> <uses-permission android:name="android.permission.WRITE_EXTERNAL_STORAGE" />
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对象,通过它的回调函数获取支付结果。
2、
异步通知商户需要提供一个http协议的接口,包含在请求支付的入参中,其key对应notify_url。支付宝服务器在支付完成后,会以POST方式调用notify_url传输数据。
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 notify_url="http://javen.ittun.com/alipay/pay_notify"; 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<String, String> 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 支付 * https://doc.open.alipay.com/docs/doc.htm?treeId=54&articleId=106370&docType=1 * @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支付支付回调通知 * https://doc.open.alipay.com/docs/doc.htm?treeId=54&articleId=106370& * docType=1#s3 */ public void app_pay_notify() { try { // 获取支付宝POST过来反馈信息 Map<String, String> params = AliPayApi.toMap(getRequest()); for (Map.Entry<String, String> entry : params.entrySet()) { System.out.println(entry.getKey() + " = " + entry.getValue()); } // 切记alipaypublickey是支付宝的公钥,请去open.alipay.com对应应用下查看。 // boolean AlipaySignature.rsaCheckV1(Map<String, String> 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<String, String> toMap(HttpServletRequest request) { System.out.println(">>>>" + request.getQueryString()); Map<String, String> params = new HashMap<String, String>(); Map<String, String[]> requestParams = request.getParameterMap(); for (Iterator<String> 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、客户端实现
客户端请求此action返回orderInfo,默认的访问地址为http://[域名或者IP]:端口号/[项目名称]/alipay/appPay
成功将返回:
{ "code": 0, "data": "charset=utf-8&biz_content=%7B%22out_trade_no%22%3A%22120822453414812%22%2C%22total_amount%22%3A%220.01%22%2C%22subject%22%3A%221%22%2C%22body%22%3A%22%E6%88%91%E6%98%AF%E6%B5%8B%E8%AF%95%E6%95%B0%E6%8D%AE%22%2C%22product_code%22%3A%22QUICK_MSECURITY_PAY%22%2C%22passback_params%22%3A%22123%22%7D&method=alipay.trade.app.pay&format=json¬ify_url=http%3A%2F%2Fjaven.ittun.com%2Falipay%2Fpay_notify&app_id=2016102000727659&sign_type=RSA&version=1.0×tamp=2016-12-08+22%3A45%3A34&sign=m6fpNI58jkOIHROtm8Q2V1Ei7bxXc14JHtJEeqGM0B8dWlq3d%2FfAqpoQTZgeBb%2FVK%2B%2BydOJzVvSWc89dBxhYUq72KOeUwHiKlRJBFMnEMAZbJlRxqu9%2BRX2q7HSRmA6WRg75O68HZhkIhtO3bSNx3s710tMHmQCN230JoVWiwHw%3D", "message": null }
/** * 获取支付宝App支付订单信息 * @return */ public String getAliPayOrderInfo(Order order){ String result=HttpKit.get(Constants.ALIPAY_URL); return result; }
异步获取orderInfo
public class AliPay extends AsyncTask<Object, Integer, String> { 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<String, String> 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<String, String>) msg.obj); System.out.println("alipay call "+payResult.toString()); String resultStatus = payResult.getResultStatus(); String memo = payResult.getMemo(); if (Constants.payListener !=null){ //返回状态以及详细的描述参考 // https://doc.open.alipay.com/doc2/detail.htm?spm=a219a.7629140.0.0.xN1NnL&treeId=204&articleId=105302&docType=1 Constants.payListener.onPay(-2,resultStatus,memo); } } };
客户端具体使用方法
public void testAliPay(View view){ Toast.makeText(this, "支付宝测试", Toast.LENGTH_SHORT).show(); Order order = new Order(); order.setBody("会员充值中心"); order.setParaTradeNo(System.currentTimeMillis()+""); order.setTotalFee(20); order.setAttach("json");//附加参数 order.setNofityUrl("http://www.xxxx.com");//支付成功服务端回调通知的地址 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支持下吧
【客户端开源地址-JPay】【服务端端开源地址-在
com.javen.alipay包名下】
推荐阅读
Android版-微信APP支付
极速开发微信公众号之微信买单
极速开发微信公众号之公众号支付
极速开发微信公众号之扫码支付
极速开发微信公众号之刷卡支付
极速开发微信公众号之现金红包
记录学习的点滴,以此勉励不断奋斗的自己✌️✌️✌️ 如果对你有帮助记得点喜欢告诉我哈
相关文章推荐
- Android App支付系列(二):支付宝SDK接入详细指南(附官方支付demo)
- Android平台,支付宝和微信app支付总结
- Android:微信和支付宝的APP支付接入
- android 支付宝APP支付异常错误码 -- ALI40247
- android通过webview调起支付宝app支付
- android通过webview调起支付宝app支付
- Android WebView 微信和支付宝H5调用本地app支付
- 支付宝APP支付Android与IONIC与服务端,服务端类库从android端考取
- Android App支付:支付宝SDK接入详细指南(附官方支付demo)
- Android第三方支付——支付宝APP支付
- Android版-支付宝APP支付
- android通过webview调起支付宝app支付
- android app 集成 支付宝支付 微信支付
- Android App支付系列(二):支付宝SDK接入详细指南(附官方支付demo)
- Android app支付-支付宝
- Android App支付系列(二):支付宝SDK接入详细指南(附官方支付demo)
- 超详细的Android APP 集成 PayPal 境外支付 信用卡 借记卡 支付,支付宝 微信海外 境外支付
- android 集成支付宝app支付(原生态)-包括android前端与java后台
- Android - 使用自定义webview调用支付宝app支付
- Android App支付系列(二):支付宝SDK接入详细指南(附官方支付demo)