前言
之前一篇介绍了react-native支付宝支付,微信这篇偷懒借鉴他人的react-native微信支付的例子,并对他的文章进行优化。
在集成之前获取APPID:商户在微信开放平台申请开发APP应用后,微信开放平台会生成APP的唯一标识APPID。
Android
1.微信开发平台配置
商户在微信开放平台申请开发应用后,微信开放平台会生成APP的唯一标识APPID。由于需要保证支付安全,需要在开放平台绑定商户应用包名和应用签名,设置好后才能正常发起支付。设置界面在【开放平台】中的栏目【管理中心 / 修改应用 / 修改开发信息】里面,如下图红框内所示。
应用签名获取可以使用:应用签名获取工具,将安装包安装到手机里,输入应用包名即可获取到签名。
注:安卓调用微信支付在调试模式使用开发签名只能调起微信客户端一次且无法回调,相信这个做安卓开发的朋友都遇到过,不多赘述。这里有个调试技巧,可以将应用的签名改为 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,否则后续将无法处理回调
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。如图标红位置所示:
2.添加微信白名单
info.plist
–> 右击
–> open as
–> source Code
–> 添加白名单:
<key>LSApplicationQueriesSchemes</key>
<array>
<string>weixin</string>
</array>
3.导入必要的库文件,如下图所示:
4.在项目目录下创建Group
Wxpay
,并创建WxpayModule
模块5.下载开发工具包(SDK),导入
Wxpay
中,最终如下图所示: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('支付失败');
});
}