欢迎您访问程序员文章站本站旨在为大家提供分享程序员计算机编程知识!
您现在的位置是: 首页  >  移动技术

Android编程实现的微信支付功能详解【附Demo源码下载】

程序员文章站 2022-03-24 18:21:34
本文实例讲述了android编程实现的微信支付功能。分享给大家供大家参考,具体如下: 最近公司弄ionic框架,项目中需要微信支付,无奈,把我调过去弄,期间也是几近崩溃,...

本文实例讲述了android编程实现的微信支付功能。分享给大家供大家参考,具体如下:

最近公司弄ionic框架,项目中需要微信支付,无奈,把我调过去弄,期间也是几近崩溃,好在皇天不负有心人,在看别人的文档,终于是在项目中集成了微信支付,下面作为一个小白的我,想要把我的经验分享给大家,希望对大家有所帮助。

先给一个可用的demo吧(运行前先看txt文件)

demo代码点击此处本站下载

这个demo是基于eclipse开发的,博主也在android studio开发过微信支付,原理都是一样的,大家把这个demo弄懂了,在as上面也是一样的。

(温馨提示:大家下载下来可能会出错,也有可能不会。下面给出出错的解决方法:1.进入项目中的weixinpay->build path->configure build path,移除那个报错的jar包。 2.会出现资源找不到的情况,这是因为你没有v7包,下载一个v7包,或者把出错的地方都删除,只是一个主题,删除了看起来不好看而已,当然,你也可以用你有的主题。 还有一个问题需要提出来,就是你可能按照里面的text操作的仍然调不起客户端,有可能是你没有安装微信客户端,因为我没有做判断。这个demo不会出现只能成功支付一次的情况,博主亲测有效。出现只能支付一次只能说明你的签名没有对应)

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

//appid 微信分配的公众账号id
public static final string app_id = "";
//商户号 微信分配的公众账号id
public 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包,导入。

微信支付分为三个步骤

① .生成prepayid

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

② .生成签名参数

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

接下来就是有个支付结果的页面代码。是微信官方提供的一个类。你要在manifest注册这个类。这里需要注意的是,这个类必须放在wxapi包下,你自己新建一个包即可。

为了大家可以直接运行这个demo,我的微信加签都是在本地执行的,获取prepayid和加签都应该在服务端完成,还有最终的支付返回结果也是以服务端的为准。

*下面给出运行结果图*

Android编程实现的微信支付功能详解【附Demo源码下载】

Android编程实现的微信支付功能详解【附Demo源码下载】

大家下载demo然后把参数换了,弄下keystore,包名,签名。应该就可以用了。

更多关于android相关内容感兴趣的读者可查看本站专题:《android开发入门与进阶教程》、《android数据库操作技巧总结》、《android编程之activity操作技巧总结》、《android文件操作技巧汇总》、《android编程开发之sd卡操作方法汇总》、《android资源操作技巧汇总》、《android视图view技巧总结》及《android控件用法总结

希望本文所述对大家android程序设计有所帮助。