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

Android—基于微信开放平台v3SDK开发(微信支付填坑)

程序员文章站 2024-02-28 21:18:04
接触微信支付之前听说过这是一个坑,,,心里已经有了准备。。。我以为我没准跳坑出不来了,没有想到我填上了,调用成功之后我感觉公司所有的同事都是漂亮的,隔着北京的大雾霾我仿佛看...

接触微信支付之前听说过这是一个坑,,,心里已经有了准备。。。我以为我没准跳坑出不来了,没有想到我填上了,调用成功之后我感觉公司所有的同事都是漂亮的,隔着北京的大雾霾我仿佛看见了太阳~~~好了,装逼结束。。。进入正题

开发准备:

1.在微信开放平台申请账号

2.成功后创建应用,就是填一些看似很官方很正经的资料了。。。(说审核7天左右,没有意外的情况下你的app第二天就审核成功了是不是很开心,有了appid,是不是就可以调用微   信支付了????-------想多了,真的)

3.微信支付是需要额外申请的:需要资料审核,账户验证,协议签署等步骤,(我记得,,资料审核要填写的东西好多,,,好多,,,账户验证就是你审核成功后微信会发送邮件到你   注册时登记的邮箱账号,其中含有随机金额用于账户验证,协议签署,略,太简单)一定要好好阅读你邮件的任何信息,因为有的细节错了,,,你可能填坑很久。。。。。。

正式开发阶段:

问题1:

调用官方的sdk发现只能成功的调起一次微信,再次支付的时候怎么也调用不起来了

解决:

似乎不是什么正经方法:在手机设置中管理应用程序,清除微信数据,缓存,,再来一遍,绝对可以调起来(当然还是只是一次。。。。)

继续:

我认为要用微信支付嘛,,就只看了调用支付接口的文档:Android—基于微信开放平台v3SDK开发(微信支付填坑)
后来发现需要的参数prepayid是怎么也找不到啊,,后来才发现这个prepayid是先调用”统一下单“这个接口时候温馨反过来的东西,但是官方的sdk中并没有统一下单的代码。坑吗???

所以要先看统一下单文档了

1.使用自己的app调用的时候把官网down下来的sdk中wxpayentryactivity拷贝到自己的项目,所在包的名字最后一定是.wxapi(我连包一起拷了。。。。)

2.在项目清单文件中填写:Android—基于微信开放平台v3SDK开发(微信支付填坑)

3.sdk中的appregister拷贝下来,,,里面换成你自己的appid,然后在项目清单中也注册一下。Android—基于微信开放平台v3SDK开发(微信支付填坑)
4.重点来了,,就是你app要调微信支付的activity,我这还叫payactivity

要调起微信支付页面,要在这个activity中,将你的app注册到微信Android—基于微信开放平台v3SDK开发(微信支付填坑)
 接下来先调用统一下单获取prepayid,参数,微信人家要xml格式的!我们就得发送xml格式的!Android—基于微信开放平台v3SDK开发(微信支付填坑)
好了调用的时候把这个方法的返回值当参数传,,等待微信返回success吧!。。

 我遇见的错误:签名错误

我的原因是大意了 configutil.notify_url这个参数写的空字符串

还有是因为debug版运行的,没有打包运行

返回成功之后,可以调用支付接口了Android—基于微信开放平台v3SDK开发(微信支付填坑)

不要忘了这一步去跳转界面,,,,,
Android—基于微信开放平台v3SDK开发(微信支付填坑)
没有跳转到微信支付可能是你由运行的debug版本,,,,没有打包。。。。。

下面是我的payactivity完整代码:

package com.example.taijiapp.ui;
 
import java.io.stringreader;
import java.net.inetaddress;
import java.net.networkinterface;
import java.net.socketexception;
import java.util.enumeration;
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.example.taijiapp.r;
import com.example.taijiapp.util.constants;
import com.example.taijiapp.util.md5;
import com.example.taijiapp.util.t;
import com.example.taijiapp.util.util;
import com.example.taijiapp.utils.configutil;
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.progressdialog;
import android.content.context;
import android.net.wifi.wifiinfo;
import android.net.wifi.wifimanager;
import android.os.asynctask;
import android.os.bundle;
import android.util.log;
import android.util.xml;
import android.view.view;
import android.widget.button;
 
public class payactivity extends activity {
  payreq req;
  private iwxapi msgapi;
  map<string, string=""> resultunifiedorder;
  stringbuffer sb;
  @override
  protected void oncreate(bundle savedinstancestate) {
    super.oncreate(savedinstancestate);
    setcontentview(r.layout.pay);
    req = new payreq();
    sb = new stringbuffer();
    msgapi = wxapifactory.createwxapi(this, constants.app_id);
    /**
     * 将app注册到微信
     */
    boolean registerapp = msgapi.registerapp(constants.app_id);
    t.show(this, "注册========"+registerapp+"");
    button appaybtn = (button) findviewbyid(r.id.appay_btn);
    button check_pay_btn = (button) findviewbyid(r.id.check_pay_btn);
    appaybtn.setonclicklistener(new view.onclicklistener() {
 
      @override
      public void onclick(view v) {
        getprepayidtask getprepayid = new getprepayidtask();
        getprepayid.execute();
      }
    });
    /**
     * 将该app注册到微信
     */
    check_pay_btn.setonclicklistener(new view.onclicklistener() {
 
      @override
      public void onclick(view v) {
        genpayreq();
        sendpayreq();
         
      }
    });
//   // 生成签名参数
//   button appay_pre_btn = (button) findviewbyid(r.id.appay_pre_btn);
//   appay_pre_btn.setonclicklistener(new view.onclicklistener() {
//
//     @override
//     public void onclick(view v) {
//       genpayreq();
//     }
//   });
  }
  /**
   * 生成签名
   */
 
  private string genpackagesign(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.key);
    log.e("拼接=====", sb.tostring());
    string packagesign = md5.getmessagedigest(sb.tostring().getbytes()).touppercase();
    log.e("orion生成签名===", packagesign);
    return packagesign;
  }
 
  /**
   * 签名工具 不含商户密钥 -暂时不用 = * 编码格式 utf-8 = * @return
   */
  public static string createsignnokey(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('&');
    }
    string signstr = sb.tostring();
    string substr = signstr.substring(0, signstr.length() - 1);
    // 注意sign转为大写
    return md5.getmessagedigest(substr.getbytes()).touppercase();
  }
 
  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.key);
 
    this.sb.append("sign str\n" + sb.tostring() + "\n\n");
    string appsign = md5.getmessagedigest(sb.tostring().getbytes());
    log.e("orion", appsign);
    return appsign;
  }
 
  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("orion", sb.tostring());
    return sb.tostring();
  }
 
  private class getprepayidtask extends asynctask<void, void,="" map<string,="" string="">> {
 
    private progressdialog dialog;
 
    @override
    protected void onpreexecute() {
      dialog = progressdialog.show(payactivity.this, getstring(r.string.app_tip),
          getstring(r.string.getting_prepayid));
    }
 
    @override
    protected void onpostexecute(map<string, string=""> result) {
      if (dialog != null) {
        dialog.dismiss();
      }
      sb.append("prepay_id\n" + result.get("prepay_id") + "\n\n");
 
      resultunifiedorder = result;
 
    }
 
    @override
    protected void oncancelled() {
      super.oncancelled();
    }
 
    @override
    protected map<string, string=""> doinbackground(void... params) {
 
      string url = string.format("https://api.mch.weixin.qq.com/pay/unifiedorder");
      string entity = genproductargs();
      log.e("orion===发送过去", entity);
      byte[] buf = util.httppost(url, entity);
 
      string content = new string(buf);
      log.e("orion", content);
      map<string, string=""> xml = decodexml(content);
 
      return xml;
    }
  }
 
  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("orion", e.tostring());
    }
    return null;
 
  }
  /**
   * 生成随机数
   * @return
   */
  private string gennoncestr() {
    random random = new random();
    return md5.getmessagedigest(string.valueof(random.nextint(10000)).getbytes());
  }
  /**
   * 时间戳
   * @return
   */
  private long gentimestamp() {
    return system.currenttimemillis() / 1000;
  }
  /**
   * 随机数
   * @return
   */
  private string genouttradno() {
    random random = new random();
    return md5.getmessagedigest(string.valueof(random.nextint(10000)).getbytes());
  }
  /**
   * 获取设备的ip地址
   * @return
   */
  public string getlocalipaddress() {
    try {
      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()) {
            return inetaddress.gethostaddress().tostring();
          }
        }
      }
    } catch (socketexception ex) {
    }
    return null;
  }
 
  private string getwifiip() {
    // 获取wifi服务
    wifimanager wifimanager = (wifimanager) getsystemservice(context.wifi_service);
    // 判断wifi是否开启
    if (!wifimanager.iswifienabled()) {
      wifimanager.setwifienabled(true);
    }
    wifiinfo wifiinfo = wifimanager.getconnectioninfo();
    int ipaddress = wifiinfo.getipaddress();
    string ip = inttoip(ipaddress);
    return ip;
  }
  /**
   * 转化成ip地址的格式
   * @param i
   * @return
   */
  private string inttoip(int i) {
 
    return (i & 0xff) + "." + ((i >> 8) & 0xff) + "." + ((i >> 16) & 0xff) + "." + (i >> 24 & 0xff);
  }
 
  private string genproductargs() {
    stringbuffer xml = new stringbuffer();
    string ip = getwifiip();
    if (ip == "" && ip == "") {
      ip = getlocalipaddress();
    }
    try {
      string noncestr = gennoncestr();
      xml.append("");
      list<namevaluepair> packageparams = new linkedlist<namevaluepair>();
      packageparams.add(new basicnamevaluepair("appid", constants.app_id));
      packageparams.add(new basicnamevaluepair("body", "apptest"));
      packageparams.add(new basicnamevaluepair("mch_id", constants.mch_id));
      packageparams.add(new basicnamevaluepair("nonce_str", noncestr));
      packageparams.add(new basicnamevaluepair("notify_url", configutil.notify_url));
      packageparams.add(new basicnamevaluepair("out_trade_no", genouttradno()));
      packageparams.add(new basicnamevaluepair("spbill_create_ip", ip));
      packageparams.add(new basicnamevaluepair("total_fee", "100"));
      packageparams.add(new basicnamevaluepair("trade_type", "app"));
      string sign = genpackagesign(packageparams);
      packageparams.add(new basicnamevaluepair("sign", sign));
      string xmlstring = toxml(packageparams);
      return xmlstring;
    } catch (exception e) {
      log.e("tag", "fail, ex = " + e.getmessage());
      return null;
    }
  }
 
  private void genpayreq() {
    req.appid = constants.app_id;
    req.partnerid = constants.mch_id;
    req.prepayid = resultunifiedorder.get("prepay_id");
    req.packagevalue = "prepay_id=" + resultunifiedorder.get("prepay_id");
    req.noncestr = gennoncestr();
    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");
    log.e("orion==genpayreq===============", signparams.tostring());
 
  }
 
  private void sendpayreq() {
    boolean sendreq = msgapi.sendreq(req);
    t.show(this, "微信跳转====="+sendreq+"");
  }
 
}
</namevaluepair></namevaluepair></namevaluepair></namevaluepair></inetaddress></networkinterface></string,></string,></string,></string,></string,></string,></void,></namevaluepair></namevaluepair></namevaluepair></namevaluepair></string,>

里面没有的类,,,,呐:。自己下载一下拷贝一下。。。

参考文章:

以上就是本文的全部内容,希望对大家的学习有所帮助,也希望大家多多支持。