1. 程式人生 > 其它 >小程式專案微信支付

小程式專案微信支付

微信支付

去年開發的小程式支付專案,一直沒空梳理

需要申請商家支付服務

檢視開發文件流程

流程文件地址

流程:
->使用者在購物車頁點選支付
-> 這時調起我們寫的介面(使用者所攜帶的商品id,金額等等引數攜帶到伺服器)
-> 這時業務操作可以在這裡實現,比如生成訂單 -> 商戶後臺收到使用者支付單,(需要填上支付成功回撥介面)呼叫微信支付統一下單介面
-> 傳送post請求"統一下單介面"返回預支付id:prepay_id (需要把參與簽名的欄位名為appid,partnerid,prepayid,noncestr,timestamp,package 返回給前端 然後喚起支付頁面)
-> 前端支付成功後會走支付回撥介面

使用Java開發微信支付

demo工具類下載

https://pay.weixin.qq.com/wiki/doc/api/jsapi.php?chapter=11_1

開發介面如下

@Slf4j
@Api(tags = "app支付功能")
@RestController
@RequestMapping("/payment/")
public class PaymentController {

    @Resource
    private Environment environment;


    /*呼叫支付介面*/
    @ApiOperation(httpMethod = "POST", value = "呼叫支付介面")
    @RequestMapping(value = "prePay", method = RequestMethod.POST)
    public Map<String, Object> prePay(@RequestBody Pay pay,HttpServletRequest request){
        log.info("呼叫支付介面");
        // 返回引數
        Map<String, Object> resMap = new HashMap<>();
        //獲取當前請求ip地址
        String ip = request.getHeader("x-forwarded-for");
        if(ip == null || ip.length() == 0 || "unknown".equalsIgnoreCase(ip)){
            ip = request.getHeader("Proxy-Client-IP");
        }
        if(ip == null || ip.length() == 0 || "unknown".equalsIgnoreCase(ip)){
            ip = request.getHeader("WL-Proxy-Client-IP");
        }
        if(ip == null || ip.length() == 0 || "unknown".equalsIgnoreCase(ip)){
            ip = request.getRemoteAddr();
        }
        if(ip.indexOf(",")!=-1){
            String[] ips = ip.split(",");
            ip = ips[0].trim();
        }

        try {
            //業務需求

            //前臺傳輸一個openid--每個使用者對應小程式都會生成一個獨一無二的openid
            Map<String, Object> paraMap = new HashMap<>();
            //查詢房屋
            String body = "cs";
            // 封裝11個必需的引數
            //小程式ID
            paraMap.put("appid", environment.getProperty("wx.appId"));
            //商家ID
            paraMap.put("mch_id", environment.getProperty("wx.mchId"));
            //獲取隨機字串 Nonce Str
            paraMap.put("nonce_str", WXPayUtil.generateNonceStr());
            //商品名稱
            paraMap.put("body", body);
            //訂單號
            if (pay.getType()==MsgConsts.ZERO_STATUS) {
                //業務需求
//              DecimalFormat df = new DecimalFormat("0.00%");
                NumberFormat numberFormat  = NumberFormat.getPercentInstance();


                Double money = hpOrder.getTotalFee();//租金
                numberFormat.setMinimumFractionDigits(2);//保留到小數點後2位,不設定或者設定為0表示不保留小數

                //支付金額,單位:分,這邊需要轉成字串型別,否則後面的簽名會失敗
                String totalFee= BigDecimal.valueOf(money).multiply(new BigDecimal(100)).setScale(0,BigDecimal.ROUND_HALF_UP) + "";


                paraMap.put("total_fee",totalFee);
                paraMap.put("out_trade_no", hpOrder.getOrderNo());
            }else{
                Double money = obOrder.getTotalFee();
                //支付金額,單位:分,這邊需要轉成字串型別,否則後面的簽名會失敗
                String totalFee= BigDecimal.valueOf(money).multiply(new BigDecimal(100)).setScale(0,BigDecimal.ROUND_HALF_UP) + "";

                paraMap.put("total_fee",totalFee);
                paraMap.put("out_trade_no", obOrder.getOrderNo());
            }
            paraMap.put("spbill_create_ip", ip);
            // 此路徑是微信伺服器呼叫支付結果通知路徑
            paraMap.put("notify_url", "http://payment/callBack");
            paraMap.put("trade_type", "JSAPI");
            paraMap.put("openid", pay.getOpenid());
            String sign = WXPayUtil.generateSignature(paraMap,  environment.getProperty("wx.mchKey"));
            //生成簽名. 注意,若含有sign_type欄位,必須和signType引數保持一致。
            paraMap.put("sign", sign);
            //將所有引數(map)轉xml格式
            String xml = WXPayUtil.mapToXml(paraMap);
            log.info("xml=: "+xml);
            // 統一下單 https://api.mch.weixin.qq.com/pay/unifiedorder
            String unifiedorder_url = WXPayConstants.UNIFIEDORDER_URL;
            log.info("統一下單介面unifiedorder_url:"+unifiedorder_url);
            //傳送post請求"統一下單介面"返回預支付id:prepay_id
            String xmlStr = HttpClientUtil.doPostXml(unifiedorder_url, xml);

            //以下內容是返回前端頁面的json資料
            //預支付id
            String prepay_id = "";
            if (xmlStr.indexOf("SUCCESS") != -1) {
                Map<String, Object> map = WXPayUtil.xmlToMap(xmlStr);//XML格式字串轉換為Map
                //獲取封裝好的預支付id
                prepay_id =  map.get("prepay_id").toString();
                log.info("prepay_id_1=  "+prepay_id);
            }

            // 封裝所需6個引數調支付頁面
            Map<String, Object> payMap = new HashMap<String, Object>();
            payMap.put("appId", environment.getProperty("wx.appId"));
            payMap.put("timeStamp", WXPayUtil.getCurrentTimestamp()+"");//獲取當前時間戳,單位秒
            payMap.put("nonceStr", WXPayUtil.generateNonceStr());//獲取隨機字串 Nonce Str
            payMap.put("signType", "MD5");
            payMap.put("package", "prepay_id=" + prepay_id);
            //生成帶有 sign 的 XML 格式字串
            String paySign = WXPayUtil.generateSignature(payMap, environment.getProperty("wx.mchKey"));
            payMap.put("paySign", paySign);
            // 封裝正常情況返回資料
            resMap.put("success",true);
            resMap.put("payMap",payMap);
        } catch (Exception e) {
            //異常刪除訂單

            // 封裝異常情況返回資料
            log.info("呼叫統一訂單介面錯誤");
            resMap.put("success",false);
            resMap.put("message","呼叫統一訂單介面錯誤");
            e.printStackTrace();
        }
        return resMap;

    }




    /*支付成功回撥*/
    @ApiOperation(httpMethod = "POST", value = "呼叫支付成功回撥的地址")
    @RequestMapping(value = "callBack")
    public Result callBack(HttpServletRequest request, HttpServletResponse response){
        Result result = new Result();
        log.info("呼叫微信支付成功回撥");
        InputStream is = null;
        String resXml = "";
        try {
            is = request.getInputStream();//獲取請求的流資訊(這裡是微信發的xml格式所有隻能使用流來讀)
            String xml = WXPayUtil.inputStream2String(is);
            Map<String, Object> notifyMap = WXPayUtil.xmlToMap(xml);//將微信發的xml轉map
            if(notifyMap.get("return_code").equals("SUCCESS")){
                try {
                    //業務需求
                    resXml = "<xml>" + "<return_code><![CDATA[SUCCESS]]></return_code>"
                            + "<return_msg><![CDATA[OK]]></return_msg>" + "</xml> ";
                    BufferedOutputStream out = new BufferedOutputStream(response.getOutputStream());
                    out.write(resXml.getBytes());
                    out.flush();
                    out.close();
                    System.err.println("返回給微信的值:"+resXml.getBytes());
                    is.close();
                }catch (Exception e){
                    log.info("訂單狀態修改失敗");
                    result.setMsg("訂單狀態修改失敗");
                }
            }
        } catch (Exception e) {
            e.printStackTrace();
        }
        return result;
    }
}

支付引數

@Data
public class Pay {
    public String openid;
    private Long id;
    private Long customerViewingRecordId;
    private Long userId;
    private Integer type;
    private String ordersNo;
    private String frontIdCardUrl;
    private String backIdCardUrl;
    private String contractUrl;
    private String idCard;
    private String contactName;
    private String phoneNumber;
}