android端微信支付V3版本地签名统一下单详解_Android

满满的都是坑,因为服务器偷懒让客服端写统一下单,服务器只给了通知的url。微信的支付demo并没有统一下单的代码。

读此文前先阅读: https://pay.weixin.qq.com/wiki/doc/api/app/app.PHP?chapter=9_1

一步步的来  先根据统一下单的参数介绍工具:

1. 获取到当前的ip:

<span style="font-size:14px;">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;
  } 

  private String intToIp(int i) { 

    return (i & 0xFF) + "." +
        ((i >> 8) & 0xFF) + "." +
        ((i >> 16) & 0xFF) + "." +
        (i >> 24 & 0xFF);
  }
</span> 

2.随机订单号生成 test 你们可根据自己生成随机数:

<span style="font-size:14px;">private String genOutTradNo() {
    Random random = new Random();
    return MD5.getMessageDigest(String.valueOf(random.nextInt(10000)).getBytes());
  }</span> 

3.签名工具:

<span style="font-size:14px;">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("orion",appSign);
    return appSign;
  }</span> 

差不多了  现在我们需要生成传递的参数   参数要求是xml 格式的:

<span style="font-size:14px;">private String genProductArgs() {
    StringBuffer xml = new StringBuffer();
    String ip = getWifiIp();
    if (ip == "" && ip == "") {
      ip = getLocalIpAddress();
    }
    try {
      String nonceStr = genNonceStr();
      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",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", "1"));
      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;
    }
  }</span>

其中  toxml:

<span style="font-size:14px;">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();
  }</span> 

得到传递的参数,根据文档指示,我们需要用post去吊连接URL地址:https://api.mch.weixin.qq.com/pay/unifiedorder:

<span style="font-size:14px;">  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;
    }
  }</span>

 其中decodexml就是:

 <span style="font-size:14px;">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; 

  }</span>

 下单完成,第二部就是给微信支付传递调起微信支付的参数(具体参数看文档说明):

 <span style="font-size:14px;">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", signParams.toString()); 

  }</span>

 第三部,调微信支付:

 <span style="font-size:14px;">private void sendPayReq() {
    msgApi.registerApp(Constants.APP_ID);
    msgApi.sendReq(req);
  }</span>

 其中:

 <span style="font-size:14px;">Constants.APP_ID</span>

是appid 在开发者平台获取

<span style="font-size:14px;">    req.partnerId = Constants.MCH_ID;</span> 

商户id

<span style="font-size:14px;">ConfigUtil.NOTIFY_URL</span> 

支付后的回调通知地址。

签名两次,然后用的api——key是商户平台api安全里面自定义的。

对了 还有个获取时间工具

<span style="font-size:14px;">private long genTimeStamp() {
    return System.currentTimeMillis() / 1000;
  }</span>

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

以上是小编为您精心准备的的内容,在的博客、问答、公众号、人物、课程等栏目也有的相关内容,欢迎继续使用右上角搜索按钮进行搜索统一下单 签名错误、微信统一下单签名错误、统一下单 签名失败、统一下单接口签名错误、微信统一下单中文签名,以便于您获取更多的相关知识。

时间: 2024-12-03 23:37:12

android端微信支付V3版本地签名统一下单详解_Android的相关文章

android端微信支付V3版本地签名统一下单详解

满满的都是坑,因为服务器偷懒让客服端写统一下单,服务器只给了通知的url.微信的支付demo并没有统一下单的代码. 读此文前先阅读: https://pay.weixin.qq.com/wiki/doc/api/app/app.PHP?chapter=9_1 一步步的来  先根据统一下单的参数介绍工具: 1. 获取到当前的ip: <span style="font-size:14px;">public String getLocalIpAddress() { try { f

Android中用Bmob实现短信验证码功能的方法详解_Android

 这篇文章主要介绍发送验证码和校验验证码的功能,用到一个第三方平台Bmob,那Bmob是什么呢?Bmob可以开发一个云存储的移动应用软件,他提供了大量的标准的API接口,根据需要接入相关服务,开发者可以更加专注于应用的开发,让产品交付更快速,验证码功能就是其中一个. 一.跟其他第三方一样,我们开发之前要做一些准备工作. 1.首先,去官网注册一个帐号:http://www.bmob.cn/: 2.然后就可以创建应用了:具体怎么做Bmob说得很清楚了(官方操作介绍),如果你不想看,我简单说一下:点击

Android常用布局(FrameLayout、LinearLayout、RelativeLayout)详解_Android

很多开发者一听说Android终端的屏幕尺寸五花八门,屏幕分辨率千奇百怪,就觉得Android开发在屏幕适配方面是必定是一件头疼的事情.因为在Android问世之前,广大开发者知道的UI解决方案大致分为两类: 1.在Web开发中的CSS,一层一层的去层叠样式. 2.在iOS开发中去计算每一个UIView的尺寸. 上面两种方案,无论哪种方案面对碎片化严重的Android终端,那都是一场噩梦.好在Android提供了另一套解决方案来应对严重的终端碎片化,这就是布局和9-patch. 这里想来说说布局

Android自定义进度条的圆角横向进度条实例详解_Android

1.本文将向你介绍自定义进度条的写法,比较简单,但还是有些知识点是需要注意的: invalidate()方法 RectF方法的应用 onMeasure方法的应用 2.原理 画3层圆角矩形,底层为黑色,第二层为灰色,最上一层为进度条颜色,示例图如下: 3.效果图   实现圆角进度条还有很多其他方法,比如在Progress控件里填充圆角图片,通过拉伸图片来达到预想的效果,虽然听起来很简单,但实现起来还是有些麻烦的. 4.解说方法 (1)invalidate()方法 invalidate()是用来刷新

Android开发之机顶盒上gridview和ScrollView的使用详解_Android

最近在机顶盒上做一个gridview, 其焦点需要在item的子控件上,但gridview的焦点默认在item上,通过 android:descendantFocusability="afterDescendants" <ScrollView android:id="@+id/scroll_content" android:layout_width="1740.0px" android:layout_height="600.0px

Android中Spinner(下拉框)控件的使用详解_Android

android给我们提供了一个spinner控件,这个控件主要就是一个列表,那么我们就来说说这个控件吧,这个控件在以前的也看见过,但今天还是从新介绍一遍吧. Spinner位于 android.widget包下,每次只显示用户选中的元素,当用户再次点击时,会弹出选择列表供用户选择,而选择列表中的元素同样来自适配器.Spinner是View类得一个子类. 1.效果图 2.创建页面文件(main.xml) <Spinner android:id="@+id/spinner1" and

深入理解Android组件间通信机制对面向对象特性的影响详解_Android

组件的特点对于Android的四大组件Activity, Service, ContentProvider和Service,不能有Setter和Getter,也不能给组件添加接口.原因是组件都是给系统框架调用的,开发者只能实现其规定的回调接口,组件的创建与销毁都是由系统框架控制的,开发者不能强行干预,更没有办法获取组件的对象.比如Activity,Service,BroadcastReceiver,你没有办法去创建一个Activity,Service或BroadcastReceiver,然后像使

Android Activity与Service通信(不同进程之间)详解_Android

在Android中,Activity主要负责前台页面的展示,Service主要负责需要长期运行的任务,所以在我们实际开发中,就会常常遇到Activity与Service之间的通信,我们一般在Activity中启动后台Service,通过Intent来启动,Intent中我们可以传递数据给Service,而当我们Service执行某些操作之后想要更新UI线程,我们应该怎么做呢?接下来我就介绍三种方式来实现Service与Activity之间的通信问题 Activity与Service通信的方式有三

Android编程中的四大基本组件与生命周期详解_Android

本文实例讲述了Android编程中的四大基本组件与生命周期.分享给大家供大家参考,具体如下: Android四大基本组件分别是Activity,Service服务,Content Provider内容提供者,BroadcastReceiver广播接收器. 一:了解四大基本组件 Activity : 应用程序中,一个Activity通常就是一个单独的屏幕,它上面可以显示一些控件也可以监听并处理用户的事件做出响应. Activity之间通过Intent进行通信.在Intent 的描述结构中,有两个最