您好,欢迎来到三六零分类信息网!老站,搜索引擎当天收录,欢迎发信息

小程序后端用什么写

2024/3/30 6:56:30发布25次查看
这里本篇文章使用java进行小程序后端编写,由于公司前段时间要做小程序支付,所以这里把自己写的小程序后端支付controller记录下来,文档参考微信支付官方文档,地址:https://pay.weixin.qq.com/wiki/doc/api/wxa/wxa_api.php?chapter=7_3&index=1。
推荐课程:java教程。
废话不多说,直接上代码:
paycontroller
@api(tags = 支付模块)@restcontroller@requestmapping()public class paycontroller {    @apioperation(value = 请求支付接口)    @requestmapping(value = /wxpay, method = requestmethod.post)    public jsonobject wxpay(httpservletrequest request) {        try {            //生成的随机字符串            string nonce_str = getrandomstringbylength(32);            //商品名称            string body = 测试商品名称;            //获取客户端的ip地址            string spbill_create_ip = getipaddr(request);            //组装参数,用户生成统一下单接口的签名            map<string, string> packageparams = new hashmap<>();            packageparams.put(appid, wechatconfig.appid);            packageparams.put(mch_id, wechatconfig.mch_id);            packageparams.put(nonce_str, nonce_str);            packageparams.put(body, body);            packageparams.put(out_trade_no, payorderid + );//商户订单号,自己的订单id            packageparams.put(total_fee, 100 + );//支付金额,这边需要转成字符串类型,否则后面的签名会失败            packageparams.put(spbill_create_ip, spbill_create_ip);            packageparams.put(notify_url, wechatconfig.notify_url);//支付成功后的回调地址            packageparams.put(trade_type, wechatconfig.tradetype);//支付方式            packageparams.put(openid, openid + );//用户的openid,自己获取            string prestr = payutil.createlinkstring(packageparams); // 把数组所有元素,按照“参数=参数值”的模式用“&”字符拼接成字符串            //md5运算生成签名,这里是第一次签名,用于调用统一下单接口            string mysign = payutil.sign(prestr, wechatconfig.key, utf-8).touppercase();            //拼接统一下单接口使用的xml数据,要将上一步生成的签名一起拼接进去            string xml = <xml> + <appid> + wechatconfig.appid + </appid>                    + <body><![cdata[" + body + "]]></body>                    + <mch_id> + wechatconfig.mch_id + </mch_id>                    + <nonce_str> + nonce_str + </nonce_str>                    + <notify_url> + wechatconfig.notify_url + </notify_url>                    + <openid> + openid + </openid>                    + <out_trade_no> + payorderid + </out_trade_no>                    + <spbill_create_ip> + spbill_create_ip + </spbill_create_ip>                    + <total_fee> + 100 + </total_fee>//支付的金额,单位:分                    + <trade_type> + wechatconfig.tradetype + </trade_type>                    + <sign> + mysign + </sign>                    + </xml>;            //调用统一下单接口,并接受返回的结果            string result = payutil.httprequest(wechatconfig.pay_url, post, xml);            // 将解析结果存储在hashmap中            map map = payutil.doxmlparse(result);            string return_code = (string) map.get(return_code);//返回状态码            string result_code = (string) map.get(result_code);//返回状态码            map<string, object> response = new hashmap<string, object>();//返回给小程序端需要的参数            if (return_code == success && return_code.equals(result_code)) {                string prepay_id = (string) map.get(prepay_id);//返回的预付单信息                response.put(noncestr, nonce_str);                response.put(package, prepay_id= + prepay_id);                long timestamp = system.currenttimemillis() / 1000;                response.put(timestamp, timestamp + );//这边要将返回的时间戳转化成字符串,不然小程序端调用wx.requestpayment方法会报签名错误                //拼接签名需要的参数                string stringsigntemp = appid= + wechatconfig.appid + &noncestr= + nonce_str + &package=prepay_id= + prepay_id + &signtype=md5×tamp= + timestamp;                //再次签名,这个签名用于小程序端调用wx.requesetpayment方法                string paysign = payutil.sign(stringsigntemp, wechatconfig.key, utf-8).touppercase();                response.put(paysign, paysign);            }            response.put(appid, wechatconfig.appid);            return response.succ(response);        } catch (exception e) {            e.printstacktrace();        }        return null;    }    //这里是支付回调接口,微信支付成功后会自动调用    @requestmapping(value = /wxnotify, method = requestmethod.post)    public void wxnotify(httpservletrequest request, httpservletresponse response) throws exception {        bufferedreader br = new bufferedreader(new inputstreamreader(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 = ;        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 prestr = payutil.createlinkstring(validparams);             //根据微信官网的介绍,此处不仅对回调的参数进行验签,还需要对返回的金额与系统订单的金额进行比对等            if (payutil.verify(prestr, (string) map.get(sign), wechatconfig.key, utf-8)) {                /**此处添加自己的业务逻辑代码start**/                                //注意要判断微信支付重复回调,支付成功后微信会重复的进行回调                                /**此处添加自己的业务逻辑代码end**/                //通知微信服务器已经支付成功                resxml = <xml> + <return_code><![cdata[success]]></return_code>                        + <return_msg><![cdata[ok]]></return_msg> + </xml> ;            }        } else {            resxml = <xml> + <return_code><![cdata[fail]]></return_code>                    + <return_msg><![cdata[报文为空]]></return_msg> + </xml> ;        }        bufferedoutputstream out = new bufferedoutputstream(                response.getoutputstream());        out.write(resxml.getbytes());        out.flush();        out.close();    }    //获取随机字符串    private 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(); } //获取ip private string getipaddr(httpservletrequest request) { string ip = request.getheader("x-forwarded-for"); if (stringutils.isnotempty(ip) && !"unknown".equalsignorecase(ip)) { //多次反向代理后会有多个ip值,第一个ip才是真实ip int index = ip.indexof(","); if (index != -1) { return ip.substring(0, index); } else { return ip; } } ip = request.getheader("x-real-ip"); if (stringutils.isnotempty(ip) && !"unknown".equalsignorecase(ip)) { return ip; } return request.getremoteaddr(); }}
上面代码用到了payutil和wechatconfig这两个类,一个是配置类,一个是工具类,代码如下:
payutil
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 java.security.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<>(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(); } public static string urlencodeutf8(string source) { string result = source; try { result = java.net.urlencoder.encode(source, "utf-8"); } catch (unsupportedencodingexception e) { // todo auto-generated catch block e.printstacktrace(); } return result; } /** * 解析xml,返回第一级元素键值对。如果第一级元素有子节点,则此节点的值是子节点的xml数据。 * * @param strxml * @return * @throws org.jdom2.jdomexception * @throws ioexception */ public static map doxmlparse(string strxml) throws exception { if (null == strxml || "".equals(strxml)) { return null; } map m = new hashmap(); inputstream in = string2inputstream(strxml); saxbuilder builder = new saxbuilder(); document doc = builder.build(in); element root = doc.getrootelement(); list list = root.getchildren(); iterator it = list.iterator(); while (it.hasnext()) { element e = (element) it.next(); string k = e.getname(); string v = ""; list children = e.getchildren(); if (children.isempty()) { v = e.gettextnormalize(); } else { v = getchildrentext(children); } m.put(k, v); } //关闭流 in.close(); return m; } /** * 获取子结点的xml * * @param children * @return string */ public static string getchildrentext(list children) { stringbuffer sb = new stringbuffer(); if (!children.isempty()) { iterator it = children.iterator(); while (it.hasnext()) { element e = (element) it.next(); string name = e.getname(); string value = e.gettextnormalize(); list list = e.getchildren(); sb.append("<" + name + ">);                if (!list.isempty()) {                    sb.append(getchildrentext(list));                }                sb.append(value);                sb.append(</" + name + ">);            }        }        return sb.tostring();    }    public static inputstream string2inputstream(string str) {        return new bytearrayinputstream(str.getbytes());    }}
wechatconfig
public class wechatconfig {    //小程序appid    public static final string appid = ;    //微信支付的商户id    public static final string mch_id = ;    //微信支付的商户密钥    public static final string key = ;    //支付成功后的服务器回调url,这里填paycontroller里的回调函数地址    public static final string notify_url = ;    //签名方式,固定值    public static final string signtype = md5;    //交易类型,小程序支付的固定值为jsapi    public static final string tradetype = jsapi;    //微信统一下单接口地址    public static final string pay_url = https://api.mch.weixin.qq.com/pay/unifiedorder;}
在刚刚开始接触小程序支付的时候,也觉得比较的棘手,因为自己并没有写过支付相关的代码。后来通过百度查找资料和阅读官方文档,最后把这个支付的controller完成了。最后,一定要多读几遍官方文档,然后结合paycontroller的代码去看,就会发现其实支付也不是很难。
以上就是小程序后端用什么写的详细内容。
该用户其它信息

VIP推荐

免费发布信息,免费发布B2B信息网站平台 - 三六零分类信息网 沪ICP备09012988号-2
企业名录 Product