微信授权与JSAPI支付

前言

最近在工作中有一个需求需要使用到JSAPI支付。我简单看了一下JSAPI支付,需要传递一些参数,其中就有openId,也就是说在支付之前需要获取用户的openId,也就是网页授权,所以就从网页授权开始做起。

微信公众号网页授权

1.首先想要获取用户信息的话,需要用到微信公众号的接口。如果没有认证的公众号的话可以申请测试公众号,可以提供测试接口。链接:https://mp.weixin.qq.com/debug/cgi-bin/sandbox?t=sandbox/login
在这里插入图片描述
2.当我们有了测试服务号之后,就可以设置接口了。第一步先设置授权回调页面域名,如果没有备案域名,可以搜索natapp进行购买通道,方便快捷。
在这里插入图片描述
3.先简单描述一下微信公众号的授权流程。

4.上面描述完了授权流程之后,下面说一下主要的代码实现。

 在github中有很多方便的sdk对微信进行了封装,在这里我选用weixin-java-mp这个jar包,
 [github地址](https://github.com/Wechat-Group/WxJava)
		<!--微信授权-->
        <dependency>
            <groupId>com.github.binarywang</groupId>
            <artifactId>weixin-java-mp</artifactId>
            <version>${weixin-java-mp.version}</version>
        </dependency>
使用weixin-java-mp工具之前,需要对其进行初始化操作,初始化有很多种方法,这里我只说一下我的
  • 配置文件
#公众号appid
wx_appid=
#公众号appsecret
wx_appsecret=
wx_token=
wx_aeskey=
  • 第一步:配置config类,从properties文件中读取到这些数据
@Configuration
public class WxMpConfig {
  @Value("#{wxProperties.wx_token}")
  private String token;

  @Value("#{wxProperties.wx_appid}")
  private String appid;

  @Value("#{wxProperties.wx_appsecret}")
  private String appSecret;

  @Value("#{wxProperties.wx_aeskey}")
  private String aesKey;

  public String getToken() {
    return this.token;
  }

  public String getAppid() {
    return this.appid;
  }

  public String getAppSecret() {
    return this.appSecret;
  }

  public String getAesKey() {
    return this.aesKey;
  }

}
  • 第二步:继承WxMpServiceImpl类,通过@PostConstruct注解对其进行初始化操作
@Service
public class WeixinService extends WxMpServiceImpl {

  @Autowired
  private WxMpConfig wxConfig;

  @PostConstruct
  public void init() {
    final WxMpDefaultConfigImpl config = new WxMpDefaultConfigImpl();
    // 设置微信公众号的appid
    config.setAppId(this.wxConfig.getAppid());
    // 设置微信公众号的app corpSecret
    config.setSecret(this.wxConfig.getAppSecret());
    // 设置微信公众号的token
    config.setToken(this.wxConfig.getToken());
    // 设置消息加解密密钥
    config.setAesKey(this.wxConfig.getAesKey());
    super.setWxMpConfigStorage(config);

  }

}
  • 第三步:编写controller类
@Controller
@RequestMapping("/api/wechat")
@Api(tags = "微信授权")
@RequiredArgsConstructor
public class WeChatController {

    private static Logger logger = LogManager.getLogger(WeChatController.class.getName());

    @Autowired
    private WxMpService wxMpService;


    @ApiOperation("微信授权")
    @GetMapping("/authorize")
    public String authorize(@RequestParam("returnUrl") String returnUrl) {
        String url = WeChatNotifyUrl.WECHAT_AUTH_NOTIFY_URL;
        String redirectUrl = wxMpService.oauth2buildAuthorizationUrl(url, WxConsts.OAuth2Scope.SNSAPI_USERINFO, URLEncoder.encode(returnUrl));
        logger.info("【微信网页授权】获取code,redirectUrl=" + redirectUrl);
        //重定向到下面一个方法
        return "redirect:" + redirectUrl;
    }

    @ApiOperation("获取用户信息")
    @GetMapping("/userInfo")
    public String userInfo(@RequestParam("code") String code,
                           @RequestParam("state") String returnUrl) {
        //获取openId
        WxMpOAuth2AccessToken wxMpOAuth2AccessToken;
        try {
            wxMpOAuth2AccessToken = wxMpService.oauth2getAccessToken(code);
        } catch (WxErrorException e) {
            logger.error("wxErrorExceptionMsg === {}",e);
            throw new ServiceException(e);
        }

        //获取用户基本信息
        WxMpUser wxMpUser = null;
        try {
            wxMpUser = wxMpService.oauth2getUserInfo(wxMpOAuth2AccessToken, null);
        } catch (WxErrorException e) {
            logger.error("wxErrorExceptionMsg === {}",e);
            throw new ServiceException(e);
        }

        Assert.notNull(wxMpUser);
        logger.info("openId === {} ; unionId === {}",wxMpOAuth2AccessToken.getOpenId(),wxMpUser.getUnionId());

        return "redirect:" + returnUrl + "?openId=" + wxMpUser.getOpenId() + "&unionId=" + wxMpUser.getUnionId();
    }
  • 以上就是授权的步骤了,当授权成功之后可以自定义需要跳转的页面与传递的参数,大家可以自行测试

微信公众号JSAPI支付

1.微信公众号的JSAPI支付请参考:https://blog.csdn.net/fight_man8866/article/details/79657562
我也是从这边博客中学习的
2.下面主要讲一下weixin-java-pay的使用

  • 首先导入weixin-java-pay的依赖,这个工具的作者与weixin-java-mp的作者是同一位,github地址
	<!--微信支付框架-->
        <dependency>
            <groupId>com.github.binarywang</groupId>
            <artifactId>weixin-java-pay</artifactId>
            <version>3.6.0</version>
        </dependency>
  • 配置文件
#微信支付商户号
mchId=
#微信支付平台商户API密钥
mchKey=
#apiclient_cert.p12 证书文件的绝对路径
keyPath=
#微信小程序appId
appId=
#服务商模式下的子商户公众账号ID
subAppId=
#服务商模式下的子商户号
subMchId=
  • 对WxPayService进行初始化
@Configuration
public class WxPayConfiguration {
    @Value("#{wxPayProperties.appId}")
    private String appId;

    @Value("#{wxPayProperties.mchId}")
    private String mchId;

    @Value("#{wxPayProperties.mchKey}")
    private String mchKey;

    @Value("#{wxPayProperties.subAppId}")
    private String subAppId;

    @Value("#{wxPayProperties.subMchId}")
    private String subMchId;

    @Value("#{wxPayProperties.keyPath}")
    private String keyPath;

    @Bean
    public WxPayConfig payConfig() {
        WxPayConfig payConfig = new WxPayConfig();
        payConfig.setAppId(this.appId);
        payConfig.setMchId(this.mchId);
        payConfig.setMchKey(this.mchKey);
        payConfig.setSubAppId(this.subAppId);
        payConfig.setSubMchId(this.subMchId);
        payConfig.setKeyPath(this.keyPath);

        return payConfig;
    }

    @Bean
    public WxPayService payService() {
        WxPayService payService = new WxPayServiceImpl();
        payService.setConfig(payConfig());
        return payService;
    }
}
  • 创建订单,向前端返回固定格式的数据
    @ApiOperation("支付")
    @GetMapping("/createOrder")
    @ResponseBody
    public WxPayMpOrderResult createOrder( String openId, Integer totalFee) {
        String date = DateUtil.format(new Date(), "yyyyMMddHHmmss");
        WxPayUnifiedOrderRequest orderRequest = new WxPayUnifiedOrderRequest();

        String nonceStr = WeChatPayUtil.createNonceStr();

        wxPayConfig.getMchKey();

        String notifyUrl = WeChatNotifyUrl.WECHAT_PAY_NOTIFY_URL;
        String tradeNo = OrderUtil.createOrderNumber();

        //创建map创建签名
        TreeMap<String, String> map = new TreeMap<>();
        map.put("appid", wxPayConfig.getAppId());
        map.put("mch_id", wxPayConfig.getMchId());
        map.put("device_info", "WEB");
        map.put("body", "test");
        map.put("trade_type", WxConstant.PAY_TYPE);
        map.put("nonce_str", nonceStr);
        map.put("notify_url", notifyUrl);
        map.put("out_trade_no", tradeNo);
        map.put("total_fee", String.valueOf(totalFee));
        map.put("openid", openId);

        //签名
        String sign = WeChatPayUtil.createSign(map, wxPayConfig.getMchKey());

        //构造订单请求数据
        orderRequest.setOpenid(openId);
        orderRequest.setAppid(wxPayConfig.getAppId());
        orderRequest.setTimeStart(date);
        orderRequest.setMchId(wxPayConfig.getMchId());
        orderRequest.setDeviceInfo("WEB");
        orderRequest.setBody("test");
        orderRequest.setNonceStr(nonceStr);
        orderRequest.setTotalFee(totalFee);
        orderRequest.setOutTradeNo(tradeNo);
        orderRequest.setSign(sign);
        orderRequest.setTradeType(WxConstant.PAY_TYPE);
        orderRequest.setNotifyUrl(notifyUrl);
        orderRequest.setSpbillCreateIp("127.0.0.1");

        WxPayMpOrderResult order = null;

        try {
            order = wxPayService.createOrder(orderRequest);
        } catch (WxPayException e) {
            logger.error("wxPayError === {}", e);
            throw new ServiceException(e);
        }
        
        return order;
    }
  • 接受支付之后,微信服务器向客户端发送的异步通知
    @ApiOperation("异步通知")
    @GetMapping("/payNotify")
    @ResponseBody
    public String parseOrderNotifyResult(@RequestBody String xmlData) throws WxPayException {
        WxPayOrderNotifyResult notifyResult = wxPayService.parseOrderNotifyResult(xmlData);
        Assert.notNull(notifyResult);
       	//TODO 执行自己的业务逻辑
        return WxPayNotifyResponse.success("ok");
    }
  • 在WxPayNotifyResponse.success(“ok”)这个调用中,weixin-java-pay对返回进行了封装,做了验证sign等操作,方便了调用
  • 以上就是支付工具的使用,在实际的开发工作中能够发挥很大作用,省去了很多麻烦的事情
  • 0
    点赞
  • 2
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值