zoukankan      html  css  js  c++  java
  • android 集成支付宝app支付(原生态)-包括android前端与java后台

    本文讲解了 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,
                                "授权成功
    " + 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 验签成功后
                        // 按照支付结果异步通知中的描述,对支付结果中的业务内容进行1234二次校验,校验成功后在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

  • 相关阅读:
    Python基础学习九 数据库备份
    Python基础学习八 写日志
    Python 小练习三 发邮件
    Python基础补充(二) 多核CPU上python多线程并行的一个假象【转】
    pat 1118 Birds in Forest (25分) 并查集
    Java Map实现按value从大到小排序
    java实现排列组合(通俗易懂)
    java实现24点游戏代码
    eclipse搭建struts2环境及所遇到的问题
    java非常好用的读取文件的流的代码
  • 原文地址:https://www.cnblogs.com/itrena/p/8305832.html
Copyright © 2011-2022 走看看