Android接入微信支付的方法

 更新时间:2018年05月28日 10:01:58   作者:大校啊  
这篇文章主要介绍了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<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;
      }
    }

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

相关文章

  • 单元测试 @mock与@SpringBootTest的使用

    单元测试 @mock与@SpringBootTest的使用

    这篇文章主要介绍了单元测试 @mock与@SpringBootTest的使用方式,具有很好的参考价值,希望对大家有所帮助。如有错误或未考虑完全的地方,望不吝赐教
    2021-10-10
  • SpringSecurity退出功能实现的正确方式(推荐)

    SpringSecurity退出功能实现的正确方式(推荐)

    本文将介绍在Spring Security框架下如何实现用户的"退出"logout的功能。本文通过实例代码讲解的非常详细,具有一定的参考借鉴价值,需要的朋友参考下吧
    2019-11-11
  • 详解SpringBoot如何自定义Starter

    详解SpringBoot如何自定义Starter

    Starter是Spring Boot中的一个非常重要的概念,Starter相当于模块,它能将模块所需的依赖整合起来并对模块内的Bean根据环境( 条件)进行自动配置。本文将介绍SpringBoot如何自定义Starter,感兴趣的可以学习一下
    2021-12-12
  • Maven scala和java混合打包方式

    Maven scala和java混合打包方式

    这篇文章主要介绍了Maven scala和java混合打包方式,具有很好的参考价值,希望对大家有所帮助。如有错误或未考虑完全的地方,望不吝赐教
    2023-06-06
  • 深入java对象复制的分析

    深入java对象复制的分析

    本篇文章是对java对象复制进行了详细的分析介绍,需要的朋友参考下
    2013-05-05
  • Java如何使用while循环计算一个整数的位数

    Java如何使用while循环计算一个整数的位数

    这篇文章主要介绍了Java使用while循环计算一个整数的位数方式,具有很好的参考价值,希望对大家有所帮助。如有错误或未考虑完全的地方,望不吝赐教
    2022-01-01
  • RocketMQ消息重试机制原理分析讲解

    RocketMQ消息重试机制原理分析讲解

    这篇文章主要介绍了RocketMQ消息重试机制,消息的发送和消费并不是百分百成功的,在出现消息推送失败时,RocketMQ有何补偿方式来进行消息重试呢?这是我们今天要一起学习的点
    2023-02-02
  • java+mysql实现商品抢购功能

    java+mysql实现商品抢购功能

    这篇文章主要为大家详细介绍了java+mysql实现商品抢购功能,具有一定的参考价值,感兴趣的小伙伴们可以参考一下
    2018-02-02
  • SpringBoot中读取jar包中的resources目录下的文件的三种方式

    SpringBoot中读取jar包中的resources目录下的文件的三种方式

    这篇文章给大家总结了SpringBoot读取 jar 包中的 resources 目录下的文件的三种方式,文中有详细的代码示例供大家参考,,需要的朋友可以参考下
    2023-06-06
  • 解决javaBean规范导致json传参首字母大写将永远获取不到问题

    解决javaBean规范导致json传参首字母大写将永远获取不到问题

    这篇文章主要介绍了解决javaBean规范导致json传参首字母大写将永远获取不到问题,具有很好的参考价值,希望对大家有所帮助。如有错误或未考虑完全的地方,望不吝赐教
    2021-07-07

最新评论