工作需要,写了服务器端的支付和退款功能,包含微信和支付宝,网上也有很多demo可以借鉴,我把我的代码放出来,写的比较简单,有问题的欢迎指正,大家一起学习。
微信支付需要调用微信的统一下单接口,而支付宝不用。
我写的时候微信和支付宝都单独写了一个工具类,来调用支付,给前端返回需要的数据。
ps:支付是可以不需要服务器端的,不过为了安全一点点,所以前端需要调起支付的字段都直接从服务器端返回,前端拿到字段直接调起支付就可以了。
1
2
3
4
5
6
7
8
9
|
map<string,string> map = new hashmap<string,string>();
switch (record.getchecktype()) {
case 10 :
map = alipay.prepay(record.getamount(),out_trade_no);
return responsedata.ok(map);
case 20 :
map = wxpay.prepay(record.getamount(),out_trade_no);
return responsedata.ok(map);
}
|
10是支付宝支付,20是微信支付,map里存放前端需要的字段,直接返回给手机端
其中out_trade_no这个是商户自己生成的唯一订单号
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
|
public class wxpay {
private static string url = string.format( "https://api.mch.weixin.qq.com/pay/unifiedorder" );
//统一下单
public static map<string,string> prepay(bigdecimal amount,string out_trade_no){
string entity = genproductargs(amount,out_trade_no);
byte [] buf = util.httppost(url, entity);
string content = new string(buf);
map<string,string> xml=decodexml(content);
return getrep(xml);
}
private static map<string, string> getrep(map<string, string> xml) {
random random = new random();
list<namevaluepair> signparams = new linkedlist<namevaluepair>();
signparams.add( new basicnamevaluepair( "appid" , constants.app_id_wx));
signparams.add( new basicnamevaluepair( "noncestr" , md5.getmessagedigest(string.valueof(random.nextint( 10000 )).getbytes())));
// signparams.add(new basicnamevaluepair("package", "prepay_id="+xml.get("prepay_id")));
signparams.add( new basicnamevaluepair( "package" , "sign=wxpay" ));
signparams.add( new basicnamevaluepair( "partnerid" , constants.mch_id));
signparams.add( new basicnamevaluepair( "prepayid" , xml.get( "prepay_id" )));
signparams.add( new basicnamevaluepair( "timestamp" , string.valueof(system.currenttimemillis() / 1000 )));
xml.put( "sign" , genpackagesign(signparams));
for ( int i = 0 ; i < signparams.size(); i++) {
xml.put(signparams.get(i).getname(),signparams.get(i).getvalue());
}
return removeelements(xml);
}
private static map<string, string> removeelements(map<string, string> xml) {
xml.remove( "appid" );
xml.remove( "mch_id" );
xml.remove( "nonce_str" );
xml.remove( "trade_type" );
//xml.remove("partnerid");
xml.remove( "prepay_id" );
xml.remove( "result_code" );
xml.remove( "return_code" );
xml.remove( "return_msg" );
return xml;
}
private static string genproductargs(bigdecimal amount,string out_trade_no) {
stringbuffer xml = new stringbuffer();
string noncestr = gennoncestr();
xml.append( "</xml>" );
list<namevaluepair> packageparams = new linkedlist<namevaluepair>();
packageparams.add( new basicnamevaluepair( "appid" , constants.app_id_wx));
packageparams.add( new basicnamevaluepair( "body" , "app pay test" ));
packageparams.add( new basicnamevaluepair( "mch_id" , constants.mch_id));
packageparams.add( new basicnamevaluepair( "nonce_str" , noncestr));
packageparams.add( new basicnamevaluepair( "notify_url" , "填写服务器的支付回调路径" ));
packageparams.add( new basicnamevaluepair( "out_trade_no" ,out_trade_no));
packageparams.add( new basicnamevaluepair( "spbill_create_ip" , "127.0.0.1" ));
packageparams.add( new basicnamevaluepair( "total_fee" , string.valueof(amount.movepointright( 2 ))));
// packageparams.add(new basicnamevaluepair("total_fee", "1"));
packageparams.add( new basicnamevaluepair( "trade_type" , "app" ));
string sign = genpackagesign(packageparams);
packageparams.add( new basicnamevaluepair( "sign" , sign));
string xmlstring =toxml(packageparams);
return xmlstring;
}
public static string gennoncestr() {
random random = new random();
return md5.getmessagedigest(string.valueof(random.nextint( 10000 )).getbytes());
}
public static string genpackagesign(list<namevaluepair> params) {
stringbuilder sb = new stringbuilder();
for ( int i = 0 ; i < params.size(); i++) {
sb.append(params.get(i).getname());
sb.append( '=' );
sb.append(params.get(i).getvalue());
sb.append( '&' );
}
sb.append( "key=" );
sb.append(constants.api_key);
string packagesign = md5.getmessagedigest(sb.tostring().getbytes()).touppercase();
return packagesign;
}
public static string toxml(list<namevaluepair> params) {
stringbuilder sb = new stringbuilder();
sb.append( "<xml>" );
for ( int i = 0 ; i < params.size(); i++) {
sb.append( "<" +params.get(i).getname()+ ">" );
sb.append(params.get(i).getvalue());
sb.append( "</" +params.get(i).getname()+ ">" );
}
sb.append( "</xml>" );
return sb.tostring();
}
}
|
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
|
public class alipay {
public static map<string,string> prepay(bigdecimal payableamount,string out_trade_no){
//string orderinfo = getorderinfo("订单付款", "订单付款",out_trade_no,"0.01");
string orderinfo = getorderinfo( "订单付款" , "订单付款" ,out_trade_no,string.valueof(payableamount));
string sign = sign(orderinfo);
try {
/**
* 仅需对sign 做url编码
*/
sign = urlencoder.encode(sign, "utf-8" );
} catch (unsupportedencodingexception e) {
e.printstacktrace();
}
/**
* 完整的符合支付宝参数规范的订单信息
*/
final string payinfo = orderinfo + "&sign=\"" + sign + "\"&" + getsigntype();
map<string,string> map = new hashmap<string, string>();
map.put( "payinfo" , payinfo);
return map;
}
private static string getorderinfo(string subject, string body,string out_trade_no,string price) {
// 签约合作者身份id
string orderinfo = "partner=" + "\"" + constants.partner + "\"" ;
// 签约卖家支付宝账号
orderinfo += "&seller_id=" + "\"" + constants.seller + "\"" ;
// 商户网站唯一订单号
orderinfo += "&out_trade_no=" + "\"" + out_trade_no + "\"" ;
// 商品名称
orderinfo += "&subject=" + "\"" + subject + "\"" ;
// 商品详情
orderinfo += "&body=" + "\"" + body + "\"" ;
// 商品金额
orderinfo += "&total_fee=" + "\"" + price + "\"" ;
// 服务器异步通知页面路径
orderinfo += "¬ify_url=" + "\"" + "填写服务器的支付回调路径" + "\"" ;
// 服务接口名称, 固定值
orderinfo += "&service=\"mobile.securitypay.pay\"" ;
// 支付类型, 固定值
orderinfo += "&payment_type=\"1\"" ;
// 参数编码, 固定值
orderinfo += "&_input_charset=\"utf-8\"" ;
// 设置未付款交易的超时时间
// 默认30分钟,一旦超时,该笔交易就会自动被关闭。
// 取值范围:1m~15d。
// m-分钟,h-小时,d-天,1c-当天(无论交易何时创建,都在0点关闭)。
// 该参数数值不接受小数点,如1.5h,可转换为90m。
orderinfo += "&it_b_pay=\"30m\"" ;
// extern_token为经过快登授权获取到的alipay_open_id,带上此参数用户将使用授权的账户进行支付
// orderinfo += "&extern_token=" + "\"" + extern_token + "\"";
// 支付宝处理完请求后,当前页面跳转到商户指定页面的路径,可空
orderinfo += "&return_url=\"m.alipay.com\"" ;
// 调用银行卡支付,需配置此参数,参与签名, 固定值 (需要签约《无线银行卡快捷支付》才能使用)
// orderinfo += "&paymethod=\"expressgateway\"";
return orderinfo;
}
private static string sign(string content) {
return signutils.sign(content, constants.rsa_private);
}
private static string getsigntype() {
return "sign_type=\"rsa\"" ;
}
}
|
退款部分
支付宝
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
|
string strresponse = null ;
alipaytraderefundresponse response = null ;
try {
alipayclient alipayclient = new defaultalipayclient(url,constants.appid_alipay,constants.rsa_private, "json" , "utf-8" ,constants.rsa_public);
alipaytraderefundrequest request = new alipaytraderefundrequest();
refundinfo alidata = new refundinfo();
alidata.setout_trade_no(out_trade_no);
alidata.setrefund_amount(refund_amount);
request.setbizcontent(json.tojsonstring(alidata));
response = alipayclient.sdkexecute(request);
if (response.issuccess()) {
strresponse= "退款成功" ;
} else {
strresponse= "退款失败" ;
}
return strresponse;
} catch (exception e) {
strresponse= "退款出错" ;
}
return strresponse;
|
微信
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
|
public class wxrefund {
private static final string url = "https://api.mch.weixin.qq.com/secapi/pay/refund" ;
/**
* 微信退款
* @param out_trade_no 商户订单号
* @param total_fee 总金额
* @param refund_fee 退款金额
* @return
*/
public static string dorefund(string out_trade_no, int total_fee, int refund_fee) {
inputstream instream = null ;
keystore keystore = null ;
closeablehttpresponse response = null ;
closeablehttpclient httpclient = null ;
stringbuilder text = new stringbuilder();
string key = constants.mch_id;
try {
/**
* 注意pkcs12证书 是从微信商户平台-》账户设置-》 api安全 中下载的
*/
keystore = keystore.getinstance( "pkcs12" );
instream = wxrefund. class .getresourceasstream( "/apiclient_cert.p12" ); //p12文件
/**
* 此处要改
*/
keystore.load(instream, key.tochararray()); // 这里写密码..默认是mchid
/**
* 此处要改
*/
sslcontext sslcontext = sslcontexts.custom().loadkeymaterial(keystore, key.tochararray()) // 这里也是写密码的
.build();
// allow tlsv1 protocol only
sslconnectionsocketfactory sslsf = new sslconnectionsocketfactory(sslcontext, new string[] { "tlsv1" }, null , sslconnectionsocketfactory.browser_compatible_hostname_verifier);
httpclient = httpclients.custom().setsslsocketfactory(sslsf).build();
//=======================证书配置完成========================
httppost httppost = new httppost(url);
string xmlstring = getrefunargs(out_trade_no,total_fee,refund_fee);
httppost.setentity( new stringentity(xmlstring));
httppost.setheader( "accept" , "application/json" );
httppost.setheader( "content-type" , "application/json" );
response = httpclient.execute(httppost);
httpentity entity = response.getentity();
if (entity != null ) {
bufferedreader bufferedreader = new bufferedreader( new inputstreamreader(entity.getcontent()));
string str;
while ((str = bufferedreader.readline()) != null ) {
text.append(str);
}
}
entityutils.consume(entity);
} catch (exception e){
} finally {
if (instream != null ){
try {
instream.close();
} catch (ioexception e) {
e.printstacktrace();
}
}
if (response != null ){
try {
response.close();
} catch (ioexception e) {
e.printstacktrace();
}
}
if (httpclient != null ){
try {
httpclient.close();
} catch (ioexception e) {
e.printstacktrace();
}
}
}
map<string,string> map = wxpay.decodexml(text.tostring());
string return_msg = map.get( "return_msg" );
if ( "ok" .equals(return_msg) && "success" .equals(map.get( "return_code" ))) {
return "退款成功" ;
}
return return_msg;
}
//设置请求参数的值
private static string getrefunargs(string out_trade_no, int total_fee, int refund_fee) {
string nonce_str = wxpay.gennoncestr();
list<namevaluepair> packageparams = new linkedlist<namevaluepair>();
packageparams.add( new basicnamevaluepair( "appid" , constants.app_id_wx));
packageparams.add( new basicnamevaluepair( "mch_id" , constants.mch_id));
packageparams.add( new basicnamevaluepair( "nonce_str" , nonce_str));
packageparams.add( new basicnamevaluepair( "op_user_id" , constants.mch_id));
packageparams.add( new basicnamevaluepair( "out_refund_no" ,out_trade_no));
packageparams.add( new basicnamevaluepair( "out_trade_no" ,out_trade_no));
packageparams.add( new basicnamevaluepair( "refund_fee" , string.valueof(refund_fee)));
packageparams.add( new basicnamevaluepair( "total_fee" , string.valueof(total_fee)));
string sign = wxpay.genpackagesign(packageparams);
packageparams.add( new basicnamevaluepair( "sign" , sign));
return wxpay.toxml(packageparams);
}
}
|
以上就是本文的全部内容,希望对大家的学习有所帮助,也希望大家多多支持服务器之家。
原文链接:https://blog.csdn.net/l269327509/article/details/53518401