native react 后台唤起

2019-05-05 23:51:46 DIWUCH 阅读数 486

一、 安卓配置

在{项目}/android/app/src/main/AndroidManifest.xml文件下添加:

<intent-filter>

  <action android:name="android.intent.action.VIEW" />

  <category android:name="android.intent.category.DEFAULT" />

  <category android:name="android.intent.category.BROWSABLE" />

  <data android:scheme="URL" />

</intent-filter>

注:

<data android:scheme="URL" />

中的URL是与第三方定的协议(URL://)

 

二、 iOS配置

看文档中需要往AppDelegate.m添加部分代码,但我进项目里面找过,发现只有:

这部分的代码,其余文档中的代码不加也不影响功能。

 

并且要在打包时在info中配置 URL Schemes:

三、 项目中

在componentDidMount中添加Linking的方法:

Linking.getInitialURL().then(url => this.handleOpenURL(url))

Linking.addEventListener('url', (event) => this.handleOpenURL(event.url))

 

注:第一个方法getInitialURL主要为了杀死APP后重启时跳转,第二个方法addEventListener为了监听在后台运行唤起时的跳转

总结遇到的问题:

如果只用了getInitialURL方法,则只有杀死APP再调起时才起作用。

如果只用addEventListener方法,则APP杀死后的首次调起不会起作用。

最好不要在AppState.addEventListener方法中的active加Linking的方法,遇到的问题是,在运行拉拉队前台时,手机锁屏再打开以后,会调用到linking方法。

可以自行写一个HTML文件进行调试:

<html>
<head>
<meta http-equiv="Content-Type" content="text/html" charset="utf-8" />
    <meta name="viewport" content="width=device-width" />
</head>
<a href="javascript:;" id="openApp">打开app</a>
<script type="text/javascript">
    function platform() {
        var u = navigator.userAgent || "", app = navigator.appVersion;
        return {
            trident: u.indexOf('Trident') > -1, //IE内核
            presto: u.indexOf('Presto') > -1, //opera内核
            webKit: u.indexOf('AppleWebKit') > -1, //苹果、谷歌内核
            gecko: u.indexOf('Gecko') > -1 && u.indexOf('KHTML') == -1,//火狐内核
            mobile: !!u.match(/AppleWebKit.*Mobile.*/), //是否为移动终端
            ios: !!u.match(/\(i[^;]+;( U;)? CPU.+Mac OS X/), //ios终端
            android: u.indexOf('Android') > -1 || u.indexOf('Linux') > -1, //android终端或者uc浏览器
            iPhone: u.indexOf('iPhone') > -1, //是否为iPhone或者QQHD浏览器
            iPad: u.indexOf('iPad') > -1, //是否iPad
            webApp: u.indexOf('Safari') == -1, //是否web应该程序,没有头部与底部
            weixin: u.indexOf('MicroMessenger') > -1, //是否微信 (2015-01-22新增)
            qq: u.match(/\sQQ/i) == " qq" //是否QQ
        };
    }
    document.getElementById('openApp').onclick = function(e){
        window.location = "URL://";//app协议
        if (platform().iPhone) {
            window.setTimeout(function () {
                window.location = "bu la bu la";//ios 下载地址
            }, 2000)
        }
        if (platform().android) {
            window.setTimeout(function () {
                window.location = "a ba a ba";//android 下载地址
            }, 2000)
        }
    };
</script>
</html>

 

2018-12-11 14:11:44 xue4345 阅读数 329

Android ReactNative和Activity间互相调用

因为项目中需要集成ReactNative,涉及到Android 原生Activity和RN之间的交互,就需要提前做预研,写了这个测试的demo;

  1. 将ReactNative集成到现有项目参考的ReactNative官网的教程

在编译时会存在一个错误,因为RN使用的findbug和Android中的版本不一致,会报错:
Warning:Conflict with dependency 'com.google.code.findbugs:jsr305'. Resolved versions for app (3.0.1) and test app (2.0.1) differ. See http://g.co/androidstudio/app-test-app-conflict for details.

解决办法:

在项目的app根目录中build.gradle中的

android{
……
configurations.all {
    resolutionStrategy.force 'com.google.code.findbugs:jsr305:3.0.0'
}
}
  1. ReactNative和原生互相调用
    1. RN唤起原生的Activity,参考Android原生模块创建一个插件;
      在插件添加一个public void startActivityForResult(String className, ReadableMap params, Callback resultCallback)的方法,调用context.startActivityForResult启动目标Activity;
      这里需要注意重新ReactNative的onActivityResult方法:
    @Override
    protected void onActivityResult(int requestCode, int resultCode, Intent data) {
        super.onActivityResult(requestCode, resultCode, data);
        //这网上很多资料没介绍
        mReactInstanceManager.onActivityResult(this,requestCode,resultCode,data);
    }
    
    1. Activity调用RN中的界面,页面跳转参考react-navigator,主要是在ReactNative使用的Activity的中添加上对应的scheme、host属性;并在react-navigator的StackNavigator注册页面;

具体的实现参考demo

2017-05-26 16:52:59 sinat_17775997 阅读数 1604

支付宝没有支持RN,所以只能通过在原生封装支付宝让RN调用。来一波效果图:

原文http://www.jianshu.com/p/bde956449299


选择支付宝支付.png

充值提示.png

在没有安装支付宝APP的情况下,跳转网页支付宝页面:


支付宝网页页面.png


整体流程:
1.在蚂蚁金服开放平台申请应用
2.原生集成支付宝
3.原生封装支付宝
4.RN调用参数定义
5.RN调用原生支付宝支付

一.在蚂蚁金服开放平台申请应用
蚂蚁金服开发平台:https://openhome.alipay.com/platform/manageHome.htm
进入应用:


55CCD31C-C591-4570-AE82-226840C54F60.png


按照支付宝文档要求逐步走创建应用流程(审核需要一天左右):


9E1793DD-9407-4999-9D95-47F1E0DEAA46.png


审核通过之后在接口加签方式上传RSA2(SHA256)密钥(推荐)


添加密钥.png


进入开发文档,选择APP支付:


0012210B-4DC1-4446-AEE4-5BB15D2391E7.png

二:原生集成支付宝
1.导入代码,进入SDK及DEMO下载,下载含有demo的一项,


646B6C0C-FF0E-41C3-AFC1-0E87DA542C00.png


2.回到进入iOS集成流程,按照文档一步步集成到xcode中
(1)把两个包AlipaySDK.bundle,AlipaySDK.framework导入到xcode中
(2)底层依赖库的添加:项目 --> build phases --> link binary with libraries
在link binary with libraries中点加号,添加上图中的依赖文件,如下图所示。


1C97D616-57A4-4C34-9A11-6446B501A9FC.png


(3)导入支付宝iosDemo_2.0中的Order.h和Order.m。之后Build一下


88B58AA3-470D-4D3E-9CF3-973A96E00C88.png


(4)在AppDelegate.m中,引入:

import <AlipaySDK/AlipaySDK.h> 添加下面代理(注意区分是否是iOS9之后)

- (BOOL)application:(UIApplication *)application
            openURL:(NSURL *)url
  sourceApplication:(NSString *)sourceApplication
         annotation:(id)annotation {

    if ([url.host isEqualToString:@"safepay"]) {
        //跳转支付宝钱包进行支付,处理支付结果
        [[AlipaySDK defaultService] processOrderWithPaymentResult:url standbyCallback:^(NSDictionary *resultDic) {
            NSLog(@"result = %@",resultDic);
        }];
    }
    return YES;
}

// NOTE: 9.0以后使用新API接口
- (BOOL)application:(UIApplication *)app openURL:(NSURL *)url options:(NSDictionary<NSString*, id> *)options
{
    if ([url.host isEqualToString:@"safepay"]) {
        //跳转支付宝钱包进行支付,处理支付结果
        [[AlipaySDK defaultService] processOrderWithPaymentResult:url standbyCallback:^(NSDictionary *resultDic) {
            NSLog(@"result = %@",resultDic);
        }];
    }
    return YES;
}

三.原生封装支付宝
1.新建一个支付按钮继承与UIButton的类(我的是WeChatPayBtn)
在WeChatPayBtn.h中引入头文件:#import "Order.h",#import <AlipaySDK/AlipaySDK.h>,#import <RCTBridge.h>,#import <RCTConvert.h>,#import <RCTComponent.h>,#import <UIView+React.h>,#import <RCTEventDispatcher.h>并集成


引入文件.png

2.在WeChatPayBtn.m中 doAlipayPay是调用支付宝支付,按钮点击方法pay中用到一个代理。WeChatPayBtn的代理是即将要新建的继承于RCTViewManager的WeChatPayManager, _signedString是与JS通信传入的参数,下面的第四条RN调用参数定义会介绍

#import "WeChatPayBtn.h"
#import "WXApiManager.h"
#import "WXApiObject.h"
#import "WXApi.h"

@implementation WeChatPayBtn
-(instancetype)initWithFrame:(CGRect)frame{
  if ((self = [super initWithFrame:frame])) {
    [self addTarget:self action:@selector(pay)
   forControlEvents:UIControlEventTouchUpInside];
    [self setBackgroundColor:[UIColor redColor]];
  }
  return self;
}
//调起支付宝支付
- (void)doAlipayPay
{
    NSString *appScheme = @"CloudProcessing";
    NSLog(@"支付宝签名:%@",_signedString);
    // NOTE: 调用支付结果开始支付
    [[AlipaySDK defaultService] payOrder:_signedString fromScheme:appScheme callback:^(NSDictionary *resultDic) {
      NSLog(@"支付宝支付结果:reslut = %@",resultDic);
    }];
}
//点击btn时 触发支付宝支付
-(void)pay{
  if([_delegate respondsToSelector:@selector(ButtonClicked)]){
    [self.delegate ButtonClicked];
  }
  //支付宝支付
  [self doAlipayPay];
}

3.新建新建的继承于RCTViewManager的WeChatPayManager
注意看WeChatPayManager.h只引入了#import <Foundation/Foundation.h>


WeChatPayManager.h.png

4.WeChatPayManager.m,WeChatPay(重点)js 中会用到。添加标记宏RCT_EXPORT_MODULE()将该模块导出作为一个组件,实现-(UIView *)view方法,在view方法中初始化了之前建立的WeChatPayBtn。


WeChatPayManager.m.png
#import "WeChatPayManager.h"
#import "WXApi.h"
#import "RCTViewManager.h"
#import "WeChatPayBtn.h"
@interface WeChatPay : RCTViewManager
@property (nonatomic,strong) WeChatPayBtn *bt;
@end

@implementation WeChatPay
RCT_EXPORT_MODULE()
-(UIView *)view{
  _bt = [[WeChatPayBtn alloc]initWithFrame:CGRectMake(20, 250, 200, 40)];
  _bt.delegate = self;
  NSLog(@"进入_we_btn");
  return _bt;
}
@end

原生部分代码最基本的部分完成了,下面还需要定义参数(作用是从react native 的js传值给WeChatPayBtn中的支付宝支付签名_signedString)
四.RN调用参数定义
需要用到的参数是signedString,服务端返回的支付宝订单加签,在调用支付宝支付的入参。
1.在WeChatPayBtn.h文件中定义参数signedString

//支付宝签名
@property (nonatomic,copy) NSString *signedString;

2.WeChatPayManager.m文件 中导出参数 RCT_EXPORT_VIEW_PROPERTY(signedString, NSString)

#import "WeChatPayManager.h"
#import "WXApi.h"
#import "RCTViewManager.h"
#import "WeChatPayBtn.h"
@interface WeChatPay : RCTViewManager<WeChatDelegate>
@property (nonatomic,strong) WeChatPayBtn *bt;
@end

@implementation WeChatPay
RCT_EXPORT_MODULE()
//将参数导出给JS
RCT_EXPORT_VIEW_PROPERTY(signedString, NSString)
-(UIView *)view{
  _bt = [[WeChatPayBtn alloc]initWithFrame:CGRectMake(20, 250, 200, 40)];
  _bt.delegate = self;
  NSLog(@"进入_we_btn");
  return _bt;
}

五.RN调用原生支付宝支付
1.接下来实现JS中的组件封装与简单调用。我是在一个JS文件中完成组件封装和调用。你也可以分组件完成。首先导入原生组件,从导入中取到创建的组件,作为默认的组件导出,以供其他JS调用。这里,我们其实可以直接在其他JS中调用了,但是为了进行参数的封装,我们也需要将其封装成一个单独的组件
js中引入import {requireNativeComponent} from 'react-native',
var PayManage = requireNativeComponent('WeChatPay',WeChatPayMan)
WeChatPay就是在原生中WeChatPayManager.m中定义的, PayManage 是调用原生的组件,

export class WeChatPayMan extends Component {
    //传递到原生的属性
    static propTypes = {
        signedString:PropTypes.string,
    };
    render() {
        return (
            <PayManage {...this.props}/>
        );
    }

    componentDidMount() {
        console.log('支付宝支付JS界面')
    }
}

上面代码中static propTypes中的signedString是需要传递到原生的支付宝加签

2.封装组件的调用。下面代码所示是前面封装组件的调用,这里我们已经封装了很多JS需要传递给原生的参数, signedString就是原生中调起支付宝支付的签名(在服务器后台配置通过网络请求返回)

<WeChatPayMan
                        style={{marginTop:100,width:width-80,height:40,alignItems:'center',
                            justifyContent:'center',borderRadius:5,backgroundColor:'#35a40c'
                        }}
                        signedString={this.state.signedString}
                        }}
                    >

到这里RN调用iOS原生支付已全部实现完成

2017-11-21 11:38:33 meiyulong518 阅读数 1275

React Native iOS 集成支付宝支付功能–回调问题

首先 附上GitHub地址0x5e/react-native-alipay

react-native-alipay Git有不少版本 当你使用npm时需要多加注意了

之前打算用react-native-yunpeng-alipay 和 react-native-alipay 但是继承了进去后 编译成功了 ,在JS里面一直不能拿到方法(以后有机会还会再试的),

后来就找到了$ yarn add @0x5e/react-native-alipay ,集成后可以jump 到支付宝支付并且支付成功,但是JS的回调一直不走,Xcode里面的回调是有拿到返回值的,

最终的解决办法是参考的react-native-alipay 里面的解决方法:

这里写图片描述

在RCTAlipay.m 中:

#import "RCTAlipay.h"
#import <AlipaySDK/AlipaySDK.h>
static NSString *const kOpenURLNotification = @"RCTOpenURLNotification";

@implementation RCTAlipay{
    RCTPromiseResolveBlock _resolve;//定义了一个全局的Block
}

- (instancetype)init {
    if (self = [super init]) {
        self->_resolve = nil;//初始化置空
        [[NSNotificationCenter defaultCenter] addObserver:self selector:@selector(handleOpenURL:) name:kOpenURLNotification object:nil];
    }
    return self;
}

- (void)dealloc {
    [[NSNotificationCenter defaultCenter] removeObserver:self];
}

- (void)handleOpenURL:(NSNotification *)notification {
    NSString *urlString = notification.userInfo[@"url"];
    NSURL *url = [NSURL URLWithString:urlString];
    if ([url.host isEqualToString:@"safepay"]) {
        [AlipaySDK.defaultService processOrderWithPaymentResult:url standbyCallback:^(NSDictionary *resultDic) {
         //由于在跳转支付宝客户端支付的过程中,商户app在后台很可能被系统kill了,所以pay接口的callback就会失效,请商户对standbyCallback返回的回调结果进行处理,就是在这个方法里面处理跟callback一样的逻辑
            if (self->_resolve) {
                self->_resolve(resultDic);//接受并返回回调信息
                self->_resolve = nil;
            }
            NSLog(@"processOrderWithPaymentResult = %@", resultDic);
        }];

        [AlipaySDK.defaultService processAuth_V2Result:url standbyCallback:^(NSDictionary *resultDic) {
            NSLog(@"processAuth_V2Result = %@", resultDic);
        }];
    }
}

- (dispatch_queue_t)methodQueue
{
    return dispatch_get_main_queue();
}
RCT_EXPORT_MODULE()

RCT_EXPORT_METHOD(authWithInfo:(NSString *)infoStr resolver:(RCTPromiseResolveBlock)resolve rejecter:(RCTPromiseRejectBlock)reject) {
    [AlipaySDK.defaultService auth_V2WithInfo:infoStr fromScheme:self.appScheme callback:^(NSDictionary *resultDic) {
        resolve(resultDic);
    }];
}

RCT_EXPORT_METHOD(pay:(NSString *)orderInfo resolver:(RCTPromiseResolveBlock)resolve rejecter:(RCTPromiseRejectBlock)reject) {
        self->_resolve = resolve;//跳到支付宝时候  赋值
    [AlipaySDK.defaultService payOrder:orderInfo fromScheme:self.appScheme callback:^(NSDictionary *resultDic) {
         self->_resolve = nil;//回调置空 
        resolve(resultDic);
    }];
}

RCT_EXPORT_METHOD(payInterceptorWithUrl:(NSString *)urlStr
                  resolver:(RCTPromiseResolveBlock)resolve
                  rejecter:(RCTPromiseRejectBlock)reject) {
    [AlipaySDK.defaultService payInterceptorWithUrl:urlStr fromScheme:self.appScheme callback:^(NSDictionary *resultDic) {
        resolve(resultDic);
    }];
}

RCT_EXPORT_METHOD(getVersion:(RCTPromiseResolveBlock)resolve) {
    resolve(AlipaySDK.defaultService.currentVersion);
}

- (NSString *)appScheme {
    NSArray *urlTypes = NSBundle.mainBundle.infoDictionary[@"CFBundleURLTypes"];
    for (NSDictionary *urlType in urlTypes) {
        NSString *urlName = urlType[@"CFBundleURLName"];
        if ([urlName hasPrefix:@"alipay"]) {
            NSArray *schemes = urlType[@"CFBundleURLSchemes"];
            return schemes.firstObject;
        }
    }
    return nil;
}

@end

注意:

  1. URL_Schemes 的设置
  2. 注意 appdelegate.m中的
- (BOOL)application:(UIApplication *)application openURL:(NSURL *)url sourceApplication:(NSString *)sourceApplication annotation:(id)annotation{

  return [RCTLinkingManager application:application openURL:url sourceApplication:sourceApplication annotation:annotation];
}
- (BOOL)application:(UIApplication *)application openURL:(NSURL *)url options:(NSDictionary<UIApplicationOpenURLOptionsKey, id> *)options{
  return [RCTLinkingManager application:application openURL:url options:options];
}
2018-04-24 16:17:28 jasonzds 阅读数 3527
最近在忙着做rn移动端的开发,碰到不少问题,其中把微信支付的问题分享给大家,希望对大家有所帮助
react-native 集成微信支付主要有两种方法(目前来说,不排除以后还有别的npm第三方包)第一种是使用npm包(react-native-wechat),这个包是别人封装好的,优点:使用过程中方便,不写原生的代码,但是我在用这个包时碰到一个最奇葩的问题,就是在ios上面真机调试没有任何错误,打包之后,运行ipa安装包时,微信支付报错( <Notice>: Exception '-[__NSCFString unsignedIntValue]: unrecognized selector sent to instance 0x1c4233ae0' ),同样的代码,在android是好的,ios调试是好的,唯独ipa包是报错的,后来果断的放弃这个包改用rn调用原生支付的模式,也就是今天我讲的第二种方法。期间参考了这篇博客:

http://fangzf.me/2017/12/11/react-native-集成微信支付/

但是这篇博客有些坑,且看以下简述:

第一步 场景介绍

适用于商户在移动端APP中集成微信支付功能。
商户APP调用微信提供的SDK调用微信支付模块,商户APP会跳转到微信中完成支付。
支付完后跳回到商户APP内,最后展示支付结果。
目前微信支付支持手机系统有:IOS(苹果)、Android(安卓)和WP(Windows Phone)。


第二步 集成微信支付SDK

android的导入方法

1) 获取APPID:商户在微信开放平台申请开发APP应用后,微信开放平台会生成APP的唯一标识APPID。

后台设置
商户在微信开放平台申请开发应用后,微信开放平台会生成APP的唯一标识APPID。由于需要保证支付安全,需要在开放平台绑定商户应用包名和应用签名,设置好后才能正常发起支付。设置界面在【开放平台】中的栏目【管理中心 / 修改应用 / 修改开发信息】里面,如下图红框内所示。



注意了前方高能,此处有坑:android 应用的签名有调试签名和上线签名两个,调试阶段,先运行程序,然后根据签名工具GenSignature获取签名,这个签名是调试的签名,配好之后,需要3个小时左右才能生效(微信同步数据需要时间),反正不是立马生效的,所以配好后马上调用微信支付,肯定是失败的(跳不到微信支付的页面),需要等2-3个小时,再调用,就会跳到微信支付的页面。同时上线也是一样的,别忘了改正式版的签名,用GenSignature获取打包后的apk签名,然后在配上去,2-3个小时,才能生效。同一个程序调试和发布的签名是不一样的。


应用签名获取可以使用:应用签名获取工具,将安装包安装到手机里,输入应用包名即可获取到签名。




2) 导入微信SDK,修改android/app/build.gradle添加如下代码:
  1. dependencies { ...... compile "com.tencent.mm.opensdk:wechat-sdk-android-with-mta:+" ......}

3)在com.xx.xx创建包名wxapi,注意此处包名一定要为wxapi,否则后续将无法处理回调
针对没有原生开发经验的可能并不太明白这句话意思。
注意了,此处有坑:假如你创建了一个应用:react-native init test
那么android程序的目录一定是这样的:

创建的wxapi包一定要在test里面,这样才能处理微信支付后的回调结果,如图



4)编写 Module,在wxapi包下创建WxpayModule.java,代码如下:
package com.test.wxapi;

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.tencent.mm.opensdk.modelpay.PayReq;
import com.tencent.mm.opensdk.openapi.IWXAPI;
import com.tencent.mm.opensdk.openapi.WXAPIFactory;

class WxpayModule extends ReactContextBaseJavaModule {

 private IWXAPI api;
 static String APP_ID = "";
 static Promise promise = null;

 WxpayModule(ReactApplicationContext reactContext) {
   super(reactContext);
   api = WXAPIFactory.createWXAPI(reactContext, null);
 }

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

 @ReactMethod
 public void registerApp(String APP_ID) { // 向微信注册
   WxpayModule.APP_ID = APP_ID;
   api.registerApp(APP_ID);
 }

 @ReactMethod
 public void pay(final ReadableMap order, Promise promise) {
   WxpayModule.promise = promise;
   PayReq request = new PayReq();
   request.appId = order.getString("appId");
   request.partnerId = order.getString("partnerId");
   request.prepayId= order.getString("prepayId");
   request.packageValue = order.getString("package");
   request.nonceStr= order.getString("nonceStr");
   request.timeStamp= order.getString("timeStamp");
   request.sign= order.getString("sign");
   api.sendReq(request);
 }

 @ReactMethod
 public void isSupported(Promise promise) { // 判断是否支持调用微信SDK
   boolean isSupported = api.isWXAppInstalled();
   promise.resolve(isSupported);
 }

}
此处也有个小坑:第一行的报名一定要写对,同时request.appId = order.getString("appId");这个appid是根据你服务器生成预支付订单返回的数据决定的,你服务器返回APPID,这个地方就而写APPID。写一篇我会写一个基于nodejs服务端微信支付生成预支付订单的接口实现。


5)编写 Package,在wxapi包下创建WxpayPackage.java,代码如下:
package com.test.wxapi;

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 WxpayPackage implements ReactPackage {

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

 @Override
 public List<NativeModule> createNativeModules(
         ReactApplicationContext reactContext) {
   List<NativeModule> modules = new ArrayList<>();
   modules.add(new WxpayModule(reactContext));
   return modules;
 }

}

6)编写 WXPayEntryActivity 处理微信支付回调,在wxapi包下创建WXPayEntryActivity.java,注意包名或类名不一致会造成无法回调,代码如下:
package com.test.wxapi;

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

import com.facebook.react.bridge.Arguments;
import com.facebook.react.bridge.WritableMap;
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, WxpayModule.APP_ID);
       api.handleIntent(getIntent(), this);
   }

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

 @Override
 public void onReq(BaseReq req) {
 }

 @Override
 public void onResp(BaseResp resp) {
   Log.d(TAG, "onPayFinish, errCode = " + resp.errCode);
   if (resp.getType() == ConstantsAPI.COMMAND_PAY_BY_WX) {
     WritableMap map = Arguments.createMap();
     map.putInt("errCode", resp.errCode);
     WxpayModule.promise.resolve(map);
     finish();
   }
 }
}
7)最后在 Android 这边要做的最后一件事就是注册这个模块,在com.xx.xx.MainApplication中注册模块:
@Override
protected List<ReactPackage> getPackages() {
   return Arrays.<ReactPackage>asList(
       new MainReactPackage(),
       // ...other packages
       new WxpayPackage() // <-- 注册模块
   );
}
ios的导入方法


1)项目设置APPID,在Xcode中打开项目,设置项目属性中的URL Schemes为你的APPID。如图标红位置所示:


2)添加微信白名单和修改http访问权限,默认的xcode是https的访问


3)添加必要的类库 这个pay相当于test,就是工程名字,不影响支付功能


这3个文件去微信开放平台下载

4)导入必要的库文件



5)在项目目录下创建Group Wxapi,并创建WxpayMoudle模块
6)编写WxpayModule.h代码如下:

#import <React/RCTBridgeModule.h>
#import <React/RCTLog.h>
#import "WXApiObject.h"
#import "WXApi.h"

@interface WxpayMoudle : NSObject <RCTBridgeModule, WXApiDelegate>
@end
7)编写WxpayModule.m代码如下:
#import "WxpayMoudle.h"

@implementation WxpayMoudle

RCTPromiseResolveBlock resolveBlock = nil;

- (instancetype)init
{
 self = [super init];
 if (self) {
   [[NSNotificationCenter defaultCenter] addObserver:self selector:@selector(handleWXPay:) name:@"WXPay" object:nil];
 }
 return self;
}

- (void)dealloc
{
 [[NSNotificationCenter defaultCenter] removeObserver:self];
}

- (void)handleWXPay:(NSNotification *)aNotification
{
 NSString * errCode =  [aNotification userInfo][@"errCode"];
 resolveBlock(@{@"errCode": errCode});
}

RCT_EXPORT_METHOD(registerApp:(NSString *)APP_ID){
 [WXApi registerApp: APP_ID];//向微信注册
}

RCT_EXPORT_METHOD(pay:(NSDictionary *)order
                 resolver:(RCTPromiseResolveBlock)resolve
                 rejecter:(RCTPromiseRejectBlock)reject){
 resolveBlock = resolve;
 //调起微信支付
 PayReq *req = [[PayReq alloc] init];
 req.partnerId = [order objectForKey:@"partnerId"];
 req.prepayId = [order objectForKey:@"prepayId"];
 req.nonceStr = [order objectForKey:@"nonceStr"];
 req.timeStamp = [[order objectForKey:@"timeStamp"] intValue];
 req.package = [order objectForKey:@"package"];
 req.sign = [order objectForKey:@"sign"];
 [WXApi sendReq:req];
}

RCT_REMAP_METHOD(isSupported, // 判断是否支持调用微信SDK
                 resolver:(RCTPromiseResolveBlock)resolve
                 rejecter:(RCTPromiseRejectBlock)reject){
 if (![WXApi isWXAppInstalled]) resolve(@NO);
 else resolve(@YES);
}

RCT_EXPORT_MODULE(Wxpay);

@end

8)处理微信支付回调,在AppDelegate.m中添加如下代码:
//支付回调9以后
- (BOOL)application:(UIApplication *)app openURL:(NSURL *)url options:(NSDictionary*)options {
 return  [WXApi handleOpenURL:url delegate:self];
}
//支付回调9以前
- (BOOL)application:(UIApplication *)application handleOpenURL:(NSURL *)url {
 return  [WXApi handleOpenURL:url delegate:self];
}
//ios9以后的方法
- (BOOL)application:(UIApplication *)application openURL:(NSURL *)url sourceApplication:(NSString *)sourceApplication annotation:(id)annotation {
 return [WXApi handleOpenURL:url delegate:self];
}

#pragma mark - wx callback

- (void) onReq:(BaseReq*)req
{
 // TODO Something
}

- (void)onResp:(BaseResp *)resp
{
 //判断是否是微信支付回调 (注意是PayResp 而不是PayReq)
 if ([resp isKindOfClass:[PayResp class]])
 {
   //发出通知 从微信回调回来之后,发一个通知,让请求支付的页面接收消息,并且展示出来,或者进行一些自定义的展示或者跳转
   NSNotification * notification = [NSNotification notificationWithName:@"WXPay" object:nil userInfo:@{@"errCode":@(resp.errCode)}];
   [[NSNotificationCenter defaultCenter] postNotification:notification];
 }
}
致此微信支付的相关原生功能模块都写好了,android和ios的。接下来要react-native去调用这些原生的功能方法。react-native怎么和原生交互请看官方文档:


第三步 react-native 端
1)修改原生代码后,需要重新打包运行程序:
react-native run-android # 运行Android端
react-native run-ios # 运行iOS端
2)编写Wxpay.js工具类
import { NativeModules } from 'react-native';
export default NativeModules.Wxpay;
3)在入口文件index.js向微信注册应用
import Wxpay from './your/path/to/Wxpay';
Wxpay.registerApp(APPID); //向微信注册
4)调用Wxpay模块发起微信支付:
import Wxpay from './your/path/to/Wxpay';


async pay(params) { // params 为后端提供的参数
    let isSupported = await Wxpay.isSupported();
    if (!isSupported) { // 判断是否支持微信支付
      alertModel('找不到微信应用,请安装最新版微信');
      return;
    }
    let ret = await Wxpay.pay(params); // 调起微信客户端,发起支付
    if (ret.errCode === 0) {
      // 支付成功回调
       alertModel('支付成功');
    } else {
      // 支付失败回调
      alertModel('支付失败');
    }
  }

服务端返回的params数据结构如
{
    "appId": "wx28f86efd23cc3dse",
    "partnerId": "1494562862",
    "prepayId": "wx24153040008020562a5d00291301203432",
    "nonceStr": "d7c18718502a444a1a88227b0915de84",
    "timeStamp": "1524555040",
    "package": "Sign=WXPay",
    "sign": "44718752BAC35C8C29896F7707A96A77"
}