React Native微信

Android

申请微信appidhttp://open.weixin.qq.com/
image.png

  1. 引入sdk
    android/app/build.gradle
dependencies {
  ...
  api 'com.tencent.mm.opensdk:wechat-sdk-android:+'
  ...
}
  1. 添加权限
    android/app/src/main/AndroidMainifest.xml




  1. 添加代码混淆规则
# 微信
-keep class com.tencent.mm.opensdk.**{*;}
-keep class com.tencent.wxop.** {*;}
-keep class com.tencent.mm.sdk.** {*;}
  1. 写android原生

在android/app/src/main/java/com/xxx 文件里创建文件夹wechat
创建WechatModule.java

package com.xxx.wechat;

import android.content.Context;
import android.graphics.Bitmap;
import android.net.Uri;
import androidx.annotation.Nullable;

import com.facebook.react.bridge.Arguments;
import com.facebook.react.bridge.Callback;
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.facebook.datasource.DataSource;
import com.facebook.drawee.backends.pipeline.Fresco;
import com.facebook.imagepipeline.image.CloseableImage;
import com.facebook.imagepipeline.datasource.BaseBitmapDataSubscriber;
import com.facebook.imagepipeline.common.ResizeOptions;
import com.facebook.imagepipeline.core.ImagePipeline;
import com.facebook.imagepipeline.request.ImageRequest;
import com.facebook.imagepipeline.request.ImageRequestBuilder;
import com.facebook.common.references.CloseableReference;
import com.facebook.common.executors.UiThreadImmediateExecutorService;
import com.facebook.common.util.UriUtil;

import com.tencent.mm.opensdk.constants.Build;
import com.tencent.mm.opensdk.modelmsg.SendAuth; // sendAuth
import com.tencent.mm.opensdk.modelpay.PayReq;
import com.tencent.mm.opensdk.openapi.IWXAPI;
import com.tencent.mm.opensdk.openapi.WXAPIFactory;
import com.tencent.mm.opensdk.modelmsg.SendMessageToWX;
import com.tencent.mm.opensdk.modelmsg.WXFileObject;
import com.tencent.mm.opensdk.modelmsg.WXImageObject;
import com.tencent.mm.opensdk.modelmsg.WXMediaMessage;
import com.tencent.mm.opensdk.modelmsg.WXMusicObject;
import com.tencent.mm.opensdk.modelmsg.WXTextObject;
import com.tencent.mm.opensdk.modelmsg.WXVideoObject;
import com.tencent.mm.opensdk.modelmsg.WXWebpageObject;
import com.tencent.mm.opensdk.modelmsg.WXMiniProgramObject;
import com.tencent.mm.opensdk.modelbiz.WXLaunchMiniProgram;

import java.io.File;
import java.io.ByteArrayOutputStream;
import java.net.URI;
import java.util.ArrayList;
import java.util.UUID;

public class WechatModule extends ReactContextBaseJavaModule {

    private static ReactApplicationContext reactContext;
    private final static String NOT_REGISTERED = "未安装微信";
    private IWXAPI api = null;
    private String appId;
    
    public static Promise promise;

    public WechatModule(ReactApplicationContext context) {
        super(context);
        reactContext = context;
    }

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

    // 注册appId
    @ReactMethod
    private void registerApp(String appId, Promise promise) {
        try {
            this.appId = appId;
            api = WXAPIFactory.createWXAPI(reactContext.getApplicationContext(), null, false);
            promise.resolve(api.registerApp(appId));
        } catch (Exception e) {
            promise.reject("-1", e.getMessage());
        }
    }

    private static byte[] bitmapResizeGetBytes(Bitmap image, int size){
        ByteArrayOutputStream baos = new ByteArrayOutputStream();
        // 质量压缩方法,这里100表示第一次不压缩,把压缩后的数据缓存到 baos
        image.compress(Bitmap.CompressFormat.JPEG, 100, baos);
        int options = 100;
        // 循环判断压缩后依然大于 32kb 则继续压缩
        while (baos.toByteArray().length / 1024 > size) {
            // 重置baos即清空baos
            baos.reset();
            if (options > 10) {
                options -= 8;
            } else {
                return bitmapResizeGetBytes(Bitmap.createScaledBitmap(image, 280, image.getHeight() / image.getWidth() * 280, true), size);
            }
            // 这里压缩options%,把压缩后的数据存放到baos中
            image.compress(Bitmap.CompressFormat.JPEG, options, baos);
        }
        return baos.toByteArray();
    }

    // 判断是否安装客户端
    @ReactMethod
    private void isWxInstalled(Promise promise) {
        try {
            if (api == null) {
                throw new Exception(NOT_REGISTERED);
            }
            promise.resolve(api.isWXAppInstalled());
        } catch (Exception e) {
            promise.reject("-1", e.getMessage());
        }
    }

    // 打开微信客户端
    @ReactMethod
    public void openWxApp(Promise promise) {
        try {
            if (api == null) {
                throw new Exception(NOT_REGISTERED);
            }
            promise.resolve(api.openWXApp());
        } catch (Exception e) {
            promise.reject("-1", e.getMessage());
        }
    }

    // 打开微信小程序
    @ReactMethod
    public void openMiniProgram(String appId, String path, Promise promise) {
        try {
            if (api == null) {
                throw new Exception(NOT_REGISTERED);
            }
            WXLaunchMiniProgram.Req req = new WXLaunchMiniProgram.Req();
            req.userName = appId;
            req.path = path;
            req.miniprogramType = WXLaunchMiniProgram.Req.MINIPTOGRAM_TYPE_RELEASE;
            promise.resolve(api.sendReq(req));
        } catch (Exception e) {
            promise.reject("-1", e.getMessage());
        }
    }

    // 获取微信版本号
    @ReactMethod
    private void getAppVersion(Promise promise) {
        try {
             if (api == null) {
                 throw new Exception(NOT_REGISTERED);
             }
            promise.resolve(api.getWXAppSupportAPI());
        } catch (Exception e) {
            promise.reject("-1", e.getMessage());
        }
    }

    // 微信授权登录
    @ReactMethod
    public void sendAuthRequest(String scope, String state, Promise promise) {
        try {
            if (api == null) {
                throw new Exception(NOT_REGISTERED);
            }
            SendAuth.Req req = new SendAuth.Req();
            req.scope = scope;
            req.state = state;
            promise.resolve(api.sendReq(req));
        } catch (Exception e) {
            promise.reject("-1", e.getMessage());
        }
    }

    // 微信支付
    @ReactMethod
    private void pay(ReadableMap request, Promise promise) {
        WechatModule.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_INSURANCE_SDK_INT) {
            api.sendReq(req);
        } else if (wxSdkVersion == 0) {
            WritableMap map = Arguments.createMap();
            map.putInt("errCode", -3);
            WechatModule.promise.resolve(map);
        } else {
            WritableMap map = Arguments.createMap();
            map.putInt("errCode", -4);
            WechatModule.promise.resolve(map);
        }
    }
    // 分享小程序小程序
    @ReactMethod
    public void shareMiniProgram(ReadableMap data, Promise promise){
        if (api == null) {
            callback.invoke(NOT_REGISTERED);
            return;
        }
        WXMiniProgramObject miniProgramObj = new WXMiniProgramObject();
        // 兼容低版本的网页链接
        miniProgramObj.webpageUrl = data.hasKey("webpageUrl") ? data.getString("webpageUrl") : null;
        // 正式版:0,测试版:1,体验版:2
        miniProgramObj.miniprogramType = data.hasKey("miniProgramType") ? data.getInt("miniProgramType") : WXMiniProgramObject.MINIPTOGRAM_TYPE_RELEASE;
        // 小程序原始id
        miniProgramObj.userName = data.hasKey("userName") ? data.getString("userName") : null;
        // 小程序页面路径;对于小游戏,可以只传入 query 部分,来实现传参效果,如:传入 "?foo=bar"
        miniProgramObj.path = data.hasKey("path") ? data.getString("path") : null;
        final WXMediaMessage msg = new WXMediaMessage(miniProgramObj);
        // 小程序消息 title
        msg.title = data.hasKey("title") ? data.getString("title") : null;
        // 小程序消息 desc
        msg.description = data.hasKey("description") ? data.getString("description") : null;
        String thumbImageUrl = data.hasKey("hdImageUrl") ? data.getString("hdImageUrl") : data.hasKey("thumbImageUrl") ? data.getString("thumbImageUrl") : null;
        if (thumbImageUrl != null && !thumbImageUrl.equals("")) {
            this._getImage(Uri.parse(thumbImageUrl), null, new ImageCallback() {
                @Override
                public void invoke(@Nullable Bitmap bmp) {
                    // 小程序消息封面图片,小于128k
                    if (bmp != null) {
                        msg.thumbData = bitmapResizeGetBytes(bmp, 128);
                    }
                    // 构造一个Req
                    SendMessageToWX.Req req = new SendMessageToWX.Req();
                    req.transaction = "miniProgram";
                    req.message = msg;
                    req.transaction = UUID.randomUUID().toString();
                    req.scene = data.hasKey("scene") ? data.getInt("scene") : SendMessageToWX.Req.WXSceneSession;
                    callback.invoke(null, api.sendReq(req));
                }
            });
        } else {
            // 构造一个Req
            SendMessageToWX.Req req = new SendMessageToWX.Req();
            req.transaction = "miniProgram";
            req.message = msg;
            req.transaction = UUID.randomUUID().toString();
            req.scene = data.hasKey("scene") ? data.getInt("scene") : SendMessageToWX.Req.WXSceneSession;
            callback.invoke(null, api.sendReq(req));
        }
    }
    // 分享到朋友圈
    @ReactMethod
    public void shareToTimeline(ReadableMap data, Callback callback) {
        if (api == null) {
            callback.invoke(NOT_REGISTERED);
            return;
        }
        _share(SendMessageToWX.Req.WXSceneTimeline, data, callback);
    }
    // 分享到朋友或群
    @ReactMethod
    public void shareToSession(ReadableMap data, Callback callback) {
        if (api == null) {
            callback.invoke(NOT_REGISTERED);
            return;
        }
        _share(SendMessageToWX.Req.WXSceneSession, data, callback);
    }

    // 收藏
    @ReactMethod
    public void shareToFavorite(ReadableMap data, Callback callback) {
        if (api == null) {
            callback.invoke(NOT_REGISTERED);
            return;
        }
        _share(SendMessageToWX.Req.WXSceneFavorite, data, callback);
    }

    private void _share(final int scene, final ReadableMap data, final Callback callback) {
        Uri uri = null;
        if (data.hasKey("thumbImage")) {
            String imageUrl = data.getString("thumbImage");

            try {
                uri = Uri.parse(imageUrl);
                if (uri.getScheme() == null) {
                    uri = getResourceDrawableUri(getReactApplicationContext(), imageUrl);
                }
            } catch (Exception e) {
            }
        }

        if (uri != null) {
            this._getImage(uri, new ResizeOptions(100, 100), new ImageCallback() {
                @Override
                public void invoke(@Nullable Bitmap bitmap) {
                    WechatModule.this._share(scene, data, bitmap, callback);
                }
            });
        } else {
            this._share(scene, data, null, callback);
        }
    }

    private void _getImage(Uri uri, ResizeOptions resizeOptions, final ImageCallback imageCallback) {
        BaseBitmapDataSubscriber dataSubscriber = new BaseBitmapDataSubscriber() {
            @Override
            protected void onNewResultImpl(Bitmap bitmap) {
                if (bitmap != null) {
                    if (bitmap.getConfig() != null) {
                        bitmap = bitmap.copy(bitmap.getConfig(), true);
                        imageCallback.invoke(bitmap);
                    } else {
                        bitmap = bitmap.copy(Bitmap.Config.ARGB_8888, true);
                        imageCallback.invoke(bitmap);
                    }
                } else {
                    imageCallback.invoke(null);
                }
            }

            @Override
            protected void onFailureImpl(DataSource> dataSource) {
                imageCallback.invoke(null);
            }
        };

        ImageRequestBuilder builder = ImageRequestBuilder.newBuilderWithSource(uri);
        if (resizeOptions != null) {
            builder = builder.setResizeOptions(resizeOptions);
        }
        ImageRequest imageRequest = builder.build();

        ImagePipeline imagePipeline = Fresco.getImagePipeline();
        DataSource> dataSource = imagePipeline.fetchDecodedImage(imageRequest, null);
        dataSource.subscribe(dataSubscriber, UiThreadImmediateExecutorService.getInstance());
    }

    private static Uri getResourceDrawableUri(Context context, String name) {
        if (name == null || name.isEmpty()) {
            return null;
        }
        name = name.toLowerCase().replace("-", "_");
        int resId = context.getResources().getIdentifier(
                name,
                "drawable",
                context.getPackageName());

        if (resId == 0) {
            return null;
        } else {
            return new Uri.Builder()
                    .scheme(UriUtil.LOCAL_RESOURCE_SCHEME)
                    .path(String.valueOf(resId))
                    .build();
        }
    }

    private void _share(final int scene, final ReadableMap data, final Bitmap thumbImage, final Callback callback) {
        if (!data.hasKey("type")) {
            callback.invoke(INVALID_ARGUMENT);
            return;
        }
        String type = data.getString("type");

        WXMediaMessage.IMediaObject mediaObject = null;
        if (type.equals("news")) {
            mediaObject = _jsonToWebpageMedia(data);
        } else if (type.equals("text")) {
            mediaObject = _jsonToTextMedia(data);
        } else if (type.equals("imageUrl") || type.equals("imageResource")) {
            __jsonToImageUrlMedia(data, new MediaObjectCallback() {
                @Override
                public void invoke(@Nullable WXMediaMessage.IMediaObject mediaObject) {
                    if (mediaObject == null) {
                        callback.invoke(INVALID_ARGUMENT);
                    } else {
                        WechatModule.this._share(scene, data, thumbImage, mediaObject, callback);
                    }
                }
            });
            return;
        } else if (type.equals("imageFile")) {
            __jsonToImageFileMedia(data, new MediaObjectCallback() {
                @Override
                public void invoke(@Nullable WXMediaMessage.IMediaObject mediaObject) {
                    if (mediaObject == null) {
                        callback.invoke(INVALID_ARGUMENT);
                    } else {
                        WechatModule.this._share(scene, data, thumbImage, mediaObject, callback);
                    }
                }
            });
            return;
        } else if (type.equals("video")) {
            mediaObject = __jsonToVideoMedia(data);
        } else if (type.equals("audio")) {
            mediaObject = __jsonToMusicMedia(data);
        } else if (type.equals("file")) {
            mediaObject = __jsonToFileMedia(data);
        }

        if (mediaObject == null) {
            callback.invoke(INVALID_ARGUMENT);
        } else {
            _share(scene, data, thumbImage, mediaObject, callback);
        }
    }

    private void _share(int scene, ReadableMap data, Bitmap thumbImage, WXMediaMessage.IMediaObject mediaObject, Callback callback) {
        WXMediaMessage message = new WXMediaMessage();
        message.mediaObject = mediaObject;

        if (thumbImage != null) {
            message.setThumbImage(thumbImage);
        }
        if (data.hasKey("title")) {
            message.title = data.getString("title");
        }
        if (data.hasKey("description")) {
            message.description = data.getString("description");
        }
        if (data.hasKey("mediaTagName")) {
            message.mediaTagName = data.getString("mediaTagName");
        }
        if (data.hasKey("messageAction")) {
            message.messageAction = data.getString("messageAction");
        }
        if (data.hasKey("messageExt")) {
            message.messageExt = data.getString("messageExt");
        }

        SendMessageToWX.Req req = new SendMessageToWX.Req();
        req.message = message;
        req.scene = scene;
        req.transaction = UUID.randomUUID().toString();
        callback.invoke(null, api.sendReq(req));
    }

    private WXTextObject _jsonToTextMedia(ReadableMap data) {
        if (!data.hasKey("description")) {
            return null;
        }

        WXTextObject ret = new WXTextObject();
        ret.text = data.getString("description");
        return ret;
    }

    private WXWebpageObject _jsonToWebpageMedia(ReadableMap data) {
        if (!data.hasKey("webpageUrl")) {
            return null;
        }

        WXWebpageObject ret = new WXWebpageObject();
        ret.webpageUrl = data.getString("webpageUrl");
        if (data.hasKey("extInfo")) {
            ret.extInfo = data.getString("extInfo");
        }
        return ret;
    }

    private void __jsonToImageMedia(String imageUrl, final MediaObjectCallback callback) {
        Uri imageUri;
        try {
            imageUri = Uri.parse(imageUrl);
            if (imageUri.getScheme() == null) {
                imageUri = getResourceDrawableUri(getReactApplicationContext(), imageUrl);
            }
        } catch (Exception e) {
            imageUri = null;
        }

        if (imageUri == null) {
            callback.invoke(null);
            return;
        }

        this._getImage(imageUri, null, new ImageCallback() {
            @Override
            public void invoke(@Nullable Bitmap bitmap) {
                callback.invoke(bitmap == null ? null : new WXImageObject(bitmap));
            }
        });
    }

    private void __jsonToImageUrlMedia(ReadableMap data, MediaObjectCallback callback) {
        if (!data.hasKey("imageUrl")) {
            callback.invoke(null);
            return;
        }
        String imageUrl = data.getString("imageUrl");
        __jsonToImageMedia(imageUrl, callback);
    }

    private void __jsonToImageFileMedia(ReadableMap data, MediaObjectCallback callback) {
        if (!data.hasKey("imageUrl")) {
            callback.invoke(null);
            return;
        }

        String imageUrl = data.getString("imageUrl");
        if (!imageUrl.toLowerCase().startsWith("file://")) {
            imageUrl = "file://" + imageUrl;
        }
        __jsonToImageMedia(imageUrl, callback);
    }

    private WXMusicObject __jsonToMusicMedia(ReadableMap data) {
        if (!data.hasKey("musicUrl")) {
            return null;
        }

        WXMusicObject ret = new WXMusicObject();
        ret.musicUrl = data.getString("musicUrl");
        return ret;
    }

    private WXVideoObject __jsonToVideoMedia(ReadableMap data) {
        if (!data.hasKey("videoUrl")) {
            return null;
        }

        WXVideoObject ret = new WXVideoObject();
        ret.videoUrl = data.getString("videoUrl");
        return ret;
    }

    private WXFileObject __jsonToFileMedia(ReadableMap data) {
        if (!data.hasKey("filePath")) {
            return null;
        }
        return new WXFileObject(data.getString("filePath"));
    }

    private interface ImageCallback {
        void invoke(@Nullable Bitmap bitmap);
    }
    
    private interface MediaObjectCallback {
        void invoke(@Nullable WXMediaMessage.IMediaObject mediaObject);
    }
}

创建WechatPackage.java

package com.xxx.wechat;

import com.facebook.react.ReactPackage;
import com.facebook.react.bridge.JavaScriptModule;
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 WechatPackage implements ReactPackage {
    @Override
    public List createNativeModules(ReactApplicationContext reactContext) {
        List modules = new ArrayList<>();
        modules.add(new WechatModule(reactContext));
        return modules;
    }

    public List> createJSModules() {
        return Collections.emptyList();
    }

    @Override
    public List createViewManagers(ReactApplicationContext reactContext) {
        return Collections.emptyList();
    }
}
  1. 添加模块
    android/app/src/main/java/com/xxx/MainApplication.java
...
import com.xxx.wechat.WechatPackage;
...
public class MainApplication extends Application implements ReactApplication {
   ...
        protected List getPackages() {
          @SuppressWarnings("UnnecessaryLocalVariable")
          List packages = new PackageList(this).getPackages();
          ...
          packages.add(new WechatPackage());
          return packages;
        }
      ...

IOS

React Native

import {NativeModules, Platform} from 'react-native';

const WechatModule = NativeModules.Wechat;


class Wechat {
    
    // 注册微信
    public registerApp = (appId: string, universalLink?: string) => {
        if (Platform.OS === "android") {
            return WechatModule.registerApp(appId);
        } else {
            return WechatModule.registerApp(appId, universalLink);
        }
        
    };
    
    // 微信登录
    public sendAuthWxLogin = (options: {
        scope: string
        state: string
    }) => {
        return WechatModule.sendAuthRequest(options.scope, options.state);
    };
    
    //打开微信app
    public openWxApp = () => {
        return WechatModule.openWxApp();
    };
    
    //打开微信小程序
    public openMiniProgram = (id: string, path: string) => {
        return WechatModule.openMiniProgram(id, path);
    };
    
    public shareMini = (data: {
        // 标题
        title: string;
        // 小程序
        miniName: PLATNAME_TYPE;
        // 分享的路径 pages/index/index?foo=bar
        path?: string;
        // 兼容低版本的网页链接(官网)
        webpageUrl?: string;
        // 描述
        description?: string;
        // 图片
        thumbImageUrl: string;
        // 正式版:0,测试版:1,体验版:2
        miniprogramType?: 0 | 1 | 2;
    }) => {
        return new Promise((resolve) => {
            WechatModule.shareMiniProgram({
                miniprogramType: data.miniprogramType || 0,
                webpageUrl: data.webpageUrl || 'https://www.xxxx.com', // 官网
                userName: APPID[data.miniName].originalId,
                path: data.path || '',
                description: data.description || '',
                thumbImageUrl: data.thumbImageUrl,
                scene: 0,
                title: data.title
            }, () => {
                resolve();
           });
       });
    };
    
    // 分享给好友
    public shareToSession = (data: {
        type: 'news' | 'text' | 'imageUrl' | 'imageFile' | 'imageResource' | 'video' | 'audio' | 'file'
        title?: string;
        thumbImage?: string
        webpageUrl?: string
        imageUrl?: string
        videoUrl?: string
        musicUrl?: string
        filePath?: string
        fileExtension?: string
        description?: string
        extInfo?: string
    }) => {
        return new Promise((resolve) => {
             WechatModule.shareToSession(data, () => {
                 resolve();
             })
        });
    };
    
    // 分享到朋友圈
    public shareToTimeline = (data: {
        type: 'news' | 'text' | 'imageUrl' | 'imageFile' | 'imageResource' | 'video' | 'audio' | 'file'
        title?: string;
        thumbImage?: string
        webpageUrl?: string
        imageUrl?: string
        videoUrl?: string
        musicUrl?: string
        filePath?: string
        fileExtension?: string
        description?: string
        extInfo?: string
    }) => {
        return Promise((resolve) => {
            WechatModule.shareToTimeline(data, () => {
                 resolve();
            });
        })
    };
    
    // 支付
    public pay = (options: {
        appid: string;
        partnerid: string;  // 商家向财付通申请的商家id
        prepayid: string; // 预支付订单
        noncestr: string; // 随机串,防重发
        timestamp: number; // 时间戳,防重发.
        package: string; // 商家根据财付通文档填写的数据和签名
        sign: string; // 商家根据微信开放平台文档对数据做的签名
    }) => {
        return WechatModule.pay(options);
    };
}

你可能感兴趣的:(React Native微信)