7 接入微信
7.1 接入分析
惠民支付平台是将各各常用的第三方支付渠道统一为一个支付通道,前边实现了C扫B支付宝支付的流程,下边接入 微信支付,根据接入支付宝的流程分析接入微信需要实现的如下:
1、支付入口
顾客扫码进入支付入口,根据客户端类型判断是微信还是支付宝,是支付宝则直接进入收银台,如果是微信则需要 首先获取openid,再进入收银台。
2、立即支付
点击立即支付调用微信的统一下单接口,若下单成功则唤起微信客户端开始支付。 3、获取支付结果
调用微信的“支付结果查询”接口获取支付结果。
7.2 支付入口
7.2.1 获取openid接口
参考:惠民支付-第3章-微信支付接入指南.pdf
7.2.2 获取微信授权码
用户进入支付入口,判断客户端类型如果是微信则获取微信授权码。 根据获取openid的流程得知,第一步获取微信授权码,这里需要生成获取微信授权码的URL,由页面重定向即可。 1、在nacos中交易服务的主配置文件中添加如下参数:
weixin:
oauth2RequestUrl: "https://open.weixin.qq.com/connect/oauth2/authorize"
oauth2CodeReturnUrl: "http://xfc.nat300.top/transaction/wx‐oauth‐code‐return"
oauth2Token: "https://api.weixin.qq.com/sns/oauth2/access_token"
2、在交易服务PayController中添加获取微信授权码方法。
@Value("${weixin.oauth2RequestUrl}")
private String wxOAuth2RequestUrl;
@Value("${weixin.oauth2CodeReturnUrl}")
private String wxOAuth2CodeReturnUrl;
/**
\* 获取微信授权码
*
\* @param order 订单对象
\* @return
\* @throws Exception
*/
@Override
public String getWXOAuth2Code(PayOrderDTO order) throws BusinessException {
//将订单信息封装到state参数中
String state = EncryptUtil.encodeUTF8StringBase64(JSON.toJSONString(order));
//应用id
String appId = order.getAppId();
//服务类型
String channel = order.getChannel();
//获取微信支付渠道参数,根据应用、服务类型、支付渠道查询支付渠道参数
PayChannelParamDTO payChannelParamDTO =
payChannelService.queryParamByAppPlatformAndPayChannel(appId,
channel, "WX_JSAPI");
if(payChannelParamDTO == null){
throw new BusinessException(CommonErrorCode.E_300007);
}
//支付渠道参数
String payParam = payChannelParamDTO.getParam();
WXConfigParam wxConfigParam = JSON.parseObject(payParam, WXConfigParam.class);
try {
String url = String
.format("%s?appid=%s&scope=snsapi_base&state=%s&redirect_uri=%s",
wxOAuth2RequestUrl, wxConfigParam.getAppId(),
state, URLEncoder.encode(wxOAuth2CodeReturnUrl, "utf‐8"));
log.info("微信生成授权码url:{}",url);
return "redirect:" + url;
} catch (UnsupportedEncodingException e) {
e.printStackTrace();
return "forward:/pay‐page‐error";//生成获取授权码链接失败
}
}
2、支付入口调用微信授权码获取方法
@RequestMapping(value = "/pay‐entry/{ticket}")
public String payEntry(@PathVariable("ticket") String ticket,HttpServletRequest request) {
...
BrowserType browserType = BrowserType.valueOfUserAgent(request.getHeader("user‐agent"));
switch (browserType) {
case ALIPAY: //直接跳转收银台pay.html
return "forward:/pay‐page?" + toParamsString(order);
case WECHAT: //获取授权码(待实现)
return transactionService.getWXOAuth2Code(order);
default:
}
...
}
7.2.3 微信授权码回调接口
授权码获取成功后微信会将授权码传入授权码回调URL,在授权码回调接口中实现获取openid。
7.2.3.1 接口定义
1、在PayController中定义微信授权码回调接口
@ApiOperation("微信授权码回调")
@GetMapping("/wx‐oauth‐code‐return")
public String wxOAuth2CodeReturn(@RequestParam String code, @RequestParam String state) {
//获取openid
//重定向到支付确认页面
}
2、在TransactionService中定义获取openid方法
/**
\* 获取微信openid
*
\* @param code 授权id
\* @param appId 应用id,用于获取微信支付的参数
\* @return openid
*/
public String getWXOAuthOpenId(String code, String appId);
7.2.3.2 接口实现
1、添加RestTemplate配置
使用RestTemplate发起http请求,在huiminpay-transaction-service工程的pom.xml中添加依赖:
<!‐‐ okhttp3 ‐‐>
<dependency>
<groupId>com.squareup.okhttp3</groupId>
<artifactId>okhttp</artifactId>
</dependency>
在TransactionBootstrap中注入RestTemplate
@Bean
public RestTemplate restTemplate() {
return new RestTemplate(new OkHttp3ClientHttpRequestFactory());
}
2、添加获取openid地址配置
在nacos中向交易服务添加获取openid地址配置,如下:
weixin:
oauth2Token: "https://api.weixin.qq.com/sns/oauth2/access_token"
3、getWXOAuthOpenId接口实现
/**
\* 获取微信openid
\* @param code 授权id
\* @param appId 应用id,用于获取微信支付的参数
\* @param channel 服务类型,用于获取微信支付的参数
\* @return openid
*/
@Override
public String getWXOAuthOpenId(String code, String appId) {
//获取微信支付渠道参数,根据应用、服务类型、支付渠道查询支付渠道参数
PayChannelParamDTO payChannelParamDTO =
payChannelService.queryParamByAppPlatformAndPayChannel(appId, "huimin_c2b", "WX_JSAPI");
if(payChannelParamDTO == null){
throw new BusinessException(CommonErrorCode.E_300007);
}
//支付渠道参数
String payParam = payChannelParamDTO.getParam();
WXConfigParam wxConfigParam = JSON.parseObject(payParam, WXConfigParam.class);
//密钥
String appSecret = wxConfigParam.getAppSecret();
//获取openid地址
String url = String.format("%s?appid=%s&secret=%s&code=%s&grant_type=authorization_code",
oauth2Token,wxConfigParam.getAppId(), wxConfigParam.getAppSecret(), code);
ResponseEntity<String> exchange = restTemplate.exchange(tokenUrl, HttpMethod.GET, null, String.class);
String response = exchange.getBody();
return JSONObject.parseObject(response).getString("openid");
}
4、微信授权码回调接口实现
@ApiOperation("微信授权码回调")
@GetMapping("/wx‐oauth‐code‐return")
public String wxOAuth2CodeReturn(@RequestParam String code, @RequestParam String state) {
//将之前state中保存的订单信息读取出来
PayOrderDTO payOrderDTO = JSON.parseObject(EncryptUtil.decodeUTF8StringBase64(state), PayOrderDTO.class);
//应用id
String appId = payOrderDTO.getAppId();
//获取openid
String openId = transactionService.getWXOAuthOpenId(code,appId);
try {
//将订单信息转成query参数的形式拼接起来
String orderInfo = ParseURLPairUtil.parseURLPair(payOrderDTO);
//返回所有的query参数到支付确认页面
return String.format("forward:/pay‐page?openId=%s&%s", openId, orderInfo);
} catch (Exception e) {
e.printStackTrace();
return "forward:/pay‐page‐error";
}
}
7.2.4 测试
1、生成门店c扫b的二维码
2、打开内网穿透工具
3、打开模拟器,使用微信扫码
4、观察程序输出日志,确认openid是否生成成功,支付确认页面是否正常打开