微信支付传送门:https://www.cnblogs.com/dingxiansen/p/9209159.html

一、支付宝支付

1. 支付宝支付流程图

2. 集成前准备

  1. 去蚂蚁金服注册应用获取appKey等信息
  2. 创建应用,添加APP支付功能
  3. 找到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" /> <!--Mob分享-->
<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" /> <!--支付宝支付权限-->
<!-- 安卓读写sd权限 -->
<uses-permission android:name="android.permission.READ_EXTERNAL_STORAGE" />

支付回调

<!--支付宝支付-->
<!-- 支付宝H5页面支付用的 -->
<activity
android:name="com.alipay.sdk.app.H5PayActivity"
android:configChanges="orientation|keyboardHidden|navigation"
android:exported="false"
android:screenOrientation="behind" />
<!-- 支付宝App支付页面用的 -->
<activity
android: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&notify_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&timestamp=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<String>() {
@RequiresApi(api = Build.VERSION_CODES.M)
@Override
public 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() {
@Override
public void onErrorResponse(VolleyError volleyError) { }
}) {
@Override
public Map<String, String> getParams() throws AuthFailureError {
Log.e("GoPayOrderActivity", "getParams:-----------------> " + userEntity.getPhone()); Map<String, String> map = new HashMap<String, String>();
map.put("account", userEntity.getPhone());
map.put(key, value);
map.put("token", userEntity.getToken());
return map;
} @Override
public Map<String, String> getHeaders() throws AuthFailureError {
HashMap<String, String> headers = new HashMap<String, String>();
if (userEntity.getToken().equals("") && userEntity != null) {
headers.put("Authorization", userEntity.getToken());
}
return headers;
} };
/*设置请求一次*/
stringRequest.setRetryPolicy(
new DefaultRetryPolicy(
5000,//默认超时时间,应设置一个稍微大点儿的,例如本处的500000
DefaultRetryPolicy.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<String, String>) 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<String, String> 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() { @Override
public void run() {
PayTask alipay = new PayTask(context);
Map<String, String> 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() { @Override
public void run() {
PayTask alipay = new PayTask(context);
Map<String, String> 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<String, String> buildOrderParamMap(boolean rsa2) {
Map<String, String> keyValues = new HashMap<String, String>(); 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<String, String> map) {
List<String> keys = new ArrayList<String>(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<String, String> map, String rsaKey, boolean rsa2) {
List<String> keys = new ArrayList<String>(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

    

Android开发支付集成——支付宝集成的更多相关文章

  1. Android开发支付集成——微信集成

    支付宝支付传送门:https://www.cnblogs.com/dingxiansen/p/9208949.html 二.微信支付 1. 微信支付流程图 相比较而言,微信支付是要比支付宝麻烦一些,并 ...

  2. android开发 ,对接支付宝,服务器(PHP)校验失败

    已备忘记,资料链接: http://my.oschina.net/u/256646/blog/174222 注意: 里面有一个设计到支付宝公钥的地方: 注 意这个是2048位的公钥应该是9行或者10行 ...

  3. android 集成支付宝app支付(原生态)-包括android前端与java后台

    本文讲解了 android开发的原生态app集成了支付宝支付, 还提供了java后台服务器处理支付宝支付的加密代码, app前端与java后台服务器使用json数据格式交互信息,java后台服务主要用 ...

  4. 五步搞定Android开发环境部署

    引言   在windows安装Android的开发环境不简单也说不上算复杂,本文写给第一次想在自己Windows上建立Android开发环境投入 Android浪潮的朋友们,为了确保大家能顺利完成开发 ...

  5. Android开发学习——搭建开发环境

    在学校开课学习了android的一些简单的UI组件,布局,四大组件学习了2个,数据存储及网络通信,都是一些简单的概念,入门而已.许多东西需要自己去学习. 学习一下 Android开发环境的搭建,两种方 ...

  6. android开发环境搭建日记和嵌入式Android开发环境初探

    非常感谢博客园的各位,按照你们的博文,还有利用百度和谷歌逐渐建立了android的开发环境,只是给自己备份参考查看,看过的人可以忽略这篇文章. 本文章大部分参考了:http://www.cnblogs ...

  7. Android开发环境部署

    引言   在windows系统中安装Android的开发环境,将分为五个步骤来完成: 第一步:安装JDK 第二步:配置Windows上JDK的变量环境 第三步: 下载安装Eclipse 第四步:下载安 ...

  8. 五步搞定Android开发环境部署——非常详细的Android开发环境搭建教程

      在windows安装Android的开发环境不简单也说不上算复杂,本文写给第一次想在自己Windows上建立Android开发环境投入Android浪潮的朋友们,为了确保大家能顺利完成开发环境的搭 ...

  9. 【Android开发】 第一课 环境搭建教程

    Windows 开发环境部署: Android Studio 中文社区:http://www.android-studio.org/ 本教程将分为五个步骤来完成Android开发环境的部署. 第一步: ...

随机推荐

  1. handler原理

    一.消息机制概述 1.消息机制的简介 (1)Handler是什么 handler使Android给我们提供的用来更新UI的一套机制,也是一套消息处理机制:我们可以用它发送处理消息. (2)Androi ...

  2. 关于ef+codefirst+mysql/dapper(dbFirse)(入门)

    ef+mssql详细是许多.net程序员的标配.作为一个程序员当然不能只会mssql这一个数据库,今天简单聊聊ef+mysql.推荐新人阅读. 1]首先创建一个mvc项目,如图: 创建完毕之后再nug ...

  3. fab 菜单实现—圆形、半圆、扇形、直线、射线

    前段时间记录一下fab 菜单实现之前传-钟表表盘,今天终于弄正文了. 本文基于上篇文章的布局方式和位置计算,并参考35 Cool Floating Action Button Animations(h ...

  4. Sharepoint模态窗体(实战)

    分享人:广州华软 无名 一. 前言 对SharePoint二次开发时,需要知道SharePoint有什么.没有什么,才能在开发过程中避免重复造轮子.SharePoint提供了许多开箱即用的功能,这次要 ...

  5. openlayers一:显示地图与鼠标地理坐标

    openlayers两个好用的开源JS互动地图库之一,另一个是leaflet. openlayers的特点是是大而全,自身包含绝大多数功能,文档好看. leaflet是小而美,自身小,但支持扩展,好用 ...

  6. 2. [mmc subsystem] mmc core数据结构和宏定义说明

    一.host相关 1.struct mmc_host struct mmc_host是mmc core由host controller抽象出来的结构体,用于代表一个mmc host控制器. 数据结构如 ...

  7. July 09th, 2018. Monday, Week 28th.

    Happiness is an inside job. 自内寻找,才能找到幸福. From William Arthur Ward. Nobody wants to suffer, and we al ...

  8. kafka监控项目大全

    https://github.com/claudemamo/kafka-web-console   http://github.com/pinterest/doctorkafka   http://g ...

  9. SpringCloud警告(Eureka):EMERGENCY! EUREKA MAY BE INCORRECTLY CLAIMING INSTANCES ARE UP WHEN THEY'RE NOT. RENEWALS ARE LESSER THAN THRESHOLD AND HENCE THE INSTANCES ARE NOT BEING EXPIRED JUST TO BE SAFE.

    警告!Eureka可能存在维护了错误的实例列表(当它们没有启动的时候,Eureka却把它当成启动的了):Renews值小于Threshold值,因此剩下未过期的都是安全的. 原因分析: 这个是Eure ...

  10. Java多线程系列(1)

    本章主要内容有: 1.线程进程的区别 2.线程的生命周期 3.Java内存模型 原子性,可见性及有序性 4.线程池及Java实现 1. 线程进程的区别 线程:程序运行的最小单位 进程:资源分配的最小单 ...