美文网首页
Android 支付宝支付

Android 支付宝支付

作者: 易瑞 | 来源:发表于2017-08-13 18:29 被阅读0次

    之前写了一个关于微信支付的博文,后来有人问我为什么不写上一个支付宝支付的呢。当初想的是支付宝支付比较简单,不像微信支付里面有很多坑,支付宝支付只是处理好异步回调就可以了,不过既然问到了,那我也写出来支付宝支付,同样还是比较简单,将东西都抽出来,方便调用。

    首先是OrderInfoUtil2_0这个基础类。后面调用的很多方法都抽出来了集成在这个类里面,就当这个是一个工具类吧。

    publicclassOrderInfoUtil2_0 {

    /**

    * 构造授权参数列表

    *

    * @param pid

    * @param app_id

    * @param target_id

    * @return

    */

    publicstaticMap buildAuthInfoMap(String pid, String app_id, String target_id) {

    Map keyValues =newHashMap();

    // 商户签约拿到的app_id,如:2013081700024223

    keyValues.put("app_id", app_id);

    // 商户签约拿到的pid,如:2088102123816631

    keyValues.put("pid", pid);

    // 服务接口名称, 固定值

    keyValues.put("apiname","com.alipay.account.auth");

    // 商户类型标识, 固定值

    keyValues.put("app_name","mc");

    // 业务类型, 固定值

    keyValues.put("biz_type","openservice");

    // 产品码, 固定值

    keyValues.put("product_id","APP_FAST_LOGIN");

    // 授权范围, 固定值

    keyValues.put("scope","kuaijie");

    // 商户唯一标识,如:kkkkk091125

    keyValues.put("target_id", target_id);

    // 授权类型, 固定值

    keyValues.put("auth_type","AUTHACCOUNT");

    // 签名类型

    keyValues.put("sign_type","RSA");

    returnkeyValues;

    }

    /**

    * 构造支付订单参数列表

    *

    * @return

    */

    publicstaticMap buildOrderParamMap(String app_id, String total_amount, String product_info, String time,String out_trade_no) {

    Map keyValues =newHashMap();

    keyValues.put("app_id", app_id);

    keyValues.put("biz_content","{\"timeout_express\":\"30m\",\"product_code\":\"QUICK_MSECURITY_PAY\",\"total_amount\":\""+ total_amount +"\",\"subject\":\""+ product_info +"\",\"body\":\"兑换\",\"out_trade_no\":\""+out_trade_no +"\"}");

    keyValues.put("charset","utf-8");

    keyValues.put("method","alipay.trade.app.pay");

    keyValues.put("sign_type","RSA");

    keyValues.put("timestamp", time);// "2016-07-29 16:55:53"

    keyValues.put("version","1.0");

    keyValues.put("notify_url","成功回调地址");

    returnkeyValues;

    }

    /**

    * 构造支付订单参数信息

    *

    * @param map 支付订单参数

    * @return

    */

    publicstaticString buildOrderParam(Map map) {

    List keys =newArrayList(map.keySet());

    StringBuilder sb =newStringBuilder();

    for(inti =0; i < keys.size() -1; i++) {

    String key = keys.get(i);

    String value = map.get(key);

    sb.append(buildKeyValue(key, value,true));

    sb.append("&");

    }

    String tailKey = keys.get(keys.size() -1);

    String tailValue = map.get(tailKey);

    sb.append(buildKeyValue(tailKey, tailValue,true));

    returnsb.toString();

    }

    /**

    * 拼接键值对

    *

    * @param key

    * @param value

    * @param isEncode

    * @return

    */

    privatestaticString buildKeyValue(String key, String value,booleanisEncode) {

    StringBuilder sb =newStringBuilder();

    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);

    }

    returnsb.toString();

    }

    /**

    * 对支付参数信息进行签名

    *

    * @param map 待签名授权信息

    * @return

    */

    publicstaticString getSign(Map map, String rsaKey) {

    List keys =newArrayList(map.keySet());

    // key排序

    Collections.sort(keys);

    StringBuilder authInfo =newStringBuilder();

    for(inti =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 = SignUtils.sign(authInfo.toString(), rsaKey);

    String encodedSign ="";

    try{

    encodedSign = URLEncoder.encode(oriSign,"UTF-8");

    }catch(UnsupportedEncodingException e) {

    e.printStackTrace();

    }

    return"sign="+ encodedSign;

    }

    /**

    * 要求外部订单号必须唯一。

    *

    * @return

    */

    privatestaticString getOutTradeNo() {

    SimpleDateFormat format =newSimpleDateFormat("MMddHHmmss", Locale.getDefault());

    Date date =newDate();

    String key = format.format(date);

    Random r =newRandom();

    key = key + r.nextInt();

    key = key.substring(0,15);

    returnkey;

    }

    }

    /**

    * 重要说明:

    * 这里只是为了方便直接向商户展示支付宝的整个支付流程;所以Demo中加签过程直接放在客户端完成;

    * 真实App里,privateKey等数据严禁放在客户端,加签过程务必要放在服务端完成;

    * 防止商户私密数据泄露,造成不必要的资金损失,及面临各种安全风险;

    */

    publicclassPayDemoActivityextendsFragmentActivity {

    /**

    * 支付宝支付业务:入参app_id

    */

    publicstaticfinalString APPID ="入参app_id";

    /**

    * 支付宝账户登录授权业务:入参pid值

    */

    publicstaticfinalString PID ="入参pid值";

    /**

    * 支付宝账户登录授权业务:入参target_id值

    */

    publicstaticfinalString TARGET_ID ="入参target_id值";

    /**

    * 商户私钥,pkcs8格式

    */

    publicstaticfinalString RSA_PRIVATE ="商户私钥";

    privatestaticfinalintSDK_PAY_FLAG =1;

    privatestaticfinalintSDK_AUTH_FLAG =2;

    @SuppressLint("HandlerLeak")

    privateHandler mHandler =newHandler() {

    @SuppressWarnings("unused")

    publicvoidhandleMessage(Message msg) {

    switch(msg.what) {

    caseSDK_PAY_FLAG: {

    @SuppressWarnings("unchecked")

    PayResult payResult =newPayResult((Map) msg.obj);

    /**

    对于支付结果,请商户依赖服务端的异步通知结果。同步通知结果,仅作为支付结束的通知。

    */

    String resultInfo = payResult.getResult();// 同步返回需要验证的信息

    String resultStatus = payResult.getResultStatus();

    // 判断resultStatus 为9000则代表支付成功

    if(TextUtils.equals(resultStatus,"9000")) {

    // 该笔订单是否真实支付成功,需要依赖服务端的异步通知。

    MyToast.makeText(PayDemoActivity.this,"支付成功", Toast.LENGTH_SHORT).show();

    }else{

    // 该笔订单真实的支付结果,需要依赖服务端的异步通知。

    MyToast.makeText(PayDemoActivity.this,"支付失败", Toast.LENGTH_SHORT).show();

    }

    break;

    }

    caseSDK_AUTH_FLAG: {

    @SuppressWarnings("unchecked")

    AuthResult authResult =newAuthResult((Map) 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

    // 传入,则支付账户为该授权账户

    MyToast.makeText(PayDemoActivity.this,

    "授权成功\n"+ String.format("authCode:%s", authResult.getAuthCode()), Toast.LENGTH_SHORT)

    .show();

    }else{

    // 其他状态值则为授权失败

    MyToast.makeText(PayDemoActivity.this,

    "授权失败"+ String.format("authCode:%s", authResult.getAuthCode()), Toast.LENGTH_SHORT).show();

    }

    break;

    }

    default:

    break;

    }

    }

    ;

    };

    @Override

    protectedvoidonCreate(Bundle savedInstanceState) {

    super.onCreate(savedInstanceState);

    setContentView(R.layout.pay_main);

    SimpleDateFormat dfs =newSimpleDateFormat("yyyy-MM-dd HH:mm:ss");

    String date_e = dfs.format(newDate());

    payV2("0.02","团币兑换", date_e);

    }

    /**

    * 支付宝支付业务

    */

    publicvoidpayV2(String price, String product_info, String time) {

    if(TextUtils.isEmpty(APPID) || TextUtils.isEmpty(RSA_PRIVATE)) {

    newAlertDialog.Builder(this).setTitle("警告").setMessage("需要配置APPID | RSA_PRIVATE")

    .setPositiveButton("确定",newDialogInterface.OnClickListener() {

    publicvoidonClick(DialogInterface dialoginterface,inti) {

    finish();

    }

    }).show();

    return;

    }

    /**

    * 这里只是为了方便直接向商户展示支付宝的整个支付流程;所以Demo中加签过程直接放在客户端完成;

    * 真实App里,privateKey等数据严禁放在客户端,加签过程务必要放在服务端完成;

    * 防止商户私密数据泄露,造成不必要的资金损失,及面临各种安全风险;

    *

    * orderInfo的获取必须来自服务端;

    */

    //        Map params = OrderInfoUtil2_0.buildOrderParamMap(APPID, price, product_info, time);

    Map params=newHashMap();

    String orderParam = OrderInfoUtil2_0.buildOrderParam(params);

    String sign = OrderInfoUtil2_0.getSign(params, RSA_PRIVATE);

    finalString orderInfo = orderParam +"&"+ sign;

    Runnable payRunnable =newRunnable() {

    @Override

    publicvoidrun() {

    PayTask alipay =newPayTask(PayDemoActivity.this);

    Map result = alipay.payV2(orderInfo,true);

    Log.e("msp", result.toString());

    Message msg =newMessage();

    msg.what = SDK_PAY_FLAG;

    msg.obj = result;

    mHandler.sendMessage(msg);

    }

    };

    Thread payThread =newThread(payRunnable);

    payThread.start();

    }

    /**

    * 支付宝账户授权业务

    *

    * @param v

    */

    publicvoidauthV2(View v) {

    if(TextUtils.isEmpty(PID) || TextUtils.isEmpty(APPID) || TextUtils.isEmpty(RSA_PRIVATE)

    || TextUtils.isEmpty(TARGET_ID)) {

    newAlertDialog.Builder(this).setTitle("警告").setMessage("需要配置PARTNER |APP_ID| RSA_PRIVATE| TARGET_ID")

    .setPositiveButton("确定",newDialogInterface.OnClickListener() {

    publicvoidonClick(DialogInterface dialoginterface,inti) {

    }

    }).show();

    return;

    }

    /**

    * 这里只是为了方便直接向商户展示支付宝的整个支付流程;所以Demo中加签过程直接放在客户端完成;

    * 真实App里,privateKey等数据严禁放在客户端,加签过程务必要放在服务端完成;

    * 防止商户私密数据泄露,造成不必要的资金损失,及面临各种安全风险;

    *

    * authInfo的获取必须来自服务端;

    */

    Map authInfoMap = OrderInfoUtil2_0.buildAuthInfoMap(PID, APPID, TARGET_ID);

    String info = OrderInfoUtil2_0.buildOrderParam(authInfoMap);

    String sign = OrderInfoUtil2_0.getSign(authInfoMap, RSA_PRIVATE);

    finalString authInfo = info +"&"+ sign;

    Runnable authRunnable =newRunnable() {

    @Override

    publicvoidrun() {

    // 构造AuthTask 对象

    AuthTask authTask =newAuthTask(PayDemoActivity.this);

    // 调用授权接口,获取授权结果

    Map result = authTask.authV2(authInfo,true);

    Message msg =newMessage();

    msg.what = SDK_AUTH_FLAG;

    msg.obj = result;

    mHandler.sendMessage(msg);

    }

    };

    // 必须异步调用

    Thread authThread =newThread(authRunnable);

    authThread.start();

    }

    /**

    * get the sdk version. 获取SDK版本号

    */

    publicvoidgetSDKVersion() {

    PayTask payTask =newPayTask(this);

    String version = payTask.getVersion();

    MyToast.makeText(this, version, Toast.LENGTH_SHORT).show();

    }

    /**

    * 原生的H5(手机网页版支付切natvie支付) 【对应页面网页支付按钮】

    *

    * @param v

    */

    publicvoidh5Pay(View v) {

    Intent intent =newIntent(this, H5PayDemoActivity.class);

    Bundle extras =newBundle();

    /**

    * url是测试的网站,在app内部打开页面是基于webview打开的,demo中的webview是H5PayDemoActivity,

    * demo中拦截url进行支付的逻辑是在H5PayDemoActivity中shouldOverrideUrlLoading方法实现,

    * 商户可以根据自己的需求来实现

    */

    String url ="http://m.taobao.com";

    // url可以是一号店或者淘宝等第三方的购物wap站点,在该网站的支付过程中,支付宝sdk完成拦截支付

    extras.putString("url", url);

    intent.putExtras(extras);

    startActivity(intent);

    }

    }

    剩下就是支付宝支付的业务逻辑了。下面的out_trade_no是自己请求服务器返回过来的订单号,time就是当前时间,product_info就是显示在支付页面上的字段,自己设定,试试就知道。

    /**

    * 支付宝支付业务

    */

    publicvoidpayV2(String price, String product_info, String time, String out_trade_no) {

    if(TextUtils.isEmpty(APPID) || TextUtils.isEmpty(RSA_PRIVATE)) {

    newAlertDialog.Builder(this).setTitle("警告").setMessage("需要配置APPID | RSA_PRIVATE")

    .setPositiveButton("确定",newDialogInterface.OnClickListener() {

    publicvoidonClick(DialogInterface dialoginterface,inti) {

    finish();

    }

    }).show();

    return;

    }

    /**

    * 这里只是为了方便直接向商户展示支付宝的整个支付流程;所以Demo中加签过程直接放在客户端完成;

    * 真实App里,privateKey等数据严禁放在客户端,加签过程务必要放在服务端完成;

    * 防止商户私密数据泄露,造成不必要的资金损失,及面临各种安全风险;

    *

    * orderInfo的获取必须来自服务端;

    */

    Map params = OrderInfoUtil2_0.buildOrderParamMap(APPID, price, product_info, time, out_trade_no);

    String orderParam = OrderInfoUtil2_0.buildOrderParam(params);

    String sign = OrderInfoUtil2_0.getSign(params, RSA_PRIVATE);

    finalString orderInfo = orderParam +"&"+ sign;

    Runnable payRunnable =newRunnable() {

    @Override

    publicvoidrun() {

    PayTask alipay =newPayTask(RechargeMoneyActivity.this);

    Map result = alipay.payV2(orderInfo,true);

    Message msg =newMessage();

    msg.what = SDK_PAY_FLAG;

    msg.obj = result;

    mHandler.sendMessage(msg);

    }

    };

    Thread payThread =newThread(payRunnable);

    payThread.start();

    }

    handler处理

    [java]view plaincopy

    privateHandler mHandler =newHandler() {

    @SuppressWarnings("unused")

    publicvoidhandleMessage(Message msg) {

    switch(msg.what) {

    caseSDK_PAY_FLAG: {

    @SuppressWarnings("unchecked")

    PayResult payResult =newPayResult((Map) msg.obj);

    /**

    对于支付结果,请商户依赖服务端的异步通知结果。同步通知结果,仅作为支付结束的通知。

    */

    String resultInfo = payResult.getResult();// 同步返回需要验证的信息

    String memo = payResult.getMemo();

    String resultStatus = payResult.getResultStatus();

    // 判断resultStatus 为9000则代表支付成功

    if(TextUtils.equals(resultStatus,"9000")) {

    // 该笔订单是否真实支付成功,需要依赖服务端的异步通知。

    //                        showHintDialog("支付成功");

    }else{

    pay_state ="0";

    }

    String sign = TGmd5.getMD5(logid + pay_state + memo);

    tuanbiExchangePresenter.doAlipay(logid, pay_state, memo, sign);

    break;

    }

    caseSDK_AUTH_FLAG: {

    @SuppressWarnings("unchecked")

    AuthResult authResult =newAuthResult((Map) 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

    // 传入,则支付账户为该授权账户

    MyToast.makeText(RechargeMoneyActivity.this,

    "授权成功\n"+ String.format("authCode:%s", authResult.getAuthCode()), Toast.LENGTH_SHORT)

    .show();

    }else{

    // 其他状态值则为授权失败

    MyToast.makeText(RechargeMoneyActivity.this,

    "授权失败"+ String.format("authCode:%s", authResult.getAuthCode()), Toast.LENGTH_SHORT).show();

    }

    break;

    }

    default:

    break;

    }

    }

    ;

    };

    这样一个支付宝支付就集成了,是不是很简单。复制代码就能写出,注意里面代码注解。填写各种id。

    csdn项目地址:http://blog.csdn.net/greatdaocaoren/article/details/75257603

    相关文章

      网友评论

          本文标题:Android 支付宝支付

          本文链接:https://www.haomeiwen.com/subject/aauerxtx.html