Android app支付-支付宝

前言:

银联、微信支付都已经讲解过,今天写的是支付宝支付,支付宝支付应该是比较常用的了,在2016年8月份以后在支付宝平台申请得App支付都使用2.0的了,要搞清楚,不要导错包了。

一.支付宝支付资料下载和开发文档。

1.支付宝支付的开发文档:点击打开链接

 2.支付宝sdk下载地址:点击打开链接

 

二.支付宝支付流程图:



三.支付宝资源导入和配置

 1.把alipaySdk-20161222.jar复制到libs目录下,并添加依赖.

  2.在AndroidManifest配置权限和配置支付宝控件。

<uses-permission android:name="android.permission.INTERNET" />
<uses-permission android:name="android.permission.ACCESS_NETWORK_STATE" />
<uses-permission android:name="android.permission.ACCESS_WIFI_STATE" />
<uses-permission android:name="android.permission.READ_PHONE_STATE" />
<uses-permission android:name="android.permission.WRITE_EXTERNAL_STORAGE" />

<!-- 支付宝 -->
        <activity
            android:name="com.alipay.sdk.app.H5PayActivity"
            android:configChanges="orientation|keyboardHidden|navigation|screenSize"
            android:exported="false"
            android:screenOrientation="behind"
            android:windowSoftInputMode="adjustResize|stateHidden" />
        <activity
            android:name="com.alipay.sdk.app.H5AuthActivity"
            android:configChanges="orientation|keyboardHidden|navigation"
            android:exported="false"
            android:screenOrientation="behind"
            android:windowSoftInputMode="adjustResize|stateHidden" />



四.前期工作准备好,开始接入代码

1.订单数据的生成(这步可以在服务端完成,也可以在客户端)

在支付宝的demo有一个OrderInfoUtil2_0工具类,我们可以拷贝到我们自己的项目,该类是用来生成订单的。这个工具类,我进行了改动,可能跟支付宝Demo的不一样.

       /**
	 * 构造支付订单参数列表
	 * @param app_id
	 * @return
	 */
	public static Map<String, String> buildOrderParamMap(String title,String body,String amount) {
		Map<String, String> keyValues = new HashMap<String, String>();

		keyValues.put("app_id", AppId)

		keyValues.put("biz_content", "{\"timeout_express\":\"30m\",\"product_code\":\"QUICK_MSECURITY_PAY\",\"total_amount\":\""+amount+"\",\"subject\":\""+title+"\",                                       \"body\":\""+body+"\",\"out_trade_no\":\"" + getOutTradeNo()+ "\"}");
		
		keyValues.put("charset", "utf-8");

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

		keyValues.put("notify_url", "这里填写支付宝支付成功的回调地址,需要服务端提供");

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

		keyValues.put("timestamp", "2016-07-29 16:55:53");//这个日期可以自己生成

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

        /**
	 * 构造支付订单参数信息
	 * 
	 * @param map
	 * 支付订单参数
	 * @return
	 */
	public static 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("&");
		}

		String tailKey = keys.get(keys.size() - 1);
		String tailValue = map.get(tailKey);
		sb.append(buildKeyValue(tailKey, tailValue, true));

		return sb.toString();
	}
	
	/**
	 * 拼接键值对
	 * 
	 * @param key
	 * @param value
	 * @param isEncode
	 * @return
	 */
	private static 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();
	}
	
	/**
	 * 对支付参数信息进行签名
	 * 
	 * @param map
	 *            待签名授权信息
	 * 
	 * @return
	 */
	public static String getSign(Map<String, String> map, String rsaKey) {
		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 = SignUtils.sign(authInfo.toString(), rsaKey);
		String encodedSign = "";

		try {
			encodedSign = URLEncoder.encode(oriSign, "UTF-8");
		} catch (UnsupportedEncodingException e) {
			e.printStackTrace();
		}
		return "sign=" + encodedSign;
	}
	
	/**
	 * 要求外部订单号必须唯一。
	 * @return
	 */
	private static String getOutTradeNo() {
		SimpleDateFormat format = new SimpleDateFormat("MMddHHmmss", Locale.getDefault());
		Date date = new Date();
		String key = format.format(date);

		Random r = new Random();
		key = key + r.nextInt();
		key = key.substring(0, 15);
		return key;
	}


2.调用buildOrderParamMap方法,传入标题,描述,金额构建订单。
Map<String, String>  params = OrderInfoUtil2_0.buildOrderParamMap("订单标题","订单描述","金额");
把params 订单拼接成字符串(也可以在后台进行这个操作),注意,这里有个编码问题,在转成字符串时,会进行UTF-8编码,如果前端进行编码,服务端就无需再转码,注意,不然会出错。

String orderParam = OrderInfoUtil2_0.buildOrderParam(params);

3.把orderParam传给后台进行加签.(加签要放在服务端进行,不然很容易泄漏信息)


4.后台会返回一个加签后的字符串sign(个人命名),生成完整的符合支付宝支付的订单信息.
final String orderInfo = orderParam + "&" + sign;
注意:orderInfo大概是这样的

partner="2088101568358171"&seller_id="xxx@alipay.com"&out_trade_no="0819145412-6177"&subject="测试"&body="测试测试"&total_fee="0.01"¬ify_url="http://notify.msp.hk/notify.htm"&service="mobile.securitypay.pay"&payment_type="1"&_input_charset="utf-8"&it_b_pay="30m"&sign="lBBK%2F0w5LOajrMrji7DUgEqNjIhQbidR13GovA5r3TgIbNqv231yC1NksLdw%2Ba3JnfHXoXuet6XNNHtn7VE%2BeCoRO1O%2BR1KugLrQEZMtG5jmJIe2pbjm%2F3kb%2FuGkpG%2BwYQYI51%2BhA3YBbvZHVQBYveBqK%2Bh8mUyb7GM1HxWs9k4%3D"&sign_type="RSA"


5.最终,服务端会返回加签后的订单信息,我们可以发送一步请求去支付了

Runnable payRunnable = new Runnable() {
            @Override
            public void run() {
                PayTask alipay = new PayTask(PayMentActivity.this);
                Map<String, String> result = alipay.payV2(orderInfos, true);
                Message msg = new Message();
                msg.what = SDK_PAY_FLAG;
                msg.obj = result;
                mHandler.sendMessage(msg);
            }
        };
// 必须异步调用
        Thread payThread = new Thread(payRunnable);
        payThread.start();


6.在当前Activity新建一个Handler,用于接收异步的信息

@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")) {

                        ToastUtil.showShortToast(PayMentActivity.this,"用户支付成功");
                    } else if(TextUtils.equals(resultStatus,"6001")){
                        ToastUtil.showShortToast(PayMentActivity.this,"用户取消了支付");
                    } else {
                        ToastUtil.showShortToast(PayMentActivity.this,"用户支付失败");
                    }
                    break;
                }
                default:
                    break;
            }
        }

        ;
    };

注意:java使用的是pack8格式的私钥,私钥不要暴露在客户端。




原创博客,转载请注明:
http://blog.csdn.NET/lgl5785592












  • 0
    点赞
  • 3
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值