(Android集成支付宝支付)react-native实现支付宝支付

网上关于RN的支付宝支付组件大部分都是IOS的,Android要实现支付宝支付只剩下走原生这一步了。

整体思路:

1、在蚂蚁金服开放平台申请应用

2、在android原生集成支付宝

3、封装android原生

4、RN与android的通信

一、准备工作

1、在蚂蚁金服开放平台https://docs.open.alipay.com/204/105051/ 按照官方提示创建应用,添加app支付的功能。

2、在审核通过后可以拿到调用支付所需要的参数。

3、下载官方的Demo和SDKhttps://docs.open.alipay.com/54/104509



解压项目,用Android Studio打开alipay_demo项目,核心代码都在这个文件夹中。

二、项目操作

1、初始化zfbDemo的RN项目。并用Android Studio打开android部分。

2、在zfbDemo/android/app/目录下新建libs文件夹,将官网下载的alipay_demo中的libs下的sdk复制到新建的libs文件夹下。并右键 Add as  Library添加到项目中。


3、在AndroidManifest.xml文件中加入注册声明:

<!-- alipay sdk begin -->

        <activity
            android:name="com.alipay.sdk.app.H5PayActivity"
            android:configChanges="orientation|keyboardHidden|navigation|screenSize"
            android:exported="false"
            android:screenOrientation="behind"
            android:windowSoftInputMode="adjustResize|stateHidden" >
        </activity>
        <activity
            android:name="com.alipay.sdk.app.H5AuthActivity"
            android:configChanges="orientation|keyboardHidden|navigation"
            android:exported="false"
            android:screenOrientation="behind"
            android:windowSoftInputMode="adjustResize|stateHidden" >
        </activity>

        <!-- alipay sdk end -->

和权限声明:

<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" />

4、我们直接实现点击RN中的按钮调出支付宝支付页面。

创建一个类继承ReactContextBaseJavaModule,这个类放入被RN调用的方法封装成有个原生模块

新建一个MyNativeModule的类,内容:

package com.zfbdemo;

import android.content.Context;
import android.content.Intent;

import com.facebook.react.bridge.ReactApplicationContext;
import com.facebook.react.bridge.ReactContextBaseJavaModule;
import com.facebook.react.bridge.ReactMethod;

/**
 * Created by admin on 2017/11/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(){

    }

}

创建一个类实现接口ReactPackage包管理器,把上面一步创建的类添加到原生模块(nativeModule)列表里

新建一个MyReactPackge的类,内容:

package com.zfbdemo;

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.ArrayList;
import java.util.Collections;
import java.util.List;

/**
 * Created by admin on 2017/11/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();
    }
}

在MainApplication中加入new MyReactPackge()

@Override
    protected List<ReactPackage> getPackages() {
      return Arrays.<ReactPackage>asList(
          new MainReactPackage(),
              new MyReactPackge()//添加这一句
      );
    }

到现在,RN调用的原生Android方法就封装好了,下一步就需要在方法里面调用支付了,不再一一叙述,直接贴代码:

tip:这一块只是为了实现支付功能的演示,真正的项目是需要后台加密返回orderInfo的。

先引入一些文件:


将官方demo中的这些文件复制过来,然后逐个打开,有包名之类的错误的改正。

将MyNativeModule.Java文件改为以下内容:

package com.zfbdemo;

import android.annotation.SuppressLint;
import android.app.AlertDialog;
import android.content.Context;
import android.content.DialogInterface;
import android.content.Intent;
import android.os.Handler;
import android.os.Looper;
import android.os.Message;
import android.text.TextUtils;
import android.util.Log;
import android.view.View;
import android.widget.Toast;

import com.alipay.sdk.app.PayTask;
import com.facebook.react.bridge.ReactApplicationContext;
import com.facebook.react.bridge.ReactContextBaseJavaModule;
import com.facebook.react.bridge.ReactMethod;
import com.zfbdemo.util.OrderInfoUtil2_0;

import java.util.Map;

/**
 * Created by admin on 2017/11/3.
 */

public class MyNativeModule  extends ReactContextBaseJavaModule {
    /** 支付宝支付业务:入参app_id */
    public static final String APPID = "申请的appid";

    /** 支付宝账户登录授权业务:入参pid值 */
    public static final String PID = "申请的pid";
    /** 支付宝账户登录授权业务:入参target_id值 */
    public static final String TARGET_ID = "";

    /** 商户私钥,pkcs8格式 */
    /** 如下私钥,RSA2_PRIVATE 或者 RSA_PRIVATE 只需要填入一个 */
    /** 如果商户两个都设置了,优先使用 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;
    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(){
        payV2();
    }

    @SuppressLint("HandlerLeak")
    private Handler mHandler = new Handler(Looper.getMainLooper()) {
        @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(mContext, "支付成功", Toast.LENGTH_SHORT).show();
                    } else {
                        // 该笔订单真实的支付结果,需要依赖服务端的异步通知。
                        Toast.makeText(mContext, "支付失败", 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(mContext,
                                "授权成功\n" + String.format("authCode:%s", authResult.getAuthCode()), Toast.LENGTH_SHORT)
                                .show();
                    } else {
                        // 其他状态值则为授权失败
                        Toast.makeText(mContext,
                                "授权失败" + String.format("authCode:%s", authResult.getAuthCode()), Toast.LENGTH_SHORT).show();

                    }
                    break;
                }
                default:
                    break;
            }
        };
    };


    public void payV2() {
        /**
         * 这里只是为了方便直接向商户展示支付宝的整个支付流程;所以Demo中加签过程直接放在客户端完成;
         * 真实App里,privateKey等数据严禁放在客户端,加签过程务必要放在服务端完成;
         * 防止商户私密数据泄露,造成不必要的资金损失,及面临各种安全风险;
         *
         * orderInfo的获取必须来自服务端;
         */
        boolean rsa2 = (RSA2_PRIVATE.length() > 0);
        Map<String, String> params = OrderInfoUtil2_0.buildOrderParamMap(APPID, rsa2);
        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;

        Runnable payRunnable = new Runnable() {

            @Override
            public void run() {
                PayTask alipay = new PayTask(getCurrentActivity());
                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();
    }



}

在JS中:

import {
    AppRegistry,
    StyleSheet,
    Text,
    View,
    NativeModules,
    TouchableOpacity
} from 'react-native';

<TouchableOpacity style={styles.btn} onPress={()=>{
            NativeModules.MyNativeModule.rnCallNative()
        }}>
          <Text>调用支付</Text>
        </TouchableOpacity>

此时点击RN中的按钮会直接调出支付宝支付。

再次提醒orderInfo必须从后台获得(防止信息泄密)


当手机安装了支付宝会调用支付宝支付,如果没有支付宝会登录网页版的支付宝。

需要注意一点,当应用设置了状态栏沉浸模式,网页版的支付宝的activity会被提上来影响美观,需要在AndroidManifest.xml中加一句:

android:theme="@android:style/Theme"
















  • 0
    点赞
  • 2
    收藏
    觉得还不错? 一键收藏
  • 1
    评论
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值