java开发⽀付
最近做了⽀付的开发,由于是第⼀次做也摸索了⼏天的时间,也只是达到了实现功能的⽔平,并没有太多考虑到性能问题,所以这篇⽂章⽐较适合初学者。
⽀付的总体其实很简单,⼤致就分为三步。第⼀步需要获取⽤户授权;第⼆步调⽤统⼀下单接⼝获取预⽀付id;第三步H5调起⽀付的内置的js。下⾯介绍具体每⼀步的开发流程。
⼀⾸先要明确⽀付属于⽹页版⽀付,所以相较于app的直接调取⽀付要多⼀步授权。也就是需要获取⽤户的openid。使⽤的交易类型是JSAPI,所以统⼀下单接⼝的⽂档明确的写到
因此我们必须去获取openid,同时也可以处理⼀些我们需要的逻辑。获取⽤户授权有两种⽅
式:1.scope=snsapi_base;2.scope=snsapi_userinfo.我使⽤的是snsapi_base
Scope为snsapi_base
Scope为snsapi_userinfo
的官⽅⽂档也有对各个参数的详细说明,我就关键的参数仔细的说明⼀下。⾸先appid就不多说了就是你的appid固定写死的,redirect_uri这个参数是最重要的,这个地址是访问你处理的接⼝地址。你可以在这个链接上拼接上你所需要的参数,⼀般你是要把订单的⾦额传到这个接⼝⾥的,访问这个链接的时候会给你code你需要⽤它去获取openid,记得要对其进⾏urlencode处理。state参数可以理解为扩展字段,其他的参数都是固定写法就不在多做介绍了。下⾯是获取openid的代码⽚段。
//获取openId
HttpClientUtil util = Instance();
Map<String, String> map = new HashMap<String, String>();
map.put("appid", WxPayConfig.APPID);
map.put("secret", WxPayConfig.APPSECRET);
map.put("code", code);
map.put("grant_type", WxPayConfig.GRANT_TYPE);
String returnStr = util.doPostRetString("api.weixin.qq/sns/oauth2/access_token", null,map);
logger.info("returnStr:[" + returnStr + "]");
AccessToken at = JSON.parseObject(returnStr, AccessToken.class);
AccessToken.java
public class AccessToken {
private String access_token;
private String expires_in;
private String refresh_token;
private String openid;
private String scope;
private String unionid;
public String getAccess_token() {
return access_token;
}
public void setAccess_token(String access_token) {
this.access_token = access_token;
}
public String getExpires_in() {
return expires_in;
}
public void setExpires_in(String expires_in) {
}
public String getRefresh_token() {
return refresh_token;
}
public void setRefresh_token(String refresh_token) {
}
public String getOpenid() {
return openid;
}
public void setOpenid(String openid) {
this.openid = openid;
}
public String getScope() {
return scope;
}
public void setScope(String scope) {
this.scope = scope;
}
public String getUnionid() {
return unionid;
}
public void setUnionid(String unionid) {
this.unionid = unionid;
}
@Override
public String toString() {
return "AccessToken [access_token=" + access_token + ", expires_in="
+ expires_in + ", refresh_token=" + refresh_token + ", openid="
+ openid + ", scope=" + scope + ", unionid=" + unionid + "]";
}
}
⼆我们获取了openid后,就可以进⾏下⼀步的统⼀下单的开发了。上统⼀下单接⼝的⽂档写的⽐较详细了,具体的参数含义我就不多做介绍了。下⾯直接贴最直观的代码,特别提醒的是⼀定要注意签名的正确。签名所使⽤的key并不是AppSecret⽽是你申请时⾃⼰定义的商户key。
//统⼀下单
WxPaySendData data = new WxPaySendData();
data.setAppid(WxPayConfig.APPID);
data.setAttach("⽀付");
data.setBody("⽀付");
data.setMch_id(WxPayConfig.MCHID);
data.setNonce_str(nonceStr);
data.setNotify_url(WxPayConfig.NOTIFY_URL);
data.setOut_trade_no(tradeNo);
data.setTotal_fee((int)(fee*100));//单位:分
data.setTrade_type("JSAPI");
data.setSpbill_create_ip(ip);
data.Openid());
String returnXml = UnifiedorderService.unifiedOrder(data,WxPayConfig.KEY);
WxPayReturnData reData = new WxPayReturnData();
XStream xs1 = new XStream(new DomDriver());
xs1.alias("xml", WxPayReturnData.class);
reData = (WxPayReturnData) xs1.fromXML(returnXml);
UnifiedorderService.java
public class UnifiedorderService {
private final static Logger logger = Logger(UnifiedorderService.class);
public static String unifiedOrder(WxPaySendData data,String key){
//统⼀下单⽀付
String returnXml = null;
try {
//⽣成sign签名
SortedMap<Object,Object> parameters = new TreeMap<Object,Object>();
parameters.put("appid", Appid());
parameters.put("attach", Attach());
parameters.put("body", Body());
parameters.put("mch_id", Mch_id());
parameters.put("nonce_str", Nonce_str());
parameters.put("notify_url", Notify_url());
parameters.put("out_trade_no", Out_trade_no());
parameters.put("total_fee", Total_fee());
parameters.put("trade_type", Trade_type());
parameters.put("spbill_create_ip", Spbill_create_ip());
parameters.put("openid", Openid());
parameters.put("device_info", Device_info());
logger.info("SIGN:"+ateSign(parameters,key));
data.ateSign(parameters,key));
XStream xs = new XStream(new DomDriver("UTF-8",new XmlFriendlyNameCoder("-_", "_")));
xs.alias("xml", WxPaySendData.class);
String xml = xs.toXML(data);
logger.info("统⼀下单xml为:\n" + xml);
HttpClientUtil util = Instance();
returnXml = util.doPostForString("h.weixin.qq/pay/unifiedorder", null, xml);
logger.info("返回结果:" + returnXml);
} catch (Exception e) {
e.printStackTrace();
}
return returnXml;
}
}
WxSign
public class WxSign {
private static String characterEncoding = "UTF-8";
@SuppressWarnings("rawtypes")
public static String createSign(SortedMap<Object,Object> parameters,String key){
StringBuffer sb = new StringBuffer();
Set es = Set();//所有参与传参的参数按照accsii排序(升序)
Iterator it = es.iterator();
while(it.hasNext()) {
Map.Entry entry = (Map.();
String k = (Key();
Object v = Value();
if(null != v && !"".equals(v)
&& !"sign".equals(k) && !"key".equals(k)) {
sb.append(k + "=" + v + "&");
}
}
sb.append("key=" + key);
String sign = MD5Util.String(), characterEncoding).toUpperCase();
return sign;
}
public static String getNonceStr() {
Random random = new Random();
return MD5Util.MD5Encode(String.Int(10000)), "UTF-8");
}
public static String getTimeStamp() {
return String.valueOf(System.currentTimeMillis() / 1000);
}
}
最后要提⼀下的是NOTIFY_URL回调地址,接收⽀付异步通知回调地址。
三通过上⾯的操作我们获得了预⽀付交易会话标识prepay_id,这样我们就可以进⾏最后⼀步的操作了。使⽤H5调起⽀付api。//H5调起⽀付
attr.addAttribute("appId", Appid());
attr.addAttribute("timeStamp", TimeStamp());
attr.addAttribute("nonceStr", Nonce_str());
attr.addAttribute("package", "prepay_id="+Prepay_id());
attr.addAttribute("signType", "MD5");
SortedMap<Object,Object> signMap = new TreeMap<Object,Object>();
signMap.put("appId", Appid());
signMap.put("timeStamp", TimeStamp());
signMap.put("nonceStr", Nonce_str());
signMap.put("package", "prepay_id="+Prepay_id());
signMap.put("signType", "MD5");
logger.info("PaySIGN:"+ateSign(signMap,WxPayConfig.KEY));
attr.addAttribute("paySign", ateSign(signMap,WxPayConfig.KEY));
将需要的参数传给页⾯后,使⽤提供⽅法调起⽀付。
<script>
function getUrlParam(name) {
//构造⼀个含有⽬标参数的正则表达式对象
var reg = new RegExp("(^|&)" + name + "=([^&]*)(&|$)");
//匹配⽬标参数
var r = window.location.search.substr(1).match(reg);
/
/返回参数值
if (r != null)
return unescape(r[2]);
return null;
时间正则表达式java}
function onBridgeReady() {
var appId = getUrlParam('appId');
var timeStamp = getUrlParam('timeStamp');
var nonceStr = getUrlParam('nonceStr');
var Package = getUrlParam('package');
var signType = getUrlParam('signType');
var paySign = getUrlParam('paySign');
WeixinJSBridge.invoke('getBrandWCPayRequest', {
"appId" : appId,//"wx2421b1c4370ec43b", //名称,由商户传⼊
"timeStamp" : timeStamp,//"1395712654", //时间戳,⾃1970年以来的秒数
"nonceStr" : nonceStr,//"e61463f8efa94090b1f366cccfbbb444", //随机串
"package" : Package,//"prepay_id=u802345jgfjsdfgsdg888",
"signType" : signType,//"MD5", //签名⽅式:
"paySign" : paySign,//"70EA570631E4BB79628FBCA90534C63FF7FADD89" //签名
}, function(res) { // 使⽤以上⽅式判断前端返回,团队郑重提⽰:_msg将在⽤户⽀付成功后返回 ok,但并不保证它绝对可靠。
//_msg);
if (_msg == "get_brand_wcpay_request:ok") {
alert("⽀付成功");
}
if (_msg == "get_brand_wcpay_request:cancel") {
alert("交易取消");
}
if (_msg == "get_brand_wcpay_request:fail") {
alert("⽀付失败");
}
});
}
function callPay() {
if (typeof WeixinJSBridge == "undefined") {
if (document.addEventListener) {
document.addEventListener('WeixinJSBridgeReady', onBridgeReady,
false);
} else if (document.attachEvent) {
document.attachEvent('WeixinJSBridgeReady', onBridgeReady);
document.attachEvent('onWeixinJSBridgeReady', onBridgeReady);
}
} else {
onBridgeReady();
}
}
</script>
在返回结果的地⽅可以⾃定义⼀些⾃⼰的返回页⾯。
总结:由于我也是第⼀次做,写这篇⽂章是想记录⼀下⾃⼰的⼯作成果,和分享给⼀下也是新⼿的朋友们可以有⼀些帮助,最后希望有好的见解朋友可以留⾔讨论,⼤家⼀起学习进步。
以上就是关于java开发公众⽀付的所有内容了,希望⼤家能够喜欢。
版权声明:本站内容均来自互联网,仅供演示用,请勿用于商业和其他非法用途。如果侵犯了您的权益请与我们联系QQ:729038198,我们将在24小时内删除。
发表评论