安卓接支付宝支付
官方文档: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
(没有这个目录就自己新建一个)目录下:
2、在android
目录下的build.gradle
中,添加下面的内容,将libs
目录作为依赖仓库:
allprojects {
repositories {
// 添加下面的内容
flatDir {
dirs 'libs'
}
// ... jcenter() 等其他仓库
}
复制代码
3、在app
目录下的build.gradle
中,添加下面的内容,将支付宝SDK作为项目的依赖:
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
复制代码
3、编写调用支付宝支付接口
大家可以参考我的项目目录,因为我这个项目需要接支付宝和微信支付,所以把支付的模块写在一起,然后把支付宝和微信的单独分开来。
1、创建一个pay
的包,然后再创建一个alipay
的包,新建一个AliPay.java
文件:
2、在下载的Demo中把PayResult.java
复制到pay/alipay
目录下:
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
其具体代码如下:
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、后台设置
这部分我就不多说了,大家看着官方文档去做就好啦!就是填写这两项即可!
2、导入微信支付SDK
1、在app
目录下的build.gradle
中,添加下面的内容,将微信SDK作为项目的依赖:
dependencies {
// 微信支付
implementation "com.tencent.mm.opensdk:wechat-sdk-android-without-mta:+"
// 其他依赖
}
复制代码
3、写原生代码
1、搭建微信支付目录
在pay
这个包底下,创建一个wechat
的包:
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
的包。
⚠注意注意!!!!这个包一定要在你的包底下这一层,不能放在别的地方!
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));
复制代码
这个文件的具体代码看上面的支付宝支付
部分
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
就是一个包含如下属性的对象: