Android支付实践(二)之微信支付详解与Demo

前言:集成支持宝和微信支付,是公司获取收益的最主要的部分,这两大巨头几乎在支付业务上不可或缺,今天看下Simon_Crystin独家授权本公众号发步的Android支付实践(二)之微信支付详解与Demo,Simon_Crystin的blog地址为:http://blog.csdn.net/Simon_Crystin/。点击【阅读原文】,可下载案例的demo

最近公司弄Ionic框架,项目中需要微信支付,无奈,把我调过去弄,期间也是几近崩溃,好在皇天不负有心人,在看别人的文档,终于是在项目中集成了微信支付,下面作为一个小白的我,想要把我的经验分享给大家,希望对大家有所帮助。 (温馨提示:大家下载下来可能会出错,也有可能不会。下面给出出错的解决方法:1.进入项目中的WeIXinPay->Build Path->configure build path,移除那个报错的jar包。 2.会出现资源找不到的情况,这是因为你没有v7包,下载一个v7包,或者把出错的地方都删除,只是一个主题,删除了看起来不好看而已,当然,你也可以用你有的主题。 还有一个问题需要提出来,就是你可能按照里面的text操作的仍然调不起客户端,有可能是你没有安装微信客户端,因为我没有做判断。这个demo不会出现只能成功支付一次的情况,博主亲测有效。出现只能支付一次只能说明你的签名没有对应)

先看下效果图:

1.去微信开放平台申请微信支付服务,绑定自己的应用这里具体不多讲,但是一定要申请完成,将会得到是三个参数

//appid 微信分配的公众账号IDpublic static final String APP_ID = "";//商户号 微信分配的公众账号IDpublic static final String MCH_ID = "";//API密钥,在商户平台设置public static final  String API_KEY= "";
  • 坑点提示:在微信开发平台设置包名和签名。这里的包名一定要和你自己的包名一样,就是manifest中的package,签名一定要和你用官方app生成的一样(https://open.weixin.qq.com/zh_CN/htmledition/res/dev/download/sdk/Gen_Signature_Android.apk)。 微信会根据你的填写的包名,然后对你的keystore进行一种算法,生成你的签名。包名和签名一定要和微信开放平台的相同。不过这里需要注意的是,如果你发布的正式版本,需要用官方app重新生成签名,然后在开放平台重新设置sign,因为测试版本的keystore与正式版的keystore不一样。总之,就是你用的keystore生成的sign要和微信开放平台的时刻保持一致。

2.准备工作做好了,接下来就是开发了,先下载微信的jar包,导入。 微信支付分为三个步骤 1.生成prepayId

@Overrideprotected Map<String, String> doInBackground(String... params) {     String url=String.format(params[0]);     String entity=getProductArgs();     Log.e("Simon",">>>>"+entity);     byte[] buf=Util.httpPost(url, entity);     String content = new String(buf);     Log.e("orion", "----"+content);     Map<String,String> xml=decodeXml(content);     return xml;}

2.生成签名参数

private void genPayReq() {        req.appId = Constants.APP_ID;        req.partnerId = Constants.MCH_ID;        if (resultunifiedorder!=null) {            req.prepayId = resultunifiedorder.get("prepay_id");            req.packageValue = "prepay_id="+resultunifiedorder.get("prepay_id");        }        else {            Toast.makeText(MainActivity.this, "prepayid为空", Toast.LENGTH_SHORT).show();        }        req.nonceStr = getNonceStr();        req.timeStamp = String.valueOf(genTimeStamp());        List<NameValuePair> signParams = new LinkedList<NameValuePair>();        signParams.add(new BasicNameValuePair("appid", req.appId));        signParams.add(new BasicNameValuePair("noncestr", req.nonceStr));        signParams.add(new BasicNameValuePair("package", req.packageValue));        signParams.add(new BasicNameValuePair("partnerid", req.partnerId));        signParams.add(new BasicNameValuePair("prepayid", req.prepayId));        signParams.add(new BasicNameValuePair("timestamp", req.timeStamp));        req.sign = genAppSign(signParams);        sb.append("sign\n"+req.sign+"\n\n");        textView.setText(sb.toString());        Log.e("Simon", "----"+signParams.toString());    }

3.调起支付

/* * 调起微信支付 */private void sendPayReq() {    msgApi.registerApp(Constants.APP_ID);    msgApi.sendReq(req);    Log.i(">>>>>", req.partnerId);}

完整代码

package com.alpha.live;import java.io.StringReader;import java.util.HashMap;import java.util.LinkedList;import java.util.List;import java.util.Map;import java.util.Random;import org.apache.http.NameValuePair;import org.apache.http.message.BasicNameValuePair;import org.xmlpull.v1.XmlPullParser;import com.tencent.mm.sdk.modelpay.PayReq;import com.tencent.mm.sdk.openapi.IWXAPI;import com.tencent.mm.sdk.openapi.WXAPIFactory;import android.app.Activity;import android.app.AlertDialog;import android.app.ProgressDialog;import android.os.AsyncTask;import android.os.Bundle;import android.util.Log;import android.util.Xml;import android.view.View;import android.view.View.OnClickListener;import android.widget.Button;import android.widget.TextView;import android.widget.Toast;/** * Created by Simon on 2016/12/2. */public class MainActivity extends Activity implements OnClickListener {    private Button submitButton;    private Button confirmButton;    private TextView textView;    private StringBuffer sb;    private Map<String,String> resultunifiedorder;    private PayReq req;    private final IWXAPI msgApi = WXAPIFactory.createWXAPI(this, null);    @Override    protected void onCreate(Bundle savedInstanceState) {        super.onCreate(savedInstanceState);        setContentView(R.layout.activity_main);        submitButton=(Button) findViewById(R.id.bt_submit_order);        confirmButton=(Button) findViewById(R.id.bt_corfirm);        textView=(TextView) findViewById(R.id.tv_prepay_id);        submitButton.setOnClickListener(this);        confirmButton.setOnClickListener(this);        sb=new StringBuffer();        req=new PayReq();    }    @Override    public void onClick(View v) {        // TODO Auto-generated method stub        switch (v.getId()) {        case R.id.bt_submit_order:            String urlString="https://api.mch.weixin.qq.com/pay/unifiedorder";             PrePayIdAsyncTask prePayIdAsyncTask=new PrePayIdAsyncTask();             prePayIdAsyncTask.execute(urlString);      //生成prepayId        break;        case R.id.bt_corfirm:            genPayReq();//生成签名参数            sendPayReq();//调起支付        break;        default:            break;        }    }    /*     * 调起微信支付     */    private void sendPayReq() {        msgApi.registerApp(Constants.APP_ID);        msgApi.sendReq(req);        Log.i(">>>>>", req.partnerId);    }    private long genTimeStamp() {        return System.currentTimeMillis() / 1000;    }    private void genPayReq() {        req.appId = Constants.APP_ID;        req.partnerId = Constants.MCH_ID;        if (resultunifiedorder!=null) {            req.prepayId = resultunifiedorder.get("prepay_id");            req.packageValue = "prepay_id="+resultunifiedorder.get("prepay_id");        }        else {            Toast.makeText(MainActivity.this, "prepayid为空", Toast.LENGTH_SHORT).show();        }        req.nonceStr = getNonceStr();        req.timeStamp = String.valueOf(genTimeStamp());        List<NameValuePair> signParams = new LinkedList<NameValuePair>();        signParams.add(new BasicNameValuePair("appid", req.appId));        signParams.add(new BasicNameValuePair("noncestr", req.nonceStr));        signParams.add(new BasicNameValuePair("package", req.packageValue));        signParams.add(new BasicNameValuePair("partnerid", req.partnerId));        signParams.add(new BasicNameValuePair("prepayid", req.prepayId));        signParams.add(new BasicNameValuePair("timestamp", req.timeStamp));        req.sign = genAppSign(signParams);        sb.append("sign\n"+req.sign+"\n\n");        textView.setText(sb.toString());        Log.e("Simon", "----"+signParams.toString());    }    private String genAppSign(List<NameValuePair> 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(Constants.API_KEY);        this.sb.append("sign str\n"+sb.toString()+"\n\n");        String appSign = MD5.getMessageDigest(sb.toString().getBytes());        Log.e("Simon","----"+appSign);        return appSign;    }    private class PrePayIdAsyncTask extends AsyncTask<String,Void, Map<String, String>>    {        private ProgressDialog dialog;        @Override        protected void onPreExecute() {            // TODO Auto-generated method stub            super.onPreExecute();            dialog = ProgressDialog.show(MainActivity.this, "提示", "正在提交订单");        }        @Override        protected Map<String, String> doInBackground(String... params) {            // TODO Auto-generated method stub            String url=String.format(params[0]);            String entity=getProductArgs();            Log.e("Simon",">>>>"+entity);            byte[] buf=Util.httpPost(url, entity);            String content = new String(buf);            Log.e("orion", "----"+content);            Map<String,String> xml=decodeXml(content);            return xml;        }        @Override        protected void onPostExecute(Map<String, String> result) {            // TODO Auto-generated method stub            super.onPostExecute(result);            if (dialog != null) {                dialog.dismiss();            }            sb.append("prepay_id\n"+result.get("prepay_id")+"\n\n");            textView.setText(sb.toString());            resultunifiedorder=result;        }    }    public Map<String,String> decodeXml(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) {            Log.e("Simon","----"+e.toString());        }        return null;    }    private String getProductArgs() {        // TODO Auto-generated method stub        StringBuffer xml=new StringBuffer();        try {            String nonceStr=getNonceStr();            xml.append("<xml>");            List<NameValuePair> packageParams=new LinkedList<NameValuePair>();            packageParams.add(new BasicNameValuePair("appid",Constants.APP_ID));            packageParams.add(new BasicNameValuePair("body", "APP pay test"));            packageParams.add(new BasicNameValuePair("mch_id", Constants.MCH_ID));            packageParams.add(new BasicNameValuePair("nonce_str", nonceStr));            packageParams.add(new BasicNameValuePair("notify_url", "https://www.baidu.com"));//写你们的回调地址            packageParams.add(new BasicNameValuePair("out_trade_no",genOutTradNo()));            packageParams.add(new BasicNameValuePair("total_fee", "1"));            packageParams.add(new BasicNameValuePair("trade_type", "APP"));            String sign=getPackageSign(packageParams);            packageParams.add(new BasicNameValuePair("sign", sign));            String xmlString=toXml(packageParams);            return xmlString;        } catch (Exception e) {            // TODO: handle exception            return null;        }    }    //生成订单号,测试用,在客户端生成    private String genOutTradNo() {        Random random = new Random();//      return "dasgfsdg1234"; //订单号写死的话只能支付一次,第二次不能生成订单        return MD5.getMessageDigest(String.valueOf(random.nextInt(10000)).getBytes());    }    //生成随机号,防重发    private String getNonceStr() {        // TODO Auto-generated method stub        Random random=new Random();        return MD5.getMessageDigest(String.valueOf(random.nextInt(10000)).getBytes());    }    /**     生成签名     */    private String getPackageSign(List<NameValuePair> 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(Constants.API_KEY);        String packageSign = MD5.getMessageDigest(sb.toString().getBytes()).toUpperCase();        Log.e("Simon",">>>>"+packageSign);        return packageSign;    }    /*     * 转换成xml     */    private String toXml(List<NameValuePair> params) {        StringBuilder sb = new StringBuilder();        sb.append("<xml>");        for (int i = 0; i < params.size(); i++) {            sb.append("<"+params.get(i).getName()+">");            sb.append(params.get(i).getValue());            sb.append("</"+params.get(i).getName()+">");        }        sb.append("</xml>");        Log.e("Simon",">>>>"+sb.toString());        return sb.toString();    }}

原文发布于微信公众号 - 何俊林(DriodDeveloper)

原文发表时间:2016-12-22

本文参与腾讯云自媒体分享计划,欢迎正在阅读的你也加入,一起分享。

发表于

我来说两句

0 条评论
登录 后参与评论

相关文章

来自专栏everhad

ViewPager无限滑动

前言 View轮播效果在app中很常见,一想到左右滑动的效果就很容易想到使用ViewPager来实现。对于像我们常说的banner这样的效果,具备无限滑动的功能...

3987
来自专栏向治洪

listview优化(中)

1,对Imageview使用setTag()方法来解决图片错位问题,这个Tag中设置的是图片的url,然后在加载的时候取得这个url和要加载那position...

22310
来自专栏码匠的流水账

聊聊spring cloud gateway的SetStatusGatewayFilter

本文主要研究下spring cloud gateway的SetStatusGatewayFilter

1331
来自专栏木头编程 - moTzxx

androidannotions开发框架在Eclipse中的配置

版权声明:本文为博主原创文章,未经博主允许不得转载。 https://blog.csdn.net/u011415782/article/de...

1652
来自专栏何俊林

Android Multimedia框架总结(二十三)MediaCodec补充及MediaMuxer引入(附案例)

前言:前面几章都是分析MediaCodec相关源码,有收到提问,说MediaCodec到底是硬解码还是软解码?看下今天的Agenda: MediaCodec到...

34510
来自专栏码匠的流水账

聊聊spring cloud gateway的RedirectToGatewayFilter

本文主要研究下spring cloud gateway的RedirectToGatewayFilter

1681
来自专栏Flutter入门到实战

一次使用Kotlin实现酷炫多选操作的尝试

“手机上的多选很难操作”,我们的设计师Vitaly Rubtsov如是说。大多数应用中的多选方案 -Telegram, Apple Music, Spotif...

922
来自专栏俞其荣的博客

Android Architecture Component之Lifecycle解析HeaderLifecyclePart 1Part 2Part 3Footer

终于到了最后的关头,Android Architecture Component 系列的最后一节内容。今天给大家带来的就是 Lifecycle 的解析。

1704
来自专栏james大数据架构

在Android中调用WebService

某些情况下我们可能需要与Mysql或者Oracle数据库进行数据交互,有些朋友的第一反应就是直接在Android中加载驱动然后进行数据的增删改查。我个人不推荐这...

2705
来自专栏Android干货

关于Activity销毁,而绘制UI的子线程未销毁出现的问题

3736

扫码关注云+社区

领取腾讯云代金券