一:需求

满足公司在网页上达到直接微信扫码支付的需求

二:API官方文档

参考链接:https://pay.weixin.qq.com/wiki/doc/api/native.php?chapter=9_1

三:微信支付的过程(用户-商家-微信服务器)

四:代码实现

实体类: 参考链接:https://pay.weixin.qq.com/wiki/doc/api/native.php?chapter=9_1

1.统一下单请求参数

/*** 统一下单请求参数(必填)*/
@XmlRootElement <span>此处加注解是为了后台xmljie
public class UnifiedOrderRequest { private String appid;              //IDprivate String mch_id;              //商户号private String nonce_str;          //随机字符串private String sign;             //数字签名private String body;              //商品描述private String out_trade_no;      //商户订单private String total_fee;         //总金额private String spbill_create_ip;  //终端Ipprivate String notify_url;         //通知地址private String trade_type;        //交易类型public UnifiedOrderRequest(){};public UnifiedOrderRequest(String appid, String mch_id,String nonce_str, String sign, String body,String out_trade_no, String total_fee, String spbill_create_ip,String notify_url, String trade_type) {super();this.appid = appid;this.mch_id = mch_id;this.nonce_str = nonce_str;this.sign = sign;this.body = body;this.out_trade_no = out_trade_no;this.total_fee = total_fee;this.spbill_create_ip = spbill_create_ip;this.notify_url = notify_url;this.trade_type = trade_type;}
}

统一下单参数(非必须)
/*** 统一下单请求参数(非必填)*/
@XmlRootElement <span>此处加注解是为了xml解析</span>
public class UnifiedOrderRequestExt extends UnifiedOrderRequest{private String device_info;              //设备号private String detail;                     //商品详情private String attach;                    //附加数据private String fee_type;                  //货币类型private String time_start;                //交易起始时间private String time_expire;             //交易结束时间private String goods_tag;               //商品标记private String product_id;                //商品IDprivate String limit_pay;                 //指定支付方式private String openid;                      //用户标志public UnifiedOrderRequestExt(){super();}public UnifiedOrderRequestExt(String appid, String mch_id,String nonce_str, String sign, String body, String out_trade_no,String total_fee, String spbill_create_ip, String notify_url,String trade_type, String device_info, String detail,String attach, String fee_type, String time_start,String time_expire, String goods_tag, String product_id,String limit_pay, String openid) {super(appid, mch_id, nonce_str, sign, body, out_trade_no, total_fee,spbill_create_ip, notify_url, trade_type);this.device_info = device_info;this.detail = detail;this.attach = attach;this.fee_type = fee_type;this.time_start = time_start;this.time_expire = time_expire;this.goods_tag = goods_tag;this.product_id = product_id;this.limit_pay = limit_pay;this.openid = openid;}
}
3.订单返回参数
/*** 统一下单返回参数**/
<span>此处加注解是为了xml解析</span>
@XmlAccessorType(XmlAccessType.FIELD)@XmlRootElement(name = "UnifiedOrderRespose")@XmlType(propOrder={"return_code","return_msg","appid","mch_id","device_info","nonce_str","sign","result_code","err_code","err_code_des","trade_type","prepay_id","code_url"})public
class UnifiedOrderRespose {private String return_code; //返回状态码private String return_msg; //返回信息private String appid; //公众账号IDprivate String mch_id; //商户号private String device_info; //设备号private String nonce_str; //随机字符串private String sign; //数字签名private String
result_code; //业务结果private String err_code; //错误代码private String err_code_des; // 错误代码描述private String trade_type; //交易类型private String prepay_id; //预支付交易会话标致private String code_url; //二维码链接public UnifiedOrderRespose(){}public UnifiedOrderRespose(String return_code,
String return_msg,String appid, String mch_id, String device_info, String nonce_str,String sign, String result_code, String err_code,String err_code_des, String trade_type, String prepay_id,String code_url) {super();this.return_code = return_code;this.return_msg
= return_msg;this.appid = appid;this.mch_id = mch_id;this.device_info = device_info;this.nonce_str = nonce_str;this.sign = sign;this.result_code = result_code;this.err_code = err_code;this.err_code_des = err_code_des;this.trade_type = trade_type;this.prepay_id
= prepay_id;this.code_url = code_url;}

二:xml解析(二种解析类型,已封装,可直接使用)
import org.w3c.dom.Document;
import org.w3c.dom.Element;
import org.w3c.dom.Node;
import org.w3c.dom.NodeList;
public class XMLObjectConvertUtil {/*** 将xml文件转换为Map集合* @param String类型的xml* @return map集合*/public static Map<String, String> getMap(String xml) throws Exception{try{Map<String, String> maps = new HashMap<String, String>();DocumentBuilderFactory documentBuilderFactory = DocumentBuilderFactory.newInstance();DocumentBuilder documentBuilder = documentBuilderFactory.newDocumentBuilder();InputStream inputStream = new ByteArrayInputStream(xml.getBytes("utf-8"));Document document = documentBuilder.parse(inputStream);document.getDocumentElement().normalize();//获得所有的节点NodeList nodeList = document.getDocumentElement().getChildNodes();for (int i = 0; i < nodeList.getLength(); i++) {Node node = nodeList.item(i);//如果为标记节点 如 <username>if(node.getNodeType() == node.ELEMENT_NODE){Element e = (Element) node;//将节点名称与节点内容放进map集合中maps.put(e.getNodeName(),e.getTextContent());}}return maps;}catch(Exception e){e.printStackTrace();}return null;      }/*** 将Map集合转换成String类型的xml* @param maps* @return* @throws Exception*/public String getXml(Map<String, String> maps) throws Exception{DocumentBuilderFactory documentBuilderFactory = DocumentBuilderFactory.newInstance();DocumentBuilder documentBuilder = documentBuilderFactory.newDocumentBuilder();Document document = documentBuilder.newDocument();//创建根目录Element  root = document.createElement("xml");//添加根目录进文档document.appendChild(root);//遍历所有的keyfor(String key:maps.keySet()){//获得key所对应的valueString value= maps.get(key);if(value == null){value ="";}//去掉空格value = value.trim();//创建子节点Element filed = document.createElement(key);//将key所对应的value放入node中filed.appendChild(document.createTextNode(value));//将子节点放入根节点中root.appendChild(filed);}TransformerFactory transformerFactory = TransformerFactory.newInstance();Transformer transformer =transformerFactory.newTransformer();DOMSource domSource = new DOMSource(document);transformer.setOutputProperty(OutputKeys.ENCODING,"utf-8");transformer.setOutputProperty(OutputKeys.INDENT,"yes");StringWriter sw = new StringWriter();StreamResult sr = new StreamResult(sw);transformer.transform(domSource, sr);String output = sw.getBuffer().toString();return output;}/*** 将java对象转换成String类型的xml* @param obj* @return* @throws Exception*/public String getXml(Object obj) throws Exception{StringWriter sw = new StringWriter();JAXBContext context = JAXBContext.newInstance(obj.getClass());Marshaller mar = context.createMarshaller();//统一编码mar.setProperty(mar.JAXB_ENCODING, "utf-8");mar.setProperty(mar.JAXB_FORMATTED_OUTPUT, Boolean.TRUE);mar.marshal(obj, sw);return sw.toString();   }
}
四:现在实体类和转换方法都已经贴出。现在就是后台接口的编写了
package com.util;import java.io.BufferedOutputStream;
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.StringReader;
import java.io.StringWriter;
import java.net.HttpURLConnection;
import java.net.MalformedURLException;
import java.net.URL;
import java.util.HashMap;
import java.util.Iterator;
import java.util.Map;
import java.util.Map.Entry;
import java.util.Set;
import java.util.SortedMap;
import java.util.TreeMap;
import java.util.UUID;import javax.servlet.http.HttpServletResponse;
import javax.xml.bind.JAXBContext;
import javax.xml.bind.JAXBException;
import javax.xml.bind.Marshaller;
import javax.xml.bind.Unmarshaller;
import javax.xml.parsers.DocumentBuilder;
import javax.xml.parsers.DocumentBuilderFactory;
import javax.xml.parsers.ParserConfigurationException;import org.apache.struts2.ServletActionContext;
import org.w3c.dom.Document;
import org.w3c.dom.Element;
import org.w3c.dom.Node;
import org.w3c.dom.NodeList;
import org.xml.sax.SAXException;import com.bean.UnifiedOrderRequest;
import com.bean.UnifiedOrderRespose;
import com.google.zxing.BarcodeFormat;
import com.google.zxing.EncodeHintType;
import com.google.zxing.MultiFormatWriter;
import com.google.zxing.common.BitMatrix;
import com.sun.org.apache.xalan.internal.xsltc.runtime.Hashtable;public class MainAction {String orderId;HttpServletResponse response;String msg;/*** 创建二维码*/public void createCode(){//创建订单String orderInfo = createOrderInfo(orderId);if(orderInfo!=null){//得到统一下单 APIString codeUrl = httpOrder(orderInfo);if(codeUrl!=null){//利用 返回的预支付交易链接(codeUrl) 生成扫描的二维码try {int width =200; //宽200int height = 200; //高200String format = "jpg"; //图片格式//开始创建二维码Hashtable hs = new Hashtable();//设置编码格式hs.put(EncodeHintType.CHARACTER_SET, "utf-8");     //设置二维码BitMatrix bit = new MultiFormatWriter().encode(codeUrl, BarcodeFormat.QR_CODE, width, height);OutputStream out = null;out = ServletActionContext.getResponse().getOutputStream();MatrixToImageWriter.writeToStream(bit,format,out);out.flush();out.close();} catch (Exception e) {// TODO Auto-generated catch blocke.printStackTrace();}}}}/*** 调统一下单API*/private String httpOrder(String orderInfo) {//微信支付统一接口String url ="https://api.mch.weixin.qq.com/pay/unifiedorder";try {//连接微信统一支付urlHttpURLConnection conn = (HttpURLConnection) new URL(url).openConnection();//加入数据conn.setRequestMethod("POST");//打开传输输出流conn.setDoOutput(true);//获取输出流BufferedOutputStream buffer = new BufferedOutputStream(conn.getOutputStream());buffer.write(orderInfo.getBytes());buffer.flush();buffer.close();//获取输入流BufferedReader reader = new BufferedReader(new InputStreamReader(conn.getInputStream()));//接受数据String line = null; StringBuffer sb = new StringBuffer();//将输入流中的信息放在sb中while((line=reader.readLine())!=null){sb.append(line);};//解析xml成对象JAXBContext context = JAXBContext.newInstance(UnifiedOrderRespose.class);//反序列化成对象Unmarshaller unmarshaller = context.createUnmarshaller();//读取数据StringReader sr = new StringReader(sb.toString());//根据微信Demo 将xml转换成MapMap<String, String> ResponseMap = new  HashMap<String, String>();//创建文档类型 DocumentBuilderFactory dbf = DocumentBuilderFactory.newInstance();DocumentBuilder db = dbf.newDocumentBuilder();    //将获取到的xml放入输入流中InputStream in = new ByteArrayInputStream(sb.toString().getBytes("utf-8"));Document doc;doc = db.parse(in); NodeList nl = doc.getDocumentElement().getChildNodes();for (int i = 0; i < nl.getLength(); i++) {Node node = nl.item(i);if(node.getNodeType() == node.ELEMENT_NODE){Element e = (Element) node;ResponseMap.put(e.getNodeName(), e.getTextContent());}}/* 转换成UnifiedOrderRespose对象UnifiedOrderRespose unRespose = (UnifiedOrderRespose) unmarshaller.unmarshal(new File("C:/Users/Administrator/Workspaces/MyEclipse 10/weixinpay/WebRoot/xmls/Result.xml"));              UnifiedOrderRespose unRespose = (UnifiedOrderRespose) unmarshaller.unmarshal(sr);              System.out.println(unRespose.getReturn_code()+"|"+unRespose.getReturn_msg());unRespose.setReturn_code("SUCCESS");unRespose.setReturn_msg("SUCCESS");unRespose.setCode_url("www.baidu.com");*///如果请求成功返回 ,则返回支付链接if(null!=ResponseMap && "SUCCESS".equals(ResponseMap.get("return_code"))&& "SUCCESS".equals(ResponseMap.get("return_msg"))){return ResponseMap.get("code_url");}else{return null;}}catch (SAXException e) {// TODO Auto-generated catch blocke.printStackTrace();}catch (ParserConfigurationException e) {// TODO Auto-generated catch blocke.printStackTrace();} catch (JAXBException e) {// TODO Auto-generated catch blocke.printStackTrace();} catch (MalformedURLException e) {// TODO Auto-generated catch blocke.printStackTrace();} catch (IOException e) {// TODO Auto-generated catch blocke.printStackTrace();}return null;}/*** 生成订单,返回xml文件*/private String createOrderInfo(String orderId) {UnifiedOrderRequest un = new UnifiedOrderRequest();un.setAppid("xxxxxxxxxxxxx");//公众账号ID  un.setMch_id("xxxxxxxxx");//商户号  un.setNonce_str(UUID.randomUUID().toString().substring(0,30));//随机字符串       <span style="color:#ff0000;"><strong>说明2(见文末)</strong></span>  un.setBody("xxxxxx");//商品描述  un.setOut_trade_no(orderId);//商户订单号  un.setTotal_fee("10000");  //金额需要扩大100倍:1代表支付时是0.01  un.setSpbill_create_ip("xxxxxxxxxxxxx");//终端IP  un.setNotify_url("xxxxxxxxxxxxxx");//支付成功后,回调的地址  un.setSign(createSign(un));//签名un.setTrade_type("NATIVE");//JSAPI--公众号支付、NATIVE--原生扫码支付、APP--app支付try {//将订单对象转为xml格式StringWriter sw = new StringWriter();JAXBContext context = JAXBContext.newInstance(un.getClass());Marshaller mar = context.createMarshaller();mar.setProperty(mar.JAXB_ENCODING, "utf-8");mar.setProperty(mar.JAXB_FORMATTED_OUTPUT, Boolean.TRUE);mar.marshal(un, sw);/*将xml转换为对象JAXBContext context = JAXBContext.newInstance(UnifiedOrderRequest.class);  Unmarshaller unmarshaller = context.createUnmarshaller();  UnifiedOrderRequest unifiedOrderRequest = (UnifiedOrderRequest)unmarshaller.unmarshal(new StringReader("xml文件"));  */return sw.toString();} catch (JAXBException e) {// TODO Auto-generated catch blocke.printStackTrace();} return null;}/*** 生成数字签名*/private String createSign(UnifiedOrderRequest un) {//创建可排序的Map集合SortedMap<String, String> packageParms = new TreeMap<String, String>();packageParms.put("appid", un.getAppid());packageParms.put("body", un.getBody());packageParms.put("mch_id", un.getMch_id());packageParms.put("nonce_str", un.getNonce_str());packageParms.put("notify_url", un.getNotify_url());packageParms.put("out_trade_no", un.getOut_trade_no());packageParms.put("spbill_create_ip", un.getSpbill_create_ip());packageParms.put("trade_type", un.getTrade_type());packageParms.put("total_fee", un.getTotal_fee());StringBuffer sb = new StringBuffer();//按照字典排序Set se = packageParms.entrySet();//迭代器Iterator iterator = se.iterator();while(iterator.hasNext()){Map.Entry entry = (Entry) iterator.next();String k = (String) entry.getKey();String v = (String) entry.getValue();//为空不参与签名,参数名区分大小写if(null!=v && !"".equals(v)&& !"key".equals(k) && !"sign".equals(k)){sb.append(k+ "="+v+"&");}}/*拼接 key,设置路径:微信商户平台(pay.weixin.com)->账户设置->API安全-->秘钥设置 */sb.append("key="+"xxxxxxxxxxx");MD5Utile md5= new MD5Utile();String sign = md5.getMD5(sb.toString(),"utf-8");return sign;}public String getOrderId() {return orderId;}public void setOrderId(String orderId) {this.orderId = orderId;}}
看到这里,包括二维码的制作,与用户,服务器的交互都已完成。如有不懂,可以私信!

微信支付后台接口开发(扫码版)相关推荐

  1. 微信支付教程系列之扫码支付

    目录 (一)微信公众号开发之VS远程调试 (二)微信公众号开发之基础梳理 (三)微信公众号开发之自动消息回复和自定义菜单 (四)微信公众号开发之网页授权获取用户基本信息 (五)微信公众号开发之网页中及 ...

  2. C# 微信支付教程系列之扫码支付

    微信支付教程系列之扫码支付 今天,我们来一起探讨一下这个微信扫码支付.何为扫码支付呢?这里面,扫的码就是二维码了,就是我们经常扫一扫的那种二维码图片,例如,我们自己添加好友的时候,可以通过输入对方的微 ...

  3. 企业微信支付的接口开发总结

    涉及微信方面的开发,总是避免不了做微信支付.网上的总结繁杂而没有重点,看了摸不清思路,官方文档简单解决不了实际业务问题.于是根据业务需要写了一个微信支付接口,并做分享. 1.准备工作 1.1 登录微信 ...

  4. 消息称淘宝正测试微信支付 需要手动截图扫码支付

    3月26日消息,互联互通迎来新进展,有网友发现,在淘宝App下单后可以选择用微信支付了. 根据网友晒出的截图,在订单提交界面,用户可以通过淘宝给出的二维码进行微信支付.但需要先自己截图并手动打开微信扫 ...

  5. php 微信支付退款接口开发,微信支付退款功能开发

    第一次做微信的退款处理,特此标记一下 准备 appId 微信分配的公众账号ID(企业号corpid即为此appId) mch_id 微信支付分配的商户号 pay_secret 商户平台设置的秘钥:微信 ...

  6. 微信支付之pc端扫码支付

    支付不用说直接看文档:https://developers.weixin.qq.com/doc/oplatform/Website_App/WeChat_Login/Wechat_Login.html ...

  7. 微信公众号可通过现金红包接口发放微信支付现金红包(附开发教程)

    标签: 农历新年将至,支付宝红包打了一仗,微信在朋友圈屏蔽了它的分享,但单防守还不行,进攻才是最好的防守.昨日,微信支付现金红包接口正式开放,只需开通微信支付,即可接入现金红包.微信公众号也可以发放现 ...

  8. 支付宝开发 - 扫码支付

    一.支付场景 用户使用支付宝钱包上的"扫一扫"功能,扫码商户针对每个订单实时生成的订单二维码,并在手机端确认支付. 二.调用流程 图2.1 支付宝扫码支付调用流程 a. 商户系统调 ...

  9. 微信第三方登录接口开发

    微信登录接口开发须知 APP登录接口 PC网站登录接口 微信移动网页登录接口(又称微信公众号授权登录) 移动端非微信自带浏览不支持微信登录 微信移动网页登录接口(又称微信公众号授权登录) 先要与开放平 ...

最新文章

  1. 1019 数字黑洞 (20 分)(c语言)
  2. mysql数据库水平分割_数据库的水平分割和垂直分割
  3. MVC 模式/Servlet/JSP 编译原理剖析:Servlet 组件到底属于 MVC 模式的哪一层?
  4. Oracle SQL性能优化的40条军规
  5. linux下播放wma格式,Ubuntu 20.04中使Rhythmbox支持WMA格式文件播放
  6. Python知识点-hashlib模块
  7. 洛谷 P1040 加分二叉树
  8. 【笔记】Windows Sublime text安装json格式化插件SublimePrettyJson
  9. 使用adb命令解锁Android手机
  10. 网上购物系统设计类图
  11. 年会抽奖小游戏java_抽奖小游戏
  12. PPT中插入矢量图(以及从visio直接复制变模糊的处理方法)
  13. Win10电脑时间无法同步解决方法
  14. 技巧分享-电脑版微信如何登录多个账号
  15. QQ空间快速登录地址
  16. js实现点击切换checkbox背景图片
  17. CloudCompare使用说明
  18. Fotophire Toolkit(图片处理软件)v1.3.1中文版
  19. STC89c51利用esp8266发微信消息,POST例程
  20. JupyterLab 常用配置

热门文章

  1. 分享几个IP获取地理位置的API接口
  2. CLion 的 Debug 模式是怎么回事
  3. JUDE工具类图制作
  4. 真相为何竟如此难得 -- 《中国健康调查报告》
  5. 工业软件+无代码开发,国产软件崛起正当时
  6. 电子制作——锂电池大功率充电器
  7. 网上赚钱第一步是借鉴与学习
  8. 将一个word文档按一页或多页拆分成多个文档
  9. win10系统如何格式化
  10. 使用Visio画各种可视化的流程图之基本流程图和跨职能流程图