Springboot 微信页面H5wap商家支付

在这里介绍的是使用SpringBoot 来完成对微信页面wap商家支付

前提:使用了springboot框架技术来整合,实现了微信授权拉去用户信息,

开通了微信认证的公众号以及申请了商家支付以及域名备案。

商家支付需要开通微信认证后的公众号才能申请,个人的话目前不能申请。

参考下方官方微信公众号支付开发文档,本次是用了wap网页支付。

https://pay.weixin.qq.com/wiki/doc/api/H5.php?chapter=15_1

自己看了文档说实话还是有点蒙蒙的,还是有结合一些相关视频进行学习,并简单实现微信支付。

wap支付是指商户在微信客户端外的移动端网页展示商品或服务,用户在前述页面确认使用微信支付时,商户发起本服务呼起微信客户端进行支付。

主要用于触屏版的手机浏览器请求微信支付的场景。可以方便的从外部浏览器唤起微信支付。


一、在项目导入相关支付pom依赖

用的是在github上别人写的一个封装包,可能版本有点旧,有兴趣的同学可以去github搜best-pay。

<dependency>

<groupId>cn.springboot</groupId>

<artifactId>best-pay-sdk</artifactId>

<version>1.2.0</version>

</dependency>

二、上微信支付商家平台

下方为官方微信支付商家网页

https://pay.weixin.qq.com/index.php/core/home/login

2.1 登录微信支付书,并点击产品中心,选中支付产品,JSAPI支付,里面会有相关支付展示

图1

2.2 开发配置

在使用JSAPI支付和Native支付需要配置开发需要的域名

在此需要点击添加,并注意右边的问号的提示


图2


2.3 添加备好案的域名

添加的时候看下提示,可以选择http和https

举例你的项目是   

www.xxxx.com/项目名/映射地址/

www.xxxx.com/demo/pay/

注意:配置上面的地址后,只要在pay地址的目录都可以。

例如    /pay/demo/           /pay/demo/demo2

图3

2.4 商户信息

第一步:需要微信支付商户号和密钥

第二步:点击商户信息和API设置密码


图4

第三步:设置商户的key密码并安装证书

按步骤申请证书下载和密钥设置

图5

三、项目配置

由于项目是使用springboot整合三大框架,所以在yml下配置已知的微信公众号appid、密钥、商户账号、密钥、证书目录以及需要用到的回调地址等。

图6

3.1 商户账户实体类

@Data

@Component

@ConfigurationProperties(prefix ="wechat")

public class WechatAccounConfig {

private StringmpAppId;

private StringmpAppSecret;

/**

* 商户号

*/

    private  StringmchId;

/**

* 商户密钥

*/

    private StringmchKey;

/**

* 商户证书路径

*/

    private StringkeyPath;

/**

* 微信支付异步通知地址

*

*/

    private StringnotifyUrl;

}

3.2 支付环境配置实体类

@Component

public class WechatPayConfig {

@Autowired

    private WechatAccounConfigaccounConfig;

@Bean

    public BestPayServiceImpl bestPayService(){

BestPayServiceImpl bestPayService =new BestPayServiceImpl();

bestPayService.setWxPayH5Config(wxPayH5Config());

return bestPayService;

}

@Bean

    public WxPayH5Config wxPayH5Config(){

WxPayH5Config wxPayH5Config =new WxPayH5Config();

wxPayH5Config.setAppId(accounConfig.getMpAppId());

wxPayH5Config.setAppSecret(accounConfig.getMpAppSecret());

wxPayH5Config.setMchId(accounConfig.getMchId());

wxPayH5Config.setMchKey(accounConfig.getMchKey());

wxPayH5Config.setKeyPath(accounConfig.getKeyPath());

wxPayH5Config.setNotifyUrl(accounConfig.getNotifyUrl());

return wxPayH5Config;

}

}

3.3 写一个支付接口的类并且实现

public interface PayService {

/**

* 创建支付订单

    * @param orderDTO

    */

    PayResponse create(OrderDTO orderDTO);

/**

* 异步通知

    * @param notify

    */

    PayResponse notify(String notify);

}

3.4 支付接口实现类

@Service("payService")

@Slf4j

public class PayServiceImplimplements PayService {

private static final StringORDER_NAME ="微信预约";

@Autowired

    private BestPayServiceImplbestPayService;

@Autowired

    private AppointOrderServiceorderService;

@Autowired

    private AppointmentMapperappointmentMapper;

@Override

    public PayResponse create(OrderDTO orderDTO) {

Appointment appointment =appointmentMapper.selectByPrimaryKey(orderDTO.getAppointId());

PayRequest payRequest =new PayRequest();

payRequest.setOpenid(orderDTO.getCustomerOpenid());

payRequest.setOrderAmount(orderDTO.getOrderAmount().doubleValue());

payRequest.setOrderId(orderDTO.getOrderId());

payRequest.setOrderName(ORDER_NAME);

payRequest.setPayTypeEnum(BestPayTypeEnum.WXPAY_H5);

log.info("[微信支付]发起支付,request={}", JsonUtil.toJson(payRequest));

PayResponse payResponse =bestPayService.pay(payRequest);

log.info("[微信支付]发起支付,response ={}",JsonUtil.toJson(payRequest));

return payResponse;

}

@Override

    public PayResponse notify(String notify) {

//1.验证签名

//2.支付的状态

//3.支付金额

//4.支付人(下单人 == 支付人)

        PayResponse payResponse =bestPayService.asyncNotify(notify);

log.info("[微信支付]异步通知,payResponse={}",JsonUtil.toJson(payResponse));

//查询订单

        OrderDTO orderDTO =orderService.findOne(payResponse.getOrderId());

//判断订单是否存在

        if (orderDTO ==null){

log.error("[微信支付]异步通知,订单不存在,orderId={}",payResponse.getOrderId());

throw new AppointException(ResultEnum.ORDER_NOT_EXIST);

}

//判断金额是否一致(考虑 0.10 0.1)  注意比较类型

        if (!MathUtil.equals(payResponse.getOrderAmount(),orderDTO.getOrderAmount().doubleValue())){

log.error("[微信支付]异步通知,订单金额不一致,orderId={},微信通知金额={},系统金额={}"

                    ,payResponse.getOrderId(),payResponse.getOrderAmount(),orderDTO.getOrderAmount());

throw new AppointException(ResultEnum.WXPAY_NOTIFY_MONEY_ERROR);

}

//修改订单支付状态

        orderService.paid(orderDTO);

return payResponse;

}

}

3.5 前端页面传值给下单接口,并返回数据给回调地址

在之前必须实现一个下单接口,并通过回调地址实现对支付的发起

wechatPayUrl: www.xxx.com/项目名/pay/create  的接口

returnUrl: 是你支付完后返回的地址

图7

3.6  location.href 接口Controller代码实现以及微信异步通知

@RestController

@RequestMapping("/pay")

public class PayController {

@Autowired

    private AppointOrderServiceorderService;

@Autowired

    private PayServicepayService;

@GetMapping("/create")

public ModelAndView create(@RequestParam("orderId")String orderId,

@RequestParam("returnUrl")String returnUrl,

Map map){

//1.查询订单

        OrderDTO orderDTO =orderService.findOne(orderId);

if (orderDTO ==null){

throw new AppointException(ResultEnum.ORDER_NOT_EXIST);

}

//2.发起支付

        PayResponse payResponse =payService.create(orderDTO);

map.put("payResponse",payResponse);

map.put("returnUrl",returnUrl);

return new ModelAndView("pay/create",map);

}

/**

* 微信异步通知

* 需要配置

*/

    @PostMapping("/notify")

public ModelAndView notify(@RequestBody String notifyData){

payService.notify(notifyData);

//返回给微信处理

        return new ModelAndView("pay/success");

}

}

3.7 需要写js和xml调起微信支付窗口和返回结果

可以通过API列表了解一下

https://pay.weixin.qq.com/wiki/doc/api/H5.php?chapter=9_20&index=1

项目是用freemarker

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>

success.ftl

<xml>

<return_code> <![CDATA[SUCCESS]]></return_code>

<return_msg><![CDATA[OK]]></return_msg>

</xml>

四、实现支付功能

点击提交按钮,调用下单接口,前端用图7那样方式进行跳转发起支付接口


图8

调起支付窗口并输入支付密码

注:本图为真机操作

图9

注:该文章主要为个人学习内容

最后编辑于
©著作权归作者所有,转载或内容合作请联系作者
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念sama阅读 218,525评论 6 507
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 93,203评论 3 395
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
    开封第一讲书人阅读 164,862评论 0 354
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 58,728评论 1 294
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 67,743评论 6 392
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 51,590评论 1 305
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 40,330评论 3 418
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 39,244评论 0 276
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 45,693评论 1 314
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 37,885评论 3 336
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 40,001评论 1 348
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 35,723评论 5 346
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 41,343评论 3 330
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 31,919评论 0 22
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 33,042评论 1 270
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 48,191评论 3 370
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 44,955评论 2 355

推荐阅读更多精彩内容