java服务器端微信、支付宝支付和退款功能
程序员文章站
2024-03-07 08:14:44
工作需要,写了服务器端的支付和退款功能,包含微信和支付宝,网上也有很多demo可以借鉴,我把我的代码放出来,写的比较简单,有问题的欢迎指正,大家一起学习。
微信支付需要调...
工作需要,写了服务器端的支付和退款功能,包含微信和支付宝,网上也有很多demo可以借鉴,我把我的代码放出来,写的比较简单,有问题的欢迎指正,大家一起学习。
微信支付需要调用微信的统一下单接口,而支付宝不用。
我写的时候微信和支付宝都单独写了一个工具类,来调用支付,给前端返回需要的数据。
ps:支付是可以不需要服务器端的,不过为了安全一点点,所以前端需要调起支付的字段都直接从服务器端返回,前端拿到字段直接调起支付就可以了。
map<string,string> map = new hashmap<string,string>(); switch (record.getchecktype()) { case 10: map = alipay.prepay(record.getamount(),out_trade_no); return responsedata.ok(map); case 20: map = wxpay.prepay(record.getamount(),out_trade_no); return responsedata.ok(map); }
10是支付宝支付,20是微信支付,map里存放前端需要的字段,直接返回给手机端
其中out_trade_no这个是商户自己生成的唯一订单号
public class wxpay { private static string url = string.format("https://api.mch.weixin.qq.com/pay/unifiedorder"); //统一下单 public static map<string,string> prepay(bigdecimal amount,string out_trade_no){ string entity = genproductargs(amount,out_trade_no); byte[] buf = util.httppost(url, entity); string content = new string(buf); map<string,string> xml=decodexml(content); return getrep(xml); } private static map<string, string> getrep(map<string, string> xml) { random random = new random(); list<namevaluepair> signparams = new linkedlist<namevaluepair>(); signparams.add(new basicnamevaluepair("appid", constants.app_id_wx)); signparams.add(new basicnamevaluepair("noncestr", md5.getmessagedigest(string.valueof(random.nextint(10000)).getbytes()))); // signparams.add(new basicnamevaluepair("package", "prepay_id="+xml.get("prepay_id"))); signparams.add(new basicnamevaluepair("package", "sign=wxpay")); signparams.add(new basicnamevaluepair("partnerid", constants.mch_id)); signparams.add(new basicnamevaluepair("prepayid", xml.get("prepay_id"))); signparams.add(new basicnamevaluepair("timestamp", string.valueof(system.currenttimemillis() / 1000))); xml.put("sign", genpackagesign(signparams)); for (int i = 0; i < signparams.size(); i++) { xml.put(signparams.get(i).getname(),signparams.get(i).getvalue()); } return removeelements(xml); } private static map<string, string> removeelements(map<string, string> xml) { xml.remove("appid"); xml.remove("mch_id"); xml.remove("nonce_str"); xml.remove("trade_type"); //xml.remove("partnerid"); xml.remove("prepay_id"); xml.remove("result_code"); xml.remove("return_code"); xml.remove("return_msg"); return xml; } private static string genproductargs(bigdecimal amount,string out_trade_no) { stringbuffer xml = new stringbuffer(); string noncestr = gennoncestr(); xml.append("</xml>"); list<namevaluepair> packageparams = new linkedlist<namevaluepair>(); packageparams.add(new basicnamevaluepair("appid", constants.app_id_wx)); 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", "填写服务器的支付回调路径")); packageparams.add(new basicnamevaluepair("out_trade_no",out_trade_no)); packageparams.add(new basicnamevaluepair("spbill_create_ip","127.0.0.1")); packageparams.add(new basicnamevaluepair("total_fee", string.valueof(amount.movepointright(2)))); // 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; } public static string gennoncestr() { random random = new random(); return md5.getmessagedigest(string.valueof(random.nextint(10000)).getbytes()); } public static string genpackagesign(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); string packagesign = md5.getmessagedigest(sb.tostring().getbytes()).touppercase(); return packagesign; } public static 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>"); return sb.tostring(); } }
public class alipay { public static map<string,string> prepay(bigdecimal payableamount,string out_trade_no){ //string orderinfo = getorderinfo("订单付款", "订单付款",out_trade_no,"0.01"); string orderinfo = getorderinfo("订单付款", "订单付款",out_trade_no,string.valueof(payableamount)); string sign = sign(orderinfo); try { /** * 仅需对sign 做url编码 */ sign = urlencoder.encode(sign, "utf-8"); } catch (unsupportedencodingexception e) { e.printstacktrace(); } /** * 完整的符合支付宝参数规范的订单信息 */ final string payinfo = orderinfo + "&sign=\"" + sign + "\"&" + getsigntype(); map<string,string> map = new hashmap<string, string>(); map.put("payinfo", payinfo); return map; } private static string getorderinfo(string subject, string body,string out_trade_no,string price) { // 签约合作者身份id string orderinfo = "partner=" + "\"" + constants.partner + "\""; // 签约卖家支付宝账号 orderinfo += "&seller_id=" + "\"" + constants.seller + "\""; // 商户网站唯一订单号 orderinfo += "&out_trade_no=" + "\"" + out_trade_no + "\""; // 商品名称 orderinfo += "&subject=" + "\"" + subject + "\""; // 商品详情 orderinfo += "&body=" + "\"" + body + "\""; // 商品金额 orderinfo += "&total_fee=" + "\"" + price + "\""; // 服务器异步通知页面路径 orderinfo += "¬ify_url=" + "\"" + "填写服务器的支付回调路径" + "\""; // 服务接口名称, 固定值 orderinfo += "&service=\"mobile.securitypay.pay\""; // 支付类型, 固定值 orderinfo += "&payment_type=\"1\""; // 参数编码, 固定值 orderinfo += "&_input_charset=\"utf-8\""; // 设置未付款交易的超时时间 // 默认30分钟,一旦超时,该笔交易就会自动被关闭。 // 取值范围:1m~15d。 // m-分钟,h-小时,d-天,1c-当天(无论交易何时创建,都在0点关闭)。 // 该参数数值不接受小数点,如1.5h,可转换为90m。 orderinfo += "&it_b_pay=\"30m\""; // extern_token为经过快登授权获取到的alipay_open_id,带上此参数用户将使用授权的账户进行支付 // orderinfo += "&extern_token=" + "\"" + extern_token + "\""; // 支付宝处理完请求后,当前页面跳转到商户指定页面的路径,可空 orderinfo += "&return_url=\"m.alipay.com\""; // 调用银行卡支付,需配置此参数,参与签名, 固定值 (需要签约《无线银行卡快捷支付》才能使用) // orderinfo += "&paymethod=\"expressgateway\""; return orderinfo; } private static string sign(string content) { return signutils.sign(content, constants.rsa_private); } private static string getsigntype() { return "sign_type=\"rsa\""; } }
退款部分
支付宝
string strresponse = null; alipaytraderefundresponse response = null; try { alipayclient alipayclient = new defaultalipayclient(url,constants.appid_alipay,constants.rsa_private,"json","utf-8",constants.rsa_public); alipaytraderefundrequest request = new alipaytraderefundrequest(); refundinfo alidata = new refundinfo(); alidata.setout_trade_no(out_trade_no); alidata.setrefund_amount(refund_amount); request.setbizcontent(json.tojsonstring(alidata)); response = alipayclient.sdkexecute(request); if (response.issuccess()) { strresponse="退款成功"; } else { strresponse="退款失败"; } return strresponse; } catch (exception e) { strresponse="退款出错"; } return strresponse;
微信
public class wxrefund { private static final string url = "https://api.mch.weixin.qq.com/secapi/pay/refund"; /** * 微信退款 * @param out_trade_no 商户订单号 * @param total_fee 总金额 * @param refund_fee 退款金额 * @return */ public static string dorefund(string out_trade_no,int total_fee,int refund_fee) { inputstream instream = null; keystore keystore = null; closeablehttpresponse response = null; closeablehttpclient httpclient = null; stringbuilder text = new stringbuilder(); string key = constants.mch_id; try { /** * 注意pkcs12证书 是从微信商户平台-》账户设置-》 api安全 中下载的 */ keystore = keystore.getinstance("pkcs12"); instream = wxrefund.class.getresourceasstream("/apiclient_cert.p12");//p12文件 /** * 此处要改 */ keystore.load(instream, key.tochararray());// 这里写密码..默认是mchid /** * 此处要改 */ sslcontext sslcontext = sslcontexts.custom().loadkeymaterial(keystore, key.tochararray())// 这里也是写密码的 .build(); // allow tlsv1 protocol only sslconnectionsocketfactory sslsf = new sslconnectionsocketfactory(sslcontext, new string[] { "tlsv1" }, null, sslconnectionsocketfactory.browser_compatible_hostname_verifier); httpclient = httpclients.custom().setsslsocketfactory(sslsf).build(); //=======================证书配置完成======================== httppost httppost = new httppost(url); string xmlstring = getrefunargs(out_trade_no,total_fee,refund_fee); httppost.setentity(new stringentity(xmlstring)); httppost.setheader("accept", "application/json"); httppost.setheader("content-type", "application/json"); response = httpclient.execute(httppost); httpentity entity = response.getentity(); if (entity != null) { bufferedreader bufferedreader = new bufferedreader(new inputstreamreader(entity.getcontent())); string str; while ((str = bufferedreader.readline()) != null) { text.append(str); } } entityutils.consume(entity); }catch(exception e){ }finally { if(instream != null){ try { instream.close(); } catch (ioexception e) { e.printstacktrace(); } } if(response != null){ try { response.close(); } catch (ioexception e) { e.printstacktrace(); } } if(httpclient != null){ try { httpclient.close(); } catch (ioexception e) { e.printstacktrace(); } } } map<string,string> map = wxpay.decodexml(text.tostring()); string return_msg = map.get("return_msg"); if ("ok".equals(return_msg) && "success".equals(map.get("return_code"))) { return "退款成功"; } return return_msg; } //设置请求参数的值 private static string getrefunargs(string out_trade_no,int total_fee,int refund_fee) { string nonce_str = wxpay.gennoncestr(); list<namevaluepair> packageparams = new linkedlist<namevaluepair>(); packageparams.add(new basicnamevaluepair("appid", constants.app_id_wx)); packageparams.add(new basicnamevaluepair("mch_id", constants.mch_id)); packageparams.add(new basicnamevaluepair("nonce_str", nonce_str)); packageparams.add(new basicnamevaluepair("op_user_id", constants.mch_id)); packageparams.add(new basicnamevaluepair("out_refund_no",out_trade_no)); packageparams.add(new basicnamevaluepair("out_trade_no",out_trade_no)); packageparams.add(new basicnamevaluepair("refund_fee", string.valueof(refund_fee))); packageparams.add(new basicnamevaluepair("total_fee", string.valueof(total_fee))); string sign = wxpay.genpackagesign(packageparams); packageparams.add(new basicnamevaluepair("sign", sign)); return wxpay.toxml(packageparams); } }
以上就是本文的全部内容,希望对大家的学习有所帮助,也希望大家多多支持。
上一篇: IO_处理流_字节缓冲流
下一篇: SpringMVC的源码解析