本人第一次在dcloud上写文章,写的不好,请大家多多包涵,觉得有帮助,感谢送分!!!其他的不多说,本文为解决hbuilder上开发app微信支付的诸多细节,因缺少文档带来的不便。
一.开发前准备:
1.首先必须在微信开放平台注册账号,认证开发者资质。附链接:https://open.weixin.qq.com/
- 新建移动应用,如果要跟微信公众号的账号同步,可以关联上公众账号.如图附件图1.
- 新建应用的要填写的应用签名和包名(这个后面说配置)
- 要为所建应用申请微信支付,申请成功之后,获取商户号以及微信支付签名串paysignkey(32位)以备用。
二,java服务端代码:
/**
- app微信支付 调用接口
- @return
-
@throws Exception
*/
public String getWxPayShopParameters()throws Exception{
BigDecimal totalAmt = new BigDecimal (getParameter("total"));
String notify_url = getUrl()+"/appshop/app_shop_api!notifywxPayment.action"; //支付成功通知路径
Setting setting = SettingUtil.getSetting();
String appId = setting.getShopAppId();//移动应用的appid
String paySignKey = setting.getShopAppPaySignKey();//微信支付签名串
String mch_id = setting.getShopPartnerId(); //商户号(微信支付申请的商户号)
String totalfee = totalAmt.multiply(new BigDecimal(100)).intValue() + ""; // 支付金额,单位为分
String nonce_str = WxUtil.CreateNoncestr(); //随机数
String body = getParameter("body"); //商品描述
String attach = appId; //附加数据
String out_trade_no = getParameter("out_trade_no"); //商户订单号
String spbill_create_ip = getRequest().getRemoteAddr(); //订单生成的机器 IP
String trade_type = "APP";//交易类型
SortedMap<String, String> packageParams = new TreeMap<String, String>();
packageParams.put("appid", appId);
packageParams.put("mch_id", mch_id);
packageParams.put("nonce_str", nonce_str);
if(body != null && body.length() > 15) {
body = body.substring(0, 10) + "...";
}
packageParams.put("body", body);
packageParams.put("attach", attach);
packageParams.put("out_trade_no", out_trade_no);
packageParams.put("total_fee", totalfee);
packageParams.put("fee_type", "CNY");//币种
packageParams.put("spbill_create_ip", spbill_create_ip);
packageParams.put("notify_url", notify_url);
packageParams.put("trade_type", trade_type);
//packageParams.put("openid", "oc3KnjpEVsQDDYWq-KHMSPDhOTwU");String sign = WxUtil.createSign(packageParams, paySignKey); packageParams.put("sign", sign);//打包签名 String xml = WxUtil.ArrayToXml(packageParams); log.info("packageParams:" + packageParams); Map<String, Object> dataMap = new HashMap(); try { dataMap = WxUtil.getPrepayId(xml); log.info("dataMap:" + dataMap); } catch (Exception e) { e.printStackTrace(); } if(!"SUCCESS".equals(dataMap.get("return_code")) || !"SUCCESS".equals(dataMap.get("result_code"))) { throw new RuntimeException("获取prepay_id失败!"); } String prepay_id = (String) dataMap.get("prepay_id"); //wxOrderInfo.setPrepayId(prepay_id); SortedMap<String, String> finalpackage = new TreeMap<String, String>(); String timestamp = String.valueOf(System.currentTimeMillis() / 1000); String nonceStr2 = nonce_str; //需要的参数如下: finalpackage.put("appid",appId); finalpackage.put("partnerid",mch_id); finalpackage.put("prepayid", prepay_id); finalpackage.put("package", "Sign=WXPay"); finalpackage.put("noncestr",nonceStr2); finalpackage.put("timestamp",timestamp); String paySign = WxUtil.createSign(finalpackage, paySignKey); finalpackage.put("sign", paySign); return ajax(finalpackage);
}
三,hbuilder页面逻辑代码:
<script type="text/javascript">
mui.init();
var channel = null;
var channels = null;
var pays={};
function plusReady(){
// 获取支付通道
plus.payment.getChannels(function(cs) {
channels = cs;
}, function(e) {
alert("获取支付通道失败:" + e.message);
});
}
document.addEventListener('plusready',plusReady,false);
var w=null;
var WXPAYSERVER='..../gateway/mui_pay!getWxPayShopParameters.action?payid=';
var ALIPAYSERVER='.../payservice?payid='
//调用支付
function pay(id,amount,sheetNo){
if(w){return;}//检查是否请求订单中
// 从服务器请求支付订单
var PAYSERVER = '';
if (id == 'alipay') {
PAYSERVER = ALIPAYSERVER;
} else if (id == 'wxpay') {
PAYSERVER = WXPAYSERVER;
} else {
plus.nativeUI.alert("不支持此支付通道!");
return;
}
//获取支付通道
for (var i in channels) {
if (channels[i].id == id) {
channel = channels[i];
}
}
w=plus.nativeUI.showWaiting();
//获取支付通道
mui.get(PAYSERVER, {
total: 0.01,//支付费用
body: "测试支付",
out_trade_no:sheetNo
}, function(data) {
var varpay = {//参数顺序必须正确
retcode: 0,//5+必备参数
retmsg: "ok",//5+必备参数
appid: data.appid,
noncestr: data.noncestr,
package: "Sign=WXPay",
partnerid: data.partnerid,
prepayid: data.prepayid,
timestamp: data.timestamp,
sign: data.sign
}
plus.payment.request(channel, varpay, function(result) {
w.close();w=null;
plus.nativeUI.alert("支付成功!", function() {
saveSuccess()
});
}, function(e) {
w.close();w=null;
plus.nativeUI.alert("支付失败:" + e.message);
});
}, "json");
var xhr = new XMLHttpRequest();
xhr.onreadystatechange = function() {
switch (xhr.readyState) {
case 4:
w.close();w=null;
if (xhr.status == 200) {
alert(xhr.result);
plus.payment.request(channel, xhr.result, function(result) {
plus.nativeUI.alert("支付成功!", function() {
saveSuccess()
});
}, function(error) {
plus.nativeUI.alert("支付失败:" + error.code);
});
} else {
alert("获取订单信息失败!");
}
break;
default:
break;
}
}
}
</script>
四,注意的细节:
1.测试包名可随意填写,格式参照(应用在一台设备上的唯一标识,在manifest文件里面声明,该包名应和正式发布应用的包名一致。例如,微信的包名为com.tencent.mm)
- 签名:如果是dcloud证书打包,包名默认为:d382d671c6672cba4b87980992cd9d77(必须小写)
- 支付测试时必须打包成.apk,才能测试。
如还不能支付,请检查参数是否正确,参数顺序是否正确,包名是否匹配,以及appid和商户号,以及支付签名是否正确有效。