移动支付

移动支付

用户使用移动的设备,完成对所购买商品或者服务的支付功能.远程支付(网上支付,短信支付),近场支付(刷卡,滴卡,pos机)

app集成支付功能/支付功能

常见的支付厂商

  • 支付宝:阿里公司,支付宝使用比较多.
  • 微信:腾讯公司,也是越来越多.
  • 易付宝:
  • 财付通:腾讯公司
  • 银联:不属于某一个公司
  • 百付宝:百度

  • 支付宝钱包:阿里的.

  • 百度钱包:百度
  • 快钱:

  • ping++:整合了很多的支付平台

支付难不难?

不难,都是属于第三方的东西.难度不大

支付安不安全?

肯定是安全的.因为这些都是大公司的产品.都有自己的安全策略;

做一个支付需要多久?

程序员实际集成时间
* 项目评估(非第一次)
* 支付宝:大概15分钟.
* 银联支付:大概15分钟.
* 微信支付:大概30分钟.

支付流程_从生活出发

  1. 选择商品
  2. 选择支付方式
  3. 处理支付结果
    1. 成功
    2. 失败
    3. 取消

支付流程_从app开发角度(保证可以先完成功能)

  1. 拼接支付信息,post到自己服务器;–>request
    1. 支付信息包含支付方式
    2. 服务器:是我们自己的服务器
    3. 支付协议:http://mobileif.***.com/version3/orderform/order?version=2
  2. 服务器返回支付串码/付款信息;—>reponse

    请求的url(支付协议/确认订单协议):  http://mobileif.**.com/version3/orderform/order?version=2
    请求方式:post
    post参数形式:jsonString
    输入参数:{"goodInfos":[{"goodCounts":"1","goodExtInfo":{},"goodIDs":"361","goodType":"1"}],"loginFlag":"0","mobile":"18682036558","orderId":"0","otherInfo":{"agentID":"0-maizuo","channelID":"31","clientID":"31"},"payDatas":{"discountInfo":{"activeID":"0","discountID":"0","discountPrice":""},"payInfo":[{"bankType":"7","payCount":"3200","payTicketCount":"1","payType":"1"}],"payPass":"","returnUrl":"","totalPrice":"3200"},"processPath":"1","sessionKey":"mqneaadqapkpkqshxvdj","userID":"200394160"}
    输出结果{"result":"ok","payExtInfo":{"alipayVerifyKey":"_input_charset=\"UTF-8\"&body=\"卖座网电子影票\"&it_b_pay=\"1h\"&notify_url=\"http%3A%2F%2Fpay.maizuo.com%2FmobileBack.htm\"&out_trade_no=\"201507238712113008\"&partner=\"2088411628331920\"&payment_type=\"1\"&seller_id=\"2088411628331920\"&service=\"mobile.securitypay.pay\"&subject=\"金逸影城沙井店(2D通兑票1张)\"&total_fee=\"32.00\"&sign=\"M0O0Ej5J13A25SAWupc5a6vAGmJnblx2CvuWF2dwFGxMZ%2BxlRWmp%2F6ZDfI8Y%2FFJbjiEqE99MAsKh%0AfIBQqP4Y1TyNkbY0XixQFPgAAqsqwGqYJSDtqUFWRgje%2B8pI1KuxfPE3UcDZs4hxDZoP%2Bdof%2Bldf%0AKQmximUyqT5Crtwj1Ag%3D\"&sign_type=\"RSA\""},"bankType":"","userId":"200394160","resource":{"rel":"view","link":"/orderform/200394160/201507238712113008"},"payType":"7","payUrl":"","orderId":"201507238712113008","uniqueKey":"D5585vO8624915A11z","timeNow":"1437622208552"}
    
  3. 拿着支付串码,调用第三方服务,完成支付(集成支付宝)

  4. 处理支付结果
    1. 同步返回:支付后通知我们自己的apk
    2. 异步通知:支付后通知我们的server

什么是支付串码/付款信息

这个是自己定义的一个概念.其实就是第三步调用起第三方支付平台核心支付方法所需要的参数

集成支付宝流程

  1. 我们自己要和支付宝签约(商户签约).–>运营
  2. 秘钥配置–>协助运营完成秘钥的配置(公钥互换),可能程序员会参与
  3. 集成支付宝–>必须是程序员去做.

    1. 下载sdk/demo/文档
    2. demo尝试的去运行
      1. 出现了错误:因为缺少运行必须的,DEFAULT_PARTNER,DEFAULT_SELLER,如果1,2步完成的话,我们在这个时候就可以有DEFAULT_PARTNER,DEFAULT_SELLER
    3. 开始集成–>参照移动快捷支付应用集成接入包支付接口接入与使用规则.pdf

      1. 添加jar,alipay.jar
      2. 添加lib,alipay_lib
      3. 添加了一个activity
      4. 添加了一些权限
      5. 调用支付的核心代码

        //  3.调用第三方服务,完成支付
        //获取Alipay对象,构造参数为当前Activity和Handler实例对象
        AliPay alipay = new AliPay(MainActivity.this, mHandler);
        //调用pay方法,将订单信息传入
        //同步返回    取消操作  支付成功  支付失败(网络异常)
        String payResult = alipay.pay(alipayVerifyKey);
        
      6. 处理支付结果—>支付宝处理支付结果用的handler机制

        /**---------------demo里面处理支付结果的代码---------------**/
        
        /*Result result = new Result((String) msg.obj);
        switch (msg.what) {
        case RQF_PAY:
        case RQF_LOGIN: {
            Toast.makeText(ExternalPartner.this, result.getResult(), Toast.LENGTH_SHORT).show();
        
        }
            break;
        default:
            break;
        }
        */
        /**---------------实际开发处理支付结果的代码---------------**/
        
        /*Result.sResult = (String) msg.obj;
        Logger.i(TAG, "strRet:" + Result.sResult);
        try {
            String errorMsg = Result.getPayResult();
            Logger.i(TAG, "errorMsg:" + errorMsg);
            if (!"".equals(errorMsg)) {
                Toast.makeText(getApplicationContext(), errorMsg, 0).show();
                if ("操作成功".equals(errorMsg)) {
                    payOk();//支付成功可以调到订单界面
                } else {
                    payFail();//可以弹出对话框进行重复支付
                }
            }
        } catch (Exception e) {
            e.printStackTrace();
            if (!PayActivity.this.isFinishing()) {
                BaseHelper.showDialog(PayActivity.this, "提示", Result.sResult + ",如有疑问请联系卖座客服:4001808400", R.drawable.infoicon);
            }
        }
        

        }
        };*/

支付宝demo分析

  • 查看demo发现他的支付串码,是在客户端生成的.支付串码由服务器生成.有出入;
  • 为了不暴露我们privatekey,我们应该把生成支付串码的过程交给我们的服务器

    /**---------------生成支付串码的过程  begin---------------**/
    Log.i("ExternalPartner", "onItemClick");
    String info = getNewOrderInfo(position);
    //其实下面的操作应该是server端去完成.不然我们会暴露privatekey---begin---add_by_billy
    //所有我们会把info的具体内容用jsonString的形式.post给server进行签名.然后返回签名后的结果---add_by_billy
    String sign = Rsa.sign(info, Keys.PRIVATE);
    sign = URLEncoder.encode(sign);
    info += "&sign=\"" + sign + "\"&" + getSignType();
    Log.i("ExternalPartner", "start pay");
    // start the pay.
    Log.i(TAG, "info = " + info);
    //其实下面的操作应该是server端去完成.不然我们会暴露privatekey---end---add_by_billy
    final String orderInfo = info;
    /**---------------生成支付串码的过程  end---------------**/
    

支付串码_自己定义的一个概念

支付串码就是调用第三方应用的时候需要的一些核心的参数

银联支付

  • 银联支付,就只需要一个交易流水号就可以,而且看代码比较简单,重点是,银联强制要求生产支付串码的过程必须交给我们的服务端
  • 集成形式
    • 内嵌apk形式:就是把一个apk放到我们的assets目录下面–>老的方式
    • 新版本so库形式:在libs下面就有很多的so库.已经不需要在assets目录下面放置apk
  • 模式:
    • 测试模式:银联会给我们提供一个测试环境+提供了一个银联的账号/密码
    • 正式模式:就必须使用真实的账号/密码
  • 运行demo看效果:
  • 集成步骤:

    • 1.添加libs里面相关的东西;
    • 2.添加activity配置

      <activity
      android:name="com.unionpay.uppay.PayActivityEx"
      android:configChanges="orientation|keyboardHidden|screenSize"
      android:excludeFromRecents="true"
      android:label="@string/app_name"
      android:screenOrientation="portrait"
      android:windowSoftInputMode="adjustResize" />
      <activity
          android:name="com.unionpay.uppay.PayActivity"
          android:configChanges="orientation|keyboardHidden|screenSize"
          android:excludeFromRecents="true"
          android:screenOrientation="portrait" />
      
    • 3.添加权限

      <!-- uupay -->
      <uses-permission android:name="android.permission.CHANGE_NETWORK_STATE" />
      <uses-permission android:name="android.permission.WRITE_EXTERNAL_STORAGE" />
      <uses-permission android:name="android.permission.READ_PHONE_STATE" />
      
    • 4.调用核心的支付方法

      //拿着支付串码
      System.out.println("alipayVerifyKey:" + alipayVerifyKey);
      //  3.调用第三方服务,完成支付
      // “00” – 银联正式环境
      // “01” – 银联测试环境,该环境中不发生真实交易
      //tn 交易流水号  
      UPPayAssistEx.startPayByJAR(MainActivity.this, PayActivity.class, null, null,
              alipayVerifyKey, "00");
      
    • 5.处理支付结果

      /**---------------银联处理支付结果---------------**/
      protected void onActivityResult(int requestCode, int resultCode, Intent data) {
      /*************************************************
       * 
       * 步骤4:处理银联手机支付控件返回的支付结果
       * 
       ************************************************/
      if (data == null) {
          return;
      }
      
      String msg = "";
      /*
       * 支付控件返回字符串:success、fail、cancel 分别代表支付成功,支付失败,支付取消
       */
      String str = data.getExtras().getString("pay_result");
      if (str.equalsIgnoreCase("success")) {
          msg = "支付成功!";
      } else if (str.equalsIgnoreCase("fail")) {
          msg = "支付失败!";
      } else if (str.equalsIgnoreCase("cancel")) {
          msg = "用户取消了支付";
      }
      
      AlertDialog.Builder builder = new AlertDialog.Builder(this);
      builder.setTitle("支付结果通知");
      builder.setMessage(msg);
      builder.setInverseBackgroundForced(true);
      // builder.setCustomTitle();
      builder.setNegativeButton("确定", new DialogInterface.OnClickListener() {
          @Override
          public void onClick(DialogInterface dialog, int which) {
              dialog.dismiss();
          }
      });
      builder.create().show();
      }
      

微信支付

  • 直接运行demo,发现最后提示错误,发现工程下面有一个debug.keystore
  • 想要运行.可以如下操作

    • 自定义keystore
    • 或者直接导出的时候用工程下面的debug.keystore去签名
  • 微信支付的安全策略之一:必须包名和keystore签名需要一致

  • demo里面定义的步骤

    • 一、获取 access_token
    • 二、生成预支付订单,需要用到第一步的access_token,得到的是prepayId
    • 三、调起微信支付
    • 四、处理支付结果
    • 这个时候一看.感觉微信支付很难.但是我们看到demo里面这样的一句话注意:不能hardcode在客户端,建议genPackage这个过程由服务器端完成,所以,其实我们的微信支付,一、二步骤为了安全起见应该交给Server
  • 实际开发,只需关心3,4步就可以

    • 三、调起微信支付

      /**
       * @author Administrator
       * 支付的时候真正关心的数据
       * 这个对象是我自己封装的.和微信支付的sdk没有关系
       */
      public class WXPayData {
      private String sign_method;
      private String timestamp;
      private String noncestr;
      private String partnerid;
      private String app_signature;
      private String prepayid;
      private String package1;
      private String appid;
      }
      
      //核心支付方法
      private void sendPayReq(WXPayData info) {
      api = WXAPIFactory.createWXAPI(this, info.getAppid());
      PayReq req = new PayReq();
      req.appId = info.getAppid();
      req.partnerId = info.getPartnerid();
      req.prepayId = info.getPrepayid();//预支付id
      req.nonceStr = info.getNoncestr();//32位内的随机串,防重发
      req.timeStamp = String.valueOf(info.getTimestamp());//时间戳,为 1970 年 1 月 1 日 00:00 到请求发起时间的秒数
      req.packageValue = info.getPackage1();
      req.sign = info.getApp_signature();
      // 在支付之前,如果应用没有注册到微信,应该先调用IWXMsg.registerApp将应用注册到微信
      api.sendReq(req);
      

      }

    • 四、处理支付结果:微信支付支付的回调是在net.sourceforge.simcpux.wxapi.WXPayEntryActivity.class里面

      @Override
      public void onResp(BaseResp resp) {
      Log.d(TAG, "onPayFinish, errCode = " + resp.errCode);
      
      if (resp.getType() == ConstantsAPI.COMMAND_PAY_BY_WX) {
          AlertDialog.Builder builder = new AlertDialog.Builder(this);
          builder.setTitle(R.string.app_tip);
          builder.setMessage(getString(R.string.pay_result_callback_msg, String.valueOf(resp.errCode)));
          builder.show();
      }
      }
      

安全码策略

安全码的组成规则为:Android签名证书的sha1值+“;”+packagename(即:数字签名+分号+包名)

  • 作用:确定apk的唯一性

你可能感兴趣的:(APP,移动支付)