您的位置:首页 > 移动开发 > Android开发

android支付之支付宝支付

2015-10-23 15:00 731 查看
先导入jar包alipaySDK-20150818

调用支付宝

AlipayUtils.pay(this,mHandler,"订单信息","订单描述","0.01");


接收支付宝的返回结果

/**
* 接收支付宝的返回结果
*/
private Handler mHandler = new Handler() {
public void handleMessage(Message msg) {
switch (msg.what) {
case ConstantValues.SDK_PAY_FLAG: {
PayResult payResult = new PayResult((String) msg.obj);
// 支付宝返回此次支付结果及加签,建议对支付宝签名信息拿签约时支付宝提供的公钥做验签
String resultInfo = payResult.getResult();
String resultStatus = payResult.getResultStatus();
if (TextUtils.equals(resultStatus, "9000")) {
Toast.makeText(MainActivity.this,"支付成功",Toast.LENGTH_SHORT).show();
} else {
if (TextUtils.equals(resultStatus,"8000")) {
Toast.makeText(MainActivity.this,"支付结果确认中",Toast.LENGTH_SHORT).show();
} else if (TextUtils.equals(resultStatus,"6001")){
Toast.makeText(MainActivity.this,"您取消了订单支付",Toast.LENGTH_SHORT).show();
}else if (TextUtils.equals(resultStatus,"6002")){
Toast.makeText(MainActivity.this,"网络连接出错",Toast.LENGTH_SHORT).show();
}else {
Toast.makeText(MainActivity.this,"支付失败",Toast.LENGTH_SHORT).show();
}
}
break;
}
default:
break;
}
};
};


以上是在支付页面中的调用↑

下面是几个必须的页面(类名不要改)

1、Base64

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


2、PayResult

import android.text.TextUtils;

public class PayResult {
private String resultStatus;
private String result;
private String memo;

public PayResult(String rawResult) {

if (TextUtils.isEmpty(rawResult))
return;

String[] resultParams = rawResult.split(";");
for (String resultParam : resultParams) {
if (resultParam.startsWith("resultStatus")) {
resultStatus = gatValue(resultParam, "resultStatus");
}
if (resultParam.startsWith("result")) {
result = gatValue(resultParam, "result");
}
if (resultParam.startsWith("memo")) {
memo = gatValue(resultParam, "memo");
}
}
}

@Override
public String toString() {
return "resultStatus={" + resultStatus + "};memo={" + memo
+ "};result={" + result + "}";
}

private String gatValue(String content, String key) {
String prefix = key + "={";
return content.substring(content.indexOf(prefix) + prefix.length(),
content.lastIndexOf("}"));
}

/**
* @return the resultStatus
*/
public String getResultStatus() {
return resultStatus;
}

/**
* @return the memo
*/
public String getMemo() {
return memo;
}

/**
* @return the result
*/
public String getResult() {
return result;
}
}


3、SignUtils

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 DEFAULT_CHARSET = "UTF-8";

public static String sign(String content, String privateKey) {
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(SIGN_ALGORITHMS);

signature.initSign(priKey);
signature.update(content.getBytes(DEFAULT_CHARSET));

byte[] signed = signature.sign();

return Base64.encode(signed);
} catch (Exception e) {
e.printStackTrace();
}

return null;
}

}


4、AlipayUtils

import java.io.UnsupportedEncodingException;
import java.net.URLEncoder;
import java.text.SimpleDateFormat;
import java.util.Date;
import java.util.Locale;
import java.util.Random;

import android.os.Handler;
import android.os.Message;

import com.alipay.sdk.app.PayTask;
import com.xh.boke.ConstantValues;
import com.xh.boke.base.BaseActivity;

/**
* 支付宝支付工具类
* Created by Administrator on 2015/10/23 0023.
*/
public class AlipayUtils {
/**
* call alipay sdk pay. 调用SDK支付
*/
public static void pay(final BaseActivity activity,final Handler handler,String title,String desc,String price) {
// 订单
String orderInfo = getOrderInfo(title,desc,price);

// 对订单做RSA 签名
String sign = sign(orderInfo);
try {
// 仅需对sign 做URL编码
sign = URLEncoder.encode(sign, "UTF-8");
} catch (UnsupportedEncodingException e) {
e.printStackTrace();
}

// 完整的符合支付宝参数规范的订单信息
final String payInfo = orderInfo + "&sign=\"" + sign + "\"&"
+ getSignType();

Runnable payRunnable = new Runnable() {

@Override
public void run() {
// 构造PayTask 对象
PayTask alipay = new PayTask(activity);
// 调用支付接口,获取支付结果
String result = alipay.pay(payInfo);

Message msg = new Message();
msg.what = ConstantValues.SDK_PAY_FLAG;
msg.obj = result;
handler.sendMessage(msg);
}
};
// 必须异步调用
Thread payThread = new Thread(payRunnable);
payThread.start();
}

/**
* check whether the device has authentication alipay account.
* 查询终端设备是否存在支付宝认证账户
*
*/
public static void check(final BaseActivity activity,final Handler handler) {
Runnable checkRunnable = new Runnable() {

@Override
public void run() {
// 构造PayTask 对象
PayTask payTask = new PayTask(activity);
// 调用查询接口,获取查询结果
boolean isExist = payTask.checkAccountIfExist();

Message msg = new Message();
msg.what = ConstantValues.SDK_CHECK_FLAG;
msg.obj = isExist;
handler.sendMessage(msg);
}
};
Thread checkThread = new Thread(checkRunnable);
checkThread.start();

}

/**
* create the order info. 创建订单信息
*
*/
public static String getOrderInfo(String subject, String body, String price) {
// 签约合作者身份ID
String orderInfo = "partner=" + "\"" + ConstantValues.PARTNER + "\"";

// 签约卖家支付宝账号
orderInfo += "&seller_id=" + "\"" + ConstantValues.SELLER + "\"";

// 商户网站唯一订单号
orderInfo += "&out_trade_no=" + "\"" + getOutTradeNo() + "\"";

// 商品名称
orderInfo += "&subject=" + "\"" + subject + "\"";

// 商品详情
orderInfo += "&body=" + "\"" + body + "\"";

// 商品金额
orderInfo += "&total_fee=" + "\"" + price + "\"";

// 服务器异步通知页面路径
orderInfo += "¬ify_url=" + "\"" + "http://notify.msp.hk/notify.htm"
+ "\"";

// 服务接口名称, 固定值
orderInfo += "&service=\"mobile.securitypay.pay\"";

// 支付类型, 固定值
orderInfo += "&payment_type=\"1\"";

// 参数编码, 固定值
orderInfo += "&_input_charset=\"utf-8\"";

// 设置未付款交易的超时时间
// 默认30分钟,一旦超时,该笔交易就会自动被关闭。
// 取值范围:1m~15d。
// m-分钟,h-小时,d-天,1c-当天(无论交易何时创建,都在0点关闭)。
// 该参数数值不接受小数点,如1.5h,可转换为90m。
orderInfo += "&it_b_pay=\"30m\"";

// extern_token为经过快登授权获取到的alipay_open_id,带上此参数用户将使用授权的账户进行支付
// orderInfo += "&extern_token=" + "\"" + extern_token + "\"";

// 支付宝处理完请求后,当前页面跳转到商户指定页面的路径,可空
orderInfo += "&return_url=\"m.alipay.com\"";

// 调用银行卡支付,需配置此参数,参与签名, 固定值 (需要签约《无线银行卡快捷支付》才能使用)
// orderInfo += "&paymethod=\"expressGateway\"";

return orderInfo;
}

/**
* get the out_trade_no for an order. 生成商户订单号,该值在商户端应保持唯一(可自定义格式规范)
*
*/
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;
}

/**
* sign the order info. 对订单信息进行签名
*
* @param content
*            待签名订单信息
*/
public static String sign(String content) {
return SignUtils.sign(content, ConstantValues.RSA_PRIVATE);
}

/**
* get the sign type we use. 获取签名方式
*
*/
public static String getSignType() {
return "sign_type=\"RSA\"";
}
}


下面是支付宝商户的配置信息

/**
* 常量
* Created by Administrator on 2015/10/23 0023.
*/
public class ConstantValues {
/** 支付宝支付 */
//商户PID
public static final String PARTNER = "";
//商户收款账号
public static final String SELLER = "";
//商户私钥,pkcs8格式
public static final String RSA_PRIVATE = "";
//支付宝公钥
public static final String RSA_PUBLIC = "";
public static final int SDK_PAY_FLAG = 1;
public static final int SDK_CHECK_FLAG = 2;
}


获取公钥和私钥

1、获取公钥和私钥的方法

2、如何上传公钥

另外,在Android Manifest.xml 里面加上这句,在没有安装支付宝的情况下可以跳转一个H5页面进行支付

<!--没安装支付宝时弹出的支付页面-->
<activity
android:name="com.alipay.sdk.app.H5PayActivity"
android:configChanges="orientation|keyboardHidden|navigation"
android:exported="false"
android:screenOrientation="behind"
android:windowSoftInputMode="adjustResize|stateHidden" >
</activity>
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: