kvs_payment.erl 6.1 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161
  1. -module(kvs_payment).
  2. -include_lib("kvs/include/membership.hrl").
  3. -include_lib("kvs/include/payments.hrl").
  4. -include_lib("kvs/include/log.hrl").
  5. -include_lib("kvs/include/accounts.hrl").
  6. -include_lib("kvs/include/feed_state.hrl").
  7. -compile(export_all).
  8. user_paid(UId) ->
  9. case kvs:get(user_payment, UId) of
  10. {error,_} -> false;
  11. {ok,#user_payment{top = undefined}} -> false;
  12. _ -> true end.
  13. default_if_undefined(Value, Undefined, Default) ->
  14. case Value of
  15. Undefined -> Default;
  16. _ -> Value end.
  17. charge_user_account(MP) ->
  18. OrderId = MP#payment.id,
  19. Package = MP#payment.membership,
  20. UserId = MP#payment.user_id,
  21. Currency = Package#membership.currency,
  22. Quota = Package#membership.quota,
  23. PaymentTransactionInfo = #tx_payment{id=MP#payment.id},
  24. try
  25. kvs_account:transaction(UserId, currency, Currency, PaymentTransactionInfo),
  26. kvs_account:transaction(UserId, quota, Quota, PaymentTransactionInfo)
  27. catch
  28. _:E ->
  29. ?ERROR("unable to charge user account. User=~p, OrderId=~p. Error: ~p",
  30. [UserId, OrderId, E])
  31. end.
  32. add_payment(#payment{} = MP) -> add_payment(#payment{} = MP, undefined, undefined).
  33. add_payment(#payment{} = MP, State0, Info) ->
  34. case kvs:get(payment, MP#payment.id) of
  35. {ok, _} -> {error, already_bought_that_one};
  36. {error, _} ->
  37. Start = now(),
  38. State = default_if_undefined(State0, undefined, ?MP_STATE_ADDED),
  39. StateLog = case Info of
  40. undefined -> [#state_change{time = Start, state = State, info = system_change}];
  41. _ -> [#state_change{time = Start, state = State, info = Info}] end,
  42. Id = default_if_undefined(MP#payment.id, undefined, payment_id()),
  43. Purchase = MP#payment{id = Id, state = State, start_time = Start, state_log = StateLog},
  44. %mqs:notify_purchase(Purchase),
  45. % ?INFO("Payment added ~p ~p",[Purchase#payment.user_id, Purchase]),
  46. add_to_user(Purchase#payment.user_id, Purchase)
  47. end.
  48. add_to_user(UserId,Payment) ->
  49. {ok,Team} = case kvs:get(user_payment, UserId) of
  50. {ok,T} -> {ok,T};
  51. _ -> ?INFO("user_payment not found ~p. create top",[UserId]),
  52. Head = #user_payment{ user = UserId, top = undefined},
  53. {kvs:put(Head),Head}
  54. end,
  55. EntryId = Payment#payment.id,
  56. Prev = undefined,
  57. case Team#user_payment.top of
  58. undefined -> Next = undefined;
  59. X -> case kvs:get(payment, X) of
  60. {ok, TopEntry} ->
  61. Next = TopEntry#payment.id,
  62. EditedEntry = TopEntry#payment{next = TopEntry#payment.next, prev = EntryId},
  63. kvs:put(EditedEntry);
  64. {error, _} -> Next = undefined end end,
  65. kvs:put(#user_payment{ user = UserId, top = EntryId}), % update team top with current
  66. Entry = Payment#payment{id = EntryId, user_id = UserId, next = Next, prev = Prev},
  67. case kvs:put(Entry) of ok -> {ok, EntryId};
  68. Error -> ?INFO("Cant write purchase"), {failure,Error} end.
  69. set_payment_state(MPId, NewState, Info) ->
  70. case kvs:get(payment, MPId) of
  71. {ok, MP} ->
  72. Time = now(),
  73. StateLog = MP#payment.state_log,
  74. NewStateLog = [#state_change{time = Time, state = NewState, info = Info}|StateLog],
  75. EndTime = case NewState of
  76. ?MP_STATE_DONE -> now();
  77. ?MP_STATE_CANCELLED -> now();
  78. ?MP_STATE_FAILED -> now();
  79. _ -> MP#payment.end_time
  80. end,
  81. Purchase = MP#payment{state = NewState, end_time = EndTime, state_log = NewStateLog},
  82. % mqs:notify_purchase(Purchase),
  83. NewMP=MP#payment{state = NewState, end_time = EndTime, state_log = NewStateLog},
  84. kvs:put(NewMP),
  85. if
  86. NewState == ?MP_STATE_DONE -> charge_user_account(MP); % affiliates:purchase_hook(NewMP);
  87. true -> ok
  88. end,
  89. ok;
  90. Error -> ?INFO("Can't set purchase state, not yet in db"), Error
  91. end.
  92. set_payment_info(MPId, Info) ->
  93. {ok, MP} = kvs:get(payment, MPId),
  94. kvs:put(MP#payment{info = Info}).
  95. set_payment_external_id(MPId, ExternalId) ->
  96. {ok, MP} = kvs:get(payment, MPId),
  97. case MP#payment.external_id of
  98. ExternalId -> ok;
  99. _ -> kvs:put(MP#payment{external_id = ExternalId}) end.
  100. list_payments() -> kvs:all(payment).
  101. list_payments(SelectOptions) ->
  102. Predicate = fun(MP = #payment{}) -> kvs_membership:check_conditions(SelectOptions, MP, true) end,
  103. kvs_membership:select(payment, Predicate).
  104. payment_id() ->
  105. NextId = kvs:next_id("payment"),
  106. lists:concat([kvs_membership:timestamp(), "_", NextId]).
  107. handle_notice(["kvs_payment", "user", _, "set_state"] = Route,
  108. Message, #state{owner = Owner, type =Type} = State) ->
  109. ?INFO("queue_action(~p): set_purchase_state: Owner=~p, Route=~p, Message=~p", [self(), {Type, Owner}, Route, Message]),
  110. {MPId, NewState, Info} = Message,
  111. set_payment_state(MPId, NewState, Info),
  112. {noreply, State};
  113. handle_notice(["kvs_payment", "user", _, "add"] = Route,
  114. Message, #state{owner = Owner, type =Type} = State) ->
  115. ?INFO("queue_action(~p): add_purchase: Owner=~p, Route=~p, Message=~p", [self(), {Type, Owner}, Route, Message]),
  116. {MP} = Message,
  117. add_payment(MP),
  118. {noreply, State};
  119. handle_notice(["kvs_payment", "user", _, "set_external_id"] = Route,
  120. Message, #state{owner = Owner, type =Type} = State) ->
  121. ?INFO("queue_action(~p): set_purchase_external_id: Owner=~p, Route=~p, Message=~p", [self(), {Type, Owner}, Route, Message]),
  122. {PurchaseId, TxnId} = Message,
  123. set_payment_external_id(PurchaseId, TxnId),
  124. {noreply, State};
  125. handle_notice(["kvs_payment", "user", _, "set_info"] = Route,
  126. Message, #state{owner = Owner, type =Type} = State) ->
  127. ?INFO("queue_action(~p): set_purchase_info: Owner=~p, Route=~p, Message=~p", [self(), {Type, Owner}, Route, Message]),
  128. {OrderId, Info} = Message,
  129. set_payment_info(OrderId, Info),
  130. {noreply, State};
  131. handle_notice(Route, Message, State) -> error_logger:info_msg("Unknown PAYMENTS notice").