Android應用接入微信支付實現支付功能
記得很早以前公司項目中添加過移動支付這一塊, 包括 微信,支付寶,銀聯等第三方的整合。 但是後來懶於總結就沒留下什麼, 最近公司項目打算添加,所以打算簡單總結一下,記上一筆以備將來使用。 畢竟第三方的支付SDK , 一般定下了以後三五年不會改變。 閒話少說,開幹。 集成第三方SDK沒什麼難度,只要我們用心閱讀文檔和開發引導,集成起來再留點神,一切都不是問題。
申請準備材料
首先說一下,微信支付需要在開放平臺進行註冊,申請商戶資質。不是公衆平臺,另外這兩個平臺卻用了同一套賬號體系也就是說,有一個郵箱你註冊公衆平臺,開放平臺就不行了。
先給個官網鏈接https://pay.weixin.qq.com/index.php.
申請商戶的準備工作,需要申請商戶資質的材料也不會特殊,大概都需要以下幾種:
- 單位營業執照彩色掃描件或數碼照片
- 對公銀行賬戶(基本賬戶、一般賬戶均可)
- 法定代表人的身份證彩色掃描件或數碼照片
若爲代理人(即法人以外的公司代表)申請認證,需額外提供以下兩項材料 - 代理人的身份證彩色掃描件或數碼照片
- 委託書,委託書上必須蓋有單位公章或財務專用章(合同專用章、業務專用章等無效)下載委託書模版
- 開發者資質審覈需要299元RMB/年.
申請過程按照微信官網提示進行操作即可,就不在贅述了。
SDK配置
集成過程很簡單,現在一般都使用gradle看一下配置
//下面依賴根據業務需要,任選其一
dependencies {
//包含統計功能
compile 'com.tencent.mm.opensdk:wechat-sdk-android-with-mta:+'
//不包含統計功能,不使用統計功能的話這個就足夠使用了。
compile 'com.tencent.mm.opensdk:wechat-sdk-android-without-mta:+'
}
如果還是用eclipse的話, 就記得把libammsdk.jar 放到libs目錄中, 記得addToBuildPath
下邊是權限配置
<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"/>
下邊就看一下Manifest.xml 文檔配置。
<activity android:name=".wxapi.WXPayEntryActivity"
android:exported="true"
android:launchMode="singleTop" />
這個文件就是支付完成之後微信通過Aidl回調傳送結果的類,所以exported屬性爲true。 另外這個文件的放置目錄一定要準確包名的路徑和AndroidManifest.xml文件中WXPayEntryActivity配置一致 ,微信回調找不到class 就會checkargs出錯,調不起微信。
接下來就看一下代碼吧:
官網SDKDemo下載解壓導入eclipse之後可以看到。一個很簡單的調用過程。
檢查當前的微信版本是否支持.發起req的時候一定要檢測一下sdk是否支持.
Button checkPayBtn = (Button) findViewById(R.id.check_pay_btn);
checkPayBtn.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View v) {
boolean isPaySupported = api.getWXAppSupportAPI() >= Build.PAY_SUPPORTED_SDK_INT;
Toast.makeText(PayActivity.this, String.valueOf(isPaySupported), Toast.LENGTH_SHORT).show();
}
});
下邊看一下發起支付請求的主調用方法
try {
Log.d("get server pay params:", content);
JSONObject json = new JSONObject(content);
if (null != json && !json.has("retcode")) {
PayReq req = new PayReq();
req.appId = Constants.APP_ID;
req.prepayId = json.getString("prepayid");
req.nonceStr = json.getString("noncestr");
req.timeStamp = json.getString("timestamp");
req.packageValue = json.getString("package");
req.sign = json.getString("sign");
req.extData = "app data"; // optional
Toast.makeText(PayActivity.this, "正常調起支付", Toast.LENGTH_SHORT).show();
api.sendReq(req);
} else {
Log.d("PAY_GET", "返回錯誤" + json.getString("retmsg"));
Toast.makeText(PayActivity.this, "返回錯誤" + json.getString("retmsg"), Toast.LENGTH_SHORT).show();
}
} catch (Exception e) {
Log.e("PAY_GET", "異常:" + e.getMessage());
Toast.makeText(PayActivity.this, "異常:" + e.getMessage(), Toast.LENGTH_SHORT).show();
}
在支付之前,如果應用沒有註冊到微信,應該先調用IWXMsg.registerApp將應用註冊到微信:
api = WXAPIFactory.createWXAPI(this, Constants.APP_ID);
api.registerApp(Constants.APP_ID);
createWXAPI這個方法,有個參數checkSignature,是否要檢查簽名。前期調試很好使,上線時候記得關掉。
下邊看一下支付完成之後的微信的回調
public class WXPayEntryActivity extends Activity implements IWXAPIEventHandler {
private static final String TAG = "MicroMsg.SDKSample.WXPayEntryActivity";
private IWXAPI api;
@Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.pay_result);
api = WXAPIFactory.createWXAPI(this, Constants.APP_ID);
api.handleIntent(getIntent(), this);
}
@Override
protected void onNewIntent(Intent intent) {
super.onNewIntent(intent);
setIntent(intent);
api.handleIntent(intent, this);
}
@Override
public void onReq(BaseReq req) {
}
@Override
public void onResp(BaseResp resp) {
Log.d(TAG, "onPayFinish, errCode = " + resp.errCode);
if (resp.getType() == ConstantsAPI.COMMAND_PAY_BY_WX) {
AlertDialog.Builder builder = new AlertDialog.Builder(this);
builder.setTitle("R.string.app_tip");
builder.setMessage(getString(R.string.pay_result_callback_msg, String.valueOf(resp.errCode)));
builder.show();
}
}
}
這裏有個方法可以根據onResp方法的BaseResp參數來判斷支付結果。 errCode =0 就是沒錯,支付成功。 -2 用戶取消支付, -1 支付出錯。
- 這裏有個坑,我覺得有必要說一下,一般支付完畢之後可以告訴用戶是否成功, 如果產品讓添加一下支付的介面呢, 比如添加一下UI, 這時候就需要根據結果來初始化UI, 這裏的聲明週期方法 就是 onResp –> onNewIntent –> onCreate , 所以需要聲明一個字段提前保存支付狀態。然後再根據結果再onCreate中進行初始化UI元素,以及其他操作。
整體流程分析
說起流程分析最適合的就是弄個sequence, 看圖
紅色的主體是我們自己的APP的和Server 。
這裏注意14步,支付驗證授權,完成支付交易之後,這裏觸發的是一個並行的流程。
* 微信後臺通知微信APP ,然後再回調我們的APP通知結果
* 微信後臺異步通知我們的後臺Server,我們Server再進行接收保存等處理。
另一個地方是對於支付的結果,我們自己可以查詢自己Server之前保存的結果,也可以Server調用微信的後臺API來查詢支付結果,這裏不再贅述。
注意事項
- APPId一定要配置成自己的APPID,別忘改了。
- 在SDK集成封裝完成之後,一定要用正式簽名來打包。否則就會出errorCode -1
- WXPayEntryActivity這個類要放到wxapi的package下,並聲明export=true ,這個一般複製demo的話也不容易出錯。
- 我們的支付結果一般認爲使用sdk提供的onResp回調就行了,可是移動端畢竟有很多不可控因素,所以在一些特殊的場合(斷網或者弱網,斷電,kill進程,等等)還是依賴我們自己Server的回調確認比較好。
總結
說到官網API不得不說和支付寶的根本沒法比,
首先就說Demo,支付寶提供的demo兩種版本,eclipse & gradle。 微信sdkdemo 只放的有eclipse 代碼已經很久沒有維護了,網絡請求還在主線程中寫着。
再說支付結構來說,微信是使用aidl進程間通信來回調WXPayEntryActivity這個類,使用上限制比較多,比如包名,簽名,類放置位置,甚至在調起微信的過程還得請求驗籤。 支付寶很簡單,靠的是強大的RSA2加密算法把自己的SDK嵌入到了調用者的APP中,調用十分方便,整潔。
另附完整支付寶微信集成源碼:https://github.com/samuelhehe/PayDemo
關於支付寶的集成看我的另一篇文章Android應用接入支付寶實現支付功能