1. 程式人生 > >微信支付中文亂碼,帶中文簽名不成功

微信支付中文亂碼,帶中文簽名不成功

  • 在做微信公眾號支付和H5支付時發現支付引數帶中文就會簽名失敗,試過很多種辦法如:
new String(xml.toString().getBytes(), "ISO8859-1");

把xml轉為ISO8859-1提交到微信統一下單介面簽名不正確,網上一般都是說這種做法。

  • 後面我用這樣的方式能簽名成功,也能支付
paraMap.put("body", URLEncoder.encode("棋牌", "UTF-8")); 

但是這樣編碼後,微信支付顯示的body是編碼後的一串亂碼。

  • 最後終於查到是需要改md5簽名前字串的編碼。

  • 統一下單的程式碼:WeChatH5PayImpl.java 微信h5支付

@Override
    public JsonObject gateway(PayPlatform payPlatform, PayOrder order, Map<String, String> params) {
        JsonObject result = new JsonObject();
        try {
            //字典序列排序
            //第一次簽名
            Map<String, String> paraMap = new HashMap<>();
            // paraMap.put
("total_fee", order.getPrice().toString()); paraMap.put("total_fee", "1"); paraMap.put("appid", APPID); paraMap.put("out_trade_no", order.getMerchantOrderNo()); paraMap.put("attach", order.getMerchantOrderNo()); //TODO 中文編碼有問題 paraMap.put
("body", "棋牌" ); //如果不轉碼,引數帶中文會簽名失敗 paraMap.put("mch_id", MCH_ID); paraMap.put("nonce_str", WeChatPublicNumberPayImpl.getNonceStr()); paraMap.put("notify_url", notifyUrl); //paraMap.put("openid", params.getOrDefault("operId", ""));//"oPKW80lcsqmHLWvPLElQoN2p6Eow"); String spbill_create_ip = params.getOrDefault("spbillCreateIp","127.0.0.1"); if(-1 != spbill_create_ip.indexOf(",")){ spbill_create_ip = spbill_create_ip.split(",")[0]; } paraMap.put("spbill_create_ip", spbill_create_ip); paraMap.put("trade_type", "MWEB"); paraMap.put("scene_info","{\"h5_info\": {\"type\":\"Wap\",\"wap_url\": \"http://www.test.com\",\"wap_name\": \"棋牌\"}} "); //字典序列排序 String url = WeChatPublicNumberPayImpl.formatUrlMap(paraMap, false, true); url = url + "&key=" + MCH_ID_KEY; String sign = MD5Utils.MD5Encoding(url).toUpperCase(); StringBuffer xml = new StringBuffer(); xml.append("<xml>"); for (Map.Entry<String, String> entry : paraMap.entrySet()) { xml.append("<" + entry.getKey() + ">"); xml.append(entry.getValue()); xml.append("</" + entry.getKey() + ">" + "\n"); } xml.append("<sign>"); xml.append(sign); xml.append("</sign>"); xml.append("</xml>"); log.info("xml \n {} ", xml.toString()); String responseBosy = HttpUtils.sentPost(PAYURL, xml.toString(), "UTF-8"); log.info("responseBosy \n {} " , responseBosy ); Map<String,String> respBodyMap = WeChatPublicNumberPayImpl.readStringXmlOut(responseBosy); String return_code = respBodyMap.getOrDefault("return_code",""); if(null != return_code && "SUCCESS".equals(return_code)){ //成功 result.put("code", 1); result.put("type", ReturnType.JUMP_PAGE_TYPE.getCode()); result.put("redirect", respBodyMap.getOrDefault("mweb_url","")+"&redirect_url=http://h5.ccac7.com/api/login"); }else{ //失敗 result.put("code",0); result.put("message","sign error"); } } catch (Exception e) { result.put("code", 0); result.put("message","建立訂單失敗"); } return result; }
  • WeChatPublicNumberPayImpl.java ASCII 碼從小到大排序的程式碼
 /**
     * 方法用途: 對所有傳入引數按照欄位名的Unicode碼從小到大排序(字典序),並且生成url引數串<br>   
       特別注意如果是微信公眾號第二次簽名使用這個 (prepay_id=wx2018011916085772ffb69ce20165288425)拼接出來的url package會有問題
     * 實現步驟: <br>
     *
     * @param paraMap    要排序的Map物件
     * @param urlEncode  是否需要URLENCODE
     * @param keyToLower 是否需要將Key轉換為全小寫
     *                   true:key轉化成小寫,false:不轉化
     * @return
     */
    public static String formatUrlMap(Map<String, String> paraMap, boolean urlEncode, boolean keyToLower) {
        String buff = "";
        Map<String, String> tmpMap = paraMap;
        try {
            List<Map.Entry<String, String>> infoIds = new ArrayList<Map.Entry<String, String>>(tmpMap.entrySet());
            // 對所有傳入引數按照欄位名的 ASCII 碼從小到大排序(字典序)
            Collections.sort(infoIds, new Comparator<Map.Entry<String, String>>() {
                @Override
                public int compare(Map.Entry<String, String> o1, Map.Entry<String, String> o2) {
                    return (o1.getKey()).toString().compareTo(o2.getKey());
                }
            });
            // 構造URL 鍵值對的格式
            StringBuilder buf = new StringBuilder();
            for (Map.Entry<String, String> item : infoIds) {
                if (StringUtils.isNotBlank(item.getKey())) {
                    String key = item.getKey();
                    String val = item.getValue();
                    if (urlEncode) {
                        val = URLEncoder.encode(val, "utf-8");
                    }
                    if (keyToLower) {
                        buf.append(key.toLowerCase() + "=" + val);
                    } else {
                        buf.append(key + "=" + val);
                    }
                    buf.append("&");
                }

            }
            buff = buf.toString();
            if (buff.isEmpty() == false) {
                buff = buff.substring(0, buff.length() - 1);
            }
        } catch (Exception e) {
            return null;
        }
        return buff;
    }
  • MD5Utils.java
package com.rw.common.utils;

import java.security.MessageDigest;

public class MD5Utils {

    private static final char hexDigits[] = {'0', '1', '2', '3', '4', '5', '6', '7', '8', '9', 'a', 'b', 'c', 'd', 'e', 'f'};

   //重要的就是這裡,要調這個方法簽名才可以
    public static String MD5Encoding(String s) {
        byte[] btInput = null;
        try {
            btInput = s.getBytes("UTF-8");
        }catch (Exception e){
        }
        return MD5(btInput, 32);
    }


    public static String MD5(String s) {
        byte[] btInput = s.getBytes();
        return MD5(btInput, 32);
    }

    public static String MD5_16(String str) {
        byte[] btInput = str.getBytes();
        return MD5(btInput, 16);
    }

    private static String MD5(byte[] btInput, int length) {
        try {
            // 獲得MD5摘要演算法的 MessageDigest 物件
            MessageDigest mdInst = MessageDigest.getInstance("MD5");
            // MessageDigest mdInst = MessageDigest.getInstance("SHA-1");
            // 使用指定的位元組更新摘要
            mdInst.update(btInput);
            // 獲得密文
            byte[] md = mdInst.digest();
            // 把密文轉換成十六進位制的字串形式
            int j = md.length;
            char str[] = new char[j * 2];
            int k = 0;
            for (byte byte0 : md) {
                str[k++] = hexDigits[byte0 >>> 4 & 0xf];
                str[k++] = hexDigits[byte0 & 0xf];
            }
            String result = new String(str);
            return length == 16 ? result.substring(8, 24) : result;
        } catch (Exception e) {
            e.printStackTrace();
            return null;
        }
    }
}
  • 這是最後執行結果:
    這裡寫圖片描述

  • 還有注意的:微信公眾號支付的支付授權地址路徑不能只寫域名地址

相關推薦

支付中文亂碼,中文簽名成功

在做微信公眾號支付和H5支付時發現支付引數帶中文就會簽名失敗,試過很多種辦法如: new String(xml.toString().getBytes(), "ISO8859-1"); 把xml轉為ISO8859-1提交到微信統一下單介面簽名不正確,

android 支付,body為中文字元,簽名錯誤

微信支付訂單生產方法: /** * 根據您的訂單資訊 生成 微信產品支付訂單資訊 */ private String createWeChatOrder() { StringBuffer xml = new StringBuffer();

支付後臺總是返回資料簽名錯誤篇一

ps:微信支付後臺總是返回資料簽名錯誤,在本地呼叫支付方法返回正常,可以獲取到prepay_id,可是到程式碼上傳到伺服器,在手機裡面呼叫,總是說,簽名錯誤。我的錯誤原因是因為,商品描述,body欄位傳的中文字串。把中文改完拼音就可以了。個人推斷應該是編碼的問題。 St

支付提示:同一筆交易能多次提交

微信支付API上說明: OUT_TRADE_NO_USED 商戶訂單號重複 同一筆交易不能多次提交 請核實商戶訂單號是否重複提交 測試的時候先用微信支付得到預支付id,取消當前支付,再次付款的時候就會提示:“訂單號重複” 網上搜了一下,大概共有三種解決辦法: 1

支付 統一下單 欄位 body 為中文時 報【簽名錯誤】解決方案(C# SDK)

方案一 如果你是從微信支付官網下載的 .NET C#【微信支付】API對應的SDK 呼叫示例 檢視原始碼,會發現這個SDK中的 WxPayData 的類的 CalcHMACSHA256Hash 簽名方法採用的是  Encoding.Default 

支付 統一下單 字段 body 為中文時 報【簽名錯誤】解決方案(C# SDK)

def salt ext var pri utf8 () rap vat 方案一 如果你是從微信支付官網下載的 .NET C#【微信支付】API對應的SDK 調用示例 查看源碼,會發現這個SDK中的 WxPayData 的類的 CalcHMACSHA256Hash 簽名

統一下單body傳中文導致簽名失敗和亂碼的問題

呼叫微信統一下單介面時如果返回簽名錯誤,可以先去官方提供的線上簽名去校驗一下,這裡只能校驗簽名演算法有沒有問題。https://pay.weixin.qq.com/wiki/doc/api/jsapi.php?chapter=20_1如果這裡校驗簽名沒有問題,但實際呼叫返回的

小程式POST請求中文亂碼的解決方法

前兩天在整合微信小程式前後端的過程中,出現了中文 亂碼。解決方法如下:前端的程式碼:wx.request({ url: '.........', data: { ....... }, header: {'Content-T

小程式後臺返回中文亂碼問題--gxy

wx.reqiest( ) 請求後臺返回的資料為: ???3???????56716,???16???????56701,???26???????56600,???24???????56459,???19???????56448,???28???????5

獲取支付所需簽名

mode auto ppi rate one url con turn sub @RequestMapping(value = "/toPay", method = RequestMethod.POST) @ResponseBody public String getSho

【java】java反射機制,動態獲取對象的屬性和對應的參數值,並屬性按照字典序排序,Field.setAccessible()方法的說明【可用於支付 簽名生成】

modifier 直接 this 字段值 1-1 讓我 toupper ima play 方法1:通過get()方法獲取屬性值 package com.sxd.test.controller; public class FirstCa{ private

支付:手機系統自的瀏覽器,調用支付如何實現(非掃碼)

所有 價格 驗證 返回 調用 -i 是否為空 支付申請 data- Q:翻看了微信支付的api沒發現支持h5調支付接口的情況(微信js除外),然後卻發現美團的支付成功調用了,這是怎麽實現的? A: 使用微信H5支付即可。H5支付通過URL調起微信APP,

支付 apiclient_cert.p12證書的請求方法 JAVA版

sls std return key AR import init p12證書 下午 以下是帶apiclient_cert.p12證書的請求方法 package utils.wechat; import java.io.File; import java.io.File

支付的簡易log

lena code pat ram log err nbsp PC deb using System; using System.Collections.Generic; using System.Web; using System.IO; namespac

【PHP原生】xml和數組互轉(支付簽名算法)

互轉 amp 字母 ble md5加密 clas toarray sig val 數組轉XML publicfunction arrayToXml($arr) { $xml ="<xml>"; foreach($arr as $key =&g

ASP支付asp源碼下載2018年10月最新版證書

格式 圖片 做的 沒有 bubuko 新版 win 獲取 == 昨天晚上給朋友寫了一個asp的微信公眾號支付接口,我這朋友的公眾號用的asp做的,以前沒有支付,非讓我給寫一個支付,因為必須是asp來寫,他不會,所以我就幫他寫了,順便還寫了一個asp獲取用戶資料頭像和微信名入

支付非同步回撥,你解決支付的深坑

1.首先我們先下載微信支付的伺服器端demo 2.個檔案作用介紹 index.jsp  下單  payRequest.jsp  獲取微信支付prepay_id等。 重點我說說這個payNotifyUrl.jsp

小程式:將中文語音直接轉化成英文語音

作者:瘟小駒    文章來源《微信小程式個人開發全過程》 準備工作: 準備工具:Eclipse、FileZilla、微信開發者工具、一個配置好SSL證書(https)的有域名的伺服器 所需知識:SpringMVC框架、Java+HTML+CSS+JS、檔案上傳技術、To

支付-返回簽名錯誤

Android 微信支付SDK ,支付操作大概3步。 1、生成預支付訂單 2、生成簽名引數 3、調取微信支付頁面 但是需要注意的是,在獲取預支付訂單的時候會報簽名錯誤。 大概也就那幾種可能: 1、微信開放平臺的簽名設定和你當前的的確不一樣,這個需要自己檢查 2、API 密匙不

支付”勒索病毒被破解:源頭是病毒的開發工具

   12月1日,國內首次出現了要求微信支付贖金的勒索病毒。這款病毒的勒索方式和“WannaCry”一樣,入侵電腦執行後會加密使用者檔案,但是它不收取比特幣,而是要求受害者掃描彈出的微信支付二維碼交付贖金。根據“火絨威脅情報系統”監測和評估,截至4日晚,該病毒至少感染了10