admin管理员组文章数量:1559079
1.首先可以下载官方sdk查看相关工具类
微信支付九游会真人第一品牌官网sdk下载
其中wxpayconstants和wxpayutil会在后边使用到
import java.security.securerandom;
import java.util.*;
public class wxpayutil {
private static final string symbols = "0123456789abcdefghijklmnopqrstuvwxyzabcdefghijklmnopqrstuvwxyz";
private static final random random = new securerandom();
/**
* 获取随机字符串 32位 nonce str
*
* @return string 随机字符串
*/
public static string generatenoncestr() {
char[] noncechars = new char[32];
for (int index = 0; index < noncechars.length; index) {
noncechars[index] = symbols.charat(random.nextint(symbols.length()));
}
return new string(noncechars);
}
/**
* 获取当前时间戳,单位秒
*
* @return
*/
public static long getcurrenttimestamp() {
return system.currenttimemillis() / 1000;
}
/**
* 获取当前时间戳,单位毫秒
*
* @return
*/
public static long getcurrenttimestampms() {
return system.currenttimemillis();
}
}
import org.apache.http.client.httpclient;
/**
* 常量
*/
public class wxpayconstants {
public enum signtype {
md5, hmacsha256
}
public static final string domain_api = "api.mch.weixin.qq";
public static final string domain_api2 = "api2.mch.weixin.qq";
public static final string domain_apihk = "apihk.mch.weixin.qq";
public static final string domain_apius = "apius.mch.weixin.qq";
public static final string fail = "fail";
public static final string success = "success";
public static final string hmacsha256 = "hmac-sha256";
public static final string md5 = "md5";
public static final string field_sign = "sign";
public static final string field_sign_type = "sign_type";
public static final string wxpaysdk_version = "wxpaysdk/3.0.9";
public static final string user_agent = wxpaysdk_version
" (" system.getproperty("os.arch") " " system.getproperty("os.name") " " system.getproperty("os.version")
") java/" system.getproperty("java.version") " httpclient/" httpclient.class.getpackage().getimplementationversion();
public static final string micropay_url_suffix = "/pay/micropay";
public static final string unifiedorder_url_suffix = "/pay/unifiedorder";
public static final string orderquery_url_suffix = "/pay/orderquery";
public static final string reverse_url_suffix = "/secapi/pay/reverse";
public static final string closeorder_url_suffix = "/pay/closeorder";
public static final string refund_url_suffix = "/secapi/pay/refund";
public static final string refundquery_url_suffix = "/pay/refundquery";
public static final string downloadbill_url_suffix = "/pay/downloadbill";
public static final string report_url_suffix = "/payitil/report";
public static final string shorturl_url_suffix = "/tools/shorturl";
public static final string authcodetoopenid_url_suffix = "/tools/authcodetoopenid";
// sandbox
public static final string sandbox_micropay_url_suffix = "/sandboxnew/pay/micropay";
public static final string sandbox_unifiedorder_url_suffix = "/sandboxnew/pay/unifiedorder";
public static final string sandbox_orderquery_url_suffix = "/sandboxnew/pay/orderquery";
public static final string sandbox_reverse_url_suffix = "/sandboxnew/secapi/pay/reverse";
public static final string sandbox_closeorder_url_suffix = "/sandboxnew/pay/closeorder";
public static final string sandbox_refund_url_suffix = "/sandboxnew/secapi/pay/refund";
public static final string sandbox_refundquery_url_suffix = "/sandboxnew/pay/refundquery";
public static final string sandbox_downloadbill_url_suffix = "/sandboxnew/pay/downloadbill";
public static final string sandbox_report_url_suffix = "/sandboxnew/payitil/report";
public static final string sandbox_shorturl_url_suffix = "/sandboxnew/tools/shorturl";
public static final string sandbox_authcodetoopenid_url_suffix = "/sandboxnew/tools/authcodetoopenid";
}
2.创建商户号
创建商户号,登录商户平台配置小程序appid以及获取证书序列号、微信支付商户号、apiv3密钥,这部分比较简单不做详述
3.微信支付的三个核心步骤 预支付、验签、回调方法
微信支付接口调用方法有预支付、验签、回调方法、关闭订单以及查询订单和退款,其中的难点在验签和回调,废话不多说直接上代码。
导入依赖
<dependency>
<groupid>com.github.wechatpay-apiv3</groupid>
<artifactid>wechatpay-apache-httpclient</artifactid>
<version>0.4.4</version>
</dependency>
将需要的密钥导入项目,也可以添加到properties文件中方便后期修改
//小程序appid
public static final string appid = "***************";
//商户号
public static final string mchid = "*****************";
//证书序列号
public static final string mchserialno = "***********";
//v3密钥
public static final string apiv3key = "**************";
//支付通知回调
public static final string notifyurl = "http://******";
//小程序密钥
public static final string secret="******************";
//证书密钥
public static final string privatekey = "************";
//http客户端
public static closeablehttpclient httpclient;
//退款通知回调
public static final string refundnotifyurl="http://**";
public static autoupdatecertificatesverifier verifier;
1.预支付
public static void setup() throws ioexception {
// 加载商户私钥(privatekey:私钥字符串)
privatekey merchantprivatekey = pemutil.loadprivatekey(new bytearrayinputstream(privatekey.getbytes("utf-8")));
// 加载平台证书(mchid:商户号,mchserialno:商户证书序列号,apiv3key:v3密钥)
verifier = new autoupdatecertificatesverifier(
new wechatpay2credentials(mchid, new privatekeysigner(mchserialno, merchantprivatekey)),
apiv3key.getbytes("utf-8"));
// 初始化httpclient
httpclient = wechatpayhttpclientbuilder.create().withmerchant(mchid, mchserialno, merchantprivatekey)
.withvalidator(new wechatpay2validator(verifier)).build();
}
/**
* 获取小程序请求用户openid
* @param jscode
* @return
* @throws urisyntaxexception
* @throws ioexception
*/
public static string getopenid(string jscode) throws urisyntaxexception, ioexception {
string url = "https://api.weixin.qq/sns/jscode2session?appid="
appid"&secret="secret"&js_code="jscode"&grant_type=authorization_code";
uribuilder uribuilder = new uribuilder(url);
httpget httpget = new httpget(uribuilder.build());
httpget.addheader("accept", "application/json");
closeablehttpresponse response = httpclient.execute(httpget);
string openidparse = entityutils.tostring(response.getentity());
map<string,string> parse = (map) json.parse(openidparse);
string openid = parse.get("openid");
return openid;
}
//预支付方法,返回prepay_id(预支付id)paybean是用于接收前端数据的实体类
public static string order(paybean paybean,string outtradeno) throws ioexception, urisyntaxexception {
setup();
//url: 哪一种支付
httppost httppost = new httppost("https://api.mch.weixin.qq/v3/pay/transactions/jsapi");
httppost.addheader("accept", "application/json");
httppost.addheader("content-type", "application/json; charset=utf-8");
bytearrayoutputstream bos = new bytearrayoutputstream();
objectmapper objectmapper = new objectmapper();
string openid = getopenid(paybean.getjscode());
objectnode rootnode = objectmapper.createobjectnode();
rootnode.put("mchid", mchid)
.put("appid", appid)
.put("description", "")
.put("notify_url",notifyurl )//异步通知 yrl
.put("out_trade_no", outtradeno);//自己平台的商户号
rootnode.putobject("amount").put("total", 1).put("currency", "cny");
rootnode.putobject("payer").put("openid", openid);
objectmapper.writevalue(bos, rootnode);
httppost.setentity(new stringentity(bos.tostring("utf-8"), "utf-8"));
closeablehttpresponse response = httpclient.execute(httppost);
string bodyasstring = entityutils.tostring(response.getentity());
system.out.println(bodyasstring);
return bodyasstring;
}
2.验签(v3加密方式只有rsa非对称性加密)
public ajaxresult pay(paybean paybean) throws exception {
//后端生成
string outtradeno = "ly" system.currenttimemillis();// 平台商品号码
string order = "";
try {
order = order(paybean, outtradeno);
} catch (ioexception e) {
// todo auto-generated catch block
e.printstacktrace();
} catch (urisyntaxexception e) {
// todo auto-generated catch block
e.printstacktrace();
}
//生成时间戳
long timestamp = wxpayutil.getcurrenttimestamp();
生成随机数订单号
string generatenoncestr = wxpayutil.generatenoncestr();
map<string, string> parse = (map) json.parse(order);
// 需要签名的
stringbuilder builder = new stringbuilder();
builder.append(appid "\n");
builder.append(timestamp "\n");
builder.append(generatenoncestr "\n");
builder.append("prepay_id=" parse.get("prepay_id") "\n");// 加签 商户号一致
byte[] signbytes = builder.tostring().getbytes("utf-8");
//加密方法
string paysign = sign(signbytes);
hashmap<string, string> signdata = new hashmap<string, string>(8);
signdata.put("mchid", wechatpay.mchid);
signdata.put("appid", wechatpay.appid);
signdata.put("package", "prepay_id=" parse.get("prepay_id"));
signdata.put("noncestr", generatenoncestr);// 随机字符串32位
signdata.put("timestamp", timestamp.tostring());// 时间戳
signdata.put("sign", paysign);
return ajaxresult.success(signdata);
}
/**
stringbuilder builder = new stringbuilder();
builder.append(wechatpay.appid "\n");
builder.append(timestamp "\n");
builder.append(generatenoncestr "\n");
builder.append("prepay_id=" parse.get("prepay_id") "\n");// 加签 商户号一致
byte[] message = builder.tostring().getbytes("utf-8");
* @param message 需要签名的字符传byte数组
* @return
* @throws ioexception
* @throws nosuchalgorithmexception
* @throws invalidkeyexception
* @throws signatureexception
*/
public string sign(byte[] message) throws ioexception, nosuchalgorithmexception, invalidkeyexception, signatureexception {
// 加载商户私钥(privatekey:私钥字符串)
privatekey merchantprivatekey = wechatpay.getprivatekey();
signature sign = signature.getinstance("sha256withrsa");
sign.initsign(merchantprivatekey);
sign.update(message);
return base64.getencoder().encodetostring(sign.sign());
}
3.回调方法
public map callback(httpservletrequest request, httpservletresponse response)
throws ioexception, generalsecurityexception {
map<string, string> result = new hashmap<string, string>();
// 响应接口
result.put("code", "fail");
/** 从请求头获取验签字段 */
// 时间戳
string timestamp = request.getheader("wechatpay-timestamp");
string nonce = request.getheader("wechatpay-nonce");// 字符数按
string signature = request.getheader("wechatpay-signature");
string serial = request.getheader("wechatpay-serial");
system.out.println("开始读取请求头的信息");
// 请求头
system.out.println("wechatpay-timestamp=" timestamp);
system.out.println("wechatpay-nonce=" nonce);
system.out.println("wechatpay-signature=" signature);
system.out.println("wechatpay-serial=" serial);
// 加载商户私钥(privatekey:私钥字符串)
privatekey merchantprivatekey = pemutil
.loadprivatekey(new bytearrayinputstream(privatekey.getbytes("utf-8")));
// 加载平台证书(mchid:商户号,mchserialno:商户证书序列号,apiv3key:v3密钥)
autoupdatecertificatesverifier verifier = new autoupdatecertificatesverifier(
new wechatpay2credentials(mchid,
new privatekeysigner(mchserialno, merchantprivatekey)),
apiv3key.getbytes("utf-8"));
// 读取请求体的信息
system.out.println("开始读取请求体的信息");
servletinputstream inputstream = request.getinputstream();
stringbuffer stringbuffer = new stringbuffer();
bufferedreader bufferedreader = new bufferedreader(new inputstreamreader(inputstream));
string s;
// 读取回调请求体
while ((s = bufferedreader.readline()) != null) {
stringbuffer.append(s);
}
string s1 = stringbuffer.tostring();
system.out.println("请求体" s1);
map<string, string> requestmap = (map) json.parse(s1);
// 开始按照验签进行拼接
string id = requestmap.get("id");
system.out.println("id=" id);
string resource = string.valueof(requestmap.get("resource"));
system.out.println("resource=" resource);
map<string, string> requestmap2 = (map) json.parse(resource);
string associated_data = requestmap2.get("associated_data");
string nonce = requestmap2.get("nonce");
string ciphertext = requestmap2.get("ciphertext");// 数据密文
// 按照文档要求拼接验签串
string verifysignature = timestamp "\n" nonce "\n" s1 "\n";
system.out.println("拼接后的验签串=" verifysignature);
// 使用官方验签工具进行验签
boolean verify = verifier.verify(serial, verifysignature.getbytes(), signature);
system.out.println("官方工具验签=" verify);
// 判断验签的结果
system.out.println("=======判断验签结果=======");
if (verify == false) {
result.put("message", "sign error");
return result;
}
system.out.println("验签成功后,开始进行解密");
// 解密,如果这里报错,就一定是apiv3密钥错误
aesutil aesutil = new aesutil(apiv3key.getbytes("utf-8"));
string aes = aesutil.decrypttostring(associated_data.getbytes(), nonce.getbytes(), ciphertext);
system.out.println("解密后=" aes);
map<string, string> callbackdata = getcallbackdata(aes);
string tradestate = callbackdata.get("trade_state");
if ("success".equals(tradestate)) {
result.put("code", "success");
result.put("message", "成功");
} else {
result.put("message", "trade_state error");
}
return result;
}
public static map<string,string> getcallbackdata(string body){
map<string,string> resmap=new hashmap<>();
map<string,object> strtomap = (map) json.parse(body);
resmap.put("out_trade_no",strtomap.get("out_trade_no").tostring());
resmap.put("transaction_id",strtomap.get("transaction_id").tostring());
resmap.put("trade_state",strtomap.get("trade_state").tostring());
map<string,object> payermap = (map) json.parse(strtomap.get("payer").tostring());
map<string,object> amountmap = (map) json.parse(strtomap.get("amount").tostring());
resmap.put("openid",payermap.get("openid").tostring());
resmap.put("total",amountmap.get("total").tostring());
resmap.put("payer_total",amountmap.get("payer_total").tostring());
return resmap;
}
4.查询订单
/**
* 查询订单
* @param outtradeno 商户订单号(本地平台的订单号)
* @return
* @throws urisyntaxexception
* @throws ioexception
*
*/
public static string findorder(string outtradeno) throws urisyntaxexception, ioexception {
string url = "https://api.mch.weixin.qq/v3/pay/transactions/out-trade-no/" outtradeno "?mchid=" mchid;
uribuilder uribuilder = new uribuilder(url);
httpget httpget = new httpget(uribuilder.build());
httpget.addheader("accept", "application/json");
closeablehttpresponse response = httpclient.execute(httpget);
string bodyasstring = entityutils.tostring(response.getentity());
return bodyasstring;
}
5.退款与退款通知
退款是前端用户退款时请求的方法,退款通知是微信平台收到退款请求的回调
/**
* 退款(api)
*/
public map refund(string outtradeno){
map<string, object> result = new hashmap<string, object>();
string out_refund_no = "tb" system.currenttimemillis();// 平台商品号码
shachargerecord recode = shachargerecordservice.selectshachargerecordbyouttradeno(outtradeno);
long price = recode.getrealtotalprice().longvalueexact();
try {
jsonobject order = new jsonobject();
order.put("out_trade_no", outtradeno);//商户订单号
order.put("out_refund_no", out_refund_no);//商户退款单号
// order.put("reason", reason);//退款原因
order.put("notify_url", refundnotifyurl);//退款通知
jsonobject amount = new jsonobject();
amount.put("refund", price * 100);//退款金额 price * 100
amount.put("currency", "cny");
amount.put("total", price * 100);//原订单金额
order.put("amount", amount);
// 加载商户私钥(privatekey:私钥字符串)
privatekey merchantprivatekey = pemutil
.loadprivatekey(new bytearrayinputstream(wechatpay.privatekey.getbytes("utf-8")));
// 加载平台证书(mchid:商户号,mchserialno:商户证书序列号,apiv3key:v3密钥)
autoupdatecertificatesverifier verifier = new autoupdatecertificatesverifier(
new wechatpay2credentials(mchid,
new privatekeysigner(mchserialno, merchantprivatekey)),
apiv3key.getbytes("utf-8"));
// 初始化httpclient
closeablehttpclient httpclient = wechatpayhttpclientbuilder.create().withmerchant(mchid, mchserialno, merchantprivatekey)
.withvalidator(new wechatpay2validator(verifier)).build();
httppost httppost = new httppost("https://api.mch.weixin.qq/v3/refund/domestic/refunds");
httppost.addheader("accept", "application/json");
httppost.addheader("content-type","application/json; charset=utf-8");
httppost.setentity(new stringentity(order.tojsonstring(), "utf-8"));
httpresponse response = httpclient.execute(httppost);
//获取返回数据
string bodyasstring = entityutils.tostring(response.getentity());
jsonobject bodyasjson = jsonobject.parseobject(bodyasstring);
logger.info(bodyasjson.tojsonstring());
final string status = bodyasjson.getstring("status");
result.put("status", status);
if("success".equals(status)){
logger.info("退款成功");
result.put("message", "退款成功");
}else if("closed".equals(status)){
logger.info("退款关闭");
result.put("message", "退款关闭");
}else if("processing".equals(status)){
logger.info("退款处理中");
result.put("message", "退款处理中");
result.put("code", 200);
}else if("abnormal".equals(status)){
result.put("message", "退款异常");
logger.info("退款异常");
}
} catch (exception e) {
logger.info(e.tostring());
e.printstacktrace();
}
return result;
}
/**
* 退款通知(api)
*/
public map refundnotice(httpservletrequest request, httpservletresponse response) {
map<string, string> result = new hashmap<string, string>();
result.put("code", "fail");
try {
string reqparams = wechatpay.read(request.getinputstream());
logger.info("-------支付结果:" reqparams);
jsonobject json = jsonobject.parseobject(reqparams);
string ciphertext = json.getjsonobject("resource").getstring("ciphertext");
final string associated_data = json.getjsonobject("resource").getstring("associated_data");
final string nonce = json.getjsonobject("resource").getstring("nonce");
aesutil aesutil = new aesutil(apiv3key.getbytes("utf-8"));
//解密数据
ciphertext = aesutil.decrypttostring(associated_data.getbytes(), nonce.getbytes(), ciphertext);
map<string, object> resmap = new hashmap<>();
map<string, object> strtomap = (map) json.parse(ciphertext);
string outtradeno = (string) strtomap.get("out_trade_no");
final string eventtype = json.getstring("event_type");
if ("refund.success".equals(eventtype)) {
result.put("code", "success");
result.put("message", "退款成功");
} else if ("refund.abnormal".equals(eventtype)) {
result.put("message", "退款异常");
} else if ("refund.closed".equals(eventtype)) {
result.put("message", "退款关闭");
}
} catch (exception e) {
e.printstacktrace();
}
return result;
}
/**
* 查询单笔退款订单
*
* @param outtradeno
* @return
* @throws ioexception
* @throws urisyntaxexception
*
* 微信开发文档 https://pay.weixin.qq/wiki/doc/apiv3/apis/chapter3_1_10.shtml
*/
public ajaxresult getrefundsorderbyouttradeno(string outtradeno) throws ioexception, urisyntaxexception {
string order = getrefundsorderbyouttradeno(outtradeno);
map<string,object> resmap=new hashmap<>();
map<string,object> strtomap = (map) json.parse(order);
resmap.put("status", strtomap.get("status"));
if ("success".equals(strtomap.get("status"))) {
}
return ajaxresult.success(resmap);
}
/**
* 查询订单
* @param outtradeno 商户订单号(力云平台的订单号)
* @return
* @throws urisyntaxexception
* @throws ioexception
*
*/
public static string getrefundsorderbyouttradeno(string outtradeno) throws urisyntaxexception, ioexception {
string url = "https://api.mch.weixin.qq/v3/refund/domestic/refunds/" outtradeno ;
uribuilder uribuilder = new uribuilder(url);
httpget httpget = new httpget(uribuilder.build());
httpget.addheader("accept", "application/json");
closeablehttpresponse response = httpclient.execute(httpget);
string bodyasstring = entityutils.tostring(response.getentity());
return bodyasstring;
}
public static string read(inputstream is){
try {
bytearrayoutputstream baos = new bytearrayoutputstream();
int len = 0;
byte[] buffer = new byte[512];
while((len = is.read(buffer)) != -1){
baos.write(buffer, 0, len);
}
return new string(baos.tobytearray(), 0, baos.size(), "utf-8");
}catch (exception e) {
e.printstacktrace();
}
return "";
}
本文标签:
j9九游会老哥俱乐部交流区的版权声明:本文标题:微信支付接口v3结合微信小程序步骤 内容由热心网友自发贡献,该文观点仅代表作者本人, 转载请联系作者并注明出处:https://www.elefans.com/xitong/1727371645a1111242.html, 本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌抄袭侵权/违法违规的内容,一经查实,本站将立刻删除。
发表评论