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

作者:失足小葩葩 时间:2023-05-18 02:37:44 

满满的都是坑,因为服务器偷懒让客服端写统一下单,服务器只给了通知的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>

来源:http://blog.csdn.net/meijuanyou/article/details/51863720

标签:微信支付,android
0
投稿

猜你喜欢

  • SQLite在C#中的安装与操作技巧

    2023-04-19 08:31:12
  • Android 拦截返回键事件的实例详解

    2023-02-19 07:09:09
  • Java+element实现excel的导入和导出

    2022-07-31 12:45:53
  • Kotlin可见性修饰符详解

    2023-02-28 22:36:18
  • React-Native之Android(6.0及以上)权限申请详解

    2023-07-28 01:56:55
  • C#使用HttpClient的正确方式你了解吗

    2023-07-04 12:12:40
  • Spring创建Bean的过程Debug的详细流程

    2023-02-09 23:55:37
  • Android开发必备:秒杀真机超快模拟器Genymotion介绍

    2021-06-22 03:00:17
  • Android下使用TCPDUMP实现数据抓包教程

    2021-12-08 07:58:42
  • 详解Java的回调机制

    2023-07-27 07:17:43
  • Spring Boot整合流控组件Sentinel的场景分析

    2023-06-22 19:27:53
  • Android自定义渐变式炫酷ListView下拉刷新动画

    2021-12-26 17:31:09
  • JavaWeb Hibernate使用全面介绍

    2021-09-13 11:26:07
  • Android中Activity启动默认不显示输入法解决方法

    2022-12-27 20:49:30
  • java二叉查找树的实现代码

    2022-08-12 02:36:43
  • Java面试题-实现复杂链表的复制代码分享

    2023-11-23 20:05:39
  • Android个人中心的头像上传,图片编码及截取实例

    2021-10-24 11:56:40
  • 在Unity中实现简单的伪时间同步

    2023-09-11 03:40:46
  • Java 获取当前时间及实现时间倒计时功能【推荐】

    2022-08-21 16:08:27
  • 使用纯Java实现一个WebSSH项目的示例代码

    2023-03-11 11:32:20
  • asp之家 软件编程 m.aspxhome.com