目錄
效果圖
關於官方的Demo
這裏我們先跑一個官方給的demo試試
進入開發者平臺
沙箱應用
創建一個沙箱應用
關鍵信息:APPID、UID、商家賬號
下載他的沙箱版支付寶
如果是在模擬器運行的代碼記得把這個沙箱版安裝在模擬器裏面
下載完成之後,可以登錄(賬號在上面截圖的位置,每個人創建的應用不同賬號也不同)進去看看,也給以試着往裏面加錢,最大可以加999999999…吧…好像,要是真的就好了。。。
下載官方給的SDK
下載地址
下載解壓後有幾個文件(和以前的老版不一樣,這個坑…老版教程不適用)
Android_Demo這個文件夾打開後的文件直接導入在Android studio裏面打開
導入官方給的Demo
文件結構如下圖
然後複製Android_SDK這個文件夾下的aar文件
導入SDK
指導文檔
給出了新版SDK也就是後綴爲aar文件和之前老版jar文件的導入區別,跟着文檔來,記錄一下:下面這個語句要改一下,因爲文檔的name和自己下的sdk版本名稱可能不一致導致報錯,最後同步一下項目(我的和你的版本可能也不一樣,自己對着自己的版本改)
// 添加下面的內容
implementation (name: 'alipaysdk-15.8.00.201112210139', ext: 'aar')
修改APPID、PID、TARGET_ID
在PayDemoActivity這個類下修改相關參數
RSA2_PRIVATE問題也就是這個沙箱的公鑰和私鑰
這個要從這個軟件裏面獲取
下載密鑰工具
下載後打開工具
將生成的應用公鑰複製到之前的沙箱應用管理裏面
再複製之前工具生成的私鑰放進代碼裏面
看文檔好像是說的2048字節長度
最後加入這條語句EnvUtils.setEnv(EnvUtils.EnvEnum.SANDBOX);在onCreate()方法裏面
應該可以運行成功的
然後下面就是改一下部署到自己項目裏面
效果圖的代碼
SDK導入方式和前面說的一樣,再然後就是將官方給的demo裏面的這幾個文件複製進自己項目
activity佈局文件
<?xml version="1.0" encoding="utf-8"?>
<androidx.constraintlayout.widget.ConstraintLayout xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:app="http://schemas.android.com/apk/res-auto"
xmlns:tools="http://schemas.android.com/tools"
android:layout_width="match_parent"
android:layout_height="match_parent"
tools:context="com.example.newapplication.MainActivity">
<androidx.constraintlayout.widget.ConstraintLayout
android:id="@+id/constraintLayout"
android:layout_width="match_parent"
android:layout_height="140dp"
android:layout_marginStart="10dp"
android:layout_marginLeft="10dp"
android:layout_marginTop="20dp"
android:layout_marginEnd="10dp"
android:layout_marginRight="10dp"
android:background="@drawable/activity_search_tv_shape"
app:layout_constraintEnd_toEndOf="parent"
app:layout_constraintStart_toStartOf="parent"
app:layout_constraintTop_toTopOf="parent"><!--這個background可以刪-->
<ImageView
android:id="@+id/imageView"
android:layout_width="100dp"
android:layout_height="100dp"
android:layout_marginStart="15dp"
android:layout_marginLeft="15dp"
android:src="@drawable/ma"
app:layout_constraintBottom_toBottomOf="parent"
app:layout_constraintStart_toStartOf="parent"
app:layout_constraintTop_toTopOf="parent" />
<TextView
android:id="@+id/textView"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="二維碼"
android:textColor="#555555"
android:textSize="20sp"
app:layout_constraintEnd_toEndOf="parent"
app:layout_constraintStart_toEndOf="@+id/imageView"
app:layout_constraintTop_toTopOf="@+id/imageView" />
<TextView
android:id="@+id/textView2"
android:layout_width="260dp"
android:layout_height="wrap_content"
android:layout_marginStart="5dp"
android:layout_marginLeft="5dp"
android:ellipsize="end"
android:lines="2"
android:text="二維碼又稱二維條碼,常見的二維碼爲QR Code,QR全稱Quick Response,是一個近幾年來移動設備上超流行的一種編碼方式,它比傳統的Bar Code條形碼能存更多的信息,也能表示更多的數據類型"
android:textColor="#666666"
android:textSize="18sp"
app:layout_constraintEnd_toEndOf="parent"
app:layout_constraintStart_toEndOf="@+id/imageView"
app:layout_constraintTop_toBottomOf="@+id/textView" />
<TextView
android:id="@+id/textView3"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="價格:"
android:textColor="#333333"
app:layout_constraintBottom_toBottomOf="parent"
app:layout_constraintEnd_toStartOf="@+id/price"
app:layout_constraintTop_toBottomOf="@+id/textView2"
app:layout_constraintVertical_bias="0.65999997" />
<TextView
android:id="@+id/price"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_marginEnd="20dp"
android:layout_marginRight="20dp"
android:text="¥1599.00"
android:textColor="#D81E06"
app:layout_constraintBottom_toBottomOf="@+id/textView3"
app:layout_constraintEnd_toEndOf="@+id/textView2"
app:layout_constraintTop_toTopOf="@+id/textView3"
app:layout_constraintVertical_bias="0.0" />
</androidx.constraintlayout.widget.ConstraintLayout>
<Button
android:id="@+id/button"
android:layout_width="match_parent"
android:layout_height="50dp"
android:layout_marginTop="10dp"
android:text="支付"
android:textSize="25sp"
app:layout_constraintEnd_toEndOf="parent"
app:layout_constraintStart_toStartOf="parent"
app:layout_constraintTop_toBottomOf="@+id/constraintLayout" />
</androidx.constraintlayout.widget.ConstraintLayout>
MainActivity文件
package com.example.newapplication;
import androidx.appcompat.app.AppCompatActivity;
import android.annotation.SuppressLint;
import android.app.AlertDialog;
import android.content.Context;
import android.content.DialogInterface;
import android.os.Bundle;
import android.os.Handler;
import android.os.Message;
import android.text.TextUtils;
import android.util.Log;
import android.view.LayoutInflater;
import android.view.View;
import android.view.ViewGroup;
import android.widget.Button;
import android.widget.LinearLayout;
import android.widget.TextView;
import android.widget.Toast;
import com.alipay.sdk.app.EnvUtils;
import com.alipay.sdk.app.PayTask;
import java.util.Map;
public class MainActivity extends AppCompatActivity {
/**
* 用於支付寶支付業務的入參 app_id。
*/
public static final String APPID = "202100011******4";//參數都填自己的
/**
* 用於支付寶賬戶登錄授權業務的入參 pid。
*/
public static final String PID = "208862195******4";
/**
* 用於支付寶賬戶登錄授權業務的入參 target_id。
*/
public static final String TARGET_ID = "lvuk******.com";
/**
* pkcs8 格式的商戶私鑰。
*
* 如下私鑰,RSA2_PRIVATE 或者 RSA_PRIVATE 只需要填入一個,如果兩個都設置了,本 Demo 將優先
* 使用 RSA2_PRIVATE。RSA2_PRIVATE 可以保證商戶交易在更加安全的環境下進行,建議商戶使用
* RSA2_PRIVATE。
*
* 建議使用支付寶提供的公私鑰生成工具生成和獲取 RSA2_PRIVATE。
* 工具地址:https://doc.open.alipay.com/docs/doc.htm?treeId=291&articleId=106097&docType=1
*/
public static final String RSA2_PRIVATE = "填自己工具生成的私鑰";
public static final String RSA_PRIVATE = "";//不用填
private static final int SDK_PAY_FLAG = 1;
private static final int SDK_AUTH_FLAG = 2;
@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")) {
// 該筆訂單是否真實支付成功,需要依賴服務端的異步通知。
showAlert(MainActivity.this, getString(R.string.pay_success) + payResult);
} else {
// 該筆訂單真實的支付結果,需要依賴服務端的異步通知。
showAlert(MainActivity.this, getString(R.string.pay_failed) + payResult);
}
break;
}
case SDK_AUTH_FLAG: {
@SuppressWarnings("unchecked")
AuthResult authResult = new AuthResult((Map<String, String>) 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
// 傳入,則支付賬戶爲該授權賬戶
showAlert(MainActivity.this, getString(R.string.auth_success) + authResult);
} else {
// 其他狀態值則爲授權失敗
showAlert(MainActivity.this, getString(R.string.auth_failed) + authResult);
}
break;
}
default:
break;
}
};
};
@Override
protected void onCreate(Bundle savedInstanceState) {
EnvUtils.setEnv(EnvUtils.EnvEnum.SANDBOX);
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
Button button = findViewById(R.id.button);
button.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View v) {
payV2(v);
}
});
}
/**
* 支付寶支付業務示例
*/
public void payV2(View v) {
if (TextUtils.isEmpty(APPID) || (TextUtils.isEmpty(RSA2_PRIVATE) && TextUtils.isEmpty(RSA_PRIVATE))) {
showAlert(this, getString(R.string.error_missing_appid_rsa_private));
return;
}
/*
* 這裏只是爲了方便直接向商戶展示支付寶的整個支付流程;所以Demo中加簽過程直接放在客戶端完成;
* 真實App裏,privateKey等數據嚴禁放在客戶端,加簽過程務必要放在服務端完成;
* 防止商戶私密數據泄露,造成不必要的資金損失,及面臨各種安全風險;
*
* orderInfo 的獲取必須來自服務端;
*/
boolean rsa2 = (RSA2_PRIVATE.length() > 0);
Map<String, String> params = OrderInfoUtil2_0.buildOrderParamMap(APPID, rsa2,"1599.00");
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;
final Runnable payRunnable = new Runnable() {
@Override
public void run() {
PayTask alipay = new PayTask(MainActivity.this);
Map<String, String> result = alipay.payV2(orderInfo, true);
Log.i("msp", result.toString());
Message msg = new Message();
msg.what = SDK_PAY_FLAG;
msg.obj = result;
mHandler.sendMessage(msg);
}
};
// 必須異步調用
Thread payThread = new Thread(payRunnable);
payThread.start();
}
private static void showAlert(Context ctx, String info) {
showAlert(ctx, info, null);
}
private static void showAlert(Context ctx, String info, DialogInterface.OnDismissListener onDismiss) {
new AlertDialog.Builder(ctx)
.setMessage(info)
.setPositiveButton(R.string.confirm, null)
.show();
}
private static void showToast(Context ctx, String msg) {
Toast.makeText(ctx, msg, Toast.LENGTH_LONG).show();
}
private static String bundleToString(Bundle bundle) {
if (bundle == null) {
return "null";
}
final StringBuilder sb = new StringBuilder();
for (String key: bundle.keySet()) {
sb.append(key).append("=>").append(bundle.get(key)).append("\n");
}
return sb.toString();
}
}
有兩處改動
string.xml文件改一下(從官方Demo複製)
改一下剛剛從demo複製的OrderInfoUtil2_0類下的方法,根據需要自己改(訂單的構造方法)
就這樣集成完畢!!!