美文网首页Android技术Android知识React Native
React-Native之android集成支付宝

React-Native之android集成支付宝

作者: 云上月 | 来源:发表于2017-03-25 10:17 被阅读2050次

    支付宝流程效果图

    充值 android原生确认支付界面 付款详情 正在付款
    整体思路:
    1.在蚂蚁金服开放平台申请应用
    2.在android原生集成支付宝
    3.封装android原生
    4.RN与android的通信
    一.在蚂蚁金服开放平台申请应用
    蚂蚁金服开放平台链接:https://openhome.alipay.com/platform/manageHome.htm
    1.在注册登录成功之后选择应用 选择应用

    2.选择创建应用,按照文档流程申请应用

    申请应用

    二、在android原生集成支付宝
    1.在app目录下面新建一个libs的目录
    2.把支付宝的SDK复制粘贴到libs目录下

    粘贴SDK.png

    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>
    

    如果此时com.alipay.sdk.auth.AuthActivity报红说明未找到这个包。解决方法:
    往build.gradle(有app的)中添加下面篮框的内容

    00682750-1D48-4548-B851-7047C71D14D8.png

    和权限声明:

    <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.新建一个支付的acitivity,

    新建一个新的acitivity.png 输入activity的name.png

    2.进入activity_pay.xml文件点击text

    activity_pay.xml文件.png

    3.把activity_pay.xml的源码删除,改成我现在的布局:

    activity_pay.xml的源码.png

    4.PayActivity文件 添加取消按键onBack点击方法,

     public void onBack(View v){
            finish();
        }
    

    5.根据蚂蚁金服开放平台提供的alipay_demo中的PayDemoActivity.java中添加支付接口,这里我的加签过程是在服务端配置返回的key,EnvUtils.setEnv(EnvUtils.EnvEnum.SANDBOX)(生产环境不需要调用)中如果EnvUtils报红,选中alt+enter就能引入头文件

    public void payV2(View v) {
            Bundle bundle = getIntent().getExtras();
            String key = bundle.getString("key");
            final String orderInfo = key;
    //支付宝沙箱android测试需要调用
            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.此时会报SDK_PAY_FLAG,所以我们要添加进去

    private static final int SDK_PAY_FLAG = 1;
        private static final int SDK_AUTH_FLAG = 2;
    

    支付回调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")) {
                            // 该笔订单是否真实支付成功,需要依赖服务端的异步通知。
                            Toast.makeText(PayActivity.this, "支付成功", Toast.LENGTH_SHORT).show();
                        } else {
                            // 该笔订单真实的支付结果,需要依赖服务端的异步通知。
                             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”则代表授权成功,具体状态码代表含义可参考授权接口文档
                        if (TextUtils.equals(resultStatus, "9000") && TextUtils.equals(authResult.getResultCode(), "200")) {
                            // 获取alipay_open_id,调支付时作为参数extern_token 的value
                            // 传入,则支付账户为该授权账户
                            Toast.makeText(PayActivity.this,
                                    "授权成功\n" + String.format("authCode:%s", authResult.getAuthCode()), Toast.LENGTH_SHORT)
                                    .show();
                        } else {
                            // 其他状态值则为授权失败
                            Toast.makeText(PayActivity.this,
                                    "授权失败" + String.format("authCode:%s", authResult.getAuthCode()), Toast.LENGTH_SHORT).show();
    
                        }
                        break;
                    }
                    default:
                        break;
                }
            };
        };
    

    此时报红的PayResult,AuthResult,需要去到支付宝的alipay_demo中往工程中加入这两个文件,方法是复制这两个文件到工程的相应目录下粘贴
    7.获取SDK版本号

    public void getSDKVersion() {
            PayTask payTask = new PayTask(this);
            String version = payTask.getVersion();
            Toast.makeText(this, version, Toast.LENGTH_SHORT).show();
        }
    

    PayActivity.java文件源码完成
    此时支付宝的原生集成已经完成 所有调用全在PayActivity.java中
    四.RN与android的通信
    1.创建一个类继承ReactContextBaseJavaModule,这个类放入被RN调用的方法封装成有个原生模块

    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;
        //构造方法
        public MyNativeModule(ReactApplicationContext reactContext) {
            super(reactContext);
            mContext = reactContext;
        }
        @Override
        public String getName() {
            //MyNativeModule 需要此名字来调用该类方法
            return "MyNativeModule";
        }
        //函数不能有返回值,被调用的原生代码是异步的,原生代码执行结束之后只能通过回调函数发送消息给RN
    
        //rnCallNative为RN需要调用的方法
        @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.创建一个类实现接口ReactPackage包管理器,把上面一步创建的类添加到原生模块(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.将第二步中创建的包管理器添加到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调用封装的android原生组件
    1.引入NativeModules

    import { NativeModules} from 'react-native';
    

    2.定义一个view,当点击的时候触发原生事件

    <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.点击的nativeAndroid方法,MyNativeModule是安卓原生MyNativeModule文件中的getName返回的名字,rnCallNative是rnCallNative为RN需要调用的方法,下面的触发方法中的this.state.signedString是服务器对支付宝加签返回的签名,也就是客户端调支付宝时用到的orderInfo

    nativeAndroid(){
            var sign = this.state.signedString
            if(sign){
                NativeModules.MyNativeModule.rnCallNative(sign)
            }
        }
    

    到这里RN调用安卓原生支付宝的步骤已全部完成

    相关文章

      网友评论

      • 26e0f0a4df15:为什么我写的能打开支付宝,但是点击原生页面的确认支付后,app退到后台了,显示手机桌面,然后在加载支付宝的付款页面,支付宝的付款详情上面就能看看到手机桌面上的东西,请指点下
      • 无尽甜蜜里悠悠记忆:请问服务器返回给我的签名,我每次点击支付请求时,都会报ALI40247,请问您遇到过这种情况吗?您给判断一下 是代码的问题还是服务器的问题? 谢谢您了
        云上月:@无尽甜蜜里悠悠记忆 我忘了,这很久了,你查看支付宝返回错误参数的文档。看对应是什么出错
      • 无尽甜蜜里悠悠记忆:哥 请问支付宝的签名不对,点击支付是不是没有反应?
        云上月:@无尽甜蜜里悠悠记忆 没有任何提示吗,看提示看看。
      • 春春0505:你好,我想问一下,我按照你的步骤全部做好,但是在页面上点击却一点反应都没有,也没有报错,但是点击无反应是什么原因呢?期待你的回复,谢谢
        云上月:需要到支付宝开发者网站注册一个APP,成功之后就会有签名
        春春0505:@云上月 好的,谢谢哦!再请问一下那个传入的签名是哪里来的
        云上月:那应该是在安卓原生上出错啦,你在仔细看看原生那块
      • 乾坤醉心尘::kissing_heart: 求约会

      本文标题:React-Native之android集成支付宝

      本文链接:https://www.haomeiwen.com/subject/axnxottx.html