Android接入微信支付的方法

网友投稿 370 2023-01-31


Android接入微信支付的方法

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 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 map = decodeXml(content);

if (map != null) {

//再次签名(参与签名的字段有 :Appid partnerId prepayId nonceStr TimeStamp package)

String appId = "";

String prepayId = "";

String nonceStr = "";

for (Map.Entry 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 params) {

StringBuilder sb = new Strinhttp://gBuilder();

sb.append("");

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

return sb.toString();

}

public Map decodeXml(String content) {

try {

Map 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 getFirstSignParams(WXPrePost params) {

List packageParams = new LinkedList<>();

packageParams.add(new BasicNameValuePair(http://"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。其他详见http://时间规则 注意:最短失效时间间隔必须大于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;

}

}


版权声明:本文内容由网络用户投稿,版权归原作者所有,本站不拥有其著作权,亦不承担相应法律责任。如果您发现本站中有涉嫌抄袭或描述失实的内容,请联系我们jiasou666@gmail.com 处理,核实后本网站将在24小时内删除侵权内容。

上一篇:spring springMVC中常用注解解析
下一篇:LibrarySystem图书管理系统(二)
相关文章

 发表评论

暂时没有评论,来抢沙发吧~