美文网首页
Alipay(支付宝支付) 如何实现一个项目配置多个商户信息付款

Alipay(支付宝支付) 如何实现一个项目配置多个商户信息付款

作者: telami | 来源:发表于2018-10-23 16:25 被阅读0次

    如何实现一个项目配置多个商户信息付款给对应商户

    最近在对接支付宝支付时,遇到了一个问题

    用户在付款时,需要直接付款到指定支付宝账户。

    这个需求也无可厚非,就像我们公司有四个分公司,分别在北京、上海等地,如果钱只能到总公司的账户上,那在财务结算的时候就很麻烦。

    简单说一下问题背景:

    公司准备上线一个商城应用,有分公司和服务商的概念,意思就是收钱的不是一个人。

    前一阵子,蚂蚁金服投了一大笔钱,也算是达成了合作,所以在第三方支付中首选了支付宝,场景是手机网站支付,问题就在这出现了。目前支付宝只在当面付中支持配置多个收款账户,也是在社区里逛了一阵子才知道这个信息的。

    [图片上传失败...(image-88cfb5-1540283092156)]
    [图片上传失败...(image-7f4e27-1540283092156)]
    蚂蚁金服开发者社区原贴:如何实现一个项目配置多个商户信息付款给对应商户

    上面的帖子明确说明了目前实现的两种方式,很明显方案二看起来比较优雅,也比较好实现,但是很抱歉,手机网站支付不支持方案二。

    ps:判断是否支持方案二的方法就是去看它的文档,如果请求参数中有app_auth_token这个参数就是支持方案二的。

    为了证实这个蛋疼的消息,我又专门发了一个帖子确认了一遍

    手机网站支付遇到了一些问题

    管理员明确的回复了我,只能用方案一,并且要申请N个应用,并全部上线。

    Google了一下,没搜到用这种方式实现的代码,只能自己写了。。

    支付宝最终是根据请求过来的appid来判断哪一个商户收款(也就是请求是谁的appid就收款到谁的账号下)

    所以我申请了四个应用。。。。

    先定一个接口;

    public interface AlipayClientConfig {
      /**
       * 网关.
       */
      String getGatewayUrl();
      /**
       * appid.
       */
      String getAppId();
      /**
       * 私钥.
       */
      String getAppPrivateKey();
      /**
       * 格式 默认json.
       */
      String getFormat();
      /**
       * 编码 默认utf-8.
       */
      String getCharset();
      /**
       * 支付宝公钥.
       */
      String getAlipayPublicKey();
      /**
       * 签名方式.
       */
      String getSignType();
    }
    

    在定义一个抽象类实现接口;

    @Getter
    @Setter
    public class AlipayAbstractClientConfig implements AlipayClientConfig {
    
      /**
       * 网关.
       */
      private String gatewayUrl;
      /**
       * appid.
       */
      private String appId;
      /**
       * 私钥.
       */
      private String appPrivateKey;
      /**
       * 格式 默认json.
       */
      private String format;
      /**
       * 编码 默认utf-8.
       */
      private String charset;
      /**
       * 支付宝公钥.
       */
      private String alipayPublicKey;
      /**
       * 签名方式.
       */
      private String signType;
    }
    

    然后是四个配置文件继承抽象类;

    @Configuration(AlipayConstant.BEIJING_CLIENT)
    @ConfigurationProperties(prefix = "alipay.apenapi.beijing")
    @Getter
    @Setter
    public class AlipayBeiJingClientConfig extends AlipayAbstractClientConfig {
    
    }
    
    @Configuration(AlipayConstant.NANJING_CLIENT)
    @ConfigurationProperties(prefix = "alipay.apenapi.nanjing")
    @Getter
    @Setter
    public class AlipayNanJingClientConfig extends AlipayAbstractClientConfig {
    
    }
    
    @Configuration(AlipayConstant.SHANGHAI_CLIENT)
    @ConfigurationProperties(prefix = "alipay.apenapi.shanghai")
    @Getter
    @Setter
    public class AlipayShangHaiClientConfig extends AlipayAbstractClientConfig {
    
    }
    
    @Configuration(AlipayConstant.TIANJIN_CLIENT)
    @ConfigurationProperties(prefix = "alipay.apenapi.tianjin")
    @Getter
    @Setter
    public class AlipayTianJinClientConfig extends AlipayAbstractClientConfig {
    
    }
    

    注解的常量信息;

    public interface AlipayConstant {
    
      String BEIJING_CLIENT = "BJ";
     
      String TIANJIN_CLIENT = "TJ";
      
      String NANJING_CLIENT = "NJ";
     
      String SHANGHAI_CLIENT = "SH";
    }
    

    再贴一下配置文件信息;

    alipay:
      apenapi:
        tianjin:
          gateway_url: https://openapi.alipay.com/gateway.do
          app_id: 2018*********
          app_private_key: KubiKtPbIoMLITLRMKTu9MwIwE8lC9Grg5
                           6c/00rsypY/b8SQh8ydYsEPt098JYAEhS6HvLQNz6W5XvCZNeAcv307kj3RYql2W
                           Xntkh9Rr0s/cEc1WnHmBeUF3
          alipay_public_key: MIIBIjANBgkqhkistdzwIDAQAB
          format: json
          charset: utf-8
          sign_type: RSA2
        beijing:
          gateway_url: https://openapi.alipay.com/gateway.do
          app_id: 2018**********
          app_private_key: JTj9Lz6G4W3RMO8QCCK8XYWdkEH5H5I
          alipay_public_key: MIIBIjANBgB
          format: json
          charset: utf-8
          sign_type: RSA2
        shanghai:
          gateway_url: https://openapi.alipay.com/gateway.do
          app_id: 2018********
          app_private_key: MIIEvAIBADANBgcpUyx/WxcdhuAYmF3Di
          alipay_public_key: MIIBIjANBgkqhkiG9w0
          format: json
          charset: utf-8
          sign_type: RSA2
        nanjing:
          gateway_url: https://openapi.alipay.com/gateway.do
          app_id: 20181********
          app_private_key: MIIEvgIBA
          alipay_public_key: MIIBIjANBgk
          format: json
          charset: utf-8
          sign_type: RSA2
    

    在service层调用时,只要动态的获取不同的配置文件,即可初始化不同的AlipayClient,向支付宝发起请求;

    @Service
    @Slf4j
    @Transactional(readOnly = true)
    public class AlipayServiceImpl implements AlipayService {
    
      @Autowired
      private AlipayDetailConfig alipayDetailConfig;
    
      @Autowired
      private Map<String, AlipayClientConfig> configMap;
    
      @Override
      public AlipayTradeWapPayResponse wapPay(AlipayWayPayRequest request) throws AlipayApiException {
        String method = "wapPay";
        log.debug("Enter {}", method);
        log.debug("WapPay form info : orderCode:【{}】 、orderTotalAmount:【{}】 "
                + "、orderSubject:【{}】 、orderDescription:【{}】 、quitUrl:【{}】 、companyCode:【{}】。",
            request.getOrderCode(), request.getOrderTotalAmount(), request.getOrderSubject(),
            request.getOrderDescription(), request.getQuitUrl(), request.getCompanyCode()
        );
        AlipayTradeWapPayRequest alipayRequest = new AlipayTradeWapPayRequest();
        alipayRequest.setNotifyUrl(alipayDetailConfig.getNotifyUrl());
        alipayRequest.setReturnUrl(alipayDetailConfig.getReturnUrl());
        AlipayTradeWapPayModel payModel = new AlipayTradeWapPayModel();
        //商户订单号
        payModel.setOutTradeNo(request.getOrderCode());
        //订单总金额,单位为元,精确到小数点后两位,取值范围[0.01,100000000]
        payModel.setTotalAmount(request.getOrderTotalAmount().toString());
        //订单标题
        payModel.setSubject(request.getOrderSubject());
        //订单描述
        payModel.setBody(request.getOrderDescription());
        //用户付款中途退出返回商户网站的地址
        payModel.setQuitUrl(request.getQuitUrl());
        //商品主类型  虚拟类商品不支持使用花呗渠道
        payModel.setGoodsType(AlipayConstant.VIRTUAL_GOODS_TYPE);
        //该笔订单允许的最晚付款时间,逾期将关闭交易
        payModel.setTimeoutExpress(alipayDetailConfig.getTimeoutExpress());
        //销售产品码,与支付宝签约的产品码名称
        payModel.setProductCode(AlipayConstant.WAP_PAY_PRODUCT_CODE);
        //设置回传参数
        payModel.setPassbackParams(request.getCompanyCode());
        alipayRequest.setBizModel(payModel);
        //返回支付信息
        AlipayClient alipayClient = getAlipayClient(request.getCompanyCode());
        log.debug("Exit {}", method);
        return alipayClient.pageExecute(alipayRequest);
      }
      
      
        /**
       * 根据分公司code返回对应的client.
       *
       * @param companyCode 分公司code.
       */
      private AlipayClient getAlipayClient(String companyCode) {
        AlipayClientConfig config = configMap.get(companyCode);
        return new DefaultAlipayClient(
            config.getGatewayUrl(),
            config.getAppId(),
            config.getAppPrivateKey(),
            config.getFormat(),
            config.getCharset(),
            config.getAlipayPublicKey(),
            config.getSignType()
        );
      }
    

    至此,算是比较优雅的实现了付款给指定商户账号。

    后记:微信支付早就解决了这个问题 ,也因此在社区里,一大批吐槽者疯狂吐槽支付宝的设计思路和实现方式。

    image

    相关文章

      网友评论

          本文标题:Alipay(支付宝支付) 如何实现一个项目配置多个商户信息付款

          本文链接:https://www.haomeiwen.com/subject/ncyazftx.html