React Native 安卓端调用支付宝和微信支付

安卓接支付宝支付

官方文档:opendocs.alipay.com/open/204/10…

文档也有对应的Demo代码,但是是Android原生的代码,想要在React Native上调用的话要做一些修改。

所以接下来介绍的是在React Native上怎么接支付SDK。

1、导入支付宝SDK

下载链接:opendocs.alipay.com/open/54/104…

我目前下的版本是:AlipaySDK-standard-15.8.03.3

1、下载好SDK后,把文件里面的alipaysdk-15.8.03.210428205839.aar(这个只是我目前下的SDK版本,实际的话按你们下载的文件为准)放到工程项目的libs(没有这个目录就自己新建一个)目录下:

image.png

2、在android目录下的build.gradle中,添加下面的内容,将libs目录作为依赖仓库:

image.png

allprojects {
    repositories {
    
        // 添加下面的内容
        flatDir {
            dirs 'libs'
        }
        
        // ... jcenter() 等其他仓库
}
复制代码

3、在app目录下的build.gradle中,添加下面的内容,将支付宝SDK作为项目的依赖:

image.png

dependencies {

    // 添加下面的内容, 注意: 这里写的是你上面导入的.arr文件
    implementation (name: 'alipaysdk-15.8.03.210428205839.aar', ext: 'aar')

    // ... 其他依赖项
}
复制代码

2、修改运行权限

android/app/src/main下的AndroidManifest.xml配置如下3个权限:

android.permission.INTERNET
android.permission.ACCESS_NETWORK_STATE
android.permission.ACCESS_WIFI_STATE
复制代码

image.png

3、编写调用支付宝支付接口

大家可以参考我的项目目录,因为我这个项目需要接支付宝和微信支付,所以把支付的模块写在一起,然后把支付宝和微信的单独分开来。

1、创建一个pay的包,然后再创建一个alipay的包,新建一个AliPay.java文件:

image.png

2、在下载的Demo中把PayResult.java复制到pay/alipay目录下:

image.png

3、编写AliPay.java文件

在文件的开头导入以下的包:

package 自己的包名.pay.alipay;

import 自己的包名.R;

import android.annotation.SuppressLint;
import android.os.Handler;
import android.os.Looper;
import android.os.Message;
import android.util.Log;

import java.util.Map;
import com.alipay.sdk.app.PayTask;

import com.facebook.react.bridge.Promise;
import com.facebook.react.bridge.ReactApplicationContext;
import com.facebook.react.bridge.ReactContextBaseJavaModule;
import com.facebook.react.bridge.ReactMethod;
复制代码

然后编写主要的业务代码:

public class AliPay extends ReactContextBaseJavaModule {
    private static ReactApplicationContext reactContext;
    public static Promise promise;

    public AliPay(ReactApplicationContext context) {
        super(context);
        reactContext = context;
    }

    private static final int SDK_PAY_FLAG = 1;

    /**
     * ReactContextBaseJavaModule要求派生类实现getName方法。
     * 这个函数用于返回一个字符串名字,这个名字在 JavaScript 端标记这个模块。
     * 这里我们把这个模块叫做AliPay,这样就可以在 JavaScript 中通过
     * NativeModules.AliPay访问到这个模块。
     */
    @Override
    public String getName() {
        return "AliPay";
    }

    /**
     * 支付结果获取和处理
     * 在支付结束后,会弹出Toast显示结果,但并不能知道该笔订单是否真实支付成功
     * 对于支付结果,请商户依赖服务端的异步通知结果。
     *
     * 这里是关键点:private Handler mHandler = new Handler(Looper.getMainLooper())
     * 官方Demo这里是直接 private Handler mHandler = new Handler()
     * 但是在RN上运行会报错,报错大概是不能在这个线程上创建句柄
     * 解决方法就是给这个构造函数传入Looper.getMainLooper()
     */
    @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则代表支付成功, 具体resultStatus结果码含义查看https://opendocs.alipay.com/open/204/105301
                    AliPay.promise.resolve(resultStatus);
                    break;
                }
                default:
                    break;
            }
        };
    };

    /**
     * payV2 这个函数名可以随便改,在js就是调用这个方法
     * 调起支付宝支付,有安装支付宝会跳转到支付宝,没安装支付宝会跳转到H5
     * @params {String} orderInfo 后端返回给你的订单数据
     */
    @ReactMethod
    public void payV2(String orderInfo, Promise promise) {
        AliPay.promise = promise;

        final 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();
    }

}
复制代码

4、注册模块

写完这个支付模块后,就需要注册模块,如果不注册模块,就无法在js访问到这个模块。

/pay目录下创建一个新的Java类并命名为PayPackage

image.png

其具体代码如下:

package 自己的包名.pay;

import 自己的包名.pay.alipay.AliPay;

import com.facebook.react.ReactPackage;
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;

public class PayPackage implements ReactPackage {

    @Override
    public List<ViewManager> createViewManagers(ReactApplicationContext reactContext) {
        return Collections.emptyList();
    }

    @Override
    public List<NativeModule> createNativeModules(
            ReactApplicationContext reactContext) {
        List<NativeModule> modules = new ArrayList<>();

        /**
         * 在这里注册模块
         */
        // 支付宝支付,这个ApiPay就是我们上面写的AliPay.java
        modules.add(new AliPay(reactContext));

        return modules;
    }

}
复制代码

5、导出模块

模块注册好后,就需要把这个模块导出去,这样才能在React Native中的NativeModules访问到。

android/app/src/main/java/com/你的应用名称/MainApplication.java中添加如下代码:

// MainApplication.java
...
import 自己的包名.PayPackage; // <-- 引入我们上面注册模块时的包
...
protected List<ReactPackage> getPackages() {
  @SuppressWarnings("UnnecessaryLocalVariable")
  List<ReactPackage> packages = new PackageList(this).getPackages();
  // Packages that cannot be autolinked yet can be added manually here, for example:
  // packages.add(new MyReactNativePackage());
  
  // 支付模块
  packages.add(new PayPackage()); // <-- 添加这一行,类名替换成你的Package类的名字 name.
  ...
  return packages;
}
复制代码

4、在js中发起支付宝支付

ok,经过上面的步骤,我们就把一个原生的支付模块写好了。修改了原生的代码,就需要重新运行react-native run-android指令来重新编译项目,这样原生的代码才会生效。

然后在react-native中导入NativeModules模块,这个指的是原生模块,就是我们自己在安卓或IOS写的模块。直接调用原生模块中对应的模块里面的函数即可。

这里是以Promise的形式来使用,因为在原生模块中使用了Promise.resolve来返回结果。

import { NativeModules } from 'react-native';

/**
 * NativeModules.AliPay中的AliPay
 * 对应步骤3中编写的 AliPay.java 文件中 getName()函数的返回值
 *
 * 而payV2方法则是对应 AliPay.java 文件中的 payV2()函数
 */
enum AliPayResult { SUCCESS = 9000, UNKNOW_DEALING = 8000, UNKNOW = 6004, NETWORK_ERR = 6002, CANCEL = 6001, REPEAT_REQ = 5000, FAIL = 4000 }

export const aliPay = async (orderInfo) => {
  const result_code = await NativeModules.AliPay.payV2(orderInfo)
  // 根据result_code做不同的处理
}
复制代码

安卓接微信支付

有了上面接支付宝的基础,接微信支付就很方便了。

官方文档:pay.weixin.qq.com/wiki/doc/ap…

1、后台设置

这部分我就不多说了,大家看着官方文档去做就好啦!就是填写这两项即可!

image.png

2、导入微信支付SDK

1、在app目录下的build.gradle中,添加下面的内容,将微信SDK作为项目的依赖:

dependencies {
    // 微信支付
    implementation "com.tencent.mm.opensdk:wechat-sdk-android-without-mta:+"
    // 其他依赖
}
复制代码

3、写原生代码

1、搭建微信支付目录

pay这个包底下,创建一个wechat的包:

image.png

2、在/pay/wechat下创建Const.java文件

这个文件主要是用来存放你的APPID:

package 你的包名.pay.wechat;

public class Const {
    public static final String APP_ID = "你的APPID";
}
复制代码

3、在/pay/wechat下创建WeChatPay.java文件

这个文件就是调起微信支付的主要代码:

package 你的包名.pay.wechat;

import com.facebook.react.bridge.Arguments;
import com.facebook.react.bridge.Promise;
import com.facebook.react.bridge.ReactApplicationContext;
import com.facebook.react.bridge.ReactContextBaseJavaModule;
import com.facebook.react.bridge.ReactMethod;
import com.facebook.react.bridge.ReadableMap;
import com.facebook.react.bridge.WritableMap;

import com.tencent.mm.opensdk.constants.Build;
import com.tencent.mm.opensdk.modelpay.PayReq;
import com.tencent.mm.opensdk.openapi.IWXAPI;
import com.tencent.mm.opensdk.openapi.WXAPIFactory;

public class WeChatPay extends ReactContextBaseJavaModule {
    private static ReactApplicationContext reactContext;
    public static Promise promise;

    private IWXAPI api;

    public WeChatPay(ReactApplicationContext context) {
        super(context);
        reactContext = context;
        api = WXAPIFactory.createWXAPI(context, Const.APP_ID, false);
        api.registerApp(Const.APP_ID);
    }

    @Override
    public String getName() {
        return "WeChatPay";
    }

    @ReactMethod
    public void pay(ReadableMap request, Promise promise) {
        WeChatPay.promise = promise;

        PayReq req = new PayReq();
        req.appId = request.getString("appid");
        req.partnerId = request.getString("partnerid");
        req.prepayId = request.getString("prepayid");
        req.packageValue = "Sign=WXPay";
        req.nonceStr = request.getString("nonceStr");
        req.timeStamp = request.getString("timestamp");
        req.sign = request.getString("sign");

        int wxSdkVersion = api.getWXAppSupportAPI();
        if (wxSdkVersion >= Build.PAY_SUPPORTED_SDK_INT) {
            api.sendReq(req);
        } else if (wxSdkVersion == 0){
            // 未安装微信
            WritableMap map = Arguments.createMap();
            map.putInt("errCode", -3);
            WeChatPay.promise.resolve(map);
        } else {
            // 微信版本过低
            WritableMap map = Arguments.createMap();
            map.putInt("errCode", -4);
            WeChatPay.promise.resolve(map);
        }
    }
}
复制代码

4、编写微信支付回调代码

这一步要做的是,获取微信支付的结果。

1、首先,在你安卓项目下,创建一个wxapi的包。

⚠注意注意!!!!这个包一定要在你的包底下这一层,不能放在别的地方!

image.png

2、在这个wxapi包下创建一个WXPayEntryActivity.java文件

⚠注意注意!!!!这个文件名也不要改

代码:

package 你的包名.wxapi;

import 你的包名.pay.wechat.Const;
import 你的包名.pay.wechat.WeChatPay;

import android.app.Activity;
import android.content.Intent;
import android.os.Bundle;

import com.facebook.react.bridge.Arguments;
import com.facebook.react.bridge.WritableMap;
import com.facebook.react.uimanager.IllegalViewOperationException;
import com.tencent.mm.opensdk.constants.ConstantsAPI;
import com.tencent.mm.opensdk.modelbase.BaseReq;
import com.tencent.mm.opensdk.modelbase.BaseResp;
import com.tencent.mm.opensdk.openapi.IWXAPI;
import com.tencent.mm.opensdk.openapi.IWXAPIEventHandler;
import com.tencent.mm.opensdk.openapi.WXAPIFactory;

public class WXPayEntryActivity extends Activity implements IWXAPIEventHandler {

    private static final String TAG = "WXPayEntryActivity";
    private IWXAPI api;

    @Override
    public void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        api = WXAPIFactory.createWXAPI(this, Const.APP_ID);
        api.handleIntent(getIntent(), this);
    }

    @Override
    protected void onNewIntent(Intent intent) {
        super.onNewIntent(intent);
        setIntent(intent);
        api.handleIntent(intent, this);
    }

    @Override
    public void onResp(BaseResp resp) {
        System.out.println("onResp2");
        if(resp.getType()== ConstantsAPI.COMMAND_PAY_BY_WX){
            try {
                //把支付结果返回出去。
                WritableMap map = Arguments.createMap();
                map.putInt("errCode", resp.errCode);
                WeChatPay.promise.resolve(map);
                finish();
            } catch (IllegalViewOperationException e) {
                WeChatPay.promise.reject(e);
            }
        }
    }
}
复制代码

5、注册模块

pay/PayPackage.java中,添加以下代码:

// 微信支付
modules.add(new WeChatPay(reactContext));
复制代码

这个文件的具体代码看上面的支付宝支付部分

image.png

6、修改AndroidManifest.xml

添加一个activity

<activity
        android:name=".wxapi.WXPayEntryActivity"
        android:label="@string/app_name"
        android:theme="@android:style/Theme.Translucent.NoTitleBar"
        android:exported="true"
        android:taskAffinity="!!!!!!你的包名!!!!!!"
        android:launchMode="singleTask">
</activity>
复制代码

7、在js中调用

import { NativeModules } from "react-native"

enum WeChatPayResult { SUCCESS = 0, ERROR = -1, CANCEL = -2, NOT_INSTALL = -3, VERSION_TOO_LOW = -4 }

const { errCode } = await NativeModules.WeChatPay.pay(request)
// 根据errCode做出不同处理
复制代码

其中传递过去的参数request就是一个包含如下属性的对象:

image.png

© 版权声明
THE END
喜欢就支持一下吧
点赞0 分享