微信端代码如下:
支付按钮:
<view class="container">
<input bindinput="getOrderCode" style="border:1px solid #ccc;" type="text" placeholder="请填写订单号" />
<button bindtap="pay">立即支付</button></view>
js代码:
pay() {
let orderCode = this.orderCode;
wepy.login({
success: res => {
if (res.code) {
HTTP.get({
url: constant.restServer.host + '/weChatApplePay/toPay',
params: {
key: constant.restServer.wxapp_id,
code: res.code,
orderCode: orderCode
},
headers: {
'Content-Type': 'application/json'
},
mask: false,
loading: false,
}).then((data) => {
console.log('后台下单返回数据', data)
wx.requestPayment({
timeStamp: data.data.timeStamp,
nonceStr: data.data.nonceStr,
package: data.data.package,
signType: data.data.signType,
paySign: data.data.paySign,
success: res => {
console.log(res);
},
fail: () => {
console.log(res);
},
complete: () => {
console.log(res);
}
})
}).
catch((error) => {
console.log('app.wpy signin login get jscode error...', error)
})
} else {
console.log('获取用户登录态失败!' + res.errMsg)
}
}
});
},
//获取订单号 自定义输入
getOrderCode(e) {
this.orderCode = e.detail.value;
this.$apply();
},
};
后台实现代码 才用java编写:
Controller:
public static final String PATH = "weChatApplePay"; @Autowired private WechatServiceApplet wechatServiceApplet; @ApiOperation("微信小程序统一下单接口") @RequestMapping(value = "toPay", method = RequestMethod.GET) public RestfulApiResponse<JSONObject> toPay(@RequestParam @ApiParam(value = "登录返回的code 换取openid的登录凭证", required = true) String code, @RequestParam @ApiParam(value = "订单号", required = true) String orderCode, @RequestParam @ApiParam(value = "订单号", required = true) String key) { return RestfulApiResponse.success("获取成功",wechatServiceApplet.toPay(code,orderCode,key)); } @ApiOperation("微信端回调地址 后期需要修改订单状态") @RequestMapping(value = "payResult", method = {RequestMethod.GET, RequestMethod.POST}) public void payResult(HttpServletRequest request, HttpServletResponse response)throws ServletException, IOException { String reqParams = StreamUtil.read(request.getInputStream()); System.out.println("-------支付结果:"+reqParams); StringBuffer sb = new StringBuffer("<xml><return_code>SUCCESS</return_code><return_msg>OK</return_msg></xml>"); response.getWriter().append(sb.toString()); }
wechatServiceApplet:
private static final Logger logger = LoggerFactory.getLogger(WechatServiceApplet.class); @Autowired private AppletSettingService appletSettingService; //发起支付 public JSONObject toPay(String code, String orderCode, String key) { try { AppletSetting appletSetting = appletSettingService.selectByKey(key); //这个是我自定义 根据key 取后台appId,根据场景,自定义。 if (null == appletSetting) throw new AppletSettingException("该小程序信息不存在"); OrderInfo order = new OrderInfo(); order.setAppid(appletSetting.getAppId()); order.setMch_id(Configure.getMch_id());//后期需要从数据库中取数据 order.setNonce_str(RandomStringGenerator.getRandomStringByLength(32)); order.setBody("dfdfdf"); order.setOut_trade_no(orderCode); order.setTotal_fee("1");//从前端传数据 order.setSpbill_create_ip("");//后期需要从数据库中取数据 终端IP order.setNotify_url("");//测环境 后期需要从数据库中取数据 order.setTrade_type("JSAPI"); order.setSign_type("MD5"); return getOrder(order, code,appletSetting); } catch (Exception e) { e.printStackTrace(); logger.error("-------", e); } return null; } //下单 生成prepay_id 用于签名 小程序端发起支付 private JSONObject getOrder(OrderInfo order, String code,AppletSetting appletSetting) throws UnrecoverableKeyException, KeyManagementException, KeyStoreException, NoSuchAlgorithmException, ClientProtocolException, IllegalAccessException, ServletException, IOException { //生成签名 order.setOpenid(getOpenId(code,appletSetting)); String sign = Signature.getSign(order); order.setSign(sign); String result = HttpRequest.sendPost(WechatAppletConfig.APPLET_PAY, order); logger.info("---------下单返回:" + result); return sign(convertXml(result).getPrepay_id(),appletSetting); } //下单之后的签名小程序端发起支付 private JSONObject sign(String repay_id,AppletSetting appletSetting) throws IllegalAccessException { SignInfo signInfo = new SignInfo(); signInfo.setAppId(appletSetting.getAppId()); long time = System.currentTimeMillis() / 1000; signInfo.setTimeStamp(String.valueOf(time)); signInfo.setNonceStr(RandomStringGenerator.getRandomStringByLength(32)); signInfo.setRepay_id("prepay_id=" + repay_id); signInfo.setSignType("MD5"); //生成签名 String sign = Signature.getSign(signInfo); JSONObject json = new JSONObject(); json.put("timeStamp", signInfo.getTimeStamp()); json.put("nonceStr", signInfo.getNonceStr()); json.put("package", signInfo.getRepay_id()); json.put("signType", signInfo.getSignType()); json.put("paySign", sign); return json; } //获取openId 用于下单参数 private String getOpenId(String code,AppletSetting appletSetting) throws ServletException, IOException { HttpGet httpGet = new HttpGet("https://api.weixin.qq.com/sns/jscode2session?appid=" + appletSetting.getAppId() + "&secret=" + appletSetting.getAppSecret() + "&js_code=" + code + "&grant_type=authorization_code"); //设置请求器的配置 HttpClient httpClient = HttpClients.createDefault(); HttpResponse res = httpClient.execute(httpGet); HttpEntity entity = res.getEntity(); String result=EntityUtils.toString(entity, "UTF-8"); return convertOpenId(result); } //结果转Map 取出openId private String convertOpenId(String result){ Gson gson = new Gson(); Map<String, Object> map = new HashMap<String, Object>(); map = gson.fromJson(result, map.getClass()); String openId=(String) map.get("openid"); return openId; } //xml 转json 取prepay_id private OrderReturnInfo convertXml(String result){ JSONObject obj = new JSONObject(); try { Document doc = DocumentHelper.parseText(result); Element root = doc.getRootElement(); obj.put(root.getName(), iterateElement(root)); OrderReturnInfo orderReturnInfo = JSON.toJavaObject(obj.getJSONObject("xml"),OrderReturnInfo.class); return orderReturnInfo; }catch (Exception e){ e.printStackTrace(); return null; } } @SuppressWarnings("unchecked") private static Map iterateElement(Element element) { List jiedian = element.elements(); Element et = null; Map obj = new HashMap(); Object temp; List list = null; for (int i = 0; i < jiedian.size(); i++) { list = new LinkedList(); et = (Element) jiedian.get(i); if (et.getTextTrim().equals("")) { if (et.elements().size() == 0) continue; if (obj.containsKey(et.getName())) { temp = obj.get(et.getName()); if(temp instanceof List){ list = (List)temp; list.add(iterateElement(et)); }else if(temp instanceof Map){ list.add((HashMap)temp); list.add(iterateElement(et)); }else{ list.add((String)temp); list.add(iterateElement(et)); } obj.put(et.getName(), list); }else{ obj.put(et.getName(), iterateElement(et)); } } else { if (obj.containsKey(et.getName())) { temp = obj.get(et.getName()); if(temp instanceof List){ list = (List)temp; list.add(et.getTextTrim()); }else if(temp instanceof Map){ list.add((HashMap)temp); list.add(iterateElement(et)); }else{ list.add((String)temp); list.add(et.getTextTrim()); } obj.put(et.getName(), list); }else{ obj.put(et.getName(), et.getTextTrim()); } } } return obj; }
OrderInfo:
/** * 预订单 * * @author zuoliangzhu * */ public class OrderInfo { private String appid;// 小程序ID private String mch_id;// 商户号 private String nonce_str;// 随机字符串 private String sign_type;//签名类型 private String sign;// 签名 private String body;// 商品描述 private String out_trade_no;// 商户订单号 private String total_fee;// 标价金额 ,单位为分 private String spbill_create_ip;// 终端IP private String notify_url;// 通知地址 private String trade_type;// 交易类型 private String openid;//用户标识
}
public class Configure { private static String key = "你的商户的api秘钥"; //商户号 private static String mch_id = ""; //
}
Signature:
public class Signature { private static final Logger L = Logger.getLogger(Signature.class); /** * 签名算法 * @param o 要参与签名的数据对象 * @return 签名 * @throws IllegalAccessException */ public static String getSign(Object o) throws IllegalAccessException { ArrayList<String> list = new ArrayList<String>(); Class cls = o.getClass(); Field[] fields = cls.getDeclaredFields(); for (Field f : fields) { f.setAccessible(true); if (f.get(o) != null && f.get(o) != "") { String name = f.getName(); XStreamAlias anno = f.getAnnotation(XStreamAlias.class); if(anno != null) name = anno.value(); list.add(name + "=" + f.get(o) + "&"); } } int size = list.size(); String [] arrayToSort = list.toArray(new String[size]); Arrays.sort(arrayToSort, String.CASE_INSENSITIVE_ORDER); StringBuilder sb = new StringBuilder(); for(int i = 0; i < size; i ++) { sb.append(arrayToSort[i]); } String result = sb.toString(); result += "key=" + Configure.getKey();//后期需要从数据库中取数据 System.out.println("签名数据:"+result); result = MD5.MD5Encode(result).toUpperCase(); return result; } public static String getSign(Map<String,Object> map){ ArrayList<String> list = new ArrayList<String>(); for(Map.Entry<String,Object> entry:map.entrySet()){ if(entry.getValue()!=""){ list.add(entry.getKey() + "=" + entry.getValue() + "&"); } } int size = list.size(); String [] arrayToSort = list.toArray(new String[size]); Arrays.sort(arrayToSort, String.CASE_INSENSITIVE_ORDER); StringBuilder sb = new StringBuilder(); for(int i = 0; i < size; i ++) { sb.append(arrayToSort[i]); } String result = sb.toString(); result += "key=" + Configure.getKey();//后期需要从数据库中取数据 //Util.log("Sign Before MD5:" + result); result = MD5.MD5Encode(result).toUpperCase(); //Util.log("Sign Result:" + result); return result; } }
如果运行不起来 可以加QQ 976452322