Current location - Quotes Website - Personality signature - Wechat payment background article
Wechat payment background article
Wechat payment series articles

Wechat payment -java back-end implementation

Wechat payment -vue front-end implementation

Java demo: download address at the bottom of the article

technology stack

Leaf spring cover

Java language (a computer language, especially for creating websites)

XML (wechat is in. chi dori . wx pay;

Import core.com.wxpay.iwxpaydomain;

Import core.com.wxpay.wxpayconfig;

Import core.com.wxpay.wxpayconstants;

Import org.springframework.beans.factory.annotation.value;

Import org.springframework.stereotype.service;

Import java.io.bytearrayinputstream;

Import java.io.file;

Import java.io.fileinputstream;

Import java.io.inputstream;

@ Service

The public class iwxpayconfig extends WXPayConfig {// inherits sdk WXPayConfig to implement some abstract methods in sdk.

Private byte [] certdata;

@ Value(" $ { vendor . wx . config . app _ id } ")

Private string app _ id

@Value("${vendor.wx.pay.key} ")

Private string wx _ pay _ key

@ Value(" $ { vendor . wx . pay . mch _ id } ")

Private string wx _ pay _ mch _ id

The public iwxpayconfig () throwsexception {//constructor reads the certificate, and the sdk can get the certificate through getCertStream.

string cert path = "/data/config/chi dori/API client _ cert . p 12 ";

File file = new file (certpath);

InputStream certStream = new file InputStream(file);

this . certdata = new byte[(int)file . length()];

certstream . read(this . certdata);

certstream . close();

}

@ Overlay

Public string getAppID() {

Return app _ id

}

@ Overlay

Public string getMchID() {

Returns wx _ pay _ mch _ id.

}

@ Overlay

Public string getKey() {

Returns wx _ pay _ key.

}

@ Overlay

Common input stream getCertStream() {

Returns a new bytearray inputstream (this. certdata);

}

@ Overlay

Public iwxpaydomain getwxPaydomain () {//This method needs to be implemented, otherwise WXPay cannot be initialized normally.

IWXPayDomain IWXPayDomain = new IWXPayDomain(){

@ Overlay

Public void report (string field, long elapsedTimeMillis, Exception ex) {

}

@ Overlay

Public domain information getdomain (wxpayconfig) (

Returns a new IWXPayDomain. DomainInfo(WXPayConstants。 DOMAIN_API,true);

}

};

Return to iwxPayDomain

}

}

Initiate a unified order, and the front end will adjust the necessary parameters of WeChat payment.

//Initiate WeChat payment

WXPay wxpay = null

Map result = new HashMap & gt();

Try {

// ******************************************

//

//Unified sorting

//

// ******************************************

wx pay = new wx pay(iWxPayConfig); //* * * Inject the self-implemented WeChat configuration class to create the WXPay core class, including a unified ordering interface.

map data = new HashMap();

Data.put("body ","order details ");

data.put("out_trade_no ",trans order . getglobaloderid()); //Unique order number, which cannot be repeated.

data.put("total_fee ",string . value of(trans order . getorderamount()。 Multiplication (new BigDecimal( 100)). int value())); //Order amount, in minutes

data.put("spbill_create_ip "," 192. 168.3 1. 166 "); //place an order ip

data.put("openid ",openId); //WeChat official account unified logo openid

data.put("notify_url ","/pay callback "); //Order result notification, WeChat takes the initiative to call back this interface.

data.put("trade_type "," JSAPI "); //Fixed filling

Logger.info ("Initiate WeChat payment order interface, request={}", data);

Map response = wxpay.unifiedOrder (data); //WeChat sdk integration method, unifiedOrder interface, here we request MD5 encryption method.

Logger.info ("wechat payment order was placed successfully, and the return value is response={}", response);

string return code = response . get(" return _ code ");

If (! SUCCESS.equals(returnCode)) {

Returns null

}

string result code = response . get(" result _ code ");

If (! SUCCESS.equals(resultCode)) {

Returns null

}

string prepay _ id = response . get(" prepay _ id ");

if (prepay_id == null) {

Returns null

}

// ******************************************

//

//The front end calls out the necessary parameters for WeChat payment.

//

// ******************************************

string packages = " prepay _ id = "+prepay _ id;

map wx paymap = new HashMap();

wxPayMap.put("appId ",iwxpayconfig . getappid());

wxPayMap.put("timeStamp ",string . value of(utility . getcurrenttimestamp()));

wx pay map . put(" non centr ",utility . generate uid());

WxPayMap.put("package ",package);

wxPayMap.put("signType "," MD5 ");

//the encrypted string includes five parameters, appid timestamp nonce str package signtype, which is encrypted by sdk WXPayUtil class. Note that the MD5 encryption method is used here.

string sign = wxpayutil . generate signature(wxPayMap,iwxpayconfig . getkey());

// ******************************************

//

//Return the necessary parameters for calling WeChat payment to the front end.

//

// ******************************************

Result. put ("prepaid _ id", prepaid _ id);

Result.put("sign ",symbol);

result . putall(wx paymap);

Return the result;

Catch (exception e) {

}

Callback result processing

The core is to check whether the encryption signature matches when calling back the payment instruction to prevent the simulation success notice.

@ request mapping(value = "/pay callback ",method = RequestMethod。 Post)

Common string payCallback(HttpServletRequest, HttpServletResponse) (

Logger.info ("asynchronous notification of entering WeChat payment");

String resXml =

Try {

//

InputStream is = request . getinputstream();

//Convert InputStream into a string

buffered reader reader = new buffered reader(new InputStreamReader(is));

StringBuilder sb = new StringBuilder();

String line = null

Try {

while ((line = reader.readLine())! = null) {

sb . append(line+" ");

}

} catch (IOException e) {

e . printstacktrace();

} Finally {

Try {

is . close();

} catch (IOException e) {

e . printstacktrace();

}

}

resXml = sb . tostring();

Logger.info ("WeChat payment asynchronous notification request package: {}", resxml);

Returns wxtticketservice. payback (resxml);

}catch (exception e){

Logger.error ("WeChat payment callback notification failed", e);

String result = "";

Return the result;

}

}

@ Overlay

String notify data (

logger.info("payBack() start,notifyData={} ",notify data);

String xmlBack =

Map notifyMap = null

Try {

wx pay wx pay = new wx pay(iWxPayConfig);

notify map = wxpayutil . XML tomap(notify data); //Convert to map

if(wx pay . ispayresultnotifysignaturevalid(notifyMap)){

//The signature is correct

//for processing.

//Pay attention to special circumstances: the order has been refunded, but the notice of successful payment has been received. You should not change the order status of the merchant from refund to successful payment.

string return _ code = notifymap . get(" return _ code "); //status

string out _ trade _ no = notifymap . get(" out _ trade _ no "); //Order number

if (out_trade_no == null) {

Logger.info ("WeChat payment callback failed order number: {}", notifymap);

xmlBack =

Return xmlBack

}

//Business logic processing * * * * * * * * * * * * * * * * * * * * * * *

Logger.info ("wechat payment callback successful order number: {0}", notifymap);

xmlBack =

Return xmlBack

} Otherwise {

Logger.error ("WeChat payment callback notification signature error");

xmlBack =

Return xmlBack

}

Catch (exception e) {

Logger.error ("WeChat payment callback notification failed", e);

xmlBack =

}

Return xmlBack

}

The signature of the unified order and the signature of the subsequent front-end pull WeChat payment need to be unified, that is, both of them are encrypted with MD5. If it is not the same, the front-end pull WeChat payment will fail, which is a huge pit. It has been debugged for a long time, and WeChat has not clearly stated in the file that the signature verification method of unified orders needs to be consistent with the signature verification of front-end pull WeChat payment.

The source code in WeChat sdk needs to be adjusted for this problem, and the adjustment is as follows:

The WXPay class needs to modify the encryption judgment. In the WXPay construction method, the adjustment is as follows.

The public WXPay (final WXPayConfig configuration, final string notifyUrl, final boolean autoReport, final boolean useSandbox) throws an exception {

this.config = config

this . notify URL = notify URL;

this.autoReport = autoReport

this . use sandbox = use sandbox;

if (useSandbox) {

this.signType = SignType。 MD5// Sandbox Environment

}

Otherwise {

this.signType = SignType。 MD5// Change the encryption method here to SignType. MD5, and keep consistent with the front-end WeChat encryption method.

}

this . WXPayRequest = new WXPayRequest(config);

}

Concluding remarks

After the completion, the back-end logic of WeChat payment is still very clear, but it is very difficult in the development process. It is not clear where each technical term is configured on WeChat, and the encryption method is very confusing.