Android开发支付集成——支付宝集成
微信支付传送门:https://www.cnblogs.com/dingxiansen/p/9209159.html
一、支付宝支付
1. 支付宝支付流程图
2. 集成前准备
- 去蚂蚁金服注册应用获取appKey等信息
- 创建应用,添加APP支付功能
- 找到APP支付开发文档,下载 SDK&Demo
3. 开始集成
1、导入Demo中需要用到的Jar包

2、配置AndroidManifest.xml(这里直接放常用的权限)
<uses-permission android:name="android.permission.ACCESS_COARSE_LOCATION" /><uses-permission android:name="android.permission.ACCESS_FINE_LOCATION" /><uses-permission android:name="android.permission.ACCESS_WIFI_STATE" /><uses-permission android:name="android.permission.CHANGE_WIFI_STATE" /><uses-permission android:name="android.permission.READ_PHONE_STATE" /><uses-permission android:name="android.permission.INTERNET" /><uses-permission android:name="android.permission.READ_LOGS" /><uses-permission android:name="android.permission.VIBRATE" /><uses-permission android:name="android.permission.WAKE_LOCK" /><uses-permission android:name="android.permission.WRITE_SETTINGS" /><uses-permission android:name="android.permission.ACCESS_NETWORK_STATE" /><uses-permission android:name="android.permission.WRITE_EXTERNAL_STORAGE" /><uses-permission android:name="android.permission.MOUNT_UNMOUNT_FILESYSTEMS" /><uses-permission android:name="android.permission.GET_TASKS" /><uses-permission android:name="android.permission.RECEIVE_SMS" /><uses-permission android:name="android.permission.READ_SMS" /><uses-permission android:name="android.permission.MODIFY_AUDIO_SETTINGS" /><uses-permission android:name="android.permission.READ_EXTERNAL_STORAGE" />
支付回调
<activityandroid:name="com.alipay.sdk.app.H5PayActivity"android:configChanges="orientation|keyboardHidden|navigation"android:exported="false"android:screenOrientation="behind" /><activityandroid:name="com.alipay.sdk.auth.AuthActivity"android:configChanges="orientation|keyboardHidden|navigation"android:exported="false"android:screenOrientation="behind" />
3、请求后台接口拿到签过名的信息(appKey,订单信息等等),这里我获取数据,是直接给后台传递的商品id,如果有的需要商品数量直接给传给后台,后台根据id查询出商品的信息,然后返回给前台所需要的支付参数。
支付宝返回参数用例(开始集成的时候看过好多博客都没有返回参数数据结构,结果一脸懵逼,在这里贴出,未加密之前的0.0):

格式化后的:
{"msg":"success","code":200,"data":"alipay_sdk=alipay-sdk-java-dynamicVersionNo&app_id=你们申请的app_id&biz_content=%7B%22out_trade_no%22%3A%22HY201806210002%22%2C%22product_code%22%3A%22QUICK_MSECURITY_PAY%22%2C%22subject%22%3A%22%E4%BC%98%E9%93%BA%E4%BC%9A%E5%91%98%E6%9C%8D%E5%8A%A1%E8%B4%B9%22%2C%22total_amount%22%3A%220.01%22%7D&charset=UTF-8&format=json&method=alipay.trade.app.pay¬ify_url=http%3A%2F%2F你们的回调地址%2FaliPayCallBack%2FcallBack&sign=buipaoj2F8xl5XCAUVoJz%2Fbh8dHbaoRmdzoAEzqKRJqtZATT4bfFdzSHurAAL5C5gvntFrDTGHgNRGw%2BNZBtG4DfetOzcpHMAyjslrmUIMIr1YGC7Qya04mFBCh%2B0UIa1E7RISZWSbIVCHpZISknNgF2oTuTixNosXvDXzkGYGBUoaxdh1f6%2F%2Bw9lqKz7mkhsUc0x8lCeJHw4MnTS4gSLU%2BDmOCk6Tkiwb4Yv4Mz%2F6j7XReeagfX7qxs5qbObnnPX%2FFmu9T%2BF0LwJaPxr5Xys8kr8E4bhd4f7Y5FimXiw%2BG7EFkY0I69boiRob7zo%2BbWQ%2F53TAMeTXX5RJybEdXhrA%3D%3D&sign_type=RSA2×tamp=2018-06-21+14%3A11%3A40&version=1.0","status":"0" }
后台返回信息之后接下来就是我们的事情了,调起支付宝进行支付
/*支付宝测试*/private void testZfbPay(final String key, final String value) {StringRequest stringRequest = new StringRequest(Request.Method.POST, NetWorkUrl.ZFBPAY, new Response.Listener() {@RequiresApi(api = Build.VERSION_CODES.M)@Overridepublic void onResponse(String s) {Log.e("GoPayOrderActivity", "-------getJson2-------" + s.toString());/*判断code*/String code = (JSONObject.parseObject(s.toString()).getString("code"));if (code.equals("200")) {String orderInfo = (JSONObject.parseObject(s.toString()).getString("data"));//返回的信息MyALipayUtils.ALiPayBuilder builder = new MyALipayUtils.ALiPayBuilder();builder.build().toALiPay(GoPayOrderActivity.this, orderInfo);}}}, new Response.ErrorListener() {@Overridepublic void onErrorResponse(VolleyError volleyError) {}}) {@Overridepublic Map getParams() throws AuthFailureError {Log.e("GoPayOrderActivity", "getParams:-----------------> " + userEntity.getPhone());Map map = new HashMap ();map.put("account", userEntity.getPhone());map.put(key, value);map.put("token", userEntity.getToken());return map;}@Overridepublic Map getHeaders() throws AuthFailureError {HashMap headers = new HashMap ();if (userEntity.getToken().equals("") && userEntity != null) {headers.put("Authorization", userEntity.getToken());}return headers;}};/*设置请求一次*/stringRequest.setRetryPolicy(new DefaultRetryPolicy(5000,//默认超时时间,应设置一个稍微大点儿的,例如本处的500000DefaultRetryPolicy.DEFAULT_MAX_RETRIES,//默认最大尝试次数 DefaultRetryPolicy.DEFAULT_BACKOFF_MULT));AppApplication.getHttpQueues().add(stringRequest);/*请求数据*/}
MyALipayUtils.java这个类直接copy使用就可以
/*** Created by dingchao on 2018/3/20.*/public class MyALipayUtils {private static final int SDK_PAY_FLAG = 1;private Activity context;private ALiPayBuilder builder;private MyALipayUtils(ALiPayBuilder builder) {this.builder = builder;}private Handler mHandler = new Handler() {public void handleMessage(Message msg) {// 返回码 含义 // 9000 订单支付成功 // 8000 正在处理中,支付结果未知(有可能已经支付成功),请查询商户订单列表中订单的支付状态 // 4000 订单支付失败 // 5000 重复请求 // 6001 用户中途取消 // 6002 网络连接出错 // 6004 支付结果未知(有可能已经支付成功),请查询商户订单列表中订单的支付状态 // 其它 其它支付错误PayResult payResult = new PayResult((Map) msg.obj);switch (payResult.getResultStatus()) {case "9000":MobclickAgent.onEvent(context, "payment_success", "付款成功");Toast.makeText(context, "支付成功", Toast.LENGTH_SHORT).show();AppApplication.finishActivity();context.finish(); // Toast.makeText(this, "支付成功", Toast.LENGTH_SHORT).show();/*跳转我的会员页面*/ // Intent intent = new Intent(context, MyVipActivity.class); // context.startActivity(intent);break;case "8000":Toast.makeText(context, "正在处理中", Toast.LENGTH_SHORT).show();break;case "4000":MobclickAgent.onEvent(context, "payment_fali", "付款失败");Toast.makeText(context, "订单支付失败", Toast.LENGTH_SHORT).show();break;case "5000":Toast.makeText(context, "重复请求", Toast.LENGTH_SHORT).show();break;case "6001":Toast.makeText(context, "已取消支付", Toast.LENGTH_SHORT).show();break;case "6002":Toast.makeText(context, "网络连接出错", Toast.LENGTH_SHORT).show();break;case "6004":Toast.makeText(context, "正在处理中", Toast.LENGTH_SHORT).show();break;default:MobclickAgent.onEvent(context, "payment_fali", "付款失败");Toast.makeText(context, "支付失败", Toast.LENGTH_SHORT).show();break;}}};/*** 签名发在客户端来做。** @param context*/public void toALiPay(final Activity context) {this.context = context;boolean rsa2 = (builder.getRsa2().length() > 0);Map params = buildOrderParamMap(rsa2);String orderParam = buildOrderParam(params);String privateKey = rsa2 ? builder.getRsa2() : builder.getRsa();String sign = getSign(params, privateKey, rsa2);final String orderInfo = orderParam + "&" + sign;Log.e("chx", "toALiPay: " + orderInfo);Runnable payRunnable = new Runnable() {@Overridepublic void run() {PayTask alipay = new PayTask(context);Map result = alipay.payV2(orderInfo, true);Message msg = new Message();msg.what = SDK_PAY_FLAG;msg.obj = result;mHandler.sendMessage(msg);}};Thread payThread = new Thread(payRunnable);payThread.start();}/*** 签名在服务端来做** @param context* @param orderInfo*/public void toALiPay(final Activity context, final String orderInfo) {this.context = context;Runnable payRunnable = new Runnable() {@Overridepublic void run() {PayTask alipay = new PayTask(context);Map result = alipay.payV2(orderInfo, true);Message msg = new Message();msg.what = SDK_PAY_FLAG;msg.obj = result;mHandler.sendMessage(msg);}};Thread payThread = new Thread(payRunnable);payThread.start();}/*** 构造支付订单参数列表** @param* @param* @return*/private Map buildOrderParamMap(boolean rsa2) {Map keyValues = new HashMap ();keyValues.put("app_id", builder.appid);keyValues.put("biz_content", "{\"timeout_express\":\"30m\",\"product_code\":\"QUICK_MSECURITY_PAY\",\"total_amount\":\"" + builder.money + "\",\"subject\":\"" + builder.title + "\",\"out_trade_no\":\"" + builder.orderTradeId + "\"}");keyValues.put("charset", "utf-8");keyValues.put("method", "alipay.trade.app.pay");//回调接口keyValues.put("notify_url", builder.getNotifyUrl());keyValues.put("sign_type", rsa2 ? "RSA2" : "RSA");// keyValues.put("timestamp", "2016-07-29 16:55:53");keyValues.put("timestamp", getCurrentTimeString());keyValues.put("version", "1.0");return keyValues;}/*** 构造支付订单参数信息** @param map 支付订单参数* @return*/private String buildOrderParam(Map map) {List keys = new ArrayList (map.keySet());StringBuilder sb = new StringBuilder();for (int i = 0; i < keys.size() - 1; i++) {String key = keys.get(i);String value = map.get(key);sb.append(buildKeyValue(key, value, true));sb.append("&");Log.e("chx", "buildOrderParam: " + buildKeyValue(key, value, true));}String tailKey = keys.get(keys.size() - 1);String tailValue = map.get(tailKey);sb.append(buildKeyValue(tailKey, tailValue, true));return sb.toString();}/*** 对支付参数信息进行签名** @param map 待签名授权信息* @return*/private String getSign(Map map, String rsaKey, boolean rsa2) {List keys = new ArrayList (map.keySet());// key排序 Collections.sort(keys);StringBuilder authInfo = new StringBuilder();for (int i = 0; i < keys.size() - 1; i++) {String key = keys.get(i);String value = map.get(key);authInfo.append(buildKeyValue(key, value, false));authInfo.append("&");}String tailKey = keys.get(keys.size() - 1);String tailValue = map.get(tailKey);authInfo.append(buildKeyValue(tailKey, tailValue, false));String oriSign = sign(authInfo.toString(), rsaKey, rsa2);String encodedSign = "";try {encodedSign = URLEncoder.encode(oriSign, "UTF-8");} catch (UnsupportedEncodingException e) {e.printStackTrace();}return "sign=" + encodedSign;}private static final String ALGORITHM = "RSA";private static final String SIGN_ALGORITHMS = "SHA1WithRSA";private static final String SIGN_SHA256RSA_ALGORITHMS = "SHA256WithRSA";private static final String DEFAULT_CHARSET = "UTF-8";private String getAlgorithms(boolean rsa2) {return rsa2 ? SIGN_SHA256RSA_ALGORITHMS : SIGN_ALGORITHMS;}private String sign(String content, String privateKey, boolean rsa2) {try {PKCS8EncodedKeySpec priPKCS8 = new PKCS8EncodedKeySpec(Base64.decode(privateKey));KeyFactory keyf = KeyFactory.getInstance(ALGORITHM);PrivateKey priKey = keyf.generatePrivate(priPKCS8);java.security.Signature signature = java.security.Signature.getInstance(getAlgorithms(rsa2));signature.initSign(priKey);signature.update(content.getBytes(DEFAULT_CHARSET));byte[] signed = signature.sign();return Base64.encode(signed);} catch (Exception e) {e.printStackTrace();}return null;}/*** 拼接键值对** @param key* @param value* @param isEncode* @return*/private String buildKeyValue(String key, String value, boolean isEncode) {StringBuilder sb = new StringBuilder();sb.append(key);sb.append("=");if (isEncode) {try {sb.append(URLEncoder.encode(value, "UTF-8"));} catch (UnsupportedEncodingException e) {sb.append(value);}} else {sb.append(value);}return sb.toString();}/*** 获取当前日期字符串** @return*/private String getCurrentTimeString() {SimpleDateFormat df = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss");return df.format(new Date());}public static class ALiPayBuilder {private String rsa2 = "";private String rsa = "";private String appid;private String money;private String title;private String notifyUrl;private String orderTradeId;public MyALipayUtils build() {return new MyALipayUtils(this);}public String getOrderTradeId() {return orderTradeId;}public ALiPayBuilder setOrderTradeId(String orderTradeId) {this.orderTradeId = orderTradeId;return this;}public String getRsa2() {return rsa2;}public ALiPayBuilder setRsa2(String rsa2) {this.rsa2 = rsa2;return this;}public String getRsa() {return rsa;}public ALiPayBuilder setRsa(String rsa) {this.rsa = rsa;return this;}public String getAppid() {return appid;}public ALiPayBuilder setAppid(String appid) {this.appid = appid;return this;}public String getMoney() {return money;}public ALiPayBuilder setMoney(String money) {this.money = money;return this;}public String getTitle() {return title;}public ALiPayBuilder setTitle(String title) {this.title = title;return this;}public String getNotifyUrl() {return notifyUrl;}public ALiPayBuilder setNotifyUrl(String notifyUrl) {this.notifyUrl = notifyUrl;return this;}} }
完成上述操作,你的app在蚂蚁金服后台应用上线之后,就完全可以调用支付了,但是在开发阶段,应用没有上线,你是不能进行调试的,所以支付宝有沙箱模式可以进行调试,ios没有哟
进行沙箱调试在Activity的的onCreate()方法中添加
EnvUtils.setEnv(EnvUtils.EnvEnum.SANDBOX);//支付宝沙箱环境,正式需注释
别忘了让你们后台把appKey等信息换成沙箱的,然后测试支付的时候,需要下载一个沙箱支付宝,这个你可以随意支付,附上链接
沙箱首页:https://sandbox.alipaydev.com/user/accountDetails.htm?currentBar=1
App支付接入文档:https://docs.open.alipay.com/204/105051
沙箱钱包下载:

调试都没有问题之后,就可以在蚂蚁金服开发者平台进行应用上线,然后沙箱代码就可以注释了,这样支付宝支付就接入完成
如果问题或建议请发送到我的邮箱:dingchao7323@qq.com
转载于:https://www.cnblogs.com/dingxiansen/p/9208949.html
本文来自互联网用户投稿,文章观点仅代表作者本人,不代表本站立场,不承担相关法律责任。如若转载,请注明出处。 如若内容造成侵权/违法违规/事实不符,请点击【内容举报】进行投诉反馈!
