HBuilder打包h5实现微信支付前后端

背景:前端使用HBuilder打包h5,后端使用java.

首先在微信开放平台注册一个移动应用:https://open.weixin.qq.com/cgi-bin/index?t=home/index&lang=zh_CN

对创建的应用进行一些功能上的申请:由于我使用的是公司账号,通过绑定公司的商户号获取微信支付功能.

如图微信支付功能为已获得状态的时候,就可以继续进行下一步操作了.

微信开放平台的包名和签名有获取的规则,不过多进行叙述.

 

由于使用HBuilder打包h5,我们先看一下微信的统一下单:https://pay.weixin.qq.com/wiki/doc/api/app/app.php?chapter=9_1

按照开放平台给的文档的规则请求:https://api.mch.weixin.qq.com/pay/unifiedorder

得到返回的订单信息:

注意点:

对统一下单接口进行请求之后返回的sign签名并不是调用支付接口需要的签名.只是生成的签名方式要保持一次.

也就是说,统一下单我们需要生成一次sign,调用支付接口还需要生成一次sign.

由于package是java的关键字,

"package","Sign=WXPay"

只能进行前端拼接,但是后端生成sign的时候还要添加进去.

到这里后端的一些处理已经基本完成.

下面是前端的一些问题:

我们进入HBuilder官网,找到支付插件配置页面:https://ask.dcloud.net.cn/article/71

以下是HBuilder给的前端实例代码:

var channel=null;  
// 1. 获取支付通道  
function plusReady(){ //uni-app中将此function里的代码放入vue页面的onLoad生命周期中  // 获取支付通道  plus.payment.getChannels(function(channels){  channel=channels[0];  },function(e){  alert("获取支付通道失败:"+e.message);  });  
}  
document.addEventListener('plusready',plusReady,false);//uni-app不需要此代码  var ALIPAYSERVER='http://demo.dcloud.net.cn/helloh5/payment/alipay.php?total=';  
var WXPAYSERVER='http://demo.dcloud.net.cn/helloh5/payment/wxpay.php?total=';  
// 2. 发起支付请求  
function pay(id){  // 从服务器请求支付订单  var PAYSERVER='';  if(id=='alipay'){  PAYSERVER=ALIPAYSERVER;  }else if(id=='wxpay'){  PAYSERVER=WXPAYSERVER;  }else{  plus.nativeUI.alert("不支持此支付通道!",null,"捐赠");  return;  }  var xhr=new XMLHttpRequest(); //uni-app中请使用uni的request api联网  xhr.onreadystatechange=function(){  switch(xhr.readyState){  case 4:  if(xhr.status==200){  plus.payment.request(channel,xhr.responseText,function(result){  plus.nativeUI.alert("支付成功!",function(){  back();  });  },function(error){  plus.nativeUI.alert("支付失败:" + error.code);  });  }else{  alert("获取订单信息失败!");  }  break;  default:  break;  }  }  xhr.open('GET',PAYSERVER);  xhr.send();  
}

然后按下面的配置操作一番,进行打包Android版本,进行真机测试.

这时候我们发现,可以进行支付宝测试,但是无法唤起微信支付.

下面是对HBuilder前端进行的一些修改:

Hello MUI

这样就能唤醒微信支付,同时完成付款了.

HBuilder打包的时候使用自有证书,同时保证签名与微信开放平台一致.

此处Appid与微信开放平台生成的一致:

HBuilder打包h5微信支付,最主要的问题就是HBuilder官网给的前端数据是有问题的.

下面是一些后端使用到的工具类;

生成sign签名:

package com.jixiu.user.utils;import org.apache.commons.lang3.StringUtils;
import org.assertj.core.util.Lists;import java.security.MessageDigest;
import java.util.*;public class  EncodeSign {/*** sign 签名 (参数名按ASCII码从小到大排序(字典序)+key+MD5+转大写签名)* @param map* @return*/public static String encodeSign(SortedMap map, String key){if(StringUtils.isEmpty(key)){throw new RuntimeException("签名key不能为空");}Set> entries = map.entrySet();Iterator> iterator = entries.iterator();List values = Lists.newArrayList();while(iterator.hasNext()){Map.Entry entry = (Map.Entry) iterator.next();String k = String.valueOf(entry.getKey());String v = String.valueOf(entry.getValue());if (StringUtils.isNotEmpty(v) && entry.getValue() !=null && !"sign".equals(k) && !"key".equals(k)) {values.add(k + "=" + v);}}values.add("key="+ key);String sign = StringUtils.join(values, "&");System.out.println(sign+"计算之前的值");return MD5.MD5Encode(sign,"utf8").toUpperCase();}}

调起支付接口需要的参数封装的实体类:

package com.jixiu.user.pojo;import io.swagger.annotations.ApiModelProperty;
import lombok.Data;
import org.springframework.boot.context.properties.ConfigurationProperties;
import org.springframework.stereotype.Component;import javax.xml.bind.annotation.XmlAccessType;
import javax.xml.bind.annotation.XmlAccessorType;
import javax.xml.bind.annotation.XmlRootElement;
import javax.xml.bind.annotation.XmlType;@Data
@Component
@ConfigurationProperties(prefix = "weixin")
@XmlAccessorType(XmlAccessType.FIELD)
//xml文件根标识
@XmlRootElement(name = "xml")
//控制JAXB绑定类中属性和字段的排序
@XmlType(propOrder = {"appid","mch_id","nonce_str","body","out_trade_no","total_fee","spbill_create_ip","notify_url","trade_type","sign","sign_type"
})
public class PlaceAnOrder {//应用idprivate String appid;//商户号private String mch_id;//随机字符串private String nonce_str;//商品描述private String body;//商户订单号private String out_trade_no;//总金额private String total_fee;//终端ipprivate String spbill_create_ip;//通知地址private String notify_url;//交易类型private String trade_type;//签名private String sign;//签名类型private String sign_type;}

对象转XML字符串:

package com.jixiu.user.utils;import java.io.FileNotFoundException;
import java.io.FileReader;
import java.io.FileWriter;
import java.io.IOException;
import java.io.StringReader;
import java.io.StringWriter;import javax.xml.bind.JAXBContext;
import javax.xml.bind.JAXBException;
import javax.xml.bind.Marshaller;
import javax.xml.bind.Unmarshaller;/*** 封装了XML转换成object,object转换成XML的代码** @author Steven**/
public class XMLUtil {/*** 将对象直接转换成String类型的 XML输出** @param obj* @return*/public static String convertToXml(Object obj) {// 创建输出流StringWriter sw = new StringWriter();try {// 利用jdk中自带的转换类实现JAXBContext context = JAXBContext.newInstance(obj.getClass());Marshaller marshaller = context.createMarshaller();// 格式化xml输出的格式marshaller.setProperty(Marshaller.JAXB_FORMATTED_OUTPUT,Boolean.TRUE);// 将对象转换成输出流形式的xmlmarshaller.marshal(obj, sw);} catch (JAXBException e) {e.printStackTrace();}return sw.toString();}/*** 将对象根据路径转换成xml文件** @param obj* @param path* @return*/public static void convertToXml(Object obj, String path) {try {// 利用jdk中自带的转换类实现JAXBContext context = JAXBContext.newInstance(obj.getClass());Marshaller marshaller = context.createMarshaller();// 格式化xml输出的格式marshaller.setProperty(Marshaller.JAXB_FORMATTED_OUTPUT,Boolean.TRUE);// 将对象转换成输出流形式的xml// 创建输出流FileWriter fw = null;try {fw = new FileWriter(path);} catch (IOException e) {e.printStackTrace();}marshaller.marshal(obj, fw);} catch (JAXBException e) {e.printStackTrace();}}@SuppressWarnings("unchecked")/*** 将String类型的xml转换成对象*/public static Object convertXmlStrToObject(Class clazz, String xmlStr) {Object xmlObject = null;try {JAXBContext context = JAXBContext.newInstance(clazz);// 进行将Xml转成对象的核心接口Unmarshaller unmarshaller = context.createUnmarshaller();StringReader sr = new StringReader(xmlStr);xmlObject = unmarshaller.unmarshal(sr);} catch (JAXBException e) {e.printStackTrace();}return xmlObject;}@SuppressWarnings("unchecked")/*** 将file类型的xml转换成对象*/public static Object convertXmlFileToObject(Class clazz, String xmlPath) {Object xmlObject = null;try {JAXBContext context = JAXBContext.newInstance(clazz);Unmarshaller unmarshaller = context.createUnmarshaller();FileReader fr = null;try {fr = new FileReader(xmlPath);} catch (FileNotFoundException e) {e.printStackTrace();}xmlObject = unmarshaller.unmarshal(fr);} catch (JAXBException e) {e.printStackTrace();}return xmlObject;}
}

java发送post请求:

public static String sendPost(String url, Map param) {PrintWriter out = null;BufferedReader in = null;String result = "";try {URL realUrl = new URL(url);// 打开和URL之间的连接URLConnection conn = realUrl.openConnection();// 设置通用的请求属性conn.setRequestProperty("accept", "application/json");//设置请求类型,注意第三方文档接口的要求,一定要保持一致conn.setRequestProperty("Content-Type", "application/json");conn.setRequestProperty("connection", "Keep-Alive");conn.setRequestProperty("user-agent", "Mozilla/4.0 (compatible; MSIE 6.0; Windows NT 5.1;SV1)");// 发送POST请求必须设置如下两行conn.setDoOutput(true);conn.setDoInput(true);// 获取URLConnection对象对应的输出流out = new PrintWriter(conn.getOutputStream());JSONObject jsonObject = new JSONObject(param);//配置jsonObject.put("grant_type", "client_credentials");jsonObject.put("client_id", "YXA6_9BOlrnhSWSb-FUk0fvzqw");jsonObject.put("client_secret", "YXA6FIe8F_euvzf-NosJ7nXCx-MMosk");out.print(jsonObject);// flush输出流的缓冲out.flush();// 定义BufferedReader输入流来读取URL的响应in = new BufferedReader(new InputStreamReader(conn.getInputStream()));String line;while ((line = in.readLine()) != null) {result += line;}} catch (Exception e) {System.out.println("发送 POST 请求出现异常!" + e);e.printStackTrace();}// 使用finally块来关闭输出流、输入流finally {try {if (out != null) {out.close();}if (in != null) {in.close();}} catch (IOException ex) {ex.printStackTrace();}}return result;}

结束.


本文来自互联网用户投稿,文章观点仅代表作者本人,不代表本站立场,不承担相关法律责任。如若转载,请注明出处。 如若内容造成侵权/违法违规/事实不符,请点击【内容举报】进行投诉反馈!

相关文章

立即
投稿

微信公众账号

微信扫一扫加关注

返回
顶部