xu-li / cordova-plugin-wechat

A cordova plugin, a JS version of Wechat SDK
1.22k stars 509 forks source link

点击分享除了Wechat.isInstalled返回了YES,下面两次都没返回任何东西,java代码中没报错 #168

Closed giantss closed 8 years ago

giantss commented 8 years ago
  Wechat.isInstalled(function (installed) {
        alert("Wechat installed: " + (installed ? "Yes" : "No"));
    }, function (reason) {
        alert("Failed: " + reason);
    });

Wechat.isInstalled 返回了 YES

    var scope = "snsapi_userinfo";
    Wechat.auth(scope, function (response) {
        // you may use response.code to get the access token.
        alert(JSON.stringify(response));
    }, function (reason) {
        alert("Failed: " + reason);
    });

Wechat.auth 没返回任何消息

    Wechat.share({
        message: {
            title: "Hi, there",
            description: "This is description.",
            thumb: "www/img/thumbnail.png",
            mediaTagName: "TEST-TAG-001",
            messageExt: "这是第三方带的测试字段",
            messageAction: "<action>dotalist</action>",
            media: {
                type: Wechat.Type.LINK,
                webpageUrl: "http://tech.qq.com/zt2012/tmtdecode/252.htm"
            }
        },
        scene: Wechat.Scene.TIMELINE   // share to Timeline
    }, function () {
        alert("Success");
    }, function (reason) {
        alert("Failed: " + reason);
    });

Wechat.share 没返回任何消息

williambao commented 8 years ago

我这也一样, android6.0. 可以识别微信安装与否, 调用分享时会闪一下一个页面就没有了.

giantss commented 8 years ago

我试了一下ios,ios上第一次分享是可以的,但是第二次分享弹出来了授权登录窗口,我点授权登录,退回到了我的app页面,然后弹出了"发送请求失败"

giantss commented 8 years ago

发送分享请求后,返回了,"未知错误".

giantss commented 8 years ago

image 这个图片是点击分享后控制台打印的信息,哥快出来看看啊

giantss commented 8 years ago

image 上面的图片是debug签名证书点击分享后控制台打印的信息,现在这个是发布签名证书点击分享后控制台打印的信息.

xu-li commented 8 years ago

你这个bug和 #164 很像啊。是不是测试机的问题?

giantss commented 8 years ago

哦,我试试,我上面说的ios上的问题,你有没有遇到过呢

giantss commented 8 years ago

华为手机也试过了跟我一楼说的一样

xu-li commented 8 years ago

@williambao , @giantss android闪一下,就是签名错了。

giantss commented 8 years ago

闪都没闪,后面两个方法都没返回东西,同样的代码在ios上第一次分享正常,第二次会弹出授权登录的窗口,我点授权登录,退回到了我的app页面,然后弹出了"发送请求失败"

giantss commented 8 years ago

晕,没人遇到过我这样的情况吗

ming1zhou88 commented 8 years ago

我也遇上同样的问题了,不过我感觉是cordova5.0的问题,我把xuli的源码改啦,如下,找到protected boolean sendAuthRequest(CordovaArgs args, CallbackContext callbackContext) { final IWXAPI api = getWXAPI(); final SendAuth.Req req = new SendAuth.Req(); req.scope = "snsapi_userinfo"; req.state = "wechat"; // try { // req.scope = "snsapi_userinfo"; // req.state = "wechat"; // } catch (JSONException e) { // Log.e(TAG, e.getMessage()); // // req.scope = "snsapi_userinfo"; // req.state = "wechat"; // }

    if (api.sendReq(req)) {

将try catch部分都注释掉,然后req.scope = "snsapi_userinfo"; req.state = "wechat";这样直接赋值就行。

ming1zhou88 commented 8 years ago

这个trycatch与xuli的不同,因为我不断改,不知道xuli的原来代码是啥了

ming1zhou88 commented 8 years ago

这是我的完整代码,添加了toast

package xu.li.cordova.wechat;

import android.graphics.Bitmap; import android.graphics.BitmapFactory; import android.os.Environment; import android.util.Base64; import android.util.Log; import android.webkit.URLUtil; import android.widget.Toast; import android.os.Build;

import com.tencent.mm.sdk.modelmsg.SendAuth; import com.tencent.mm.sdk.modelmsg.SendMessageToWX; import com.tencent.mm.sdk.modelmsg.WXAppExtendObject; import com.tencent.mm.sdk.modelmsg.WXEmojiObject; import com.tencent.mm.sdk.modelmsg.WXFileObject; import com.tencent.mm.sdk.modelmsg.WXImageObject; import com.tencent.mm.sdk.modelmsg.WXMediaMessage; import com.tencent.mm.sdk.modelmsg.WXMusicObject; import com.tencent.mm.sdk.modelmsg.WXTextObject; import com.tencent.mm.sdk.modelmsg.WXVideoObject; import com.tencent.mm.sdk.modelmsg.WXWebpageObject; import com.tencent.mm.sdk.modelpay.PayReq; import com.tencent.mm.sdk.openapi.IWXAPI; import com.tencent.mm.sdk.openapi.WXAPIFactory;

import org.apache.cordova.CallbackContext; import org.apache.cordova.CordovaArgs; import org.apache.cordova.CordovaPlugin; import org.apache.cordova.PluginResult; import org.json.JSONException; import org.json.JSONObject;

import java.io.ByteArrayInputStream; import java.io.File; import java.io.FileInputStream; import java.io.FileNotFoundException; import java.io.IOException; import java.io.InputStream;

public class Wechat extends CordovaPlugin {

public static final String TAG = "Cordova.Plugin.Wechat";

public static final String WXAPPID_PROPERTY_KEY = "wechatappid";

public static final String ERROR_WECHAT_NOT_INSTALLED = "未安装微信";
public static final String ERROR_INVALID_PARAMETERS = "参数格式错误";
public static final String ERROR_SEND_REQUEST_FAILED = "发送请求失败";
public static final String ERROR_WECHAT_RESPONSE_COMMON = "普通错误";
public static final String ERROR_WECHAT_RESPONSE_USER_CANCEL = "用户点击取消并返回";
public static final String ERROR_WECHAT_RESPONSE_SENT_FAILED = "发送失败";
public static final String ERROR_WECHAT_RESPONSE_AUTH_DENIED = "授权失败";
public static final String ERROR_WECHAT_RESPONSE_UNSUPPORT = "微信不支持";
public static final String ERROR_WECHAT_RESPONSE_UNKNOWN = "未知错误";

public static final String EXTERNAL_STORAGE_IMAGE_PREFIX = "external://";

public static final String KEY_ARG_MESSAGE = "message";
public static final String KEY_ARG_SCENE = "scene";
public static final String KEY_ARG_TEXT = "text";
public static final String KEY_ARG_MESSAGE_TITLE = "title";
public static final String KEY_ARG_MESSAGE_DESCRIPTION = "description";
public static final String KEY_ARG_MESSAGE_THUMB = "thumb";
public static final String KEY_ARG_MESSAGE_MEDIA = "media";
public static final String KEY_ARG_MESSAGE_MEDIA_TYPE = "type";
public static final String KEY_ARG_MESSAGE_MEDIA_WEBPAGEURL = "webpageUrl";
public static final String KEY_ARG_MESSAGE_MEDIA_IMAGE = "image";
public static final String KEY_ARG_MESSAGE_MEDIA_TEXT = "text";
public static final String KEY_ARG_MESSAGE_MEDIA_MUSICURL = "musicUrl";
public static final String KEY_ARG_MESSAGE_MEDIA_MUSICDATAURL = "musicDataUrl";
public static final String KEY_ARG_MESSAGE_MEDIA_VIDEOURL = "videoUrl";
public static final String KEY_ARG_MESSAGE_MEDIA_FILE = "file";
public static final String KEY_ARG_MESSAGE_MEDIA_EMOTION = "emotion";
public static final String KEY_ARG_MESSAGE_MEDIA_EXTINFO = "extInfo";
public static final String KEY_ARG_MESSAGE_MEDIA_URL = "url";

public static final int TYPE_WECHAT_SHARING_APP = 1;
public static final int TYPE_WECHAT_SHARING_EMOTION = 2;
public static final int TYPE_WECHAT_SHARING_FILE = 3;
public static final int TYPE_WECHAT_SHARING_IMAGE = 4;
public static final int TYPE_WECHAT_SHARING_MUSIC = 5;
public static final int TYPE_WECHAT_SHARING_VIDEO = 6;
public static final int TYPE_WECHAT_SHARING_WEBPAGE = 7;
public static final int TYPE_WECHAT_SHARING_TEXT = 8;

public static final int SCENE_SESSION = 0;
public static final int SCENE_TIMELINE = 1;
public static final int SCENE_FAVORITE = 2;

public static final int MAX_THUMBNAIL_SIZE = 320;

public static Wechat instance = null;

protected CallbackContext currentCallbackContext;
protected IWXAPI wxAPI;
protected String appId;

private static final boolean IS_AT_LEAST_LOLLIPOP = Build.VERSION.SDK_INT >= 21;
@Override
protected void pluginInitialize() {

    super.pluginInitialize();

    instance = this;

    initWXAPI();

    Log.d(TAG, "plugin initialized.");
}

protected void initWXAPI() {
    if (wxAPI == null) {
        String appId = getAppId();

        wxAPI = WXAPIFactory.createWXAPI(webView.getContext(), appId, true);
        wxAPI.registerApp(appId);
    }
}

public IWXAPI getWxAPI() {
    return wxAPI;
}

public CallbackContext getCurrentCallbackContext() {
    return currentCallbackContext;
}

@Override
public boolean execute(String action, CordovaArgs args, CallbackContext callbackContext) throws JSONException {
    Log.d(TAG, String.format("%s is called. Callback ID: %s.", action, callbackContext.getCallbackId()));

    if (action.equals("share")) {
        return share(args, callbackContext);
    } else if (action.equals("sendAuthRequest")) {
        return sendAuthRequest(args, callbackContext);
    } else if (action.equals("sendPaymentRequest")) {
        return sendPaymentRequest(args, callbackContext);
    } else if (action.equals("isWXAppInstalled")) {
        return isInstalled(callbackContext);
    }

    return false;
}

protected boolean share(CordovaArgs args, final CallbackContext callbackContext)
        throws JSONException {
    final IWXAPI api = getWXAPI();

    // check if installed
    if (!api.isWXAppInstalled()) {
        callbackContext.error(ERROR_WECHAT_NOT_INSTALLED);
        return true;
    }

    // check if # of arguments is correct
    final JSONObject params;
    try {
        params = args.getJSONObject(0);
    } catch (JSONException e) {
        callbackContext.error(ERROR_INVALID_PARAMETERS);
        return true;
    }

    final SendMessageToWX.Req req = new SendMessageToWX.Req();
    req.transaction = buildTransaction();

    if (params.has(KEY_ARG_SCENE)) {
        switch (params.getInt(KEY_ARG_SCENE)) {
            case SCENE_FAVORITE:
                req.scene = SendMessageToWX.Req.WXSceneFavorite;
                break;
            case SCENE_TIMELINE:
                req.scene = SendMessageToWX.Req.WXSceneTimeline;
                break;
            case SCENE_SESSION:
                req.scene = SendMessageToWX.Req.WXSceneSession;
                break;
            default:
                req.scene = SendMessageToWX.Req.WXSceneTimeline;
        }
    } else {
        req.scene = SendMessageToWX.Req.WXSceneTimeline;
    }

    // run in background
    cordova.getThreadPool().execute(new Runnable() {

        @Override
        public void run() {
            try {
                req.message = buildSharingMessage(params);
            } catch (JSONException e) {
                Log.e(TAG, "Failed to build sharing message.", e);

                // clear callback context
                currentCallbackContext = null;

                // send json exception error
                callbackContext.sendPluginResult(new PluginResult(PluginResult.Status.JSON_EXCEPTION));
            }

            if (api.sendReq(req)) {
                Log.i(TAG, "Message has been sent successfully.");
            } else {
                Log.i(TAG, "Message has been sent unsuccessfully.");

                // clear callback context
                currentCallbackContext = null;

                // send error
                callbackContext.error(ERROR_SEND_REQUEST_FAILED);
            }
        }
    });

    // send no result
    sendNoResultPluginResult(callbackContext);

    return true;
}

protected boolean sendAuthRequest(CordovaArgs args, CallbackContext callbackContext) {
    final IWXAPI api = getWXAPI();
    final SendAuth.Req req = new SendAuth.Req();
    req.scope = "snsapi_userinfo";
    req.state = "wechat";

// try { // req.scope = "snsapi_userinfo"; // req.state = "wechat"; // } catch (JSONException e) { // Log.e(TAG, e.getMessage()); // // req.scope = "snsapi_userinfo"; // req.state = "wechat"; // }

    if (api.sendReq(req)) {
        Log.i(TAG, "Auth request has been sent successfully.");
        Toast toast = Toast.makeText(IS_AT_LEAST_LOLLIPOP ? cordova.getActivity().getWindow().getContext() : cordova.getActivity().getApplicationContext(), "已发送", Toast.LENGTH_LONG);
        toast.show();
        // send no result
        sendNoResultPluginResult(callbackContext);
    } else {
        Log.i(TAG, "Auth request has been sent unsuccessfully.");
        Toast toast1 = Toast.makeText(IS_AT_LEAST_LOLLIPOP ? cordova.getActivity().getWindow().getContext() : cordova.getActivity().getApplicationContext(), "发送失败", Toast.LENGTH_LONG);
        toast1.show();
        // send error
        callbackContext.error(ERROR_SEND_REQUEST_FAILED);
    }

    return true;
}

protected boolean sendPaymentRequest(CordovaArgs args, CallbackContext callbackContext) {

    final IWXAPI api = getWXAPI();

    // check if # of arguments is correct
    final JSONObject params;
    try {
        params = args.getJSONObject(0);
    } catch (JSONException e) {
        callbackContext.error(ERROR_INVALID_PARAMETERS);
        return true;
    }

    PayReq req = new PayReq();

    try {
        req.appId = getAppId();
        req.partnerId = params.has("mch_id") ? params.getString("mch_id") : params.getString("partnerid");
        req.prepayId = params.has("prepay_id") ? params.getString("prepay_id") : params.getString("prepayid");
        req.nonceStr = params.has("nonce") ? params.getString("nonce") : params.getString("noncestr");
        req.timeStamp = params.getString("timestamp");
        req.sign = params.getString("sign");
        req.packageValue = "Sign=WXPay";
    } catch (Exception e) {
        Log.e(TAG, e.getMessage());

        callbackContext.error(ERROR_INVALID_PARAMETERS);
        return true;
    }

    if (api.sendReq(req)) {
        Log.i(TAG, "Payment request has been sent successfully.");

        // send no result
        sendNoResultPluginResult(callbackContext);
    } else {
        Log.i(TAG, "Payment request has been sent unsuccessfully.");

        // send error
        callbackContext.error(ERROR_SEND_REQUEST_FAILED);
    }

    return true;
}

protected boolean isInstalled(CallbackContext callbackContext) {
    final IWXAPI api = getWXAPI();

    if (!api.isWXAppInstalled()) {
        callbackContext.success(0);
    } else {
        callbackContext.success(1);
    }

    return true;
}

protected WXMediaMessage buildSharingMessage(JSONObject params)
        throws JSONException {
    Log.d(TAG, "Start building message.");

    // media parameters
    WXMediaMessage.IMediaObject mediaObject = null;
    WXMediaMessage wxMediaMessage = new WXMediaMessage();

    if (params.has(KEY_ARG_TEXT)) {
        WXTextObject textObject = new WXTextObject();
        textObject.text = params.getString(KEY_ARG_TEXT);
        mediaObject = textObject;
        wxMediaMessage.description = textObject.text;
    } else {
        JSONObject message = params.getJSONObject(KEY_ARG_MESSAGE);
        JSONObject media = message.getJSONObject(KEY_ARG_MESSAGE_MEDIA);

        wxMediaMessage.title = message.getString(KEY_ARG_MESSAGE_TITLE);
        wxMediaMessage.description = message.getString(KEY_ARG_MESSAGE_DESCRIPTION);

        // thumbnail
        Bitmap thumbnail = getThumbnail(message, KEY_ARG_MESSAGE_THUMB);
        if (thumbnail != null) {
            wxMediaMessage.setThumbImage(thumbnail);
            thumbnail.recycle();
        }

        // check types
        int type = media.has(KEY_ARG_MESSAGE_MEDIA_TYPE) ? media
                .getInt(KEY_ARG_MESSAGE_MEDIA_TYPE) : TYPE_WECHAT_SHARING_WEBPAGE;

        switch (type) {
            case TYPE_WECHAT_SHARING_APP:
                WXAppExtendObject appObject = new WXAppExtendObject();
                appObject.extInfo = media.getString(KEY_ARG_MESSAGE_MEDIA_EXTINFO);
                appObject.filePath = media.getString(KEY_ARG_MESSAGE_MEDIA_URL);
                mediaObject = appObject;
                break;

            case TYPE_WECHAT_SHARING_EMOTION:
                WXEmojiObject emoObject = new WXEmojiObject();
                InputStream emoji = getFileInputStream(media.getString(KEY_ARG_MESSAGE_MEDIA_EMOTION));
                if (emoji != null) {
                    try {
                        emoObject.emojiData = Util.readBytes(emoji);
                    } catch (IOException e) {
                        e.printStackTrace();
                    }
                }
                mediaObject = emoObject;
                break;

            case TYPE_WECHAT_SHARING_FILE:
                WXFileObject fileObject = new WXFileObject();
                fileObject.filePath = media.getString(KEY_ARG_MESSAGE_MEDIA_FILE);
                mediaObject = fileObject;
                break;

            case TYPE_WECHAT_SHARING_IMAGE:
                Bitmap image = getBitmap(message.getJSONObject(KEY_ARG_MESSAGE_MEDIA), KEY_ARG_MESSAGE_MEDIA_IMAGE, 0);
                mediaObject = new WXImageObject(image);
                image.recycle();
                break;

            case TYPE_WECHAT_SHARING_MUSIC:
                WXMusicObject musicObject = new WXMusicObject();
                musicObject.musicUrl = media.getString(KEY_ARG_MESSAGE_MEDIA_MUSICURL);
                musicObject.musicDataUrl = media.getString(KEY_ARG_MESSAGE_MEDIA_MUSICDATAURL);
                mediaObject = musicObject;
                break;

            case TYPE_WECHAT_SHARING_VIDEO:
                WXVideoObject videoObject = new WXVideoObject();
                videoObject.videoUrl = media.getString(KEY_ARG_MESSAGE_MEDIA_VIDEOURL);
                mediaObject = videoObject;
                break;

            case TYPE_WECHAT_SHARING_WEBPAGE:
            default:
                mediaObject = new WXWebpageObject(media.getString(KEY_ARG_MESSAGE_MEDIA_WEBPAGEURL));
        }
    }

    wxMediaMessage.mediaObject = mediaObject;

    return wxMediaMessage;
}

protected IWXAPI getWXAPI() {
    return wxAPI;
}

private String buildTransaction() {
    return String.valueOf(System.currentTimeMillis());
}

private String buildTransaction(final String type) {
    return type + System.currentTimeMillis();
}

protected Bitmap getThumbnail(JSONObject message, String key) {
    return getBitmap(message, key, MAX_THUMBNAIL_SIZE);
}

protected Bitmap getBitmap(JSONObject message, String key, int maxSize) {
    Bitmap bmp = null;
    String url = null;

    try {
        if (!message.has(key)) {
            return null;
        }

        url = message.getString(key);

        // get input stream
        InputStream inputStream = getFileInputStream(url);
        if (inputStream == null) {
            return null;
        }

        // decode it
        // @TODO make sure the image is not too big, or it will cause out of memory
        BitmapFactory.Options options = new BitmapFactory.Options();
        bmp = BitmapFactory.decodeStream(inputStream, null, options);

        // scale
        if (maxSize > 0 && (options.outWidth > maxSize || options.outHeight > maxSize)) {

            Log.d(TAG, String.format("Bitmap was decoded, dimension: %d x %d, max allowed size: %d.",
                    options.outWidth, options.outHeight, maxSize));

            int width = 0;
            int height = 0;

            if (options.outWidth > options.outHeight) {
                width = maxSize;
                height = width * options.outHeight / options.outWidth;
            } else {
                height = maxSize;
                width = height * options.outWidth / options.outHeight;
            }

            Bitmap scaled = Bitmap.createScaledBitmap(bmp, width, height, true);
            bmp.recycle();

            bmp = scaled;
        }

        inputStream.close();

    } catch (JSONException e) {
        bmp = null;
        e.printStackTrace();
    } catch (IOException e) {
        bmp = null;
        e.printStackTrace();
    }

    return bmp;
}

/**
 * Get input stream from a url
 *
 * @param url
 * @return
 */
protected InputStream getFileInputStream(String url) {
    try {

        InputStream inputStream = null;

        if (URLUtil.isHttpUrl(url) || URLUtil.isHttpsUrl(url)) {

            File file = Util.downloadAndCacheFile(webView.getContext(), url);

            if (file == null) {
                Log.d(TAG, String.format("File could not be downloaded from %s.", url));
                return null;
            }

            url = file.getAbsolutePath();
            inputStream = new FileInputStream(file);

            Log.d(TAG, String.format("File was downloaded and cached to %s.", url));

        } else if (url.startsWith("data:image")) {  // base64 image

            String imageDataBytes = url.substring(url.indexOf(",") + 1);
            byte imageBytes[] = Base64.decode(imageDataBytes.getBytes(), Base64.DEFAULT);
            inputStream = new ByteArrayInputStream(imageBytes);

            Log.d(TAG, "Image is in base64 format.");

        } else if (url.startsWith(EXTERNAL_STORAGE_IMAGE_PREFIX)) { // external path

            url = Environment.getExternalStorageDirectory().getAbsolutePath() + url.substring(EXTERNAL_STORAGE_IMAGE_PREFIX.length());
            inputStream = new FileInputStream(url);

            Log.d(TAG, String.format("File is located on external storage at %s.", url));

        } else if (!url.startsWith("/")) { // relative path

            inputStream = cordova.getActivity().getApplicationContext().getAssets().open(url);

            Log.d(TAG, String.format("File is located in assets folder at %s.", url));

        } else {

            inputStream = new FileInputStream(url);

            Log.d(TAG, String.format("File is located at %s.", url));

        }

        return inputStream;

    } catch (FileNotFoundException e) {
        e.printStackTrace();
    } catch (IOException e) {
        e.printStackTrace();
    }

    return null;
}

protected String getAppId() {
    if (this.appId == null) {
        this.appId = preferences.getString(WXAPPID_PROPERTY_KEY, "");
    }

    return this.appId;
}

private void sendNoResultPluginResult(CallbackContext callbackContext) {
    // save current callback context
    currentCallbackContext = callbackContext;

    // send no result and keep callback
    PluginResult result = new PluginResult(PluginResult.Status.NO_RESULT);
    result.setKeepCallback(true);
    callbackContext.sendPluginResult(result);
}

}

giantss commented 8 years ago

楼上留个联系方式行吗 QQ谢谢

xu-li commented 8 years ago

额,我仔细看了一下我的那个README里面的实例代码。其实scope参数是不需要的,默认就是snsapi_userinfo。当初加在README里面,只是为了告诉大家,可以传scope。

giantss commented 8 years ago

6mwovgh7azp7mnps au ab

giantss commented 8 years ago

r99 37y j21 h2gpm0 bht

xu-li commented 8 years ago

@giantss

首先,你用的什么版本的cordova-plugin-wechat?最新版的代码不是这样的。 其次,返回了-6,你应该去找微信,为什么他们会返回-6? 最后,我的switch的语句,目的是转换微信的error code到我自定义的error code (因为我还有其它的error code要返回,比如参数错误)。

giantss commented 8 years ago

s pgmvnh91 _ 5cf6bc 159

giantss commented 8 years ago

我擦,签名问题.重新申请了一个应用填写资料好了