支付寶流程效果圖
整體思路:
1.在螞蟻金服開放平臺(tái)申請(qǐng)應(yīng)用
2.在android原生集成支付寶
3.封裝android原生
4.RN與android的通信
一.在螞蟻金服開放平臺(tái)申請(qǐng)應(yīng)用
螞蟻金服開放平臺(tái)鏈接:https://openhome.alipay.com/platform/manageHome.htm
1.在注冊(cè)登錄成功之后選擇應(yīng)用
2.選擇創(chuàng)建應(yīng)用,按照文檔流程申請(qǐng)應(yīng)用
二、在android原生集成支付寶
1.在app目錄下面新建一個(gè)libs的目錄
2.把支付寶的SDK復(fù)制粘貼到libs目錄下
3.選擇SDK右鍵選擇add as library
4.修改Manifest,在工程的AndroidManifest.xml文件里面添加聲明:
<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>
如果此時(shí)com.alipay.sdk.auth.AuthActivity報(bào)紅說明未找到這個(gè)包。解決方法:
往build.gradle(有app的)中添加下面籃框的內(nèi)容
和權(quán)限聲明:
<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" />
三.封裝android原生
1.新建一個(gè)支付的acitivity,
2.進(jìn)入activity_pay.xml文件點(diǎn)擊text
3.把a(bǔ)ctivity_pay.xml的源碼刪除,改成我現(xiàn)在的布局:
4.PayActivity文件 添加取消按鍵onBack點(diǎn)擊方法,
public void onBack(View v){
finish();
}
5.根據(jù)螞蟻金服開放平臺(tái)提供的alipay_demo中的PayDemoActivity.java中添加支付接口,這里我的加簽過程是在服務(wù)端配置返回的key,EnvUtils.setEnv(EnvUtils.EnvEnum.SANDBOX)(生產(chǎn)環(huán)境不需要調(diào)用)中如果EnvUtils報(bào)紅,選中alt+enter就能引入頭文件
public void payV2(View v) {
Bundle bundle = getIntent().getExtras();
String key = bundle.getString("key");
final String orderInfo = key;
//支付寶沙箱android測(cè)試需要調(diào)用
EnvUtils.setEnv(EnvUtils.EnvEnum.SANDBOX);
Runnable payRunnable = new Runnable() {
@Override
public void run() {
PayTask alipay = new PayTask(PayActivity.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();
}
6.此時(shí)會(huì)報(bào)SDK_PAY_FLAG,所以我們要添加進(jìn)去
private static final int SDK_PAY_FLAG = 1;
private static final int SDK_AUTH_FLAG = 2;
支付回調(diào)mHandler方法
@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();
Toast.makeText(PayActivity.this, resultStatus, Toast.LENGTH_SHORT).show();
// 判斷resultStatus 為9000則代表支付成功
if (TextUtils.equals(resultStatus, "9000")) {
// 該筆訂單是否真實(shí)支付成功,需要依賴服務(wù)端的異步通知。
Toast.makeText(PayActivity.this, "支付成功", Toast.LENGTH_SHORT).show();
} else {
// 該筆訂單真實(shí)的支付結(jié)果,需要依賴服務(wù)端的異步通知。
Toast.makeText(PayActivity.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”則代表授權(quán)成功,具體狀態(tài)碼代表含義可參考授權(quán)接口文檔
if (TextUtils.equals(resultStatus, "9000") && TextUtils.equals(authResult.getResultCode(), "200")) {
// 獲取alipay_open_id,調(diào)支付時(shí)作為參數(shù)extern_token 的value
// 傳入,則支付賬戶為該授權(quán)賬戶
Toast.makeText(PayActivity.this,
"授權(quán)成功\n" + String.format("authCode:%s", authResult.getAuthCode()), Toast.LENGTH_SHORT)
.show();
} else {
// 其他狀態(tài)值則為授權(quán)失敗
Toast.makeText(PayActivity.this,
"授權(quán)失敗" + String.format("authCode:%s", authResult.getAuthCode()), Toast.LENGTH_SHORT).show();
}
break;
}
default:
break;
}
};
};
此時(shí)報(bào)紅的PayResult,AuthResult,需要去到支付寶的alipay_demo中往工程中加入這兩個(gè)文件,方法是復(fù)制這兩個(gè)文件到工程的相應(yīng)目錄下粘貼
7.獲取SDK版本號(hào)
public void getSDKVersion() {
PayTask payTask = new PayTask(this);
String version = payTask.getVersion();
Toast.makeText(this, version, Toast.LENGTH_SHORT).show();
}
PayActivity.java文件源碼完成
此時(shí)支付寶的原生集成已經(jīng)完成 所有調(diào)用全在PayActivity.java中
四.RN與android的通信
1.創(chuàng)建一個(gè)類繼承ReactContextBaseJavaModule,這個(gè)類放入被RN調(diào)用的方法封裝成有個(gè)原生模塊
package com.cloudprocessing;
import android.content.Context;
import android.content.Intent;
import android.os.Bundle;
import android.widget.Toast;
import com.facebook.react.bridge.ReactApplicationContext;
import com.facebook.react.bridge.ReactContextBaseJavaModule;
import com.facebook.react.bridge.ReactMethod;
/**
* Created by on 2017/3/3.
*/
public class MyNativeModule extends ReactContextBaseJavaModule{
private Context mContext;
//構(gòu)造方法
public MyNativeModule(ReactApplicationContext reactContext) {
super(reactContext);
mContext = reactContext;
}
@Override
public String getName() {
//MyNativeModule 需要此名字來調(diào)用該類方法
return "MyNativeModule";
}
//函數(shù)不能有返回值,被調(diào)用的原生代碼是異步的,原生代碼執(zhí)行結(jié)束之后只能通過回調(diào)函數(shù)發(fā)送消息給RN
//rnCallNative為RN需要調(diào)用的方法
@ReactMethod
public void rnCallNative(String msg){
//添加意圖
Intent intent = new Intent(mContext,PayActivity.class);
intent.setFlags(Intent.FLAG_ACTIVITY_NEW_TASK);
//bundle為需要傳給PayActivity的加密簽名
Bundle bundle = new Bundle();
bundle.putString("key",msg);
intent.putExtras(bundle);
//startActivity
mContext.startActivity(intent,bundle);
}
}
2.創(chuàng)建一個(gè)類實(shí)現(xiàn)接口ReactPackage包管理器,把上面一步創(chuàng)建的類添加到原生模塊(nativeModule)列表里
package com.cloudprocessing;
import com.facebook.react.ReactPackage;
import com.facebook.react.bridge.JavaScriptModule;
import com.facebook.react.bridge.NativeModule;
import com.facebook.react.bridge.ReactApplicationContext;
import com.facebook.react.uimanager.ViewManager;
import java.util.Collection;
import java.util.Collections;
import java.util.List;
import java.util.ArrayList;
/**
* Created by on 2017/3/3.
*/
public class MyReactPackge implements ReactPackage{
@Override
public List<NativeModule> createNativeModules(ReactApplicationContext reactContext) {
List<NativeModule> modules = new ArrayList<>();
modules.add(new MyNativeModule(reactContext));
return modules;
}
@Override
public List<Class<? extends JavaScriptModule>> createJSModules() {
return Collections.emptyList();
}
@Override
public List<ViewManager> createViewManagers(ReactApplicationContext reactContext) {
return Collections.emptyList();
}
}
3.將第二步中創(chuàng)建的包管理器添加到ReactPackage列表里的getPackges方法 MainApplication中加入new MyReactPackge()
package com.cloudprocessing;
import android.app.Application;
import android.util.Log;
import com.facebook.react.ReactApplication;
import com.lwansbrough.RCTCamera.RCTCameraPackage;
import com.facebook.react.ReactInstanceManager;
import com.facebook.react.ReactNativeHost;
import com.facebook.react.ReactPackage;
import com.facebook.react.shell.MainReactPackage;
import com.facebook.soloader.SoLoader;
import java.util.Arrays;
import java.util.List;
public class MainApplication extends Application implements ReactApplication {
private final ReactNativeHost mReactNativeHost = new ReactNativeHost(this) {
@Override
protected boolean getUseDeveloperSupport() {
return BuildConfig.DEBUG;
}
@Override
protected List<ReactPackage> getPackages() {
return Arrays.<ReactPackage>asList(
new MainReactPackage(),
new RCTCameraPackage(),
new MyReactPackge()
);
}
};
@Override
public ReactNativeHost getReactNativeHost() {
return mReactNativeHost;
}
@Override
public void onCreate() {
super.onCreate();
SoLoader.init(this, /* native exopackage */ false);
}
}
五.js調(diào)用封裝的android原生組件
1.引入NativeModules
import { NativeModules} from 'react-native';
2.定義一個(gè)view,當(dāng)點(diǎn)擊的時(shí)候觸發(fā)原生事件
<TouchableHighlight style={{width:width-80,height:40,alignItems:'center',marginTop:50}} underlayColor='#28780b'
onPress={()=>this.nativeAndroid()}>
<View style={{width:width-80,height:40,alignItems:'center',justifyContent:'center',
backgroundColor:'#35a40c',borderRadius:5}}>
<Text style={{color:'white',fontSize:17}}>確定</Text>
</View>
</TouchableHighlight>
3.點(diǎn)擊的nativeAndroid方法,MyNativeModule是安卓原生MyNativeModule文件中的getName返回的名字,rnCallNative是rnCallNative為RN需要調(diào)用的方法,下面的觸發(fā)方法中的this.state.signedString是服務(wù)器對(duì)支付寶加簽返回的簽名,也就是客戶端調(diào)支付寶時(shí)用到的orderInfo
nativeAndroid(){
var sign = this.state.signedString
if(sign){
NativeModules.MyNativeModule.rnCallNative(sign)
}
}
到這里RN調(diào)用安卓原生支付寶的步驟已全部完成