SpringBoot实战项目精华总结 -- 微信公众号(三)

SpringBoot实战项目精华总结 -- 微信公众号(三)

  注:这里的总结仅供自己以后参考,游客还请以微信官方文档为主
 一、微信特性
  1.微信授权
    1.1 网页域名授权配置
    1.2 获取openid
    手工方式
    利用第三方SDK(github上 => weixin-java-tools)
    1.3 前后端联调
 二、微信支付
  1.官网文档
  2.公众号里发起支付
  3.第三方SDK
  4.支付时序
    4.1 发起统一下单
    4.2 利用预付单信息+freemarker完成动态参数注入js签名,唤起前端支付
    4.3 最后通过微信内置对象WeixinJSBridge唤起支付密码输入弹窗

  5.处理微信异步通知(API列表=>支付结果通知)
 三、微信退款
  1.基于SDK的方法代码
  2.退款微信也会调用异步通知(与支付异步通知同一接口)需要处理
 四、其他
  1.基于Gson的Json格式化工具

一、微信特性
 1.微信授权 
  官网文档:https://developers.weixin.qq.com/doc/offiaccount/Getting_Started/Overview.html
  1.1 网页域名授权配置
    -> 本地开发环境使用内网穿透:https://natapp.cn/ 将本地的8080端口映射到购买的可用于微信开发的二级域名,注意要买备案的
    -> 在微信公众平台=>功能设置=>网页授权域名,下载文件存放至 resource/static 目录下
    -> 启动natapp.exe(参考natapp1分钟教程),启动本地项目(临时去掉 server.context-path 设置)
    -> 微信公众平台填写买到的二级域名,完成保存。设置后即可删除txt文件
  1.2 获取openid
  手工方式
    -> 先调微信授权接口并指定回调地址,用户端弹出授权框,同意后可获取code
    -> 回调地址接口接收到微信的回调,带回code,code只能使用一次,5分钟有效期
    -> 后端微信回调的接口再使用code+appid+secret获取access_token+openid+refresh_token
    -> 使用access_token+openid拉取用户基本信息,但注意拉取得信息编码是ISO-8859-1编码
    -> 对用户信息的转码操作 new String(response.getBytes("ISO-8859-1"), "UTF-8")

  利用第三方SDK(github上 => weixin-java-tools)

<dependency>
  <groupId>com.github.binarywang</groupId>
  <artifactId>weixin-java-mp</artifactId>
  <version>2.7.0</version>
</dependency>

    -> 前端发起用户授权请求,入参为回调地址(前端接收授权后openid的地址)
  1.3 前后端联调
    -> 手机网页抓包工具charles及破解教程:https://www.cnblogs.com/jiayuchn-test/p/8875105.html
    -> 10003 redirect_uri域名与后台配置不一致:公众号设置=>功能设置=>网页授权域名 必须要与 授权链接 https://open.weixin.qq.com/connect/oauth2/authorize?appid=wx69fxxxxxxxxed8&redirect_uri=http%3a%2f%2fwww.xxx.com%2fvShop%2fdefault&response_type=code&scope=snsapi_base&state=STATE#wechat_redirect 中redirect_uri一致!
二、微信支付
 1.官网文档
  https://pay.weixin.qq.com/wiki/doc/api/index.html
 2.公众号里发起支付
  https://pay.weixin.qq.com/wiki/doc/api/jsapi.php?chapter=7_4
 3.第三方SDK
  https://github.com/Pay-Group/best-pay-sdk

 4.支付时序
  4.1 发起统一下单
  notifyUrl(异步通知必填)设置为自己单独的接口地址给微信支付平台调用,传来预付单信息,此时微信端已经记录下“订单号+订单金额”信息(所以只改订单金额是不行的)

  4.2 利用预付单信息+freemarker完成动态参数注入js签名,唤起前端支付

<dependency>
  <groupId>org.springframework.boot</groupId>
  <artifactId>spring-boot-starter-freemarker</artifactId>
</dependency>

pay/create.ftl

<script>
  function onBridgeReady(){
  WeixinJSBridge.invoke(
    'getBrandWCPayRequest', {
      "appId":"${payResponse.appId}",   //公众号名称,由商户传入
      "timeStamp":"${payResponse.timeStamp}",   //时间戳,自1970年以来的秒数
      "nonceStr":"${payResponse.nonceStr}", //随机串
      "package":"${payResponse.packAge}",
      "signType":"MD5",   //微信签名方式:
      "paySign":"${payResponse.paySign}" //微信签名
    },
    function(res){
//      if(res.err_msg == "get_brand_wcpay_request:ok" ) {
//      }   // 使用以上方式判断前端返回,微信团队郑重提示:res.err_msg将在用户支付成功后返回  ok,但并不保证它绝对可靠。
      location.href = "${returnUrl}";
    }
  );
  }
  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>

  4.3 最后通过微信内置对象WeixinJSBridge唤起支付密码输入弹窗

 5.处理微信异步通知(API列表=>支付结果通知)

/**
 * 微信异步通知
 * @param notifyData
 */
@PostMapping("/notify")
public ModelAndView notify(@RequestBody String notifyData) {
  payService.notify(notifyData);
  //返回给微信处理结果
  return new ModelAndView("pay/success");
}

pay/success.ftl 告诉微信订单处理成功,就不会再收到微信通知支付成功了

<xml>
  <return_code><![CDATA[SUCCESS]]></return_code>
  <return_msg><![CDATA[OK]]></return_msg>
</xml>

三、微信退款
  官方文档:https://pay.weixin.qq.com/wiki/doc/api/jsapi.php?chapter=9_4
 1.基于SDK的方法代码
  需要封装一个退款请求类:RefundRequest(订单号,订单金额,支付类型)

/**
 * 退款
 * @param orderDTO
 */
@Override
public RefundResponse refund(OrderDTO orderDTO) {
  RefundRequest refundRequest = new RefundRequest();
  refundRequest.setOrderId(orderDTO.getOrderId());
  refundRequest.setOrderAmount(orderDTO.getOrderAmount().doubleValue());
  refundRequest.setPayTypeEnum(BestPayTypeEnum.WXPAY_MP);
  log.info("【微信退款】request={}", JsonUtil.toJson(refundRequest));

  RefundResponse refundResponse = bestPayService.refund(refundRequest);
  log.info("【微信退款】response={}", JsonUtil.toJson(refundResponse));

  return refundResponse;
}

 2.退款微信也会调用异步通知(与支付异步通知同一接口)需要处理
四、其他
 1.基于Gson的Json格式化工具

/**
 * @Description Json格式化处理工具
 * @Date 2020/2/16 12:08
 */
public class JsonUtil {
  public static String toJson(Object object) {
    GsonBuilder gsonBuilder = new GsonBuilder();
    gsonBuilder.setPrettyPrinting();
    Gson gson = gsonBuilder.create();
    return gson.toJson(object);
  }
}

 

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章