计费系统搭建 未完待续

计费系统


服务端搭建


大体逻辑为客户端申请充值列表,------需修改


整体项目maven构建,所有第三方jar包配置在pom.xml中,数据库操作使用mybitas,查询后的关键数据使用memcache缓存到系统中


计费系统分为自运和渠道,自运使用支付宝等充值,后边详细介绍,先介绍渠道的充值方式




项目启动后,spring加载需要实例化的bean。编写StartbBilling类,通过PostConstruct注释启动mina编写的server服务端,


服务端使用 mina 构建,在服务由maven打包后,需要接收渠道的回调url申请,url回调申请使用spring的注释,--@RequestMapping



package com.example.billing.applacation.channel.lenovo;
 
import java.io.PrintWriter;
import java.math.BigDecimal;
import java.math.BigInteger;
import java.util.Arrays;
import java.util.Date;
import java.util.Map.Entry;
 
import javax.annotation.Resource;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
 
import org.apache.log4j.Logger;
import org.json.JSONObject;
import org.springframework.stereotype.Controller;
import org.springframework.util.Assert;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RequestMethod;
 
import com.google.gson.Gson;
import com.google.gson.GsonBuilder;
import com.example.billing.applacation.game.base.PushMessage;
import com.example.billing.cache.Configuration;
import com.example.billing.domain.model.ChargeChannel;
import com.example.billing.domain.model.MoneyLog;
import com.example.billing.domain.service.MoneyLogService;
import com.example.billing.util.GameUtil;
 
/**
 * Lenovo sdk
 */
@Controller
@RequestMapping(value = "/lenovo")
//依照上边的value值,渠道回调地址为http://address:pot/项目名称/service/lenovo
public class LenovoResultAction {
//添加日志
    private final static Logger logger = Logger.getLogger(LenovoResultAction.class.getName());
    protected static final GsonBuilder builder = new GsonBuilder().excludeFieldsWithoutExposeAnnotation();
 
    protected static final Gson gson = builder.create();
//注入所需业务处理bean
    @Resource
    MoneyLogService moneyLogService;
 
    @Resource
    private PushMessage pushMessage;
 //回调方式,依据渠道的要求编写,本示例为http协议,POST方法
    @RequestMapping(value = "", method = RequestMethod.GET)
    protected void doGet(HttpServletRequest req, HttpServletResponse resp) throws Exception {
        doPost(req, resp);
    }
 
    @RequestMapping(value = "", method = RequestMethod.POST)
    protected void doPost(HttpServletRequest req, HttpServletResponse resp) throws Exception {
        PrintWriter writer = null;
        try {
            StringBuffer buffer = new StringBuffer("收到lenovo支付返回消息:");
            for (Entry<String, String[]> ent : req.getParameterMap().entrySet()) {
                buffer.append(ent.getKey()).append("=").append(Arrays.toString(ent.getValue())).append("|");
            }
            logger.info(buffer);
            // 签名
            String sign = req.getParameter("sign");
            // 订单数据串
            String transdata = req.getParameter("transdata");
            // json转化为对象
            JSONObject obj = new JSONObject(transdata);
            // 外部订单号-商户订单号
            String exorderno = obj.getString("exorderno");
            // 计费支付平台的交易流水号
            String transid = obj.getString("transid");
            // 平台为商户应用分配的唯一编号
            String appid = obj.getString("appid");
            // 平台为应用内需计费商品分配的编号
            String waresid = obj.getString("waresid");
            // 计费类型: 0 – 开放价格 1 – 免费 2 – 按次 3 – 包自然时长 4 – 包账期 5 – 买断 6 – 包次数 7 –
            // 按时长 8 – 包活跃时长 9 – 批量购买 100 – 按次免费试用 101 – 按时长免费试用
            String feetype = obj.getString("feetype");
            // 本次交易金额(单位:分)
            String money = obj.getString("money");
            // 购买数量
            String count = obj.getString("count");
            // 交易结果: 0 – 交易成功 1 – 交易失败
            String result = obj.getString("result");
            // 交易类型
            String transtype = obj.getString("transtype");
            // 交易时间
            String transtime = obj.getString("transtime");
            // 商户私有信息
            String cpprivate = obj.getString("cpprivate");
            // 支付方式支付方式(该字段值后续可能会增加) 支付方式(该字段值后续可能会增加) 支付方式(该字段值后续可能会增加) 支付方式(该字段值后续可能会增加) 支付方式(该字段值后续可能会增加) 支付方式(该字段值后续可能会增加) 支付方式(该字段值后续可能会增加)
            // 0 –话费支付
            // 1 - 充值卡
            // 2 –游戏点卡
            // 3 –银行卡
            // 401 –支付宝
            // 402 –财付通
            // 5 –联想 币
            // 6 –联想 一键支付 一键支付
            // 8、测试验证与发布集
            String paytype = obj.getString("paytype");
            logger.info("获取参数信息:exorderno="
                + exorderno
                + ",transid="
                + transid
                + ",appid="
                + appid
                + ",waresid="
                + waresid
                + ",feetype="
                + feetype
                + ",money="
                + money
                + ",count="
                + count
                + ",result="
                + result
                + ",transtype="
                + transtype
                + ",transtime="
                + transtime
                + ",cpprivate="
                + cpprivate
                + ",paytype="
                + paytype);
            int results = Integer.parseInt(result);
            if (results == 0) {
 
                int chargeStatus = MoneyLog.CHARGE_FAILED;
                // 步骤1:查询订单,依据业务流程,使用服务器申请的本公司的订单号查询订单,没有通过断言退出
                MoneyLog moneyLog = moneyLogService.getmoneyLogByorderid(exorderno);
								// 步骤2:通过订单记录取得渠道id,没有通过断言退出
                ChargeChannel channel = Configuration.getChannel(moneyLog.getCid() + "");
                Assert.notNull(channel, "渠道不存在:" + exorderno);
                Assert.notNull(moneyLog, "订单号不存在:" + exorderno);
								// 步骤3:通过渠道信息取得验证使用的加密私钥
                String key = channel.getSeckey();
                // 步骤4:验证签名
                boolean validSign = validSign(transdata, sign, key);
                Assert.isTrue(validSign, "lenovo验证签名失败!");

                int money = 0;
                if (MoneyLog.CHARGE_SUCCESS != moneyLog.getChargestatus()) {
                // 步骤5:依据业务转换人名币to游戏币
                    money = GameUtil.parseMoney(Double.valueOf(money), channel.getCtype());
                    if (money > 0) {
                        // 1:已发送请求。2:充值成功。3:充值失败。
                        chargeStatus = MoneyLog.CHARGE_SUCCESS;
                        // 步骤6:通知服务器更新用户游戏币
                        // 返回给服务器的内容
                        this.pushMessage.PushServer(moneyLog.getGame(), moneyLog.getRid(), moneyLog.getAid(), money, channel.getChannel());
                    } else {
                        // 充值金额为0 定义为失败
                        chargeStatus = MoneyLog.CHARGE_FAILED;
                    }
                    // 步骤7:更新数据库,记录日志
                    moneyLog.setSpstatus("success");
                    moneyLog.setSporderid(transid);
                    moneyLog.setChargestatus(chargeStatus);
                    moneyLog.setAmount(Double.valueOf(money));
                    moneyLog.setMoney(money);
                    moneyLog.setUtime(new Date());
                    moneyLogService.saveOrUpdateMoneyLog(moneyLog);
                    logger.info("充值成功。。。。。。");
                } else {
                    logger.info("已经充过了。。。。。。");
                }
                writer = resp.getWriter();
                writer.write("success");
                writer.flush();
                writer.close();
            } else {
                logger.info("LENOVO充值失败。。。。。。");
            }
 
        } catch (Exception e) {
            writer = resp.getWriter();
            writer.write("FAIL");
            writer.flush();
            writer.close();
            logger.error("lenovo充值异常:", e);
        }
 
    }
 
    /**
     * 验证签名
     * 
     * @param transdata
     *            同步过来的transdata数据
     * @param sign
     *            同步过来的sign数据
     * @param key
     *            应用的密钥(商户可从商户自服务系统获取)
     * @return 验证签名结果 true:验证通过 false:验证失败
     */
 
    public static boolean validSign(String transdata, String sign, String key) {
        try {
            String md5Str = MD5.md5Digest(transdata);
 
            String decodeBaseStr = Base64.decode(key);
 
            String[] decodeBaseVec = decodeBaseStr.replace('+', '#').split("#");
 
            String privateKey = decodeBaseVec[0];
            String modkey = decodeBaseVec[1];
 
            String reqMd5 = RSAUtil.decrypt(sign, new BigInteger(privateKey), new BigInteger(modkey));
 
            if (md5Str.equals(reqMd5)) {
                return true;
            } else {
                return false;
            }
 
        } catch (Exception e) {
            e.printStackTrace();
        }
 
        return false;
 
    }
 
}



  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值