1、效果图:
2、SDK下载:https://docs.open.alipay.com/54/104509/
解压文件将alipaySdk-20180316.jar复制到自己项目libs目录下,并Add As Library
3、AndroidManifest.xml 清单文件添加如下
<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"/>
4、MainActivity.java:
public class MainActivity extends AppCompatActivity {
/**
* 支付宝支付业务
*/
private String orderSign;
private static final String TAG = "MainActivity";
private static final int SDK_PAY_FLAG = 1;
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
findViewById(R.id.pay_btn).setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View v) {
ZfbPayBean data = new ZfbPayBean();
data.setSign("P7gKQBzVP5TP/GI75PPvRo9cZy4pATUl......");
data.set_input_charset("UTF-8");
data.setBody("2c9213d7613195290166666666666666");
data.setNotify_url("http://192.168.0.0/pay/callback/alipay");
data.setOut_trade_no("1522366666666");
data.setPartner("2088826666666666");
data.setPayment_type("1");
data.setSeller_id("123456789@qq.com");
data.setService("mobile.securitypay.pay");
data.setSubject("Hello Word支付");
data.setTotal_fee("0.01");
data.setSign_type("RSA");
startPay(data);
}
});
}
/**
* 开始支付
*/
private void startPay(ZfbPayBean data) {
//签名(https://docs.open.alipay.com/59/103927)
String sign = data.getSign();
//格式
String utf_8 = data.get_input_charset();
//类型
String type = "&sign_type=\"" + data.getSign_type() + "\"";
try {
orderSign = URLEncoder.encode(sign, utf_8);
} catch (UnsupportedEncodingException e) {
e.printStackTrace();
}
String orderInfo = getOrderInfo(data);
//其中sign已加签可穿可不传
final String payInfo = orderInfo + "&sign=\"" + orderSign;
//final String payInfo = orderInfo + "&sign=\"" + orderSign + type;
Log.e(TAG, "startPay: 支付订单信息:" + payInfo);
Runnable payRunnable = new Runnable() {
@Override
public void run() {
PayTask alipay = new PayTask(MainActivity.this);
//参数1:app支付请求参数字符串,主要包含商户的订单信息,key=value形式,以&连接。
//参数2:优化点击付款到支付唤起支付页面的过渡过程。(加载loading)
//1.后台直接返回一个数组值以key= "value"进行组合
//Map<String, String> result = alipay.payV2(payInfo, true);
//2.前端自行拼接
String result = alipay.pay(payInfo, true);
Message msg = new Message();
msg.what = SDK_PAY_FLAG;
msg.obj = result;
mHandler.sendMessage(msg);
}
};
// 必须异步调用
Thread payThread = new Thread(payRunnable);
payThread.start();
}
private Handler mHandler = new Handler() {
public void handleMessage(Message msg) {
switch (msg.what) {
case SDK_PAY_FLAG: {
PayResult payResult = new PayResult((String) msg.obj);
/**
*对于支付结果,请商户依赖服务端的异步通知结果。同步通知结果,仅作为支付结束的通知。
*https://docs.open.alipay.com/59/103665
*/
String resultInfo = payResult.getResult();// 同步返回需要验证的信息
String resultStatus = payResult.getResultStatus();//返回的状态
Log.e(TAG, "支付验证的信息:" + resultInfo);
Log.e(TAG, "支付验证的状态码:" + resultStatus);
// 判断resultStatus 为9000则代表支付成功
if (TextUtils.equals(resultStatus, "9000")) {
//注意: 该笔订单是否真实支付成功,需要依赖服务端的异步通知。
Log.e(TAG, "handleMessage: 支付成功");
} else if (TextUtils.equals(resultStatus, "8000")) {
// "8000"代表支付结果因为支付渠道原因或者系统原因还在等待支付结果确认,
// 最终交易是否成功以服务端异步通知为准(小概率状态)
Log.e(TAG, "handleMessage: 支付结果确认中");
} else if (TextUtils.equals(resultStatus, "6001")) {
// 用户中途取消
Log.e(TAG, "handleMessage: 支付取消");
} else if (TextUtils.equals(resultStatus, "6002")) {
// 网络连接出错
Log.e(TAG, "handleMessage: 网络连接出错");
} else {
Log.e(TAG, "handleMessage: 支付失败");
}
break;
}
}
}
};
private String getOrderInfo(ZfbPayBean data) {
String orderInfo = "_input_charset=\"" + data.get_input_charset() + "\"";
// 商品详情
orderInfo += "&body=\"" + data.getBody() + "\"";
// 服务器异步通知页面路径
orderInfo += "¬ify_url=\"" + data.getNotify_url() + "\"";
// 商户网站唯一订单号
orderInfo += "&out_trade_no=\"" + data.getOut_trade_no() + "\"";
// 签约合作者身份ID
orderInfo += "&partner=\"" + data.getPartner() + "\"";
// 支付类型, 固定值
orderInfo += "&payment_type=\"" + data.getPayment_type() + "\"";
// 签约卖家支付宝账号
orderInfo += "&seller_id=\"" + data.getSeller_id() + "\"";
// 服务接口名称, 固定值
orderInfo += "&service=\"" + data.getService() + "\"";
// 商品名称
orderInfo += "&subject=\"" + data.getSubject() + "\"";
// 商品金额
orderInfo += "&total_fee=\"" + data.getTotal_fee() + "\"";
return orderInfo;
}
}
布局文件:activity_main.xml
<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:tools="http://schemas.android.com/tools"
android:layout_width="match_parent"
android:layout_height="match_parent"
tools:context=".MainActivity">
<Button
android:id="@+id/pay_btn"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:text="开始支付" />
</LinearLayout>
注意:其中返回格式有2种,分别对应上文中的1和2方法
1、无需拼接,直接传入data 即可
2、自行拼接
5、对应实体ZfbPayBean.java
public class ZfbPayBean {
private String _input_charset;
private String body;
private String notify_url;
private String out_trade_no;
private String partner;
private String payment_type;
private String seller_id;
private String service;
private String sign;
private String sign_type;
private String total_fee;
public String subject;
public String getSubject() {
return subject;
}
public void setSubject(String subject) {
this.subject = subject;
}
public String get_input_charset() {
return _input_charset;
}
public void set_input_charset(String _input_charset) {
this._input_charset = _input_charset;
}
public String getBody() {
return body;
}
public void setBody(String body) {
this.body = body;
}
public String getNotify_url() {
return notify_url;
}
public void setNotify_url(String notify_url) {
this.notify_url = notify_url;
}
public String getOut_trade_no() {
return out_trade_no;
}
public void setOut_trade_no(String out_trade_no) {
this.out_trade_no = out_trade_no;
}
public String getPartner() {
return partner;
}
public void setPartner(String partner) {
this.partner = partner;
}
public String getPayment_type() {
return payment_type;
}
public void setPayment_type(String payment_type) {
this.payment_type = payment_type;
}
public String getSeller_id() {
return seller_id;
}
public void setSeller_id(String seller_id) {
this.seller_id = seller_id;
}
public String getService() {
return service;
}
public void setService(String service) {
this.service = service;
}
public String getSign() {
return sign;
}
public void setSign(String sign) {
this.sign = sign;
}
public String getSign_type() {
return sign_type;
}
public void setSign_type(String sign_type) {
this.sign_type = sign_type;
}
public String getTotal_fee() {
return total_fee;
}
public void setTotal_fee(String total_fee) {
this.total_fee = total_fee;
}
}
6、PayResult.java
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;
}
}