Micro-channel payment wxpay - a second movable end section app - java backend code

It needs a total of 5

1.pom, add the following dependent

<dependency>
   <groupId>com.github.wxpaygroupId>
   <artifactId>wxpay-sdkartifactId>
   <version>0.0.3version>
dependency>

2. configuration file (folder):

WxpayConfig.properties

# Micro-channel payment arrangement 
# mobile end AppID 
APP_ID = wx3d3c125230d2ba ** 

# merchant number 
BUSINESS_CODE = 153 982 *** 

# keys --sign obtain required in Account Center -> api security --api keys set 
API_KEY = gin201907 * ********** 

APIV3_KEY = GIN2 ******* 

# signature type HMAC-SHA256 and MD5, the default is MD5 
sign_type = MD5 

# certificates address 
PEM_ADDRESS = /wxConfig/**/apiclient_cert.p12 

# asynchronous notification address (Note that you must be outside the network) 
notify_url = HTTP: // *** / wxAppPay / the notify 


# number of public appID - to be determined --- 
#GZH_APP_ID = wxcfe45ec ****

While another folder in the same directory certificate, micro-channel pay part of the function requires a certificate

3. The sign of the generated class util: WxMD5Util

import java.io.UnsupportedEncodingException;
import java.security.MessageDigest;
import java.security.NoSuchAlgorithmException;
import java.util.Arrays;
import java.util.Map;
import java.util.Set;

/**
 * Created by Mafy on 2019/7/9.
 * 该类是生成签名用
 */
public class WxMD5Util {

    public static String getSign(Map data) throws Exception {
        WXConfigUtil config = WXConfigUtil.initWXconfigUtil();
        Set keySet = data.keySet();
        String[] keyArray = keySet.toArray(new String[keySet.size()]);
        Arrays.sort(keyArray);
        StringBuilder sb = new StringBuilder();
        for (String k : keyArray) {
            if (k.equals(WXPayConstants.FIELD_SIGN)) {
                continue;
            }
            if (data.get(k).trim().length() > 0) // 参数值为空,则不参与签名
                sb.append(k).append("=").append(data.get(k).trim()).append("&");
        }
        sb.append("key=").append(config.getKey());
        MessageDigest md = null;
        try {
            md = MessageDigest.getInstance("MD5");
        } catch (NoSuchAlgorithmException e) {
            e.printStackTrace();
        }
        byte[] array = new byte[0];
        try {
            array = md.digest(sb.toString().getBytes("UTF-8"));
        } catch (UnsupportedEncodingException e) {
            e.printStackTrace ();
        }
        StringBuilder sb2 = new StringBuilder();
        for (byte item : array) {
            sb2.append(Integer.toHexString((item & 0xFF) | 0x100).substring(1, 3));
        }
        return sb2.toString().toUpperCase();
    }
}

4. Get profile configuration class - there singleton pattern

import com.github.wxpay.sdk.WXPayConfig;
import org.springframework.util.ObjectUtils;

import java.io.*;
import java.util.Properties;

/**
 * Created by Mafy on 2019/7/9.
 */
public class WXConfigUtil implements WXPayConfig{
    Properties properties= null;
    private byte[] certData;

    private static WXConfigUtil wxConfigUtil = new WXConfigUtil();

    public static WXConfigUtil initWXconfigUtil(){
        return wxConfigUtil;
    }

    private WXConfigUtil() {
        String certPath = PropertiesUtil.class.getResource(getProperties().getProperty("PEM_ADDRESS")).getPath();//从微信商户平台下载的安全证书存放的路径
        InputStream certStream = null;
        try {
            File file = new File(certPath);
            certStream = new FileInputStream(file);
            this.certData = new byte[(int) file.length()];
            certStream.read(this.certData);

        } catch (IOException e) {
            e.printStackTrace();
        }finally {
            if(!ObjectUtils.isEmpty(certStream)){
                try {
                    certStream.close();
                } catch (IOException e) {
                    e.printStackTrace();
                }
            }
        }
    }

    @Override
    public String getAppID() {
        return getProperties().getProperty("APP_ID");
    }

    //parnerid,商户号
    @Override
    public String getMchID() {
        return getProperties().getProperty("BUSINESS_CODE");
    }

    @Override
    public String getKey() {
        return getProperties().getProperty("API_KEY");
    }

    @Override
    public InputStream getCertStream() {
        ByteArrayInputStream certBis = new ByteArrayInputStream(this.certData);
        return certBis;
    }

    @Override
    public int getHttpConnectTimeoutMs() {
        return 8000;
    }

    @Override
    public int getHttpReadTimeoutMs() {
        return 10000;
    }

    Properties getProperties() {
        if(null == properties) {
            properties = PropertiesUtil.getProperties("/wxConfig/WxpayConfig.properties");
        }
        return properties;
    }
}

5. Call controller interface payment: WxAppPayController

import com.alibaba.fastjson.JSONObject;
import com.github.wxpay.sdk.WXPay;
import com.github.wxpay.sdk.WXPayUtil;
import com.xinlianpu.util.PropertiesUtil;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.stereotype.Controller;
import org.springframework.web.bind.annotation.RequestBody;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RequestMethod;
import org.springframework.web.bind.annotation.ResponseBody;

import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.io.BufferedReader;
import java.io.IOException;
import java.io.InputStream;
java.io.InputStreamReader Import; 
Import java.util.HashMap; 
Import java.util.Map; 
Import java.util.Properties; 

/ ** 
 * the Created by MAFy ON 2019/7/9. 
 * / 
@Controller 
@ResponseBody 
@ RequestMapping ( "/ wxAppPay") 
public class WxAppPayController { 

    static the Properties Properties = null; 

    Final static Logger Logger = LoggerFactory.getLogger (WxAppPayController.class); 

// @Resource 
// Private wxPayService wxPayService; 

    // asynchronous notification address (note must be extranet) 
    / ** 
     * unified orders - no certificate
    public static final String NOTIFY_URL = getProperties().getProperty("NOTIFY_URL");
    // transaction type, JSAPI - JSAPI pay (or applet payment), NATIVE - Native payment, APP - app payments, MWEB - H5 pay 
    public static TRADE_TYPE_APP Final String = "APP"; 


     * includes generating a pre-pay orders -> order generation -> return to the front-end order data 
     * official document: HTTPS: //pay.weixin.qq.com/wiki/doc/api/app/app.php Chapter 9_1 =? 
     * @param jsonObject 
     * @ return 
     * @throws Exception 
     * / 
    @ RequestMapping (value = "/ the Pay", Method, = RequestMethod.POST) 
// public the Map wxPay (@RequestParam (value = "userId") String user_id, @RequestParam (value = "totalFee") total_fee String) throws Exception { 
    public DataResponse wxPayUnEncryption (@RequestBody the jSONObject jsonObject) throws Exception { 
        logger.info ( "single payment, app pass over the parameter: {}", jsonObject);

        DataResponse = DataResponse.success DataResponse ();  
// String user_id = TokenManager.getUserId ();
        String user_id = "123";
// String total_fee = jsonObject.getString ( "totalFee"); // total value 
        String total_fee = "1"; // total amount - points 
        String spbillCreateIp = jsonObject.getString ( "spbillCreateIp "); // click on the button of the machine to pay ip 
// spbillCreateIp String =" 0.01 "; // click on the button of the machine to pay ip 


        the Map the Map = null; 
        the try { 
// the attach String =" {\ "user_id \": \ "" + user_id + "\ "} "; // extension field is returned as 
            String attach =" extension field "; // extension field is returned as 
            // request pre-payment orders 
            Map result = dounifiedOrder (attach, total_fee , spbillCreateIp ); 
            logger.info ( "before the next single, pre-paid return information: {}", JSONObject.toJSON (result)); 
            whether it can be determined // change the order of data correctly prepaid 
            after // pre-payment orders generated with the signature of the client your payment information 
            map = new HashMap <> ();

            // returns APP-side data 
            // participate in the signature tune from the field and have to pay only 6, respectively appid, partnerid, prepayid, package, noncestr and timestamp, and must be lowercase --- start--
            map.put ( "AppID", result.get ( "AppID")); 
            map.put ( "partnerid", result.get ( "mch_id")); 
            map.put ( "prepayid", result.get ( "prepay_id ")); 
            map.put (" Package "," Sign = WXPay "); 
            map.put (" noncestr ", result.get (" nonce_str ")); 
            String signTimstamp = String.valueOf (System.currentTimeMillis () / 1000); 
            map.put ( "timestamp", signTimstamp); // seconds 
            // participate transfer payments from the signature field and there are only six, respectively appid, partnerid, prepayid, package, noncestr and timestamp, and requires lowercase end-- --- 


            the Map = new new mobileParam the HashMap <> ();mch_id"));
            mobileParam.put("prepayId", result.get("prepay_id"));
            mobileParam.put ( "for appId", result.get ( "AppID"));
            mobileParam.put ( "partnerId", result.get ( "mch_id"));
            mobileParam.put ( "packageValue", "Sign = WXPay"); //? ? ? 
            mobileParam.put ( "nonceStr", result.get ( "nonce_str")); 
            mobileParam.put ( "timeStamp", signTimstamp); // seconds 
            to return here when // ---- Do not use request pre-payment orders signature ------- 
            mobileParam.put ( "Sign", WxMD5Util.getSign (Map)); 
            mobileParam.put ( "extData", the attach); 
            logger.info ( "pay return parameter: {}", JSONObject. the toJSONString (Map)); 
            logger.info ( "the return movement end parameter: {}", JSONObject.toJSONString (mobileParam)); 
            dataResponse.setData (mobileParam); 
        } the catch (Exception E) { 
            return DataResponse.failure (); 
        } 
        Return dataResponse; 
    } 


    / **
     * Micro-channel interfaces Refund - refund 
     * @param jsonObject 
     * @return 
     * / 
    public DataResponse wxRefund (@RequestBody the JSONObject jsonObject) { 
        DataResponse Model DataResponse.success = (); 
        String = jsonObject.getString the orderId ( "the orderId"); // order ID 
        the try { 
            WXConfigUtil WXConfigUtil.initWXconfigUtil config = (); 
            wXPay wxpay = new new wXPay (config); 
            the Map Data new new = the HashMap <> (); 


            the Map = Refund wxpay.refund (Data); 
        } the catch (Exception E) {
            e.printStackTrace();
        } 

        Return Model; 
    } 



    / ** 
     * payment asynchronous result notification, we passed when requesting pre-payment orders address - no parameters 
     * official document: https: //pay.weixin.qq.com/wiki/doc/api /app/app.php?chapter=9_7&index=3 
     * / 
    @RequestMapping (value = "/ Notify", Method RequestMethod.GET = {,} RequestMethod.POST) 
    public String wxPayNotifyUnEncryption (the HttpServletRequest Request, the HttpServletResponse Response) { 
        String = resXml ""; 
        the try { 
            InputStream request.getInputStream inputStream = (); 
            // converted into the InputStream xmlString to 
            the BufferedReader Reader the BufferedReader new new = (the InputStreamReader new new (inputStream)); 
            the StringBuilder the StringBuilder new new SB = ();
            Line = null String; 
            the try { 
                while ((line = reader.readLine()) != null) {
                    sb.append(line + "\n");
                } 
            } the catch (IOException E) { 
                System.out.println (e.getMessage ()); 
            } {the finally 
                the try { 
                    inputStream.close (); 
                } the catch (IOException E) { 
                    e.printStackTrace ( ); 
                } 
            } 
            resXml sb.toString = (); 
            String Result = PAYBACK (resXml); 
            return Result; 
        } the catch (Exception E) { 
            logger.info ( "micro-channel mobile payment failed:" + e.getMessage ()); 
            the System .out.println ( "micro-channel mobile payment failure:" + e.getMessage ());
            The Result = String "" + "" + "" + ""; 
            return the Result; 
        } 
    } 


    / ** 
     * official SDK calls to obtain pre-payment orders and other parameters 
     * 
     * @param The attach additional parameters 
     * @param total_fee total price 
     * @return 
     * Exception @throws 
     * / 
    public dounifiedOrder the Map (the attach String, String total_fee, String spbillCreateIp) throws Exception { 
        logger.info ( "call into sdk official method parameters: {}, {}", the attach, total_fee); 
        the Map returnMap is new new = the HashMap <> (); 
        WXConfigUtil WXConfigUtil.initWXconfigUtil config = (); 
        WXPay wxpay = new new WXPay (config); 
        the Map Data new new = the HashMap <> ();
        // generate business order number, can not be repeated 
        String out_trade_no = "wxpay "+ System.currentTimeMillis (); 

        data.put (" AppID ", config.getAppID ()); // application ID 
        data.put (" mch_id ", config.getMchID ()); // number of merchants
        data.put ( "nonce_str", WXPayUtil.generateNonceStr ( )); // random string not longer than 32 bits. Recommended random number generation algorithm 
        String body = "New Face micro-channel payment orders - Test -" + System.currentTimeMillis (); 
        data.put ( "body", body); // Product Description 
        data.put ( "out_trade_no", out_trade_no) ; // merchant Order number 
        data.put ( "total_fee", total_fee) ; // total amount 
        data.put ( "spbill_create_ip", spbillCreateIp) ; // machine IP address of your server --- pay for a click IP 
        data.put ( "notify_url", nOTIFY_URL); // asynchronous notification address (Note that you must be outside the network) 
        data.put ( "trade_type", TRADE_TYPE_APP); // transaction type 
        data.put ( "attach", attach) ; // additional data, as they are returned in the query API and payment notification, this field is mainly used to customize the data carried by the merchant orders 
        String sign1 = WxMD5Util.getSign (the data);
        data.put ( "sign", sign1) ; // signature 
                returnMap.put (" AppID ",response.get("appid"));
        logger.info ( "single reservation generated parameters, {}", JSONObject.toJSON (Data)); 
        the try { 
            // use the official API requests prepaid orders 
            the Map wxpay.unifiedOrder Response = (Data); 
            logger.info ( "preorder returns the result, {} ", JSONObject.toJSON (Response)); 
            String response.get the returnCode = (" the return_code "); // Get return code 
            // if the return code is SUCCESS, it returns a result_code, then the result_code is judged 
            if (returnCode.equals ( "SUCCESS") ) {// return the following five main parameters 
                logger.info ( "return result preorder SUCCESS, {}", JSONObject.toJSON (Response)); 
                String = the resultCode response.get ( "RESULT_CODE");
                returnMap.put("nonce_str", response.get("nonce_str"));
                returnMap.put ( "mch_id", response.get ( "mch_id"));
            } else {
                returnMap.put ( "Sign", response.get ( "Sign")); 
                IF ( "SUCCESS" .equals (resultCode)) {// resultCode to SUCCESS, and will not return prepay_id trade_type 
                    // get pre-payment transaction answer logo 
                    returnMap.put ( "trade_type", response.get ( "trade_type")); 
                    returnMap.put ( "prepay_id", response.get ( "prepay_id")); 
                    return returnMap is; 
                } the else { 
                    logger.info ( "single reservation return results ERROR, {} ", JSONObject.toJSON (Response)); 
                    // This will return data is not paid orders 
                    return returnMap is; 
                } 
                return returnMap is;
            }
        } catch (Exception e) { 
            System.out.println (E); 
            other errors when the system // 
        } 
        return returnMap is; 
    } 


    / ** 
     * @param notifyData the XML data asynchronous notification 
     * @return 
     * / 
    public String PAYBACK (String notifyData) { 
        logger.info ( "asynchronous notification data entry method: {}", notifyData); 
        WXConfigUtil config = null; 
        the try { 
            config = WXConfigUtil.initWXconfigUtil (); 
        } the catch (Exception E) { 
            e.printStackTrace (); 
        } 
        wXPay wxpay new new WXPay = (config); 
        String xmlBack = ""; 
        the Map notifyMap = null; 
        the try { 
            notifyMap = WXPayUtil.xmlToMap (notifyData); // call official SDK map type data is converted into 
            logger.info ( "Asynchronous payment result notification: {}", JSONObject.toJSONString (notifyMap)); 
            IF (wxpay.isPayResultNotifySignatureValid (notifyMap )) {// verify the signature is valid, then the effective further processing 

                String return_code = notifyMap.get ( "return_code" ); // state 
                String out_trade_no = notifyMap.get ( "out_trade_no" ); // merchant order number 
                if (return_code. the equals ( "SUCCESS")) { 
                    IF (out_trade_no!Null =) { 
                        // Special Note: The order has been refunded, but received a notification of a successful result of payment, order status should not be changed to a refund from the merchant's payment success 
                        // special situation: the same micro-channel notification service end may be repeatedly sent to the merchant system, it is necessary to check whether the data has been processed before persistence, treatment success sign a direct return 
                        // business data persistence

                        System.err.println ( "Payment Successful"); 

                        logger.info ( "micro-channel mobile payment successful callback order number: {}", out_trade_no); 
                        xmlBack = "" + "" + "" + ""; 
                    } the else { 
                        Logger .info ( "micro-channel mobile payment failed callback order number: {}", out_trade_no); 
                        xmlBack = "" + "" + "" + ""; 
                    } 
                } 
                return xmlBack; 
            } the else { 
                // error signature, if there are no data sign field, also considered a signature error 
                // Do not store the data fail to be? 
                logger.error ( "mobile payment notification callback signature error"); 
                xmlBack = ""
        } catch (Exception e) {
            logger.error("手机支付回调通知失败", e);
            xmlBack = "" + "" + "" + " ";
        }
        return xmlBack;
    }

    static Properties getProperties() {
        if(null == properties) {
            properties = PropertiesUtil.getProperties("/wxConfig/WxpayConfig.properties");
        }
        return properties;
    }

  

 

 

 

 

 

 

Guess you like

Origin www.cnblogs.com/mafy/p/11888968.html