E企盈营销工具技术服务商 热线:4006-838-530

踩坑:微信小程序支付流程(统一下单,支付回调)

E企盈直播平台营销卖货系统

公司最近开发小程序,涉及到支付功能. 现在支付功能已经做完,特此记录一下自己踩坑经验:众所周知,微信小程序目前只能使用微信支付, 而且微信小程序支付相对于app支付,h5支付都要简单一些,但是该支付文档对java这语言是非常不友好的,居然没有demo, 网上虽说有很多博客,但是找了好多都是跑不通, 乱七八糟的很多都跑不通, 以下 代码不是自己写的,大多都是这儿抄一点哪儿抄一顿,但是能跑通,亲测没毛病,如果有毛病可以留言交流.废话不多说,先说准备工作!对依赖不清楚或者回调失败的请访问: https://www.keppel.fun/articles/2019/03/06/1551844306979.html并注意该链接页面最下面的说明目录 1. 登录微信公众平台, 开通微信支付功能2. 登录微信商户平台3. 准备完毕, 小程序代码4. 后端统一下单和支付回调接口5. 相关配置类以及工具类6. 最后还有些jar包说明一下1. 登录微信公众平台, 开通微信支付功能这是准备工作的第一步, 确保小程序对应的支付功能已经开启2. 登录微信商户平台该步骤需要获取两个参数, 一个是商户号, 一个是支付秘钥, 如下图所示注意秘钥自己要保护好,相当于支付密码,每次签名都需要该参数, 该参数只能设置的时候看得见,其余的时候是没法看得见.所以要记好了!3. 准备完毕, 小程序代码微信小程序发起支付的请求到开发者服务器, 后台预下单返回一个prepay_id, 还有其他乱七八糟的参数.然后微信小程序调用支付方法进行支付, 最后微信服务器会发起回调函数到开发者服务器.先贴一段微信的测试代码,微信统一下单必须要openId参数://index.js//获取应用实例var app = getApp()Page({  data: {    motto: ‘Hello World’,    userInfo: {}  },  onLoad: function () {    console.log(‘onLoad’)      },  //  payoff: function(e){    var that = this;      console.log(‘zhixingle’)    wx.login({      success: function(res) {          wx.getUserInfo({                           success: function(re) {                  that.getAddress(re,res.code);              },              fail: function () {                  console.log(‘失败了’)              }          })      }          });      },  // 获取用户的收货地址    getAddress: function (re,code) {      var that = this;      wx.chooseAddress({          success: function (add) {              that.getOpenId(re, add.userName,add.provinceName,add.cityName,add.countyName,              add.detailInfo,add.telNumber,code);          }      })  },  //获取openid  getOpenId: function(re, userName, provinceName, cityName, countryName, detailInfo, telNumber,code){    var that = this;    wx.request({         // 开发者服务器地址        url: ‘http://1d7a111.iok.la:10534/api/getUnionId’,         method: ‘POST’,        header: {           ‘content-type’: ‘application/x-www-form-urlencoded’        },        data: { encryptedData: re.encryptedData, iv: re.iv, code: code },        success: function(res) {            var openId = res.data.userInfo.openId;            var unionId = res.data.userInfo.unionId;            // console.log(‘res>’, openId);            that.loginPlatform(userName, provinceName, cityName, countryName, detailInfo, telNumber,unionId, openId);                  }    })  },  // 登录    loginPlatform: function (userName, provinceName, cityName, countryName, detailInfo, telNumber,unionId, openId) {        var that = this;        wx.request({            url: ‘http://1d7a111.iok.la:12534/api/login/platform’,            method: ‘POST’,            header: {                ‘content-type’: ‘application/json’            },            data: { unionId: unionId, platform: ‘WECHAT’ },            success: function(res) {                console.log(‘res’, res.data.token);                var token = res.data.token;                that.xiadan(userName, provinceName, cityName, countryName, detailInfo, telNumber,openId, token);            }        })    },  //下单    xiadan: function (userName, provinceName, cityName, countryName, detailInfo, telNumber,openId, token){    console.log(‘openId’, openId);    console.log(‘token’, token);    var that = this;    wx.request({        url: ‘http://1d7a01111.iok.la:12534/api/v1/weixin/payment’,         method: ‘POST’,        header: {            ‘content-type’: ‘application/json’,            ‘authorization’: ‘Bearer ‘ + token        },        data: {            openId: openId,            cfId: ‘5b32f553aff8ca411f839eb4’,             planId: ‘5b32f5cbaff8ca111f839eb7’,            quantity: 2,            orderRemark: ‘说点啥备注好?’,            name: userName,            phone: telNumber,            province: provinceName,            city: cityName,            district: countryName,            address: detailInfo        },        success: function(res) {            console.log(‘res>>>’,res)            that.requestPayment(res.data.data);        }    })  },  //申请支付  requestPayment: function(obj){      console.log(‘obj>>’,obj)    wx.requestPayment({      ‘timeStamp’: obj.timeStamp,      ‘nonceStr’: obj.nonceStr,      ‘package’: obj.package,      ‘signType’: obj.signType,      ‘paySign’: obj.paySign,      ‘success’:function(res){      },      ‘fail’:function(res){      }    })  }  })因为我这边需求是要获取微信用户的收货地址,然后unionId是登录获取token,openId是支付的必须参数,所以代码写的有点乱,不是专业的4. 后端统一下单和支付回调接口 import com.thoughtworks.xstream.XStream;import org.apache.log4j.Logger;import org.dom4j.DocumentException;import org.springframework.beans.factory.annotation.Autowired;import org.springframework.beans.factory.annotation.Value;import org.springframework.security.core.Authentication;import org.springframework.security.core.context.SecurityContextHolder;import org.springframework.web.bind.annotation.RequestBody;import org.springframework.web.bind.annotation.RequestMapping;import org.springframework.web.bind.annotation.RequestMethod;import org.springframework.web.bind.annotation.RestController;import javax.servlet.ServletInputStream;import javax.servlet.http.HttpServletRequest;import javax.servlet.http.HttpServletResponse;import javax.validation.Valid;import java.io.BufferedOutputStream;import java.io.BufferedReader;import java.io.InputStreamReader;import java.io.UnsupportedEncodingException;import java.util.HashMap;import java.util.Map;/** * @Author: YFei * @Date: Created in 18:10 2018/7/25 * @Description: */@RestController@RequestMapping(value = “/api/v1”)public class WXAppletPayCtrl {       private static final long serialVersionUID = 1L;    private static final Logger L = Logger.getLogger(WXAppletPayCtrl.class);    @Value(“${wxapplet.config.weixinpay.notifyurl}”)    private String notify_url;    //交易类型    private final String trade_type = “JSAPI”;    //统一下单API接口链接    private final String url = “https://api.mch.weixin.qq.com/pay/unifiedorder”;    /**     *     * @param request     * @return     * @throws UnsupportedEncodingException     * @throws DocumentException     */    @RequestMapping(            value = “/weixin/payment”,            method = RequestMethod.POST    )    public Map payment(@Valid @RequestBody NewWXOrderRequest request, HttpServletRequest httpServletRequest) {        Map map = new HashMap();        String money = “10”;        String title = “商品名字”;               try {            OrderInfo order = new OrderInfo();            order.setAppid(Configure.getAppID());            order.setMch_id(Configure.getMch_id());            order.setNonce_str(RandomStringGenerator.getRandomStringByLength(32));            order.setBody(title);            order.setOut_trade_no(RandomStringGenerator.getRandomStringByLength(32));            order.setTotal_fee(Integer.parseInt(money));     // 该金钱其实10 是 0.1元            order.setSpbill_create_ip(“127.0.0.1”);            order.setNotify_url(notify_url);            order.setTrade_type(trade_type);            order.setOpenid(request.getOpenId());            order.setSign_type(“MD5”);            //生成签名            String sign = Signature.getSign(order);            order.setSign(sign);            String result = HttpRequest.sendPost(url, order);            System.out.println(result);            XStream xStream = new XStream();            xStream.alias(“xml”, OrderReturnInfo.class);            OrderReturnInfo returnInfo = (OrderReturnInfo)xStream.fromXML(result);            // 二次签名            if (“SUCCESS”.equals(returnInfo.getReturn_code()) && returnInfo.getReturn_code().equals(returnInfo.getResult_code())) {                SignInfo signInfo = new SignInfo();                signInfo.setAppId(Configure.getAppID());                long time = System.currentTimeMillis()/1000;                signInfo.setTimeStamp(String.valueOf(time));                signInfo.setNonceStr(RandomStringGenerator.getRandomStringByLength(32));                signInfo.setRepay_id(“prepay_id=”+returnInfo.getPrepay_id());                signInfo.setSignType(“MD5”);                //生成签名                String sign1 = Signature.getSign(signInfo);                Map payInfo = new HashMap();                payInfo.put(“timeStamp”, signInfo.getTimeStamp());                payInfo.put(“nonceStr”, signInfo.getNonceStr());                payInfo.put(“package”, signInfo.getRepay_id());                payInfo.put(“signType”, signInfo.getSignType());                payInfo.put(“paySign”, sign1);                map.put(“status”, 200);                map.put(“msg”, “统一下单成功!”);                map.put(“data”, payInfo);                // 此处可以写唤起支付前的业务逻辑                                // 业务逻辑结束                return map;            }            map.put(“status”, 500);            map.put(“msg”, “统一下单失败!”);            map.put(“data”, null);            return map;        } catch (Exception e) {            e.printStackTrace();            L.error(“——-“, e);        }        return null;    }    /**     * 微信小程序支付成功回调函数     * @param request     * @param response     * @throws Exception     */    @RequestMapping(value = “/weixin/callback”)    public void wxNotify(HttpServletRequest request,HttpServletResponse response) throws Exception{        BufferedReader br = new BufferedReader(new InputStreamReader((ServletInputStream)request.getInputStream()));        String line = null;        StringBuilder sb = new StringBuilder();        while((line = br.readLine()) != null){            sb.append(line);        }        br.close();        //sb为微信返回的xml        String notityXml = sb.toString();        String resXml = “”;        System.out.println(“接收到的报文:” + notityXml);        Map map = PayUtil.doXMLParse(notityXml);        String returnCode = (String) map.get(“return_code”);        if(“SUCCESS”.equals(returnCode)){            //验证签名是否正确            Map<String, String> validParams = PayUtil.paraFilter(map);  //回调验签时需要去除sign和空值参数            String validStr = PayUtil.createLinkString(validParams);//把数组所有元素,按照“参数=参数值”的模式用“&”字符拼接成字符串            String sign = PayUtil.sign(validStr, Configure.getKey(), “utf-8”).toUpperCase();//拼装生成服务器端验证的签名            // 因为微信回调会有八次之多,所以当第一次回调成功了,那么我们就不再执行逻辑了                       //根据微信官网的介绍,此处不仅对回调的参数进行验签,还需要对返回的金额与系统订单的金额进行比对等            if(sign.equals(map.get(“sign”))){                /**此处添加自己的业务逻辑代码start**/                  // bla bla bla….                /**此处添加自己的业务逻辑代码end**/                //通知微信服务器已经支付成功                resXml = “<xml>” + “<return_code><![CDATA[SUCCESS]]></return_code>”                        + “<return_msg><![CDATA[OK]]></return_msg>” + “</xml> “;            } else {                System.out.println(“微信支付回调失败!签名不一致”);            }        }else{            resXml = “<xml>” + “<return_code><![CDATA[FAIL]]></return_code>”                    + “<return_msg><![CDATA[报文为空]]></return_msg>” + “</xml> “;        }        System.out.println(resXml);        System.out.println(“微信支付回调数据结束”);        BufferedOutputStream out = new BufferedOutputStream(                response.getOutputStream());        out.write(resXml.getBytes());        out.flush();        out.close();    }}以上是统一下单的接口和微信支付成功的回调接口, 注意的如果springboot项目中的springsecurity,一定要注意放行回调地址, 否则回调会失败.5. 相关配置类以及工具类先上一下签名类:import com.thoughtworks.xstream.annotations.XStreamAlias;import org.apache.log4j.Logger;import java.lang.reflect.Field;import java.util.ArrayList;import java.util.Arrays;import java.util.Map;/** * 签名 * @author zuoliangzhu * */public class Signature {private static final Logger L = Logger.getLogger(Signature.class);/**     * 签名算法     * @param o 要参与签名的数据对象     * @return 签名     * @throws IllegalAccessException     */    public static String getSign(Object o) throws IllegalAccessException {        ArrayList<String> list = new ArrayList<String>();        Class cls = o.getClass();        Field[] fields = cls.getDeclaredFields();        for (Field f : fields) {            f.setAccessible(true);            if (f.get(o) != null && f.get(o) != “”) {            String name = f.getName();            XStreamAlias anno = f.getAnnotation(XStreamAlias.class);            if(anno != null)            name = anno.value();                list.add(name + “=” + f.get(o) + “&”);            }        }        int size = list.size();        String [] arrayToSort = list.toArray(new String[size]);        Arrays.sort(arrayToSort, String.CASE_INSENSITIVE_ORDER);        StringBuilder sb = new StringBuilder();        for(int i = 0; i < size; i ++) {            sb.append(arrayToSort[i]);        }        String result = sb.toString();        result += “key=” + Configure.getKey();        System.out.println(“签名数据:”+result);        result = MD5.MD5Encode(result).toUpperCase();        return result;    }    public static String getSign(Map<String,Object> map){        ArrayList<String> list = new ArrayList<String>();        for(Map.Entry<String,Object> entry:map.entrySet()){            if(entry.getValue()!=””){                list.add(entry.getKey() + “=” + entry.getValue() + “&”);            }        }        int size = list.size();        String [] arrayToSort = list.toArray(new String[size]);        Arrays.sort(arrayToSort, String.CASE_INSENSITIVE_ORDER);        StringBuilder sb = new StringBuilder();        for(int i = 0; i < size; i ++) {            sb.append(arrayToSort[i]);        }        String result = sb.toString();        result += “key=” + Configure.getKey();        //Util.log(“Sign Before MD5:” + result);        result = MD5.MD5Encode(result).toUpperCase();        //Util.log(“Sign Result:” + result);        return result;    }}然后配置类:public class Configure {    // 商户支付秘钥    private static String key = “xxxxxxNOBVmszxxxxxxxxxxxxxxxxxxx”;    //小程序ID        private static String appID = “wx42ebbFFFFFFFFFF”;    //商户号    private static String mch_id = “1499111112”;    // 小程序的secret    private static String secret = “xxxxxxxxxxxxxxxxxxx”;    public static String getSecret() {        return secret;    }    public static void setSecret(String secret) {        Configure.secret = secret;    }    public static String getKey() {        return key;    }    public static void setKey(String key) {        Configure.key = key;    }    public static String getAppID() {        return appID;    }    public static void setAppID(String appID) {        Configure.appID = appID;    }    public static String getMch_id() {        return mch_id;    }    public static void setMch_id(String mch_id) {        Configure.mch_id = mch_id;    }}然后工具类:import com.thoughtworks.xstream.XStream;import com.thoughtworks.xstream.io.xml.DomDriver;import com.thoughtworks.xstream.io.xml.XmlFriendlyNameCoder;import org.apache.http.HttpEntity;import org.apache.http.HttpResponse;import org.apache.http.client.ClientProtocolException;import org.apache.http.client.HttpClient;import org.apache.http.client.config.RequestConfig;import org.apache.http.client.methods.HttpPost;import org.apache.http.entity.StringEntity;import org.apache.http.impl.client.HttpClients;import org.apache.http.util.EntityUtils;import javax.net.ssl.X509TrustManager;import java.io.IOException;import java.security.KeyManagementException;import java.security.KeyStoreException;import java.security.NoSuchAlgorithmException;import java.security.UnrecoverableKeyException;import java.security.cert.CertificateException;public class HttpRequest {    //连接超时时间,默认10秒    private static final int socketTimeout = 10000;    //传输超时时间,默认30秒    private static final int connectTimeout = 30000;    /**     * post请求     * @throws IOException      * @throws ClientProtocolException      * @throws NoSuchAlgorithmException      * @throws KeyStoreException      * @throws KeyManagementException      * @throws UnrecoverableKeyException      */    public static String sendPost(String url, Object xmlObj) throws ClientProtocolException, IOException, UnrecoverableKeyException, KeyManagementException, KeyStoreException, NoSuchAlgorithmException {                        HttpPost httpPost = new HttpPost(url);        //解决XStream对出现双下划线的bug        XStream xStreamForRequestPostData = new XStream(new DomDriver(“UTF-8”, new XmlFriendlyNameCoder(“-_”, “_”)));        xStreamForRequestPostData.alias(“xml”, xmlObj.getClass());        //将要提交给API的数据对象转换成XML格式数据Post给API        String postDataXML = xStreamForRequestPostData.toXML(xmlObj);        //得指明使用UTF-8编码,否则到API服务器XML的中文不能被成功识别        StringEntity postEntity = new StringEntity(postDataXML, “UTF-8”);        httpPost.addHeader(“Content-Type”, “text/xml”);        httpPost.setEntity(postEntity);        //设置请求器的配置        RequestConfig requestConfig = RequestConfig.custom().setSocketTimeout(socketTimeout).setConnectTimeout(connectTimeout).build();        httpPost.setConfig(requestConfig);                HttpClient httpClient = HttpClients.createDefault();        HttpResponse response = httpClient.execute(httpPost);        HttpEntity entity = response.getEntity();        String result = EntityUtils.toString(entity, “UTF-8”);        return result;    }    /**     * 自定义证书管理器,信任所有证书     * @author pc     *     */    public static class MyX509TrustManager implements X509TrustManager {        @Override        public void checkClientTrusted(                java.security.cert.X509Certificate[] arg0, String arg1)                throws CertificateException {            // TODO Auto-generated method stub        }        @Override        public void checkServerTrusted(                java.security.cert.X509Certificate[] arg0, String arg1)                throws CertificateException {            // TODO Auto-generated method stub                    }        @Override        public java.security.cert.X509Certificate[] getAcceptedIssuers() {            // TODO Auto-generated method stub            return null;        }      }}MD5加密工具: import java.security.MessageDigest;/** * User: rizenguo * Date: 2014/10/23 * Time: 15:43 */public class MD5 {    private final static String[] hexDigits = {“0”, “1”, “2”, “3”, “4”, “5”, “6”, “7”,            “8”, “9”, “a”, “b”, “c”, “d”, “e”, “f”};    /**     * 转换字节数组为16进制字串     * @param b 字节数组     * @return 16进制字串     */    public static String byteArrayToHexString(byte[] b) {        StringBuilder resultSb = new StringBuilder();        for (byte aB : b) {            resultSb.append(byteToHexString(aB));        }        return resultSb.toString();    }    /**     * 转换byte到16进制     * @param b 要转换的byte     * @return 16进制格式     */    private static String byteToHexString(byte b) {        int n = b;        if (n < 0) {            n = 256 + n;        }        int d1 = n / 16;        int d2 = n % 16;        return hexDigits[d1] + hexDigits[d2];    }    /**     * MD5编码     * @param origin 原始字符串     * @return 经过MD5加密之后的结果     */    public static String MD5Encode(String origin) {        String resultString = null;        try {            resultString = origin;            MessageDigest md = MessageDigest.getInstance(“MD5”);            resultString = byteArrayToHexString(md.digest(resultString.getBytes()));        } catch (Exception e) {            e.printStackTrace();        }        return resultString;    }}预订单实体类:package com.xxxx.common.utils.wxUtil;/** * 预订单 *  * @author zuoliangzhu * */public class OrderInfo {    private String appid;// 小程序ID        private String mch_id;// 商户号    private String nonce_str;// 随机字符串    private String sign_type;//签名类型    private String sign;// 签名    private String body;// 商品描述    private String out_trade_no;// 商户订单号    private int total_fee;// 标价金额 ,单位为分    private String spbill_create_ip;// 终端IP    private String notify_url;// 通知地址    private String trade_type;// 交易类型    private String openid;//用户标识        public String getSign_type() {        return sign_type;    }    public void setSign_type(String sign_type) {        this.sign_type = sign_type;    }    public String getOpenid() {        return openid;    }    public void setOpenid(String openid) {        this.openid = openid;    }    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;    }}订单返回消息实体类package com.xxxx.common.utils.wxUtil;public class OrderReturnInfo {    private String return_code;    private String return_msg;    private String result_code;    private String appid;    private String mch_id;    private String nonce_str;    private String sign;    private String prepay_id;    private String trade_type;    public String getReturn_code() {        return return_code;    }    public void setReturn_code(String return_code) {        this.return_code = return_code;    }    public String getReturn_msg() {        return return_msg;    }    public void setReturn_msg(String return_msg) {        this.return_msg = return_msg;    }    public String getResult_code() {        return result_code;    }    public void setResult_code(String result_code) {        this.result_code = result_code;    }    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 getPrepay_id() {        return prepay_id;    }    public void setPrepay_id(String prepay_id) {        this.prepay_id = prepay_id;    }    public String getTrade_type() {        return trade_type;    }    public void setTrade_type(String trade_type) {        this.trade_type = trade_type;    }}随机数生成工具类:import java.util.Random;/** * 随机字符串生成 * @author zuoliangzhu * */public class RandomStringGenerator {    /**     * 获取一定长度的随机字符串     * @param length 指定字符串长度     * @return 一定长度的字符串     */    public static String getRandomStringByLength(int length) {        String base = “abcdefghijklmnopqrstuvwxyz0123456789”;        Random random = new Random();        StringBuffer sb = new StringBuffer();        for (int i = 0; i < length; i++) {            int number = random.nextInt(base.length());            sb.append(base.charAt(number));        }        return sb.toString();    }}签名实体类:import com.thoughtworks.xstream.annotations.XStreamAlias;/** * 签名信息 * @author zuoliangzhu * */public class SignInfo {    private String appId;//小程序ID        private String timeStamp;//时间戳        private String nonceStr;//随机串        @XStreamAlias(“package”)    private String repay_id;    private String signType;//签名方式        public String getAppId() {        return appId;    }    public void setAppId(String appId) {        this.appId = appId;    }    public String getTimeStamp() {        return timeStamp;    }    public void setTimeStamp(String timeStamp) {        this.timeStamp = timeStamp;    }    public String getNonceStr() {        return nonceStr;    }    public void setNonceStr(String nonceStr) {        this.nonceStr = nonceStr;    }    public String getRepay_id() {        return repay_id;    }    public void setRepay_id(String repay_id) {        this.repay_id = repay_id;    }    public String getSignType() {        return signType;    }    public void setSignType(String signType) {        this.signType = signType;    }}最后有一些乱七八糟的配置文件:import java.io.BufferedReader;import java.io.ByteArrayInputStream;import java.io.IOException;import java.io.InputStream;import java.io.InputStreamReader;import java.io.OutputStream;import java.io.UnsupportedEncodingException;import java.net.HttpURLConnection;import java.net.URL;import java.security.SignatureException;import java.util.ArrayList;import java.util.Collections;import java.util.HashMap;import java.util.Iterator;import java.util.List;import java.util.Map;import org.apache.commons.codec.digest.DigestUtils;import org.jdom.Document;import org.jdom.Element;import org.jdom.JDOMException;import org.jdom.input.SAXBuilder;public class PayUtil {    /**     * 签名字符串     * @param text 需要签名的字符串     * @param key 密钥     * @param input_charset 编码格式     * @return 签名结果     */    public static String sign(String text, String key, String input_charset) {        text = text + “&key=” + key;        return DigestUtils.md5Hex(getContentBytes(text, input_charset));    }    /**     * 签名字符串     *  @param text 需要签名的字符串     * @param sign 签名结果     * @param key 密钥     * @param input_charset 编码格式     * @return 签名结果     */    public static boolean verify(String text, String sign, String key, String input_charset) {        text = text + key;        String mysign = DigestUtils.md5Hex(getContentBytes(text, input_charset));        if (mysign.equals(sign)) {            return true;        } else {            return false;        }    }    /**     * @param content     * @param charset     * @return     * @throws SignatureException     * @throws UnsupportedEncodingException     */    public static byte[] getContentBytes(String content, String charset) {        if (charset == null || “”.equals(charset)) {            return content.getBytes();        }        try {            return content.getBytes(charset);        } catch (UnsupportedEncodingException e) {            throw new RuntimeException(“MD5签名过程中出现错误,指定的编码集不对,您目前指定的编码集是:” + charset);        }    }    private static boolean isValidChar(char ch) {        if ((ch >= ‘0’ && ch <= ‘9’) || (ch >= ‘A’ && ch <= ‘Z’) || (ch >= ‘a’ && ch <= ‘z’))            return true;        if ((ch >= 0x4e00 && ch <= 0x7fff) || (ch >= 0x8000 && ch <= 0x952f))            return true;// 简体中文汉字编码        return false;    }    /**     * 除去数组中的空值和签名参数     * @param sArray 签名参数组     * @return 去掉空值与签名参数后的新签名参数组     */    public static Map<String, String> paraFilter(Map<String, String> sArray) {        Map<String, String> result = new HashMap<String, String>();        if (sArray == null || sArray.size() <= 0) {            return result;        }        for (String key : sArray.keySet()) {            String value = sArray.get(key);            if (value == null || value.equals(“”) || key.equalsIgnoreCase(“sign”)                    || key.equalsIgnoreCase(“sign_type”)) {                continue;            }            result.put(key, value);        }        return result;    }    /**     * 把数组所有元素排序,并按照“参数=参数值”的模式用“&”字符拼接成字符串     * @param params 需要排序并参与字符拼接的参数组     * @return 拼接后字符串     */    public static String createLinkString(Map<String, String> params) {        List<String> keys = new ArrayList<String>(params.keySet());        Collections.sort(keys);        String prestr = “”;        for (int i = 0; i < keys.size(); i++) {            String key = keys.get(i);            String value = params.get(key);            if (i == keys.size() – 1) {// 拼接时,不包括最后一个&字符                prestr = prestr + key + “=” + value;            } else {                prestr = prestr + key + “=” + value + “&”;            }        }        return prestr;    }    /**     *     * @param requestUrl 请求地址     * @param requestMethod 请求方法     * @param outputStr 参数     */    public static String httpRequest(String requestUrl,String requestMethod,String outputStr) {        // 创建SSLContext        StringBuffer buffer = null;        try {            URL url = new URL(requestUrl);            HttpURLConnection conn = (HttpURLConnection) url.openConnection();            conn.setRequestMethod(requestMethod);            conn.setDoOutput(true);            conn.setDoInput(true);            conn.connect();            //往服务器端写内容            if (null != outputStr) {                OutputStream os = conn.getOutputStream();                os.write(outputStr.getBytes(“utf-8”));                os.close();            }            // 读取服务器端返回的内容            InputStream is = conn.getInputStream();            InputStreamReader isr = new InputStreamReader(is, “utf-8”);            BufferedReader br = new BufferedReader(isr);            buffer = new StringBuffer();            String line = null;            while ((line = br.readLine()) != null) {                buffer.append(line);            }            br.close();        }catch(Exception e){            e.printStackTrace();        }        return buffer.toString();    }    p

赞(0) 打赏
未经允许不得转载:E企盈小程序开发-热线:4006-838-530 » 踩坑:微信小程序支付流程(统一下单,支付回调)
分享到: 更多 (0)
E企盈小程序直播营销卖货系统
E企盈直播平台营销卖货系统

评论 抢沙发

E企盈小程序开发

联系我们联系我们

觉得文章有用就打赏一下文章作者

支付宝扫一扫打赏

微信扫一扫打赏