react-native 集成微信支付

4 篇文章 0 订阅
3 篇文章 0 订阅
最近在忙着做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"
}



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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值