Просмотр исходного кода

完成一元捐基本的界面逻辑开发,接入支付宝前备份

Bitliker 8 лет назад
Родитель
Сommit
a7524cad3a
16 измененных файлов с 1176 добавлено и 23 удалено
  1. BIN
      app_modular/apputils/libs/alipaySdk-20170922.jar
  2. 21 0
      app_modular/apputils/src/main/AndroidManifest.xml
  3. 13 0
      app_modular/apputils/src/main/java/com/modular/apputils/listener/OnPlayListener.java
  4. 103 0
      app_modular/apputils/src/main/java/com/modular/apputils/utils/playsdk/AliLoadPlayApi.java
  5. 98 0
      app_modular/apputils/src/main/java/com/modular/apputils/utils/playsdk/AliPlay.java
  6. 268 0
      app_modular/apputils/src/main/java/com/modular/apputils/utils/playsdk/Base64.java
  7. 222 0
      app_modular/apputils/src/main/java/com/modular/apputils/utils/playsdk/OrderInfoUtil2_0.java
  8. 54 0
      app_modular/apputils/src/main/java/com/modular/apputils/utils/playsdk/PayResult.java
  9. 44 0
      app_modular/apputils/src/main/java/com/modular/apputils/utils/playsdk/SignUtils.java
  10. 46 23
      app_modular/appworks/src/main/java/com/uas/appworks/OA/platform/fragment/CharitableListFragment.java
  11. 3 0
      app_modular/appworks/src/main/java/com/uas/appworks/OA/platform/model/TestString.java
  12. 74 0
      app_modular/appworks/src/main/java/com/uas/appworks/widget/SelectPlayPop.java
  13. 7 0
      app_modular/appworks/src/main/res/drawable/pop_text_color_bg.xml
  14. 5 0
      app_modular/appworks/src/main/res/drawable/pop_text_frame_bg.xml
  15. 10 0
      app_modular/appworks/src/main/res/drawable/text_frame_red_bg.xml
  16. 208 0
      app_modular/appworks/src/main/res/layout/pop_play_select.xml

BIN
app_modular/apputils/libs/alipaySdk-20170922.jar


+ 21 - 0
app_modular/apputils/src/main/AndroidManifest.xml

@@ -6,6 +6,27 @@
         android:label="@string/app_name"
         android:supportsRtl="true">
         <activity android:name=".activity.SingleImagePreviewActivity"></activity>
+
+
+
+        <!-- alipay sdk begin -->
+
+        <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>
+        <activity
+            android:name="com.alipay.sdk.app.H5AuthActivity"
+            android:configChanges="orientation|keyboardHidden|navigation"
+            android:exported="false"
+            android:screenOrientation="behind"
+            android:windowSoftInputMode="adjustResize|stateHidden" >
+        </activity>
+
+        <!-- alipay sdk end -->
     </application>
 
 </manifest>

+ 13 - 0
app_modular/apputils/src/main/java/com/modular/apputils/listener/OnPlayListener.java

@@ -0,0 +1,13 @@
+package com.modular.apputils.listener;
+
+import java.io.Serializable;
+
+/**
+ * Created by Bitlike on 2017/11/13.
+ */
+
+public interface OnPlayListener   extends Serializable {
+
+	void onSuccess(String resultStatus,String resultInfo);
+	void onFailure(String resultStatus,String resultInfo);
+}

+ 103 - 0
app_modular/apputils/src/main/java/com/modular/apputils/utils/playsdk/AliLoadPlayApi.java

@@ -0,0 +1,103 @@
+package com.modular.apputils.utils.playsdk;
+
+import android.app.Activity;
+import android.os.Bundle;
+import android.os.Handler;
+import android.os.Looper;
+import android.os.Message;
+import android.text.TextUtils;
+
+
+import com.alipay.sdk.app.EnvUtils;
+import com.alipay.sdk.app.PayTask;
+import com.common.LogUtil;
+import com.core.utils.ToastUtil;
+import com.modular.apputils.listener.OnPlayListener;
+
+import java.util.Map;
+
+/**
+ * 阿里支付封装,本地获取订单号
+ * Created by Bitlike on 2017/11/13.
+ */
+
+public class AliLoadPlayApi {
+
+	//TODO 申请到的应用对应appid
+	public final String APPID = "2016081900289790";
+
+	/** 商户私钥,pkcs8格式 */
+	/** 如下私钥,RSA2_PRIVATE 或者 RSA_PRIVATE 只需要填入一个 */
+	/** 如果商户两个都设置了,优先使用 RSA2_PRIVATE */
+	/** RSA2_PRIVATE 可以保证商户交易在更加安全的环境下进行,建议使用 RSA2_PRIVATE */
+	/** 获取 RSA2_PRIVATE,建议使用支付宝提供的公私钥生成工具生成, */
+	/**
+	 * 工具地址:https://doc.open.alipay.com/docs/doc.htm?treeId=291&articleId=106097&docType=1
+	 */
+
+	/**
+	 * TODO 支付宝需要的私钥,这个需要服务来处理
+	 * 商户私钥,pkcs8格式
+	 * 如下私钥,RSA2_PRIVATE 或者 RSA_PRIVATE 只需要填入一个
+	 * 如果商户两个都设置了,优先使用 RSA2_PRIVATE
+	 * SA2_PRIVATE 可以保证商户交易在更加安全的环境下进行,建议使用 RSA2_PRIVATE
+	 * 获取 RSA2_PRIVATE,建议使用支付宝提供的公私钥生成工具生成:
+	 *
+	 * @link(https://doc.open.alipay.com/docs/doc.htm?treeId=291&articleId=106097&docType=1)
+	 */
+	public static final String RSA2_PRIVATE = "MIIEvgIBADANBgkqhkiG9w0BAQEFAASCBKgwggSkAgEAAoIBAQCAFuBe4C2UlLUFrllXmtxMF2MvCdfhatXsEYUQRsYV2nrj3XKcceDd44H1mQt0TzkmjfoeIe/ec7MNVrKUmGrAft8lFbxSH0aUXm+3QURQtsaCjd8yxkuUkbQ9eRqyix4/ayGZD3Sn7gHmqL576aslfNNo7XhH+GT/7kYWXE3aqkgnm0m5CWxVpcXyRysi0ToTGlszTO0nnhUduQVra6bAh7uGU80O1a+1JIDJKVg2Z2DcSx0pJ9CDjiar4u98Pwhdp+e+oohCTCIygv8PRbTZocOz2N843wTe3ZlNqKvdzKXu1t/w56bidgZ8TI6SI6FHVSyzwvUl5WypIyMQpyrdAgMBAAECggEAKud+wEjW+63T9NMxmeaFY/dxgZAKf7cJcMltiMYsE6XbA/hpK335lFlgbqOU8qCWxBNKdE1py1l14EHqD1v+ZfwZQpLFQby4J3p6cSerel2+oHxlBtzk9B7aAL1P8/4lY5i+6EYFDTrr6BcdtuPOMABf0AW7BGBvdEqbr2G7skJbLbFytLP5Wp7mSMFy/zq5+nVVHXUkbHYepLq2oXUyZVRF75ldG/TVx0fTn6F+nObOe1yTRiAjst8b02xhnNPV0d0Ia5IzXkM2Cy3P2Mr6pGMi/0h0xl7ouk5gDiXKp0wgoCGQe84TSBgbTiRAOxlbj+nynLozgHGUUZEgr0RpAQKBgQDhaZPA3Lq3D3WqRSkQDCscJj/N0Ex88XAOhpZO4xaPHMuYp3cdrSJCbAdchoLCG/QY2N3zSu5NRz7U+LFx6WKkHGJhvoPLnNn9uvhGwHOqbWVwdKPubwbf1H4wQcm1mZiqDQ/WPKDWby75NcAb98SIwLZUdPEZ0y+jLYNZQxZ38wKBgQCReHiaVAUHM/4Xe2UPI4zR7E1POFb+X6qJosgVvNACbqp3KeED2CmEd8n7fzuBOVxie9V7kAEMV+RrO65CgRJI8k+qeLggF7+G0W7KJLYy64Pjo3VENRcJIZ0M6XhsCbi+KiYBJtvo0k4aQ5GBKh6lGxS9THpYBuVPyk0aZ6DV7wKBgQCXpkr0Vsv7Ophj7FGa7UTXlFgapEfBS0GjVCKtghP8RlgnJIt72K4S19EAC7LO2rWXPdfcxY2bShJYf9QJmgV1+W6q6dyLUMRL8szz9KgcgarcRGzBjcqnLbOTzb7hwSs3RMBh1royaezFVscfScrcYiKIoYBPaohDFOyoUf08xwKBgGQYBrP59/O63Kz/pMvD5FNVSuSlmYYyAT/vF8mNP3tM9lJEKKXiiL6zRfGc3C7Qbzb8iioZLf92Qp9eU0tDUHeM8zATHG5IqOp1FMxWcl+bGgb6I+got4765/tIcim0jr+adMf6GvqaKk98CpRbjPaCKcUO6GfFZud+BYuTnmFVAoGBAMTjA6Lds8ORSNvYOR7G56jlxilLwsiNrc/zLacXV44BKICvavmUaSGelwkgBotcSBQyE5ER83tNkTyYcKOm2cbmGuNb5fA91xzgyAOqmVxPO2qGt8MGVcYJtTICcD43hSTfNUdZArXok59tBHyyDF3NJg9qKbOqB0Pe6oU3l60M";
+	public static final String RSA_PRIVATE = "";
+
+
+	/**
+	 * 这里只是为了方便直接向商户展示支付宝的整个支付流程;所以Demo中加签过程直接放在客户端完成;
+	 * 真实App里,privateKey等数据严禁放在客户端,加签过程务必要放在服务端完成
+	 * 防止商户私密数据泄露,造成不必要的资金损失,及面临各种安全风险
+	 * orderInfo的获取必须来自服务端
+	 *
+	 * @param ct             上下文
+	 * @param onPlayListener 回调
+	 */
+	private void alipay(final Activity ct, final OnPlayListener onPlayListener) {
+		EnvUtils.setEnv(EnvUtils.EnvEnum.SANDBOX);
+		if (TextUtils.isEmpty(APPID) || (TextUtils.isEmpty(RSA2_PRIVATE) && TextUtils.isEmpty(RSA_PRIVATE))) {
+			ToastUtil.showToast(ct, "需要配置APPID | RSA_PRIVATE");
+			return;
+		}
+		boolean rsa2 = (RSA2_PRIVATE.length() > 0);
+		Map<String, String> params = OrderInfoUtil2_0.buildOrderParamMap(APPID, rsa2);
+		String orderParam = OrderInfoUtil2_0.buildOrderParam(params);
+		String privateKey = rsa2 ? RSA2_PRIVATE : RSA_PRIVATE;
+		String sign = OrderInfoUtil2_0.getSign(params, privateKey, rsa2);
+		final String orderInfo = orderParam + "&" + sign;
+		Runnable payRunnable = new Runnable() {
+			@Override
+			public void run() {
+				PayTask alipay = new PayTask(ct);
+				LogUtil.i("orderInfo=" + orderInfo);
+				Map<String, String> result = alipay.payV2(orderInfo, true);
+				LogUtil.i(result.toString());
+				Message msg = new Message();
+				msg.what = 11;
+				msg.obj = result;
+//TODO 发送回调				sendMessage(msg);
+
+			}
+		};
+		Thread payThread = new Thread(payRunnable);
+		payThread.start();
+	}
+
+
+	//TODO 本地获取OrderInfo ,发布时候需要通过接口获取
+	public String getLoadOrderInfo() {
+		EnvUtils.setEnv(EnvUtils.EnvEnum.SANDBOX);
+		boolean rsa2 = (RSA2_PRIVATE.length() > 0);
+		Map<String, String> params = OrderInfoUtil2_0.buildOrderParamMap(APPID, rsa2);
+		String orderParam = OrderInfoUtil2_0.buildOrderParam(params);
+		String privateKey = rsa2 ? RSA2_PRIVATE : RSA_PRIVATE;
+		String sign = OrderInfoUtil2_0.getSign(params, privateKey, rsa2);
+		String orderInfo = orderParam + "&" + sign;
+		return orderInfo;
+	}
+}

+ 98 - 0
app_modular/apputils/src/main/java/com/modular/apputils/utils/playsdk/AliPlay.java

@@ -0,0 +1,98 @@
+package com.modular.apputils.utils.playsdk;
+
+import android.app.Activity;
+import android.os.Bundle;
+import android.os.Handler;
+import android.os.Looper;
+import android.os.Message;
+import android.text.TextUtils;
+
+import com.alipay.sdk.app.PayTask;
+import com.common.LogUtil;
+import com.common.thread.ThreadPool;
+import com.modular.apputils.listener.OnPlayListener;
+
+import java.util.Map;
+
+/**
+ * Created by Bitlike on 2017/11/13.
+ */
+
+public class AliPlay extends Handler {
+	private final int SDK_PAY_FLAG = 1;
+
+	private static AliPlay api;
+
+	public static AliPlay api() {
+		if (api == null) {
+			synchronized (AliPlay.class) {
+				if (api == null) {
+					api = new AliPlay();
+				}
+			}
+		}
+		return api;
+	}
+
+	private AliPlay() {
+		super(Looper.getMainLooper());
+	}
+
+	@Override
+	public void handleMessage(Message msg) {
+		super.handleMessage(msg);
+		if (msg != null && msg.what == SDK_PAY_FLAG) {
+			try {
+				handerPlayResult(msg);
+			} catch (Exception e) {
+				if (e != null) {
+					LogUtil.i("AliPlay Exception=" + e.getMessage());
+				}
+			}
+		}
+	}
+
+	private void handerPlayResult(Message msg) throws Exception {
+		Bundle bundle = msg.getData();
+		if (bundle == null) return;
+		OnPlayListener onPlayListener = (OnPlayListener) bundle.getSerializable("onPlayListener");
+		if (onPlayListener == null) return;
+		PayResult payResult = new PayResult((Map<String, String>) msg.obj);
+			/*对于支付结果,请商户依赖服务端的异步通知结果。同步通知结果,仅作为支付结束的通知。*/
+		String resultInfo = payResult.getResult();// 同步返回需要验证的信息
+		LogUtil.i("resultInfo=" + resultInfo);
+		String resultStatus = payResult.getResultStatus();
+		// 判断resultStatus 为9000则代表支付成功
+		if (TextUtils.equals(resultStatus, "9000")) {
+			// 该笔订单是否真实支付成功,需要依赖服务端的异步通知。
+			if (onPlayListener != null) {
+				onPlayListener.onSuccess(resultStatus, resultInfo);
+			}
+		} else {
+			// 该笔订单真实的支付结果,需要依赖服务端的异步通知。
+			if (onPlayListener != null) {
+				onPlayListener.onFailure(resultStatus, resultInfo);
+			}
+		}
+	}
+
+
+	public void alipay(final Activity ct, final String orderInfo, final OnPlayListener onPlayListener) {
+		ThreadPool.getThreadPool().addTask(new Runnable() {
+			@Override
+			public void run() {
+				PayTask alipay = new PayTask(ct);
+				LogUtil.i("orderInfo=" + orderInfo);
+				Map<String, String> result = alipay.payV2(orderInfo, true);
+				LogUtil.i(result.toString());
+				Message msg = new Message();
+				Bundle bundle = new Bundle();
+				bundle.putSerializable("onPlayListener", onPlayListener);
+				msg.setData(bundle);
+				msg.what = SDK_PAY_FLAG;
+				msg.obj = result;
+				sendMessage(msg);
+			}
+		});
+	}
+}

+ 268 - 0
app_modular/apputils/src/main/java/com/modular/apputils/utils/playsdk/Base64.java

@@ -0,0 +1,268 @@
+package com.modular.apputils.utils.playsdk;
+
+public final class Base64 {
+
+	private static final int BASELENGTH = 128;
+	private static final int LOOKUPLENGTH = 64;
+	private static final int TWENTYFOURBITGROUP = 24;
+	private static final int EIGHTBIT = 8;
+	private static final int SIXTEENBIT = 16;
+	private static final int FOURBYTE = 4;
+	private static final int SIGN = -128;
+	private static char PAD = '=';
+	private static byte[] base64Alphabet = new byte[BASELENGTH];
+	private static char[] lookUpBase64Alphabet = new char[LOOKUPLENGTH];
+
+	static {
+		for (int i = 0; i < BASELENGTH; ++i) {
+			base64Alphabet[i] = -1;
+		}
+		for (int i = 'Z'; i >= 'A'; i--) {
+			base64Alphabet[i] = (byte) (i - 'A');
+		}
+		for (int i = 'z'; i >= 'a'; i--) {
+			base64Alphabet[i] = (byte) (i - 'a' + 26);
+		}
+
+		for (int i = '9'; i >= '0'; i--) {
+			base64Alphabet[i] = (byte) (i - '0' + 52);
+		}
+
+		base64Alphabet['+'] = 62;
+		base64Alphabet['/'] = 63;
+
+		for (int i = 0; i <= 25; i++) {
+			lookUpBase64Alphabet[i] = (char) ('A' + i);
+		}
+
+		for (int i = 26, j = 0; i <= 51; i++, j++) {
+			lookUpBase64Alphabet[i] = (char) ('a' + j);
+		}
+
+		for (int i = 52, j = 0; i <= 61; i++, j++) {
+			lookUpBase64Alphabet[i] = (char) ('0' + j);
+		}
+		lookUpBase64Alphabet[62] = (char) '+';
+		lookUpBase64Alphabet[63] = (char) '/';
+
+	}
+
+	private static boolean isWhiteSpace(char octect) {
+		return (octect == 0x20 || octect == 0xd || octect == 0xa || octect == 0x9);
+	}
+
+	private static boolean isPad(char octect) {
+		return (octect == PAD);
+	}
+
+	private static boolean isData(char octect) {
+		return (octect < BASELENGTH && base64Alphabet[octect] != -1);
+	}
+
+	/**
+	 * Encodes hex octects into Base64
+	 * 
+	 * @param binaryData
+	 *            Array containing binaryData
+	 * @return Encoded Base64 array
+	 */
+	public static String encode(byte[] binaryData) {
+
+		if (binaryData == null) {
+			return null;
+		}
+
+		int lengthDataBits = binaryData.length * EIGHTBIT;
+		if (lengthDataBits == 0) {
+			return "";
+		}
+
+		int fewerThan24bits = lengthDataBits % TWENTYFOURBITGROUP;
+		int numberTriplets = lengthDataBits / TWENTYFOURBITGROUP;
+		int numberQuartet = fewerThan24bits != 0 ? numberTriplets + 1
+				: numberTriplets;
+		char encodedData[] = null;
+
+		encodedData = new char[numberQuartet * 4];
+
+		byte k = 0, l = 0, b1 = 0, b2 = 0, b3 = 0;
+
+		int encodedIndex = 0;
+		int dataIndex = 0;
+
+		for (int i = 0; i < numberTriplets; i++) {
+			b1 = binaryData[dataIndex++];
+			b2 = binaryData[dataIndex++];
+			b3 = binaryData[dataIndex++];
+
+			l = (byte) (b2 & 0x0f);
+			k = (byte) (b1 & 0x03);
+
+			byte val1 = ((b1 & SIGN) == 0) ? (byte) (b1 >> 2)
+					: (byte) ((b1) >> 2 ^ 0xc0);
+			byte val2 = ((b2 & SIGN) == 0) ? (byte) (b2 >> 4)
+					: (byte) ((b2) >> 4 ^ 0xf0);
+			byte val3 = ((b3 & SIGN) == 0) ? (byte) (b3 >> 6)
+					: (byte) ((b3) >> 6 ^ 0xfc);
+
+			encodedData[encodedIndex++] = lookUpBase64Alphabet[val1];
+			encodedData[encodedIndex++] = lookUpBase64Alphabet[val2 | (k << 4)];
+			encodedData[encodedIndex++] = lookUpBase64Alphabet[(l << 2) | val3];
+			encodedData[encodedIndex++] = lookUpBase64Alphabet[b3 & 0x3f];
+		}
+
+		// form integral number of 6-bit groups
+		if (fewerThan24bits == EIGHTBIT) {
+			b1 = binaryData[dataIndex];
+			k = (byte) (b1 & 0x03);
+			
+			byte val1 = ((b1 & SIGN) == 0) ? (byte) (b1 >> 2)
+					: (byte) ((b1) >> 2 ^ 0xc0);
+			encodedData[encodedIndex++] = lookUpBase64Alphabet[val1];
+			encodedData[encodedIndex++] = lookUpBase64Alphabet[k << 4];
+			encodedData[encodedIndex++] = PAD;
+			encodedData[encodedIndex++] = PAD;
+		} else if (fewerThan24bits == SIXTEENBIT) {
+			b1 = binaryData[dataIndex];
+			b2 = binaryData[dataIndex + 1];
+			l = (byte) (b2 & 0x0f);
+			k = (byte) (b1 & 0x03);
+
+			byte val1 = ((b1 & SIGN) == 0) ? (byte) (b1 >> 2)
+					: (byte) ((b1) >> 2 ^ 0xc0);
+			byte val2 = ((b2 & SIGN) == 0) ? (byte) (b2 >> 4)
+					: (byte) ((b2) >> 4 ^ 0xf0);
+
+			encodedData[encodedIndex++] = lookUpBase64Alphabet[val1];
+			encodedData[encodedIndex++] = lookUpBase64Alphabet[val2 | (k << 4)];
+			encodedData[encodedIndex++] = lookUpBase64Alphabet[l << 2];
+			encodedData[encodedIndex++] = PAD;
+		}
+
+		return new String(encodedData);
+	}
+
+	/**
+	 * Decodes Base64 data into octects
+	 * 
+	 * @param encoded
+	 *            string containing Base64 data
+	 * @return Array containind decoded data.
+	 */
+	public static byte[] decode(String encoded) {
+
+		if (encoded == null) {
+			return null;
+		}
+
+		char[] base64Data = encoded.toCharArray();
+		// remove white spaces
+		int len = removeWhiteSpace(base64Data);
+
+		if (len % FOURBYTE != 0) {
+			return null;// should be divisible by four
+		}
+
+		int numberQuadruple = (len / FOURBYTE);
+
+		if (numberQuadruple == 0) {
+			return new byte[0];
+		}
+
+		byte decodedData[] = null;
+		byte b1 = 0, b2 = 0, b3 = 0, b4 = 0;
+		char d1 = 0, d2 = 0, d3 = 0, d4 = 0;
+
+		int i = 0;
+		int encodedIndex = 0;
+		int dataIndex = 0;
+		decodedData = new byte[(numberQuadruple) * 3];
+
+		for (; i < numberQuadruple - 1; i++) {
+
+			if (!isData((d1 = base64Data[dataIndex++]))
+					|| !isData((d2 = base64Data[dataIndex++]))
+					|| !isData((d3 = base64Data[dataIndex++]))
+					|| !isData((d4 = base64Data[dataIndex++]))) {
+				return null;
+			}// if found "no data" just return null
+
+			b1 = base64Alphabet[d1];
+			b2 = base64Alphabet[d2];
+			b3 = base64Alphabet[d3];
+			b4 = base64Alphabet[d4];
+
+			decodedData[encodedIndex++] = (byte) (b1 << 2 | b2 >> 4);
+			decodedData[encodedIndex++] = (byte) (((b2 & 0xf) << 4) | ((b3 >> 2) & 0xf));
+			decodedData[encodedIndex++] = (byte) (b3 << 6 | b4);
+		}
+
+		if (!isData((d1 = base64Data[dataIndex++]))
+				|| !isData((d2 = base64Data[dataIndex++]))) {
+			return null;// if found "no data" just return null
+		}
+
+		b1 = base64Alphabet[d1];
+		b2 = base64Alphabet[d2];
+
+		d3 = base64Data[dataIndex++];
+		d4 = base64Data[dataIndex++];
+		if (!isData((d3)) || !isData((d4))) {// Check if they are PAD characters
+			if (isPad(d3) && isPad(d4)) {
+				if ((b2 & 0xf) != 0)// last 4 bits should be zero
+				{
+					return null;
+				}
+				byte[] tmp = new byte[i * 3 + 1];
+				System.arraycopy(decodedData, 0, tmp, 0, i * 3);
+				tmp[encodedIndex] = (byte) (b1 << 2 | b2 >> 4);
+				return tmp;
+			} else if (!isPad(d3) && isPad(d4)) {
+				b3 = base64Alphabet[d3];
+				if ((b3 & 0x3) != 0)// last 2 bits should be zero
+				{
+					return null;
+				}
+				byte[] tmp = new byte[i * 3 + 2];
+				System.arraycopy(decodedData, 0, tmp, 0, i * 3);
+				tmp[encodedIndex++] = (byte) (b1 << 2 | b2 >> 4);
+				tmp[encodedIndex] = (byte) (((b2 & 0xf) << 4) | ((b3 >> 2) & 0xf));
+				return tmp;
+			} else {
+				return null;
+			}
+		} else { // No PAD e.g 3cQl
+			b3 = base64Alphabet[d3];
+			b4 = base64Alphabet[d4];
+			decodedData[encodedIndex++] = (byte) (b1 << 2 | b2 >> 4);
+			decodedData[encodedIndex++] = (byte) (((b2 & 0xf) << 4) | ((b3 >> 2) & 0xf));
+			decodedData[encodedIndex++] = (byte) (b3 << 6 | b4);
+
+		}
+
+		return decodedData;
+	}
+
+	/**
+	 * remove WhiteSpace from MIME containing encoded Base64 data.
+	 * 
+	 * @param data
+	 *            the byte array of base64 data (with WS)
+	 * @return the new length
+	 */
+	private static int removeWhiteSpace(char[] data) {
+		if (data == null) {
+			return 0;
+		}
+
+		// count characters that's not whitespace
+		int newSize = 0;
+		int len = data.length;
+		for (int i = 0; i < len; i++) {
+			if (!isWhiteSpace(data[i])) {
+				data[newSize++] = data[i];
+			}
+		}
+		return newSize;
+	}
+}

+ 222 - 0
app_modular/apputils/src/main/java/com/modular/apputils/utils/playsdk/OrderInfoUtil2_0.java

@@ -0,0 +1,222 @@
+package com.modular.apputils.utils.playsdk;
+
+import com.alipay.sdk.app.EnvUtils;
+
+import java.io.UnsupportedEncodingException;
+import java.net.URLEncoder;
+import java.text.SimpleDateFormat;
+import java.util.ArrayList;
+import java.util.Collections;
+import java.util.Date;
+import java.util.HashMap;
+import java.util.List;
+import java.util.Locale;
+import java.util.Map;
+import java.util.Random;
+
+
+public class OrderInfoUtil2_0 {
+	//TODO 申请到的应用对应appid
+	public final String APPID = "2016081900289790";
+
+	/** 商户私钥,pkcs8格式 */
+	/** 如下私钥,RSA2_PRIVATE 或者 RSA_PRIVATE 只需要填入一个 */
+	/** 如果商户两个都设置了,优先使用 RSA2_PRIVATE */
+	/** RSA2_PRIVATE 可以保证商户交易在更加安全的环境下进行,建议使用 RSA2_PRIVATE */
+	/** 获取 RSA2_PRIVATE,建议使用支付宝提供的公私钥生成工具生成, */
+	/**
+	 * 工具地址:https://doc.open.alipay.com/docs/doc.htm?treeId=291&articleId=106097&docType=1
+	 */
+
+	/**
+	 * TODO 支付宝需要的私钥,这个需要服务来处理
+	 * 商户私钥,pkcs8格式
+	 * 如下私钥,RSA2_PRIVATE 或者 RSA_PRIVATE 只需要填入一个
+	 * 如果商户两个都设置了,优先使用 RSA2_PRIVATE
+	 * SA2_PRIVATE 可以保证商户交易在更加安全的环境下进行,建议使用 RSA2_PRIVATE
+	 * 获取 RSA2_PRIVATE,建议使用支付宝提供的公私钥生成工具生成:
+	 *
+	 * @link(https://doc.open.alipay.com/docs/doc.htm?treeId=291&articleId=106097&docType=1)
+	 */
+	public static final String RSA2_PRIVATE = "MIIEvgIBADANBgkqhkiG9w0BAQEFAASCBKgwggSkAgEAAoIBAQCAFuBe4C2UlLUFrllXmtxMF2MvCdfhatXsEYUQRsYV2nrj3XKcceDd44H1mQt0TzkmjfoeIe/ec7MNVrKUmGrAft8lFbxSH0aUXm+3QURQtsaCjd8yxkuUkbQ9eRqyix4/ayGZD3Sn7gHmqL576aslfNNo7XhH+GT/7kYWXE3aqkgnm0m5CWxVpcXyRysi0ToTGlszTO0nnhUduQVra6bAh7uGU80O1a+1JIDJKVg2Z2DcSx0pJ9CDjiar4u98Pwhdp+e+oohCTCIygv8PRbTZocOz2N843wTe3ZlNqKvdzKXu1t/w56bidgZ8TI6SI6FHVSyzwvUl5WypIyMQpyrdAgMBAAECggEAKud+wEjW+63T9NMxmeaFY/dxgZAKf7cJcMltiMYsE6XbA/hpK335lFlgbqOU8qCWxBNKdE1py1l14EHqD1v+ZfwZQpLFQby4J3p6cSerel2+oHxlBtzk9B7aAL1P8/4lY5i+6EYFDTrr6BcdtuPOMABf0AW7BGBvdEqbr2G7skJbLbFytLP5Wp7mSMFy/zq5+nVVHXUkbHYepLq2oXUyZVRF75ldG/TVx0fTn6F+nObOe1yTRiAjst8b02xhnNPV0d0Ia5IzXkM2Cy3P2Mr6pGMi/0h0xl7ouk5gDiXKp0wgoCGQe84TSBgbTiRAOxlbj+nynLozgHGUUZEgr0RpAQKBgQDhaZPA3Lq3D3WqRSkQDCscJj/N0Ex88XAOhpZO4xaPHMuYp3cdrSJCbAdchoLCG/QY2N3zSu5NRz7U+LFx6WKkHGJhvoPLnNn9uvhGwHOqbWVwdKPubwbf1H4wQcm1mZiqDQ/WPKDWby75NcAb98SIwLZUdPEZ0y+jLYNZQxZ38wKBgQCReHiaVAUHM/4Xe2UPI4zR7E1POFb+X6qJosgVvNACbqp3KeED2CmEd8n7fzuBOVxie9V7kAEMV+RrO65CgRJI8k+qeLggF7+G0W7KJLYy64Pjo3VENRcJIZ0M6XhsCbi+KiYBJtvo0k4aQ5GBKh6lGxS9THpYBuVPyk0aZ6DV7wKBgQCXpkr0Vsv7Ophj7FGa7UTXlFgapEfBS0GjVCKtghP8RlgnJIt72K4S19EAC7LO2rWXPdfcxY2bShJYf9QJmgV1+W6q6dyLUMRL8szz9KgcgarcRGzBjcqnLbOTzb7hwSs3RMBh1royaezFVscfScrcYiKIoYBPaohDFOyoUf08xwKBgGQYBrP59/O63Kz/pMvD5FNVSuSlmYYyAT/vF8mNP3tM9lJEKKXiiL6zRfGc3C7Qbzb8iioZLf92Qp9eU0tDUHeM8zATHG5IqOp1FMxWcl+bGgb6I+got4765/tIcim0jr+adMf6GvqaKk98CpRbjPaCKcUO6GfFZud+BYuTnmFVAoGBAMTjA6Lds8ORSNvYOR7G56jlxilLwsiNrc/zLacXV44BKICvavmUaSGelwkgBotcSBQyE5ER83tNkTyYcKOm2cbmGuNb5fA91xzgyAOqmVxPO2qGt8MGVcYJtTICcD43hSTfNUdZArXok59tBHyyDF3NJg9qKbOqB0Pe6oU3l60M";
+	public static final String RSA_PRIVATE = "";
+
+	public String getLoadOrderInfo() {
+		boolean rsa2 = (RSA2_PRIVATE.length() > 0);
+		Map<String, String> params = OrderInfoUtil2_0.buildOrderParamMap(APPID, rsa2);
+		String orderParam = OrderInfoUtil2_0.buildOrderParam(params);
+		String privateKey = rsa2 ? RSA2_PRIVATE : RSA_PRIVATE;
+		String sign = OrderInfoUtil2_0.getSign(params, privateKey, rsa2);
+		String orderInfo = orderParam + "&" + sign;
+		return orderInfo;
+	}
+
+	/**
+	 * 构造授权参数列表
+	 *
+	 * @param pid
+	 * @param app_id
+	 * @param target_id
+	 * @return
+	 */
+	public static Map<String, String> buildAuthInfoMap(String pid, String app_id, String target_id, boolean rsa2) {
+		Map<String, String> keyValues = new HashMap<String, String>();
+
+		// 商户签约拿到的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", rsa2 ? "RSA2" : "RSA");
+
+		return keyValues;
+	}
+
+	/**
+	 * 构造支付订单参数列表
+	 *
+	 * @param app_id
+	 * @return
+	 */
+	public static Map<String, String> buildOrderParamMap(String app_id, boolean rsa2) {
+		Map<String, String> keyValues = new HashMap<String, String>();
+
+		keyValues.put("app_id", app_id);
+
+		keyValues.put("biz_content", "{\"timeout_express\":\"30m\",\"product_code\":\"QUICK_MSECURITY_PAY\",\"total_amount\":\"0.01\",\"subject\":\"1\",\"body\":\"我是测试数据\",\"out_trade_no\":\"" + getOutTradeNo() + "\"}");
+
+		keyValues.put("charset", "utf-8");
+
+		keyValues.put("method", "alipay.trade.app.pay");
+
+		keyValues.put("sign_type", rsa2 ? "RSA2" : "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, boolean rsa2) {
+		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, rsa2);
+		String encodedSign = "";
+
+		try {
+			encodedSign = URLEncoder.encode(oriSign, "UTF-8");
+		} catch (UnsupportedEncodingException e) {
+			e.printStackTrace();
+		}
+		return "sign=" + encodedSign;
+	}
+
+	/**
+	 * 要求外部订单号必须唯一。
+	 *
+	 * @return
+	 */
+	public 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;
+	}
+
+}

+ 54 - 0
app_modular/apputils/src/main/java/com/modular/apputils/utils/playsdk/PayResult.java

@@ -0,0 +1,54 @@
+package com.modular.apputils.utils.playsdk;
+
+import java.util.Map;
+
+import android.text.TextUtils;
+
+public class PayResult {
+	private String resultStatus;
+	private String result;
+	private String memo;
+
+	public PayResult(Map<String, String> rawResult) {
+		if (rawResult == null) {
+			return;
+		}
+
+		for (String key : rawResult.keySet()) {
+			if (TextUtils.equals(key, "resultStatus")) {
+				resultStatus = rawResult.get(key);
+			} else if (TextUtils.equals(key, "result")) {
+				result = rawResult.get(key);
+			} else if (TextUtils.equals(key, "memo")) {
+				memo = rawResult.get(key);
+			}
+		}
+	}
+
+	@Override
+	public String toString() {
+		return "resultStatus={" + resultStatus + "};memo={" + memo
+				+ "};result={" + result + "}";
+	}
+
+	/**
+	 * @return the resultStatus
+	 */
+	public String getResultStatus() {
+		return resultStatus;
+	}
+
+	/**
+	 * @return the memo
+	 */
+	public String getMemo() {
+		return memo;
+	}
+
+	/**
+	 * @return the result
+	 */
+	public String getResult() {
+		return result;
+	}
+}

+ 44 - 0
app_modular/apputils/src/main/java/com/modular/apputils/utils/playsdk/SignUtils.java

@@ -0,0 +1,44 @@
+package com.modular.apputils.utils.playsdk;
+
+import java.security.KeyFactory;
+import java.security.PrivateKey;
+import java.security.spec.PKCS8EncodedKeySpec;
+
+public class SignUtils {
+
+	private static final String ALGORITHM = "RSA";
+
+	private static final String SIGN_ALGORITHMS = "SHA1WithRSA";
+
+	private static final String SIGN_SHA256RSA_ALGORITHMS = "SHA256WithRSA";
+
+	private static final String DEFAULT_CHARSET = "UTF-8";
+
+	private static String getAlgorithms(boolean rsa2) {
+		return rsa2 ? SIGN_SHA256RSA_ALGORITHMS : SIGN_ALGORITHMS;
+	}
+	
+	public static String sign(String content, String privateKey, boolean rsa2) {
+		try {
+			PKCS8EncodedKeySpec priPKCS8 = new PKCS8EncodedKeySpec(
+					Base64.decode(privateKey));
+			KeyFactory keyf = KeyFactory.getInstance(ALGORITHM);
+			PrivateKey priKey = keyf.generatePrivate(priPKCS8);
+
+			java.security.Signature signature = java.security.Signature
+					.getInstance(getAlgorithms(rsa2));
+
+			signature.initSign(priKey);
+			signature.update(content.getBytes(DEFAULT_CHARSET));
+
+			byte[] signed = signature.sign();
+
+			return Base64.encode(signed);
+		} catch (Exception e) {
+			e.printStackTrace();
+		}
+
+		return null;
+	}
+
+}

+ 46 - 23
app_modular/appworks/src/main/java/com/uas/appworks/OA/platform/fragment/CharitableListFragment.java

@@ -3,59 +3,41 @@ package com.uas.appworks.OA.platform.fragment;
 import android.content.Context;
 import android.content.Intent;
 import android.os.Bundle;
-import android.support.v4.content.ContextCompat;
-import android.support.v7.widget.DefaultItemAnimator;
-import android.support.v7.widget.LinearLayoutManager;
-import android.support.v7.widget.RecyclerView;
 import android.view.LayoutInflater;
 import android.view.Menu;
 import android.view.MenuInflater;
 import android.view.MenuItem;
 import android.view.View;
-import android.view.ViewGroup;
-import android.view.ViewTreeObserver;
 import android.widget.AdapterView;
-import android.widget.Button;
 import android.widget.GridView;
-import android.widget.ImageView;
-import android.widget.LinearLayout;
-import android.widget.ListView;
 import android.widget.TextView;
-import android.widget.Toast;
 
 import com.alibaba.fastjson.JSON;
 import com.alibaba.fastjson.JSONArray;
 import com.alibaba.fastjson.JSONObject;
-import com.baidu.mapapi.model.LatLng;
 import com.common.LogUtil;
 import com.common.config.BaseConfig;
 import com.common.data.JSONUtil;
 import com.common.data.ListUtils;
 import com.core.app.Constants;
-import com.core.app.MyApplication;
 import com.core.base.BaseActivity;
 import com.core.base.EasyFragment;
-import com.core.utils.BaiduMapUtil;
-import com.core.utils.DistanceUtils;
 import com.core.utils.IntentUtils;
 import com.core.utils.ToastUtil;
-import com.core.widget.MyListView;
 import com.handmark.pulltorefresh.library.PullToRefreshBase;
 import com.handmark.pulltorefresh.library.PullToRefreshListView;
 import com.me.network.app.http.HttpClient;
 import com.me.network.app.http.Method;
 import com.me.network.app.http.rx.ResultListener;
 import com.me.network.app.http.rx.ResultSubscriber;
-import com.modular.apputils.widget.AutoPagerAdapter;
+import com.modular.apputils.listener.OnPlayListener;
+import com.modular.apputils.utils.playsdk.AliLoadPlayApi;
+import com.modular.apputils.utils.playsdk.AliPlay;
 import com.modular.apputils.widget.AutoPagerIndicator;
 import com.modular.apputils.widget.CustomerBanner;
-import com.modular.apputils.widget.SrollViewPager;
-import com.modular.apputils.widget.ViewPagerIndicator;
-import com.nostra13.universalimageloader.core.ImageLoader;
 import com.uas.appworks.OA.platform.activity.CharitSearchActivity;
 import com.uas.appworks.OA.platform.adapter.AutoPlayPagerAdapter;
 import com.uas.appworks.OA.platform.adapter.CharitableAdapter;
-import com.uas.appworks.OA.platform.adapter.CharitableListAdapter;
 import com.uas.appworks.OA.platform.adapter.TypeAdapter;
 import com.uas.appworks.OA.platform.model.Carousel;
 import com.uas.appworks.OA.platform.model.CharitModel;
@@ -70,7 +52,7 @@ import java.util.List;
  * Created by Bitlike on 2017/11/7.
  */
 
-public class CharitableListFragment extends EasyFragment {
+public class CharitableListFragment extends EasyFragment implements OnPlayListener {
 	private HttpClient httpClient = new HttpClient.Builder(Constants.charitBaseUrl()).isDebug(true).build();
 	private TextView moneyAmountTv;
 	private CustomerBanner banner;
@@ -78,6 +60,8 @@ public class CharitableListFragment extends EasyFragment {
 	private BaseActivity baseActivity;
 	private PullToRefreshListView refreshListView;
 
+	private boolean playing = false;
+
 	@Override
 	public void onAttach(Context context) {
 		super.onAttach(context);
@@ -277,7 +261,7 @@ public class CharitableListFragment extends EasyFragment {
 			charitableAdapter = new CharitableAdapter(ct, models, new CharitableAdapter.MyClickListener() {
 				@Override
 				public void myOnClick(int position, View v) {
-					ToastUtil.showToast(ct, "点击了我要捐款=" + position);
+					loadOrderInfo(charitableAdapter.getModels(position));
 				}
 			});
 			refreshListView.setAdapter(charitableAdapter);
@@ -297,4 +281,43 @@ public class CharitableListFragment extends EasyFragment {
 		}
 	}
 
+
+	private void loadOrderInfo(CharitModel model) {
+		if (model == null) {
+			ToastUtil.showToast(ct, "内部错误");
+			return;
+		}
+		if (playing) {
+			ToastUtil.showToast(ct, "目前正在支付,请稍后!!!!");
+			return;
+		}
+		playing = true;
+		//TODO 从接口获取oderInfo
+		String orderInfo = getTestOrderInfo();
+		toPlay(orderInfo);
+
+	}
+
+	private void toPlay(String orderInfo) {
+		AliPlay.api().alipay(getActivity(), orderInfo, this);
+	}
+
+	@Override
+	public void onSuccess(String resultStatus, String resultInfo) {
+		ToastUtil.showToast(ct, "支付成功");
+		playing = false;
+	}
+
+	@Override
+	public void onFailure(String resultStatus, String resultInfo) {
+		ToastUtil.showToast(ct, "支付失败了");
+		playing = false;
+	}
+
+
+	//TODO test 本地获取订单信息
+	private String getTestOrderInfo() {
+		return TestString.ORDER_INFO;
+//		new AliLoadPlayApi().getLoadOrderInfo();
+	}
 }

+ 3 - 0
app_modular/appworks/src/main/java/com/uas/appworks/OA/platform/model/TestString.java

@@ -84,4 +84,7 @@ public class TestString {
 			"\t\"sumActJoin\": 12,\n" +
 			"\t\"sumProJoin\": 12\n" +
 			"}";
+
+
+	public static String ORDER_INFO="alipay_sdk=alipay-sdk-java-dynamicVersionNo&app_id=2016081600255841&biz_content=%7B%22body%22%3A%22%E6%88%91%E6%98%AF%E6%B5%8B%E8%AF%95%E6%95%B0%E6%8D%AE%22%2C%22out_trade_no%22%3A%2265F1DD5E612%22%2C%22product_code%22%3A%22QUICK_MSECURITY_PAY%22%2C%22subject%22%3A%22App%E6%94%AF%E4%BB%98%E6%B5%8B%E8%AF%95Java%22%2C%22timeout_express%22%3A%2230m%22%2C%22total_amount%22%3A%220.01%22%7D&charset=UTF-8&format=json&method=alipay.trade.app.pay&notify_url=%E5%95%86%E6%88%B7%E5%A4%96%E7%BD%91%E5%8F%AF%E4%BB%A5%E8%AE%BF%E9%97%AE%E7%9A%84%E5%BC%82%E6%AD%A5%E5%9C%B0%E5%9D%80&sign=C0sJ76k4KTnDVqnWRmnZQI%2FVVl9gX7OQaatNmFmCJ4TS%2Bm0aDBLCT2kAvAvBq%2FNaqcy5UAqEjhczTq0rOPCPwjjoWIOJ6jsRglasCp4THlCi3rCq4vmkou7zMQf1s1fd%2FqMwBgKkAa1PGs6gRcng2s01YMoZuf9fey3d4KGiUae95xtFoW8ngmr62DT8kyrndpUYw2n0B5SV0RufwdQnJdSaqgt26HJ0i%2BPQi4yZkLiy0IxhUcFlTvDpxERPVJO3sqEiGg0MB0r5e4yzStH%2FR047rOwxHOnF9COytaUWvCkBTPoKHJvMx32sFSlBotDQ%2BtzmLCNsSb6ab0B3weJMtQ%3D%3D&sign_type=RSA2&timestamp=2017-11-13+17%3A33%3A14&version=1.0";
 }

+ 74 - 0
app_modular/appworks/src/main/java/com/uas/appworks/widget/SelectPlayPop.java

@@ -0,0 +1,74 @@
+package com.uas.appworks.widget;
+
+import android.app.Activity;
+import android.content.Context;
+import android.text.Editable;
+import android.text.TextUtils;
+import android.view.Gravity;
+import android.view.LayoutInflater;
+import android.view.View;
+import android.widget.CheckBox;
+import android.widget.EditText;
+import android.widget.PopupWindow;
+import android.widget.TextView;
+
+import com.common.data.StringUtil;
+import com.common.system.DisplayUtil;
+import com.core.utils.ToastUtil;
+import com.core.widget.listener.EditChangeListener;
+import com.modular.apputils.widget.DivideRadioGroup;
+import com.uas.appworks.R;
+
+/**
+ * Created by Bitlike on 2017/11/13.
+ */
+
+public class SelectPlayPop {
+
+
+	public void show(final Activity ct, String name) {
+		final PopupWindow window = new PopupWindow(ct);
+		View view = LayoutInflater.from(ct).inflate(R.layout.pop_play_select, null);
+		window.setContentView(view);
+		window.getContentView().measure(0, 0);
+		window.setHeight(DisplayUtil.dip2px(ct, 270));
+		window.setWidth(DisplayUtil.getSreechWidth((Activity) ct));
+		initView(ct, view, name == null ? "" : name);
+//		window.setBackgroundDrawable(ct.getResources().getDrawable(R.drawable.pop_round_bg));
+		DisplayUtil.backgroundAlpha(ct, 0.4f);
+		window.setTouchable(true);
+		window.setOutsideTouchable(false);
+		window.setFocusable(true);
+		window.setOnDismissListener(new PopupWindow.OnDismissListener() {
+			@Override
+			public void onDismiss() {
+				DisplayUtil.backgroundAlpha(ct, 1f);
+			}
+		});
+		window.showAtLocation(view, Gravity.CENTER, 0, 0);
+	}
+
+
+	private void initView(final Context ct, View view, String name) {
+		TextView nameTv = (TextView) view.findViewById(R.id.nameTv);
+		nameTv.setText(name);
+		final EditText autoNumEd = (EditText) view.findViewById(R.id.autoNumEd);
+		final CheckBox agreeCb = (CheckBox) view.findViewById(R.id.autoNumEd);
+		final DivideRadioGroup selectRg = (DivideRadioGroup) view.findViewById(R.id.selectRg);
+		final DivideRadioGroup typeRg = (DivideRadioGroup) view.findViewById(R.id.typeRg);
+		view.findViewById(R.id.giftBtn).setOnClickListener(new View.OnClickListener() {
+			@Override
+			public void onClick(View view) {
+				if (agreeCb.isChecked()) {
+					giftBtn(autoNumEd, selectRg, typeRg);
+				} else {
+					ToastUtil.showToast(ct, "同意才行哟");
+				}
+			}
+		});
+	}
+
+	private synchronized void giftBtn(EditText autoNumEd, DivideRadioGroup selectRg, DivideRadioGroup typeRg) {
+	}
+
+}

+ 7 - 0
app_modular/appworks/src/main/res/drawable/pop_text_color_bg.xml

@@ -0,0 +1,7 @@
+<?xml version="1.0" encoding="utf-8"?>
+<selector xmlns:android="http://schemas.android.com/apk/res/android">
+
+    <item android:color="@color/indianred" android:state_checked="true" />
+    <item android:color="@color/text_hine" />
+
+</selector>

+ 5 - 0
app_modular/appworks/src/main/res/drawable/pop_text_frame_bg.xml

@@ -0,0 +1,5 @@
+<?xml version="1.0" encoding="utf-8"?>
+<selector xmlns:android="http://schemas.android.com/apk/res/android">
+    <item android:drawable="@drawable/text_frame_red_bg"     android:state_checked="true" android:state_enabled="true"/>
+    <item android:drawable="@drawable/text_frame_bg"/>
+</selector>

+ 10 - 0
app_modular/appworks/src/main/res/drawable/text_frame_red_bg.xml

@@ -0,0 +1,10 @@
+<?xml version="1.0" encoding="utf-8"?>
+<selector xmlns:android="http://schemas.android.com/apk/res/android">
+    <item>
+        <shape>
+            <solid android:color="@color/white" />
+            <stroke android:width="@dimen/line" android:color="@color/indianred" />
+            <padding android:bottom="2dp" android:left="2dp" android:right="2dp" android:top="2dp" />
+        </shape>
+    </item>
+</selector>

+ 208 - 0
app_modular/appworks/src/main/res/layout/pop_play_select.xml

@@ -0,0 +1,208 @@
+<?xml version="1.0" encoding="utf-8"?>
+<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
+    android:layout_width="match_parent"
+    android:layout_height="270dp"
+    android:padding="@dimen/padding">
+
+    <TextView
+        android:id="@+id/nameTv"
+        android:layout_width="wrap_content"
+        android:layout_height="wrap_content"
+        android:text="周杰伦"
+        android:textColor="@color/text_main"
+        android:textSize="@dimen/text_main" />
+
+    <TextView
+        android:layout_width="wrap_content"
+        android:layout_height="wrap_content"
+        android:layout_alignBottom="@id/nameTv"
+        android:layout_marginLeft="10dp"
+        android:layout_toLeftOf="@id/infoTag"
+        android:layout_toRightOf="@id/nameTv"
+        android:text="一份爱心,一份温暖"
+        android:textColor="@color/hintColor"
+        android:textSize="@dimen/text_hine" />
+
+
+    <com.modular.apputils.widget.DivideRadioGroup
+        android:id="@+id/selectRg"
+        android:layout_width="match_parent"
+        android:layout_height="wrap_content"
+        android:layout_below="@id/nameTv"
+        android:baselineAligned="false"
+        android:gravity="bottom"
+        android:orientation="horizontal"
+        android:paddingBottom="4dp"
+        android:paddingTop="4dp">
+
+        <RadioButton
+            style="@style/IMTabButton"
+            android:layout_width="0dp"
+            android:layout_height="match_parent"
+            android:layout_marginLeft="5dp"
+            android:layout_marginRight="5dp"
+            android:layout_weight="1"
+            android:background="@drawable/pop_text_frame_bg"
+            android:checked="true"
+            android:padding="10dp"
+            android:paddingTop="3dp"
+            android:text="1元"
+            android:textColor="@drawable/pop_text_color_bg" />
+
+
+        <RadioButton
+            style="@style/IMTabButton"
+            android:layout_width="0dp"
+            android:layout_height="match_parent"
+            android:layout_marginLeft="5dp"
+            android:layout_marginRight="5dp"
+            android:layout_weight="1"
+            android:background="@drawable/pop_text_frame_bg"
+            android:padding="10dp"
+            android:paddingTop="3dp"
+            android:text="2元"
+            android:textColor="@drawable/pop_text_color_bg" />
+
+        <RadioButton
+            style="@style/IMTabButton"
+            android:layout_width="0dp"
+            android:layout_height="match_parent"
+            android:layout_marginLeft="5dp"
+            android:layout_marginRight="5dp"
+            android:layout_weight="1"
+            android:background="@drawable/pop_text_frame_bg"
+            android:padding="10dp"
+            android:paddingTop="3dp"
+            android:text="5元"
+            android:textColor="@drawable/pop_text_color_bg" />
+
+        <RadioButton
+            style="@style/IMTabButton"
+            android:layout_width="0dp"
+            android:layout_height="match_parent"
+            android:layout_marginLeft="5dp"
+            android:layout_marginRight="5dp"
+            android:layout_weight="1"
+            android:background="@drawable/pop_text_frame_bg"
+            android:padding="10dp"
+            android:paddingTop="3dp"
+            android:text="10元"
+            android:textColor="@drawable/pop_text_color_bg" />
+
+    </com.modular.apputils.widget.DivideRadioGroup>
+
+
+    <RelativeLayout
+        android:id="@+id/autoRl"
+        android:layout_width="wrap_content"
+        android:layout_height="wrap_content"
+        android:layout_below="@id/selectRg"
+        android:layout_margin="@dimen/padding"
+        android:layout_marginLeft="10dp"
+        android:background="@drawable/text_frame_bg"
+        android:padding="@dimen/padding">
+
+        <EditText
+            android:id="@+id/autoNumEd"
+            android:layout_width="wrap_content"
+            android:layout_height="wrap_content"
+            android:background="@null"
+            android:hint="自定义金额"
+            android:minWidth="40dp"
+            android:textSize="@dimen/text_main" />
+
+        <TextView
+            android:layout_width="wrap_content"
+            android:layout_height="wrap_content"
+            android:layout_marginLeft="20dp"
+            android:layout_toRightOf="@+id/autoNumEd"
+            android:text="元"
+            android:textColor="@color/indianred"
+            android:textSize="@dimen/text_main" />
+    </RelativeLayout>
+
+
+    <TextView
+        android:id="@+id/typeTv"
+        android:layout_width="wrap_content"
+        android:layout_height="wrap_content"
+        android:layout_alignLeft="@id/autoRl"
+        android:layout_below="@id/autoRl"
+        android:layout_marginTop="10dp"
+        android:paddingTop="10dp"
+        android:text="付款方式:"
+        android:textColor="@color/text_main"
+        android:textSize="@dimen/text_main" />
+
+    <com.modular.apputils.widget.DivideRadioGroup
+        android:id="@+id/typeRg"
+        android:layout_width="match_parent"
+        android:layout_height="wrap_content"
+        android:layout_alignTop="@id/typeTv"
+        android:layout_marginLeft="10dp"
+        android:layout_marginRight="20dp"
+        android:layout_toRightOf="@id/typeTv"
+        android:baselineAligned="false"
+        android:gravity="bottom"
+        android:orientation="horizontal"
+        android:paddingBottom="4dp"
+        android:paddingTop="4dp">
+
+        <RadioButton
+            style="@style/IMTabButton"
+            android:layout_width="0dp"
+            android:layout_height="match_parent"
+            android:layout_marginLeft="5dp"
+            android:layout_marginRight="5dp"
+            android:layout_weight="1"
+            android:background="@drawable/pop_text_frame_bg"
+            android:checked="true"
+            android:padding="10dp"
+            android:paddingTop="3dp"
+            android:text="微信"
+            android:textColor="@drawable/pop_text_color_bg" />
+
+
+        <RadioButton
+            style="@style/IMTabButton"
+            android:layout_width="0dp"
+            android:layout_height="match_parent"
+            android:layout_marginLeft="5dp"
+            android:layout_marginRight="5dp"
+            android:layout_weight="1"
+            android:background="@drawable/pop_text_frame_bg"
+            android:padding="10dp"
+            android:paddingTop="3dp"
+            android:text="支付宝"
+            android:textColor="@drawable/pop_text_color_bg" />
+
+
+    </com.modular.apputils.widget.DivideRadioGroup>
+
+
+    <CheckBox
+        android:id="@+id/agreeCb"
+        android:layout_width="wrap_content"
+        android:layout_height="wrap_content"
+        android:layout_below="@id/typeTv"
+        android:layout_marginLeft="10dp"
+        android:layout_marginTop="20dp"
+        android:button="@drawable/oa_checkbox"
+        android:drawablePadding="@dimen/padding"
+        android:text="同意并接受"
+        android:textColor="@color/hintColor"
+        android:textSize="@dimen/text_main" />
+
+    <TextView
+        android:id="@+id/giftBtn"
+        android:layout_width="match_parent"
+        android:layout_height="wrap_content"
+        android:layout_alignParentBottom="true"
+        android:layout_below="@id/agreeCb"
+        android:layout_marginTop="@dimen/padding"
+        android:background="@color/indianred"
+        android:gravity="center"
+        android:padding="8dp"
+        android:text="立即捐款"
+        android:textColor="@color/white" />
+</RelativeLayout>