react-native集成微信支付

前言

之前一篇介绍了react-native支付宝支付,微信这篇偷懒借鉴他人的react-native微信支付的例子,并对他的文章进行优化。

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

Android

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


chapter8_5_2.png

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

chapter8_5_3.png

注:安卓调用微信支付在调试模式使用开发签名只能调起微信客户端一次且无法回调,相信这个做安卓开发的朋友都遇到过,不多赘述。这里有个调试技巧,可以将应用的签名改为 debug 版本的签名,等支付调试完成后再改为生产环境的签名。

2.在android/app/build.gradle中增加微信sdk从jCenter的引用(如下代码块最后一行):

dependencies {
    implementation fileTree(dir: "libs", include: ["*.jar"])
    implementation "com.android.support:appcompat-v7:23.0.1"
    implementation "com.facebook.react:react-native:+"  // From node_modules
    implementation "com.tencent.mm.opensdk:wechat-sdk-android-with-mta:+" //微信支付,jCenter获取sdk
}

3.在android/app/src/main/java/com.xx下创建包名wxapi,注意此处包名一定要为wxapi,否则后续将无法处理回调

wxAnd1.jpg

4.编写 Module,在com.xx.wxapi包下创建WxpayModule.java,代码如下:

package com.xxx.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();
        //注意此处order.getString中的key对应自己服务器返回的支付参数key
        request.appId = order.getString("appid");
        request.partnerId = order.getString("partnerId");
        request.prepayId= order.getString("prepayid");
        request.packageValue = "Sign=WXPay";
        request.nonceStr= order.getString("nonceStr");
        request.timeStamp= order.getInt("timestamp")+"";
        request.sign= order.getString("sign");
        api.sendReq(request);
    }

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

}

5.编写 Package,在com.xx.wxapi包下创建WxpayPackage.java,代码如下:

package com.xxx.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 处理微信支付回调,在com.xx.wxapi包下创建WXPayEntryActivity.java,注意包名或类名不一致会造成无法回调,代码如下:

package com.xxx.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.MainApplication中注册模块:

 @Override
    protected List<ReactPackage> getPackages() {
      return Arrays.<ReactPackage>asList(
          new MainReactPackage(),
              // ...other packages
            new WxpayPackage()// <-- 注册模块
      );
    }

iOS

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


无效4444.jpeg

2.添加微信白名单
info.plist –> 右击 –> open as –> source Code –> 添加白名单:

<key>LSApplicationQueriesSchemes</key>
  <array>
    <string>weixin</string>
  </array>

3.导入必要的库文件,如下图所示:

2017-12-11-14-30-54.jpg

4.在项目目录下创建Group Wxpay,并创建WxpayModule模块
5.下载开发工具包(SDK),导入Wxpay中,最终如下图所示:
wx2.jpg

6.编写WxpayModule.h代码如下

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

@interface WxpayModule : NSObject <RCTBridgeModule, WXApiDelegate>
@end

7.编写WxpayModule.m代码如下:

#import "WxpayModule.h"

@implementation WxpayModule

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;
  //调起微信支付
  //注意order取的值对应的key要和自己服务器提供的一致
  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];
 }
}

9.至此,iOS端微信支付SDK集成成功

react-native

1.编写Wxpay.js工具类

import { NativeModules } from 'react-native';
export default NativeModules.Wxpay;

2.在入口文件(如index.js)中向微信注册应用

import Wxpay from './your/path/to/Wxpay';
Wxpay.registerApp(APPID); //向微信注册

3.调用Wxpay模块发起微信支付:

async wxPayAction(wxDic){
        //wxDic为从服务器获取的支付信息
        Wxpay.isSupported().then((isSupported)=>{
            if (isSupported) {
                Wxpay.pay(wxDic).then((data) =>{
                    console.log('data='+JSON.stringify(data));
                    //data = {"errCode":0}//支付成功
                    //data={"errCode":-2} //取消支付
                    if (data.errCode == 0){
                       //支付成功
                        });
                    } else {
                       //支付失败
                    }
                });
            }else {
                //未安装微信或当前微信版本较低
            }
        }).catch((err) => {
            console.log('err='+err);
            this.refs.toast.show('支付失败');
        });
    }
最后编辑于
©著作权归作者所有,转载或内容合作请联系作者
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念sama阅读 195,360评论 5 461
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 82,195评论 2 373
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
    开封第一讲书人阅读 142,543评论 0 323
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 52,420评论 1 266
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 61,242评论 4 357
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 46,224评论 1 273
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 36,626评论 3 384
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 35,301评论 0 253
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 39,589评论 1 292
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 34,660评论 2 312
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 36,423评论 1 326
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 32,286评论 3 313
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 37,662评论 3 299
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 28,951评论 0 19
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 30,237评论 1 250
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 41,613评论 2 342
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 40,804评论 2 335

推荐阅读更多精彩内容