Android 微信支付

微信支付成功起调

Android 微信支付

微信skd下载:https://pay.weixin.qq.com/wiki/doc/api/app/app.php?chapter=11_1

1、首先到微信.开放平台创建账号,登录

微信开放平台:https://open.weixin.qq.com/

2、创建应用,申请微信支付权限

申请通过,填写  资料审核——审核通过如下:

Android 微信支付

 

3、微信支付  入驻申请通过会受到邮件如下:两个支付要用到的参数,商户号和APPID

Android 微信支付

这是点击前往操作,进入微信支付。商户平台

Android 微信支付

点击设置**,完成设置**并保持**,这个**是微信支付的第三个参数,也是最后一个参数。

只需APPID 、商户号、**;三个参数即可完成微信支付

4、微信支付六个工具类:

Android 微信支付

 

public class Constants {

    // appid

    public static final String APP_ID = "wx1201a018f113ce4";

    // 商户号

    public static final String MCH_ID = "1516571378";

    /**
     * 微信开放平台和商户约定的支付**
     *
     * 注意:不能hardcode在客户端,建议genSign这个过程由服务器端完成
     */

    public static final String APP_KEY = "01b2e2bd222e0db0c3765609ebc9b59f";

}

、、、、、、、、、、、、、、、、、、、、、、、、、

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;
        }
    }
}

、、、、、、、、、、、、、、、、、、、、、、、、、、、、、、、

public class WXPayEntryActivity extends Activity implements IWXAPIEventHandler {

    private IWXAPI api;

//    public static final String APP_ID = "wxf660cc9ea105ccae";
    public static final String APP_ID = "wx1201a018f11dcec6";

    @Override
    public void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);

        api = WXAPIFactory.createWXAPI(this, APP_ID);
        api.handleIntent(getIntent(), this);
    }

    @Override
    protected void onNewIntent(Intent intent) {
        super.onNewIntent(intent);
        setIntent(intent);
        api.handleIntent(intent, this);
    }

    @Override
    public void onReq(BaseReq req) {
    }

    @Override
    public void onResp(BaseResp resp) {
        if (resp.getType() == ConstantsAPI.COMMAND_PAY_BY_WX) {
            //回调结果
            if (
                    resp.errCode == 0) { Toast.makeText(WXPayEntryActivity.this,"支付成功", Toast.LENGTH_LONG).show();
//                BaseApplication.isPay = true;//设置标志为支付完成
//                if (BaseApplication.pay_Flag == 1) {
//                    RechargeActivity.updateData();
//                } else if (BaseApplication.pay_Flag == 2) {
//                    UpgradePayActivity.updateData();
//                } else if (BaseApplication.pay_Flag == 3) {
//                    BuyPeachActivity.updateData();
//                }
            } else if (resp.errCode == -2) {
                Toast.makeText(WXPayEntryActivity.this,"支付取消", Toast.LENGTH_LONG).show();
            }
            finish();
        }
    }

}

、、、、、、、、、、、、、、、、、、、、、、、、、、

/**
 * 微信分享回调
 */
public class WXEntryActivity extends WXCallbackActivity implements IWXAPIEventHandler {

//    // IWXAPI 是第三方app和微信通信的openapi接口
//    private IWXAPI api;
//
//    @Override
//    public void onCreate(Bundle savedInstanceState) {
//        super.onCreate(savedInstanceState);
//
//        // 通过WXAPIFactory工厂,获取IWXAPI的实例
//        api = WXAPIFactory.createWXAPI(this, Constants.APP_ID, false);
//        api.registerApp(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) {
////        switch (req.getType()) {
////            case ConstantsAPI.COMMAND_GETMESSAGE_FROM_WX:
////                goToGetMsg();
////                break;
////            case ConstantsAPI.COMMAND_SHOWMESSAGE_FROM_WX:
////                goToShowMsg((ShowMessageFromWX.Req) req);
////                break;
////            default:
////                break;
////        }
//    }
//
//    // 第三方应用发送到微信的请求处理后的响应结果,会回调到该方法
//    @Override
//    public void onResp(BaseResp resp) {
//        int result;
//        switch (resp.errCode) {
//            case BaseResp.ErrCode.ERR_OK:
//                result = R.string.common_share_success;
//                break;
//            case BaseResp.ErrCode.ERR_USER_CANCEL:
//                result = R.string.common_share_cancel;
//                break;
//            case BaseResp.ErrCode.ERR_AUTH_DENIED:
//                result = R.string.common_share_failure;
//                break;
//            default:
//                result = R.string.common_share_failure;
//                break;
//        }
//        ToastUtil.centralToast(getResources().getString(result), this);
//        finish();
//    }

}

。。。。。。。。。。。。。。。。。。。。。。。。。

public class HttpWxUtile {

    private static final String TAG = "lgq";

    public static byte[] bmpToByteArray(final Bitmap bmp, final boolean needRecycle) {
        ByteArrayOutputStream output = new ByteArrayOutputStream();
        bmp.compress(Bitmap.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.i(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.i(TAG, "httpGet fail, status code = " + resp.getStatusLine().getStatusCode());
                return null;
            }

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

        } catch (Exception e) {
            Log.i(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.i(TAG, "httpPost, url is null");
            return null;
        }

        HttpClient httpClient = getNewHttpClient();
        HttpPost httpPost = new HttpPost(url);

        try {
            httpPost.setEntity(new StringEntity(entity, "UTF-8"));
            httpPost.setHeader("Accept", "application/json");
            httpPost.setHeader("Content-type", "application/json");
            HttpResponse resp = httpClient.execute(httpPost);
            if (resp.getStatusLine().getStatusCode() != HttpStatus.SC_OK) {
                Log.i(TAG, "httpGet fail, status code = " + resp.getStatusLine().getStatusCode());
                return null;
            }

            return EntityUtils.toByteArray(resp.getEntity());
        } catch (Exception e) {
            Log.i(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;
    }
}

、、、、、、、、、、、、、、、、、、、、、、、、、、、、、、、、、、、、、、、、、、、

public class PayWechatManager {

    private final String TAG = "PayWechatManager";

    private Context context;

    // APPID
    public String APP_ID;

    // 商户号
    private String MCH_ID;

    // API**,在商户平台设置
    private String API_KEY;

    private String orderOn;

    private String productfeeName;

    private String price;

    private String orderType;

    // 支付结果回调(通知后台服务器)
    private String callBackUrl;

    public PayWechatManager(Context context) {
        this.context = context;
    }

    /**
     * @param APP_ID
     * @param MCH_ID
     * @param API_KEY
     * @param orderOn
     * @param productfeeName
     * @param price
     * @param callBackUrl
     * @param orderType      //附加参数,不传为null。不能为""
     */
    public void toWeChatPay(String APP_ID, String MCH_ID, String API_KEY, String orderOn, String productfeeName, String price, String callBackUrl, String orderType) {
        this.APP_ID = APP_ID;
        this.MCH_ID = MCH_ID;
        this.API_KEY = API_KEY;
        this.orderOn = orderOn;
        this.productfeeName = productfeeName;
        this.price = price;
        this.callBackUrl = callBackUrl;
        this.orderType = orderType;// 附加数据
        GetPrepayIdTask getPrepayId = new GetPrepayIdTask();
        getPrepayId.execute();
    }

    /**
     * 异步任务,提交订单(发起支付)
     */
    class GetPrepayIdTask extends AsyncTask<Void, Void, Map<String, String>> {

        @Override
        protected void onPreExecute() {
            // ui.showLoadingDialog();
        }

        @Override
        protected Map<String, String> doInBackground(Void... params) {
            String url = String.format("https://api.mch.weixin.qq.com/pay/unifiedorder");

            // 创建微信订单信息
            String entity = createWeChatOrder();
            Log.i("lgq","微信得到==="+entity);

            // 生成微信订单
            byte[] buf = HttpWxUtile.httpPost(url, entity);
            // 这里容易出错误,错误信息请见:https://pay.weixin.qq.com/wiki/doc/api/app.php?chapter=9_3&index=5

            String content = new String(buf);
            Log.i("lgq","微信返回=----==="+content);
            Map<String, String> xml = decodeXml(content);
            return xml;
        }

        @Override
        protected void onPostExecute(Map<String, String> result) {
            /** 用于存储支付信息的StringBuffer(用于打印订单信息) */
            StringBuffer sbInfo = new StringBuffer();
            sbInfo.append("prepay_id\n" + result.get("prepay_id") + "\n\n");
            createPayReq(result, sbInfo);
        }

    }

    /**
     * 根据您的订单信息 生成 微信产品支付订单信息
     */
    private String createWeChatOrder() {
        StringBuffer xml = new StringBuffer();
        try {
            String nonceStr = genNonceStr();
            xml.append("</xml>");
            List<KeyValue> packageParams = new LinkedList<KeyValue>();
            packageParams.add(new KeyValue("appid", APP_ID));
            packageParams.add(new KeyValue("attach", orderType));
            packageParams.add(new KeyValue("body", "天鑫计费-网吧充值"));
            packageParams.add(new KeyValue("mch_id", MCH_ID));
            packageParams.add(new KeyValue("nonce_str", nonceStr));
            packageParams.add(new KeyValue("notify_url", callBackUrl));
            packageParams.add(new KeyValue("out_trade_no", orderOn));
            packageParams.add(new KeyValue("spbill_create_ip", "127.0.0.1"));
            packageParams.add(new KeyValue("total_fee", getTotalFee(price)));
            // packageParams.add(new KeyValue("total_fee", price));
            packageParams.add(new KeyValue("trade_type", "APP"));
            String sign = genPackageSign(packageParams);
            packageParams.add(new KeyValue("sign", sign));
            String xmlstring = toXml(packageParams);

            return xmlstring;

//            return new String(xmlstring.toString().getBytes(), "ISO8859-1");
            // return xmlstring;
        } catch (Exception e) {
            return null;
        }
    }

    /**
     * doingBackground
     */
    private Map<String, String> decodeXml(final String content) {
        try {
            Map<String, String> xml = new HashMap<String, String>();
            XmlPullParser parser = Xml.newPullParser();
            parser.setInput(new StringReader(content));
            int event = parser.getEventType();
            while (event != XmlPullParser.END_DOCUMENT) {
                String nodeName = parser.getName();
                switch (event) {
                    case XmlPullParser.START_DOCUMENT:

                        break;
                    case XmlPullParser.START_TAG:

                        if ("xml".equals(nodeName) == false) {
                            // 实例化student对象
                            xml.put(nodeName, parser.nextText());
                        }
                        break;
                    case XmlPullParser.END_TAG:
                        break;
                }
                event = parser.next();
            }

            return xml;
        } catch (Exception e) {

        }
        return null;

    }

    // 将totalfee从单位(元)装换成整数的(分)
    private String getTotalFee(String total_fee) {
        total_fee = Double.valueOf(total_fee) * 100 / 1 + "";
        total_fee = total_fee.substring(0, total_fee.indexOf("."));
        return total_fee;
    }

    private String toXml(List<KeyValue> params) {
        StringBuilder sb = new StringBuilder();
        sb.append("<xml>");
        for (int i = 0; i < params.size(); i++) {
            sb.append("<" + params.get(i).getName() + ">");
            sb.append(String.valueOf(params.get(i).getValue()));
            sb.append("</" + params.get(i).getName() + ">");
        }
        sb.append("</xml>");
        return sb.toString();
    }

    private String genNonceStr() {
        Random random = new Random();
        return MD5.getMessageDigest(String.valueOf(random.nextInt(10000)).getBytes());
    }

    private long genTimeStamp() {
        return System.currentTimeMillis() / 1000;
    }

    /**
     * 创建订单支付请求
     */
    private void createPayReq(final Map<String, String> orderInfo, StringBuffer sbInfo) {
        PayReq req = new PayReq();
        req.appId = APP_ID;
        req.partnerId = MCH_ID;
        req.prepayId = orderInfo.get("prepay_id");
        req.packageValue = "Sign=WXPay";
        req.nonceStr = genNonceStr();
        req.timeStamp = String.valueOf(genTimeStamp());
        List<KeyValue> signParams = new LinkedList<KeyValue>();
        signParams.add(new KeyValue("appid", req.appId));
        signParams.add(new KeyValue("noncestr", req.nonceStr));
        signParams.add(new KeyValue("package", req.packageValue));
        signParams.add(new KeyValue("partnerid", req.partnerId));
        signParams.add(new KeyValue("prepayid", req.prepayId));
        signParams.add(new KeyValue("timestamp", req.timeStamp));
        req.sign = genAppSign(sbInfo, signParams);
        sbInfo.append("sign\n" + req.sign + "\n\n");
        // 发起支付
        sendPayReq(req);
    }

    // 发起支付,当前页面结束
    private void sendPayReq(final PayReq req) {
        IWXAPI wxApi = WXAPIFactory.createWXAPI(context, null);
        wxApi.registerApp(req.appId);
        wxApi.sendReq(req);
    }

    /**
     * 生成签名
     */
    @SuppressLint("DefaultLocale")
    private String genPackageSign(List<KeyValue> params) {
        StringBuilder sb = new StringBuilder();
        for (int i = 0; i < params.size(); i++) {
            sb.append(params.get(i).getName());
            sb.append('=');
            sb.append(params.get(i).getValue());
            sb.append('&');
        }
        sb.append("key=");
        sb.append(API_KEY);
        String packageSign = MD5.getMessageDigest(sb.toString().getBytes()).toUpperCase();
        return packageSign;
    }

    @SuppressLint("DefaultLocale")
    private String genAppSign(StringBuffer sbInfo, List<KeyValue> params) {
        StringBuilder sb = new StringBuilder();
        for (int i = 0; i < params.size(); i++) {
            sb.append(params.get(i).getName());
            sb.append('=');
            sb.append(params.get(i).getValue());
            sb.append('&');
        }
        sb.append("key=");
        sb.append(API_KEY);
        sbInfo.append("sign str\n" + sb.toString() + "\n\n");
        String appSign = MD5.getMessageDigest(sb.toString().getBytes()).toUpperCase();
        return appSign;
    }

    class KeyValue {

        private String name;
        private String value;

        public KeyValue(String name, String value) {
            this.name = name;
            this.value = value;
        }

        public String getName() {
            return name;
        }

        public void setName(String name) {
            this.name = name;
        }

        public String getValue() {
            return value;
        }

        public void setValue(String value) {
            this.value = value;
        }
    }

}

5、配置微信activity

<activity
    android:name=".wxapi.WXEntryActivity"
    android:configChanges="keyboardHidden|orientation|screenSize"
    android:exported="true"
    android:screenOrientation="portrait"
    android:theme="@android:style/Theme.Translucent.NoTitleBar" />

<activity
    android:name=".wxapi.WXPayEntryActivity"
    android:exported="true"
    android:launchMode="singleTop" />

6、起调微信支付:

demo链接:https://pan.baidu.com/s/1HUL4O-FkNKFUTRN2l8_Nbg

//微信支付
private void wechat() {
    new PayWechatManager(LiteActivity.this).toWeChatPay(Constants.APP_ID, Constants.MCH_ID,
            Constants.APP_KEY, getTime(), "天鑫计费-网吧充值", "0.01",
            "http://yohoweb.91yohoo.com", null);
}