現在的支付潮流莫過于微信跟支付寶了,最近我們項目涉及到會員需求,就用到微信支付跟支付寶支付,說實話接入之前會覺得這個復雜,等真正去動手實踐的時候才覺得狠簡單,真的狠簡單。從接入到支付一步到位,Run完直接調起了微信跟支付寶。接入前也看了這兩個支付的詳細接入文檔,但是看是一碼事,做也是一碼事。所以實踐很重要。
- 之所以說狠簡單而且快速接入,主要是因為我們公司的運維后臺很給力,把微信的一些請求參數,全部后臺返回給我們,我們直接用實體是接受拿到就好。
先說下微信支付吧,畢竟相對于支付而言,還是支付寶簡單快速一點,就留到后面說了
1.如果你已經成功集成了微信登錄和分享,直接用你的 libammsdk.jar和 WECHAT_APP_ID就可以了, 那么下面幫你快速集成微信支付。
2.接入前可以看看上面鏈接的文檔,不過微信官方的文檔寫的不夠好,好多開發者吐槽,至今也沒改善點啥。
3.好了直接說接入,接入微信支付SDK前準備下面三個東西,如果你集成了微信分享,登錄那只需要一個 WXPayEntryActivity 類就行了
① 微信支付的APPID
② 微信支付依賴包 -------- libammsdk.jar
③ 一個Activity類 ----------- WXPayEntryActivity
- 這里需要特別說明一下,這個WXPayEntryActivity 類,直接從微信官方下載的Demo代碼中copy到自己的工程中即可,這個頁面是在你調起微信支付完成支付(或取消或失敗)后,再回到你的App時會調用的一個頁面。頁面的布局可以是你自定義的布局(一般做法是直接注釋掉這個布局)
網上copy的一張圖講解:
4、WXPayEntryActivity中的布局是可以自定義的,如果你不需要展示什么布局,而是要跳轉頁面,把這段代碼刪除即可
/**
* -Created by Luke on 2017/2/14.
*/
public class WXPayEntryActivity extends AppCompatActivity {
private static final String TAG = WXPayEntryActivity.class.getSimpleName();
@Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
// setContentView(R.layout.pay_result);
BaseApplication.api.handleIntent(getIntent(), this);
}
}
WECHAT_APP_ID 已經在BaseApplication中定義了 在這里不需要再寫
5.下面是回調的邏輯,官方是這樣的圖
- 我這邊就簡單的演示下支付成功的地方
@Override
public void onResp(BaseResp resp) {
LogUtil.d(TAG, "Luke = " + resp.toString());
if (resp.getType() == ConstantsAPI.COMMAND_PAY_BY_WX) {
int code = resp.errCode;
switch (code) {
case 0:
ToastUtil.show("支付成功");
break;
case -1:
ToastUtil.show("支付失敗");
finish();
break;
case -2:
ToastUtil.show("支付取消");
finish();
break;
default:
ToastUtil.show("支付失敗");
setResult(RESULT_OK);
finish();
break;
}
}
}
接下來咱就把這個WXPayEntryActivity放在清單manifest文件里面注冊,然后加上exported屬性,設置為true:
<activity
android:name=".wxapi.WXPayEntryActivity"
android:exported="true"
android:launchMode="singleTop"
android:theme="@style/Theme.AppCompat.NoActionBar"/>
注意的地方:
- 0 成功 展示成功頁面
- -1 錯誤 可能的原因:簽名錯誤、未注冊APPID、項目設置APPID不正確、注冊的APPID與設置的不匹配、其他異常等。
- -2 用戶取消 無需處理。發生場景:用戶不支付了,點擊取消,返回APP。
6.這個類中的其余的回調方法,我們都不需要去操作。然后我們就可以開始支付了,蠻簡單
- 下面是請求的參數列表,我們都是服務器端返回,包括APPID,直接用已經正式的sign。
- 大概的支付流程是
① 點擊支付的時候創建訂單,獲取訂單號orderNumber (或者在需要獲取訂單號的時候獲取)
② 通過你的價格和這個orderNumber去請求微信返回的一堆參數,以及調起支付頁面:
下面是關鍵的一步:
//PrePayWeChatEntity 服務器返回給我們微信支付的參數
private void WeChatPay(PrePayWeChatEntity data) {
if (null == data) {
//判斷是否為空。丟一個toast,給個提示。比如服務器異常,錯誤啥的
return;
}
IWXAPI api = WXAPIFactory.createWXAPI(this, data.getAppid());
if (!isWXAppInstalledAndSupported(api)) {
// throw new WeChartNoFoundException();
ToastUtil.show(getString(R.string.text_uninstalled_wchat));
return;
}
//data 根據服務器返回的json數據創建的實體類對象
PayReq req = new PayReq();
req.appId = data.getAppid();
req.partnerId = data.getPartnerid();
req.prepayId = data.getPrepayid();
req.packageValue = data.getPkgstr();
req.nonceStr = data.getNoncestr();
req.timeStamp = data.getTimestamp();
req.sign = data.getSign();
api.registerApp(data.getAppid());
//發起請求
api.sendReq(req);
}
7.到這就是成功了,調起了微信支付。再回到 WXPayEntryActivity 中去判斷成功后的動作,例如支付完成跳轉一個成功的頁面finish();也許是用戶取消,和異常的支付失敗,可以在這個邏輯中去請求訂單的狀態是怎么樣的。
8.最后一個問題就是關于微信開放平臺簽名的問題。只要你手機上的程序的簽名和你在微信平臺登記的簽名一致即可,無論是debug版本,還是release版本,都是可以的,默認都可以用release的簽名
到這微信支付就愉快的結束了
支付寶支付,這個比微信稍微簡單那么點,同樣在請求參數服務端返回的情況下
- 支付寶開放平臺 在這個平臺申請我們的支付功能:
- 注意一點就是個人不能申請的,只能是企業,so 我demo里面的用的一些資料也是demo里面的
1.進入支付寶開放平臺,注冊賬戶并登錄。
2.登錄成功后,點擊管理中心創建應用(創建應用時,注意命名規范)。
下載 alipaySdk-20161222.jar 和 alipay_demo
將demo里面的alipaySdk-20161222.jar拷貝到我們工程的libs下,并添加到依賴中
跟微信一樣在清單文件中注冊下這兩個Activity
<activity
android:name="com.alipay.sdk.app.H5PayActivity"
android:configChanges="orientation|keyboardHidden|navigation"
android:exported="false"
android:screenOrientation="behind">
</activity>
<activity
android:name="com.alipay.sdk.auth.AuthActivity"
android:configChanges="orientation|keyboardHidden|navigation"
android:exported="false"
android:screenOrientation="behind">
</activity>
3.設置應用公鑰
4.生成密鑰
5.點擊上方的支付寶密鑰生成器下載下jar包之后解壓
6.點擊密鑰生成器之后回彈出黑窗口,等幾秒之后彈出生成器窗口
7.跟微信的流程相差無幾。拿到價格和訂單號,就可以去請求支付的地址了,然后用這些參數回調支付
//orderNum, orderInfo, sign, signType 服務器端返回,本地生成也是OK的
private void requestAlipay(String orderNum, String orderInfo, String sign, String signType) {
try {
// 對sign做URL編碼
sign = URLEncoder.encode(sign, "UTF-8");
} catch (UnsupportedEncodingException e) {
e.printStackTrace();
}
// 整的符合支付寶參數規范的訂單信息
final String payInfo = orderInfo + "&sign=\"" + sign + "\"&sign_type=\"" + signType + "\"";
//lambda 此處 () -> 為lambda 表達式寫法
Runnable payRunnable = () -> {
// 構造PayTask 對象
PayTask payTask = new PayTask(this);
// 調用支付接口,獲取支付結果
String result = payTask.pay(payInfo, true);
if (null == result) {
result = "out_trade_no={" + orderNum + "}";
} else {
result += ";out_trade_no={" + orderNum + "}";
}
Message msg = new Message();
msg.what = SDK_PAY_FLAG;
msg.obj = result;
mHandler.sendMessage(msg);
};
// 必須異步調用
Thread payThread = new Thread(payRunnable);
payThread.start();
}
上述生成的這些東西一般都是后臺返回的,當然我們本地生成也是可以的,所以我就大概的說下流程
- 處理支付結果:
@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")) {
// 該筆訂單是否真實支付成功,需要依賴服務端的異步通知。
Toast.makeText(PayDemoActivity.this, "支付成功", Toast.LENGTH_SHORT).show();
} else {
// 該筆訂單真實的支付結果,需要依賴服務端的異步通知。
Toast.makeText(PayDemoActivity.this, "支付失敗", Toast.LENGTH_SHORT).show();
}
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
// 傳入,則支付賬戶為該授權賬戶
Toast.makeText(PayDemoActivity.this,
"授權成功\n" + String.format("authCode:%s", authResult.getAuthCode()), Toast.LENGTH_SHORT)
.show();
} else {
// 其他狀態值則為授權失敗
Toast.makeText(PayDemoActivity.this,
"授權失敗" + String.format("authCode:%s", authResult.getAuthCode()), Toast.LENGTH_SHORT).show();
}
break;
}
default:
break;
}
}
;
};
到這兒就支付成功了,提示用戶的邏輯,我們得從服務器確認是否正在支付了,查詢是否支付成功的狀態。根據服務器端返回的判斷碼來處理支付之后的一些動作。
接入的時候有啥問題可以隨時跟我談論,我想這些會給你們一些幫助,記錄就是在腦子里過一遍,也許是最好的成長。