记一次微信支付的爬坑经历

微信支付步骤:
1.先去微信开放平台申请账号,创建移动应用,并审核通过,这样就可以获取到

    // APP_ID 替换为你的应用从官方网站申请到的合法appId
    public static final String APP_ID = "wwwwwwww";

    // 微信支付商户号
    public static final String APP_TENANT = "yyyyyy";

    // 秘钥(审核通过后会邮件通知你,然后让你登陆在里面设置秘钥)
    public static final String APP_TENANT_SIGN = "XXXXXXXXXXXXXXXXXXXXX";

2.接入微信支付的SDK
这里写图片描述

3.在AndroidManifest.xml文件中加入

<?xml version="1.0" encoding="utf-8"?>
<manifest xmlns:android="http://schemas.android.com/apk/res/android"
    package="com.xxx.yyyyy">

    <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" />

    <!-- for mta statistics -->
    <uses-permission android:name="android.permission.ACCESS_WIFI_STATE" />
    <uses-permission android:name="android.permission.READ_PHONE_STATE" />
    <uses-permission android:name="android.permission.ACCESS_NETWORK_STATE" />

    <application
        android:allowBackup="true"
        android:icon="@mipmap/ic_launcher"
        android:label="@string/app_name"
        android:supportsRtl="true"
        android:theme="@style/AppTheme">
        <activity android:name=".MainActivity">
            <intent-filter>
                <action android:name="android.intent.action.MAIN" />

                <category android:name="android.intent.category.LAUNCHER" />
            </intent-filter>
        </activity>
        <activity
            android:name=".wxapi.WXPayEntryActivity"
            android:exported="true"
            android:launchMode="singleTop" />

        <receiver android:name=".AppRegister">
            <intent-filter>
                <action android:name="com.tencent.mm.plugin.openapi.Intent.ACTION_REFRESH_WXAPP" />
            </intent-filter>
        </receiver>
    </application>

</manifest>

4.在你的包(必须是AndroidManifest.xml中的包名,上面3中的com.xxx.yyyyy)下面创建wxapi文件,在wxapi文件下面创建WXPayEntryActivity.java类;

public class WXPayEntryActivity extends Activity implements IWXAPIEventHandler {

    private static final String TAG = "MicroMsg.SDKSample.WXPayEntryActivity";

    private IWXAPI api;

    @Override
    public void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.pay_result);

        api = WXAPIFactory.createWXAPI(this, Constants.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) {
    }

    /**
     * 微信支付成功或失败取消支付的回调方法
     * @param resp
     */
    @Override
    public void onResp(BaseResp resp) {
        Log.e("WXPayEntryActivity", "onPayFinish, errCode = " + resp.errCode + "");

//      if (resp.getType() == ConstantsAPI.COMMAND_PAY_BY_WX) {
//          AlertDialog.Builder builder = new AlertDialog.Builder(this);
//          builder.setTitle(R.string.app_tip);
//          builder.setMessage(getString(R.string.pay_result_callback_msg, String.valueOf(resp.errCode)));
//          builder.show();
//      }

        System.out.println(resp.errCode);
        if (resp.getType() == ConstantsAPI.COMMAND_PAY_BY_WX) {
            if (resp.errCode == 0) {   // 0 成功  展示成功页面
                AlertDialog.Builder builder = new AlertDialog.Builder(this);
                builder.setTitle("微信支付结果");
                builder.setMessage("支付订单成功!");
                builder.setPositiveButton("确定", new DialogInterface.OnClickListener() {

                    @Override
                    public void onClick(DialogInterface dialog, int which) {
                        finish();
                    }
                });
                builder.show();
            } else if (resp.errCode == -1) {  // -1 错误  可能的原因:签名错误、未注册APPID、项目设置APPID不正确、注册的APPID与设置的不匹配、其他异常等。
                Toast.makeText(WXPayEntryActivity.this, "支付出错:" + resp.errStr, Toast.LENGTH_SHORT)
                        .show();
                finish();
            } else if (resp.errCode == -2) {  // -2 用户取消    无需处理。发生场景:用户不支付了,点击取消,返回APP。
                Toast.makeText(WXPayEntryActivity.this, "取消支付:" + resp.errStr, Toast.LENGTH_SHORT)
                        .show();
                finish();
            }
        }
    }
}

5.写一个广播类:AppRegister.java(这一步关系到是否能接收到微信的回调)

public class AppRegister extends BroadcastReceiver {

    @Override
    public void onReceive(Context context, Intent intent) {
        final IWXAPI msgApi = WXAPIFactory.createWXAPI(context, null);

        // 将该app注册到微信
        msgApi.registerApp("11225566666");
    }
}

注册到清单文件中:

<receiver android:name=".AppRegister">
            <intent-filter>
                <action android:name="com.tencent.mm.plugin.openapi.Intent.ACTION_REFRESH_WXAPP" />
            </intent-filter>
        </receiver>

接下来就是重点了:(踩坑比较多)

public class MainActivity extends Activity {

    private IWXAPI api;
    private OrderPayBean orderPaybean;

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_main);
        // 商户APP工程中引入微信JAR包,调用API前,需要先向微信注册您的APPID
        api = WXAPIFactory.createWXAPI(this, Constants.APP_ID);  // 参数二是申请的APPID

        // 将该app注册到微信
        api.registerApp(Constants.APP_ID);  // 参数是申请的APPID

        orderPaybean = new OrderPayBean();
        initData();
//        if (!TextUtils.isEmpty(IpUtil.getIPAddress(this))) {
//            String ipAddress = IpUtil.getIPAddress(this);
//            String s = ipAddress.substring(1,ipAddress.length()).trim();
//            Log.e("手机当前ip地址 = ", s);
//        }
//        Log.e("手机当前ip地址", IpUtil.getIPAddress(this));
    }

    private void initData() {
        orderPaybean.appid = Constants.APP_ID;
        orderPaybean.body = "微信支付";
        orderPaybean.mch_id = Constants.APP_TENANT;  // 商户号
        orderPaybean.nonce_str = Constants.genNonceStr();  // 获得随机字符串
        orderPaybean.notify_url = "https://www.google.com"; // //微信通知后台支付结果url
        orderPaybean.total_fee = 1;
        orderPaybean.trade_type = "APP";
        orderPaybean.out_trade_no = Constants.getNonceStr();
        orderPaybean.spbill_create_ip = "196.168.1.1";




        SortedMap<Object, Object> parameters = new TreeMap<Object, Object>();
        parameters.put("appid", orderPaybean.appid);
        parameters.put("body", orderPaybean.body);
        parameters.put("mch_id", orderPaybean.mch_id);
        parameters.put("nonce_str", orderPaybean.nonce_str);
        parameters.put("notify_url", orderPaybean.notify_url);
        parameters.put("out_trade_no", orderPaybean.out_trade_no);
        parameters.put("total_fee", orderPaybean.total_fee);
        parameters.put("trade_type", orderPaybean.trade_type);
        parameters.put("spbill_create_ip", orderPaybean.spbill_create_ip);
        parameters.put("sign", Constants.createSign("UTF-8", parameters, Constants.APP_TENANT_SIGN));//传入签名好的参数值


        StringBuilder xmlBuilder = new StringBuilder();
        xmlBuilder.append("<xml>");
        Set es = parameters.entrySet();//所有参与传参的参数按照accsii排序(升序)
        Iterator it = es.iterator();
        while (it.hasNext()) {
            Map.Entry entry = (Map.Entry) it.next();
            String k = (String) entry.getKey();
            Object v = entry.getValue();
            xmlBuilder.append("<").append(k).append(">");
            xmlBuilder.append(v);
            xmlBuilder.append("</").append(k).append(">");
        }
        xmlBuilder.append("</xml>");
        System.out.println(xmlBuilder.toString());
        try {
            new GetPrepayId(new String(xmlBuilder.toString().getBytes(), "ISO8859-1")).execute();//这一步非常重要,不这样转换编码的话,传递中文就会报“签名错误”,这是很多人都会遇到的错误。
        } catch (Exception e) {
            e.printStackTrace();
        }
    }

    public class GetPrepayId extends AsyncTask {
        String str;

        public GetPrepayId(String str) {
            this.str = str;
        }

        @Override
        protected void onPreExecute() {
            super.onPreExecute();
        }

        @Override
        protected Object doInBackground(Object[] params) {
            String url = "https://api.mch.weixin.qq.com/pay/unifiedorder";

            Log.e("参数", ">>>>" + str);

            byte[] buf = Util.httpPost(url, str);   // 发起订单向微信获取预支付交易会话标识prepay_id
            String content = null;

            if (buf != null) {
                content = new String(buf);
            }
//            String content = new String(buf);

            Log.e("返回数据", ">>>>" + content);

            Map<String, String> map = Constants.xmlToMap(content);
            String nonceStr = Constants.genNonceStr();
            String timeStamp = String.valueOf(Constants.genTimeStamp());
            SortedMap<Object, Object> parameters = new TreeMap<Object, Object>();
            parameters.put("appid", orderPaybean.appid);
            parameters.put("partnerid", orderPaybean.mch_id);
            parameters.put("prepayid", map.get("prepay_id"));
            parameters.put("package", "Sign=WXPay");
            parameters.put("noncestr", nonceStr);
            parameters.put("timestamp", timeStamp);

            PayReq request = new PayReq();
            request.appId = orderPaybean.appid;
            request.partnerId = orderPaybean.mch_id;
            request.prepayId = map.get("prepay_id");
            request.packageValue = "Sign=WXPay";
            request.nonceStr = nonceStr;
            request.timeStamp = timeStamp;
            request.sign = Constants.createSign("UTF-8", parameters, Constants.APP_TENANT_SIGN);
            api.sendReq(request);  // 发起支付
            return content;
        }
    }

}

PS:
当手机上面的微信在别处登陆的时候有时候会支付失败的(不提示没登录)
到此结束,感谢阅读。
当然奉上源码源码

下面贴上完整的代码:
工具类:Constants.java

package com.fly.weixin.utils;

import org.dom4j.Document;
import org.dom4j.Element;
import org.dom4j.io.SAXReader;
import java.io.ByteArrayInputStream;
import java.io.InputStream;
import java.util.HashMap;
import java.util.Iterator;
import java.util.List;
import java.util.Map;
import java.util.Random;
import java.util.Set;
import java.util.SortedMap;

public class Constants {
    // APP_ID 替换为你的应用从官方网站申请到的合法appId
    public static final String APP_ID = "flyflflyflyfly";

    // 微信支付商户号
    public static final String APP_TENANT = "20170611";

    // 应用签名
//    public static final String APP_TENANT_SIGN = "YYYYYYYYYYYYYYYYYYYYYYYYYYYYYYyy";

    // 秘钥
    public static final String APP_TENANT_SIGN = "xxxxxxxxxxxxxxxxxxxxxxxxx";


    //**********************************************************************************************************************************

    /**
     * 微信支付签名算法sign
     * @param characterEncoding 签名编码(UTF-8)
     * @param parameters 要签名的参数的集合
     * @param key 商户自己设置的key
     */
    @SuppressWarnings("unchecked")
    public static String createSign(String characterEncoding,SortedMap<Object,Object> parameters, String key){
        StringBuffer sb = new StringBuffer();
        Set es = parameters.entrySet();//所有参与传参的参数按照accsii排序(升序)
        Iterator it = es.iterator();
        while(it.hasNext()) {
            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=" + key);
        System.out.println(sb.toString());
        String sign = WxMd5.MD5Encode(sb.toString(), characterEncoding).toUpperCase();
        System.out.println(sign);
        return sign;
    }

    /**
     * 获取时间戳
     * @return
     */
    public static long genTimeStamp() {
        return System.currentTimeMillis() / 1000;
    }

    /**
     * 获得随机字符串
     * @return
     */
    public static String genNonceStr() {
        Random random = new Random();
        return MD5.getMessageDigest(String.valueOf(random.nextInt(10000)).getBytes());
    }

    // 生成随机号,防重复
    public static String getNonceStr() {
        Random random = new Random();
        return MD5.getMessageDigest(String.valueOf(random.nextInt(10000))
                .getBytes());
    }

    public static Map<String, String> xmlToMap(String xmlstr) {
        Map<String, String> map = new HashMap<>();

        try {
            SAXReader reader = new SAXReader();
            InputStream ins = new ByteArrayInputStream(xmlstr.getBytes("UTF-8"));
            Document doc = reader.read(ins);
            Element root = doc.getRootElement();

            List<Element> list = root.elements();

            for (Element e : list) {
                map.put(e.getName(), e.getText());
            }
            ins.close();
        } catch (Exception e) {
            e.printStackTrace();
        }
        return map;
    }
}

IpUtil.java

package com.fly.weixin.utils;

import android.content.Context;
import android.net.ConnectivityManager;
import android.net.NetworkInfo;
import android.net.wifi.WifiInfo;
import android.net.wifi.WifiManager;

import java.net.Inet4Address;
import java.net.InetAddress;
import java.net.NetworkInterface;
import java.net.SocketException;
import java.util.Enumeration;

/**
 * Created by Administrator on 2017/6/7.
 *
 */
public class IpUtil {

    /**
     * 获取手机的ip地址
     * @param context
     * @return
     */
    public static String getIPAddress(Context context) {
        NetworkInfo info = ((ConnectivityManager) context
                .getSystemService(Context.CONNECTIVITY_SERVICE)).getActiveNetworkInfo();
        if (info != null && info.isConnected()) {
            if (info.getType() == ConnectivityManager.TYPE_MOBILE) {//当前使用2G/3G/4G网络
                try {
                    //Enumeration<NetworkInterface> en=NetworkInterface.getNetworkInterfaces();
                    for (Enumeration<NetworkInterface> en = NetworkInterface.getNetworkInterfaces(); en.hasMoreElements(); ) {
                        NetworkInterface intf = en.nextElement();
                        for (Enumeration<InetAddress> enumIpAddr = intf.getInetAddresses(); enumIpAddr.hasMoreElements(); ) {
                            InetAddress inetAddress = enumIpAddr.nextElement();
                            if (!inetAddress.isLoopbackAddress() && inetAddress instanceof Inet4Address) {
                                return inetAddress.getHostAddress();
                            }
                        }
                    }
                } catch (SocketException e) {
                    e.printStackTrace();
                }

            } else if (info.getType() == ConnectivityManager.TYPE_WIFI) {//当前使用无线网络
                WifiManager wifiManager = (WifiManager) context.getSystemService(Context.WIFI_SERVICE);
                WifiInfo wifiInfo = wifiManager.getConnectionInfo();
                String ipAddress = intIP2StringIP(wifiInfo.getIpAddress());//得到IPV4地址
                return ipAddress;
            }
        } else {
            //当前无网络连接,请在设置中打开网络
        }
        return null;
    }

    /**
     * 将得到的int类型的IP转换为String类型
     *
     * @param ip
     * @return
     */
    public static String intIP2StringIP(int ip) {
        return (ip & 0xFF) + "." +
                ((ip >> 8) & 0xFF) + "." +
                ((ip >> 16) & 0xFF) + "." +
                (ip >> 24 & 0xFF);
    }

}

MD5.java

package com.fly.weixin.utils;

import java.security.MessageDigest;

public class MD5 {

    private MD5() {}

    public final static String getMessageDigest(byte[] buffer) {
        char hexDigits[] = { '0', '1', '2', '3', '4', '5', '6', '7', '8', '9', 'a', 'b', 'c', 'd', 'e', 'f' };
        try {
            MessageDigest mdTemp = MessageDigest.getInstance("MD5");
            mdTemp.update(buffer);
            byte[] md = mdTemp.digest();
            int j = md.length;
            char str[] = new char[j * 2];
            int k = 0;
            for (int i = 0; i < j; i++) {
                byte byte0 = md[i];
                str[k++] = hexDigits[byte0 >>> 4 & 0xf];
                str[k++] = hexDigits[byte0 & 0xf];
            }
            return new String(str);
        } catch (Exception e) {
            return null;
        }
    }

    private final static String[] hexDigits = {"0", "1", "2", "3", "4", "5", "6", "7",
            "8", "9", "a", "b", "c", "d", "e", "f"};

    /**
     * 转换字节数组为16进制字串
     * @param b 字节数组
     * @return 16进制字串
     */
    public static String byteArrayToHexString(byte[] b) {
        StringBuilder resultSb = new StringBuilder();
        for (byte aB : b) {
            resultSb.append(byteToHexString(aB));
        }
        return resultSb.toString();
    }

    /**
     * 转换byte到16进制
     * @param b 要转换的byte
     * @return 16进制格式
     */
    private static String byteToHexString(byte b) {
        int n = b;
        if (n < 0) {
            n = 256 + n;
        }
        int d1 = n / 16;
        int d2 = n % 16;
        return hexDigits[d1] + hexDigits[d2];
    }

    /**
     * MD5编码
     * @param origin 原始字符串
     * @return 经过MD5加密之后的结果
     */
    public static String MD5Encode(String origin) {
        String resultString = null;
        try {
            resultString = origin;
            MessageDigest md = MessageDigest.getInstance("MD5");
            md.update(resultString.getBytes("UTF-8"));
            resultString = byteArrayToHexString(md.digest());
        } catch (Exception e) {
            e.printStackTrace();
        }
        return resultString;
    }
}

Util.java

package com.fly.weixin.utils;

import android.graphics.Bitmap;
import android.graphics.Bitmap.CompressFormat;
import android.graphics.BitmapFactory;
import android.util.Log;

import junit.framework.Assert;

import org.apache.http.HttpResponse;
import org.apache.http.HttpStatus;
import org.apache.http.HttpVersion;
import org.apache.http.client.HttpClient;
import org.apache.http.client.methods.HttpGet;
import org.apache.http.client.methods.HttpPost;
import org.apache.http.conn.ClientConnectionManager;
import org.apache.http.conn.scheme.PlainSocketFactory;
import org.apache.http.conn.scheme.Scheme;
import org.apache.http.conn.scheme.SchemeRegistry;
import org.apache.http.conn.ssl.SSLSocketFactory;
import org.apache.http.entity.StringEntity;
import org.apache.http.impl.client.DefaultHttpClient;
import org.apache.http.impl.conn.tsccm.ThreadSafeClientConnManager;
import org.apache.http.params.BasicHttpParams;
import org.apache.http.params.HttpParams;
import org.apache.http.params.HttpProtocolParams;
import org.apache.http.protocol.HTTP;
import org.apache.http.util.EntityUtils;

import java.io.ByteArrayOutputStream;
import java.io.File;
import java.io.IOException;
import java.io.RandomAccessFile;
import java.net.Socket;
import java.net.UnknownHostException;
import java.security.KeyManagementException;
import java.security.KeyStore;
import java.security.KeyStoreException;
import java.security.MessageDigest;
import java.security.NoSuchAlgorithmException;
import java.security.UnrecoverableKeyException;
import java.security.cert.X509Certificate;
import java.util.ArrayList;
import java.util.List;

import javax.net.ssl.SSLContext;
import javax.net.ssl.TrustManager;
import javax.net.ssl.X509TrustManager;

public class Util {

    private static final String TAG = "SDK_Sample.Util";

    public static byte[] bmpToByteArray(final Bitmap bmp, final boolean needRecycle) {
        ByteArrayOutputStream output = new ByteArrayOutputStream();
        bmp.compress(CompressFormat.PNG, 100, output);
        if (needRecycle) {
            bmp.recycle();
        }

        byte[] result = output.toByteArray();
        try {
            output.close();
        } catch (Exception e) {
            e.printStackTrace();
        }

        return result;
    }

    public static byte[] httpGet(final String url) {
        if (url == null || url.length() == 0) {
            Log.e(TAG, "httpGet, url is null");
            return null;
        }

        HttpClient httpClient = getNewHttpClient();
        HttpGet httpGet = new HttpGet(url);

        try {
            HttpResponse resp = httpClient.execute(httpGet);
            if (resp.getStatusLine().getStatusCode() != HttpStatus.SC_OK) {
                Log.e(TAG, "httpGet fail, status code = " + resp.getStatusLine().getStatusCode());
                return null;
            }

            return EntityUtils.toByteArray(resp.getEntity());

        } catch (Exception e) {
            Log.e(TAG, "httpGet exception, e = " + e.getMessage());
            e.printStackTrace();
            return null;
        }
    }

    public static byte[] httpPost(String url, String entity) {
        if (url == null || url.length() == 0) {
            Log.e(TAG, "httpPost, url is null");
            return null;
        }

        HttpClient httpClient = getNewHttpClient();

        HttpPost httpPost = new HttpPost(url);

        try {
            httpPost.setEntity(new StringEntity(entity));
            httpPost.setHeader("Accept", "application/json");
            httpPost.setHeader("Content-type", "application/json");

            HttpResponse resp = httpClient.execute(httpPost);
            if (resp.getStatusLine().getStatusCode() != HttpStatus.SC_OK) {
                Log.e(TAG, "httpGet fail, status code = " + resp.getStatusLine().getStatusCode());
                return null;
            }

            return EntityUtils.toByteArray(resp.getEntity());
        } catch (Exception e) {
            Log.e(TAG, "httpPost exception, e = " + e.getMessage());
            e.printStackTrace();
            return null;
        }
    }

    private static class SSLSocketFactoryEx extends SSLSocketFactory {      

        SSLContext sslContext = SSLContext.getInstance("TLS");      

        public SSLSocketFactoryEx(KeyStore truststore) throws NoSuchAlgorithmException, KeyManagementException, KeyStoreException, UnrecoverableKeyException {      
            super(truststore);      

            TrustManager tm = new X509TrustManager() {      

                public X509Certificate[] getAcceptedIssuers() {      
                    return null;      
                }      

                @Override
                public void checkClientTrusted(X509Certificate[] chain, String authType) throws java.security.cert.CertificateException {
                }

                @Override
                public void checkServerTrusted(X509Certificate[] chain, String authType) throws java.security.cert.CertificateException {
                }  
            };      

            sslContext.init(null, new TrustManager[] { tm }, null);      
        }      

        @Override
        public Socket createSocket(Socket socket, String host, int port, boolean autoClose) throws IOException, UnknownHostException {
            return sslContext.getSocketFactory().createSocket(socket, host, port, autoClose);
        }

        @Override
        public Socket createSocket() throws IOException {
            return sslContext.getSocketFactory().createSocket();
        } 
    }  

    private static HttpClient getNewHttpClient() { 
       try { 
           KeyStore trustStore = KeyStore.getInstance(KeyStore.getDefaultType()); 
           trustStore.load(null, null); 

           SSLSocketFactory sf = new SSLSocketFactoryEx(trustStore); 
           sf.setHostnameVerifier(SSLSocketFactory.ALLOW_ALL_HOSTNAME_VERIFIER); 

           HttpParams params = new BasicHttpParams();
           HttpProtocolParams.setVersion(params, HttpVersion.HTTP_1_1);
           HttpProtocolParams.setContentCharset(params, HTTP.UTF_8);

           SchemeRegistry registry = new SchemeRegistry();
           registry.register(new Scheme("http", PlainSocketFactory.getSocketFactory(), 80));
           registry.register(new Scheme("https", sf, 443)); 

           ClientConnectionManager ccm = new ThreadSafeClientConnManager(params, registry);

           return new DefaultHttpClient(ccm, params);
       } catch (Exception e) { 
           return new DefaultHttpClient(); 
       } 
    }

    public static byte[] readFromFile(String fileName, int offset, int len) {
        if (fileName == null) {
            return null;
        }

        File file = new File(fileName);
        if (!file.exists()) {
            Log.i(TAG, "readFromFile: file not found");
            return null;
        }

        if (len == -1) {
            len = (int) file.length();
        }

        Log.d(TAG, "readFromFile : offset = " + offset + " len = " + len + " offset + len = " + (offset + len));

        if(offset <0){
            Log.e(TAG, "readFromFile invalid offset:" + offset);
            return null;
        }
        if(len <=0 ){
            Log.e(TAG, "readFromFile invalid len:" + len);
            return null;
        }
        if(offset + len > (int) file.length()){
            Log.e(TAG, "readFromFile invalid file len:" + file.length());
            return null;
        }

        byte[] b = null;
        try {
            RandomAccessFile in = new RandomAccessFile(fileName, "r");
            b = new byte[len]; // ���������ļ���С������
            in.seek(offset);
            in.readFully(b);
            in.close();

        } catch (Exception e) {
            Log.e(TAG, "readFromFile : errMsg = " + e.getMessage());
            e.printStackTrace();
        }
        return b;
    }

    private static final int MAX_DECODE_PICTURE_SIZE = 1920 * 1440;
    public static Bitmap extractThumbNail(final String path, final int height, final int width, final boolean crop) {
        Assert.assertTrue(path != null && !path.equals("") && height > 0 && width > 0);

        BitmapFactory.Options options = new BitmapFactory.Options();

        try {
            options.inJustDecodeBounds = true;
            Bitmap tmp = BitmapFactory.decodeFile(path, options);
            if (tmp != null) {
                tmp.recycle();
                tmp = null;
            }

            Log.d(TAG, "extractThumbNail: round=" + width + "x" + height + ", crop=" + crop);
            final double beY = options.outHeight * 1.0 / height;
            final double beX = options.outWidth * 1.0 / width;
            Log.d(TAG, "extractThumbNail: extract beX = " + beX + ", beY = " + beY);
            options.inSampleSize = (int) (crop ? (beY > beX ? beX : beY) : (beY < beX ? beX : beY));
            if (options.inSampleSize <= 1) {
                options.inSampleSize = 1;
            }

            // NOTE: out of memory error
            while (options.outHeight * options.outWidth / options.inSampleSize > MAX_DECODE_PICTURE_SIZE) {
                options.inSampleSize++;
            }

            int newHeight = height;
            int newWidth = width;
            if (crop) {
                if (beY > beX) {
                    newHeight = (int) (newWidth * 1.0 * options.outHeight / options.outWidth);
                } else {
                    newWidth = (int) (newHeight * 1.0 * options.outWidth / options.outHeight);
                }
            } else {
                if (beY < beX) {
                    newHeight = (int) (newWidth * 1.0 * options.outHeight / options.outWidth);
                } else {
                    newWidth = (int) (newHeight * 1.0 * options.outWidth / options.outHeight);
                }
            }

            options.inJustDecodeBounds = false;

            Log.i(TAG, "bitmap required size=" + newWidth + "x" + newHeight + ", orig=" + options.outWidth + "x" + options.outHeight + ", sample=" + options.inSampleSize);
            Bitmap bm = BitmapFactory.decodeFile(path, options);
            if (bm == null) {
                Log.e(TAG, "bitmap decode failed");
                return null;
            }

            Log.i(TAG, "bitmap decoded size=" + bm.getWidth() + "x" + bm.getHeight());
            final Bitmap scale = Bitmap.createScaledBitmap(bm, newWidth, newHeight, true);
            if (scale != null) {
                bm.recycle();
                bm = scale;
            }

            if (crop) {
                final Bitmap cropped = Bitmap.createBitmap(bm, (bm.getWidth() - width) >> 1, (bm.getHeight() - height) >> 1, width, height);
                if (cropped == null) {
                    return bm;
                }

                bm.recycle();
                bm = cropped;
                Log.i(TAG, "bitmap croped size=" + bm.getWidth() + "x" + bm.getHeight());
            }
            return bm;

        } catch (final OutOfMemoryError e) {
            Log.e(TAG, "decode bitmap failed: " + e.getMessage());
            options = null;
        }

        return null;
    }

    public static String sha1(String str) {
        if (str == null || str.length() == 0) {
            return null;
        }

        char hexDigits[] = { '0', '1', '2', '3', '4', '5', '6', '7', '8', '9', 'a', 'b', 'c', 'd', 'e', 'f' };

        try {
            MessageDigest mdTemp = MessageDigest.getInstance("SHA1");
            mdTemp.update(str.getBytes());

            byte[] md = mdTemp.digest();
            int j = md.length;
            char buf[] = new char[j * 2];
            int k = 0;
            for (int i = 0; i < j; i++) {
                byte byte0 = md[i];
                buf[k++] = hexDigits[byte0 >>> 4 & 0xf];
                buf[k++] = hexDigits[byte0 & 0xf];
            }
            return new String(buf);
        } catch (Exception e) {
            return null;
        }
    }

    public static List<String> stringsToList(final String[] src) {
        if (src == null || src.length == 0) {
            return null;
        }
        final List<String> result = new ArrayList<String>();
        for (int i = 0; i < src.length; i++) {
            result.add(src[i]);
        }
        return result;
    }
}

WxMd5.java

package com.fly.weixin.utils;

import java.security.MessageDigest;

/**
 * Created by Administrator on 2017/6/6.
 */
public class WxMd5 {

    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("utf-8")));
        } 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" };

}

bean包下的:OrderPayBean.java

package com.fly.weixin.bean;

import java.io.Serializable;

/**
 * Created by fly on 2017/6/6.
 */
public class OrderPayBean implements Serializable {

    public String appid; //appid
    public String body; //商品描述
    public String mch_id; //商户ID
    public String nonce_str; //随机字符串
    public String notify_url; //微信通知后台支付结果url
    public String out_trade_no; //我们自己的订单号
    public String spbill_create_ip; //客户端IP
    public int total_fee; //总的支付金额
    public String trade_type; //因为是移动应用 所以是APP
    public String sign; //以上所有参数的MD5签名

}

wxapi包下:WXPayEntryActivity.java

package com.fly.weixin.wxapi;

import android.app.Activity;
import android.app.AlertDialog;
import android.content.DialogInterface;
import android.content.Intent;
import android.os.Bundle;
import android.util.Log;
import android.widget.Toast;

import com.fly.weixin.R;
import com.fly.weixin.utils.Constants;
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;

/**
 * 把这个activity设置成dialog的样式,效果会更好
 */
public class WXPayEntryActivity extends Activity implements IWXAPIEventHandler {

    private static final String TAG = "MicroMsg.SDKSample.WXPayEntryActivity";

    private IWXAPI api;

    @Override
    public void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.pay_result);

        api = WXAPIFactory.createWXAPI(this, Constants.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) {
    }

    /**
     * 微信支付成功或失败取消支付的回调方法
     * @param resp
     */
    @Override
    public void onResp(BaseResp resp) {
        Log.e("WXPayEntryActivity", "onPayFinish, errCode = " + resp.errCode + "");

//      if (resp.getType() == ConstantsAPI.COMMAND_PAY_BY_WX) {
//          AlertDialog.Builder builder = new AlertDialog.Builder(this);
//          builder.setTitle(R.string.app_tip);
//          builder.setMessage(getString(R.string.pay_result_callback_msg, String.valueOf(resp.errCode)));
//          builder.show();
//      }

        System.out.println(resp.errCode);
        if (resp.getType() == ConstantsAPI.COMMAND_PAY_BY_WX) {
            if (resp.errCode == 0) {   // 0 成功  展示成功页面
                AlertDialog.Builder builder = new AlertDialog.Builder(this);
                builder.setTitle("微信支付结果");
                builder.setMessage("支付订单成功!");
                builder.setPositiveButton("确定", new DialogInterface.OnClickListener() {

                    @Override
                    public void onClick(DialogInterface dialog, int which) {
                        finish();
                    }
                });
                builder.show();
            } else if (resp.errCode == -1) {  // -1 错误  可能的原因:签名错误、未注册APPID、项目设置APPID不正确、注册的APPID与设置的不匹配、其他异常等。
                Toast.makeText(WXPayEntryActivity.this, "支付出错:" + resp.errStr, Toast.LENGTH_SHORT)
                        .show();
                finish();
            } else if (resp.errCode == -2) {  // -2 用户取消    无需处理。发生场景:用户不支付了,点击取消,返回APP。
                Toast.makeText(WXPayEntryActivity.this, "取消支付:" + resp.errStr, Toast.LENGTH_SHORT)
                        .show();
                finish();
            }
        }
    }
}

广播:

package com.fly.weixin.wx_success;

import android.content.BroadcastReceiver;
import android.content.Context;
import android.content.Intent;

import com.fly.weixin.utils.Constants;
import com.tencent.mm.opensdk.openapi.IWXAPI;
import com.tencent.mm.opensdk.openapi.WXAPIFactory;

public class AppRegister extends BroadcastReceiver {

    @Override
    public void onReceive(Context context, Intent intent) {
        final IWXAPI msgApi = WXAPIFactory.createWXAPI(context, null);

        // 将该app注册到微信
        msgApi.registerApp(Constants.APP_ID);
    }
}

发起支付的代码:MainActivity.java

package com.fly.weixin.wx_success;

import android.app.Activity;
import android.os.AsyncTask;
import android.os.Bundle;
import android.util.Log;

import com.fly.weixin.R;
import com.fly.weixin.bean.OrderPayBean;
import com.fly.weixin.utils.Constants;
import com.fly.weixin.utils.Util;
import com.tencent.mm.opensdk.modelpay.PayReq;
import com.tencent.mm.opensdk.openapi.IWXAPI;
import com.tencent.mm.opensdk.openapi.WXAPIFactory;

import java.util.Iterator;
import java.util.Map;
import java.util.Set;
import java.util.SortedMap;
import java.util.TreeMap;

public class MainActivity extends Activity {

    private IWXAPI api;
    private OrderPayBean orderPaybean;

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_main);
        // 商户APP工程中引入微信JAR包,调用API前,需要先向微信注册您的APPID
        api = WXAPIFactory.createWXAPI(this, Constants.APP_ID);  // 参数二是申请的APPID

        // 将该app注册到微信
        api.registerApp(Constants.APP_ID);  // 参数是申请的APPID

        orderPaybean = new OrderPayBean();
        initData();
//        if (!TextUtils.isEmpty(IpUtil.getIPAddress(this))) {
//            String ipAddress = IpUtil.getIPAddress(this);
//            String s = ipAddress.substring(1,ipAddress.length()).trim();
//            Log.e("手机当前ip地址 = ", s);
//        }
//        Log.e("手机当前ip地址", IpUtil.getIPAddress(this));
    }

    private void initData() {
        orderPaybean.appid = Constants.APP_ID;
        orderPaybean.body = "微信支付";
        orderPaybean.mch_id = Constants.APP_TENANT;  // 商户号
        orderPaybean.nonce_str = Constants.genNonceStr();  // 获得随机字符串
        orderPaybean.notify_url = "https://www.google.com"; // //微信通知后台支付结果url
        orderPaybean.total_fee = 1;
        orderPaybean.trade_type = "APP";
        orderPaybean.out_trade_no = Constants.getNonceStr();
        orderPaybean.spbill_create_ip = "196.168.1.1";




        SortedMap<Object, Object> parameters = new TreeMap<Object, Object>();
        parameters.put("appid", orderPaybean.appid);
        parameters.put("body", orderPaybean.body);
        parameters.put("mch_id", orderPaybean.mch_id);
        parameters.put("nonce_str", orderPaybean.nonce_str);
        parameters.put("notify_url", orderPaybean.notify_url);
        parameters.put("out_trade_no", orderPaybean.out_trade_no);
        parameters.put("total_fee", orderPaybean.total_fee);
        parameters.put("trade_type", orderPaybean.trade_type);
        parameters.put("spbill_create_ip", orderPaybean.spbill_create_ip);
        parameters.put("sign", Constants.createSign("UTF-8", parameters, Constants.APP_TENANT_SIGN));//传入签名好的参数值


        StringBuilder xmlBuilder = new StringBuilder();
        xmlBuilder.append("<xml>");
        Set es = parameters.entrySet();//所有参与传参的参数按照accsii排序(升序)
        Iterator it = es.iterator();
        while (it.hasNext()) {
            Map.Entry entry = (Map.Entry) it.next();
            String k = (String) entry.getKey();
            Object v = entry.getValue();
            xmlBuilder.append("<").append(k).append(">");
            xmlBuilder.append(v);
            xmlBuilder.append("</").append(k).append(">");
        }
        xmlBuilder.append("</xml>");
        System.out.println(xmlBuilder.toString());
        try {
            new GetPrepayId(new String(xmlBuilder.toString().getBytes(), "ISO8859-1")).execute();//这一步非常重要,不这样转换编码的话,传递中文就会报“签名错误”,这是很多人都会遇到的错误。
        } catch (Exception e) {
            e.printStackTrace();
        }
    }

    public class GetPrepayId extends AsyncTask {
        String str;

        public GetPrepayId(String str) {
            this.str = str;
        }

        @Override
        protected void onPreExecute() {
            super.onPreExecute();
        }

        @Override
        protected Object doInBackground(Object[] params) {
            String url = "https://api.mch.weixin.qq.com/pay/unifiedorder";

            Log.e("参数", ">>>>" + str);

            byte[] buf = Util.httpPost(url, str);   // 发起订单向微信获取预支付交易会话标识prepay_id
            String content = null;

            if (buf != null) {
                content = new String(buf);
            }
//            String content = new String(buf);

            Log.e("返回数据", ">>>>" + content);

            Map<String, String> map = Constants.xmlToMap(content);
            String nonceStr = Constants.genNonceStr();
            String timeStamp = String.valueOf(Constants.genTimeStamp());
            SortedMap<Object, Object> parameters = new TreeMap<Object, Object>();
            parameters.put("appid", orderPaybean.appid);
            parameters.put("partnerid", orderPaybean.mch_id);
            parameters.put("prepayid", map.get("prepay_id"));
            parameters.put("package", "Sign=WXPay");
            parameters.put("noncestr", nonceStr);
            parameters.put("timestamp", timeStamp);

            PayReq request = new PayReq();
            request.appId = orderPaybean.appid;
            request.partnerId = orderPaybean.mch_id;
            request.prepayId = map.get("prepay_id");
            request.packageValue = "Sign=WXPay";
            request.nonceStr = nonceStr;
            request.timeStamp = timeStamp;
            request.sign = Constants.createSign("UTF-8", parameters, Constants.APP_TENANT_SIGN);
            api.sendReq(request);  // 发起支付
            return content;
        }
    }

}

配置文件:

apply plugin: 'com.android.application'

android {
    signingConfigs {
        fly_wx {
            keyAlias 'keyStore'
            keyPassword 'android'
            storeFile file('C:/Users/Administrator.SKY-20170131CUA/Desktop/keyStore.jks')
            storePassword 'android'
        }
    }
    compileSdkVersion 25
    buildToolsVersion "25.0.2"
    defaultConfig {
        applicationId "com.fly.weixin"
        minSdkVersion 14
        targetSdkVersion 25
        versionCode 1
        versionName "1.0"
        /*ndk{
            moduleName "helloJni"/*//*生成的so文件名,必填
            abiFilters "armeabi", "armeabi-v7a", "x86" //配置输出的abi体系结构下的so库,
        }*/
    }
    buildTypes {
        release {
            minifyEnabled false
            proguardFiles getDefaultProguardFile('proguard-android.txt'), 'proguard-rules.pro'
            signingConfig signingConfigs.fly_wx
        }
        debug {
            signingConfig signingConfigs.fly_wx
        }
    }
    useLibrary 'org.apache.http.legacy'
}

dependencies {
    compile fileTree(include: ['*.jar'], dir: 'libs')
    testCompile 'junit:junit:4.12'
    compile 'com.android.support:appcompat-v7:25.3.1'
    compile 'com.tencent.mm.opensdk:wechat-sdk-android-with-mta:+'
    compile files('libs/dom4j-1.6.1.jar')
}
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值