微信native方式支付中body为中文时签名错误解决方法




http://blog.csdn.net/lifuxiangcaohui/article/details/46711319
  分类:
 
[java]  view plain copy
  1. <span style="font-family: Arial, Helvetica, sans-serif; font-size: 18px; font-weight: bold; background-color: rgb(255, 255, 255);">     </span>  


        最近在做在做微信支付中的native支付第二种支付方式,在请求参数时遇到了最大的问题就是,body(商品描述)为中文时,签名失败,为英文时签名成功。这个问题搞了好几天,没有搞定,今天终于搞定了,特此分享一哈。


其实就是一句话的问题:  把我们生成的xml请求参数转为字节数组后,用“ISO8859-1”编码格式进行编码为字符串,就可以解决问题了。


[java]  view plain copy
  1. return new String(sb2.toString().getBytes(), "ISO8859-1");  





=============================================================================================================

上面的已经可以解决问题。下面我只是说说更详细的解决步骤。

1. 首先我们来看看官方的接口文档:

认证方式:HTTPS讣证,退款和冲正接口调用需要商户证书(证书在审核邮件附件
中) 
请求采用POST方式 
提交和返回结果采用XML格式 
字符集默讣使用UTF-8,请勿使用其它字符集 
商户不微信之间的交互(特别是Native回调和支付通知回调),都需要验证签名 

4.1.统一支付接口 
URL地址:https://api.mch.weixin.qq.com/pay/unifiedorder 
统一支付接口,可接叐JSAPI/NATIVE/APP下预支付订单,返回预支付订单号。 
NATIVE支付返回二维码code_url。 
注意:JSAPI 下单前需要调用登录授权接口(详细调用说明请点击打开链接)获叏到用户
的Openid。


我们只需要传递对应的参数,请求“https://api.mch.weixin.qq.com/pay/unifiedorder ”,把得到“code_url”生成二维码即可。


2.  定义个常量类用来存储请求值

我定义了一常量类,保存我们用到的参数值(这只是我的Demo,不是真实中的项目,所以这么用,真实中不能这么弄,这个在真实中最好有服务器端操作,我们需要的只是一个"code_url"而已)。

[java]  view plain copy
  1. /** 
  2.  * 请求需要的参数 
  3.  * @author Administrator 
  4.  * 
  5.  */  
  6. public class Constans {  
  7.     //appid   
  8.     public static String APPID = "wxd930ea5d5a258f4f";  
  9.     public static String auth_code = genNonceStr();  
  10.     public static String body = "霸气的小明(qiwenming)";  
  11.     public static String device_info = "1000";  
  12.     public static String mch_id = "1900000109";  
  13.     public static String nonce_str = genNonceStr();  
  14.     public static String out_trade_no = genNonceStr();  
  15.     public static String spbill_create_ip = "127.0.0.1";  
  16.     public static String notify_url = "http://www.baidu.com";  
  17.     public static String total_fee = "1";  
  18.     public static String trade_type = "NATIVE";  
  19.     public static String private_key = "8934e7d15453e97507ef794cf7b0519d";  
  20.     public static String key = "L8LrMqqeGRxST5reouB0K66CaYAWpqhAVsq7ggKkxHCOastWksvuX1uvmvQclxaHoYd3ElNBrNO2DHnnzgfVG9Qs473M3DTOZug5er46FhuGofumV8H2FVR9qkjSlC5K";  
  21.               
  22.     //请求地址  
  23.     public static String url="https://api.mch.weixin.qq.com/pay/unifiedorder";  
  24.     //生成随机字符串  
  25.     private static String genNonceStr() {  
  26.         Random random = new Random();  
  27.         return MD5.getMessageDigest(String.valueOf(random.nextInt(10000)).getBytes());  
  28.     }  
  29. }  


3.我们组织参数,生成请求参数(XML格式 ) 

 这里分为2步:

  第一步,我们把请求参数,按字典顺序存入到一个集合中;

  第二步,我们把这些参数组装为xml格式的数据,并且完成签名的过程,这一步中最关键的是 我们要把生成的xml字符串,转为字节后,在使用“Isolates859-1”编码重新编码为字符串

 3.1按字典顺序存入到一个集合中:

[java]  view plain copy
  1. <span style="font-size:18px;"><strong>  </strong>    </span><span style="font-size:14px;"/** 
  2.      * 把一个参数添加到 一个集合中,按字典顺序,这是为了后面生成 签名方便 
  3.      *  
  4.      * @return 
  5.      */  
  6.     private String genProductArgs() {  
  7.         List<NameValuePair> packageParams = new LinkedList<NameValuePair>();  
  8.         packageParams.add(new BasicNameValuePair("appid", Constans.APPID));  
  9.         packageParams.add(new BasicNameValuePair("appkey", Constans.key));  
  10.         packageParams.add(new BasicNameValuePair("body", Constans.body));  
  11.         packageParams.add(new BasicNameValuePair("input_charset""UTF-8"));  
  12.         packageParams.add(new BasicNameValuePair("mch_id", Constans.mch_id));  
  13.         packageParams.add(new BasicNameValuePair("nonce_str",  
  14.                 Constans.nonce_str));  
  15.         packageParams.add(new BasicNameValuePair("notify_url",  
  16.                 "http://www.baidu.com"));  
  17.         packageParams.add(new BasicNameValuePair("out_trade_no",  
  18.                 Constans.out_trade_no));  
  19.         packageParams.add(new BasicNameValuePair("spbill_create_ip",  
  20.                 Constans.spbill_create_ip));  
  21.         packageParams.add(new BasicNameValuePair("total_fee", Constans.total_fee));  
  22.         packageParams.add(new BasicNameValuePair("trade_type",  
  23.                 Constans.trade_type));  
  24.          //调用genXml()方法获得xml格式的请求数据  
  25.         return genXml(packageParams);  
  26.     }</span><span style="font-size:18px;">  
  27. </span>  


3.2生成XML格式参数, 注意转码

[java]  view plain copy
  1. /** 
  2.  * 生成xml格式的请求参数 
  3.  *  
  4.  * @param params 
  5.  *            参数集合 
  6.  * @return 
  7.  */  
  8. private String genXml(List<NameValuePair> params) {  
  9.     StringBuilder sb = new StringBuilder();  
  10.     StringBuilder sb2 = new StringBuilder();  
  11.     sb2.append("<?xml version='1.0' encoding='UTF-8' standalone='yes' ?><xml>");  
  12.     for (int i = 0; i < params.size(); i++) {  
  13.         // sb是用来计算签名的  
  14.         sb.append(params.get(i).getName());  
  15.         sb.append('=');  
  16.         sb.append(params.get(i).getValue());  
  17.         sb.append('&');  
  18.         // sb2是用来做请求的xml参数  
  19.         sb2.append("<" + params.get(i).getName() + ">");  
  20.         sb2.append(params.get(i).getValue());  
  21.         sb2.append("</" + params.get(i).getName() + ">");  
  22.     }  
  23.     sb.append("key=");  
  24.     sb.append(Constans.private_key);  
  25.     String packageSign = null;  
  26.     // 生成签名  
  27.     packageSign = MD5.getMessageDigest(sb.toString().getBytes())  
  28.             .toUpperCase();  
  29.     sb2.append("<sign><![CDATA[");  
  30.     sb2.append(packageSign);  
  31.     sb2.append("]]></sign>");  
  32.     sb2.append("</xml>");  
  33.   
  34.     // 这一步最关键 我们把字符转为 字节后,再使用“ISO8859-1”进行编码,得到“ISO8859-1”的字符串  
  35.     try {  
  36.         return new String(sb2.toString().getBytes(), "ISO8859-1");  
  37.     } catch (Exception e) {  
  38.         e.printStackTrace();  
  39.     }  
  40.     return "";  
  41. }  


4.请求数据,把得到的code_url生成二维码 

[java]  view plain copy
  1.       /** 
  2.  * 获得 code_url地址,生成二维码 
  3.  * @author qiwenming 
  4.  */  
  5. class GetCodeUrl {  
  6.     ProgressDialog dialog;  
  7.     public void get() {  
  8.         String url = Constans.url;  
  9.         String entity = genProductArgs();  
  10.         Log.d("URL""url-----------:" + url);  
  11.         Log.d(TAG, " entity----------: " + entity);  
  12.   
  13.         HttpUtils http = new HttpUtils();  
  14.   
  15.         RequestParams params = new RequestParams();  
  16.         try {  
  17.             params.setBodyEntity(new StringEntity(entity));  
  18.             http.send(HttpMethod.POST, url, params,  
  19.                     new RequestCallBack<String>() {  
  20.                         @Override  
  21.                         public void onSuccess(ResponseInfo<String> res) {  
  22.                             Log.i(TAG, res.result);  
  23.                             ResultXmlbean beanxml = Util.XmlToBean(res.result);  
  24.                             if (beanxml.getResult_code() == beanxml.getReturn_code()  
  25.                                     && beanxml.getResult_code().equals("SUCCESS")) {  
  26.                                 //请求成功后,获得的code_url生成二维码  
  27.                                 int QR_WIDTH = 300, QR_HEIGHT = 300;  
  28.                                 //调用工具类生成二维码  
  29.                                 Bitmap bitmap = ZxingUtils.createQRImage(beanxml.getCode_url(), QR_WIDTH,QR_HEIGHT);  
  30.                                 Log.i(TAG, "####code_url##  "+beanxml.getCode_url());  
  31.                                 //设置二维码  
  32.                                 iv_QRcode.setImageBitmap(bitmap);  
  33.                             } else {  
  34.                                 Toast.makeText(getApplicationContext(),  
  35.                                         "error"0).show();  
  36.                             }  
  37.                         }  
  38.   
  39.                         @Override  
  40.                         public void onFailure(HttpException arg0,  
  41.                                 String arg1) {  
  42.                             Log.d(TAG, arg0.toString()+"--#####---"+arg1);  
  43.                             Log.d(TAG,"请求失败。。。。。。。。");  
  44.                         }  
  45.   
  46.                     });  
  47.         } catch (Exception e) {  
  48.             e.printStackTrace();  
  49.         }  
  50.     }  
  51. }  

以上已经解决了签名错误的问题,下面只是展示而已。

==================================================================

生成的二维码图片:



使用微信扫描的结果(微信中:发现--->扫一扫):



代码下载

版权声明:本文为博主原创文章,未经博主允许不得转载。

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值