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

注意: 本文即涉及到 android前端, 也涉及到 Java后台

准备条件:

  1. 到支付宝官网上注册用户, 打开开放平台,支付宝默认生成沙箱环境,用来测试支付流程

  2. 安装Android Studio【下载】, 安装 Eclipse mars  【下载】,  JDK1.7    tomcat7

1. 支付流程概述

使用过app支付的用户都知道,在支付环节,如果选择【支付宝支付】,我们的app会拉起支付宝app,并且将支付信息传入到

支付宝app中显示出来, 用户确认付款完成付款操作, 有朋友就会问,那我们的应用逻辑应该放在哪个步骤呢?

步骤1: 应用程序拉起支付宝app前,会按照支付宝的规则传递相应的数据给支付宝,所以启动支付宝前,我们需要构建数据, 基本数据包括商品描述,商品价钱等,但为了让支付宝区别是哪个应用程序传过来的数据,还需要AppId(应用程序在支付宝平台上对应的序号); 另外为了保障数据不被篡改,我们传递的数据需要进行RSA加密

步骤2: 对数据的加密工作是放在后台进行的,那为什么不放在前台呢,熟悉RSA加密的朋友都知道,RSA是非对称加密,加密方与解密方 需要一对密钥(公钥和私钥), 这些公钥与私钥是敏感信息,放在android端容易被盗取,所以将公钥与私钥放在后台,后台对数据加密完成后再传给前台

步骤3: 前台将加密完成后的数据传送给支付宝,由支付宝完成支付

步骤4: 支付完成后app端会得到相应的事件通知,前台根据相应的事件来判断前台的业务走向

步骤5: 支付宝官方要求,使用支付宝完成支付后,支付宝后台 会调用 应用服务的后台用来告之交易支付是否真正成功

由于本地服务无法向外界提供服务, 所以支付宝回调本地测试的服务器接口无法连通,至于连通的方法,可以看一下

ngrok的配置,  这个工具可以穿透内网

2. Android端

项目运行后如下图

2.1 下载导入项目到android studio中,将build.gradle中的storeFile的路径设置正确

2.2 android端的通信使用 retrofit rxjava技术,所以访问后台的请求url需要配置正确, 如果使用本文提供的后台,则可以不必修改,如果使用别人的后台服务,需要进行更改

3.3 android端访问后台获取加密数据,然后将加密数据传递给支付宝

注意:由于使用的支付宝的沙箱配置信息  ,必须加上 代码 EnvUtils.setEnv(EnvUtils.EnvEnum.SANDBOX);

如果使用正式环境的支付宝配置信息, 不能加上上面沙箱代码

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
private void aliPay(){
    BizContent bizContent = new BizContent();
    bizContent.setOut_trade_no(outTradeNum);
    bizContent.setTotal_amount(totalPrice);
    bizContent.setSubject("某个项目" "-支付订单");
    String strBizContent = new Gson().toJson(bizContent);
  
  
    //generateOrderInfo去后台获取加密的信息
     payService
        .generateOrderInfo(strBizContent)
            .subscribe(new Action1<String>() {
                @Override
                public void call(String s) {
                    //orderInfo为加密的信息
                    final String orderInfo = s;
                    Runnable payRunnable = new Runnable() {
                        @Override
                        public void run() {
                            //沙箱环境开启沙箱功能
                            //正式环境不需要下面这行代码
                            EnvUtils.setEnv(EnvUtils.EnvEnum.SANDBOX);
                            PayTask alipay = new PayTask(MainActivity.this);
                            Map<String, String> result = alipay.payV2(orderInfo, true);
                            Log.i("msp", result.toString());
  
                            Message msg = new Message();
                            msg.what = SDK_PAY_FLAG;
                            msg.obj = result;
                            mHandler.sendMessage(msg);
                        }
                    };
  
                    Thread payThread = new Thread(payRunnable);
                    payThread.start();
                }
            }, new Action1<Throwable>() {
                @Override
                public void call(Throwable throwable) {
                    showToast(throwable.getMessage());
                }
            });
}

  

3.4 支付宝支付完成后执行 handleMessage

在handleMessage判断支付情况, 如果 payResult.getResultStatus() == "9000" 则支付成功, 否则失败

具体的失败信息可以查看支付宝的官方文档

@SuppressLint("HandlerLeak")
private Handler mHandler = new Handler() {
@SuppressWarnings("unused")
public void handleMessage(Message msg) {
switch (msg.what) {
case SDK_PAY_FLAG: {
@SuppressWarnings("unchecked")
PayResult payResult = new PayResult((Map<String, String>) msg.obj);
/**
对于支付结果,请商户依赖服务端的异步通知结果。同步通知结果,仅作为支付结束的通知。
*/
String resultInfo = payResult.getResult();// 同步返回需要验证的信息
String resultStatus = payResult.getResultStatus();
// 判断resultStatus 为9000则代表支付成功
if (TextUtils.equals(resultStatus, "9000")) {
outTradeNum = "";
showToast("支付成功");
} else {
outTradeNum = "";
// 该笔订单真实的支付结果,需要依赖服务端的异步通知。
Toast.makeText(MainActivity.this, "支付失败", Toast.LENGTH_SHORT).show();
}
break;
}
case SDK_AUTH_FLAG: {
@SuppressWarnings("unchecked")
AuthResult authResult = new AuthResult((Map<String, String>) msg.obj, true);
String resultStatus = authResult.getResultStatus(); // 判断resultStatus 为“9000”且result_code
// 为“200”则代表授权成功,具体状态码代表含义可参考授权接口文档
if (TextUtils.equals(resultStatus, "9000") && TextUtils.equals(authResult.getResultCode(), "200")) {
// 获取alipay_open_id,调支付时作为参数extern_token 的value
// 传入,则支付账户为该授权账户
Toast.makeText(MainActivity.this,
"授权成功\n" + String.format("authCode:%s", authResult.getAuthCode()), Toast.LENGTH_SHORT)
.show();
} else {
// 其他状态值则为授权失败
Toast.makeText(MainActivity.this,
"授权失败" + String.format("authCode:%s", authResult.getAuthCode()), Toast.LENGTH_SHORT).show(); }
break;
}
default:
break;
}
};
};

3. Java后台

3.1 修改支付宝配置信息, 实例中使用的是本人支付宝中申请的沙箱配置信息

请将Config.properties中的信息改成自己的

3.2 generateOrderInfo对android传递的支付信息进行加密, 加密信息回传给android端

@RequestMapping("/generateOrderInfo.htm")
@ResponseBody
public Result generateOrderInfo(String bizContent)
{
Result result = new Result();
AlipaySignature sing= new AlipaySignature();
if(StringUtils.isEmpty(bizContent)){
result.setData("");
result.setStateCode(Constant.RESULT_FAILURE);
result.setDesc("待加签字符串不能为空");
}else
{
String appId = ConfigManager.getInstance().getConfigItem("APPID");
Map<String, String> params = OrderInfoUtil2_0.buildOrderParamMap(appId, bizContent, true);
String orderParam = OrderInfoUtil2_0.buildOrderParam(params); String privateKey = ConfigManager.getInstance().getConfigItem("ProjectPrivateKey");
String sign = OrderInfoUtil2_0.getSign(params, privateKey, true);
final String orderInfo = orderParam + "&" + sign;
result.setDesc("加签成功");
result.setStateCode(Constant.RESULT_SUCCESS);
result.setData(orderInfo);
}
return result;
}

3.3 支付成功后,支付宝服务端回调后台应用程序接口,用来告之支付是否成功

/**
* 支付宝的回调接口
* @param request
*/
@RequestMapping("/notifyOrderInfo.htm")
public void notifyOrderInfo(HttpServletRequest request){ if ("TRADE_SUCCESS".equals(request.getParameter("trade_status"))) {
Enumeration<?> pNames = request.getParameterNames();
Map<String, String> param = new HashMap<String, String>();
try {
while (pNames.hasMoreElements()) {
String pName = (String) pNames.nextElement();
param.put(pName, request.getParameter(pName));
} boolean signVerified = AlipaySignature.rsaCheckV1(param, ConfigManager.getInstance().getConfigItem("AlipayPublicKey"),
AlipayConstants.CHARSET_UTF8); // 校验签名是否正确
if (signVerified) {
// TODO 验签成功后
// 按照支付结果异步通知中的描述,对支付结果中的业务内容进行1\2\3\4二次校验,校验成功后在response中返回success,校验失败返回failure
System.out.println("订单支付成功:" + JSON.toJSONString(param));
} else {
// TODO 验签失败则记录异常日志,并在response中返回failure.
}
} catch (Exception e) {
e.printStackTrace();
}
}
return;
}

关于支付宝的其它接口的更加详细信息,请参照 【服务端详解】

DEMO下载:http://www.wisdomdd.cn/Wisdom/resource/articleDetail.htm?resourceId=844

android 集成支付宝app支付(原生态)-包括android前端与java后台的更多相关文章

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

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

  2. Android版-支付宝APP支付

    此项目已开源 赶快来围观 Start支持下吧 [客户端开源地址-JPay][服务端端开源地址-在com.javen.alipay 包名下] 上一篇详细介绍了微信APP支付 点击这里 此篇文章来详细介绍 ...

  3. 微信、支付宝App支付-JPay0.0.2发布

    JPay 对微信App支付.支付宝App支付的二次封装,对外提供一个相对简单的接口以及支付结果的回调 GitHub:https://github.com/Javen205/JPay OsChina:h ...

  4. Android版-微信APP支付

    首发地址: Android版-微信APP支付 欢迎留言.转发 微信极速开发系列文章(微信支付.授权获取用户信息等):点击这里 目录 1.注册账号.开发者认证 2.添加应用 3.申请微信支付 4.技术开 ...

  5. 支付宝 app支付 沙盘使用

    文档说明 沙箱测试: App支付沙箱接入注意点 1.app支付支持沙箱接入:在沙箱调通接口后,必须在线上进行测试与验收,所有返回码及业务逻辑以线上为准:2.app支付只支持余额支付,不支持银行卡.余额 ...

  6. 支付宝APP支付开发- IOException : DER input, Integer tag error

    支付宝APP支付Java开发报错: 1 java.security.spec.InvalidKeySpecException: java.security.InvalidKeyException: I ...

  7. 支付宝APP支付开发- IOException : DerInputStream.getLength(): lengthTag=127, too big.

    支付宝APP支付Java开发报错: IOException : DerInputStream.getLength(): lengthTag=127, too big. 后来排查是因为没有设置私钥.

  8. 支付宝APP支付之Java后台生成签名具体步骤

    /** *支付宝支付 * @param orderId 订单编号 * @param actualPay 实际支付金额 * @return */ private String getOrderInfoB ...

  9. H5使用codovar插件实现支付宝支付(支付宝APP支付模式,前端)

    H5打包的app实现支付及支付宝支付,本章主要详解支付宝支付,微信支付请查看另一篇“H5使用codovar插件实现微信支付(微信APP支付模式,前端)” ps:本文只试用H5开发的,支付宝 APP支付 ...

随机推荐

  1. UESTC--1252--24点游戏(dfs)

     24点游戏 Time Limit: 1000MS   Memory Limit: 65535KB   64bit IO Format: %lld & %llu Submit Status ...

  2. 支撑百亿级应用的 NewSQL

    支撑百亿级应用的 NewSQL https://zhuanlan.zhihu.com/newsql/ 项目背景 初次接触 TiDB,是通过同程网首席架构师王晓波先生的分享,当时同程网正在使开发和数据库 ...

  3. Spark之MLlib

    目录 Part VI. Advanced Analytics and Machine Learning Advanced Analytics and Machine Learning Overview ...

  4. springboot启动报错:Cannot determine embedded database driver class for database type NONE.

    package cn.zb.test; import org.springframework.boot.SpringApplication; import org.springframework.bo ...

  5. 【IDEA】(4)---很好用的DEBUG功能

    IDEA-DEBUG功能 一.常用快捷键 快捷键并不是完全一样的,我这边是MAC安装的IDEA, 这边最主要还是知道DEBUG时常用的功能. 1.快捷键 F7 #进入下一步,如果当前行是一个方法,则进 ...

  6. html body中的标签

    HTML中的标签有两类 一.字体标签 字体标签包含:h1~h6.<font>.<u>.<b>.<strong><em>.<sup> ...

  7. A - Voting(queue)

    Problem description There are n employees in Alternative Cake Manufacturing (ACM). They are now voti ...

  8. Oracle 生成数据字典

    SELECT ROWNUM 序号,A.COLUMN_NAME AS "字段名称",B.comments AS "字段描述", A.DATA_TYPE as 字段 ...

  9. SQLServer2008 关于while循环

    有这样一个表tbl id  code name 11   a      aa/bb/cc 22   b      ee/rr/tt 需要将name段根据‘/’拆分开来,变成新的数据行 即: id  c ...

  10. [PHP][学习笔记][CURL]监测设备运行情况小demo

    1.curl获取的web content 不能直接echo到页面,会造成js各种错误 2.想办法处理字符串的截取.拼接 2.1.裁剪html返回的字符串 function cutStringFrom( ...