支付安全验签实现

150 阅读3分钟

持续创作,加速成长!这是我参与「掘金日新计划 · 10 月更文挑战」的第21天,点击查看活动详情

每日英语:

No need to hurry. No need to sparkle. No need to be anybody but oneself.

翻译:不必行色匆匆,不必闪耀夺目,不必成为别人,只需做好自己。 ——弗吉尼亚·伍尔芙

支付安全验签流程

1606461742012.png

支付过程如上图,用户发起预支付下单,会将订单信息转成支付信息,并将支付信息传给支付服务,支付服务再调用微信服务器实现预下单操作。

如果当前用户是一个程序员,能读懂一些代码,此时会存在很多隐患问题,如果用户把支付金额修改了,就会给公司造成很大的损失,此时我们需要对数据进行安全处理。

验签:

需要传给支付服务器的数据,我们使用订单服务加密处理再返回到客户端,客户端将加密数据传给支付服务器,支付服务器对数据进行安全校验,校验通过了再下单,这个过程就是金融行业常用的验签操作。整个操作流程如下:

1606463037794.png

验签实现

AESUtil.javaMD5.javaSignature.java导入到mall-common工程的com.xz.mall.util包下。

同时记得导入FastJSON依赖包

<dependency>
    <groupId>com.alibaba</groupId>
    <artifactId>fastjson</artifactId>
    <version>1.2.51</version>
</dependency>

1)初始化Signature

mall-order-service工程的bootstrap.yml中添加秘钥配置和加盐配置,代码如下:

#支付配置
payconfig:
  #支付安全校验
  aes:
    #AES加密秘钥
    skey: ab2cc473d3334c39
    #验签盐
    salt: XPYQZb1kMES8HNaJWW8+TDu/4JdBK4owsU9eXCXZDOI=

mall-order-service工程中创建com.xz.mall.order.config.SecurityConfig用于初始化Signature,代码如下:

@Configuration
public class SecurityConfig {
​
    //秘钥
    @Value("${payconfig.aes.skey}")
    private String skey;
​
    //验签加盐值
    @Value("${payconfig.aes.salt}")
    private String salt;
​
    /***
     * 验签对象
     */
    @Bean(value = "signature")
    public Signature signature(){
        return new Signature(skey,salt);
    }
}

2)支付参数处理

mall-order-service工程中创建com.xz.mall.order.pay.WeixinPayParam,将订单信息封装到统一下单的参数中,并使用Signature进行签名和加密,代码如下:

@Component
public class WeixinPayParam {
​
    @Autowired
    private Signature signature;
​
    /****
     * 微信支付参数封装
     * 对参数进行签名
     * 对整体参数进行加密
     * @return
     */
    public String weixinParam(Order order, HttpServletRequest request) throws Exception {
        //定义Map封装参数
        Map<String,String> dataMap = new HashMap<String,String>();
        dataMap.put("body", "商城订单-"+order.getId());
        dataMap.put("out_trade_no", order.getId());
        dataMap.put("device_info", "PC");
        dataMap.put("fee_type", "CNY");
        //dataMap.put("total_fee", String.valueOf(order.getMoneys()));
        dataMap.put("total_fee", "1"); //1分钱测试
        dataMap.put("spbill_create_ip", IPUtils.getIpAddr(request));
        dataMap.put("notify_url", "http://www.example.com/wxpay/notify");
        dataMap.put("trade_type", "NATIVE");  // 此处指定为扫码支付
        //生成签名,并且参数加密
        return signature.security(dataMap);
    }
}

修改mall-order-service在该工程中com.xz.mall.order.controller.OrderController里添加方法里增加支付数据处理,代码如下:

@Autowired
private WeixinPayParam weixinPayParam;
​
/***
 * 添加订单
 */
@PostMapping
public RespResult add(@RequestBody Order order,HttpServletRequest request) throws Exception {
    String userName = "gp";
    order.setUsername(userName);
    order.setCreateTime(new Date());
    order.setUpdateTime(order.getCreateTime());
    order.setId(IdWorker.getIdStr());
    order.setOrderStatus(0);
    order.setPayStatus(0);
    order.setIsDelete(0);
    //添加订单
    Boolean bo = orderService.add(order);
    //支付信息封装
    if(bo){
        //加密字符
        String ciptext = weixinPayParam.weixinParam(order,request);
        return RespResult.ok(ciptext);
    }
    return RespResult.error(RespCode.SYSTEM_ERROR);
}

3)数据验证

mall-pay-service工程中初始化Signature,将工程mall-order-service中的com.xz.mall.order.config.SecurityConfig拷贝到mall-pay-service工程的com.xz.mall.pay.config包下。

修改mall-pay-service工程中的com.xz.mall.pay.controller.WeixinPayController#pay方法,代码如下:

@Autowired
private Signature signature;
​
/*****
 * 预下单
 * ciptext:支付信息加密字符串  AES加密,包含验签
 * @return
 * @throws Exception
 */
@GetMapping(value = "/pay")
public RespResult<Map> pay(@RequestParam(value = "ciptext")String ciphertext) throws Exception {
    //数据解析,并验签校验
    Map<String, String> map = signature.security(ciphertext);
    //1分钱测试
    if(map!=null){
        Map<String, String> resultMap = weixinPayService.preOrder(map);
        resultMap.put("orderNumber",map.get("out_trade_no"));
        resultMap.put("money",map.get("total_fee"));
        return RespResult.ok(resultMap);
    }
    return RespResult.error("支付系统繁忙,请稍后再试!");
}

总结

本篇主要讲述了一下支付安全验签流程,还有具体的验签代码实现。