• 用xposed框架开发的修改微信运动数据的小模块

    1.源码

    使用的方法是以咕咚为跳板,先修改咕咚的计步数据然后上传微信。

    其中:

    使用的手机是 小米3+miui8首先要满足xposed可以运行的条件,其次系统一定要是android6.0+,原因会在后面详细说明

    里面带了一些调试输出,用于查看过程中传感器数据的变化不需要的话可以把log.e全部删掉

    l sensor.getName().equals("Step Counter")会由于权限问题报错eclipse代码左侧提示小图标点一下无视就好

    package com.example.testxposedhook;
    import static de.robv.android.xposed.XposedHelpers.findClass;
    
    import java.lang.reflect.Field;
    
    import android.hardware.Sensor;
    import android.util.Log;
    import android.util.SparseArray;
    
    import de.robv.android.xposed.XC_MethodHook;
    import de.robv.android.xposed.IXposedHookLoadPackage;
    import de.robv.android.xposed.XposedBridge;
    import de.robv.android.xposed.callbacks.XC_LoadPackage.LoadPackageParam;
    
    public class Main implements IXposedHookLoadPackage {
    	private static int stepCount = 23333;//must lower than 98800
    	private static int acclCount = 1;//accelerate sensor count
    	@Override
    	public void handleLoadPackage(LoadPackageParam lpparam) throws Throwable {
    		// TODO Auto-generated method stub
    		if(!lpparam.packageName.equals("com.codoon.gps")){
    			return;
    		}
    		final Class<?> sensorEL = findClass("android.hardware.SystemSensorManager$SensorEventQueue", lpparam.classLoader);
    
            XposedBridge.hookAllMethods(sensorEL, "dispatchSensorEvent", new XC_MethodHook() {
    
                @Override
                protected void beforeHookedMethod(MethodHookParam param) throws Throwable {
                  //  ((float[]) param.args[1])[0] = ((float[]) param.args[1])[0] + 1168 * stepCount;
                  //  stepCount++;
                	try{
                		 //先拿manager
    	                Field mfield = param.thisObject.getClass().getSuperclass().getDeclaredField("mManager");
    	                mfield.setAccessible(true);
    	                Object mManager= mfield.get(param.thisObject);
    	                //再拿mmanager下的sensor
    	                Field field = param.thisObject.getClass().getEnclosingClass().getDeclaredField("mHandleToSensor");
    	                field.setAccessible(true);
    	                int handle = (Integer) param.args[0];
    	                Sensor sensor = ((SparseArray<Sensor>) field.get(mManager)).get(handle);
    	                
                		if(sensor.getName().equals("Step Counter"))//StepCounter sensor
                		{            		           			
    		            	Log.e("mytest","args = " + ((float[]) param.args[1])[0]+" "+ ((float[]) param.args[1])[1]+" "+ ((float[]) param.args[1])[2]+" "+ ((float[]) param.args[1])[3]);
    		                ((float[]) param.args[1])[0] = stepCount;
    		                Log.e("mytest","sensor = " + sensor);
                		}
                		else{//accelerate sensor
                			if(acclCount%100>=80){
                				Log.e("mytest", "a loop end");
                				acclCount++;
                				return;
                			}
                			((float[]) param.args[1])[0] = 20;
                			((float[]) param.args[1])[1] = 10;
                			((float[]) param.args[1])[2] = 30;
                			acclCount++;
                			if(acclCount%20==0){
                				Log.e("mytest","running accelerate");
                			}
                		}
    	            }
                	catch(Exception e){
                		Log.e("mytest",Log.getStackTraceString(e)); 
                	}
                }
                @Override
                protected void afterHookedMethod(MethodHookParam param) throws Throwable {
                	// TODO Auto-generated method stub
    //            	super.afterHookedMethod(param);
                	Field mfield = param.thisObject.getClass().getSuperclass().getDeclaredField("mManager");
                    mfield.setAccessible(true);
                    Object mManager= mfield.get(param.thisObject);
                    //再拿mmanager下的sensor
                    Field field = param.thisObject.getClass().getEnclosingClass().getDeclaredField("mHandleToSensor");
                    field.setAccessible(true);
                    int handle = (Integer) param.args[0];
                    Sensor sensor = ((SparseArray<Sensor>) field.get(mManager)).get(handle);
                    if(!sensor.getName().equals("Step Counter"))
                    	return;
                	Log.e("mytest", "after hook : "+((float[])param.args[1])[0]);
                }
            });
    
    	}
    }


    2.过程详解

    方法来源于陈浩的博客-《基于Xposed修改微信运动步数》

    但发现有几个问题:

    1.首先实测时小米3+miui8下微信并不能直接从手机获取计步器数据而咕咚获取的传感器数据不只是Step Counter,还有加速度传感器,因此判断咕咚是对两个传感器的数据进行了综合分析;

    2.其次是android 5.X-android 6.0+的变化使得原来获取sensor数据的部分报错无法获取

    其中

    Field field = param.thisObject.getClass().getEnclosingClass().getDeclaredField("sHandleToSensor");  
                    field.setAccessible(true);  
      
                    int handle = (Integer) param.args[0];  
                    Sensor sensor = ((SparseArray<Sensor>) field.get(0)).get(handle);  
                    XposedBridge.log("sensor = " + sensor);  

    这段代码不知道原作者有没有实测过,按照我的理解

    Sensor sensor = ((SparseArray<Sensor>) field.get(0)).get(handle);

    这段应该写成

    Sensor sensor = ((SparseArray<Sensor>) field.get(null)).get(handle);

    详细原因可以参照java.lang.reflectapi文档:Field api文档

    Field.get 返回参数指定对象上此 Field表示的字段的值。如果该值是一个基本类型值,则自动将其包装在一个对象中。

    因此0参数类型将为Integer,而写成null是可以的,因为在android5.X-的代码中sHandleToSensor的修饰符为final staticFiled.get在获取static型成员时可以直接使用null作为参数。

    而在android6.0+的代码中SystemSensorManager有部分变动,相关代码结构变成了以下结构:

    public class SystemSensorManager{
    	private final String mHandleToSensor="mHandleToSensor";//只是个示例实际这里的类型是SparseArray<Sensor>
    	static abstract class BasicQueue{
    		private final SystemSensorManager mManager=new SystemSensorManager();
    	}
    	static class SensorQueue extends BasicQueue{
    		public void dispatchSensorEvent(){}//这里是我们hook的地方所处的作用域
    	}
    }

    其中相比android5.X-的代码变化主要有以下两点

    l sHandleToSensor改名为mHandleToSensor

    l sHandleToSensor的修饰符由private static final变为private final

    名字改了好说,直接在Filed生成时改一下获取名就可以了,由于static关键字被取消导致无法再通过空对象反射的方法获取sensor就比较麻烦了,通过观察SystemSensorManager的源码可以发现可以先获取SensorQueue的父类BasicQueue中的mManager然后用这个mManager来去获取mHandleToSensor。代码如下

     

            //先拿manager
            Field mfield = param.thisObject.getClass().getSuperclass().getDeclaredField("mManager");
            mfield.setAccessible(true);
            Object mManager= mfield.get(param.thisObject);
    	//再拿mmanager下的sensor
    	Field field = param.thisObject.getClass().getEnclosingClass().getDeclaredField("mHandleToSensor");
    	field.setAccessible(true);
    	int handle = (Integer) param.args[0];
    	Sensor sensor = ((SparseArray<Sensor>) field.get(mManager)).get(handle);

    在修改计步器方面,最初是把所有的sensorvalues[0]全部设为一个大数

     ((float[]) param.args[1])[0] = stepCount;//stepCount=23333

    但是发现在咕咚实测的时候会变为每次只加3000步就停了,又联想到咕咚使用了两种传感器,而加速度传感器在之前也是用来做计步器的(详见xbase-《一个稳定好用的android计步器源代码》)。参考这篇文章猜测是用加速度传感器的三轴数据来判断运动状态,于是模拟了一个间歇性运动的过程

    if(acclCount%100>=80){
        Log.e("mytest", "a loop end");
        acclCount++;
        return;
    }
    ((float[]) param.args[1])[0] = 20;
    ((float[]) param.args[1])[1] = 10;
    ((float[]) param.args[1])[2] = 30;
    acclCount++;
    if(acclCount%20==0){
         Log.e("mytest","running accelerate");
    }

    其中三轴的数据刚开始用的全是8发现实测无效,随便改了一组可以了就没再研究咕咚具体的算法实现,有时间可以考虑逆向一下咕咚看一下具体的算法实现。至此整个功能就实现了。

    附一张结果图,大写的23333:


    展开全文
  • 1.第一微信开放平台注册账号,填写相关资料提交...APP_ID在微信开放平台创建应用之后的时候获得,支付功能有这三个参数足以。 注意:商户登录点击下图所示入口,别搞错了 2.详讲微信支付必填的三个参数获得方式:

    1.第一步去微信开放平台注册账号,填写相关资料提交审核,审核之后将获得商户账号,MIC_CH(商户号)和APP_KEY(APP秘钥)这两个参数要在资料审核通过之后获得,审核通过后会以邮件的方式把商户号好登录密码发送到你的邮箱里;APP_ID在微信开放平台创建应用之后的时候获得,支付功能有这三个参数足以。

    注意:商户登录点击下图所示入口,别搞错了


    2.开始集成准备工作:

    (1)APP_ID获得方式:

    在微信开放平台创建应用时获取。

    (2)MCH_ID获取方式(如图):


    (3)APP_KEY获取方式(在账户中心,api安全项设置,如图):



    自己生成然后把秘钥设置到商户平台,生成秘钥工具:http://pan.baidu.com/s/1c2xIz5Y  

    (4)微信开放平台管理中心\应用详情最下面需要填上本应用的签名,签名生成工具:http://pan.baidu.com/s/1gfgHvqF  (安装到手机输入包名即可,前提手机要装有你们开发的APP)。

    3.经过以上步骤资源方面基本准备完成,下面是核心代码,即我们要作修改的代码:

    (1)在文件名为Constants.java的文件里写入以上三个参数,如图:


    (2)支付核心函数(仅此三个我们需要用到的):

    //生成prepay_id

    GetPrepayIdTask getPrepayId = new GetPrepayIdTask();
    				getPrepayId.execute();

    //生成支付参数包括签名参数
    genPayReq();
    
    
    //调起微信支付
    sendPayReq();
    (3)以上就是我们需要调用的函数,下面提供一段需要修改的代码,如修改价格和支付成功回调地址,最后面有完整的项目地址:(把参数填入即可进行支付)

    private String genProductArgs() {
    		StringBuffer xml = new StringBuffer();
    		try {
    			String nonceStr = genNonceStr();
    			xml.append("</xml>");
                List<NameValuePair> packageParams = new LinkedList<NameValuePair>();
    			//微信开放平台审核通过的应用APPID
    			packageParams.add(new BasicNameValuePair("appid", Constants.APP_ID));
    			//商品描述,参数目前不能写中文,不知道为啥
    			packageParams.add(new BasicNameValuePair("body", "weixin"));
    			//微信支付分配的商户号
    			packageParams.add(new BasicNameValuePair("mch_id", Constants.MCH_ID));
    			//随机字符串,这里可以传用户昵称或者用户id之类的,很重要,参数可以传到回调地址那里的,也就是你们的后台那边在接收支付结果的时候,可以接到此参数
    			packageParams.add(new BasicNameValuePair("nonce_str", nonceStr));
    			//通知后台充值成功
    			packageParams.add(new BasicNameValuePair("notify_url", "http://121.40.35.3/test"));
    			//商户系统内部的订单号,32个字符内、可包含字母, 其他说明见商户订单号,自己生成
    			packageParams.add(new BasicNameValuePair("out_trade_no",genOutTradNo()));
    			//用户端实际ip
    			packageParams.add(new BasicNameValuePair("spbill_create_ip","127.0.0.1"));
    			//订单总金额,单位为分,详见支付金额
    			packageParams.add(new BasicNameValuePair("total_fee", "1"));
    			//支付类型,参考值:App支付
    			packageParams.add(new BasicNameValuePair("trade_type", "APP"));
    			//签名
    			String sign = genPackageSign(packageParams);
    			//
    			packageParams.add(new BasicNameValuePair("sign", sign));
    			//打包成xml格式
    		   String xmlstring =toXml(packageParams);
    
    			return xmlstring;
    
    		} catch (Exception e) {
    			return null;
    		}
    		
    
    	}

    流程如下:

    选好价格点击开通会员之后执行的步骤

    (1)获得支付的价格

    (2)获得Appid,mch_id,App_key

    (3)执行如下代码,生成prepay_id,即生成预支付订单

    GetPrepayIdTask getPrepayId = new GetPrepayIdTask();
    				getPrepayId.execute();
    (4)执行如下代码,生成支付参数,价格之类的

    genPayReq();

    (5)唤起支付,到此完成,很简单吧

    sendPayReq();

    项目地址:http://pan.baidu.com/s/1mhPCoZI

    展开全文
  • android集成微信分享

    2018-09-12 16:20:39
    登录 微信开放平台 把你的开发者信息填,这些就不图了,都是中文字,应该看得懂 然后进入 管理中心 点击创建++移动应用++ 创建移动应用 把你的应用信息填,有些项目不知道怎么填随便填就行了,但是注意: 应用的...

    1.注册你的APP

    登录 微信开放平台 把你的开发者信息填上,这些就不上图了,都是中文字,应该看得懂
    然后进入 管理中心 点击创建++移动应用++

    创建移动应用

    把你的应用信息填上,有些项目不知道怎么填随便填就行了,但是注意: 应用的包名和签名不能随便填!!

    • 包名就是你的应用的包名例如: fucker.idiot.asshole.wanker

    怎么获取签名?

    先下载微信提供的一些工具

    工具

    首先将你的app安装在手机或者模拟器上,

    由于平时我们调试软件都是使用debug的签名生成应用,所以我们要特别注意如果使用了debug的签名,等到APP正式发布的时候,微信的分享就不能用了.
    所以我们要使用release的签名文件
    怎么让我们debug的时候也使用release的签名文件呢?

    打开应用Module的build.gradle文件 添加这样一份代码:

    android {
        signingConfigs{
            debug{  //这里配置的就是debug的签名配置了
                storeFile file("C:\\Users\\Administrator\\.android\\asd")   //这个文件是我的,改成你自己的release签名文件
                storePassword "asd123456"   //密码改成自己的
                keyAlias "asd"              //再改成你自己的
                keyPassword "asd123456"     //再改成你自己的
            }
        }
    }
    

    再使用工具包中的软件便可以获取到应用的签名了,

    填上应用的包名,然后"Get Signature"

    获取签名

    绿色的字就是签名

    最后等待审核,可能要一两天把...

    通过审核是这样的

    通过审核

    当然要把 AppID 和 AppSecret 记录下来,在代码中需要使用

     

    第三方集成步骤大致都差不多:平台注册,引入依赖包,配置清单文件,初始化操作,最后引用

    注册就不用说了,直接上第三方官网,按照提示申请注册账号和应用,获取相应的appid,appkey等;

    2.引入依赖包:

    项目build.gradle之下

    compile 'com.tencent.mm.opensdk:wechat-sdk-android-without-mta:+'

    其中,里面的without表示没有统计功能,如果需要有统计功能修改为with即可,+号表示随时引入最新包;

    3.配置清单AndroidManifest.xml

    <uses-permission android:name="android.permission.INTERNET"/>
    
    <uses-permission android:name="android.permission.ACCESS_NETWORK_STATE"/>
    
    <uses-permission android:name="android.permission.ACCESS_WIFI_STATE"/>
    
    <uses-permission android:name="android.permission.READ_PHONE_STATE"/>
    
    <uses-permission android:name="android.permission.WRITE_EXTERNAL_STORAGE"/>

     

    4.注册到微信(我是在Application的onCreate中注册的,也可以在Activity中注册)

    IWXAPI mWxApi = WXAPIFactory.createWXAPI(this, ShareKey.WX_ID, true);
    mWxApi.registerApp(ShareKey.WX_ID);

    第四步:分享内容到微信

     

    IWXAPI mWXApi = WXAPIFactory.createWXAPI(context, ShareKey.WX_ID, true);
    mWXApi.registerApp(ShareKey.WX_ID);
    
    if (!mWXApi.isWXAppInstalled()) {
        Tool.toast(context, R.string.share_unInstall_wx);
        return;
    }
    
    WXWebpageObject webpage = new WXWebpageObject();
    webpage.webpageUrl = url;
    
    WXMediaMessage msg = new WXMediaMessage(webpage);
    msg.title = title;
    msg.description = decribe;
    msg.thumbData = getWXThumb(bitmap).toByteArray();
    
    SendMessageToWX.Req req = new SendMessageToWX.Req();
    //WXSceneTimeline朋友圈    WXSceneSession聊天界面
    req.scene = isTimeLineCb ? SendMessageToWX.Req.WXSceneTimeline : SendMessageToWX.Req.WXSceneSession;//聊天界面
    req.message = msg;
    req.transaction = String.valueOf(System.currentTimeMillis());
    mWXApi.sendReq(req);

    这是图片需要处理一下,太大了分享会报错

     

     

    public static final int IMAGE_LENGTH_LIMIT = 6291456;
    
    private static ByteArrayOutputStream getWXThumb(Bitmap resource) {
        Bitmap thumb = createScaledBitmap(resource, 100, true);
        ByteArrayOutputStream output = new ByteArrayOutputStream();
        int quality = 90;
        int realLength = Util.getBitmapByteSize(resource.getWidth(), resource.getHeight(), Bitmap.Config.ARGB_8888);
        if (realLength > IMAGE_LENGTH_LIMIT) {
            quality = (int) (IMAGE_LENGTH_LIMIT * 1f / realLength * 100);
        }
        if (quality < 75) {
            quality = 75;
        }
        resource.compress(Bitmap.CompressFormat.PNG, quality, output);
        output.reset();
        thumb.compress(Bitmap.CompressFormat.PNG, 85, output);
        return output;
    }

    第四步:最后就是分享的回调了(在自己项目包名下创建目录wxapi,这个目录下创建WXEntryActivity,也就是:你的包名.wxapi.WXEntryActivity,这个类需要在清单注册)

     

     

    <activity
        android:name=".wxapi.WXEntryActivity"
        android:exported="true"
        android:launchMode="singleTop"
        android:screenOrientation="portrait" />

    WXEntryActivity的实现:

     

     

    public class WXEntryActivity extends AppCompatActivity implements IWXAPIEventHandler {
    
        private final int REQUEST_PAY = 100;
    
        @Override
        protected void onCreate(@Nullable Bundle savedInstanceState) {
            super.onCreate(savedInstanceState);
            share = ShareKey.getShare(this);
            //如果没回调onResp,八成是这句没有写
            WXAPIFactory.createWXAPI(this, WX_ID, false).handleIntent(getIntent(), this);
        }
    
        // 微信发送请求到第三方应用时,会回调到该方法
        @Override
        public void onReq(BaseReq req) {
        }
    
        // 第三方应用发送到微信的请求处理后的响应结果,会回调到该方法
        //app发送消息给微信,处理返回消息的回调
        @Override
        public void onResp(BaseResp resp) {
            switch (resp.errCode) {
                case BaseResp.ErrCode.ERR_AUTH_DENIED:
                case BaseResp.ErrCode.ERR_USER_CANCEL:
                    switch (resp.getType()) {
                        case RETURN_MSG_TYPE_SHARE:
                            Tool.toast(this, "微信分享取消");
                            finish();
                            break;
            
                    }
                    break;
    
                case BaseResp.ErrCode.ERR_OK:
                    switch (resp.getType()) {
                      case RETURN_MSG_TYPE_SHARE:
                            finish();
                            break;
                    }
                    break;
            }
        }

    到此,微信分享就完事了。说一下需要注意的地方,

     

    1 , app签名需要和微信平台上申请的一致

    2 ,分享的图片大小要注意,缩略图不能大于32k

    3 , 回调的WXEntryActivity要放对位置,清单也要添加

     

    展开全文
  • 前段时间完成了在线支付的微信支付,趁着一些注意地方没忘记,这里记录下来吧!2. 准备这里我不想吐槽,微信支付 比 支付宝 支付准备工作 麻烦不知道多少倍,我记忆中有三个地方的审核,当然这些不是开发内容,可能...

    1. 前言

    “好记性不如烂笔头”,现在 平常 碰到的一些知识点都是直接复制到印象笔记中,但是那些资料都比较零散,该总结的还得总结。前段时间完成了在线支付的微信支付,趁着一些注意地方没忘记,这里记录下来吧!

    2. 准备

    这里我不想吐槽,微信支付 比 支付宝 支付准备工作 麻烦不知道多少倍,我记忆中有三个地方的审核,当然这些不是开发内容,可能随时会变,开发时具体是什么就是什么,我这里只是给大家提个醒。

    • 企业认证,资料填写,等待审核

    • 应用创建认证,这里填写 Android 和 Ios 两边项目的一些信息,苹果不用说了,主要 是 安卓,需要填写签名,很多人或者资料都建议先填写 测试的签名 ,为了开发平常开发测试使用方便,但是我建议使用正式的签名,有很多办法解决 ,因为这里涉及到 签名 的获取,还是留到后面一起说吧。

    • 支付认证审核,应用创建后,默认是没有支付服务的,需要开通支付,又要填写资料,商家收款银行卡,最主要的是需要 法人身份证 正方面,这里特别要注意,当初苦逼的和领导说 需要 老板的身份证 正方面把他都吓一跳(上市公司老板 身价比较高…)

    虽然微信有各种认证,各种等待,虽然提示 7 个工作日内,但是他们的效率,简直没的说,比支付宝快,一般来说半天或者一天,审核结果就下来了,这里给微信点个赞。

    2.1 应用签名

    这里单独列出来,因为这里涉及到 签名 的获取和使用 测试签名 还是 正式签名
    微信当然提供了一个 apk 用来获取 app的签名,只要我们将已经签名的项目APP安装到手机上,然后再安装他们的 apk 获取签名,其实我不太建议这样做,有点麻烦,而且他们 apk 签名工具太反人类了,有木有,显示出来的 一大串字符串 ,又不能复制,只能对着电脑一个一个敲,有点容易出错。
    其实应用签名通过处理 SHA1 值获取

    SHA1: 68:1Y:0D:89:AC:4B:B3:OF:90:64:83:UW:95:44:B7:49:36:03:AE:27

    对于如上一串 SHA1 值,将 [ : ] 去掉,大写字母改成小写,这就是 应用签名,特别注意,这里使用正式 keystore ,获取 SHA1 ,获取到的就是正式应用签名,对于应用怎样获取 SHA1 ,可以看我以前总结的一篇博客

    * 特别注意 不是 SHA1 值 是 MD5值 进行 大写改小写 去掉 : *

    快速获取debug.keystore和release.keystore的SHA1或者MD5值


    很多资料都说在微信平台先填写测试的应用签名,方便测试,然后改回正式签名上线,其实没必要,一来呢修改签名是需要审核的,最低半天时间,然后呢有其他办法方便测试。具体看我以前总结的博客,大致说下思路,要么直接在 buildTypes.debug 下配置正式签名打包,这样运行时,直接签名不是默认的 debug ,而是我们覆盖设置的 正式签名。


    点击看大图

    还有一种办法 直接去 AS–>Build –>Select Build Variant –> 选择 release ,然后运行 AS。
    前面那种办法我亲测有用,只有后面那种应该也可以,我在以前微信第三方登录时使用过,是可以的,因该是一个道理,没问题的。具体看下面博客吧!

    项目gradle学习之路(1)


    3 开发
    如果调起支付出问题或者调不起微信支付,一般都会返回 -1 ,这个问题比较严重,网上都出了 类似的搜索词条了,这里我也碰到过 -1 ,我只能说明下 我检查的分析和手段,首先 一定要保证 微信平台的的签名和运行的APP签名一致,这一定要再三检查下,可以使用最老的办法,通过
    Build –> Generate Signed APK –> 加上签名把 APK 生成出来在安装到手机上,微信端保证处于打开状态,然后网上说有可能需要清空微信的缓存,这里我倒是没有。


    如果上述都没问题,但还是报 -1 ,那可能就是 二次签名 sign 出问题了,这个 sign 获取方式,微信提供了思路,但是竟然没提供函数方法,难道想考验开发的算法功力。。。

    签名生成的通用步骤如下:
    
    第一步,设所有发送或者接收到的数据为集合M,将集合M内非空参数值的参数按照参数名ASCII码从小到大排序(字典序),使用URL键值对的格式(即key1=value1&key2=value2…)拼接成字符串stringA。
    
    特别注意以下重要规则:
    
    ◆ 参数名ASCII码从小到大排序(字典序);
    ◆ 如果参数的值为空不参与签名;
    ◆ 参数名区分大小写;
    ◆ 验证调用返回或微信主动通知签名时,传送的sign参数不参与签名,将生成的签名与该sign值作校验。
    ◆ 微信接口可能增加字段,验证签名时必须支持增加的扩展字段
    第二步,在stringA最后拼接上key得到stringSignTemp字符串,并对stringSignTemp进行MD5运算,再将得到的字符串所有字符转换为大写,得到sign值signValue。

    这里有个要注意的点,先看下面文档上要求发起支付请求的参数
    这里写图片描述

    先说下我自己认为的微信支付流程: app界面上选定金额后点击微信支付,先调用后台提供的接口,传递一些参数过去,最主要的参数当然是 金额大小,然后后台返回给我们结果,包含上图中除了 应用ID 以外的剩下参数,我们在将这些参数设置到微信提供的 API 中,向微信发起支付请求 。

    sign 这个字段是后台生成返回给我们的,我们在设置到请求参数中,所以后台在根据微信提供生成 sign 的算法时,上图中的 拓展字段 package 和 我们 用微信 API 设置参数的 字段不一样,

    payRequest.packageValue = "Sign=WXPay";

    看到没,所以我们后台在我一直 返回 -1 时也有疑问,到底使用哪个作为拼接的 key 。其实这里使用的还是
    package。当然了 我们后台确实是他给我的 sign 出问题了,导致 公众号支付 IOS 支付都没问题,就我 安卓一直不行,最后我决定自己生成 sign 来说服他。

    首先获取到后台返回给我们的所有数据,把他提供的签名 sign 去掉,然后 采用微信提供的 生成 sign
    思路获取到 sign,再将和 sign 一起的数据一起设置到 微信API 中,如果可以成功调用 微信支付,则 sign 确实后台返回给我们的有问题。
    自己拼接 key value 然后加密,可能会出错或者慢, 这里我在网上找了个生成 sign 的算法,找不到来源了,写博客的今天和当初时间很久了。

    package com.guo.firstdemo;
    
    import org.junit.Test;
    
    import java.util.*;
    
    /**
     * Created by guozhaohui628@gmail.com on 2018/2/27
     * Description:
     */
    public class SignDemo {
    
        /**
         * 获取sign签名
         *
         * @return
         */
        @Test
        public void genPayReq() {
    
            // 把参数的值传进去SortedMap集合里面
            SortedMap<Object, Object> parameters = new TreeMap<Object, Object>();
    
            //应用ID
            parameters.put("appid", "wx4446aecbce287ab8");
    
            //随机字符串
            parameters.put("noncestr", "48xQcKUtC2SULcmg");
    
            //扩展字段
            parameters.put("package", "Sign=WXPay");
    
            //商户号
            parameters.put("partnerid", "1499280172");
    
            //预支付交易会话ID
            parameters.put("prepayid", "wx201802271751141caa31c4510450228340");
    
            //时间戳
            parameters.put("timestamp","1519725074");
    
            String characterEncoding = "UTF-8";
            String mySign = createSign(characterEncoding, parameters);
            System.out.println("我的签名是:" + mySign);
        }
    
    
    
        /**
         * 微信支付签名算法sign
         *
         * @param characterEncoding
         * @param parameters
         * @return
         */
        public static String createSign(String characterEncoding,
                                        SortedMap<Object, Object> parameters) {
            StringBuffer sb = new StringBuffer();
            Set es = parameters.entrySet();// 所有参与传参的参数按照accsii排序(升序)
            Iterator it = es.iterator();
            while (it.hasNext()) {
                @SuppressWarnings("rawtypes")
                Map.Entry entry = (Map.Entry) it.next();
                String k = (String) entry.getKey();
                Object v = entry.getValue();
                if (null != v && !"".equals(v) && !"sign".equals(k)
                        && !"key".equals(k)) {
                    sb.append(k + "=" + v + "&");
                }
            }
            sb.append("key=" + "a0fa2659hdf65auh345fc9f6567k57fb5575f9c4"); //KEY是商户秘钥
            System.out.println("   ---sb--   "+sb.toString());
            String sign = MD5Util.MD5Encode(sb.toString(), characterEncoding)
                    .toUpperCase();
            return sign;
        }
    
    
    }
    
    package com.guo.firstdemo;
    
    import java.security.MessageDigest;
    
    /**
     * Created by guozhaohui628@gmail.com on 2018/2/27
     * Description:
     */
    public class MD5Util {
        private static String byteArrayToHexString(byte b[]) {
            StringBuffer resultSb = new StringBuffer();
            for (int i = 0; i < b.length; i++)
                resultSb.append(byteToHexString(b[i]));
    
            return resultSb.toString();
        }
    
        private static String byteToHexString(byte b) {
            int n = b;
            if (n < 0)
                n += 256;
            int d1 = n / 16;
            int d2 = n % 16;
            return hexDigits[d1] + hexDigits[d2];
        }
    
        public static String MD5Encode(String origin, String charsetname) {
            String resultString = null;
            try {
                resultString = new String(origin);
                MessageDigest md = MessageDigest.getInstance("MD5");
                if (charsetname == null || "".equals(charsetname))
                    resultString = byteArrayToHexString(md.digest(resultString
                            .getBytes()));
                else
                    resultString = byteArrayToHexString(md.digest(resultString
                            .getBytes(charsetname)));
            } catch (Exception exception) {
            }
            return resultString;
        }
    
        private static final String hexDigits[] = { "0", "1", "2", "3", "4", "5",
                "6", "7", "8", "9", "a", "b", "c", "d", "e", "f" };
    }
    

    里面 //KEY是商户秘钥 有点重要 注意别泄露 。
    好的 我到这里就解决了,后台修改了 生成 sign 的算法,成功调起了 微信支付。

    展开全文
  • Android微信支付接入(流程清晰) 最近有朋友问到微信支付的一些开发点,博主就把微信支付接入流程,捋一捋.基本初入安卓的也能根据本文,快速接入微信支付. 一 公司官方注册微信开放平台账号(准备1) 第一...

    #Android微信支付接入(三步完工解析+实例)

    最近有朋友问到微信支付的一些开发点,博主就把微信支付接入流程,捋一捋.基本初入安卓的也能根据本文,快速接入微信支付.默认读者具备签名打包知识(如不具备请先查阅相关知识点)

    参照博主提供例子,按照下文即可快速简单接入微信支付,给需要的读者直接上的安卓微信支付Demo

    一 公司官方注册微信开放平台账号(准备1)

    第一步:开发者第一点注意贵公司是否已申请微信开放平台账号( 微信目前只支持公司账号申请支付,暂不支持个人开发者支付申请),没有则协调沟通申请即可.

    这里写图片描述

    二 登录微信开放平台创建移动应用(准备2)

    • :登录账号后,点击上面菜单栏 [管理中心] – [移动应用]–[创建应用],创建应用三个步骤按提示填入(审核后这部分资料可修改),微信会在7天内完成审核.记录好AppIDAppSecret后面使用即可.

      注:博主那时负责安卓端与IOS端这块由我申请的,微信支持两端一起创建即可(这里踩过坑,读者注意)
      这里写图片描述

    • 安卓需要配置应用签名 :打一个release包,安装即可,在安装一个微信自己的获取签名APK,在该APK输入,刚才release包名,即可生成应用签名,绿色字体既是应用签名 (微信采用安全码策略:包名+应用名+应用签名,只要一个改变,就无法调起微信支付)

      微信官方截图如下:
      微信签名APK截图

    三 微信支付接入(核心代码)

    1.在app的build.gradle文件中,添加如下依赖:

    dependencies {
       compile 'com.tencent.mm.opensdk:wechat-sdk-android-with-mta:+'
    }
    

    2.在注册清单AndroidManifest.xml中添加权限与WXPayEntryActivity

        <uses-permission android:name="android.permission.INTERNET" />
        <uses-permission android:name="android.permission.MODIFY_AUDIO_SETTINGS"/>
        <uses-permission android:name="android.permission.WRITE_EXTERNAL_STORAGE"/>
    
        <activity
                android:name=".wxapi.WXPayEntryActivity"
                android:exported="true"
                android:launchMode="singleTop"/>
    

    3.在应用入口MyApplication中将该app注册到微信即可

    final IWXAPI msgApi = WXAPIFactory.createWXAPI(context, null);
    
    // 将该app注册到微信   AppID:步骤二申请到的AppID
    
    msgApi.registerApp(AppID);
    

    4.接受后台返回支付信息:在APP支付发起页面,向后台服务器请求,服务器生成预付单,返回response 成功,获取到prepay_id等相应参数,app再调起微信支付即可

      /**
         * 微信支付
         */
        public void payToWX() {
            StringBuilder url = new StringBuilder();
            url.append(Constants.GET_WX_PARAMETER);
            url.append("?Token=" + PreferencesUtils.getString(this, Constants.TOKEN_KEY));
            url.append("&orderNum=" + orderBean.getOrderNumber());
            HttpUtils.post(url.toString(), new HttpCallBack() {
                @Override
                public void onBefore(BaseRequest request) {
                    super.onBefore(request);
                    showDialog("加载中...");
                }
    
                @Override
                public void onSuccess(String s, Call call, Response response) {
                    InfoResultData infoResultData = new Gson().fromJson(s, InfoResultData.class);
                    if (infoResultData.getStatus() == 200) {
                        goToWX(infoResultData.getData().toString());
                    } else {
                        disDialog();
                        showShort(infoResultData.getMessage());
                    }
                }
    
                @Override
                public void onError(Call call, Response response, Exception e) {
                    super.onError(call, response, e);
                    disDialog();
                }
            });
        }
    

    5,调起原生微信支付:把服务器返回的,字典封装并提交给微信即可mWxApi.sendReq(req);

        /**
         * 前往微信页面支付
         */
        public void goToWX(String json) {
    	    // 可以在当前页面注册,或者前面APP 注册
            IWXAPI mWxApi = WXAPIFactory.createWXAPI(this, Constants.WX_APPID, true);
            mWxApi.registerApp(Constants.WX_APPID);
            if (mWxApi != null) {
                PayReq req = new PayReq();
                req.appId = Constants.WX_APPID;// 微信开放平台审核通过的应用APPID
                try {
                    JSONObject jsonObject = new JSONObject(json);
                    req.partnerId = jsonObject.getString("partnerid");// 微信支付分配的商户号
                    req.prepayId = jsonObject.getString("prepayid");// 预支付订单号,app服务器调用“统一下单”接口获取
                    req.nonceStr = jsonObject.getString("noncestr");// 随机字符串,不长于32位咱生成
                    req.timeStamp = jsonObject.getString("timestamp");// 时间戳
                    req.packageValue = jsonObject.getString("package");// 固定值Sign=WXPay,服务器返回固定值
                    req.sign = jsonObject.getString("sign");// 签名
                } catch (JSONException e) {
                    e.printStackTrace();
                }
                mWxApi.sendReq(req);
            }
        }
    

    6.支付成功:在WXPayEntryActivity页面接收微信支付结果回调,做自己相应需求即可

    	@Override
    	public void onResp(BaseResp resp) {
    		//0成功 -1支付出错 -2用户取消支付 
    		//-1支付出错可能的原因:签名错误、未注册APPID、项目设置APPID不正确、注册的APPID与设置的不匹配、其他异常等
    		if (resp.getType() == ConstantsAPI.COMMAND_PAY_BY_WX) {
    			//支付成功  TODO 
    		}
    	}
    

    注:踩过的坑–测试debug签正式签名即可调起(同release发布版一样操作即可)

    四 服务端坑点

    • 坑点一:服务端key,是微信商户平台,在账户设置,API安全,秘钥设置里面设置(这个坑我们后台接入时踩过)

    • 坑点二: 服务端返回数据需要带上商户IDpartnerId(我们后端估计没仔细看文档)

    • 坑点三: 服务端几个相关id,现在都是小写,请仔细看官方文档是id不是Id(最后直接 C + V保证一致)

    五 尾言

    希望读者看完上面文章即可简单快速接完微信支付,下面是官方链接

    微信开放平台

    微信开放平台接入指南

    微信APP端开发步骤

    六 微信返回-1终极处理补充(20190712)

    返回-1请注意:你已经确认你包名,签名等所有配置没问题,清空微信缓存,或者卸载微信缓存。
    开发时场景:debug 与 release签名切换后,导致返回-1,不能正常调起微信支付。这个是微信的一个bug也是一个坑,个人理解微信把包名和签名存储起来了,后面不更新,导致切换签名后,不能正常覆盖,而最终不能吊起支付。

    再说3次:卸载,卸载,卸载 即可

    补充–调不起微信支付原因

    注意包名,在xx.xxxxxx.xxxx.wxapi包路径中实现WXPayEntryActivity类(包名或类名不一致会造成无法回调)
    build文件配置:applicationIdSuffix 包名尾缀

    展开全文
  • “利用乐动力App的漏洞刷微信步数” 1. 手机下载乐动力App,iOS到AppStore下载,Android可到第三方应用市场下载。 2. 下载完成安装后用微信登陆。 3. 登陆完做好一些设置后来到首页,如下,初始时数显示0,...
  • 我们使用微信都知道,其右侧顶部有一个下拉对话框,我们可以执行添加好友,扫一扫等功能,今天我们就来模仿实现一下这个功能(实现的方式有很多种,我今天只说一种借助透明主题Activity的方式实现;如果有兴趣还可以...
  • 博主总结的很详细,前段时间也做过这一块,不过已经做完了。对于微信登录分享不清楚的童鞋来说,本篇帮助确实很大的。
  • 程 ... 微信运动刷是为了提供用户在微信运动排行榜的工具,该工具只需要简单的几就可以让你的排名爆涨,那么微信运动刷怎么用?下面清风小编就给大家具体介绍下微信运动刷使用教程
  • 今天模仿着微信的发送语音功能做了一下,现将步骤以及其中遇到的问题记录一下,以便以后查看。 实现功能:1、录制语音并显示到列表中;2、点击列表中的语音自动进行播放;3、录制语音时以及播放语音时的动画效果...
  • 为了提高转化率,就需要让用户不管是在微信或者是浏览器中,都能在点击链接后, 唤起本地的 app 后 , 跳转到指定页面 。虽然这个功能从用户体验方面来说是自然而然的,但是由于 iOS/Android 平台差异性,在实现...
  • 本来是不打算写关于微信支付的,网上有太多了,但是前些天一个哥们居然还问我微信支付怎么集成,所以准备做个记录。 以下内容是将微信支付的所有过程都放在在app端,这是不推荐的,实际中前几由服务器来做比较...
  • 一 概述 二 悬停头部的“交换动画” 实现了两种, 第一种就是仿饿了么点餐时,商品列表的悬停头部切换“动画效果”,如下: ...第二种是一种头部折叠起来的视效,个人觉得也还不错~...下面放文字版代码,江湖人称
  • 跟慕课网的教程制作的仿微信图片选择器,并且自己优化了在已有文件夹下增删图片之后重新在popupWindow中打开该文件夹是能够刷新数据的(也就是文件夹中的新的图片总数) 在这个实例中涉及利用多线程实现图片的异步...
  • 第二:官网随便填(当时填了百度都没事),然后应用平台选择Android,特别注意包名要和需要开发的包名是完全一致的(如果不知道在Manifest中找),而签名则需要通过你KeyStone来决定(请看第二点)。第
  • 一次集成支付宝以后,微信支付又开启了另一段痛苦的历程。由于以前没有做过微信支付,所以这次在做的过程中还是遇到很大的问题。而且,公司目前没有自己的后台,所有的接口都是外包来承接的,在遇到问题时,外包...
  • 一、微信SDK中会用到主要类的类图 上面这张类图中显示的是与微信通信过程中的请求类和响应类,第三方应用通过他们 附带的message字段来携带消息传输给微信进程。其中BaseResp有个内部...
1 2 3 4 5 ... 20
收藏数 3,417
精华内容 1,366