Android接入微信支付的方法
程序员文章站
2023-12-19 14:31:04
1、先在微信开放平台申请开发应用,微信开放平台会生成app的唯一标识appid。由于需要保证支付安全,需要在开放平台绑定商户应用包名和应用签名,设置好后才能正常发起支付。...
1、先在微信开放平台申请开发应用,微信开放平台会生成app的唯一标识appid。由于需要保证支付安全,需要在开放平台绑定商户应用包名和应用签名,设置好后才能正常发起支付。
2、注册appid (这个可以放在项目的application里)
商户app工程中引入微信jar包,调用api前,需要先向微信注册您的appid,代码如下:
final iwxapi msgapi = wxapifactory.createwxapi(context, null); // 将该app注册到微信 msgapi.registerapp("wxd930ea5d5a258f4f");
3、调用统一下单api生成预付单,获取到prepay_id后将参数再次签名传输给app发起支付。
例:
下面代码中的订单号是需要后台生成的
string url = "https://api.mch.weixin.qq.com/pay/unifiedorder"; wxprepost post = new wxprepost(); post.appid = "你的appid"; post.mch_id = "你的商户号"; post.nonce_str = stringutils.gennoncestr();//随机字符串 **1 post.body = "商品名称"; post.detail = "商品的描述"; post.out_trade_no = out_trade_no; //商户订单号 **2 post.total_fee = "商品价格";//单位是分 post.spbill_create_ip = getlocalipaddress();//ip地址 **3 post.notify_url = "";//这里是后台接受支付结果通知的url地址 post.trade_type = "app"; post.sign = genpackagesign(post);//签名 **4 list<namevaluepair> firstsignparams = getfirstsignparams(post); string xml = toxml(firstsignparams); string entity = null; try { entity = new string(xml.getbytes(), "iso8859-1"); byte[] buf = util.httppost(url, entity); if (buf != null) { string content = new string(buf); map<string, string> map = decodexml(content); if (map != null) { //再次签名(参与签名的字段有 :appid partnerid prepayid noncestr timestamp package) string appid = ""; string prepayid = ""; string noncestr = ""; for (map.entry<string, string> entry : map.entryset()) { if ("appid".equals(entry.getkey())) { appid = entry.getvalue(); } else if ("prepay_id".equals(entry.getkey())) { prepayid = entry.getvalue(); } else if ("nonce_str".equals(entry.getkey())) { noncestr = entry.getvalue(); } } log.d(tag, "run: :" + appid + "/" + prepayid + "/" + noncestr + "/"); string timestamp = string.valueof(gentimestamp()); //ok 获取二次签名 string secondpackagesign = gensecondpackagesign(getsecondsignparams(appid, prepayid, noncestr, timestamp)); payreq req = new payreq(); req.appid = appid; req.partnerid = "商户号"; req.prepayid = prepayid; req.noncestr = noncestr; req.timestamp = timestamp; req.packagevalue = "sign=wxpay"; req.sign = secondpackagesign; req.extdata = "app data"; // optional // system.out.println("genpackagesign3:"+post.getsign()+"/"+secondpackagesign); // 在支付之前,如果应用没有注册到微信,应该先调用iwxmsg.registerapp将应用注册到微信 mapi.sendreq(req); log.d(tag, "run: " + appid + "/" + prepayid + "/" + noncestr + "/" + timestamp + "/" + secondpackagesign); } } } catch (exception e) { }
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; } }
//获取随机字符串的方法 public static string gennoncestr() { random random = new random(); return md5.getmessagedigest(string.valueof(random.nextint(10000)).getbytes()); }
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>"); return sb.tostring(); }
public map<string, string> decodexml(string content) { try { map<string, string> xml = new hashmap<>(); 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)) { xml.put(nodename, parser.nexttext()); } break; case xmlpullparser.end_tag: break; } event = parser.next(); } return xml; } catch (exception e) { } return null; }
@nonnull private list<namevaluepair> getfirstsignparams(wxprepost params) { list<namevaluepair> packageparams = new linkedlist<>(); packageparams.add(new basicnamevaluepair("appid", "appid")); packageparams.add(new basicnamevaluepair("body", params.body)); packageparams.add(new basicnamevaluepair("detail", params.detail)); packageparams.add(new basicnamevaluepair("mch_id", "商户号")); packageparams.add(new basicnamevaluepair("nonce_str", params.nonce_str)); packageparams.add(new basicnamevaluepair("notify_url", params.notify_url)); packageparams.add(new basicnamevaluepair("out_trade_no", params.out_trade_no)); packageparams.add(new basicnamevaluepair("spbill_create_ip", params.spbill_create_ip)); packageparams.add(new basicnamevaluepair("total_fee", params.total_fee + "")); packageparams.add(new basicnamevaluepair("trade_type", params.trade_type)); packageparams.add(new basicnamevaluepair("sign", params.sign)); return packageparams; }
public class wxprepost { //必须带的参数 public string appid; //微信开放平台审核通过的应用appid public string mch_id; //微信支付分配的商户号 public string nonce_str; //随机字符串,不长于32位。推荐随机数生成算法 public string sign; //签名,详见签名生成算法 public string body; // 商品描述交易字段格式根据不同的应用场景按照以下格式:app——需传入应用市场上的app名字-实际商品名称,天天爱消除-游戏充值。 public string out_trade_no; // 商户系统内部的订单号,32个字符内、可包含字母, 其他说明见商户订单号 public int total_fee; // 订单总金额,单位为分,详见支付金额 public string spbill_create_ip; // 用户端实际ip public string notify_url; // 接收微信支付异步通知回调地址,通知url必须为直接可访问的url,不能携带参数。(后台提供的) public string trade_type; // 支付类型 // 非必须携带的参数 public string device_info; // 终端设备号(门店号或收银设备id),默认请传"web" public string detail; // 商品名称明细列表 public string attach; // 附加数据,在查询api和支付通知中原样返回,该字段主要用于商户携带订单的自定义数据 public string fee_type; // 符合iso 4217标准的三位字母代码,默认人民币:cny,其他值列表详见货币类型 // public string time_start; // 订单生成时间,格式为yyyymmddhhmmss,如2009年12月25日9点10分10秒表示为20091225091010。其他详见时间规则 // public string time_expire; // 订单失效时间,格式为yyyymmddhhmmss,如2009年12月27日9点10分10秒表示为20091227091010。其他详见时间规则 注意:最短失效时间间隔必须大于5分钟 public string goods_tag; // 商品标记,代金券或立减优惠功能的参数,说明详见代金券或立减优惠 // public string limit_pay; //no_credit--指定不能使用信用卡支付 public string getappid() { return appid; } public void setappid(string appid) { this.appid = appid; } public string getmch_id() { return mch_id; } public void setmch_id(string mch_id) { this.mch_id = mch_id; } public string getnonce_str() { return nonce_str; } public void setnonce_str(string nonce_str) { this.nonce_str = nonce_str; } public string getsign() { return sign; } public void setsign(string sign) { this.sign = sign; } public string getbody() { return body; } public void setbody(string body) { this.body = body; } public string getout_trade_no() { return out_trade_no; } public void setout_trade_no(string out_trade_no) { this.out_trade_no = out_trade_no; } public int gettotal_fee() { return total_fee; } public void settotal_fee(int total_fee) { this.total_fee = total_fee; } public string getspbill_create_ip() { return spbill_create_ip; } public void setspbill_create_ip(string spbill_create_ip) { this.spbill_create_ip = spbill_create_ip; } public string getnotify_url() { return notify_url; } public void setnotify_url(string notify_url) { this.notify_url = notify_url; } public string gettrade_type() { return trade_type; } public void settrade_type(string trade_type) { this.trade_type = trade_type; } public string getdevice_info() { return device_info; } public void setdevice_info(string device_info) { this.device_info = device_info; } public string getdetail() { return detail; } public void setdetail(string detail) { this.detail = detail; } public string getattach() { return attach; } public void setattach(string attach) { this.attach = attach; } public string getfee_type() { return fee_type; } public void setfee_type(string fee_type) { this.fee_type = fee_type; } public string gettime_start() { return time_start; } public void settime_start(string time_start) { this.time_start = time_start; } public string gettime_expire() { return time_expire; } public void settime_expire(string time_expire) { this.time_expire = time_expire; } public string getgoods_tag() { return goods_tag; } public void setgoods_tag(string goods_tag) { this.goods_tag = goods_tag; } public string getlimit_pay() { return limit_pay; } public void setlimit_pay(string limit_pay) { this.limit_pay = limit_pay; } }
这里给出的参数都是可以移动端自己获取到的,当然,最好是后台提供给我们,出于安全性考虑
支付完成,微信会回调wxpayentryactivity,这里就不详细说了,微信文档说的很清晰
在wxpayentryactivity的onresp()里面返回的微信支付的结果(注:这个结果不能作为我们购买商品成功与否的结果,要以微信回调给回台,然后回台告诉我们的支付结果为准)
if (resp.gettype() == constantsapi.command_pay_by_wx) { int code = resp.errcode; switch (code) { case 0: log.d(tag, "onpayfinish, errcode = " + "支付成功"); //微信支付成功后去调后台,以后台返回的支付结果为准 //这里是微信支付完成后的回调,在这里请求后台,让他来告诉我们到底支付成功没。 break; case -1: toast.maketext(this, "支付失败1", toast.length_short).show(); log.d(tag, "onpayfinish, errcode = " + "支付失败1"); finish(); break; case -2: toast.maketext(this, "支付取消", toast.length_short).show(); log.d(tag, "onpayfinish, errcode = " + "支付取消"); finish(); break; default: // toast.maketext(this, "支付失败2", toast.length_short).show(); log.d(tag, "onpayfinish, errcode = " + "支付失败2"); setresult(result_ok); finish(); break; } }
以上就是本文的全部内容,希望对大家的学习有所帮助,也希望大家多多支持。