美文网首页
springboot[maven] & 微信小程序[1]支付-p

springboot[maven] & 微信小程序[1]支付-p

作者: 孙瑞锴 | 来源:发表于2019-04-06 02:48 被阅读0次

    1.借鉴

    微信支付开发者文档,还有很多其他的博客,十分感谢。

    2. 开始

    【
        具体的流程:
        1.小程序调用我们自己的创建订单接口,然后拼接参数发给微信,微信会返回给我们成功或失败,如果成功,按照微信开发文档拼接map参数返回给小程序[①]
        2:请求1中的接口返回给小程序一个map集合,[②]
        3.小程序将map发送到微信,[③]
        4.等待和处理微信回调[④]
    】                
    以上序号在下面有用到[①,②,③,④],谢谢搜狗输入法的支持.......
    

    1. 搭建一个springboot项目

    2. 几个依赖包

    <dependency>
        <groupId>com.github.wxpay</groupId>
        <artifactId>wxpay-sdk</artifactId>
        <version>0.0.3</version>
    </dependency>
    <dependency>
        <groupId>commons-httpclient</groupId>
        <artifactId>commons-httpclient</artifactId>
        <version>3.1</version>
    </dependency>
    <dependency>
        <groupId>org.apache.httpcomponents</groupId> 
        <artifactId>httpclient</artifactId>
        <version>4.5.3</version>
    </dependency>
    

    3. 后端准备

    3.1 配置信息

    
    # =============================================================================
    # =========================        微信小程序支付        ========================
    # =============================================================================
    # 小程序[mp -> mini program]
    # 小程序ID
    wx.pay.mp.appid=
    # 商户号
    wx.pay.mp.mch_id=
    # 加密ID - 商户
    wx.pay.mp.partnerkey=
    # 加密ID - 小程序
    wx.pay.mp.partnerkeyMp=
    # 终端IP
    wx.pay.mp.spbill_create_ip=127.0.0.1
    # 用户支付时的回调URL【 TODO 这里需要变更】
    wx.pay.mp.notify_url=http://ruihong.frpgz1.idcfengye.com/notify/wxNotify
    # 统一下单URL
    wx.pay.mp.wechatUnifiedOrderURL=https://api.mch.weixin.qq.com/pay/unifiedorder
    # 查询订单URL
    wx.pay.mp.wechatOrderQueryURL=https://api.mch.weixin.qq.com/pay/orderquery
    # 企业付款URL【用户提现】
    wx.pay.mp.wechatTransfersUrl=https://api.mch.weixin.qq.com/mmpaymkttransfers/promotion/transfers
    # 申请退款【取消订单】
    wx.pay.mp.wechatRefundUrl=https://api.mch.weixin.qq.com/secapi/pay/refund
    # =============================================================================
    

    3.2 springboot 配置类

    @Component
    @ConfigurationProperties(value = "wx.pay.mp")
    @Getter @Setter
    public class WeixinMiniProgramPayProperties
    {        
        private String appid;       
        private String mchId;        
        private String spbillCreateIp;        
        private String notifyUrl;        
        private String refundUrl;        
        private String partnerkey;        
        private String partnerkeyMp;        
        private String wechatUnifiedOrderURL;        
        private String wechatOrderQueryURL;        
        private String wechatTransfersUrl;        
        private String wechatRefundUrl;
    }
    

    3.3 创建订单

    [①,②][service] 返回的map就是要返给小程序的参数,控制器随意

    public interface WeixinService
    {
         /*** * 创建小程序订单 */
         Map createMiniProgramOrder(String logKey, /** 日志key */
                                    String orderNumber, /** 订单号 */
                                    String openId, /** 微信用户的openId */
                                    String fee, /** 费用,单位分*/
                                    String body /** 商品描述 */) throws Exception;
    
    
        /*** * 企业向个人付款【提现】 */
        Map enterprice2User(String logKey, String orderNumber, String openId, String fee, String body) throws Exception;
    
    
        /** * 申请退款 */
        Map refund(String logKey,
                   String refundOrderNumber, /** 申请退款时自己创建的订单号 */
                   String transactionId, /** 微信返回的交易ID */
                   String openId, /** 微信用户openId */
                   String fee /** 费用,单位分*/) throws Exception;
    
    }
    

    [impl][这里面有个httpclient,放后面吧part2中]

    import com.github.wxpay.sdk.WXPayUtil;
    import WeixinMiniProgramPayProperties;
    import WeixinService;
    import HttpClient;
    import org.slf4j.Logger;
    import org.slf4j.LoggerFactory;
    import org.springframework.beans.factory.annotation.Autowired;
    import org.springframework.stereotype.Component;
    import org.springframework.stereotype.Service;
    import java.util.*;
    
    @Service("weixinService")
    public class WeixinServiceImpl implements WeixinService
    {
        private static final Logger logger = LoggerFactory.getLogger(WeixinServiceImpl.class);
    
        @Autowired WeixinMiniProgramPayProperties weixinPayProperties;
    
        @Override
        public Map createMiniProgramOrder(String logKey,
                                                String orderNumber,
                                                String openId,
                                                String fee,
                                                String body) throws Exception
        {
            //1.参数封装
            Map param = new HashMap();
            param.put("appid", weixinPayProperties.getAppid());// 公众账号ID
            param.put("mch_id", weixinPayProperties.getMchId());// 商户
            param.put("nonce_str", WXPayUtil.generateNonceStr());// 随机字符串
            param.put("body", body); // 商品描述
            param.put("out_trade_no", orderNumber);// 交易订单号
            param.put("total_fee", fee); // 金额(分)
            param.put("spbill_create_ip", weixinPayProperties.getSpbillCreateIp()); // 终端IP
            param.put("notify_url", weixinPayProperties.getNotifyUrl()); // 通知地址
            param.put("openid", openId); // 用户openid
            param.put("trade_type", "JSAPI"); // 交易类型
            param.put("attach", body); // 附件说明
    
            logger.info(logKey + " weixinPayProperties" + weixinPayProperties);
    
            String sign = WXPayUtil.generateSignature(param, weixinPayProperties.getPartnerkey());
            param.put("sign", sign);
    
            logger.info(logKey + " weixinService#createMiniProgramOrder:" + param);
    
            HttpClient httpClient = new HttpClient(weixinPayProperties.getWechatUnifiedOrderURL());
            httpClient.setHttps(true);
            httpClient.setXmlParam(xml2String(param));
            httpClient.post(); String xmlResult = httpClient.getContent();
    
            Map<String, String> mapResult = WXPayUtil.xmlToMap(xmlResult);
    
            logger.info(logKey + " weixinService#createMiniProgramOrder.wxpay.mp.result:" + mapResult);
    
            return reSigned(logKey, mapResult.get("prepay_id"));
        }
    
        private String xml2String(Map parameters)
        {
            StringBuffer sb = new StringBuffer();
            sb.append("<xml>");
            Set es = parameters.entrySet();
            Iterator it = es.iterator();
            while (it.hasNext())
            {
                Map.Entry entry = (Map.Entry) it.next();
                String k = (String) entry.getKey();
                String v = entry.getValue()+"";
                if ("attach".equalsIgnoreCase(k) || "body".equalsIgnoreCase(k))
                {
                    sb.append("<" + k + ">" + "<![CDATA[" + v + "]]></" + k + ">");
                } else {
                    sb.append("<" + k + ">" + v + "</" + k + ">");
                }
            }
            sb.append("</xml>");
            return sb.toString();
        }
    
        private Map reSigned(String logKey, String prepay_id) throws Exception
        {
            Map map = new HashMap();
            map.put("appId", weixinPayProperties.getAppid());
            map.put("timeStamp", (System.currentTimeMillis()+"").substring(0, 10));
            map.put("nonceStr", WXPayUtil.generateNonceStr());
            map.put("package", "prepay_id=" + prepay_id);
            map.put("signType", "MD5");
            String sign = addSign(logKey, map);
            map.put("paySign", sign);
            logger.info(logKey + " weixinService#reSigned:" + map);
            return map;
        }
    
        private String addSign(String logKey, Map hashMap2Sign) throws Exception
        {
            StringBuffer sign = new StringBuffer();
            List<Map.Entry<Object, Object>> infoIds = new ArrayList<Map.Entry<Object, Object>>(hashMap2Sign.entrySet());
            Collections.sort(infoIds, new Comparator<Map.Entry<Object, Object>>()
            {
                public int compare(Map.Entry<Object, Object> o1, Map.Entry<Object, Object> o2)
                {
                     return (o1.getKey()).toString().compareTo((String) o2.getKey());
                }
            });
    
            for(int i = 0;i < infoIds.size();i ++)
            {
                String key = (String) infoIds.get(i).getKey();
                if(sign.length() == 0)
                {    
                    sign.append(key).append("=")
                        .append(hashMap2Sign.get(key).toString().toLowerCase());
                }
                else
                {
                    sign.append("&").append(key)
                        .append("=").append(hashMap2Sign.get(key));
                }
            }
            sign.append("&key="+weixinPayProperties.getPartnerkey());
            logger.info(logKey + " addSign:" + sign.toString()); return     
            WXPayUtil.MD5(sign.toString()).toUpperCase();
        }
    }
    

    3.4 微信回调类

    import com.github.wxpay.sdk.WXPayUtil;
    import org.apache.commons.lang.StringUtils;
    import org.springframework.web.bind.annotation.RequestMapping;
    import javax.servlet.http.HttpServletRequest;
    import javax.servlet.http.HttpServletResponse;
    import java.util.Map;import java.util.SortedMap;
    import java.util.TreeMap;
    
    @RestController
    @RequestMapping(value = "/notify")
    public class NotifyController
    
    {
        @RequestMapping("/wxNotify")
        public String wxNotify(HttpServletRequest request,
                                HttpServletResponse response) throws Exception
    
        {
            request.setCharacterEncoding("UTF-8");                 
            response.setCharacterEncoding("UTF-8");                 r
            esponse.setContentType("text/html;charset=UTF-8");                 
            response.setHeader("Access-Control-Allow-Origin", "*");
            StringBuilder sb = new StringBuilder();
            String line = "";
            try
            {
                while ((line = request.getReader().readLine()) != null)
                {
                        sb.append(line); 
                }
                request.getReader().close();
            } catch (Exception e)
            {
                e.printStackTrace();
                return xml("fail","xml获取失败");
            }
            String result = sb.toString();
            if (StringUtils.isEmpty(result))
            {
                return xml("fail","xml为空");
            }
            Map<String, String> stringStringMap = WXPayUtil.xmlToMap(result);
            String total_fee = stringStringMap.get("total_fee");// 获取订单金额
            String trade_type = stringStringMap.get("trade_type");//交易类型
            String return_code = stringStringMap.get("return_code");// SUCCESS/FAIL    
            String attach = stringStringMap.get("attach");// 附件说明(消费,充值)
            String transaction_id = stringStringMap.get("transaction_id");//微信支付订单号
            String out_trade_no = stringStringMap.get("out_trade_no");// 获取商户订单号
    
            if (!"SUCCESS".equalsIgnoreCase(return_code))
            {
               return xml("fail", "支付失败!");
            }
            // 尤其要注意的是要保证幂等性
            // 从订单表中查询出数据
            // 更新订单状态等等操作
            // 操作用户积分,余额
            return xml("SUCCESS", "OK");
        }
    
        //通过xml 发给微信消息
    
        public String xml(String return_code, String return_msg)
        {
            SortedMap<String, String> parameters = new TreeMap<String, String>();
            parameters.put("return_code", return_code);
            parameters.put("return_msg", return_msg); return "<xml><return_code><![CDATA[" + return_code + "]]>" + "</return_code><return_msg><![CDATA[" + return_msg + "]]></return_msg></xml>";
        }
    
    }
    

    相关文章

      网友评论

          本文标题:springboot[maven] & 微信小程序[1]支付-p

          本文链接:https://www.haomeiwen.com/subject/vuuliqtx.html